Renderless Vue.js components that expose VueUse composable functionality through declarative template-based interfaces
—
Components and directives for handling browser events like clicks, key presses, and long press gestures.
Detects clicks outside of the wrapped element and emits trigger events.
/**
* Component that detects clicks outside the wrapped element
* @example
* <OnClickOutside @trigger="handleClickOutside">
* <div>Click outside this to trigger event</div>
* </OnClickOutside>
*/
interface OnClickOutsideProps extends RenderableComponent {
/** Options for configuring click outside behavior */
options?: OnClickOutsideOptions;
}
interface OnClickOutsideOptions {
/** List of elements that should not trigger the event */
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;
/** Window object to listen on @default defaultWindow */
window?: Window;
}
/** Component events */
interface OnClickOutsideEmits {
/** Triggered when click occurs outside the element */
trigger: (event: PointerEvent | FocusEvent) => void;
}Usage Examples:
<template>
<!-- Basic usage -->
<OnClickOutside @trigger="handleClickOutside">
<div class="modal">Modal content</div>
</OnClickOutside>
<!-- With options -->
<OnClickOutside
@trigger="handleClickOutside"
:options="{ ignore: ['.ignore-element'], detectIframe: true }"
>
<div class="dropdown">Dropdown content</div>
</OnClickOutside>
<!-- Custom wrapper element -->
<OnClickOutside as="section" @trigger="handleClickOutside">
<div>Custom section wrapper</div>
</OnClickOutside>
</template>
<script setup>
import { OnClickOutside } from '@vueuse/components';
function handleClickOutside(event) {
console.log('Clicked outside!', event);
}
</script>Directive for click outside detection without component wrapper.
/**
* Directive for detecting clicks outside an element
* @example
* <div v-on-click-outside="handler">Content</div>
* <div v-on-click-outside="[handler, options]">With options</div>
*/
type OnClickOutsideHandler = (event: PointerEvent | FocusEvent) => void;
interface VOnClickOutsideValue {
/** Simple handler function */
handler: OnClickOutsideHandler;
/** Handler with options tuple */
handlerWithOptions: [OnClickOutsideHandler, OnClickOutsideOptions];
}
/** Directive modifiers */
interface OnClickOutsideModifiers {
/** Disable capture mode (use bubble instead) */
bubble: boolean;
}Usage Examples:
<template>
<!-- Simple usage -->
<div v-on-click-outside="handleClickOutside">
Click outside me
</div>
<!-- With options -->
<div v-on-click-outside="[handleClickOutside, { capture: false }]">
With custom options
</div>
<!-- Using bubble modifier -->
<div v-on-click-outside.bubble="handleClickOutside">
Using bubble phase
</div>
</template>
<script setup>
import { vOnClickOutside } from '@vueuse/components';
function handleClickOutside(event) {
console.log('Clicked outside!', event);
}
</script>Directive for keyboard event handling.
/**
* Directive for handling keyboard events
* @example
* <input v-on-key-stroke:enter="handleEnter" />
* <div v-on-key-stroke="[handleKey, { eventName: 'keydown' }]">
*/
type OnKeyStrokeHandler = (event: KeyboardEvent) => void;
interface OnKeyStrokeOptions {
/** Key or keys to listen for */
key?: string | string[];
/** Event name to listen for @default 'keydown' */
eventName?: 'keydown' | 'keypress' | 'keyup';
/** Target element @default window */
target?: MaybeRefOrGetter<EventTarget | null | undefined>;
/** Auto-repeat behavior @default false */
autoRepeat?: boolean;
/** Window object @default defaultWindow */
window?: Window;
}
interface VOnKeyStrokeValue {
/** Simple handler function */
handler: OnKeyStrokeHandler;
/** Handler with options tuple */
handlerWithOptions: [OnKeyStrokeHandler, OnKeyStrokeOptions];
}Usage Examples:
<template>
<!-- Listen for Enter key -->
<input v-on-key-stroke:enter="handleEnter" />
<!-- Listen for Escape key -->
<div v-on-key-stroke:escape="handleEscape">
Press Escape
</div>
<!-- With options -->
<div v-on-key-stroke="[handleKeyDown, { key: 'Space', eventName: 'keyup' }]">
Custom key handling
</div>
<!-- Multiple keys -->
<input v-on-key-stroke="[handleKeys, { key: ['Enter', 'Tab'] }]" />
</template>
<script setup>
import { vOnKeyStroke } from '@vueuse/components';
function handleEnter(event) {
console.log('Enter pressed', event);
}
function handleEscape(event) {
console.log('Escape pressed', event);
}
function handleKeyDown(event) {
console.log('Space released', event);
}
function handleKeys(event) {
console.log('Enter or Tab pressed', event);
}
</script>Detects long press gestures and emits trigger events.
/**
* Component that detects long press gestures
* @example
* <OnLongPress @trigger="handleLongPress" :options="{ delay: 500 }">
* <button>Long press me</button>
* </OnLongPress>
*/
interface OnLongPressProps extends RenderableComponent {
/** Options for configuring long press behavior */
options?: OnLongPressOptions;
}
interface OnLongPressOptions {
/** Delay in ms before trigger @default 500 */
delay?: number;
/** Modifiers that need to be pressed */
modifiers?: OnLongPressModifiers;
/** Prevent context menu @default true */
preventContextMenu?: boolean;
}
interface OnLongPressModifiers {
stop?: boolean;
once?: boolean;
prevent?: boolean;
capture?: boolean;
self?: boolean;
}
/** Component events */
interface OnLongPressEmits {
/** Triggered when long press is detected */
trigger: (event: PointerEvent) => void;
}Usage Examples:
<template>
<!-- Basic usage -->
<OnLongPress @trigger="handleLongPress">
<button>Long press this button</button>
</OnLongPress>
<!-- Custom delay -->
<OnLongPress @trigger="handleLongPress" :options="{ delay: 1000 }">
<button>Hold for 1 second</button>
</OnLongPress>
<!-- With modifiers -->
<OnLongPress
@trigger="handleLongPress"
:options="{
delay: 300,
modifiers: { prevent: true, stop: true },
preventContextMenu: false
}"
>
<button>Custom long press</button>
</OnLongPress>
</template>
<script setup>
import { OnLongPress } from '@vueuse/components';
function handleLongPress(event) {
console.log('Long press detected!', event);
}
</script>Directive for long press detection without component wrapper.
/**
* Directive for detecting long press gestures
* @example
* <button v-on-long-press="handler">Long press me</button>
* <div v-on-long-press="[handler, { delay: 1000 }]">Custom delay</div>
*/
type OnLongPressHandler = (event: PointerEvent) => void;
interface VOnLongPressValue {
/** Simple handler function */
handler: OnLongPressHandler;
/** Handler with options tuple */
handlerWithOptions: [OnLongPressHandler, OnLongPressOptions];
}Usage Examples:
<template>
<!-- Simple usage -->
<button v-on-long-press="handleLongPress">
Long press me
</button>
<!-- With custom delay -->
<div v-on-long-press="[handleLongPress, { delay: 800 }]">
Hold for 800ms
</div>
<!-- Prevent context menu -->
<img
v-on-long-press="[handleLongPress, { preventContextMenu: false }]"
src="image.jpg"
alt="Long press to save"
/>
</template>
<script setup>
import { vOnLongPress } from '@vueuse/components';
function handleLongPress(event) {
console.log('Long press detected!', event);
}
</script>/** Common types used across browser event handlers */
type MaybeElementRef = HTMLElement | null | undefined;
type MaybeRefOrGetter<T> = T | Ref<T> | (() => T);
interface RenderableComponent {
/** The element that the component should be rendered as @default 'div' */
as?: object | string;
}Install with Tessl CLI
npx tessl i tessl/npm-vueuse--components