feat: Complete fleet — 94 skills across 10+ domains

Pulled ALL skills from 15 source repositories:
- anthropics/skills: 16 (docs, design, MCP, testing)
- obra/superpowers: 14 (TDD, debugging, agents, planning)
- coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth)
- better-auth/skills: 5 (auth patterns)
- vercel-labs/agent-skills: 5 (React, design, Vercel)
- antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo)
- Plus 13 individual skills from various repos

Mosaic Stack is not limited to coding — the Orchestrator and
subagents serve coding, business, design, marketing, writing,
logistics, analysis, and more.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jason Woltje
2026-02-16 16:27:42 -06:00
parent 861b28b965
commit f5792c40be
1262 changed files with 212048 additions and 61 deletions

View File

@@ -0,0 +1,159 @@
---
category: Reactivity
alias: asyncComputed
---
# computedAsync
Computed for async functions
## Usage
```ts
import { computedAsync } from '@vueuse/core'
import { shallowRef } from 'vue'
const name = shallowRef('jack')
const userInfo = computedAsync(
async () => {
return await mockLookUp(name.value)
},
null, /* initial state */
)
```
### Evaluation State
You will need to pass a ref to track if the async function is evaluating.
```ts
import { computedAsync } from '@vueuse/core'
import { shallowRef } from 'vue'
const evaluating = shallowRef(false)
const userInfo = computedAsync(
async () => { /* your logic */ },
null,
evaluating,
)
```
### onCancel
When the computed source changed before the previous async function gets resolved, you may want to cancel the previous one. Here is an example showing how to incorporate with the fetch API.
```ts
import { computedAsync } from '@vueuse/core'
// ---cut---
const packageName = shallowRef('@vueuse/core')
const downloads = computedAsync(async (onCancel) => {
const abortController = new AbortController()
onCancel(() => abortController.abort())
return await fetch(
`https://api.npmjs.org/downloads/point/last-week/${packageName.value}`,
{ signal: abortController.signal },
)
.then(response => response.ok ? response.json() : { downloads: '—' })
.then(result => result.downloads)
}, 0)
```
### Lazy
By default, `computedAsync` will start resolving immediately on creation, specify `lazy: true` to make it start resolving on the first accessing.
```ts
import { computedAsync } from '@vueuse/core'
import { shallowRef } from 'vue'
const evaluating = shallowRef(false)
const userInfo = computedAsync(
async () => { /* your logic */ },
null,
{ lazy: true, evaluating },
)
```
## Caveats
- Just like Vue's built-in `computed` function, `computedAsync` does dependency tracking and is automatically re-evaluated when dependencies change. Note however that only dependency referenced in the first call stack are considered for this. In other words: **Dependencies that are accessed asynchronously will not trigger re-evaluation of the async computed value.**
- As opposed to Vue's built-in `computed` function, re-evaluation of the async computed value is triggered whenever dependencies are changing, regardless of whether its result is currently being tracked or not.
## Type Declarations
```ts
/**
* Handle overlapping async evaluations.
*
* @param cancelCallback The provided callback is invoked when a re-evaluation of the computed value is triggered before the previous one finished
*/
export type AsyncComputedOnCancel = (cancelCallback: Fn) => void
export interface AsyncComputedOptions<Lazy = boolean> {
/**
* Should value be evaluated lazily
*
* @default false
*/
lazy?: Lazy
/**
* Ref passed to receive the updated of async evaluation
*/
evaluating?: Ref<boolean>
/**
* Use shallowRef
*
* @default true
*/
shallow?: boolean
/**
* The flush option allows for greater control over the timing of a history point, default to `pre`
*
* Possible values: `pre`, `post`, `sync`
*
* It works in the same way as the flush option in watch and watch effect in vue reactivity
* @default 'sync'
*/
flush?: WatchOptionFlush
/**
* Callback when error is caught.
*/
onError?: (e: unknown) => void
}
/**
* Create an asynchronous computed dependency.
*
* @see https://vueuse.org/computedAsync
* @param evaluationCallback The promise-returning callback which generates the computed value
* @param initialState The initial state, used until the first evaluation finishes
* @param optionsOrRef Additional options or a ref passed to receive the updates of the async evaluation
*/
export declare function computedAsync<T>(
evaluationCallback: (onCancel: AsyncComputedOnCancel) => T | Promise<T>,
initialState: T,
optionsOrRef: AsyncComputedOptions<true>,
): ComputedRef<T>
export declare function computedAsync<T>(
evaluationCallback: (onCancel: AsyncComputedOnCancel) => T | Promise<T>,
initialState: undefined,
optionsOrRef: AsyncComputedOptions<true>,
): ComputedRef<T | undefined>
export declare function computedAsync<T>(
evaluationCallback: (onCancel: AsyncComputedOnCancel) => T | Promise<T>,
initialState: T,
optionsOrRef?: Ref<boolean> | AsyncComputedOptions,
): Ref<T>
export declare function computedAsync<T>(
evaluationCallback: (onCancel: AsyncComputedOnCancel) => T | Promise<T>,
initialState?: undefined,
optionsOrRef?: Ref<boolean> | AsyncComputedOptions,
): Ref<T | undefined>
/** @deprecated use `computedAsync` instead */
export declare const asyncComputed: typeof computedAsync
```

View File

@@ -0,0 +1,62 @@
---
category: Reactivity
alias: eagerComputed
---
# computedEager
Eager computed without lazy evaluation.
::: info
This function will be removed in future version.
:::
::: tip
Note💡: If you are using Vue 3.4+, you can use `computed` right away, you no longer need this function.
In Vue 3.4+, if the computed new value does not change, `computed`, `effect`, `watch`, `watchEffect`, `render` dependencies will not be triggered.
See: https://github.com/vuejs/core/pull/5912
:::
Learn more at [Vue: When a computed property can be the wrong tool](https://dev.to/linusborg/vue-when-a-computed-property-can-be-the-wrong-tool-195j).
- Use `computed()` when you have a complex calculation going on, which can actually profit from caching and lazy evaluation and should only be (re-)calculated if really necessary.
- Use `computedEager()` when you have a simple operation, with a rarely changing return value often a boolean.
## Usage
```ts
import { computedEager } from '@vueuse/core'
const todos = ref([])
const hasOpenTodos = computedEager(() => !!todos.length)
console.log(hasOpenTodos.value) // false
toTodos.value.push({ title: 'Learn Vue' })
console.log(hasOpenTodos.value) // true
```
## Type Declarations
```ts
export type ComputedEagerOptions = WatchOptionsBase
export type ComputedEagerReturn<T = any> = Readonly<ShallowRef<T>>
/**
*
* @deprecated This function will be removed in future version.
*
* Note: If you are using Vue 3.4+, you can straight use computed instead.
* Because in Vue 3.4+, if computed new value does not change,
* computed, effect, watch, watchEffect, render dependencies will not be triggered.
* refer: https://github.com/vuejs/core/pull/5912
*
* @param fn effect function
* @param options WatchOptionsBase
* @returns readonly shallowRef
*/
export declare function computedEager<T>(
fn: () => T,
options?: ComputedEagerOptions,
): ComputedEagerReturn<T>
/** @deprecated use `computedEager` instead */
export declare const eagerComputed: typeof computedEager
```

View File

@@ -0,0 +1,86 @@
---
category: Component
---
# computedInject
Combine computed and inject
## Usage
In Provider Component
```ts twoslash include main
import type { InjectionKey, Ref } from 'vue'
import { provide } from 'vue'
interface Item {
key: number
value: string
}
export const ArrayKey: InjectionKey<Ref<Item[]>> = Symbol('symbol-key')
const array = ref([{ key: 1, value: '1' }, { key: 2, value: '2' }, { key: 3, value: '3' }])
provide(ArrayKey, array)
```
In Receiver Component
```ts
// @filename: provider.ts
// @include: main
// ---cut---
import { computedInject } from '@vueuse/core'
import { ArrayKey } from './provider'
const computedArray = computedInject(ArrayKey, (source) => {
const arr = [...source.value]
arr.unshift({ key: 0, value: 'all' })
return arr
})
```
## Type Declarations
```ts
export type ComputedInjectGetter<T, K> = (
source: T | undefined,
oldValue?: K,
) => K
export type ComputedInjectGetterWithDefault<T, K> = (
source: T,
oldValue?: K,
) => K
export type ComputedInjectSetter<T> = (v: T) => void
export interface WritableComputedInjectOptions<T, K> {
get: ComputedInjectGetter<T, K>
set: ComputedInjectSetter<K>
}
export interface WritableComputedInjectOptionsWithDefault<T, K> {
get: ComputedInjectGetterWithDefault<T, K>
set: ComputedInjectSetter<K>
}
export declare function computedInject<T, K = any>(
key: InjectionKey<T> | string,
getter: ComputedInjectGetter<T, K>,
): ComputedRef<K | undefined>
export declare function computedInject<T, K = any>(
key: InjectionKey<T> | string,
options: WritableComputedInjectOptions<T, K>,
): ComputedRef<K | undefined>
export declare function computedInject<T, K = any>(
key: InjectionKey<T> | string,
getter: ComputedInjectGetterWithDefault<T, K>,
defaultSource: T,
treatDefaultAsFactory?: false,
): ComputedRef<K>
export declare function computedInject<T, K = any>(
key: InjectionKey<T> | string,
options: WritableComputedInjectOptionsWithDefault<T, K>,
defaultSource: T | (() => T),
treatDefaultAsFactory: true,
): ComputedRef<K>
```

View File

@@ -0,0 +1,100 @@
---
category: Reactivity
alias: controlledComputed
---
# computedWithControl
Explicitly define the dependencies of computed.
## Usage
```ts twoslash include main
import { computedWithControl } from '@vueuse/core'
const source = ref('foo')
const counter = ref(0)
const computedRef = computedWithControl(
() => source.value, // watch source, same as `watch`
() => counter.value, // computed getter, same as `computed`
)
```
With this, the changes of `counter` won't trigger `computedRef` to update but the `source` ref does.
```ts
// @include: main
// ---cut---
console.log(computedRef.value) // 0
counter.value += 1
console.log(computedRef.value) // 0
source.value = 'bar'
console.log(computedRef.value) // 1
```
### Manual Triggering
You can also manually trigger the update of the computed by:
```ts
// @include: main
// ---cut---
const computedRef = computedWithControl(
() => source.value,
() => counter.value,
)
computedRef.trigger()
```
### Deep Watch
Unlike `computed`, `computedWithControl` is shallow by default.
You can specify the same options as `watch` to control the behavior:
```ts
const source = ref({ name: 'foo' })
const computedRef = computedWithControl(
source,
() => counter.value,
{ deep: true },
)
```
## Type Declarations
```ts
export interface ComputedWithControlRefExtra {
/**
* Force update the computed value.
*/
trigger: () => void
}
export interface ComputedRefWithControl<T>
extends ComputedRef<T>,
ComputedWithControlRefExtra {}
export interface WritableComputedRefWithControl<T>
extends WritableComputedRef<T>,
ComputedWithControlRefExtra {}
export type ComputedWithControlRef<T = any> =
| ComputedRefWithControl<T>
| WritableComputedRefWithControl<T>
export declare function computedWithControl<T>(
source: WatchSource | MultiWatchSources,
fn: ComputedGetter<T>,
options?: WatchOptions,
): ComputedRefWithControl<T>
export declare function computedWithControl<T>(
source: WatchSource | MultiWatchSources,
fn: WritableComputedOptions<T>,
options?: WatchOptions,
): WritableComputedRefWithControl<T>
/** @deprecated use `computedWithControl` instead */
export declare const controlledComputed: typeof computedWithControl
```

View File

@@ -0,0 +1,86 @@
---
category: Utilities
---
# createEventHook
Utility for creating event hooks
## Usage
Creating a function that uses `createEventHook`
```ts
import { createEventHook } from '@vueuse/core'
export function useMyFetch(url) {
const fetchResult = createEventHook<Response>()
const fetchError = createEventHook<any>()
fetch(url)
.then(result => fetchResult.trigger(result))
.catch(error => fetchError.trigger(error.message))
return {
onResult: fetchResult.on,
onError: fetchError.on,
}
}
```
Using a function that uses `createEventHook`
```vue
<script setup lang="ts">
import { useMyFetch } from './my-fetch-function'
const { onResult, onError } = useMyFetch('my api url')
onResult((result) => {
console.log(result)
})
onError((error) => {
console.error(error)
})
</script>
```
## Type Declarations
```ts
/**
* The source code for this function was inspired by vue-apollo's `useEventHook` util
* https://github.com/vuejs/vue-apollo/blob/v4/packages/vue-apollo-composable/src/util/useEventHook.ts
*/
type Callback<T> =
IsAny<T> extends true
? (...param: any) => void
: [T] extends [void]
? (...param: unknown[]) => void
: [T] extends [any[]]
? (...param: T) => void
: (...param: [T, ...unknown[]]) => void
export type EventHookOn<T = any> = (fn: Callback<T>) => {
off: () => void
}
export type EventHookOff<T = any> = (fn: Callback<T>) => void
export type EventHookTrigger<T = any> = (
...param: Parameters<Callback<T>>
) => Promise<unknown[]>
export interface EventHook<T = any> {
on: EventHookOn<T>
off: EventHookOff<T>
trigger: EventHookTrigger<T>
clear: () => void
}
export type EventHookReturn<T> = EventHook<T>
/**
* Utility for creating event hooks
*
* @see https://vueuse.org/createEventHook
*
* @__NO_SIDE_EFFECTS__
*/
export declare function createEventHook<T = any>(): EventHookReturn<T>
```

View File

@@ -0,0 +1,25 @@
---
category: '@Math'
---
# createGenericProjection
Generic version of `createProjection`. Accepts a custom projector function to map arbitrary type of domains.
Refer to `createProjection` and `useProjection`
## Type Declarations
```ts
export type ProjectorFunction<F, T> = (
input: F,
from: readonly [F, F],
to: readonly [T, T],
) => T
export type UseProjection<F, T> = (input: MaybeRefOrGetter<F>) => ComputedRef<T>
export declare function createGenericProjection<F = number, T = number>(
fromDomain: MaybeRefOrGetter<readonly [F, F]>,
toDomain: MaybeRefOrGetter<readonly [T, T]>,
projector: ProjectorFunction<F, T>,
): UseProjection<F, T>
```

View File

@@ -0,0 +1,95 @@
---
category: State
related: createSharedComposable
---
# createGlobalState
Keep states in the global scope to be reusable across Vue instances.
## Usage
### Without Persistence (Store in Memory)
```ts
// store.ts
import { createGlobalState } from '@vueuse/core'
import { shallowRef } from 'vue'
export const useGlobalState = createGlobalState(
() => {
const count = shallowRef(0)
return { count }
}
)
```
A bigger example:
```ts
// store.ts
import { createGlobalState } from '@vueuse/core'
import { computed, shallowRef } from 'vue'
export const useGlobalState = createGlobalState(
() => {
// state
const count = shallowRef(0)
// getters
const doubleCount = computed(() => count.value * 2)
// actions
function increment() {
count.value++
}
return { count, doubleCount, increment }
}
)
```
### With Persistence
Store in `localStorage` with `useStorage`:
```ts twoslash include store
// store.ts
import { createGlobalState, useStorage } from '@vueuse/core'
export const useGlobalState = createGlobalState(
() => useStorage('vueuse-local-storage', 'initialValue'),
)
```
```ts
// @filename: store.ts
// @include: store
// ---cut---
// component.ts
import { useGlobalState } from './store'
export default defineComponent({
setup() {
const state = useGlobalState()
return { state }
},
})
```
## Type Declarations
```ts
export type CreateGlobalStateReturn<Fn extends AnyFn = AnyFn> = Fn
/**
* Keep states in the global scope to be reusable across Vue instances.
*
* @see https://vueuse.org/createGlobalState
* @param stateFactory A factory function to create the state
*
* @__NO_SIDE_EFFECTS__
*/
export declare function createGlobalState<Fn extends AnyFn>(
stateFactory: Fn,
): CreateGlobalStateReturn<Fn>
```

View File

@@ -0,0 +1,215 @@
---
category: State
---
# createInjectionState
Create global state that can be injected into components.
## Usage
```ts twoslash include useCounterStore
// useCounterStore.ts
import { createInjectionState } from '@vueuse/core'
import { computed, shallowRef } from 'vue'
const [useProvideCounterStore, useCounterStore] = createInjectionState((initialValue: number) => {
// state
const count = shallowRef(initialValue)
// getters
const double = computed(() => count.value * 2)
// actions
function increment() {
count.value++
}
return { count, double, increment }
})
export { useProvideCounterStore }
// If you want to hide `useCounterStore` and wrap it in default value logic or throw error logic, please don't export `useCounterStore`
export { useCounterStore }
export function useCounterStoreWithDefaultValue() {
return useCounterStore() ?? {
count: shallowRef(0),
double: shallowRef(0),
increment: () => {},
}
}
export function useCounterStoreOrThrow() {
const counterStore = useCounterStore()
if (counterStore == null)
throw new Error('Please call `useProvideCounterStore` on the appropriate parent component')
return counterStore
}
```
```vue
<!-- RootComponent.vue -->
<script setup lang="ts">
// @filename: useCounterStore.ts
// @include: useCounterStore
// ---cut---
import { useProvideCounterStore } from './useCounterStore'
useProvideCounterStore(0)
</script>
<template>
<div>
<slot />
</div>
</template>
```
```vue
<!-- CountComponent.vue -->
<script setup lang="ts">
// @filename: useCounterStore.ts
// @include: useCounterStore
// ---cut---
import { useCounterStore } from './useCounterStore'
// use non-null assertion operator to ignore the case that store is not provided.
const { count, double } = useCounterStore()!
// if you want to allow component to working without providing store, you can use follow code instead:
// const { count, double } = useCounterStore() ?? { count: shallowRef(0), double: shallowRef(0) }
// also, you can use another hook to provide default value
// const { count, double } = useCounterStoreWithDefaultValue()
// or throw error
// const { count, double } = useCounterStoreOrThrow()
</script>
<template>
<ul>
<li>
count: {{ count }}
</li>
<li>
double: {{ double }}
</li>
</ul>
</template>
```
```vue
<!-- ButtonComponent.vue -->
<script setup lang="ts">
// @filename: useCounterStore.ts
// @include: useCounterStore
// ---cut---
import { useCounterStore } from './useCounterStore'
// use non-null assertion operator to ignore the case that store is not provided.
const { increment } = useCounterStore()!
</script>
<template>
<button @click="increment">
+
</button>
</template>
```
## Provide a custom InjectionKey
```ts
// useCounterStore.ts
import { createInjectionState } from '@vueuse/core'
import { computed, shallowRef } from 'vue'
// custom injectionKey
const CounterStoreKey = 'counter-store'
const [useProvideCounterStore, useCounterStore] = createInjectionState((initialValue: number) => {
// state
const count = shallowRef(initialValue)
// getters
const double = computed(() => count.value * 2)
// actions
function increment() {
count.value++
}
return { count, double, increment }
}, { injectionKey: CounterStoreKey })
```
## Provide a custom default value
```ts
// useCounterStore.ts
import { createInjectionState } from '@vueuse/core'
import { computed, shallowRef } from 'vue'
const [useProvideCounterStore, useCounterStore] = createInjectionState((initialValue: number) => {
// state
const count = shallowRef(initialValue)
// getters
const double = computed(() => count.value * 2)
// actions
function increment() {
count.value++
}
return { count, double, increment }
}, { defaultValue: 0 })
```
## Type Declarations
```ts
export type CreateInjectionStateReturn<
Arguments extends Array<any>,
Return,
> = Readonly<
[
/**
* Call this function in a provider component to create and provide the state.
*
* @param args Arguments passed to the composable
* @returns The state returned by the composable
*/
useProvidingState: (...args: Arguments) => Return,
/**
* Call this function in a consumer component to inject the state.
*
* @returns The injected state, or `undefined` if not provided and no default value was set.
*/
useInjectedState: () => Return | undefined,
]
>
export interface CreateInjectionStateOptions<Return> {
/**
* Custom injectionKey for InjectionState
*/
injectionKey?: string | InjectionKey<Return>
/**
* Default value for the InjectionState
*/
defaultValue?: Return
}
/**
* Create global state that can be injected into components.
*
* @see https://vueuse.org/createInjectionState
*
* @__NO_SIDE_EFFECTS__
*/
export declare function createInjectionState<
Arguments extends Array<any>,
Return,
>(
composable: (...args: Arguments) => Return,
options?: CreateInjectionStateOptions<Return>,
): CreateInjectionStateReturn<Arguments, Return>
```

View File

@@ -0,0 +1,31 @@
---
category: '@Math'
related: useProjection, createGenericProjection
---
# createProjection
Reactive numeric projection from one domain to another.
## Usage
```ts
import { createProjection } from '@vueuse/math'
const useProjector = createProjection([0, 10], [0, 100])
const input = ref(0)
const projected = useProjector(input) // projected.value === 0
input.value = 5 // projected.value === 50
input.value = 10 // projected.value === 100
```
## Type Declarations
```ts
export declare function createProjection(
fromDomain: MaybeRefOrGetter<readonly [number, number]>,
toDomain: MaybeRefOrGetter<readonly [number, number]>,
projector?: ProjectorFunction<number, number>,
): UseProjection<number, number>
```

View File

@@ -0,0 +1,54 @@
---
category: Reactivity
---
# createRef
Returns a `deepRef` or `shallowRef` depending on the `deep` param.
## Usage
```ts
import { createRef } from '@vueuse/core'
import { isShallow, ref } from 'vue'
const initialData = 1
const shallowData = createRef(initialData)
const deepData = createRef(initialData, true)
isShallow(shallowData) // true
isShallow(deepData) // false
```
## Type Declarations
```ts
export type CreateRefReturn<
T = any,
D extends boolean = false,
> = ShallowOrDeepRef<T, D>
export type ShallowOrDeepRef<
T = any,
D extends boolean = false,
> = D extends true ? Ref<T> : ShallowRef<T>
/**
* Returns a `deepRef` or `shallowRef` depending on the `deep` param.
*
* @example createRef(1) // ShallowRef<number>
* @example createRef(1, false) // ShallowRef<number>
* @example createRef(1, true) // Ref<number>
* @example createRef("string") // ShallowRef<string>
* @example createRef<"A"|"B">("A", true) // Ref<"A"|"B">
*
* @param value
* @param deep
* @returns the `deepRef` or `shallowRef`
*
* @__NO_SIDE_EFFECTS__
*/
export declare function createRef<T = any, D extends boolean = false>(
value: T,
deep?: D,
): CreateRefReturn<T, D>
```

View File

@@ -0,0 +1,357 @@
---
category: Component
outline: deep
---
# createReusableTemplate
Define and reuse template inside the component scope.
## Motivation
It's common to have the need to reuse some part of the template. For example:
```vue
<template>
<dialog v-if="showInDialog">
<!-- something complex -->
</dialog>
<div v-else>
<!-- something complex -->
</div>
</template>
```
We'd like to reuse our code as much as possible. So normally we might need to extract those duplicated parts into a component. However, in a separated component you lose the ability to access the local bindings. Defining props and emits for them can be tedious sometimes.
So this function is made to provide a way for defining and reusing templates inside the component scope.
## Usage
In the previous example, we could refactor it to:
```vue
<script setup lang="ts">
import { createReusableTemplate } from '@vueuse/core'
const [DefineTemplate, ReuseTemplate] = createReusableTemplate()
</script>
<template>
<DefineTemplate>
<!-- something complex -->
</DefineTemplate>
<dialog v-if="showInDialog">
<ReuseTemplate />
</dialog>
<div v-else>
<ReuseTemplate />
</div>
</template>
```
- `<DefineTemplate>` will register the template and renders nothing.
- `<ReuseTemplate>` will render the template provided by `<DefineTemplate>`.
- `<DefineTemplate>` must be used before `<ReuseTemplate>`.
> **Note**: It's recommended to extract as separate components whenever possible. Abusing this function might lead to bad practices for your codebase.
### Options API
When using with [Options API](https://vuejs.org/guide/introduction.html#api-styles), you will need to define `createReusableTemplate` outside of the component setup and pass to the `components` option in order to use them in the template.
```vue
<script>
import { createReusableTemplate } from '@vueuse/core'
import { defineComponent } from 'vue'
const [DefineTemplate, ReuseTemplate] = createReusableTemplate()
export default defineComponent({
components: {
DefineTemplate,
ReuseTemplate,
},
setup() {
// ...
},
})
</script>
<template>
<DefineTemplate v-slot="{ data, msg, anything }">
<div>{{ data }} passed from usage</div>
</DefineTemplate>
<ReuseTemplate :data="data" msg="The first usage" />
</template>
```
### Passing Data
You can also pass data to the template using slots:
- Use `v-slot="..."` to access the data on `<DefineTemplate>`
- Directly bind the data on `<ReuseTemplate>` to pass them to the template
```vue
<script setup lang="ts">
import { createReusableTemplate } from '@vueuse/core'
const [DefineTemplate, ReuseTemplate] = createReusableTemplate()
</script>
<template>
<DefineTemplate v-slot="{ data, msg, anything }">
<div>{{ data }} passed from usage</div>
</DefineTemplate>
<ReuseTemplate :data="data" msg="The first usage" />
<ReuseTemplate :data="anotherData" msg="The second usage" />
<ReuseTemplate v-bind="{ data: something, msg: 'The third' }" />
</template>
```
### TypeScript Support
`createReusableTemplate` accepts a generic type to provide type support for the data passed to the template:
```vue
<script setup lang="ts">
import { createReusableTemplate } from '@vueuse/core'
// Comes with pair of `DefineTemplate` and `ReuseTemplate`
const [DefineFoo, ReuseFoo] = createReusableTemplate<{ msg: string }>()
// You can create multiple reusable templates
const [DefineBar, ReuseBar] = createReusableTemplate<{ items: string[] }>()
</script>
<template>
<DefineFoo v-slot="{ msg }">
<!-- `msg` is typed as `string` -->
<div>Hello {{ msg.toUpperCase() }}</div>
</DefineFoo>
<ReuseFoo msg="World" />
<!-- @ts-expect-error Type Error! -->
<ReuseFoo :msg="1" />
</template>
```
Optionally, if you are not a fan of array destructuring, the following usages are also legal:
```vue
<script setup lang="ts">
import { createReusableTemplate } from '@vueuse/core'
const { define: DefineFoo, reuse: ReuseFoo } = createReusableTemplate<{
msg: string
}>()
</script>
<template>
<DefineFoo v-slot="{ msg }">
<div>Hello {{ msg.toUpperCase() }}</div>
</DefineFoo>
<ReuseFoo msg="World" />
</template>
```
```vue
<script setup lang="ts">
import { createReusableTemplate } from '@vueuse/core'
const TemplateFoo = createReusableTemplate<{ msg: string }>()
</script>
<template>
<TemplateFoo.define v-slot="{ msg }">
<div>Hello {{ msg.toUpperCase() }}</div>
</TemplateFoo.define>
<TemplateFoo.reuse msg="World" />
</template>
```
::: warning
Passing boolean props without `v-bind` is not supported. See the [Caveats](#boolean-props) section for more details.
:::
### Props and Attributes
By default, all props and attributes passed to `<ReuseTemplate>` will be passed to the template. If you don't want certain props to be passed to the DOM, you need to define the runtime props:
```ts
import { createReusableTemplate } from '@vueuse/core'
const [DefineTemplate, ReuseTemplate] = createReusableTemplate({
props: {
msg: String,
enable: Boolean,
}
})
```
If you don't want to pass any props to the template, you can pass the `inheritAttrs` option:
```ts
import { createReusableTemplate } from '@vueuse/core'
const [DefineTemplate, ReuseTemplate] = createReusableTemplate({
inheritAttrs: false,
})
```
### Passing Slots
It's also possible to pass slots back from `<ReuseTemplate>`. You can access the slots on `<DefineTemplate>` from `$slots`:
```vue
<script setup lang="ts">
import { createReusableTemplate } from '@vueuse/core'
const [DefineTemplate, ReuseTemplate] = createReusableTemplate()
</script>
<template>
<DefineTemplate v-slot="{ $slots, otherProp }">
<div some-layout>
<!-- To render the slot -->
<component :is="$slots.default" />
</div>
</DefineTemplate>
<ReuseTemplate>
<div>Some content</div>
</ReuseTemplate>
<ReuseTemplate>
<div>Another content</div>
</ReuseTemplate>
</template>
```
## Caveats
### Boolean props
As opposed to Vue's behavior, props defined as `boolean` that were passed without `v-bind` or absent will be resolved into an empty string or `undefined` respectively:
```vue
<script setup lang="ts">
import { createReusableTemplate } from '@vueuse/core'
const [DefineTemplate, ReuseTemplate] = createReusableTemplate<{
value?: boolean
}>()
</script>
<template>
<DefineTemplate v-slot="{ value }">
{{ typeof value }}: {{ value }}
</DefineTemplate>
<ReuseTemplate :value="true" />
<!-- boolean: true -->
<ReuseTemplate :value="false" />
<!-- boolean: false -->
<ReuseTemplate value />
<!-- string: -->
<ReuseTemplate />
<!-- undefined: -->
</template>
```
## References
This function is migrated from [vue-reuse-template](https://github.com/antfu/vue-reuse-template).
Existing Vue discussions/issues about reusing template:
- [Discussion on Reusing Templates](https://github.com/vuejs/core/discussions/6898)
Alternative Approaches:
- [Vue Macros - `namedTemplate`](https://vue-macros.sxzz.moe/features/named-template.html)
- [`unplugin-vue-reuse-template`](https://github.com/liulinboyi/unplugin-vue-reuse-template)
## Type Declarations
```ts
type ObjectLiteralWithPotentialObjectLiterals = Record<
string,
Record<string, any> | undefined
>
type GenerateSlotsFromSlotMap<
T extends ObjectLiteralWithPotentialObjectLiterals,
> = {
[K in keyof T]: Slot<T[K]>
}
export type DefineTemplateComponent<
Bindings extends Record<string, any>,
MapSlotNameToSlotProps extends ObjectLiteralWithPotentialObjectLiterals,
> = DefineComponent & {
new (): {
$slots: {
default: (
_: Bindings & {
$slots: GenerateSlotsFromSlotMap<MapSlotNameToSlotProps>
},
) => any
}
}
}
export type ReuseTemplateComponent<
Bindings extends Record<string, any>,
MapSlotNameToSlotProps extends ObjectLiteralWithPotentialObjectLiterals,
> = DefineComponent<Bindings> & {
new (): {
$slots: GenerateSlotsFromSlotMap<MapSlotNameToSlotProps>
}
}
export type ReusableTemplatePair<
Bindings extends Record<string, any>,
MapSlotNameToSlotProps extends ObjectLiteralWithPotentialObjectLiterals,
> = [
DefineTemplateComponent<Bindings, MapSlotNameToSlotProps>,
ReuseTemplateComponent<Bindings, MapSlotNameToSlotProps>,
] & {
define: DefineTemplateComponent<Bindings, MapSlotNameToSlotProps>
reuse: ReuseTemplateComponent<Bindings, MapSlotNameToSlotProps>
}
export interface CreateReusableTemplateOptions<
Props extends Record<string, any>,
> {
/**
* Inherit attrs from reuse component.
*
* @default true
*/
inheritAttrs?: boolean
/**
* Props definition for reuse component.
*/
props?: ComponentObjectPropsOptions<Props>
}
/**
* This function creates `define` and `reuse` components in pair,
* It also allow to pass a generic to bind with type.
*
* @see https://vueuse.org/createReusableTemplate
*
* @__NO_SIDE_EFFECTS__
*/
export declare function createReusableTemplate<
Bindings extends Record<string, any>,
MapSlotNameToSlotProps extends
ObjectLiteralWithPotentialObjectLiterals = Record<"default", undefined>,
>(
options?: CreateReusableTemplateOptions<Bindings>,
): ReusableTemplatePair<Bindings, MapSlotNameToSlotProps>
```

View File

@@ -0,0 +1,42 @@
---
category: State
related: createGlobalState
---
# createSharedComposable
Make a composable function usable with multiple Vue instances.
> [!WARNING]
> When used in a **SSR** environment, `createSharedComposable` will **automatically fallback** to a non-shared version.
> This means every call will create a fresh instance in SSR to avoid [cross-request state pollution](https://vuejs.org/guide/scaling-up/ssr.html#cross-request-state-pollution).
## Usage
```ts
import { createSharedComposable, useMouse } from '@vueuse/core'
const useSharedMouse = createSharedComposable(useMouse)
// CompA.vue
const { x, y } = useSharedMouse()
// CompB.vue - will reuse the previous state and no new event listeners will be registered
const { x, y } = useSharedMouse()
```
## Type Declarations
```ts
export type SharedComposableReturn<T extends AnyFn = AnyFn> = T
/**
* Make a composable function usable with multiple Vue instances.
*
* @see https://vueuse.org/createSharedComposable
*
* @__NO_SIDE_EFFECTS__
*/
export declare function createSharedComposable<Fn extends AnyFn>(
composable: Fn,
): SharedComposableReturn<Fn>
```

View File

@@ -0,0 +1,259 @@
---
category: Component
outline: deep
---
# createTemplatePromise
Template as Promise. Useful for constructing custom Dialogs, Modals, Toasts, etc.
## Usage
```vue
<script setup lang="ts">
import { createTemplatePromise } from '@vueuse/core'
const TemplatePromise = createTemplatePromise<ReturnType>()
async function open() {
const result = await TemplatePromise.start()
// button is clicked, result is 'ok'
}
</script>
<template>
<TemplatePromise v-slot="{ promise, resolve, reject, args }">
<!-- your UI -->
<button @click="resolve('ok')">
OK
</button>
</TemplatePromise>
</template>
```
## Features
- **Programmatic** - call your UI as a promise
- **Template** - use Vue template to render, not a new DSL
- **TypeScript** - full type safety via generic type
- **Renderless** - you take full control of the UI
- **Transition** - use support Vue transition
This function is migrated from [vue-template-promise](https://github.com/antfu/vue-template-promise)
## Usage
`createTemplatePromise` returns a **Vue Component** that you can directly use in your template with `<script setup>`
```ts twoslash include main
import { createTemplatePromise } from '@vueuse/core'
const TemplatePromise = createTemplatePromise()
const MyPromise = createTemplatePromise<boolean>() // with generic type
```
In template, use `v-slot` to access the promise and resolve functions.
```vue
<template>
<TemplatePromise v-slot="{ promise, resolve, reject, args }">
<!-- you can have anything -->
<button @click="resolve('ok')">
OK
</button>
</TemplatePromise>
<MyPromise v-slot="{ promise, resolve, reject, args }">
<!-- another one -->
</MyPromise>
</template>
```
The slot will not be rendered initially (similar to `v-if="false"`), until you call the `start` method from the component.
```ts
// @include: main
// ---cut---
const result = await TemplatePromise.start()
```
Once `resolve` or `reject` is called in the template, the promise will be resolved or rejected, returning the value you passed in. Once resolved, the slot will be removed automatically.
### Passing Arguments
You can pass arguments to the `start` with arguments.
```ts twoslash include passing-arguments
import { createTemplatePromise } from '@vueuse/core'
const TemplatePromise = createTemplatePromise<boolean, [string, number]>()
```
```ts
// @include: passing-arguments
// ---cut---
const result = await TemplatePromise.start('hello', 123) // Pr
```
And in the template slot, you can access the arguments via `args` property.
```vue
<template>
<TemplatePromise v-slot="{ args, resolve }">
<div>{{ args[0] }}</div>
<!-- hello -->
<div>{{ args[1] }}</div>
<!-- 123 -->
<button @click="resolve(true)">
OK
</button>
</TemplatePromise>
</template>
```
### Transition
You can use transition to animate the slot.
```vue
<script setup lang="ts">
const TemplatePromise = createTemplatePromise<ReturnType>({
transition: {
name: 'fade',
appear: true,
},
})
</script>
<template>
<TemplatePromise v-slot="{ resolve }">
<!-- your UI -->
<button @click="resolve('ok')">
OK
</button>
</TemplatePromise>
</template>
<style scoped>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
</style>
```
Learn more about [Vue Transition](https://vuejs.org/guide/built-ins/transition.html).
## Motivation
The common approach to call a dialog or a modal programmatically would be like this:
```ts
const dialog = useDialog()
const result = await dialog.open({
title: 'Hello',
content: 'World',
})
```
This would work by sending these information to the top-level component and let it render the dialog. However, it limits the flexibility you could express in the UI. For example, you could want the title to be red, or have extra buttons, etc. You would end up with a lot of options like:
```ts
const result = await dialog.open({
title: 'Hello',
titleClass: 'text-red',
content: 'World',
contentClass: 'text-blue text-sm',
buttons: [
{ text: 'OK', class: 'bg-red', onClick: () => {} },
{ text: 'Cancel', class: 'bg-blue', onClick: () => {} },
],
// ...
})
```
Even this is not flexible enough. If you want more, you might end up with manual render function.
```ts
const result = await dialog.open({
title: 'Hello',
contentSlot: () => h(MyComponent, { content }),
})
```
This is like reinventing a new DSL in the script to express the UI template.
So this function allows **expressing the UI in templates instead of scripts**, where it is supposed to be, while still being able to be manipulated programmatically.
## Type Declarations
```ts
export interface TemplatePromiseProps<Return, Args extends any[] = []> {
/**
* The promise instance.
*/
promise: Promise<Return> | undefined
/**
* Resolve the promise.
*/
resolve: (v: Return | Promise<Return>) => void
/**
* Reject the promise.
*/
reject: (v: any) => void
/**
* Arguments passed to TemplatePromise.start()
*/
args: Args
/**
* Indicates if the promise is resolving.
* When passing another promise to `resolve`, this will be set to `true` until the promise is resolved.
*/
isResolving: boolean
/**
* Options passed to createTemplatePromise()
*/
options: TemplatePromiseOptions
/**
* Unique key for list rendering.
*/
key: number
}
export interface TemplatePromiseOptions {
/**
* Determines if the promise can be called only once at a time.
*
* @default false
*/
singleton?: boolean
/**
* Transition props for the promise.
*/
transition?: TransitionGroupProps
}
export type TemplatePromise<
Return,
Args extends any[] = [],
> = DefineComponent<object> & {
new (): {
$slots: {
default: (_: TemplatePromiseProps<Return, Args>) => any
}
}
} & {
start: (...args: Args) => Promise<Return>
}
/**
* Creates a template promise component.
*
* @see https://vueuse.org/createTemplatePromise
*
* @__NO_SIDE_EFFECTS__
*/
export declare function createTemplatePromise<Return, Args extends any[] = []>(
options?: TemplatePromiseOptions,
): TemplatePromise<Return, Args>
```

View File

@@ -0,0 +1,51 @@
---
category: Utilities
related: reactify
---
# createUnrefFn
Make a plain function accepting ref and raw values as arguments.
Returns the same value the unconverted function returns, with proper typing.
::: tip
Make sure you're using the right tool for the job. Using `reactify`
might be more pertinent in some cases where you want to evaluate the function on each changes of it's arguments.
:::
## Usage
```ts
import { createUnrefFn } from '@vueuse/core'
import { shallowRef } from 'vue'
const url = shallowRef('https://httpbin.org/post')
const data = shallowRef({ foo: 'bar' })
function post(url, data) {
return fetch(url, { data })
}
const unrefPost = createUnrefFn(post)
post(url, data) /* ❌ Will throw an error because the arguments are refs */
unrefPost(url, data) /* ✔️ Will Work because the arguments will be auto unref */
```
## Type Declarations
```ts
export type UnrefFn<T> = T extends (...args: infer A) => infer R
? (
...args: {
[K in keyof A]: MaybeRef<A[K]>
}
) => R
: never
/**
* Make a plain function accepting ref and raw values as arguments.
* Returns the same value the unconverted function returns, with proper typing.
*
* @__NO_SIDE_EFFECTS__
*/
export declare function createUnrefFn<T extends Function>(fn: T): UnrefFn<T>
```

View File

@@ -0,0 +1,76 @@
---
category: Reactivity
---
# extendRef
Add extra attributes to Ref.
## Usage
> Please note the extra attribute will not be accessible in Vue's template.
```ts
import { extendRef } from '@vueuse/core'
import { shallowRef } from 'vue'
const myRef = shallowRef('content')
const extended = extendRef(myRef, { foo: 'extra data' })
extended.value === 'content'
extended.foo === 'extra data'
```
Refs will be unwrapped and be reactive
```ts
import { extendRef } from '@vueuse/core'
// ---cut---
const myRef = shallowRef('content')
const extraRef = shallowRef('extra')
const extended = extendRef(myRef, { extra: extraRef })
extended.value === 'content'
extended.extra === 'extra'
extended.extra = 'new data' // will trigger update
extraRef.value === 'new data'
```
## Type Declarations
```ts
export type ExtendRefReturn<T = any> = Ref<T>
export interface ExtendRefOptions<Unwrap extends boolean = boolean> {
/**
* Is the extends properties enumerable
*
* @default false
*/
enumerable?: boolean
/**
* Unwrap for Ref properties
*
* @default true
*/
unwrap?: Unwrap
}
/**
* Overload 1: Unwrap set to false
*/
export declare function extendRef<
R extends Ref<any>,
Extend extends object,
Options extends ExtendRefOptions<false>,
>(ref: R, extend: Extend, options?: Options): ShallowUnwrapRef<Extend> & R
/**
* Overload 2: Unwrap unset or set to true
*/
export declare function extendRef<
R extends Ref<any>,
Extend extends object,
Options extends ExtendRefOptions,
>(ref: R, extend: Extend, options?: Options): Extend & R
```

View File

@@ -0,0 +1,48 @@
---
category: '@RxJS'
---
# from / fromEvent
Wrappers around RxJS's [`from()`](https://rxjs.dev/api/index/function/from) and [`fromEvent()`](https://rxjs.dev/api/index/function/fromEvent) to allow them to accept `ref`s.
## Usage
<!-- TODO: import rxjs error if enable twoslash -->
```ts no-twoslash
import { from, fromEvent, toObserver, useSubscription } from '@vueuse/rxjs'
import { interval } from 'rxjs'
import { map, mapTo, takeUntil, withLatestFrom } from 'rxjs/operators'
import { shallowRef, useTemplateRef } from 'vue'
const count = shallowRef(0)
const button = useTemplateRef('buttonRef')
useSubscription(
interval(1000)
.pipe(
mapTo(1),
takeUntil(fromEvent(button, 'click')),
withLatestFrom(from(count, {
immediate: true,
deep: false,
})),
map(([curr, total]) => curr + total),
)
.subscribe(toObserver(count)), // same as ).subscribe(val => (count.value = val))
)
```
## Type Declarations
```ts
export declare function from<T>(
value: ObservableInput<T> | Ref<T>,
watchOptions?: WatchOptions,
): Observable<T>
export declare function fromEvent<T extends HTMLElement | null>(
value: MaybeRef<T>,
event: string,
): Observable<Event>
```

View File

@@ -0,0 +1,30 @@
---
category: Utilities
---
# get
Shorthand for accessing `ref.value`
## Usage
```ts
import { get } from '@vueuse/core'
const a = ref(42)
console.log(get(a)) // 42
```
## Type Declarations
```ts
/**
* Shorthand for accessing `ref.value`
*/
export declare function get<T>(ref: MaybeRef<T>): T
export declare function get<T, K extends keyof T>(
ref: MaybeRef<T>,
key: K,
): T[K]
```

View File

@@ -0,0 +1,35 @@
---
category: State
---
# injectLocal
Extended `inject` with ability to call `provideLocal` to provide the value in the same component.
## Usage
```vue
<script setup>
import { injectLocal, provideLocal } from '@vueuse/core'
provideLocal('MyInjectionKey', 1)
const injectedValue = injectLocal('MyInjectionKey') // injectedValue === 1
</script>
```
## Type Declarations
```ts
/**
* On the basis of `inject`, it is allowed to directly call inject to obtain the value after call provide in the same component.
*
* @example
* ```ts
* injectLocal('MyInjectionKey', 1)
* const injectedValue = injectLocal('MyInjectionKey') // injectedValue === 1
* ```
*
* @__NO_SIDE_EFFECTS__
*/
export declare const injectLocal: typeof inject
```

View File

@@ -0,0 +1,31 @@
---
category: Utilities
---
# isDefined
Non-nullish checking type guard for Ref.
## Usage
```ts
import { isDefined } from '@vueuse/core'
const example = ref(Math.random() ? 'example' : undefined) // Ref<string | undefined>
if (isDefined(example))
example // Ref<string>
```
## Type Declarations
```ts
export type IsDefinedReturn = boolean
export declare function isDefined<T>(
v: ComputedRef<T>,
): v is ComputedRef<Exclude<T, null | undefined>>
export declare function isDefined<T>(
v: Ref<T>,
): v is Ref<Exclude<T, null | undefined>>
export declare function isDefined<T>(v: T): v is Exclude<T, null | undefined>
```

View File

@@ -0,0 +1,40 @@
---
category: '@Math'
alias: and
related: logicNot, logicOr
---
# logicAnd
`AND` condition for refs.
## Usage
```ts
import { whenever } from '@vueuse/core'
import { logicAnd } from '@vueuse/math'
const a = ref(true)
const b = ref(false)
whenever(logicAnd(a, b), () => {
console.log('both a and b are now truthy!')
})
```
## Type Declarations
```ts
/**
* `AND` conditions for refs.
*
* @see https://vueuse.org/logicAnd
*
* @__NO_SIDE_EFFECTS__
*/
export declare function logicAnd(
...args: MaybeRefOrGetter<any>[]
): ComputedRef<boolean>
/** @deprecated use `logicAnd` instead */
export declare const and: typeof logicAnd
```

View File

@@ -0,0 +1,36 @@
---
category: '@Math'
alias: not
---
# logicNot
`NOT` condition for ref.
## Usage
```ts
import { whenever } from '@vueuse/core'
import { logicNot } from '@vueuse/math'
const a = ref(true)
whenever(logicNot(a), () => {
console.log('a is now falsy!')
})
```
## Type Declarations
```ts
/**
* `NOT` conditions for refs.
*
* @see https://vueuse.org/logicNot
*
* @__NO_SIDE_EFFECTS__
*/
export declare function logicNot(v: MaybeRefOrGetter<any>): ComputedRef<boolean>
/** @deprecated use `logicNot` instead */
export declare const not: typeof logicNot
```

View File

@@ -0,0 +1,40 @@
---
category: '@Math'
alias: or
related: logicAnd, logicNot
---
# logicOr
`OR` conditions for refs.
## Usage
```ts
import { whenever } from '@vueuse/core'
import { logicOr } from '@vueuse/math'
const a = ref(true)
const b = ref(false)
whenever(logicOr(a, b), () => {
console.log('either a or b is truthy!')
})
```
## Type Declarations
```ts
/**
* `OR` conditions for refs.
*
* @see https://vueuse.org/logicOr
*
* @__NO_SIDE_EFFECTS__
*/
export declare function logicOr(
...args: MaybeRefOrGetter<any>[]
): ComputedRef<boolean>
/** @deprecated use `logicOr` instead */
export declare const or: typeof logicOr
```

View File

@@ -0,0 +1,41 @@
---
category: Utilities
---
# makeDestructurable
Make isomorphic destructurable for object and array at the same time. See [this blog](https://antfu.me/posts/destructuring-with-object-or-array/) for more details.
## Usage
TypeScript Example:
```ts twoslash include main
import { makeDestructurable } from '@vueuse/core'
const foo = { name: 'foo' }
const bar = 1024
const obj = makeDestructurable(
{ foo, bar } as const,
[foo, bar] as const,
)
```
Usage:
```ts twoslash
// @include: main
// ---cut---
let { foo, bar } = obj
let [foo, bar] = obj
```
## Type Declarations
```ts
export declare function makeDestructurable<
T extends Record<string, unknown>,
A extends readonly any[],
>(obj: T, arr: A): T & A
```

View File

@@ -0,0 +1,187 @@
---
category: Sensors
---
# onClickOutside
Listen for clicks outside of an element. Useful for modal or dropdown.
## Usage
```vue
<script setup lang="ts">
import { onClickOutside } from '@vueuse/core'
import { useTemplateRef } from 'vue'
const target = useTemplateRef('target')
onClickOutside(target, event => console.log(event))
</script>
<template>
<div ref="target">
Hello world
</div>
<div>Outside element</div>
</template>
```
If you need more control over triggering the handler, you can use the `controls` option.
```ts
const { cancel, trigger } = onClickOutside(
modalRef,
(event) => {
modal.value = false
},
{ controls: true },
)
useEventListener('pointermove', (e) => {
cancel()
// or
trigger(e)
})
```
If you want to ignore certain elements, you can use the `ignore` option. Provide the elements to ignore as an array of Refs or CSS Selectors.
```ts
const ignoreElRef = useTemplateRef('ignoreEl')
const ignoreElSelector = '.ignore-el'
onClickOutside(
target,
event => console.log(event),
{ ignore: [ignoreElRef, ignoreElSelector] },
)
```
## Component Usage
```vue
<template>
<OnClickOutside :options="{ ignore: [/* ... */] }" @trigger="count++">
<div>
Click Outside of Me
</div>
</OnClickOutside>
</template>
```
## Directive Usage
```vue
<script setup lang="ts">
import { vOnClickOutside } from '@vueuse/components'
import { shallowRef } from 'vue'
const modal = shallowRef(false)
function closeModal() {
modal.value = false
}
</script>
<template>
<button @click="modal = true">
Open Modal
</button>
<div v-if="modal" v-on-click-outside="closeModal">
Hello World
</div>
</template>
```
You can also set the handler as an array to set the configuration items of the instruction.
```vue
<script setup lang="ts">
import { vOnClickOutside } from '@vueuse/components'
import { shallowRef, useTemplateRef } from 'vue'
const modal = shallowRef(false)
const ignoreElRef = useTemplateRef('ignoreEl')
const onClickOutsideHandler = [
(ev) => {
console.log(ev)
modal.value = false
},
{ ignore: [ignoreElRef] },
]
</script>
<template>
<button @click="modal = true">
Open Modal
</button>
<div ref="ignoreElRef">
click outside ignore element
</div>
<div v-if="modal" v-on-click-outside="onClickOutsideHandler">
Hello World
</div>
</template>
```
## Type Declarations
```ts
export interface OnClickOutsideOptions<Controls extends boolean = false>
extends ConfigurableWindow {
/**
* List of elements that should not trigger the event,
* provided as Refs or CSS Selectors.
*/
ignore?: MaybeRefOrGetter<(MaybeElementRef | string)[]>
/**
* Use capturing phase for internal event listener.
* @default true
*/
capture?: boolean
/**
* Run handler function if focus moves to an iframe.
* @default false
*/
detectIframe?: boolean
/**
* Use controls to cancel/trigger listener.
* @default false
*/
controls?: Controls
}
export type OnClickOutsideHandler<
T extends OnClickOutsideOptions<boolean> = OnClickOutsideOptions,
> = (
event:
| (T["detectIframe"] extends true ? FocusEvent : never)
| (T["controls"] extends true ? Event : never)
| PointerEvent,
) => void
interface OnClickOutsideControlsReturn {
stop: Fn
cancel: Fn
trigger: (event: Event) => void
}
/**
* Listen for clicks outside of an element.
*
* @see https://vueuse.org/onClickOutside
* @param target
* @param handler
* @param options
*/
export declare function onClickOutside<T extends OnClickOutsideOptions>(
target: MaybeComputedElementRef,
handler: OnClickOutsideHandler<T>,
options?: T,
): Fn
export declare function onClickOutside<T extends OnClickOutsideOptions<true>>(
target: MaybeComputedElementRef,
handler: OnClickOutsideHandler<T>,
options: T,
): OnClickOutsideControlsReturn
```

View File

@@ -0,0 +1,64 @@
---
category: Sensors
---
# onElementRemoval
Fires when the element or any element containing it is removed.
## Usage
```vue {13}
<script setup lang="ts">
import { onElementRemoval } from '@vueuse/core'
import { shallowRef, useTemplateRef } from 'vue'
const btnRef = useTemplateRef('btn')
const btnState = shallowRef(true)
const removedCount = shallowRef(0)
function btnOnClick() {
btnState.value = !btnState.value
}
onElementRemoval(btnRef, () => ++removedCount.value)
</script>
<template>
<button
v-if="btnState"
@click="btnOnClick"
>
recreate me
</button>
<button
v-else
ref="btnRef"
@click="btnOnClick"
>
remove me
</button>
<b>removed times: {{ removedCount }}</b>
</template>
```
## Type Declarations
```ts
export interface OnElementRemovalOptions
extends ConfigurableWindow,
ConfigurableDocumentOrShadowRoot,
WatchOptionsBase {}
/**
* Fires when the element or any element containing it is removed.
*
* @param target
* @param callback
* @param options
*/
export declare function onElementRemoval(
target: MaybeElementRef,
callback: (mutationRecords: MutationRecord[]) => void,
options?: OnElementRemovalOptions,
): Fn
```

View File

@@ -0,0 +1,176 @@
---
category: Sensors
---
# onKeyStroke
Listen for keyboard keystrokes.
## Usage
```ts
import { onKeyStroke } from '@vueuse/core'
onKeyStroke('ArrowDown', (e) => {
e.preventDefault()
})
```
See [this table](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values) for all key codes.
### Listen To Multiple Keys
```ts
import { onKeyStroke } from '@vueuse/core'
onKeyStroke(['s', 'S', 'ArrowDown'], (e) => {
e.preventDefault()
})
// listen to all keys by [true / skip the keyDefine]
onKeyStroke(true, (e) => {
e.preventDefault()
})
onKeyStroke((e) => {
e.preventDefault()
})
```
### Custom Event Target
```ts
import { onKeyStroke } from '@vueuse/core'
// ---cut---
onKeyStroke('A', (e) => {
console.log('Key A pressed on document')
}, { target: document })
```
### Ignore Repeated Events
The callback will trigger only once when pressing `A` and **hold down**.
```ts
import { onKeyStroke } from '@vueuse/core'
// ---cut---
// use `autoRepeat` option
onKeyStroke('A', (e) => {
console.log('Key A pressed')
}, { dedupe: true })
```
Reference: [KeyboardEvent.repeat](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/repeat)
## Directive Usage
```vue
<script setup lang="ts">
import { vOnKeyStroke } from '@vueuse/components'
function onUpdate(e: KeyboardEvent) {
// impl...
}
</script>
<template>
<input v-on-key-stroke:c,v="onUpdate" type="text">
<!-- with options -->
<input v-on-key-stroke:c,v="[onUpdate, { eventName: 'keyup' }]" type="text">
</template>
```
### Custom Keyboard Event
```ts
import { onKeyStroke } from '@vueuse/core'
// ---cut---
onKeyStroke('Shift', (e) => {
console.log('Shift key up')
}, { eventName: 'keyup' })
```
Or
```ts
import { onKeyUp } from '@vueuse/core'
// ---cut---
onKeyUp('Shift', () => console.log('Shift key up'))
```
## Shorthands
- `onKeyDown` - alias for `onKeyStroke(key, handler, {eventName: 'keydown'})`
- `onKeyPressed` - alias for `onKeyStroke(key, handler, {eventName: 'keypress'})`
- `onKeyUp` - alias for `onKeyStroke(key, handler, {eventName: 'keyup'})`
## Type Declarations
```ts
export type KeyPredicate = (event: KeyboardEvent) => boolean
export type KeyFilter = true | string | string[] | KeyPredicate
export type KeyStrokeEventName = "keydown" | "keypress" | "keyup"
export interface OnKeyStrokeOptions {
eventName?: KeyStrokeEventName
target?: MaybeRefOrGetter<EventTarget | null | undefined>
passive?: boolean
/**
* Set to `true` to ignore repeated events when the key is being held down.
*
* @default false
*/
dedupe?: MaybeRefOrGetter<boolean>
}
/**
* Listen for keyboard keystrokes.
*
* @see https://vueuse.org/onKeyStroke
*/
export declare function onKeyStroke(
key: KeyFilter,
handler: (event: KeyboardEvent) => void,
options?: OnKeyStrokeOptions,
): () => void
export declare function onKeyStroke(
handler: (event: KeyboardEvent) => void,
options?: OnKeyStrokeOptions,
): () => void
/**
* Listen to the keydown event of the given key.
*
* @see https://vueuse.org/onKeyStroke
* @param key
* @param handler
* @param options
*/
export declare function onKeyDown(
key: KeyFilter,
handler: (event: KeyboardEvent) => void,
options?: Omit<OnKeyStrokeOptions, "eventName">,
): () => void
/**
* Listen to the keypress event of the given key.
*
* @see https://vueuse.org/onKeyStroke
* @param key
* @param handler
* @param options
*/
export declare function onKeyPressed(
key: KeyFilter,
handler: (event: KeyboardEvent) => void,
options?: Omit<OnKeyStrokeOptions, "eventName">,
): () => void
/**
* Listen to the keyup event of the given key.
*
* @see https://vueuse.org/onKeyStroke
* @param key
* @param handler
* @param options
*/
export declare function onKeyUp(
key: KeyFilter,
handler: (event: KeyboardEvent) => void,
options?: Omit<OnKeyStrokeOptions, "eventName">,
): () => void
```

View File

@@ -0,0 +1,170 @@
---
category: Sensors
---
# onLongPress
Listen for a long press on an element.
Function provides modifiers in options
- stop
- once
- prevent
- capture
- self
## Usage
```vue
<script setup lang="ts">
import { onLongPress } from '@vueuse/core'
import { shallowRef, useTemplateRef } from 'vue'
const htmlRefHook = useTemplateRef('htmlRefHook')
const longPressedHook = shallowRef(false)
function onLongPressCallbackHook(e: PointerEvent) {
longPressedHook.value = true
}
function resetHook() {
longPressedHook.value = false
}
onLongPress(
htmlRefHook,
onLongPressCallbackHook,
{
modifiers: {
prevent: true
}
}
)
</script>
<template>
<p>Long Pressed: {{ longPressedHook }}</p>
<button ref="htmlRefHook" class="ml-2 button small">
Press long
</button>
<button class="ml-2 button small" @click="resetHook">
Reset
</button>
</template>
```
## Component Usage
```vue
<script setup lang="ts">
import { OnLongPress } from '@vueuse/components'
import { shallowRef } from 'vue'
const longPressedComponent = shallowRef(false)
function onLongPressCallbackComponent(e: PointerEvent) {
longPressedComponent.value = true
}
function resetComponent() {
longPressedComponent.value = false
}
</script>
<template>
<p>Long Pressed: {{ longPressedComponent }}</p>
<OnLongPress
as="button"
class="ml-2 button small"
@trigger="onLongPressCallbackComponent"
>
Press long
</OnLongPress>
<button class="ml-2 button small" @click="resetComponent">
Reset
</button>
</template>
```
## Directive Usage
```vue
<script setup lang="ts">
import { vOnLongPress } from '@vueuse/components'
import { shallowRef } from 'vue'
const longPressedDirective = shallowRef(false)
function onLongPressCallbackDirective(e: PointerEvent) {
longPressedDirective.value = true
}
function resetDirective() {
longPressedDirective.value = false
}
</script>
<template>
<p>Long Pressed: {{ longPressedDirective }}</p>
<button
v-on-long-press.prevent="onLongPressCallbackDirective"
class="ml-2 button small"
>
Press long
</button>
<button
v-on-long-press="[onLongPressCallbackDirective, { delay: 1000, modifiers: { stop: true } }]"
class="ml-2 button small"
>
Press long (with options)
</button>
<button class="ml-2 button small" @click="resetDirective">
Reset
</button>
</template>
```
## Type Declarations
```ts
export interface OnLongPressOptions {
/**
* Time in ms till `longpress` gets called
*
* @default 500
*/
delay?: number | ((ev: PointerEvent) => number)
modifiers?: OnLongPressModifiers
/**
* Allowance of moving distance in pixels,
* The action will get canceled When moving too far from the pointerdown position.
* @default 10
*/
distanceThreshold?: number | false
/**
* Function called when the ref element is released.
* @param duration how long the element was pressed in ms
* @param distance distance from the pointerdown position
* @param isLongPress whether the action was a long press or not
*/
onMouseUp?: (duration: number, distance: number, isLongPress: boolean) => void
}
export interface OnLongPressModifiers {
stop?: boolean
once?: boolean
prevent?: boolean
capture?: boolean
self?: boolean
}
export declare function onLongPress(
target: MaybeElementRef,
handler: (evt: PointerEvent) => void,
options?: OnLongPressOptions,
): () => void
export type UseOnLongPressReturn = ReturnType<typeof onLongPress>
```

View File

@@ -0,0 +1,43 @@
---
category: Sensors
---
# onStartTyping
Fires when users start typing on non-editable elements.
## Usage
```vue
<script setup lang="ts">
import { onStartTyping } from '@vueuse/core'
import { useTemplateRef } from 'vue'
const input = useTemplateRef('input')
onStartTyping(() => {
if (!input.value.active)
input.value.focus()
})
</script>
<template>
<input ref="input" type="text" placeholder="Start typing to focus">
</template>
```
## Type Declarations
```ts
/**
* Fires when users start typing on non-editable elements.
*
* @see https://vueuse.org/onStartTyping
* @param callback
* @param options
*/
export declare function onStartTyping(
callback: (event: KeyboardEvent) => void,
options?: ConfigurableDocument,
): void
```

View File

@@ -0,0 +1,37 @@
---
category: State
---
# provideLocal
Extended `provide` with ability to call `injectLocal` to obtain the value in the same component.
## Usage
```vue
<script setup>
import { injectLocal, provideLocal } from '@vueuse/core'
provideLocal('MyInjectionKey', 1)
const injectedValue = injectLocal('MyInjectionKey') // injectedValue === 1
</script>
```
## Type Declarations
```ts
export type ProvideLocalReturn = void
/**
* On the basis of `provide`, it is allowed to directly call inject to obtain the value after call provide in the same component.
*
* @example
* ```ts
* provideLocal('MyInjectionKey', 1)
* const injectedValue = injectLocal('MyInjectionKey') // injectedValue === 1
* ```
*/
export declare function provideLocal<T, K = LocalProvidedKey<T>>(
key: K,
value: K extends InjectionKey<infer V> ? V : T,
): ProvideLocalReturn
```

View File

@@ -0,0 +1,144 @@
---
category: Reactivity
alias: createReactiveFn
---
# reactify
Converts plain functions into reactive functions. The converted function accepts refs as its arguments and returns a ComputedRef, with proper typing.
::: tip
Interested to see some application or looking for some pre-reactified functions?
Check out [⚗️ Vue Chemistry](https://github.com/antfu/vue-chemistry)!
:::
## Usage
Basic example
```ts
import { reactify } from '@vueuse/core'
import { shallowRef } from 'vue'
// a plain function
function add(a: number, b: number): number {
return a + b
}
// now it accept refs and returns a computed ref
// (a: number | Ref<number>, b: number | Ref<number>) => ComputedRef<number>
const reactiveAdd = reactify(add)
const a = shallowRef(1)
const b = shallowRef(2)
const sum = reactiveAdd(a, b)
console.log(sum.value) // 3
a.value = 5
console.log(sum.value) // 7
```
An example of implementing a reactive [Pythagorean theorem](https://en.wikipedia.org/wiki/Pythagorean_theorem).
<!-- eslint-skip -->
```ts
import { reactify } from '@vueuse/core'
import { shallowRef } from 'vue'
const pow = reactify(Math.pow)
const sqrt = reactify(Math.sqrt)
const add = reactify((a: number, b: number) => a + b)
const a = shallowRef(3)
const b = shallowRef(4)
const c = sqrt(add(pow(a, 2), pow(b, 2)))
console.log(c.value) // 5
// 5:12:13
a.value = 5
b.value = 12
console.log(c.value) // 13
```
You can also do it this way:
```ts
import { reactify } from '@vueuse/core'
import { shallowRef } from 'vue'
function pythagorean(a: number, b: number) {
return Math.sqrt(a ** 2 + b ** 2)
}
const a = shallowRef(3)
const b = shallowRef(4)
const c = reactify(pythagorean)(a, b)
console.log(c.value) // 5
```
Another example of making reactive `stringify`
```ts
import { reactify } from '@vueuse/core'
import { shallowRef } from 'vue'
const stringify = reactify(JSON.stringify)
const obj = shallowRef(42)
const dumped = stringify(obj)
console.log(dumped.value) // '42'
obj.value = { foo: 'bar' }
console.log(dumped.value) // '{"foo":"bar"}'
```
## Type Declarations
```ts
export type Reactified<T, Computed extends boolean> = T extends (
...args: infer A
) => infer R
? (
...args: {
[K in keyof A]: Computed extends true
? MaybeRefOrGetter<A[K]>
: MaybeRef<A[K]>
}
) => ComputedRef<R>
: never
export type ReactifyReturn<
T extends AnyFn = AnyFn,
K extends boolean = true,
> = Reactified<T, K>
export interface ReactifyOptions<T extends boolean> {
/**
* Accept passing a function as a reactive getter
*
* @default true
*/
computedGetter?: T
}
/**
* Converts plain function into a reactive function.
* The converted function accepts refs as it's arguments
* and returns a ComputedRef, with proper typing.
*
* @param fn - Source function
* @param options - Options
*
* @__NO_SIDE_EFFECTS__
*/
export declare function reactify<T extends AnyFn, K extends boolean = true>(
fn: T,
options?: ReactifyOptions<K>,
): ReactifyReturn<T, K>
/** @deprecated use `reactify` instead */
export declare const createReactiveFn: typeof reactify
```

View File

@@ -0,0 +1,61 @@
---
category: Reactivity
---
# reactifyObject
Apply `reactify` to an object
## Usage
```ts
import { reactifyObject } from '@vueuse/core'
const reactifiedConsole = reactifyObject(console)
const a = ref('42')
reactifiedConsole.log(a) // no longer need `.value`
```
## Type Declarations
```ts
export type ReactifyNested<
T,
Keys extends keyof T = keyof T,
S extends boolean = true,
> = {
[K in Keys]: T[K] extends AnyFn ? Reactified<T[K], S> : T[K]
}
export type ReactifyObjectReturn<
T,
Keys extends keyof T,
S extends boolean = true,
> = ReactifyNested<T, Keys, S>
export interface ReactifyObjectOptions<T extends boolean>
extends ReactifyOptions<T> {
/**
* Includes names from Object.getOwnPropertyNames
*
* @default true
*/
includeOwnProperties?: boolean
}
/**
* Apply `reactify` to an object
*
* @__NO_SIDE_EFFECTS__
*/
export declare function reactifyObject<T extends object, Keys extends keyof T>(
obj: T,
keys?: (keyof T)[],
): ReactifyObjectReturn<T, Keys, true>
export declare function reactifyObject<
T extends object,
S extends boolean = true,
>(
obj: T,
options?: ReactifyObjectOptions<S>,
): ReactifyObjectReturn<T, keyof T, S>
```

View File

@@ -0,0 +1,34 @@
---
category: Reactivity
---
# reactiveComputed
Computed reactive object. Instead of returning a ref that `computed` does, `reactiveComputed` returns a reactive object.
## Usage
```ts
import { reactiveComputed } from '@vueuse/core'
const state = reactiveComputed(() => {
return {
foo: 'bar',
bar: 'baz',
}
})
state.bar // 'baz'
```
## Type Declarations
```ts
export type ReactiveComputedReturn<T extends object> = UnwrapNestedRefs<T>
/**
* Computed reactive object.
*/
export declare function reactiveComputed<T extends object>(
fn: ComputedGetter<T>,
): ReactiveComputedReturn<T>
```

View File

@@ -0,0 +1,86 @@
---
category: Reactivity
---
# reactiveOmit
Reactively omit fields from a reactive object.
## Usage
### Basic Usage
```ts
import { reactiveOmit } from '@vueuse/core'
const obj = reactive({
x: 0,
y: 0,
elementX: 0,
elementY: 0,
})
const picked = reactiveOmit(obj, 'x', 'elementX') // { y: number, elementY: number }
```
### Predicate Usage
```ts
import { reactiveOmit } from '@vueuse/core'
const obj = reactive({
bar: 'bar',
baz: 'should be omit',
foo: 'foo2',
qux: true,
})
const picked = reactiveOmit(obj, (value, key) => key === 'baz' || value === true)
// { bar: string, foo: string }
```
### Scenarios
#### Selectively passing props to child
```vue
<script setup lang="ts">
import { reactiveOmit } from '@vueuse/core'
const props = defineProps<{
value: string
color?: string
font?: string
}>()
const childProps = reactiveOmit(props, 'value')
</script>
<template>
<div>
<!-- only passes "color" and "font" props to child -->
<ChildComp v-bind="childProps" />
</div>
</template>
```
## Type Declarations
```ts
export type ReactiveOmitReturn<
T extends object,
K extends keyof T | undefined = undefined,
> = [K] extends [undefined] ? Partial<T> : Omit<T, Extract<K, keyof T>>
export type ReactiveOmitPredicate<T> = (
value: T[keyof T],
key: keyof T,
) => boolean
export declare function reactiveOmit<T extends object, K extends keyof T>(
obj: T,
...keys: (K | K[])[]
): ReactiveOmitReturn<T, K>
export declare function reactiveOmit<T extends object>(
obj: T,
predicate: ReactiveOmitPredicate<T>,
): ReactiveOmitReturn<T>
```

View File

@@ -0,0 +1,106 @@
---
category: Reactivity
---
# reactivePick
Reactively pick fields from a reactive object.
## Usage
### Basic Usage
```ts
import { reactivePick } from '@vueuse/core'
const obj = reactive({
x: 0,
y: 0,
elementX: 0,
elementY: 0,
})
const picked = reactivePick(obj, 'x', 'elementX') // { x: number, elementX: number }
```
### Predicate Usage
```ts
import { reactivePick } from '@vueuse/core'
const source = reactive({
foo: 'foo',
bar: 'bar',
baz: 'baz',
qux: true,
})
const state = reactivePick(source, (value, key) => key !== 'bar' && value !== true)
// { foo: string, baz: string }
source.qux = false
// { foo: string, baz: string, qux: boolean }
```
### Scenarios
#### Selectively passing props to child
```vue
<script setup lang="ts">
import { reactivePick } from '@vueuse/core'
const props = defineProps<{
value: string
color?: string
font?: string
}>()
const childProps = reactivePick(props, 'color', 'font')
</script>
<template>
<div>
<!-- only passes "color" and "font" props to child -->
<ChildComp v-bind="childProps" />
</div>
</template>
```
#### Selectively wrap reactive object
Instead of doing this
```ts
import { useElementBounding } from '@vueuse/core'
import { reactive } from 'vue'
const { height, width } = useElementBounding() // object of refs
const size = reactive({ height, width })
```
Now we can just have this
```ts
import { reactivePick, useElementBounding } from '@vueuse/core'
const size = reactivePick(useElementBounding(), 'height', 'width')
```
## Type Declarations
```ts
export type ReactivePickReturn<T extends object, K extends keyof T> = {
[S in K]: UnwrapRef<T[S]>
}
export type ReactivePickPredicate<T> = (
value: T[keyof T],
key: keyof T,
) => boolean
export declare function reactivePick<T extends object, K extends keyof T>(
obj: T,
...keys: (K | K[])[]
): ReactivePickReturn<T, K>
export declare function reactivePick<T extends object>(
obj: T,
predicate: ReactivePickPredicate<T>,
): ReactivePickReturn<T, keyof T>
```

View File

@@ -0,0 +1,44 @@
---
category: Reactivity
alias: autoResetRef
---
# refAutoReset
A ref which will be reset to the default value after some time.
## Usage
```ts
import { refAutoReset } from '@vueuse/core'
const message = refAutoReset('default message', 1000)
function setMessage() {
// here the value will change to 'message has set' but after 1000ms, it will change to 'default message'
message.value = 'message has set'
}
```
::: info
You can use `triggerRef` to trigger effects after making deep mutations to the inner value of a refAutoReset.
:::
## Type Declarations
```ts
export type RefAutoResetReturn<T = any> = Ref<T>
/**
* Create a ref which will be reset to the default value after some time.
*
* @see https://vueuse.org/refAutoReset
* @param defaultValue The value which will be set.
* @param afterMs A zero-or-greater delay in milliseconds.
*/
export declare function refAutoReset<T>(
defaultValue: MaybeRefOrGetter<T>,
afterMs?: MaybeRefOrGetter<number>,
): RefAutoResetReturn<T>
/** @deprecated use `refAutoReset` instead */
export declare const autoResetRef: typeof refAutoReset
```

View File

@@ -0,0 +1,81 @@
---
category: Reactivity
alias: useDebounce, debouncedRef
---
# refDebounced
Debounce execution of a ref value.
## Usage
```ts {5}
import { refDebounced } from '@vueuse/core'
import { shallowRef } from 'vue'
const input = shallowRef('foo')
const debounced = refDebounced(input, 1000)
input.value = 'bar'
console.log(debounced.value) // 'foo'
await sleep(1100)
console.log(debounced.value) // 'bar'
// ---cut-after---
function sleep(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms))
}
```
An example with object ref.
```js
import { refDebounced } from '@vueuse/core'
import { shallowRef } from 'vue'
const data = shallowRef({
name: 'foo',
age: 18,
})
const debounced = refDebounced(data, 1000)
function update() {
data.value = {
...data.value,
name: 'bar',
}
}
console.log(debounced.value) // { name: 'foo', age: 18 }
update()
await sleep(1100)
console.log(debounced.value) // { name: 'bar', age: 18 }
```
You can also pass an optional 3rd parameter including maxWait option. See `useDebounceFn` for details.
## Recommended Reading
- [**Debounce vs Throttle**: Definitive Visual Guide](https://kettanaito.com/blog/debounce-vs-throttle)
## Type Declarations
```ts
export type RefDebouncedReturn<T = any> = Readonly<Ref<T>>
/**
* Debounce updates of a ref.
*
* @return A new debounced ref.
*/
export declare function refDebounced<T>(
value: Ref<T>,
ms?: MaybeRefOrGetter<number>,
options?: DebounceFilterOptions,
): RefDebouncedReturn<T>
/** @deprecated use `refDebounced` instead */
export declare const debouncedRef: typeof refDebounced
/** @deprecated use `refDebounced` instead */
export declare const useDebounce: typeof refDebounced
```

View File

@@ -0,0 +1,36 @@
---
category: Reactivity
---
# refDefault
Apply default value to a ref.
## Usage
```ts
import { refDefault, useStorage } from '@vueuse/core'
const raw = useStorage('key')
const state = refDefault(raw, 'default')
raw.value = 'hello'
console.log(state.value) // hello
raw.value = undefined
console.log(state.value) // default
```
## Type Declarations
```ts
/**
* Apply default value to a ref.
*
* @__NO_SIDE_EFFECTS__
*/
export declare function refDefault<T>(
source: Ref<T | undefined | null>,
defaultValue: T,
): Ref<T>
```

View File

@@ -0,0 +1,44 @@
---
category: Reactivity
---
# refManualReset
Create a ref with manual reset functionality.
## Usage
```ts
import { refManualReset } from '@vueuse/core'
const message = refManualReset('default message')
message.value = 'message has set'
message.reset()
console.log(message.value) // 'default message'
```
## Type Declarations
```ts
/**
* Define the shape of a ref that supports manual reset functionality.
*
* This interface extends the standard `Ref` type from Vue and adds a `reset` method.
* The `reset` method allows the ref to be manually reset to its default value.
*/
export interface ManualResetRefReturn<T> extends Ref<T> {
reset: Fn
}
/**
* Create a ref with manual reset functionality.
*
* @see https://vueuse.org/refManualReset
* @param defaultValue The value which will be set.
*/
export declare function refManualReset<T>(
defaultValue: MaybeRefOrGetter<T>,
): ManualResetRefReturn<T>
```

View File

@@ -0,0 +1,99 @@
---
category: Reactivity
alias: useThrottle, throttledRef
---
# refThrottled
Throttle changing of a ref value.
## Usage
```ts
import { refThrottled } from '@vueuse/core'
import { shallowRef } from 'vue'
const input = shallowRef('')
const throttled = refThrottled(input, 1000)
```
An example with object ref.
```js
import { refThrottled } from '@vueuse/core'
import { shallowRef } from 'vue'
const data = shallowRef({
count: 0,
name: 'foo',
})
const throttled = refThrottled(data, 1000)
data.value = { count: 1, name: 'foo' }
console.log(throttled.value) // { count: 1, name: 'foo' } (immediate)
data.value = { count: 2, name: 'bar' }
data.value = { count: 3, name: 'baz' }
data.value = { count: 4, name: 'qux' }
console.log(throttled.value) // { count: 1, name: 'foo' } (still first value)
// After 1000ms, next change will be applied
await sleep(1100)
data.value = { count: 5, name: 'final' }
await nextTick()
console.log(throttled.value) // { count: 5, name: 'final' } (updated)
```
### Trailing
If you don't want to watch trailing changes, set 3rd param `false` (it's `true` by default):
```ts
import { refThrottled } from '@vueuse/core'
import { shallowRef } from 'vue'
const input = shallowRef('')
const throttled = refThrottled(input, 1000, false)
```
### Leading
Allows the callback to be invoked immediately (on the leading edge of the `ms` timeout). If you don't want this behavior, set the 4th param `false` (it's `true` by default):
```ts
import { refThrottled } from '@vueuse/core'
import { shallowRef } from 'vue'
const input = shallowRef('')
const throttled = refThrottled(input, 1000, undefined, false)
```
## Recommended Reading
- [Debounce vs Throttle: Definitive Visual Guide](https://kettanaito.com/blog/debounce-vs-throttle)
- [Debouncing and Throttling Explained Through Examples](https://css-tricks.com/debouncing-throttling-explained-examples/)
## Type Declarations
```ts
export type RefThrottledReturn<T = any> = Ref<T>
/**
* Throttle execution of a function. Especially useful for rate limiting
* execution of handlers on events like resize and scroll.
*
* @param value Ref value to be watched with throttle effect
* @param delay A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful.
* @param trailing if true, update the value again after the delay time is up
* @param leading if true, update the value on the leading edge of the ms timeout
*/
export declare function refThrottled<T = any>(
value: Ref<T>,
delay?: number,
trailing?: boolean,
leading?: boolean,
): RefThrottledReturn<T>
/** @deprecated use `refThrottled` instead */
export declare const throttledRef: typeof refThrottled
/** @deprecated use `refThrottled` instead */
export declare const useThrottle: typeof refThrottled
```

View File

@@ -0,0 +1,146 @@
---
category: Reactivity
alias: controlledRef
related: computedWithControl
---
# refWithControl
Fine-grained controls over ref and its reactivity.
## Usage
`refWithControl` uses `extendRef` to provide two extra functions `get` and `set` to have better control over when it should track/trigger the reactivity.
```ts
import { refWithControl } from '@vueuse/core'
const num = refWithControl(0)
const doubled = computed(() => num.value * 2)
// just like normal ref
num.value = 42
console.log(num.value) // 42
console.log(doubled.value) // 84
// set value without triggering the reactivity
num.set(30, false)
console.log(num.value) // 30
console.log(doubled.value) // 84 (doesn't update)
// get value without tracking the reactivity
watchEffect(() => {
console.log(num.peek())
}) // 30
num.value = 50 // watch effect wouldn't be triggered since it collected nothing.
console.log(doubled.value) // 100 (updated again since it's a reactive set)
```
### `peek`, `lay`, `untrackedGet`, `silentSet`
We also provide some shorthands for doing the get/set without track/triggering the reactivity system. The following lines are equivalent.
```ts
import { refWithControl } from '@vueuse/core'
// ---cut---
const foo = refWithControl('foo')
```
```ts
import { refWithControl } from '@vueuse/core'
const foo = refWithControl('foo')
// ---cut---
// getting
foo.get(false)
foo.untrackedGet()
foo.peek() // an alias for `untrackedGet`
```
```ts
import { refWithControl } from '@vueuse/core'
const foo = refWithControl('foo')
// ---cut---
// setting
foo.set('bar', false)
foo.silentSet('bar')
foo.lay('bar') // an alias for `silentSet`
```
## Configurations
### `onBeforeChange()`
`onBeforeChange` option is offered to give control over if a new value should be accepted. For example:
```ts
import { refWithControl } from '@vueuse/core'
// ---cut---
const num = refWithControl(0, {
onBeforeChange(value, oldValue) {
// disallow changes larger then ±5 in one operation
if (Math.abs(value - oldValue) > 5)
return false // returning `false` to dismiss the change
},
})
num.value += 1
console.log(num.value) // 1
num.value += 6
console.log(num.value) // 1 (change been dismissed)
```
### `onChanged()`
`onChanged` option offers a similar functionally as Vue's `watch` but being synchronized with less overhead compared to `watch`.
```ts
import { refWithControl } from '@vueuse/core'
// ---cut---
const num = refWithControl(0, {
onChanged(value, oldValue) {
console.log(value)
},
})
```
## Type Declarations
```ts
export interface ControlledRefOptions<T> {
/**
* Callback function before the ref changing.
*
* Returning `false` to dismiss the change.
*/
onBeforeChange?: (value: T, oldValue: T) => void | boolean
/**
* Callback function after the ref changed
*
* This happens synchronously, with less overhead compare to `watch`
*/
onChanged?: (value: T, oldValue: T) => void
}
/**
* Fine-grained controls over ref and its reactivity.
*
* @__NO_SIDE_EFFECTS__
*/
export declare function refWithControl<T>(
initial: T,
options?: ControlledRefOptions<T>,
): ShallowUnwrapRef<{
get: (tracking?: boolean) => T
set: (value: T, triggering?: boolean) => void
untrackedGet: () => T
silentSet: (v: T) => void
peek: () => T
lay: (v: T) => void
}> &
Ref<T, T>
/** @deprecated use `refWithControl` instead */
export declare const controlledRef: typeof refWithControl
```

View File

@@ -0,0 +1,30 @@
---
category: Utilities
---
# set
Shorthand for `ref.value = x`
## Usage
```ts
import { set } from '@vueuse/core'
const a = ref(0)
set(a, 1)
console.log(a.value) // 1
```
## Type Declarations
```ts
export declare function set<T>(ref: Ref<T>, value: T): void
export declare function set<O extends object, K extends keyof O>(
target: O,
key: K,
value: O[K],
): void
```

View File

@@ -0,0 +1,195 @@
---
category: Reactivity
related: syncRefs
---
# syncRef
Two-way refs synchronization.
## Usage
```ts
import { syncRef } from '@vueuse/core'
const a = ref('a')
const b = ref('b')
const stop = syncRef(a, b)
console.log(a.value) // a
b.value = 'foo'
console.log(a.value) // foo
a.value = 'bar'
console.log(b.value) // bar
```
### One directional
```ts
import { syncRef } from '@vueuse/core'
const a = ref('a')
const b = ref('b')
const stop = syncRef(a, b, { direction: 'rtl' })
```
### Custom Transform
```ts
import { syncRef } from '@vueuse/core'
const a = ref(10)
const b = ref(2)
const stop = syncRef(a, b, {
transform: {
ltr: left => left * 2,
rtl: right => right / 2
}
})
console.log(b.value) // 20
b.value = 30
console.log(a.value) // 15
```
## Type Declarations
```ts
type Direction = "ltr" | "rtl" | "both"
type SpecificFieldPartial<T, K extends keyof T> = Partial<Pick<T, K>> &
Omit<T, K>
/**
* A = B
*/
type Equal<A, B> = [A] extends [B] ? ([B] extends [A] ? true : false) : false
/**
* A ∩ B ≠ ∅
*/
type IntersectButNotEqual<A, B> =
Equal<A, B> extends true ? false : A & B extends never ? false : true
/**
* A ⊆ B
*/
type IncludeButNotEqual<A, B> =
Equal<A, B> extends true ? false : A extends B ? true : false
/**
* A ∩ B = ∅
*/
type NotIntersect<A, B> =
Equal<A, B> extends true ? false : A & B extends never ? true : false
interface EqualType<
D extends Direction,
L,
R,
O extends keyof Transform<L, R> = D extends "both" ? "ltr" | "rtl" : D,
> {
transform?: SpecificFieldPartial<Pick<Transform<L, R>, O>, O>
}
type StrictIncludeMap<
IncludeType extends "LR" | "RL",
D extends Exclude<Direction, "both">,
L,
R,
> = Equal<[IncludeType, D], ["LR", "ltr"]> &
Equal<[IncludeType, D], ["RL", "rtl"]> extends true
? {
transform?: SpecificFieldPartial<Pick<Transform<L, R>, D>, D>
}
: {
transform: Pick<Transform<L, R>, D>
}
type StrictIncludeType<
IncludeType extends "LR" | "RL",
D extends Direction,
L,
R,
> = D extends "both"
? {
transform: SpecificFieldPartial<
Transform<L, R>,
IncludeType extends "LR" ? "ltr" : "rtl"
>
}
: D extends Exclude<Direction, "both">
? StrictIncludeMap<IncludeType, D, L, R>
: never
type IntersectButNotEqualType<D extends Direction, L, R> = D extends "both"
? {
transform: Transform<L, R>
}
: D extends Exclude<Direction, "both">
? {
transform: Pick<Transform<L, R>, D>
}
: never
type NotIntersectType<D extends Direction, L, R> = IntersectButNotEqualType<
D,
L,
R
>
interface Transform<L, R> {
ltr: (left: L) => R
rtl: (right: R) => L
}
type TransformType<D extends Direction, L, R> =
Equal<L, R> extends true
? EqualType<D, L, R>
: IncludeButNotEqual<L, R> extends true
? StrictIncludeType<"LR", D, L, R>
: IncludeButNotEqual<R, L> extends true
? StrictIncludeType<"RL", D, L, R>
: IntersectButNotEqual<L, R> extends true
? IntersectButNotEqualType<D, L, R>
: NotIntersect<L, R> extends true
? NotIntersectType<D, L, R>
: never
export type SyncRefOptions<
L,
R,
D extends Direction,
> = ConfigurableFlushSync & {
/**
* Watch deeply
*
* @default false
*/
deep?: boolean
/**
* Sync values immediately
*
* @default true
*/
immediate?: boolean
/**
* Direction of syncing. Value will be redefined if you define syncConvertors
*
* @default 'both'
*/
direction?: D
} & TransformType<D, L, R>
/**
* Two-way refs synchronization.
* From the set theory perspective to restrict the option's type
* Check in the following order:
* 1. L = R
* 2. L ∩ R ≠ ∅
* 3. L ⊆ R
* 4. L ∩ R = ∅
*/
export declare function syncRef<L, R, D extends Direction = "both">(
left: Ref<L>,
right: Ref<R>,
...[options]: Equal<L, R> extends true
? [options?: SyncRefOptions<L, R, D>]
: [options: SyncRefOptions<L, R, D>]
): () => void
```

View File

@@ -0,0 +1,128 @@
---
category: Reactivity
related: syncRef
---
# syncRefs
Keep target refs in sync with a source ref
## Usage
```ts
import { syncRefs } from '@vueuse/core'
import { shallowRef } from 'vue'
const source = shallowRef('hello')
const target = shallowRef('target')
const stop = syncRefs(source, target)
console.log(target.value) // hello
source.value = 'foo'
console.log(target.value) // foo
```
### Sync with multiple targets
You can also pass an array of refs to sync.
```ts
import { syncRefs } from '@vueuse/core'
import { shallowRef } from 'vue'
const source = shallowRef('hello')
const target1 = shallowRef('target1')
const target2 = shallowRef('target2')
const stop = syncRefs(source, [target1, target2])
console.log(target1.value) // hello
console.log(target2.value) // hello
source.value = 'foo'
console.log(target1.value) // foo
console.log(target2.value) // foo
```
## Watch options
The options for `syncRefs` are similar to `watch`'s `WatchOptions` but with different default values.
```ts
export interface SyncRefOptions {
/**
* Timing for syncing, same as watch's flush option
*
* @default 'sync'
*/
flush?: WatchOptionFlush
/**
* Watch deeply
*
* @default false
*/
deep?: boolean
/**
* Sync values immediately
*
* @default true
*/
immediate?: boolean
}
```
When setting `{ flush: 'pre' }`, the target reference will be updated at [the end of the current "tick"](https://vuejs.org/guide/essentials/watchers.html#callback-flush-timing) before rendering starts.
```ts
import { syncRefs } from '@vueuse/core'
import { nextTick, shallowRef } from 'vue'
const source = shallowRef('hello')
const target = shallowRef('target')
syncRefs(source, target, { flush: 'pre' })
console.log(target.value) // hello
source.value = 'foo'
console.log(target.value) // hello <- still unchanged, because of flush 'pre'
await nextTick()
console.log(target.value) // foo <- changed!
```
## Type Declarations
```ts
export interface SyncRefsOptions extends ConfigurableFlushSync {
/**
* Watch deeply
*
* @default false
*/
deep?: boolean
/**
* Sync values immediately
*
* @default true
*/
immediate?: boolean
}
/**
* Keep target ref(s) in sync with the source ref
*
* @param source source ref
* @param targets
*/
export declare function syncRefs<T>(
source: WatchSource<T>,
targets: Ref<T> | Ref<T>[],
options?: SyncRefsOptions,
): WatchHandle
```

View File

@@ -0,0 +1,86 @@
---
category: Component
---
::: info
This function will be removed in future version.
Vue 3.5 introduced the `useTemplateRef` API which can effectively replace the functionality of `templateRef`, therefore we recommend using the native approach.
:::
# templateRef
Shorthand for binding ref to template element.
## Usage
<!-- eslint-skip -->
```vue
<script lang="ts">
import { templateRef } from '@vueuse/core'
export default {
setup() {
const target = templateRef('target')
// no need to return the `target`, it will bind to the ref magically
},
}
</script>
<template>
<div ref="target" />
</template>
```
### With JSX/TSX
```tsx
import { templateRef } from '@vueuse/core'
export default {
setup() {
const target = templateRef<HTMLElement | null>('target', null)
// use string ref
return () => <div ref="target"></div>
},
}
```
### `<script setup>`
There is no need for this when using with `<script setup>` since all the variables will be exposed to the template. It will be exactly the same as `ref`.
```vue
<script setup lang="ts">
import { ref } from 'vue'
const target = ref<HTMLElement | null>(null)
</script>
<template>
<div ref="target" />
</template>
```
## Type Declarations
```ts
/**
* @deprecated Use Vue's built-in `useTemplateRef` instead.
*
* Shorthand for binding ref to template element.
*
* @see https://vueuse.org/templateRef
* @param key
* @param initialValue
*
* @__NO_SIDE_EFFECTS__
*/
export declare function templateRef<
T extends HTMLElement | SVGElement | Component | null,
Keys extends string = string,
>(key: Keys, initialValue?: T | null): Readonly<Ref<T>>
```

View File

@@ -0,0 +1,38 @@
---
category: '@RxJS'
---
# toObserver
Sugar function to convert a `ref` into an RxJS [Observer](https://rxjs.dev/guide/observer).
## Usage
<!-- TODO: import rxjs error if enable twoslash -->
```ts no-twoslash
import { from, fromEvent, toObserver, useSubscription } from '@vueuse/rxjs'
import { interval } from 'rxjs'
import { map, mapTo, startWith, takeUntil, withLatestFrom } from 'rxjs/operators'
import { shallowRef, useTemplateRef } from 'vue'
const count = shallowRef(0)
const button = useTemplateRef('buttonRef')
useSubscription(
interval(1000)
.pipe(
mapTo(1),
takeUntil(fromEvent(button, 'click')),
withLatestFrom(from(count).pipe(startWith(0))),
map(([curr, total]) => curr + total),
)
.subscribe(toObserver(count)), // same as ).subscribe(val => (count.value = val))
)
```
## Type Declarations
```ts
export declare function toObserver<T>(value: Ref<T>): NextObserver<T>
```

View File

@@ -0,0 +1,41 @@
---
category: Reactivity
---
# toReactive
Converts ref to reactive. Also made possible to create a "swapable" reactive object.
## Usage
```ts
import { toReactive } from '@vueuse/core'
import { ref } from 'vue'
const refState = ref({ foo: 'bar' })
console.log(refState.value.foo) // => 'bar'
const state = toReactive(refState) // <--
console.log(state.foo) // => 'bar'
refState.value = { bar: 'foo' }
console.log(state.foo) // => undefined
console.log(state.bar) // => 'foo'
```
## Type Declarations
```ts
/**
* Converts ref to reactive.
*
* @see https://vueuse.org/toReactive
* @param objectRef A ref of object
*/
export declare function toReactive<T extends object>(
objectRef: MaybeRef<T>,
): UnwrapNestedRefs<T>
```

View File

@@ -0,0 +1,75 @@
---
category: Reactivity
alias: resolveRef
---
# toRef
Normalize value/ref/getter to `ref` or `computed`.
## Usage
```ts
import { toRef } from '@vueuse/core'
const foo = ref('hi')
const a = toRef(0) // Ref<number>
const b = toRef(foo) // Ref<string>
const c = toRef(() => 'hi') // ComputedRef<string>
```
## Differences from Vue's `toRef`
VueUse's `toRef` is not the same as Vues `toRef` from the `vue` package.
### VueUse `toRef`
- Accepts **value**, **ref**, or **getter**
- Returns:
- a **ref** for primitive values
- a **ref** for existing refs
- a **computed** for getter functions
- Does **not** accept `object + key`
- Getters always produce readonly computed values
### Vue `toRef`
- Accepts only:
- a **reactive object + property key**, or
- an existing **ref**
- Produces a **writable ref** linked to the underlying reactive object
- Does **not** accept primitive values
- Does **not** accept getter functions
### Summary
| Behavior | VueUse `toRef` | Vue `toRef` |
| ------------------------ | ------------------------- | ----------------------- |
| Accepts primitive values | ✔️ | ❌ |
| Accepts getter | ✔️ (computed) | ❌ |
| Accepts existing ref | ✔️ | ✔️ |
| Accepts object + key | ❌ | ✔️ |
| Writable | ✔️ (except getter) | ✔️ |
| Purpose | Normalize to ref/computed | Bind to reactive object |
## Type Declarations
```ts
/**
* Normalize value/ref/getter to `ref` or `computed`.
*/
export declare function toRef<T>(r: () => T): Readonly<Ref<T>>
export declare function toRef<T>(r: ComputedRef<T>): ComputedRef<T>
export declare function toRef<T>(r: MaybeRefOrGetter<T>): Ref<T>
export declare function toRef<T>(r: T): Ref<T>
export declare function toRef<T extends object, K extends keyof T>(
object: T,
key: K,
): ToRef<T[K]>
export declare function toRef<T extends object, K extends keyof T>(
object: T,
key: K,
defaultValue: T[K],
): ToRef<Exclude<T[K], undefined>>
```

View File

@@ -0,0 +1,81 @@
---
category: Reactivity
---
# toRefs
Extended [`toRefs`](https://vuejs.org/api/reactivity-utilities.html#torefs) that also accepts refs of an object.
## Usage
<!-- eslint-disable array-bracket-spacing -->
<!-- eslint-disable ts/no-redeclare -->
```ts
import { toRefs } from '@vueuse/core'
import { reactive, ref } from 'vue'
const objRef = ref({ a: 'a', b: 0 })
const arrRef = ref(['a', 0])
const { a, b } = toRefs(objRef)
const [a, b] = toRefs(arrRef)
const obj = reactive({ a: 'a', b: 0 })
const arr = reactive(['a', 0])
const { a, b } = toRefs(obj)
const [a, b] = toRefs(arr)
```
## Use-cases
### Destructuring a props object
```vue
<script lang="ts">
import { toRefs, useVModel } from '@vueuse/core'
export default {
setup(props) {
const refs = toRefs(useVModel(props, 'data'))
console.log(refs.a.value) // props.data.a
refs.a.value = 'a' // emit('update:data', { ...props.data, a: 'a' })
return { ...refs }
}
}
</script>
<template>
<div>
<input v-model="a" type="text">
<input v-model="b" type="text">
</div>
</template>
```
## Type Declarations
```ts
export interface ToRefsOptions {
/**
* Replace the original ref with a copy on property update.
*
* @default true
*/
replaceRef?: MaybeRefOrGetter<boolean>
}
/**
* Extended `toRefs` that also accepts refs of an object.
*
* @see https://vueuse.org/toRefs
* @param objectRef A ref or normal object or array.
* @param options Options
*/
export declare function toRefs<T extends object>(
objectRef: MaybeRef<T>,
options?: ToRefsOptions,
): ToRefs<T>
```

View File

@@ -0,0 +1,34 @@
---
category: Component
---
# tryOnBeforeMount
Safe `onBeforeMount`. Call `onBeforeMount()` if it's inside a component lifecycle, if not, just call the function
## Usage
```ts
import { tryOnBeforeMount } from '@vueuse/core'
tryOnBeforeMount(() => {
})
```
## Type Declarations
```ts
/**
* Call onBeforeMount() if it's inside a component lifecycle, if not, just call the function
*
* @param fn
* @param sync if set to false, it will run in the nextTick() of Vue
* @param target
*/
export declare function tryOnBeforeMount(
fn: Fn,
sync?: boolean,
target?: ComponentInternalInstance | null,
): void
```

View File

@@ -0,0 +1,32 @@
---
category: Component
---
# tryOnBeforeUnmount
Safe `onBeforeUnmount`. Call `onBeforeUnmount()` if it's inside a component lifecycle, if not, do nothing
## Usage
```ts
import { tryOnBeforeUnmount } from '@vueuse/core'
tryOnBeforeUnmount(() => {
})
```
## Type Declarations
```ts
/**
* Call onBeforeUnmount() if it's inside a component lifecycle, if not, do nothing
*
* @param fn
* @param target
*/
export declare function tryOnBeforeUnmount(
fn: Fn,
target?: ComponentInternalInstance | null,
): void
```

View File

@@ -0,0 +1,34 @@
---
category: Component
---
# tryOnMounted
Safe `onMounted`. Call `onMounted()` if it's inside a component lifecycle, if not, just call the function
## Usage
```ts
import { tryOnMounted } from '@vueuse/core'
tryOnMounted(() => {
})
```
## Type Declarations
```ts
/**
* Call onMounted() if it's inside a component lifecycle, if not, just call the function
*
* @param fn
* @param sync if set to false, it will run in the nextTick() of Vue
* @param target
*/
export declare function tryOnMounted(
fn: Fn,
sync?: boolean,
target?: ComponentInternalInstance | null,
): void
```

View File

@@ -0,0 +1,31 @@
---
category: Component
---
# tryOnScopeDispose
Safe `onScopeDispose`. Call `onScopeDispose()` if it's inside an effect scope lifecycle, if not, do nothing
## Usage
```ts
import { tryOnScopeDispose } from '@vueuse/core'
tryOnScopeDispose(() => {
})
```
## Type Declarations
```ts
/**
* Call onScopeDispose() if it's inside an effect scope lifecycle, if not, do nothing
*
* @param fn
*/
export declare function tryOnScopeDispose(
fn: Fn,
failSilently?: boolean,
): boolean
```

View File

@@ -0,0 +1,32 @@
---
category: Component
---
# tryOnUnmounted
Safe `onUnmounted`. Call `onUnmounted()` if it's inside a component lifecycle, if not, do nothing
## Usage
```ts
import { tryOnUnmounted } from '@vueuse/core'
tryOnUnmounted(() => {
})
```
## Type Declarations
```ts
/**
* Call onUnmounted() if it's inside a component lifecycle, if not, do nothing
*
* @param fn
* @param target
*/
export declare function tryOnUnmounted(
fn: Fn,
target?: ComponentInternalInstance | null,
): void
```

View File

@@ -0,0 +1,54 @@
---
category: Component
---
# unrefElement
Retrieves the underlying DOM element from a Vue ref or component instance
## Usage
```vue
<script setup lang="ts">
import { unrefElement } from '@vueuse/core'
import { onMounted, useTemplateRef } from 'vue'
const div = useTemplateRef('div') // will be bound to the <div> element
const hello = useTemplateRef('hello') // will be bound to the HelloWorld Component
onMounted(() => {
console.log(unrefElement(div)) // the <div> element
console.log(unrefElement(hello)) // the root element of the HelloWorld Component
})
</script>
<template>
<div ref="div" />
<HelloWorld ref="hello" />
</template>
```
## Type Declarations
```ts
export type VueInstance = ComponentPublicInstance
export type MaybeElementRef<T extends MaybeElement = MaybeElement> = MaybeRef<T>
export type MaybeComputedElementRef<T extends MaybeElement = MaybeElement> =
MaybeRefOrGetter<T>
export type MaybeElement =
| HTMLElement
| SVGElement
| VueInstance
| undefined
| null
export type UnRefElementReturn<T extends MaybeElement = MaybeElement> =
T extends VueInstance ? Exclude<MaybeElement, VueInstance> : T | undefined
/**
* Get the dom element of a ref of element or Vue component instance
*
* @param elRef
*/
export declare function unrefElement<T extends MaybeElement>(
elRef: MaybeComputedElementRef<T>,
): UnRefElementReturn<T>
```

View File

@@ -0,0 +1,165 @@
---
category: Watch
---
# until
Promised one-time watch for changes
## Usage
#### Wait for some async data to be ready
```ts
import { until, useAsyncState } from '@vueuse/core'
const { state, isReady } = useAsyncState(
fetch('https://jsonplaceholder.typicode.com/todos/1').then(t => t.json()),
{},
)
;(async () => {
await until(isReady).toBe(true)
console.log(state) // state is now ready!
})()
```
#### Wait for custom conditions
> You can use `invoke` to call the async function.
```ts
import { invoke, until, useCounter } from '@vueuse/core'
const { count } = useCounter()
invoke(async () => {
await until(count).toMatch(v => v > 7)
alert('Counter is now larger than 7!')
})
```
#### Timeout
```ts
import { until } from '@vueuse/core'
// ---cut---
// will be resolve until ref.value === true or 1000ms passed
await until(ref).toBe(true, { timeout: 1000 })
// will throw if timeout
try {
await until(ref).toBe(true, { timeout: 1000, throwOnTimeout: true })
// ref.value === true
}
catch (e) {
// timeout
}
```
#### More Examples
```ts
import { until } from '@vueuse/core'
// ---cut---
await until(ref).toBe(true)
await until(ref).toMatch(v => v > 10 && v < 100)
await until(ref).changed()
await until(ref).changedTimes(10)
await until(ref).toBeTruthy()
await until(ref).toBeNull()
await until(ref).not.toBeNull()
await until(ref).not.toBeTruthy()
```
## Type Declarations
```ts
export interface UntilToMatchOptions {
/**
* Milliseconds timeout for promise to resolve/reject if the when condition does not meet.
* 0 for never timed out
*
* @default 0
*/
timeout?: number
/**
* Reject the promise when timeout
*
* @default false
*/
throwOnTimeout?: boolean
/**
* `flush` option for internal watch
*
* @default 'sync'
*/
flush?: WatchOptionFlush
/**
* `deep` option for internal watch
*
* @default 'false'
*/
deep?: WatchOptions["deep"]
}
export interface UntilBaseInstance<T, Not extends boolean = false> {
toMatch: (<U extends T = T>(
condition: (v: T) => v is U,
options?: UntilToMatchOptions,
) => Not extends true ? Promise<Exclude<T, U>> : Promise<U>) &
((
condition: (v: T) => boolean,
options?: UntilToMatchOptions,
) => Promise<T>)
changed: (options?: UntilToMatchOptions) => Promise<T>
changedTimes: (n?: number, options?: UntilToMatchOptions) => Promise<T>
}
type Falsy = false | void | null | undefined | 0 | 0n | ""
export interface UntilValueInstance<T, Not extends boolean = false>
extends UntilBaseInstance<T, Not> {
readonly not: UntilValueInstance<T, Not extends true ? false : true>
toBe: <P = T>(
value: MaybeRefOrGetter<P>,
options?: UntilToMatchOptions,
) => Not extends true ? Promise<T> : Promise<P>
toBeTruthy: (
options?: UntilToMatchOptions,
) => Not extends true ? Promise<T & Falsy> : Promise<Exclude<T, Falsy>>
toBeNull: (
options?: UntilToMatchOptions,
) => Not extends true ? Promise<Exclude<T, null>> : Promise<null>
toBeUndefined: (
options?: UntilToMatchOptions,
) => Not extends true ? Promise<Exclude<T, undefined>> : Promise<undefined>
toBeNaN: (options?: UntilToMatchOptions) => Promise<T>
}
export interface UntilArrayInstance<T> extends UntilBaseInstance<T> {
readonly not: UntilArrayInstance<T>
toContains: (
value: MaybeRefOrGetter<ElementOf<ShallowUnwrapRef<T>>>,
options?: UntilToMatchOptions,
) => Promise<T>
}
/**
* Promised one-time watch for changes
*
* @see https://vueuse.org/until
* @example
* ```
* const { count } = useCounter()
*
* await until(count).toMatch(v => v > 7)
*
* alert('Counter is now larger than 7!')
* ```
*/
export declare function until<T extends unknown[]>(
r: WatchSource<T> | MaybeRefOrGetter<T>,
): UntilArrayInstance<T>
export declare function until<T>(
r: WatchSource<T> | MaybeRefOrGetter<T>,
): UntilValueInstance<T>
```

View File

@@ -0,0 +1,31 @@
---
category: '@Math'
---
# useAbs
Reactive `Math.abs`.
## Usage
```ts
import { useAbs } from '@vueuse/math'
const value = ref(-23)
const absValue = useAbs(value) // Ref<23>
```
## Type Declarations
```ts
/**
* Reactive `Math.abs`.
*
* @see https://vueuse.org/useAbs
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useAbs(
value: MaybeRefOrGetter<number>,
): ComputedRef<number>
```

View File

@@ -0,0 +1,65 @@
---
category: Elements
---
# useActiveElement
Reactive `document.activeElement`
## Usage
```vue
<script setup lang="ts">
import { useActiveElement } from '@vueuse/core'
import { watch } from 'vue'
const activeElement = useActiveElement()
watch(activeElement, (el) => {
console.log('focus changed to', el)
})
</script>
```
## Component Usage
```vue
<template>
<UseActiveElement v-slot="{ element }">
Active element is {{ element?.dataset.id }}
</UseActiveElement>
</template>
```
## Type Declarations
```ts
export interface UseActiveElementOptions
extends ConfigurableWindow,
ConfigurableDocumentOrShadowRoot {
/**
* Search active element deeply inside shadow dom
*
* @default true
*/
deep?: boolean
/**
* Track active element when it's removed from the DOM
* Using a MutationObserver under the hood
* @default false
*/
triggerOnRemoval?: boolean
}
/**
* Reactive `document.activeElement`
*
* @see https://vueuse.org/useActiveElement
* @param options
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useActiveElement<T extends HTMLElement>(
options?: UseActiveElementOptions,
): ShallowRef<T | null | undefined, T | null | undefined>
export type UseActiveElementReturn = ReturnType<typeof useActiveElement>
```

View File

@@ -0,0 +1,140 @@
---
category: Animation
---
# useAnimate
Reactive [Web Animations API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API).
## Usage
### Basic Usage
The `useAnimate` function will return the animate and its control function.
```vue
<script setup lang="ts">
import { useAnimate } from '@vueuse/core'
import { useTemplateRef } from 'vue'
const el = useTemplateRef('el')
const {
isSupported,
animate,
// actions
play,
pause,
reverse,
finish,
cancel,
// states
pending,
playState,
replaceState,
startTime,
currentTime,
timeline,
playbackRate,
} = useAnimate(el, { transform: 'rotate(360deg)' }, 1000)
</script>
<template>
<span ref="el" style="display:inline-block">useAnimate</span>
</template>
```
### Custom Keyframes
Either an array of keyframe objects, or a keyframe object, or a `ref`. See [Keyframe Formats](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Keyframe_Formats) for more details.
```ts
import { useAnimate } from '@vueuse/core'
import { useTemplateRef } from 'vue'
const el = useTemplateRef('el')
// ---cut---
const keyframes = { transform: 'rotate(360deg)' }
// Or
const keyframes = [
{ transform: 'rotate(0deg)' },
{ transform: 'rotate(360deg)' },
]
// Or
const keyframes = ref([
{ clipPath: 'circle(20% at 0% 30%)' },
{ clipPath: 'circle(20% at 50% 80%)' },
{ clipPath: 'circle(20% at 100% 30%)' },
])
useAnimate(el, keyframes, 1000)
```
## Type Declarations
```ts
export interface UseAnimateOptions
extends KeyframeAnimationOptions,
ConfigurableWindow {
/**
* Will automatically run play when `useAnimate` is used
*
* @default true
*/
immediate?: boolean
/**
* Whether to commits the end styling state of an animation to the element being animated
* In general, you should use `fill` option with this.
*
* @default false
*/
commitStyles?: boolean
/**
* Whether to persists the animation
*
* @default false
*/
persist?: boolean
/**
* Executed after animation initialization
*/
onReady?: (animate: Animation) => void
/**
* Callback when error is caught.
*/
onError?: (e: unknown) => void
}
export type UseAnimateKeyframes = MaybeRef<
Keyframe[] | PropertyIndexedKeyframes | null
>
export interface UseAnimateReturn {
isSupported: ComputedRef<boolean>
animate: ShallowRef<Animation | undefined>
play: () => void
pause: () => void
reverse: () => void
finish: () => void
cancel: () => void
pending: ComputedRef<boolean>
playState: ComputedRef<AnimationPlayState>
replaceState: ComputedRef<AnimationReplaceState>
startTime: WritableComputedRef<CSSNumberish | number | null>
currentTime: WritableComputedRef<CSSNumberish | null>
timeline: WritableComputedRef<AnimationTimeline | null>
playbackRate: WritableComputedRef<number>
}
/**
* Reactive Web Animations API
*
* @see https://vueuse.org/useAnimate
* @param target
* @param keyframes
* @param options
*/
export declare function useAnimate(
target: MaybeComputedElementRef,
keyframes: UseAnimateKeyframes,
options?: number | UseAnimateOptions,
): UseAnimateReturn
```

View File

@@ -0,0 +1,84 @@
---
category: Array
---
# useArrayDifference
Reactive get array difference of two arrays.
By default, it returns the difference of the first array from the second array, so call `A \ B`, [Relative Complement](<https://en.wikipedia.org/wiki/Complement_(set_theory)>) of B in A.
You can pass the `symmetric` option to get the [Symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference) of two arrays `A △ B`.
## Usage
### Use with reactive array
```ts
import { useArrayDifference } from '@vueuse/core'
const list1 = ref([0, 1, 2, 3, 4, 5])
const list2 = ref([4, 5, 6])
const result = useArrayDifference(list1, list2)
// result.value: [0, 1, 2, 3]
list2.value = [0, 1, 2]
// result.value: [3, 4, 5]
```
### Use with reactive array and use function comparison
```ts
import { useArrayDifference } from '@vueuse/core'
const list1 = ref([{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }])
const list2 = ref([{ id: 4 }, { id: 5 }, { id: 6 }])
const result = useArrayDifference(list1, list2, (value, othVal) => value.id === othVal.id)
// result.value: [{ id: 1 }, { id: 2 }, { id: 3 }]
```
### Symmetric Difference
This composable also supports [Symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference) by passing the `symmetric` option.
```ts {10}
import { useArrayDifference } from '@vueuse/core'
const list1 = ref([{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }])
const list2 = ref([{ id: 4 }, { id: 5 }, { id: 6 }])
const result = useArrayDifference(
list1,
list2,
(value, othVal) => value.id === othVal.id,
{ symmetric: true }
)
// result.value: [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 6 }]
```
## Type Declarations
```ts
export interface UseArrayDifferenceOptions {
/**
* Returns asymmetric difference
*
* @see https://en.wikipedia.org/wiki/Symmetric_difference
* @default false
*/
symmetric?: boolean
}
export type UseArrayDifferenceReturn<T = any> = ComputedRef<T[]>
export declare function useArrayDifference<T>(
list: MaybeRefOrGetter<T[]>,
values: MaybeRefOrGetter<T[]>,
key?: keyof T,
options?: UseArrayDifferenceOptions,
): UseArrayDifferenceReturn<T>
export declare function useArrayDifference<T>(
list: MaybeRefOrGetter<T[]>,
values: MaybeRefOrGetter<T[]>,
compareFn?: (value: T, othVal: T) => boolean,
options?: UseArrayDifferenceOptions,
): UseArrayDifferenceReturn<T>
```

View File

@@ -0,0 +1,59 @@
---
category: Array
---
# useArrayEvery
Reactive `Array.every`
## Usage
### Use with array of multiple refs
```ts
import { useArrayEvery } from '@vueuse/core'
const item1 = ref(0)
const item2 = ref(2)
const item3 = ref(4)
const item4 = ref(6)
const item5 = ref(8)
const list = [item1, item2, item3, item4, item5]
const result = useArrayEvery(list, i => i % 2 === 0)
// result.value: true
item1.value = 1
// result.value: false
```
### Use with reactive array
```ts
import { useArrayEvery } from '@vueuse/core'
const list = ref([0, 2, 4, 6, 8])
const result = useArrayEvery(list, i => i % 2 === 0)
// result.value: true
list.value.push(9)
// result.value: false
```
## Type Declarations
```ts
export type UseArrayEveryReturn = ComputedRef<boolean>
/**
* Reactive `Array.every`
*
* @see https://vueuse.org/useArrayEvery
* @param list - the array was called upon.
* @param fn - a function to test each element.
*
* @returns **true** if the `fn` function returns a **truthy** value for every element from the array. Otherwise, **false**.
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useArrayEvery<T>(
list: MaybeRefOrGetter<MaybeRefOrGetter<T>[]>,
fn: (element: T, index: number, array: MaybeRefOrGetter<T>[]) => unknown,
): UseArrayEveryReturn
```

View File

@@ -0,0 +1,63 @@
---
category: Array
---
# useArrayFilter
Reactive `Array.filter`
## Usage
### Use with array of multiple refs
```ts
import { useArrayFilter } from '@vueuse/core'
const item1 = ref(0)
const item2 = ref(2)
const item3 = ref(4)
const item4 = ref(6)
const item5 = ref(8)
const list = [item1, item2, item3, item4, item5]
const result = useArrayFilter(list, i => i % 2 === 0)
// result.value: [0, 2, 4, 6, 8]
item2.value = 1
// result.value: [0, 4, 6, 8]
```
### Use with reactive array
```ts
import { useArrayFilter } from '@vueuse/core'
const list = ref([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
const result = useArrayFilter(list, i => i % 2 === 0)
// result.value: [0, 2, 4, 6, 8]
list.value.shift()
// result.value: [2, 4, 6, 8]
```
## Type Declarations
```ts
export type UseArrayFilterReturn<T = any> = ComputedRef<T[]>
/**
* Reactive `Array.filter`
*
* @see https://vueuse.org/useArrayFilter
* @param list - the array was called upon.
* @param fn - a function that is called for every element of the given `list`. Each time `fn` executes, the returned value is added to the new array.
*
* @returns a shallow copy of a portion of the given array, filtered down to just the elements from the given array that pass the test implemented by the provided function. If no elements pass the test, an empty array will be returned.
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useArrayFilter<T, S extends T>(
list: MaybeRefOrGetter<MaybeRefOrGetter<T>[]>,
fn: (element: T, index: number, array: T[]) => element is S,
): UseArrayFilterReturn<S>
export declare function useArrayFilter<T>(
list: MaybeRefOrGetter<MaybeRefOrGetter<T>[]>,
fn: (element: T, index: number, array: T[]) => unknown,
): UseArrayFilterReturn<T>
```

View File

@@ -0,0 +1,50 @@
---
category: Array
---
# useArrayFind
Reactive `Array.find`.
## Usage
```ts
import { useArrayFind } from '@vueuse/core'
const list = [ref(1), ref(-1), ref(2)]
const positive = useArrayFind(list, val => val > 0)
// positive.value: 1
```
### Use with reactive array
```ts
import { useArrayFind } from '@vueuse/core'
const list = reactive([-1, -2])
const positive = useArrayFind(list, val => val > 0)
// positive.value: undefined
list.push(1)
// positive.value: 1
```
## Type Declarations
```ts
export type UseArrayFindReturn<T = any> = ComputedRef<T | undefined>
/**
* Reactive `Array.find`
*
* @see https://vueuse.org/useArrayFind
* @param list - the array was called upon.
* @param fn - a function to test each element.
*
* @returns the first element in the array that satisfies the provided testing function. Otherwise, undefined is returned.
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useArrayFind<T>(
list: MaybeRefOrGetter<MaybeRefOrGetter<T>[]>,
fn: (element: T, index: number, array: MaybeRefOrGetter<T>[]) => boolean,
): UseArrayFindReturn<T>
```

View File

@@ -0,0 +1,59 @@
---
category: Array
---
# useArrayFindIndex
Reactive `Array.findIndex`
## Usage
### Use with array of multiple refs
```ts
import { useArrayFindIndex } from '@vueuse/core'
const item1 = ref(0)
const item2 = ref(2)
const item3 = ref(4)
const item4 = ref(6)
const item5 = ref(8)
const list = [item1, item2, item3, item4, item5]
const result = useArrayFindIndex(list, i => i % 2 === 0)
// result.value: 0
item1.value = 1
// result.value: 1
```
### Use with reactive array
```ts
import { useArrayFindIndex } from '@vueuse/core'
const list = ref([0, 2, 4, 6, 8])
const result = useArrayFindIndex(list, i => i % 2 === 0)
// result.value: 0
list.value.unshift(-1)
// result.value: 1
```
## Type Declarations
```ts
export type UseArrayFindIndexReturn = ComputedRef<number>
/**
* Reactive `Array.findIndex`
*
* @see https://vueuse.org/useArrayFindIndex
* @param list - the array was called upon.
* @param fn - a function to test each element.
*
* @returns the index of the first element in the array that passes the test. Otherwise, "-1".
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useArrayFindIndex<T>(
list: MaybeRefOrGetter<MaybeRefOrGetter<T>[]>,
fn: (element: T, index: number, array: MaybeRefOrGetter<T>[]) => unknown,
): UseArrayFindIndexReturn
```

View File

@@ -0,0 +1,52 @@
---
category: Array
---
# useArrayFindLast
Reactive `Array.findLast`.
## Usage
```ts
import { useArrayFindLast } from '@vueuse/core'
const list = [ref(1), ref(-1), ref(2)]
const positive = useArrayFindLast(list, val => val > 0)
// positive.value: 2
```
### Use with reactive array
```ts
import { useArrayFindLast } from '@vueuse/core'
const list = reactive([-1, -2])
const positive = useArrayFindLast(list, val => val > 0)
// positive.value: undefined
list.push(10)
// positive.value: 10
list.push(5)
// positive.value: 5
```
## Type Declarations
```ts
export type UseArrayFindLastReturn<T = any> = ComputedRef<T | undefined>
/**
* Reactive `Array.findLast`
*
* @see https://vueuse.org/useArrayFindLast
* @param list - the array was called upon.
* @param fn - a function to test each element.
*
* @returns the last element in the array that satisfies the provided testing function. Otherwise, undefined is returned.
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useArrayFindLast<T>(
list: MaybeRefOrGetter<MaybeRefOrGetter<T>[]>,
fn: (element: T, index: number, array: MaybeRefOrGetter<T>[]) => boolean,
): UseArrayFindLastReturn<T>
```

View File

@@ -0,0 +1,63 @@
---
category: Array
---
# useArrayIncludes
Reactive `Array.includes`
## Usage
### Use with reactive array
```ts
import { useArrayIncludes } from '@vueuse/core'
const list = ref([0, 2, 4, 6, 8])
const result = useArrayIncludes(list, 10)
// result.value: false
list.value.push(10)
// result.value: true
list.value.pop()
// result.value: false
```
## Type Declarations
```ts
export type UseArrayIncludesComparatorFn<T, V> = (
element: T,
value: V,
index: number,
array: MaybeRefOrGetter<T>[],
) => boolean
export interface UseArrayIncludesOptions<T, V> {
fromIndex?: number
comparator?: UseArrayIncludesComparatorFn<T, V> | keyof T
}
export type UseArrayIncludesReturn = ComputedRef<boolean>
/**
* Reactive `Array.includes`
*
* @see https://vueuse.org/useArrayIncludes
*
* @returns true if the `value` is found in the array. Otherwise, false.
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useArrayIncludes<T, V = any>(
list: MaybeRefOrGetter<MaybeRefOrGetter<T>[]>,
value: MaybeRefOrGetter<V>,
comparator?: UseArrayIncludesComparatorFn<T, V>,
): UseArrayIncludesReturn
export declare function useArrayIncludes<T, V = any>(
list: MaybeRefOrGetter<MaybeRefOrGetter<T>[]>,
value: MaybeRefOrGetter<V>,
comparator?: keyof T,
): UseArrayIncludesReturn
export declare function useArrayIncludes<T, V = any>(
list: MaybeRefOrGetter<MaybeRefOrGetter<T>[]>,
value: MaybeRefOrGetter<V>,
options?: UseArrayIncludesOptions<T, V>,
): UseArrayIncludesReturn
```

View File

@@ -0,0 +1,74 @@
---
category: Array
---
# useArrayJoin
Reactive `Array.join`
## Usage
### Use with array of multiple refs
```ts
import { useArrayJoin } from '@vueuse/core'
const item1 = ref('foo')
const item2 = ref(0)
const item3 = ref({ prop: 'val' })
const list = [item1, item2, item3]
const result = useArrayJoin(list)
// result.value: foo,0,[object Object]
item1.value = 'bar'
// result.value: bar,0,[object Object]
```
### Use with reactive array
```ts
import { useArrayJoin } from '@vueuse/core'
const list = ref(['string', 0, { prop: 'val' }, false, [1], [[2]], null, undefined, []])
const result = useArrayJoin(list)
// result.value: string,0,[object Object],false,1,2,,,
list.value.push(true)
// result.value: string,0,[object Object],false,1,2,,,,true
list.value = [null, 'string', undefined]
// result.value: ,string,
```
### Use with reactive separator
```ts
import { useArrayJoin } from '@vueuse/core'
const list = ref(['string', 0, { prop: 'val' }])
const separator = ref()
const result = useArrayJoin(list, separator)
// result.value: string,0,[object Object]
separator.value = ''
// result.value: string0[object Object]
separator.value = '--'
// result.value: string--0--[object Object]
```
## Type Declarations
```ts
export type UseArrayJoinReturn = ComputedRef<string>
/**
* Reactive `Array.join`
*
* @see https://vueuse.org/useArrayJoin
* @param list - the array was called upon.
* @param separator - a string to separate each pair of adjacent elements of the array. If omitted, the array elements are separated with a comma (",").
*
* @returns a string with all array elements joined. If arr.length is 0, the empty string is returned.
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useArrayJoin(
list: MaybeRefOrGetter<MaybeRefOrGetter<any>[]>,
separator?: MaybeRefOrGetter<string>,
): UseArrayJoinReturn
```

View File

@@ -0,0 +1,59 @@
---
category: Array
---
# useArrayMap
Reactive `Array.map`
## Usage
### Use with array of multiple refs
```ts
import { useArrayMap } from '@vueuse/core'
const item1 = ref(0)
const item2 = ref(2)
const item3 = ref(4)
const item4 = ref(6)
const item5 = ref(8)
const list = [item1, item2, item3, item4, item5]
const result = useArrayMap(list, i => i * 2)
// result.value: [0, 4, 8, 12, 16]
item1.value = 1
// result.value: [2, 4, 8, 12, 16]
```
### Use with reactive array
```ts
import { useArrayMap } from '@vueuse/core'
const list = ref([0, 1, 2, 3, 4])
const result = useArrayMap(list, i => i * 2)
// result.value: [0, 2, 4, 6, 8]
list.value.pop()
// result.value: [0, 2, 4, 6]
```
## Type Declarations
```ts
export type UseArrayMapReturn<T = any> = ComputedRef<T[]>
/**
* Reactive `Array.map`
*
* @see https://vueuse.org/useArrayMap
* @param list - the array was called upon.
* @param fn - a function that is called for every element of the given `list`. Each time `fn` executes, the returned value is added to the new array.
*
* @returns a new array with each element being the result of the callback function.
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useArrayMap<T, U = T>(
list: MaybeRefOrGetter<MaybeRefOrGetter<T>[]>,
fn: (element: T, index: number, array: T[]) => U,
): UseArrayMapReturn<U>
```

View File

@@ -0,0 +1,81 @@
---
category: Array
---
# useArrayReduce
Reactive `Array.reduce`.
## Usage
```ts
import { useArrayReduce } from '@vueuse/core'
const sum = useArrayReduce([ref(1), ref(2), ref(3)], (sum, val) => sum + val)
// sum.value: 6
```
### Use with reactive array
```ts
import { useArrayReduce } from '@vueuse/core'
const list = reactive([1, 2])
const sum = useArrayReduce(list, (sum, val) => sum + val)
list.push(3)
// sum.value: 6
```
### Use with initialValue
```ts
import { useArrayReduce } from '@vueuse/core'
const list = reactive([{ num: 1 }, { num: 2 }])
const sum = useArrayReduce(list, (sum, val) => sum + val.num, 0)
// sum.value: 3
```
## Type Declarations
```ts
export type UseArrayReducer<PV, CV, R> = (
previousValue: PV,
currentValue: CV,
currentIndex: number,
) => R
export type UseArrayReduceReturn<T = any> = ComputedRef<T>
/**
* Reactive `Array.reduce`
*
* @see https://vueuse.org/useArrayReduce
* @param list - the array was called upon.
* @param reducer - a "reducer" function.
*
* @returns the value that results from running the "reducer" callback function to completion over the entire array.
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useArrayReduce<T>(
list: MaybeRefOrGetter<MaybeRefOrGetter<T>[]>,
reducer: UseArrayReducer<T, T, T>,
): UseArrayReduceReturn<T>
/**
* Reactive `Array.reduce`
*
* @see https://vueuse.org/useArrayReduce
* @param list - the array was called upon.
* @param reducer - a "reducer" function.
* @param initialValue - a value to be initialized the first time when the callback is called.
*
* @returns the value that results from running the "reducer" callback function to completion over the entire array.
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useArrayReduce<T, U>(
list: MaybeRefOrGetter<MaybeRefOrGetter<T>[]>,
reducer: UseArrayReducer<U, T, U>,
initialValue: MaybeRefOrGetter<U>,
): UseArrayReduceReturn<U>
```

View File

@@ -0,0 +1,59 @@
---
category: Array
---
# useArraySome
Reactive `Array.some`
## Usage
### Use with array of multiple refs
```ts
import { useArraySome } from '@vueuse/core'
const item1 = ref(0)
const item2 = ref(2)
const item3 = ref(4)
const item4 = ref(6)
const item5 = ref(8)
const list = [item1, item2, item3, item4, item5]
const result = useArraySome(list, i => i > 10)
// result.value: false
item1.value = 11
// result.value: true
```
### Use with reactive array
```ts
import { useArraySome } from '@vueuse/core'
const list = ref([0, 2, 4, 6, 8])
const result = useArraySome(list, i => i > 10)
// result.value: false
list.value.push(11)
// result.value: true
```
## Type Declarations
```ts
export type UseArraySomeReturn = ComputedRef<boolean>
/**
* Reactive `Array.some`
*
* @see https://vueuse.org/useArraySome
* @param list - the array was called upon.
* @param fn - a function to test each element.
*
* @returns **true** if the `fn` function returns a **truthy** value for any element from the array. Otherwise, **false**.
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useArraySome<T>(
list: MaybeRefOrGetter<MaybeRefOrGetter<T>[]>,
fn: (element: T, index: number, array: MaybeRefOrGetter<T>[]) => unknown,
): UseArraySomeReturn
```

View File

@@ -0,0 +1,76 @@
---
category: Array
---
# useArrayUnique
reactive unique array
## Usage
### Use with array of multiple refs
```ts
import { useArrayUnique } from '@vueuse/core'
const item1 = ref(0)
const item2 = ref(1)
const item3 = ref(1)
const item4 = ref(2)
const item5 = ref(3)
const list = [item1, item2, item3, item4, item5]
const result = useArrayUnique(list)
// result.value: [0, 1, 2, 3]
item5.value = 1
// result.value: [0, 1, 2]
```
### Use with reactive array
```ts
import { useArrayUnique } from '@vueuse/core'
const list = reactive([1, 2, 2, 3])
const result = useArrayUnique(list)
// result.value: [1, 2, 3]
list.push(1)
// result.value: [1, 2, 3]
```
### Use with custom function
```ts
import { useArrayUnique } from '@vueuse/core'
const list = reactive([
{ id: 1, name: 'foo' },
{ id: 2, name: 'bar' },
{ id: 1, name: 'baz' },
])
const result = useArrayUnique(list, (a, b) => a.id === b.id)
// result.value: [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }]
list.push({ id: 1, name: 'qux' })
// result.value: [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }]
```
## Type Declarations
```ts
export type UseArrayUniqueReturn<T = any> = ComputedRef<T[]>
/**
* reactive unique array
* @see https://vueuse.org/useArrayUnique
* @param list - the array was called upon.
* @param compareFn
* @returns A computed ref that returns a unique array of items.
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useArrayUnique<T>(
list: MaybeRefOrGetter<MaybeRefOrGetter<T>[]>,
compareFn?: (a: T, b: T, array: T[]) => boolean,
): UseArrayUniqueReturn<T>
```

View File

@@ -0,0 +1,87 @@
---
category: Utilities
---
# useAsyncQueue
Executes each asynchronous task sequentially and passes the current task result to the next task
## Usage
```ts
import { useAsyncQueue } from '@vueuse/core'
function p1() {
return new Promise((resolve) => {
setTimeout(() => {
resolve(1000)
}, 10)
})
}
function p2(result: number) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(1000 + result)
}, 20)
})
}
const { activeIndex, result } = useAsyncQueue([p1, p2])
console.log(activeIndex.value) // current pending task index
console.log(result) // the tasks result
```
## Type Declarations
```ts
export type UseAsyncQueueTask<T> = (...args: any[]) => T | Promise<T>
type MapQueueTask<T extends any[]> = {
[K in keyof T]: UseAsyncQueueTask<T[K]>
}
export interface UseAsyncQueueResult<T> {
state: "aborted" | "fulfilled" | "pending" | "rejected"
data: T | null
}
export interface UseAsyncQueueReturn<T> {
activeIndex: ShallowRef<number>
result: T
}
export interface UseAsyncQueueOptions {
/**
* Interrupt tasks when current task fails.
*
* @default true
*/
interrupt?: boolean
/**
* Trigger it when the tasks fails.
*
*/
onError?: () => void
/**
* Trigger it when the tasks ends.
*
*/
onFinished?: () => void
/**
* A AbortSignal that can be used to abort the task.
*/
signal?: AbortSignal
}
/**
* Asynchronous queue task controller.
*
* @see https://vueuse.org/useAsyncQueue
* @param tasks
* @param options
*/
export declare function useAsyncQueue<T extends any[], S = MapQueueTask<T>>(
tasks: S & Array<UseAsyncQueueTask<any>>,
options?: UseAsyncQueueOptions,
): UseAsyncQueueReturn<{
[P in keyof T]: UseAsyncQueueResult<T[P]>
}>
```

View File

@@ -0,0 +1,140 @@
---
category: State
---
# useAsyncState
Reactive async state. Will not block your setup function and will trigger changes once the promise is ready. The state is a `shallowRef` by default.
## Usage
```ts
import { useAsyncState } from '@vueuse/core'
import axios from 'axios'
const { state, isReady, isLoading } = useAsyncState(
axios
.get('https://jsonplaceholder.typicode.com/todos/1')
.then(t => t.data),
{ id: null },
)
```
### Manually trigger the async function
You can also trigger it manually. This is useful when you want to control when the async function is executed.
```vue
<script setup lang="ts">
import { useAsyncState } from '@vueuse/core'
const { state, execute, executeImmediate } = useAsyncState(action, '', { immediate: false })
async function action(event) {
await new Promise(resolve => setTimeout(resolve, 500))
return `${event.target.textContent} clicked!`
}
</script>
<template>
<p>State: {{ state }}</p>
<button class="button" @click="executeImmediate">
Execute now
</button>
<button class="ml-2 button" @click="event => execute(500, event)">
Execute with delay
</button>
</template>
```
## Type Declarations
```ts
export interface UseAsyncStateReturnBase<
Data,
Params extends any[],
Shallow extends boolean,
> {
state: Shallow extends true ? Ref<Data> : Ref<UnwrapRef<Data>>
isReady: Ref<boolean>
isLoading: Ref<boolean>
error: Ref<unknown>
execute: (delay?: number, ...args: Params) => Promise<Data>
executeImmediate: (...args: Params) => Promise<Data>
}
export type UseAsyncStateReturn<
Data,
Params extends any[],
Shallow extends boolean,
> = UseAsyncStateReturnBase<Data, Params, Shallow> &
PromiseLike<UseAsyncStateReturnBase<Data, Params, Shallow>>
export interface UseAsyncStateOptions<Shallow extends boolean, D = any> {
/**
* Delay for the first execution of the promise when "immediate" is true. In milliseconds.
*
* @default 0
*/
delay?: number
/**
* Execute the promise right after the function is invoked.
* Will apply the delay if any.
*
* When set to false, you will need to execute it manually.
*
* @default true
*/
immediate?: boolean
/**
* Callback when error is caught.
*/
onError?: (e: unknown) => void
/**
* Callback when success is caught.
* @param {D} data
*/
onSuccess?: (data: D) => void
/**
* Sets the state to initialState before executing the promise.
*
* This can be useful when calling the execute function more than once (for
* example, to refresh data). When set to false, the current state remains
* unchanged until the promise resolves.
*
* @default true
*/
resetOnExecute?: boolean
/**
* Use shallowRef.
*
* @default true
*/
shallow?: Shallow
/**
*
* An error is thrown when executing the execute function
*
* @default false
*/
throwError?: boolean
}
/**
* Reactive async state. Will not block your setup function and will trigger changes once
* the promise is ready.
*
* @see https://vueuse.org/useAsyncState
* @param promise The promise / async function to be resolved
* @param initialState The initial state, used until the first evaluation finishes
* @param options
*/
export declare function useAsyncState<
Data,
Params extends any[] = any[],
Shallow extends boolean = true,
>(
promise: Promise<Data> | ((...args: Params) => Promise<Data>),
initialState: MaybeRef<Data>,
options?: UseAsyncStateOptions<Shallow, Data>,
): UseAsyncStateReturn<Data, Params, Shallow>
```

View File

@@ -0,0 +1,70 @@
---
category: '@Integrations'
---
# useAsyncValidator
Wrapper for [`async-validator`](https://github.com/yiminghe/async-validator).
## Install
```bash
npm i async-validator@^4
```
## Usage
```ts
import { useAsyncValidator } from '@vueuse/integrations/useAsyncValidator'
```
## Type Declarations
```ts
export type AsyncValidatorError = Error & {
errors: ValidateError[]
fields: Record<string, ValidateError[]>
}
export interface UseAsyncValidatorExecuteReturn {
pass: boolean
errors: AsyncValidatorError["errors"] | undefined
errorInfo: AsyncValidatorError | null
errorFields: AsyncValidatorError["fields"] | undefined
}
export interface UseAsyncValidatorReturn {
pass: ShallowRef<boolean>
isFinished: ShallowRef<boolean>
errors: ComputedRef<AsyncValidatorError["errors"] | undefined>
errorInfo: ShallowRef<AsyncValidatorError | null>
errorFields: ComputedRef<AsyncValidatorError["fields"] | undefined>
execute: () => Promise<UseAsyncValidatorExecuteReturn>
}
export interface UseAsyncValidatorOptions {
/**
* @see https://github.com/yiminghe/async-validator#options
*/
validateOption?: ValidateOption
/**
* The validation will be triggered right away for the first time.
* Only works when `manual` is not set to true.
*
* @default true
*/
immediate?: boolean
/**
* If set to true, the validation will not be triggered automatically.
*/
manual?: boolean
}
/**
* Wrapper for async-validator.
*
* @see https://vueuse.org/useAsyncValidator
* @see https://github.com/yiminghe/async-validator
*/
export declare function useAsyncValidator(
value: MaybeRefOrGetter<Record<string, any>>,
rules: MaybeRefOrGetter<Rules>,
options?: UseAsyncValidatorOptions,
): UseAsyncValidatorReturn & PromiseLike<UseAsyncValidatorReturn>
```

View File

@@ -0,0 +1,114 @@
---
category: '@Firebase'
---
# useAuth
Reactive [Firebase Auth](https://firebase.google.com/docs/auth) binding. It provides a reactive `user` and `isAuthenticated` so you
can easily react to changes in the users' authentication status.
## Usage
```vue
<script setup lang="ts">
import { useAuth } from '@vueuse/firebase/useAuth'
import { initializeApp } from 'firebase/app'
import { getAuth, GoogleAuthProvider, signInWithPopup } from 'firebase/auth'
const app = initializeApp({ /* config */ })
const auth = getAuth(app)
const { isAuthenticated, user } = useAuth(auth)
const signIn = () => signInWithPopup(auth, new GoogleAuthProvider())
</script>
<template>
<pre v-if="isAuthenticated">{{ user }}</pre>
<div v-else>
<button @click="signIn">
Sign In with Google
</button>
</div>
</template>
```
## Type Declarations
```ts
export interface UseFirebaseAuthOptions {
isAuthenticated: ComputedRef<boolean>
user: Ref<User | null>
}
/**
* Reactive Firebase Auth binding
*
* @see https://vueuse.org/useAuth
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useAuth(auth: Auth): {
isAuthenticated: ComputedRef<boolean>
user: Ref<
{
readonly emailVerified: boolean
readonly isAnonymous: boolean
readonly metadata: {
readonly creationTime?: string | undefined
readonly lastSignInTime?: string | undefined
}
readonly providerData: {
readonly displayName: string | null
readonly email: string | null
readonly phoneNumber: string | null
readonly photoURL: string | null
readonly providerId: string
readonly uid: string
}[]
readonly refreshToken: string
readonly tenantId: string | null
delete: () => Promise<void>
getIdToken: (forceRefresh?: boolean) => Promise<string>
getIdTokenResult: (forceRefresh?: boolean) => Promise<IdTokenResult>
reload: () => Promise<void>
toJSON: () => object
readonly displayName: string | null
readonly email: string | null
readonly phoneNumber: string | null
readonly photoURL: string | null
readonly providerId: string
readonly uid: string
} | null,
| User
| {
readonly emailVerified: boolean
readonly isAnonymous: boolean
readonly metadata: {
readonly creationTime?: string | undefined
readonly lastSignInTime?: string | undefined
}
readonly providerData: {
readonly displayName: string | null
readonly email: string | null
readonly phoneNumber: string | null
readonly photoURL: string | null
readonly providerId: string
readonly uid: string
}[]
readonly refreshToken: string
readonly tenantId: string | null
delete: () => Promise<void>
getIdToken: (forceRefresh?: boolean) => Promise<string>
getIdTokenResult: (forceRefresh?: boolean) => Promise<IdTokenResult>
reload: () => Promise<void>
toJSON: () => object
readonly displayName: string | null
readonly email: string | null
readonly phoneNumber: string | null
readonly photoURL: string | null
readonly providerId: string
readonly uid: string
}
| null
>
}
```

View File

@@ -0,0 +1,36 @@
---
category: '@Math'
---
# useAverage
Get the average of an array reactively.
## Usage
```ts
import { useAverage } from '@vueuse/math'
const list = ref([1, 2, 3])
const averageValue = useAverage(list) // Ref<2>
```
```ts
import { useAverage } from '@vueuse/math'
const a = ref(1)
const b = ref(3)
const averageValue = useAverage(a, b) // Ref<2>
```
## Type Declarations
```ts
export declare function useAverage(
array: MaybeRefOrGetter<MaybeRefOrGetter<number>[]>,
): ComputedRef<number>
export declare function useAverage(
...args: MaybeRefOrGetter<number>[]
): ComputedRef<number>
```

View File

@@ -0,0 +1,292 @@
---
category: '@Integrations'
---
# useAxios
Wrapper for [`axios`](https://github.com/axios/axios).
## Install
```bash
npm i axios@^1
```
## Usage
```ts
import { useAxios } from '@vueuse/integrations/useAxios'
const { data, isFinished } = useAxios('/api/posts')
```
or use an instance of axios
```ts
import { useAxios } from '@vueuse/integrations/useAxios'
import axios from 'axios'
const instance = axios.create({
baseURL: '/api',
})
const { data, isFinished } = useAxios('/posts', instance)
```
use an instance of axios with config options
```ts
import { useAxios } from '@vueuse/integrations/useAxios'
import axios from 'axios'
const instance = axios.create({
baseURL: '/api',
})
const { data, isFinished } = useAxios('/posts', { method: 'POST' }, instance)
```
When you don't pass the `url`. The default value is `{immediate: false}`
```ts
import { useAxios } from '@vueuse/integrations/useAxios'
const { execute } = useAxios()
execute(url)
```
The `execute` function `url` here is optional, and `url2` will replace the `url1`.
```ts
import { useAxios } from '@vueuse/integrations/useAxios'
const { execute } = useAxios(url1, {}, { immediate: false })
execute(url2)
```
The `execute` function can accept `config` only.
```ts
import { useAxios } from '@vueuse/integrations/useAxios'
const { execute } = useAxios(url1, { method: 'GET' }, { immediate: false })
execute({ params: { key: 1 } })
execute({ params: { key: 2 } })
```
The `execute` function resolves with a result of network request.
```ts
import { useAxios } from '@vueuse/integrations/useAxios'
const { execute } = useAxios()
const result = await execute(url)
```
use an instance of axios with `immediate` options
```ts
import { useAxios } from '@vueuse/integrations/useAxios'
import axios from 'axios'
const instance = axios.create({
baseURL: '/api',
})
const { data, isFinished } = useAxios('/posts', { method: 'POST' }, instance, {
immediate: false,
})
```
## Type Declarations
```ts
export interface UseAxiosReturn<
T,
R = AxiosResponse<T>,
_D = any,
O extends UseAxiosOptions = UseAxiosOptions<T>,
> {
/**
* Axios Response
*/
response: ShallowRef<R | undefined>
/**
* Axios response data
*/
data: O extends UseAxiosOptionsWithInitialData<T>
? Ref<T>
: Ref<T | undefined>
/**
* Indicates if the request has finished
*/
isFinished: Ref<boolean>
/**
* Indicates if the request is currently loading
*/
isLoading: Ref<boolean>
/**
* Indicates if the request was canceled
*/
isAborted: Ref<boolean>
/**
* Any errors that may have occurred
*/
error: ShallowRef<unknown | undefined>
/**
* Aborts the current request
*/
abort: (message?: string | undefined) => void
/**
* Alias to `abort`
*/
cancel: (message?: string | undefined) => void
/**
* Alias to `isAborted`
*/
isCanceled: Ref<boolean>
}
export interface StrictUseAxiosReturn<
T,
R,
D,
O extends UseAxiosOptions = UseAxiosOptions<T>,
> extends UseAxiosReturn<T, R, D, O> {
/**
* Manually call the axios request
*/
execute: (
url?: string | AxiosRequestConfig<D>,
config?: AxiosRequestConfig<D>,
) => Promise<StrictUseAxiosReturn<T, R, D, O>>
}
export interface EasyUseAxiosReturn<T, R, D> extends UseAxiosReturn<T, R, D> {
/**
* Manually call the axios request
*/
execute: (
url: string,
config?: AxiosRequestConfig<D>,
) => Promise<EasyUseAxiosReturn<T, R, D>>
}
export interface UseAxiosOptionsBase<T = any> {
/**
* Will automatically run axios request when `useAxios` is used
*
*/
immediate?: boolean
/**
* Use shallowRef.
*
* @default true
*/
shallow?: boolean
/**
* Abort previous request when a new request is made.
*
* @default true
*/
abortPrevious?: boolean
/**
* Callback when error is caught.
*/
onError?: (e: unknown) => void
/**
* Callback when success is caught.
*/
onSuccess?: (data: T) => void
/**
* Sets the state to initialState before executing the promise.
*/
resetOnExecute?: boolean
/**
* Callback when request is finished.
*/
onFinish?: () => void
}
export interface UseAxiosOptionsWithInitialData<T>
extends UseAxiosOptionsBase<T> {
/**
* Initial data
*/
initialData: T
}
export type UseAxiosOptions<T = any> =
| UseAxiosOptionsBase<T>
| UseAxiosOptionsWithInitialData<T>
export declare function useAxios<
T = any,
R = AxiosResponse<T>,
D = any,
O extends
UseAxiosOptionsWithInitialData<T> = UseAxiosOptionsWithInitialData<T>,
>(
url: string,
config?: AxiosRequestConfig<D>,
options?: O,
): StrictUseAxiosReturn<T, R, D, O> & Promise<StrictUseAxiosReturn<T, R, D, O>>
export declare function useAxios<
T = any,
R = AxiosResponse<T>,
D = any,
O extends
UseAxiosOptionsWithInitialData<T> = UseAxiosOptionsWithInitialData<T>,
>(
url: string,
instance?: AxiosInstance,
options?: O,
): StrictUseAxiosReturn<T, R, D, O> & Promise<StrictUseAxiosReturn<T, R, D, O>>
export declare function useAxios<
T = any,
R = AxiosResponse<T>,
D = any,
O extends
UseAxiosOptionsWithInitialData<T> = UseAxiosOptionsWithInitialData<T>,
>(
url: string,
config: AxiosRequestConfig<D>,
instance: AxiosInstance,
options?: O,
): StrictUseAxiosReturn<T, R, D, O> & Promise<StrictUseAxiosReturn<T, R, D, O>>
export declare function useAxios<
T = any,
R = AxiosResponse<T>,
D = any,
O extends UseAxiosOptionsBase<T> = UseAxiosOptionsBase<T>,
>(
url: string,
config?: AxiosRequestConfig<D>,
options?: O,
): StrictUseAxiosReturn<T, R, D, O> & Promise<StrictUseAxiosReturn<T, R, D, O>>
export declare function useAxios<
T = any,
R = AxiosResponse<T>,
D = any,
O extends UseAxiosOptionsBase<T> = UseAxiosOptionsBase<T>,
>(
url: string,
instance?: AxiosInstance,
options?: O,
): StrictUseAxiosReturn<T, R, D, O> & Promise<StrictUseAxiosReturn<T, R, D, O>>
export declare function useAxios<
T = any,
R = AxiosResponse<T>,
D = any,
O extends UseAxiosOptionsBase<T> = UseAxiosOptionsBase<T>,
>(
url: string,
config: AxiosRequestConfig<D>,
instance: AxiosInstance,
options?: O,
): StrictUseAxiosReturn<T, R, D, O> & Promise<StrictUseAxiosReturn<T, R, D, O>>
export declare function useAxios<T = any, R = AxiosResponse<T>, D = any>(
config?: AxiosRequestConfig<D>,
): EasyUseAxiosReturn<T, R, D> & Promise<EasyUseAxiosReturn<T, R, D>>
export declare function useAxios<T = any, R = AxiosResponse<T>, D = any>(
instance?: AxiosInstance,
): EasyUseAxiosReturn<T, R, D> & Promise<EasyUseAxiosReturn<T, R, D>>
export declare function useAxios<T = any, R = AxiosResponse<T>, D = any>(
config?: AxiosRequestConfig<D>,
instance?: AxiosInstance,
): EasyUseAxiosReturn<T, R, D> & Promise<EasyUseAxiosReturn<T, R, D>>
```

View File

@@ -0,0 +1,88 @@
---
category: Utilities
---
# useBase64
Reactive base64 transforming. Supports plain text, buffer, files, canvas, objects, maps, sets and images.
## Usage
```ts
import { useBase64 } from '@vueuse/core'
import { shallowRef } from 'vue'
const text = shallowRef('')
const { base64 } = useBase64(text)
```
If you use object, array, map or set you can provide serializer in options. Otherwise, your data will be serialized by default serializer.
Objects and arrays will be transformed in string by JSON.stringify. Map and set will be transformed in object and array respectively before stringify.
## Type Declarations
```ts
export interface UseBase64Options {
/**
* Output as Data URL format
*
* @default true
*/
dataUrl?: boolean
}
export interface ToDataURLOptions extends UseBase64Options {
/**
* MIME type
*/
type?: string | undefined
/**
* Image quality of jpeg or webp
*/
quality?: any
}
export interface UseBase64ObjectOptions<T> extends UseBase64Options {
serializer?: (v: T) => string
}
export interface UseBase64Return {
base64: ShallowRef<string>
promise: ShallowRef<Promise<string>>
execute: () => Promise<string>
}
export declare function useBase64(
target: MaybeRefOrGetter<string | undefined>,
options?: UseBase64Options,
): UseBase64Return
export declare function useBase64(
target: MaybeRefOrGetter<Blob | undefined>,
options?: UseBase64Options,
): UseBase64Return
export declare function useBase64(
target: MaybeRefOrGetter<ArrayBuffer | undefined>,
options?: UseBase64Options,
): UseBase64Return
export declare function useBase64(
target: MaybeRefOrGetter<HTMLCanvasElement | undefined>,
options?: ToDataURLOptions,
): UseBase64Return
export declare function useBase64(
target: MaybeRefOrGetter<HTMLImageElement | undefined>,
options?: ToDataURLOptions,
): UseBase64Return
export declare function useBase64<T extends Record<string, unknown>>(
target: MaybeRefOrGetter<T>,
options?: UseBase64ObjectOptions<T>,
): UseBase64Return
export declare function useBase64<T extends Map<string, unknown>>(
target: MaybeRefOrGetter<T>,
options?: UseBase64ObjectOptions<T>,
): UseBase64Return
export declare function useBase64<T extends Set<unknown>>(
target: MaybeRefOrGetter<T>,
options?: UseBase64ObjectOptions<T>,
): UseBase64Return
export declare function useBase64<T>(
target: MaybeRefOrGetter<T[]>,
options?: UseBase64ObjectOptions<T[]>,
): UseBase64Return
```

View File

@@ -0,0 +1,67 @@
---
category: Sensors
---
# useBattery
Reactive [Battery Status API](https://developer.mozilla.org/en-US/docs/Web/API/Battery_Status_API), more often referred to as the Battery API, provides information about the system's battery charge level and lets you be notified by events that are sent when the battery level or charging status change. This can be used to adjust your app's resource usage to reduce battery drain when the battery is low, or to save changes before the battery runs out in order to prevent data loss.
## Usage
```ts
import { useBattery } from '@vueuse/core'
const { charging, chargingTime, dischargingTime, level } = useBattery()
```
| State | Type | Description |
| --------------- | --------- | ----------------------------------------------------------------- |
| charging | `Boolean` | If the device is currently charging. |
| chargingTime | `Number` | The number of seconds until the device becomes fully charged. |
| dischargingTime | `Number` | The number of seconds before the device becomes fully discharged. |
| level | `Number` | A number between 0 and 1 representing the current charge level. |
## Use-cases
Our applications normally are not empathetic to battery level, we can make a few adjustments to our applications that will be more friendly to low battery users.
- Trigger a special "dark-mode" battery saver theme settings.
- Stop auto playing videos in news feeds.
- Disable some background workers that are not critical.
- Limit network calls and reduce CPU/Memory consumption.
## Component Usage
```vue
<template>
<UseBattery v-slot="{ charging }">
Is Charging: {{ charging }}
</UseBattery>
</template>
```
## Type Declarations
```ts
export interface BatteryManager extends EventTarget {
charging: boolean
chargingTime: number
dischargingTime: number
level: number
}
/**
* Reactive Battery Status API.
*
* @see https://vueuse.org/useBattery
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useBattery(options?: ConfigurableNavigator): {
isSupported: ComputedRef<boolean>
charging: ShallowRef<boolean, boolean>
chargingTime: ShallowRef<number, number>
dischargingTime: ShallowRef<number, number>
level: ShallowRef<number, number>
}
export type UseBatteryReturn = ReturnType<typeof useBattery>
```

View File

@@ -0,0 +1,161 @@
---
category: Browser
---
# useBluetooth
Reactive [Web Bluetooth API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Bluetooth_API). Provides the ability to connect and interact with Bluetooth Low Energy peripherals.
The Web Bluetooth API lets websites discover and communicate with devices over the Bluetooth 4 wireless standard using the Generic Attribute Profile (GATT).
N.B. It is currently partially implemented in Android M, Chrome OS, Mac, and Windows 10. For a full overview of browser compatibility please see [Web Bluetooth API Browser Compatibility](https://developer.mozilla.org/en-US/docs/Web/API/Web_Bluetooth_API#browser_compatibility)
N.B. There are a number of caveats to be aware of with the web bluetooth API specification. Please refer to the [Web Bluetooth W3C Draft Report](https://webbluetoothcg.github.io/web-bluetooth/) for numerous caveats around device detection and connection.
N.B. This API is not available in Web Workers (not exposed via WorkerNavigator).
## Usage Default
```vue
<script setup lang="ts">
import { useBluetooth } from '@vueuse/core'
const {
isSupported,
isConnected,
device,
requestDevice,
server,
} = useBluetooth({
acceptAllDevices: true,
})
</script>
<template>
<button @click="requestDevice()">
Request Bluetooth Device
</button>
</template>
```
When the device has paired and is connected, you can then work with the server object as you wish.
## Usage Battery Level Example
This sample illustrates the use of the Web Bluetooth API to read battery level and be notified of changes from a nearby Bluetooth Device advertising Battery information with Bluetooth Low Energy.
Here, we use the characteristicvaluechanged event listener to handle reading battery level characteristic value. This event listener will optionally handle upcoming notifications as well.
```vue
<script setup lang="ts">
import { useBluetooth, useEventListener, watchPausable } from '@vueuse/core'
const {
isSupported,
isConnected,
device,
requestDevice,
server,
} = useBluetooth({
acceptAllDevices: true,
optionalServices: [
'battery_service',
],
})
const batteryPercent = ref<undefined | number>()
const isGettingBatteryLevels = ref(false)
async function getBatteryLevels() {
isGettingBatteryLevels.value = true
// Get the battery service:
const batteryService = await server.getPrimaryService('battery_service')
// Get the current battery level
const batteryLevelCharacteristic = await batteryService.getCharacteristic(
'battery_level',
)
// Listen to when characteristic value changes on `characteristicvaluechanged` event:
useEventListener(batteryLevelCharacteristic, 'characteristicvaluechanged', (event) => {
batteryPercent.value = event.target.value.getUint8(0)
}, { passive: true })
// Convert received buffer to number:
const batteryLevel = await batteryLevelCharacteristic.readValue()
batteryPercent.value = await batteryLevel.getUint8(0)
}
const { stop } = watchPausable(isConnected, (newIsConnected) => {
if (!newIsConnected || !server.value || isGettingBatteryLevels.value)
return
// Attempt to get the battery levels of the device:
getBatteryLevels()
// We only want to run this on the initial connection, as we will use an event listener to handle updates:
stop()
})
</script>
<template>
<button @click="requestDevice()">
Request Bluetooth Device
</button>
</template>
```
More samples can be found on [Google Chrome's Web Bluetooth Samples](https://googlechrome.github.io/samples/web-bluetooth/).
## Type Declarations
```ts
export interface UseBluetoothRequestDeviceOptions {
/**
*
* An array of BluetoothScanFilters. This filter consists of an array
* of BluetoothServiceUUIDs, a name parameter, and a namePrefix parameter.
*
*/
filters?: BluetoothLEScanFilter[] | undefined
/**
*
* An array of BluetoothServiceUUIDs.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/BluetoothRemoteGATTService/uuid
*
*/
optionalServices?: BluetoothServiceUUID[] | undefined
}
export interface UseBluetoothOptions
extends UseBluetoothRequestDeviceOptions,
ConfigurableNavigator {
/**
*
* A boolean value indicating that the requesting script can accept all Bluetooth
* devices. The default is false.
*
* !! This may result in a bunch of unrelated devices being shown
* in the chooser and energy being wasted as there are no filters.
*
*
* Use it with caution.
*
* @default false
*
*/
acceptAllDevices?: boolean
}
export declare function useBluetooth(
options?: UseBluetoothOptions,
): UseBluetoothReturn
export interface UseBluetoothReturn {
isSupported: ComputedRef<boolean>
isConnected: Readonly<ShallowRef<boolean>>
device: ShallowRef<BluetoothDevice | undefined>
requestDevice: () => Promise<void>
server: ShallowRef<BluetoothRemoteGATTServer | undefined>
error: ShallowRef<unknown | null>
}
```

View File

@@ -0,0 +1,128 @@
---
category: Browser
---
# useBreakpoints
Reactive viewport breakpoints.
## Usage
```ts
import { breakpointsTailwind, useBreakpoints } from '@vueuse/core'
const breakpoints = useBreakpoints(breakpointsTailwind)
const smAndLarger = breakpoints.greaterOrEqual('sm') // sm and larger
const largerThanSm = breakpoints.greater('sm') // only larger than sm
const lgAndSmaller = breakpoints.smallerOrEqual('lg') // lg and smaller
const smallerThanLg = breakpoints.smaller('lg') // only smaller than lg
```
```vue
<script setup lang="ts">
import { useBreakpoints } from '@vueuse/core'
const breakpoints = useBreakpoints({
mobile: 0, // optional
tablet: 640,
laptop: 1024,
desktop: 1280,
})
// Can be 'mobile' or 'tablet' or 'laptop' or 'desktop'
const activeBreakpoint = breakpoints.active()
// true or false
const laptop = breakpoints.between('laptop', 'desktop')
</script>
<template>
<div :class="activeBreakpoint">
...
</div>
</template>
```
#### Server Side Rendering and Nuxt
If you are using `useBreakpoints` with SSR enabled, then you need to specify which screen size you would like to render on the server and before hydration to avoid an hydration mismatch
```ts
import { breakpointsTailwind, useBreakpoints } from '@vueuse/core'
const breakpoints = useBreakpoints(breakpointsTailwind, {
ssrWidth: 768 // Will enable SSR mode and render like if the screen was 768px wide
})
```
Alternatively you can set this up globally for your app using [`provideSSRWidth`](../useSSRWidth/index.md)
## Presets
- Tailwind: `breakpointsTailwind`
- Bootstrap v5: `breakpointsBootstrapV5`
- Vuetify v2: `breakpointsVuetifyV2` (deprecated: `breakpointsVuetify`)
- Vuetify v3: `breakpointsVuetifyV3`
- Ant Design: `breakpointsAntDesign`
- Quasar v2: `breakpointsQuasar`
- Sematic: `breakpointsSematic`
- Master CSS: `breakpointsMasterCss`
- Prime Flex: `breakpointsPrimeFlex`
- ElementUI / ElementPlus: `breakpointsElement`
_Breakpoint presets are deliberately not auto-imported, as they do not start with `use` to have the scope of VueUse. They have to be explicitly imported:_
```js
import { breakpointsTailwind } from '@vueuse/core'
// and so on
```
## Type Declarations
```ts
export * from "./breakpoints"
export type Breakpoints<K extends string = string> = Record<
K,
MaybeRefOrGetter<number | string>
>
export interface UseBreakpointsOptions extends ConfigurableWindow {
/**
* The query strategy to use for the generated shortcut methods like `.lg`
*
* 'min-width' - .lg will be true when the viewport is greater than or equal to the lg breakpoint (mobile-first)
* 'max-width' - .lg will be true when the viewport is smaller than the xl breakpoint (desktop-first)
*
* @default "min-width"
*/
strategy?: "min-width" | "max-width"
ssrWidth?: number
}
/**
* Reactively viewport breakpoints
*
* @see https://vueuse.org/useBreakpoints
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useBreakpoints<K extends string>(
breakpoints: Breakpoints<K>,
options?: UseBreakpointsOptions,
): Record<K, ComputedRef<boolean>> & {
greaterOrEqual: (k: MaybeRefOrGetter<K>) => ComputedRef<boolean>
smallerOrEqual: (k: MaybeRefOrGetter<K>) => ComputedRef<boolean>
greater(k: MaybeRefOrGetter<K>): ComputedRef<boolean>
smaller(k: MaybeRefOrGetter<K>): ComputedRef<boolean>
between(a: MaybeRefOrGetter<K>, b: MaybeRefOrGetter<K>): ComputedRef<boolean>
isGreater(k: MaybeRefOrGetter<K>): boolean
isGreaterOrEqual(k: MaybeRefOrGetter<K>): boolean
isSmaller(k: MaybeRefOrGetter<K>): boolean
isSmallerOrEqual(k: MaybeRefOrGetter<K>): boolean
isInBetween(a: MaybeRefOrGetter<K>, b: MaybeRefOrGetter<K>): boolean
current: () => ComputedRef<K[]>
active(): ComputedRef<"" | K>
}
export type UseBreakpointsReturn<K extends string = string> = ReturnType<
typeof useBreakpoints<K>
>
```

View File

@@ -0,0 +1,74 @@
---
category: Browser
---
# useBroadcastChannel
Reactive [BroadcastChannel API](https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel).
Closes a broadcast channel automatically component unmounted.
## Usage
The BroadcastChannel interface represents a named channel that any browsing
context of a given origin can subscribe to. It allows communication between
different documents (in different windows, tabs, frames, or iframes) of the
same origin.
Messages are broadcasted via a message event fired at all BroadcastChannel
objects listening to the channel.
```ts
import { useBroadcastChannel } from '@vueuse/core'
import { shallowRef } from 'vue'
const {
isSupported,
channel,
post,
close,
error,
isClosed,
} = useBroadcastChannel({ name: 'vueuse-demo-channel' })
const message = shallowRef('')
message.value = 'Hello, VueUse World!'
// Post the message to the broadcast channel:
post(message.value)
// Option to close the channel if you wish:
close()
```
## Type Declarations
```ts
export interface UseBroadcastChannelOptions extends ConfigurableWindow {
/**
* The name of the channel.
*/
name: string
}
/**
* Reactive BroadcastChannel
*
* @see https://vueuse.org/useBroadcastChannel
* @see https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel
* @param options
*
*/
export declare function useBroadcastChannel<D, P>(
options: UseBroadcastChannelOptions,
): UseBroadcastChannelReturn<D, P>
export interface UseBroadcastChannelReturn<D, P> {
isSupported: ComputedRef<boolean>
channel: Ref<BroadcastChannel | undefined>
data: Ref<D>
post: (data: P) => void
close: () => void
error: ShallowRef<Event | null>
isClosed: ShallowRef<boolean>
}
```

View File

@@ -0,0 +1,83 @@
---
category: Browser
---
# useBrowserLocation
Reactive browser location
> NOTE: If you're using Vue Router, use [`useRoute`](https://router.vuejs.org/guide/advanced/composition-api.html) provided by Vue Router instead.
## Usage
```ts
import { useBrowserLocation } from '@vueuse/core'
const location = useBrowserLocation()
```
## Component Usage
```vue
<UseBrowserLocation v-slot="location">
Browser Location: {{ location }}
</UseBrowserLocation>
```
## Type Declarations
```ts
export interface BrowserLocationState {
readonly trigger: string
readonly state?: any
readonly length?: number
readonly origin?: string
hash?: string
host?: string
hostname?: string
href?: string
pathname?: string
port?: string
protocol?: string
search?: string
}
/**
* Reactive browser location.
*
* @see https://vueuse.org/useBrowserLocation
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useBrowserLocation(options?: ConfigurableWindow): Ref<
{
readonly trigger: string
readonly state?: any
readonly length?: number | undefined
readonly origin?: string | undefined
hash?: string | undefined
host?: string | undefined
hostname?: string | undefined
href?: string | undefined
pathname?: string | undefined
port?: string | undefined
protocol?: string | undefined
search?: string | undefined
},
| BrowserLocationState
| {
readonly trigger: string
readonly state?: any
readonly length?: number | undefined
readonly origin?: string | undefined
hash?: string | undefined
host?: string | undefined
hostname?: string | undefined
href?: string | undefined
pathname?: string | undefined
port?: string | undefined
protocol?: string | undefined
search?: string | undefined
}
>
export type UseBrowserLocationReturn = ReturnType<typeof useBrowserLocation>
```

View File

@@ -0,0 +1,53 @@
---
category: Utilities
---
# useCached
Cache a ref with a custom comparator.
## Usage
```ts
import { useCached } from '@vueuse/core'
import { shallowRef } from 'vue'
interface Data {
value: number
extra: number
}
const source = shallowRef<Data>({ value: 42, extra: 0 })
const cached = useCached(source, (a, b) => a.value === b.value)
source.value = {
value: 42,
extra: 1,
}
console.log(cached.value) // { value: 42, extra: 0 }
source.value = {
value: 43,
extra: 1,
}
console.log(cached.value) // { value: 43, extra: 1 }
```
## Type Declarations
```ts
export interface UseCachedOptions<D extends boolean = true>
extends ConfigurableDeepRefs<D>,
WatchOptions {}
export declare function useCached<T, D extends boolean = true>(
refValue: Ref<T>,
comparator?: (a: T, b: T) => boolean,
options?: UseCachedOptions<D>,
): UseCachedReturn<T, D>
export type UseCachedReturn<
T = any,
D extends boolean = true,
> = ShallowOrDeepRef<T, D>
```

View File

@@ -0,0 +1,31 @@
---
category: '@Math'
---
# useCeil
Reactive `Math.ceil`
## Usage
```ts
import { useCeil } from '@vueuse/math'
const value = ref(0.95)
const result = useCeil(value) // 1
```
## Type Declarations
```ts
/**
* Reactive `Math.ceil`.
*
* @see https://vueuse.org/useCeil
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useCeil(
value: MaybeRefOrGetter<number>,
): ComputedRef<number>
```

View File

@@ -0,0 +1,79 @@
---
category: '@Integrations'
---
# useChangeCase
Reactive wrapper for [`change-case`](https://github.com/blakeembrey/change-case).
Subsitutes `useCamelCase`, `usePascalCase`, `useSnakeCase`, `useSentenceCase`, `useCapitalize`, etc.
## Install
```bash
npm i change-case@^5
```
## Usage
```ts
import { useChangeCase } from '@vueuse/integrations/useChangeCase'
// `changeCase` will be a computed
const changeCase = useChangeCase('hello world', 'camelCase')
changeCase.value // helloWorld
changeCase.value = 'vue use'
changeCase.value // vueUse
// Supported methods
// export {
// camelCase,
// capitalCase,
// constantCase,
// dotCase,
// headerCase,
// noCase,
// paramCase,
// pascalCase,
// pathCase,
// sentenceCase,
// snakeCase,
// } from 'change-case'
```
or passing a `ref` to it, the returned `computed` will change along with the source ref's changes.
Can be passed into `options` for customization
```ts
import { useChangeCase } from '@vueuse/integrations/useChangeCase'
import { shallowRef } from 'vue'
const input = shallowRef('helloWorld')
const changeCase = useChangeCase(input, 'camelCase', {
delimiter: '-',
})
changeCase.value // hello-World
input.value = 'vue use'
changeCase.value // vue-Use
```
## Type Declarations
```ts
type EndsWithCase<T> = T extends `${infer _}Case` ? T : never
type FilterKeys<T> = {
[K in keyof T as K extends string ? K : never]: EndsWithCase<K>
}
type ChangeCaseKeys = FilterKeys<typeof changeCase>
export type ChangeCaseType = ChangeCaseKeys[keyof ChangeCaseKeys]
export declare function useChangeCase(
input: MaybeRef<string>,
type: MaybeRefOrGetter<ChangeCaseType>,
options?: MaybeRefOrGetter<Options> | undefined,
): WritableComputedRef<string>
export declare function useChangeCase(
input: MaybeRefOrGetter<string>,
type: MaybeRefOrGetter<ChangeCaseType>,
options?: MaybeRefOrGetter<Options> | undefined,
): ComputedRef<string>
```

View File

@@ -0,0 +1,51 @@
---
category: '@Math'
---
# useClamp
Reactively clamp a value between two other values.
## Usage
```ts
import { useClamp } from '@vueuse/math'
const min = shallowRef(0)
const max = shallowRef(10)
const value = useClamp(0, min, max)
```
You can also pass a `ref` and the returned `computed` will be updated when the source ref changes:
```ts
import { useClamp } from '@vueuse/math'
const number = shallowRef(0)
const clamped = useClamp(number, 0, 10)
```
## Type Declarations
```ts
/**
* Reactively clamp a value between two other values.
*
* @see https://vueuse.org/useClamp
* @param value number
* @param min
* @param max
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useClamp(
value: ReadonlyRefOrGetter<number>,
min: MaybeRefOrGetter<number>,
max: MaybeRefOrGetter<number>,
): ComputedRef<number>
export declare function useClamp(
value: MaybeRefOrGetter<number>,
min: MaybeRefOrGetter<number>,
max: MaybeRefOrGetter<number>,
): Ref<number>
```

View File

@@ -0,0 +1,99 @@
---
category: Browser
---
# useClipboard
Reactive [Clipboard API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API). Provides the ability to respond to clipboard commands (cut, copy, and paste) as well as to asynchronously read from and write to the system clipboard. Access to the contents of the clipboard is gated behind the [Permissions API](https://developer.mozilla.org/en-US/docs/Web/API/Permissions_API). Without user permission, reading or altering the clipboard contents is not permitted.
<CourseLink href="https://vueschool.io/lessons/reactive-browser-wrappers-in-vueuse-useclipboard?friend=vueuse">Learn how to reactively save text to the clipboard with this FREE video lesson from Vue School!</CourseLink>
## Usage
```vue
<script setup lang="ts">
import { useClipboard } from '@vueuse/core'
const source = ref('Hello')
const { text, copy, copied, isSupported } = useClipboard({ source })
</script>
<template>
<div v-if="isSupported">
<button @click="copy(source)">
<!-- by default, `copied` will be reset in 1.5s -->
<span v-if="!copied">Copy</span>
<span v-else>Copied!</span>
</button>
<p>Current copied: <code>{{ text || 'none' }}</code></p>
</div>
<p v-else>
Your browser does not support Clipboard API
</p>
</template>
```
Set `legacy: true` to keep the ability to copy if [Clipboard API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API) is not available. It will handle copy with [execCommand](https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand) as fallback.
## Component Usage
```vue
<template>
<UseClipboard v-slot="{ copy, copied }" source="copy me">
<button @click="copy()">
{{ copied ? 'Copied' : 'Copy' }}
</button>
</UseClipboard>
</template>
```
## Type Declarations
```ts
export interface UseClipboardOptions<Source> extends ConfigurableNavigator {
/**
* Enabled reading for clipboard
*
* @default false
*/
read?: boolean
/**
* Copy source
*/
source?: Source
/**
* Milliseconds to reset state of `copied` ref
*
* @default 1500
*/
copiedDuring?: number
/**
* Whether fallback to document.execCommand('copy') if clipboard is undefined.
*
* @default false
*/
legacy?: boolean
}
export interface UseClipboardReturn<Optional> {
isSupported: ComputedRef<boolean>
text: Readonly<ShallowRef<string>>
copied: Readonly<ShallowRef<boolean>>
copy: Optional extends true
? (text?: string) => Promise<void>
: (text: string) => Promise<void>
}
/**
* Reactive Clipboard API.
*
* @see https://vueuse.org/useClipboard
* @param options
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useClipboard(
options?: UseClipboardOptions<undefined>,
): UseClipboardReturn<false>
export declare function useClipboard(
options: UseClipboardOptions<MaybeRefOrGetter<string>>,
): UseClipboardReturn<true>
```

View File

@@ -0,0 +1,93 @@
---
category: Browser
related:
- useClipboard
---
# useClipboardItems
Reactive [Clipboard API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API). Provides the ability to respond to clipboard commands (cut, copy, and paste) as well as to asynchronously read from and write to the system clipboard. Access to the contents of the clipboard is gated behind the [Permissions API](https://developer.mozilla.org/en-US/docs/Web/API/Permissions_API). Without user permission, reading or altering the clipboard contents is not permitted.
## Difference from `useClipboard`
`useClipboard` is a "text-only" function, while `useClipboardItems` is a [ClipboardItem](https://developer.mozilla.org/en-US/docs/Web/API/ClipboardItem) based function. You can use `useClipboardItems` to copy any content supported by [ClipboardItem](https://developer.mozilla.org/en-US/docs/Web/API/ClipboardItem).
## Usage
```vue
<script setup lang="ts">
import { useClipboardItems } from '@vueuse/core'
const mime = 'text/plain'
const source = ref([
new ClipboardItem({
[mime]: new Blob(['plain text'], { type: mime }),
})
])
const { content, copy, copied, isSupported } = useClipboardItems({ source })
</script>
<template>
<div v-if="isSupported">
<button @click="copy(source)">
<!-- by default, `copied` will be reset in 1.5s -->
<span v-if="!copied">Copy</span>
<span v-else>Copied!</span>
</button>
<p>
Current copied: <code>{{ content || 'none' }}</code>
</p>
</div>
<p v-else>
Your browser does not support Clipboard API
</p>
</template>
```
## Type Declarations
```ts
export interface UseClipboardItemsOptions<Source>
extends ConfigurableNavigator {
/**
* Enabled reading for clipboard
*
* @default false
*/
read?: boolean
/**
* Copy source
*/
source?: Source
/**
* Milliseconds to reset state of `copied` ref
*
* @default 1500
*/
copiedDuring?: number
}
export interface UseClipboardItemsReturn<Optional> {
isSupported: ComputedRef<boolean>
content: Readonly<Ref<ClipboardItems>>
copied: Readonly<ShallowRef<boolean>>
copy: Optional extends true
? (content?: ClipboardItems) => Promise<void>
: (text: ClipboardItems) => Promise<void>
read: () => void
}
/**
* Reactive Clipboard API.
*
* @see https://vueuse.org/useClipboardItems
* @param options
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useClipboardItems(
options?: UseClipboardItemsOptions<undefined>,
): UseClipboardItemsReturn<false>
export declare function useClipboardItems(
options: UseClipboardItemsOptions<MaybeRefOrGetter<ClipboardItems>>,
): UseClipboardItemsReturn<true>
```

View File

@@ -0,0 +1,91 @@
---
category: Utilities
---
# useCloned
Reactive clone of a ref. By default, it use `JSON.parse(JSON.stringify())` to do the clone.
## Usage
```ts
import { useCloned } from '@vueuse/core'
const original = ref({ key: 'value' })
const { cloned } = useCloned(original)
original.value.key = 'some new value'
console.log(cloned.value.key) // 'value'
```
## Manual cloning
```ts
import { useCloned } from '@vueuse/core'
const original = ref({ key: 'value' })
const { cloned, sync } = useCloned(original, { manual: true })
original.value.key = 'manual'
console.log(cloned.value.key) // 'value'
sync()
console.log(cloned.value.key)// 'manual'
```
## Custom Clone Function
Using [`klona`](https://www.npmjs.com/package/klona) for example:
```ts
import { useCloned } from '@vueuse/core'
import { klona } from 'klona'
const original = ref({ key: 'value' })
const { cloned, isModified, sync } = useCloned(original, { clone: klona })
```
## Type Declarations
```ts
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>
/**
* Ref indicates whether the cloned data is modified
*/
isModified: Ref<boolean>
/**
* Sync cloned data with source manually
*/
sync: () => void
}
export type CloneFn<F, T = F> = (x: F) => T
export declare function cloneFnJSON<T>(source: T): T
export declare function useCloned<T>(
source: MaybeRefOrGetter<T>,
options?: UseClonedOptions,
): UseClonedReturn<T>
```

View File

@@ -0,0 +1,171 @@
---
category: Browser
related:
- useDark
- usePreferredDark
- useStorage
---
# useColorMode
Reactive color mode (dark / light / customs) with auto data persistence.
## Basic Usage
```ts
import { useColorMode } from '@vueuse/core'
const mode = useColorMode() // Ref<'dark' | 'light'>
```
By default, it will match with users' browser preference using `usePreferredDark` (a.k.a `auto` mode). When reading the ref, it will by default return the current color mode (`dark`, `light` or your custom modes). The `auto` mode can be included in the returned modes by enabling the `emitAuto` option. When writing to the ref, it will trigger DOM updates and persist the color mode to local storage (or your custom storage). You can pass `auto` to set back to auto mode.
```ts
import { useColorMode } from '@vueuse/core'
const mode = useColorMode()
// ---cut---
mode.value // 'dark' | 'light'
mode.value = 'dark' // change to dark mode and persist
mode.value = 'auto' // change to auto mode
```
## Config
```ts
import { useColorMode } from '@vueuse/core'
const mode = useColorMode({
attribute: 'theme',
modes: {
// custom colors
dim: 'dim',
cafe: 'cafe',
},
}) // Ref<'dark' | 'light' | 'dim' | 'cafe'>
```
## Advanced Usage
You can also explicit access to the system preference and storaged user override mode.
```ts
import { useColorMode } from '@vueuse/core'
const { system, store } = useColorMode()
system.value // 'dark' | 'light'
store.value // 'dark' | 'light' | 'auto'
const myColorMode = computed(() => store.value === 'auto' ? system.value : store.value)
```
## Component Usage
```vue
<template>
<UseColorMode v-slot="color">
<button @click="color.mode = color.mode === 'dark' ? 'light' : 'dark'">
Mode {{ color.mode }}
</button>
</UseColorMode>
</template>
```
## Type Declarations
```ts
export type BasicColorMode = "light" | "dark"
export type BasicColorSchema = BasicColorMode | "auto"
export interface UseColorModeOptions<T extends string = BasicColorMode>
extends UseStorageOptions<T | BasicColorMode> {
/**
* CSS Selector for the target element applying to
*
* @default 'html'
*/
selector?: string | MaybeElementRef
/**
* HTML attribute applying the target element
*
* @default 'class'
*/
attribute?: string
/**
* The initial color mode
*
* @default 'auto'
*/
initialValue?: MaybeRefOrGetter<T | BasicColorSchema>
/**
* Prefix when adding value to the attribute
*/
modes?: Partial<Record<T | BasicColorSchema, string>>
/**
* A custom handler for handle the updates.
* When specified, the default behavior will be overridden.
*
* @default undefined
*/
onChanged?: (
mode: T | BasicColorMode,
defaultHandler: (mode: T | BasicColorMode) => void,
) => void
/**
* Custom storage ref
*
* When provided, `useStorage` will be skipped
*/
storageRef?: Ref<T | BasicColorSchema>
/**
* Key to persist the data into localStorage/sessionStorage.
*
* Pass `null` to disable persistence
*
* @default 'vueuse-color-scheme'
*/
storageKey?: string | null
/**
* Storage object, can be localStorage or sessionStorage
*
* @default localStorage
*/
storage?: StorageLike
/**
* Emit `auto` mode from state
*
* When set to `true`, preferred mode won't be translated into `light` or `dark`.
* This is useful when the fact that `auto` mode was selected needs to be known.
*
* @default undefined
* @deprecated use `store.value` when `auto` mode needs to be known
* @see https://vueuse.org/core/useColorMode/#advanced-usage
*/
emitAuto?: boolean
/**
* Disable transition on switch
*
* @see https://paco.me/writing/disable-theme-transitions
* @default true
*/
disableTransition?: boolean
}
export type UseColorModeReturn<T extends string = BasicColorMode> = Ref<
T | BasicColorSchema
> & {
store: Ref<T | BasicColorSchema>
system: ComputedRef<BasicColorMode>
state: ComputedRef<T | BasicColorMode>
}
/**
* Reactive color mode with auto data persistence.
*
* @see https://vueuse.org/useColorMode
* @param options
*/
export declare function useColorMode<T extends string = BasicColorMode>(
options?: UseColorModeOptions<T>,
): UseColorModeReturn<T>
```

View File

@@ -0,0 +1,159 @@
---
category: Utilities
---
# useConfirmDialog
Creates event hooks to support modals and confirmation dialog chains.
Functions can be used on the template, and hooks are a handy skeleton for the business logic of modals dialog or other actions that require user confirmation.
## Functions and hooks
- `reveal()` - triggers `onReveal` hook and sets `revealed.value` to `true`. Returns promise that resolves by `confirm()` or `cancel()`.
- `confirm()` - sets `isRevealed.value` to `false` and triggers `onConfirm` hook.
- `cancel()` - sets `isRevealed.value` to `false` and triggers `onCancel` hook.
## Basic Usage
### Using hooks
```vue
<script setup lang="ts">
import { useConfirmDialog } from '@vueuse/core'
const { isRevealed, reveal, confirm, cancel, onReveal, onConfirm, onCancel }
= useConfirmDialog()
</script>
<template>
<button @click="reveal">
Reveal Modal
</button>
<teleport to="body">
<div v-if="isRevealed" class="modal-bg">
<div class="modal">
<h2>Confirm?</h2>
<button @click="confirm">
Yes
</button>
<button @click="cancel">
Cancel
</button>
</div>
</div>
</teleport>
</template>
```
### Promise
If you prefer working with promises:
```vue
<script setup lang="ts">
import { useConfirmDialog } from '@vueuse/core'
const {
isRevealed,
reveal,
confirm,
cancel,
} = useConfirmDialog()
async function openDialog() {
const { data, isCanceled } = await reveal()
if (!isCanceled)
console.log(data)
}
</script>
<template>
<button @click="openDialog">
Show Modal
</button>
<teleport to="body">
<div v-if="isRevealed" class="modal-layout">
<div class="modal">
<h2>Confirm?</h2>
<button @click="confirm(true)">
Yes
</button>
<button @click="confirm(false)">
No
</button>
</div>
</div>
</teleport>
</template>
```
## Type Declarations
```ts
export type UseConfirmDialogRevealResult<C, D> =
| {
data?: C
isCanceled: false
}
| {
data?: D
isCanceled: true
}
export interface UseConfirmDialogReturn<RevealData, ConfirmData, CancelData> {
/**
* Revealing state
*/
isRevealed: ComputedRef<boolean>
/**
* Opens the dialog.
* Create promise and return it. Triggers `onReveal` hook.
*/
reveal: (
data?: RevealData,
) => Promise<UseConfirmDialogRevealResult<ConfirmData, CancelData>>
/**
* Confirms and closes the dialog. Triggers a callback inside `onConfirm` hook.
* Resolves promise from `reveal()` with `data` and `isCanceled` ref with `false` value.
* Can accept any data and to pass it to `onConfirm` hook.
*/
confirm: (data?: ConfirmData) => void
/**
* Cancels and closes the dialog. Triggers a callback inside `onCancel` hook.
* Resolves promise from `reveal()` with `data` and `isCanceled` ref with `true` value.
* Can accept any data and to pass it to `onCancel` hook.
*/
cancel: (data?: CancelData) => void
/**
* Event Hook to be triggered right before dialog creating.
*/
onReveal: EventHookOn<RevealData>
/**
* Event Hook to be called on `confirm()`.
* Gets data object from `confirm` function.
*/
onConfirm: EventHookOn<ConfirmData>
/**
* Event Hook to be called on `cancel()`.
* Gets data object from `cancel` function.
*/
onCancel: EventHookOn<CancelData>
}
/**
* Hooks for creating confirm dialogs. Useful for modal windows, popups and logins.
*
* @see https://vueuse.org/useConfirmDialog/
* @param revealed `boolean` `ref` that handles a modal window
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useConfirmDialog<
RevealData = any,
ConfirmData = any,
CancelData = any,
>(
revealed?: ShallowRef<boolean>,
): UseConfirmDialogReturn<RevealData, ConfirmData, CancelData>
```

View File

@@ -0,0 +1,162 @@
---
category: '@Integrations'
---
# useCookies
Wrapper for [`universal-cookie`](https://www.npmjs.com/package/universal-cookie).
::: tip
When using with Nuxt 3, this functions will **NOT** be auto imported in favor of Nuxt's built-in [`useCookie()`](https://v3.nuxtjs.org/api/composables/use-cookie). Use explicit import if you want to use the function from VueUse.
:::
## Install
```bash
npm i universal-cookie@^7
```
## Usage
### Common usage
```vue
<script setup lang="ts">
import { useCookies } from '@vueuse/integrations/useCookies'
const cookies = useCookies(['locale'])
</script>
<template>
<div>
<strong>locale</strong>: {{ cookies.get('locale') }}
<hr>
<pre>{{ cookies.getAll() }}</pre>
<button @click="cookies.set('locale', 'ru-RU')">
Russian
</button>
<button @click="cookies.set('locale', 'en-US')">
English
</button>
</div>
</template>
```
## Options
Access and modify cookies using vue composition-api.
> By default, you should use it inside `setup()`, but this function also works anywhere else.
```ts
import { useCookies } from '@vueuse/integrations/useCookies'
// ---cut---
const {
get,
getAll,
set,
remove,
addChangeListener,
removeChangeListener
} = useCookies(['cookie-name'], {
doNotParse: false,
autoUpdateDependencies: false
})
```
### `dependencies` (optional)
Let you optionally specify a list of cookie names your component depend on or that should trigger a re-render. If unspecified, it will render on every cookie change.
### `options` (optional)
- `doNotParse` (boolean = false): do not convert the cookie into an object no matter what. **Passed as default value to `get`/`getAll` methods.**
- `autoUpdateDependencies` (boolean = false): automatically add cookie names ever provided to `get` method. If **true** then you don't need to care about provided `dependencies`.
### `cookies` (optional)
Let you provide a `universal-cookie` instance (creates a new instance by default)
> Info about methods available in the [universal-cookie api docs](https://www.npmjs.com/package/universal-cookie#api---cookies-class)
## `createCookies([req])`
Create a `universal-cookie` instance using request (default is window.document.cookie) and returns `useCookies` function with provided universal-cookie instance
- req (object): Node's [http.IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage) request object
## Type Declarations
```ts
/**
* Creates a new {@link useCookies} function
* @param req - incoming http request (for SSR)
* @see https://github.com/reactivestack/cookies/tree/master/packages/universal-cookie universal-cookie
* @description Creates universal-cookie instance using request (default is window.document.cookie) and returns {@link useCookies} function with provided universal-cookie instance
*/
export declare function createCookies(req?: IncomingMessage): (
dependencies?: string[] | null,
{
doNotParse,
autoUpdateDependencies,
}?: {
doNotParse?: boolean | undefined
autoUpdateDependencies?: boolean | undefined
},
) => {
/**
* Reactive get cookie by name. If **autoUpdateDependencies = true** then it will update watching dependencies
*/
get: <T = any>(name: string, options?: CookieGetOptions | undefined) => T
/**
* Reactive get all cookies
*/
getAll: <T = any>(options?: CookieGetOptions | undefined) => T
set: (
name: string,
value: any,
options?: CookieSetOptions | undefined,
) => void
remove: (name: string, options?: CookieSetOptions | undefined) => void
addChangeListener: (callback: CookieChangeListener) => void
removeChangeListener: (callback: CookieChangeListener) => void
}
/**
* Reactive methods to work with cookies (use {@link createCookies} method instead if you are using SSR)
* @param dependencies - array of watching cookie's names. Pass empty array if don't want to watch cookies changes.
* @param options
* @param options.doNotParse - don't try parse value as JSON
* @param options.autoUpdateDependencies - automatically update watching dependencies
* @param cookies - universal-cookie instance
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useCookies(
dependencies?: string[] | null,
{
doNotParse,
autoUpdateDependencies,
}?: {
doNotParse?: boolean | undefined
autoUpdateDependencies?: boolean | undefined
},
cookies?: Cookie,
): {
/**
* Reactive get cookie by name. If **autoUpdateDependencies = true** then it will update watching dependencies
*/
get: <T = any>(name: string, options?: CookieGetOptions | undefined) => T
/**
* Reactive get all cookies
*/
getAll: <T = any>(options?: CookieGetOptions | undefined) => T
set: (
name: string,
value: any,
options?: CookieSetOptions | undefined,
) => void
remove: (name: string, options?: CookieSetOptions | undefined) => void
addChangeListener: (callback: CookieChangeListener) => void
removeChangeListener: (callback: CookieChangeListener) => void
}
```

View File

@@ -0,0 +1,102 @@
---
category: Time
---
# useCountdown
Wrapper for `useIntervalFn` that provides a countdown timer.
## Usage
```ts
import { useCountdown } from '@vueuse/core'
const countdownSeconds = 5
const { remaining, start, stop, pause, resume } = useCountdown(countdownSeconds, {
onComplete() {
},
onTick() {
}
})
```
You can use a `ref` to change the initial countdown.
`start()` and `resume()` also accept a new countdown value for the next countdown.
```ts
import { useCountdown } from '@vueuse/core'
import { shallowRef } from 'vue'
const countdown = shallowRef(5)
const { start, reset } = useCountdown(countdown, {
})
// change the countdown value
countdown.value = 10
// start a new countdown with 2 seconds
start(2)
// reset the countdown to 4, but do not start it
reset(4)
// start the countdown with the current value of `countdown`
start()
```
## Type Declarations
```ts
export interface UseCountdownOptions {
/**
* Interval for the countdown in milliseconds. Default is 1000ms.
*/
interval?: MaybeRefOrGetter<number>
/**
* Callback function called when the countdown reaches 0.
*/
onComplete?: () => void
/**
* Callback function called on each tick of the countdown.
*/
onTick?: () => void
/**
* Start the countdown immediately
*
* @default false
*/
immediate?: boolean
}
export interface UseCountdownReturn extends Pausable {
/**
* Current countdown value.
*/
remaining: ShallowRef<number>
/**
* Resets the countdown and repeatsLeft to their initial values.
*/
reset: (countdown?: MaybeRefOrGetter<number>) => void
/**
* Stops the countdown and resets its state.
*/
stop: () => void
/**
* Reset the countdown and start it again.
*/
start: (countdown?: MaybeRefOrGetter<number>) => void
}
/**
* Wrapper for `useIntervalFn` that provides a countdown timer in seconds.
*
* @param initialCountdown
* @param options
*
* @see https://vueuse.org/useCountdown
*/
export declare function useCountdown(
initialCountdown: MaybeRefOrGetter<number>,
options?: UseCountdownOptions,
): UseCountdownReturn
```

View File

@@ -0,0 +1,86 @@
---
category: Utilities
---
# useCounter
Basic counter with utility functions.
## Basic Usage
```ts
import { useCounter } from '@vueuse/core'
const { count, inc, dec, set, reset } = useCounter()
```
## Usage with options
```ts
import { useCounter } from '@vueuse/core'
const { count, inc, dec, set, reset } = useCounter(1, { min: 0, max: 16 })
```
## Type Declarations
```ts
export interface UseCounterOptions {
min?: number
max?: number
}
export interface UseCounterReturn {
/**
* The current value of the counter.
*/
readonly count: Readonly<Ref<number>>
/**
* Increment the counter.
*
* @param {number} [delta=1] The number to increment.
*/
inc: (delta?: number) => void
/**
* Decrement the counter.
*
* @param {number} [delta=1] The number to decrement.
*/
dec: (delta?: number) => void
/**
* Get the current value of the counter.
*/
get: () => number
/**
* Set the counter to a new value.
*
* @param val The new value of the counter.
*/
set: (val: number) => void
/**
* Reset the counter to an initial value.
*/
reset: (val?: number) => number
}
/**
* Basic counter with utility functions.
*
* @see https://vueuse.org/useCounter
* @param [initialValue]
* @param options
*/
export declare function useCounter(
initialValue?: MaybeRef<number>,
options?: UseCounterOptions,
): {
count: Readonly<
| Ref<number, number>
| ShallowRef<number, number>
| WritableComputedRef<number, number>
>
inc: (delta?: number) => number
dec: (delta?: number) => number
get: () => number
set: (val: number) => number
reset: (val?: number) => number
}
```

View File

@@ -0,0 +1,50 @@
---
category: Browser
---
# useCssVar
Manipulate CSS variables
## Usage
```ts
import { useCssVar } from '@vueuse/core'
import { useTemplateRef } from 'vue'
const el = useTemplateRef('el')
const color1 = useCssVar('--color', el)
const elv = useTemplateRef('elv')
const key = ref('--color')
const colorVal = useCssVar(key, elv)
const someEl = useTemplateRef('someEl')
const color2 = useCssVar('--color', someEl, { initialValue: '#eee' })
```
## Type Declarations
```ts
export interface UseCssVarOptions extends ConfigurableWindow {
initialValue?: string
/**
* Use MutationObserver to monitor variable changes
* @default false
*/
observe?: boolean
}
/**
* Manipulate CSS variables.
*
* @see https://vueuse.org/useCssVar
* @param prop
* @param target
* @param options
*/
export declare function useCssVar(
prop: MaybeRefOrGetter<string | null | undefined>,
target?: MaybeElementRef,
options?: UseCssVarOptions,
): ShallowRef<string | undefined, string | undefined>
```

View File

@@ -0,0 +1,61 @@
---
category: Component
---
# useCurrentElement
Get the DOM element of current component as a ref.
## Usage
```ts
import { useCurrentElement } from '@vueuse/core'
const el = useCurrentElement() // ComputedRef<Element>
```
Or pass a specific vue component
```vue
<script setup lang="ts">
import { useCurrentElement, VueInstance } from '@vueuse/core'
import { shallowRef } from 'vue'
const componentRef = shallowRef<VueInstance>(null as unknown as VueInstance)
const el = useCurrentElement(componentRef) // ComputedRef<Element>
</script>
<template>
<div>
<OtherVueComponent ref="componentRef" />
<p>Hello world</p>
</div>
</template>
```
## Caveats
This functions uses [`$el` under the hood](https://vuejs.org/api/component-instance.html#el).
Value of the ref will be `undefined` until the component is mounted.
- For components with a single root element, it will point to that element.
- For components with text root, it will point to the text node.
- For components with multiple root nodes, it will be the placeholder DOM node that Vue uses to keep track of the component's position in the DOM.
It's recommend to only use this function for components with **a single root element**.
## Type Declarations
```ts
export declare function useCurrentElement<
T extends MaybeElement = MaybeElement,
R extends VueInstance = VueInstance,
E extends MaybeElement = MaybeElement extends T
? IsAny<R["$el"]> extends false
? R["$el"]
: T
: T,
>(rootComponent?: MaybeElementRef<R>): ComputedRefWithControl<E>
```

View File

@@ -0,0 +1,75 @@
---
category: Utilities
---
# useCycleList
Cycle through a list of items.
<CourseLink href="https://vueschool.io/lessons/create-an-image-carousel-with-vueuse?friend=vueuse">Learn how to use useCycleList to create an image carousel with this FREE video lesson from Vue School!</CourseLink>
## Usage
```ts
import { useCycleList } from '@vueuse/core'
const { state, next, prev, go } = useCycleList([
'Dog',
'Cat',
'Lizard',
'Shark',
'Whale',
'Dolphin',
'Octopus',
'Seal',
])
console.log(state.value) // 'Dog'
prev()
console.log(state.value) // 'Seal'
go(3)
console.log(state.value) // 'Shark'
```
## Type Declarations
```ts
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 declare function useCycleList<T>(
list: MaybeRefOrGetter<T[]>,
options?: UseCycleListOptions<T>,
): UseCycleListReturn<T>
export interface UseCycleListReturn<T> {
state: ShallowRef<T>
index: WritableComputedRef<number>
next: (n?: number) => T
prev: (n?: number) => T
/**
* Go to a specific index
*/
go: (i: number) => T
}
```

View File

@@ -0,0 +1,142 @@
---
category: Browser
related:
- useColorMode
- usePreferredDark
- useStorage
---
# useDark
Reactive dark mode with auto data persistence.
<CourseLink href="https://vueschool.io/lessons/theming-with-vueuse-usedark-and-usecolormode?friend=vueuse">Learn useDark with this FREE video lesson from Vue School!</CourseLink>
## Basic Usage
```ts
import { useDark, useToggle } from '@vueuse/core'
const isDark = useDark()
const toggleDark = useToggle(isDark)
```
## Behavior
`useDark` combines with `usePreferredDark` and `useStorage`. On start up, it reads the value from localStorage/sessionStorage (the key is configurable) to see if there is a user configured color scheme, if not, it will use users' system preferences. When you change the `isDark` ref, it will update the corresponding element's attribute and then store the preference to storage (default key: `vueuse-color-scheme`) for persistence.
> Please note `useDark` only handles the DOM attribute changes for you to apply proper selector in your CSS. It does NOT handle the actual style, theme or CSS for you.
## Configuration
By default, it uses [Tailwind CSS favored dark mode](https://tailwindcss.com/docs/dark-mode#toggling-dark-mode-manually), which enables dark mode when class `dark` is applied to the `html` tag, for example:
```html
<!--light-->
<html>
...
</html>
<!--dark-->
<html class="dark">
...
</html>
```
Still, you can also customize it to make it work with most CSS frameworks.
For example:
```ts
import { useDark } from '@vueuse/core'
// ---cut---
const isDark = useDark({
selector: 'body',
attribute: 'color-scheme',
valueDark: 'dark',
valueLight: 'light',
})
```
will work like
```html
<!--light-->
<html>
<body color-scheme="light">
...
</body>
</html>
<!--dark-->
<html>
<body color-scheme="dark">
...
</body>
</html>
```
If the configuration above still does not fit your needs, you can use the`onChanged` option to take full control over how you handle updates.
```ts
import { useDark } from '@vueuse/core'
// ---cut---
const isDark = useDark({
onChanged(dark) {
// update the dom, call the API or something
},
})
```
## Component Usage
```vue
<template>
<UseDark v-slot="{ isDark, toggleDark }">
<button @click="toggleDark()">
Is Dark: {{ isDark }}
</button>
</UseDark>
</template>
```
## Type Declarations
```ts
export interface UseDarkOptions
extends Omit<UseColorModeOptions<BasicColorSchema>, "modes" | "onChanged"> {
/**
* Value applying to the target element when isDark=true
*
* @default 'dark'
*/
valueDark?: string
/**
* Value applying to the target element when isDark=false
*
* @default ''
*/
valueLight?: string
/**
* A custom handler for handle the updates.
* When specified, the default behavior will be overridden.
*
* @default undefined
*/
onChanged?: (
isDark: boolean,
defaultHandler: (mode: BasicColorSchema) => void,
mode: BasicColorSchema,
) => void
}
/**
* Reactive dark mode with auto data persistence.
*
* @see https://vueuse.org/useDark
* @param options
*/
export declare function useDark(
options?: UseDarkOptions,
): WritableComputedRef<boolean, boolean>
export type UseDarkReturn = ReturnType<typeof useDark>
```

View File

@@ -0,0 +1,145 @@
---
category: Time
---
# useDateFormat
Get the formatted date according to the string of tokens passed in, inspired
by [dayjs](https://github.com/iamkun/dayjs).
**List of all available formats (HH:mm:ss by default):**
| Format | Output | Description |
| ------ | ------------------------ | --------------------------------------- |
| `Yo` | 2018th | Ordinal formatted year |
| `YY` | 18 | Two-digit year |
| `YYYY` | 2018 | Four-digit year |
| `M` | 1-12 | The month, beginning at 1 |
| `Mo` | 1st, 2nd, ..., 12th | The month, ordinal formatted |
| `MM` | 01-12 | The month, 2-digits |
| `MMM` | Jan-Dec | The abbreviated month name |
| `MMMM` | January-December | The full month name |
| `D` | 1-31 | The day of the month |
| `Do` | 1st, 2nd, ..., 31st | The day of the month, ordinal formatted |
| `DD` | 01-31 | The day of the month, 2-digits |
| `H` | 0-23 | The hour |
| `Ho` | 0th, 1st, 2nd, ..., 23rd | The hour, ordinal formatted |
| `HH` | 00-23 | The hour, 2-digits |
| `h` | 1-12 | The hour, 12-hour clock |
| `ho` | 1st, 2nd, ..., 12th | The hour, 12-hour clock, sorted |
| `hh` | 01-12 | The hour, 12-hour clock, 2-digits |
| `m` | 0-59 | The minute |
| `mo` | 0th, 1st, ..., 59th | The minute, ordinal formatted |
| `mm` | 00-59 | The minute, 2-digits |
| `s` | 0-59 | The second |
| `so` | 0th, 1st, ..., 59th | The second, ordinal formatted |
| `ss` | 00-59 | The second, 2-digits |
| `SSS` | 000-999 | The millisecond, 3-digits |
| `A` | AM PM | The meridiem |
| `AA` | A.M. P.M. | The meridiem, periods |
| `a` | am pm | The meridiem, lowercase |
| `aa` | a.m. p.m. | The meridiem, lowercase and periods |
| `d` | 0-6 | The day of the week, with Sunday as 0 |
| `dd` | S-S | The min name of the day of the week |
| `ddd` | Sun-Sat | The short name of the day of the week |
| `dddd` | Sunday-Saturday | The name of the day of the week |
| `z` | GMT, GMT+1 | The timezone with offset |
| `zz` | GMT, GMT+1 | The timezone with offset |
| `zzz` | GMT, GMT+1 | The timezone with offset |
| `zzzz` | GMT, GMT+01:00 | The long timezone with offset |
- Meridiem is customizable by defining `customMeridiem` in `options`.
## Usage
### Basic
```vue
<script setup lang="ts">
import { useDateFormat, useNow } from '@vueuse/core'
const formatted = useDateFormat(useNow(), 'YYYY-MM-DD HH:mm:ss')
</script>
<template>
<div>{{ formatted }}</div>
</template>
```
### Use with locales
```vue
<script setup lang="ts">
import { useDateFormat, useNow } from '@vueuse/core'
const formatted = useDateFormat(useNow(), 'YYYY-MM-DD (ddd)', { locales: 'en-US' })
</script>
<template>
<div>{{ formatted }}</div>
</template>
```
### Use with custom meridiem
```vue
<script setup lang="ts">
import { useDateFormat } from '@vueuse/core'
function customMeridiem(hours: number, minutes: number, isLowercase?: boolean, hasPeriod?: boolean) {
const m = hours > 11 ? (isLowercase ? 'μμ' : 'ΜΜ') : (isLowercase ? 'πμ' : 'ΠΜ')
return hasPeriod ? m.split('').reduce((acc, current) => acc += `${current}.`, '') : m
}
const am = useDateFormat('2022-01-01 05:05:05', 'hh:mm:ss A', { customMeridiem })
// am.value = '05:05:05 ΠΜ'
const pm = useDateFormat('2022-01-01 17:05:05', 'hh:mm:ss AA', { customMeridiem })
// pm.value = '05:05:05 Μ.Μ.'
</script>
```
## Type Declarations
```ts
export type DateLike = Date | number | string | undefined
export interface UseDateFormatOptions {
/**
* The locale(s) to used for dd/ddd/dddd/MMM/MMMM format
*
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#locales_argument).
*/
locales?: MaybeRefOrGetter<Intl.LocalesArgument>
/**
* A custom function to re-modify the way to display meridiem
*
*/
customMeridiem?: (
hours: number,
minutes: number,
isLowercase?: boolean,
hasPeriod?: boolean,
) => string
}
export declare function formatDate(
date: Date,
formatStr: string,
options?: UseDateFormatOptions,
): string
export declare function normalizeDate(date: DateLike): Date
export type UseDateFormatReturn = ComputedRef<string>
/**
* Get the formatted date according to the string of tokens passed in.
*
* @see https://vueuse.org/useDateFormat
* @param date - The date to format, can either be a `Date` object, a timestamp, or a string
* @param formatStr - The combination of tokens to format the date
* @param options - UseDateFormatOptions
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useDateFormat(
date: MaybeRefOrGetter<DateLike>,
formatStr?: MaybeRefOrGetter<string>,
options?: UseDateFormatOptions,
): UseDateFormatReturn
```

View File

@@ -0,0 +1,100 @@
---
category: Utilities
related: useThrottleFn
---
# useDebounceFn
Debounce execution of a function.
> Debounce is an overloaded waiter: if you keep asking, your requests will be ignored until you stop and give them some time to think about your latest inquiry.
## Usage
```ts
import { useDebounceFn, useEventListener } from '@vueuse/core'
const debouncedFn = useDebounceFn(() => {
// do something
}, 1000)
useEventListener(window, 'resize', debouncedFn)
```
You can also pass a 3rd parameter to this, with a maximum wait time, similar to [lodash debounce](https://lodash.com/docs/4.17.15#debounce)
```ts
import { useDebounceFn, useEventListener } from '@vueuse/core'
// If no invokation after 5000ms due to repeated input,
// the function will be called anyway.
const debouncedFn = useDebounceFn(() => {
// do something
}, 1000, { maxWait: 5000 })
useEventListener(window, 'resize', debouncedFn)
```
Optionally, you can get the return value of the function using promise operations.
```ts
import { useDebounceFn } from '@vueuse/core'
const debouncedRequest = useDebounceFn(() => 'response', 1000)
debouncedRequest().then((value) => {
console.log(value) // 'response'
})
// or use async/await
async function doRequest() {
const value = await debouncedRequest()
console.log(value) // 'response'
}
```
Since unhandled rejection error is quite annoying when developer doesn't need the return value, the promise will **NOT** be rejected if the function is canceled **by default**. You need to specify the option `rejectOnCancel: true` to capture the rejection.
```ts
import { useDebounceFn } from '@vueuse/core'
const debouncedRequest = useDebounceFn(() => 'response', 1000, { rejectOnCancel: true })
debouncedRequest()
.then((value) => {
// do something
})
.catch(() => {
// do something when canceled
})
// calling it again will cancel the previous request and gets rejected
setTimeout(debouncedRequest, 500)
```
## Recommended Reading
- [**Debounce vs Throttle**: Definitive Visual Guide](https://kettanaito.com/blog/debounce-vs-throttle)
## Type Declarations
```ts
export type UseDebounceFnReturn<T extends FunctionArgs> = PromisifyFn<T>
/**
* Debounce execution of a function.
*
* @see https://vueuse.org/useDebounceFn
* @param fn A function to be executed after delay milliseconds debounced.
* @param ms A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful.
* @param options Options
*
* @return A new, debounce, function.
*
* @__NO_SIDE_EFFECTS__
*/
export declare function useDebounceFn<T extends FunctionArgs>(
fn: T,
ms?: MaybeRefOrGetter<number>,
options?: DebounceFilterOptions,
): UseDebounceFnReturn<T>
```

Some files were not shown because too many files have changed in this diff Show More