vuse-directive 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,114 @@
1
+ # vue-directive
2
+
3
+ A collection of Vue 3 custom directives
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install vuse-directive
9
+ # or
10
+ pnpm add vuse-directive
11
+ # or
12
+ yarn add vuse-directive
13
+ ```
14
+
15
+ ## Getting Started
16
+
17
+ ### Global Registration
18
+
19
+ ```ts
20
+ import { createApp } from 'vue'
21
+ import App from './App.vue'
22
+ import { throttleClick } from 'vuse-directive'
23
+
24
+ const app = createApp(App)
25
+ app.directive('throttle-click', throttleClick)
26
+ app.mount('#app')
27
+ ```
28
+
29
+ ### On-demand Import
30
+
31
+ ```ts
32
+ import { throttleClick } from 'vuse-directive'
33
+ ```
34
+
35
+ ---
36
+
37
+ ## Directives
38
+
39
+ ### `v-throttle-click` — Throttled Click
40
+
41
+ Throttles click events to prevent repeated triggers within a short period. Supports custom delay, async lock, trailing call, and Vue modifier pass-through.
42
+
43
+ #### Basic Usage
44
+
45
+ ```vue
46
+ <!-- Default throttle interval: 300ms -->
47
+ <button v-throttle-click="handleClick">Submit</button>
48
+
49
+ <!-- Custom interval (in ms) -->
50
+ <button v-throttle-click:500="handleClick">Submit</button>
51
+
52
+ <!-- Interval 0: no throttle, modifiers still apply -->
53
+ <button v-throttle-click:0="handleClick">Submit</button>
54
+ ```
55
+
56
+ #### Modifiers
57
+
58
+ | Modifier | Description |
59
+ |----------|-------------|
60
+ | `.once` | Fire only once; all subsequent clicks are ignored |
61
+ | `.trailing` | If a click is blocked during cooldown, it fires once after the cooldown ends |
62
+ | `.async` | Async mode: new clicks are blocked until the previous callback's Promise resolves/rejects |
63
+ | `.right` | Listen to `contextmenu` (right-click) instead of `click` |
64
+ | `.capture` | Use capture phase for the event listener |
65
+ | `.passive` | Use passive listener mode for better scroll performance |
66
+ | `.stop` | Stop event propagation (passed to Vue's `withModifiers`) |
67
+ | `.prevent` | Prevent default behavior (passed to Vue's `withModifiers`) |
68
+ | `.self` | Only trigger when the event target is the element itself |
69
+
70
+ #### Examples
71
+
72
+ ```vue
73
+ <script setup lang="ts">
74
+ async function submitForm() {
75
+ await fetch('/api/submit', { method: 'POST' })
76
+ }
77
+ </script>
78
+
79
+ <template>
80
+ <!-- Async + trailing: blocks repeated clicks during async call,
81
+ fires the last blocked click after the call completes -->
82
+ <button v-throttle-click:1000.async.trailing="submitForm">
83
+ Submit
84
+ </button>
85
+
86
+ <!-- Fire once only -->
87
+ <button v-throttle-click.once="handleClick">Click once</button>
88
+
89
+ <!-- Throttle right-click -->
90
+ <div v-throttle-click.right="openMenu">Right-click area</div>
91
+ </template>
92
+ ```
93
+
94
+ #### Callback Signature
95
+
96
+ ```ts
97
+ type ClickHandler = (event: MouseEvent, ...args: unknown[]) => any
98
+ ```
99
+
100
+ The binding value receives a `MouseEvent` as the first argument:
101
+
102
+ ```ts
103
+ function handleClick(e: MouseEvent) {
104
+ console.log('clicked', e)
105
+ }
106
+ ```
107
+
108
+ In async mode, return a `Promise` to activate the async lock:
109
+
110
+ ```ts
111
+ async function handleAsync(e: MouseEvent) {
112
+ await fetch('/api/submit', { method: 'POST' })
113
+ }
114
+ ```
@@ -0,0 +1,4 @@
1
+ import { Directive } from 'vue';
2
+
3
+ declare const throttleClick: Directive;
4
+ export default throttleClick;
@@ -0,0 +1,3 @@
1
+ import { default as throttleClick } from './directives/ThrottleClick';
2
+
3
+ export { throttleClick };
@@ -0,0 +1,63 @@
1
+ import { withModifiers as d } from "vue";
2
+ const f = {
3
+ mounted(t, e) {
4
+ t._latestBinding = e, t._throttleTimer = null, t._hasCalledOnce = !1, t._trailingEvent = null, t._asyncPending = !1, t._unmounted = !1;
5
+ const s = Object.getOwnPropertyNames(
6
+ e.modifiers
7
+ );
8
+ t._throttleHandler = d((i) => {
9
+ const { modifiers: n, value: r } = t._latestBinding;
10
+ if (n.once && t._hasCalledOnce)
11
+ return;
12
+ if (n.async && t._asyncPending) {
13
+ n.trailing && (t._trailingEvent = i);
14
+ return;
15
+ }
16
+ const a = typeof t._latestBinding.arg > "u" ? 300 : Number(t._latestBinding.arg);
17
+ if (a > 0 && t._throttleTimer) {
18
+ n.trailing && (t._trailingEvent = i);
19
+ return;
20
+ }
21
+ const o = (_) => {
22
+ t._hasCalledOnce = !0, t._trailingEvent = null, n.async ? (t._asyncPending = !0, Promise.resolve(r == null ? void 0 : r(_)).finally(() => {
23
+ t._unmounted || (t._asyncPending = !1, n.trailing && t._trailingEvent && t._throttleHandler(t._trailingEvent));
24
+ })) : r == null || r(_);
25
+ };
26
+ if (a === 0) {
27
+ o(i);
28
+ return;
29
+ }
30
+ o(i), t._throttleTimer = setTimeout(() => {
31
+ t._throttleTimer = null, !n.async && n.trailing && t._trailingEvent && (t._throttleHandler(t._trailingEvent), t._trailingEvent = null);
32
+ }, a);
33
+ }, s), t._eventName = e.modifiers.right ? "contextmenu" : "click", t._listenerOptions = {
34
+ capture: e.modifiers.capture ?? !1,
35
+ passive: e.modifiers.passive ?? !1
36
+ }, t.addEventListener(
37
+ t._eventName,
38
+ t._throttleHandler,
39
+ t._listenerOptions
40
+ );
41
+ },
42
+ updated(t, e) {
43
+ const s = e.modifiers.capture ?? !1, i = e.modifiers.passive ?? !1, n = t._listenerOptions;
44
+ (s !== n.capture || i !== n.passive) && (t.removeEventListener(t._eventName, t._throttleHandler, n), t._listenerOptions = {
45
+ capture: s,
46
+ passive: i
47
+ }, t.addEventListener(
48
+ t._eventName,
49
+ t._throttleHandler,
50
+ t._listenerOptions
51
+ )), t._latestBinding = e;
52
+ },
53
+ unmounted(t) {
54
+ t.removeEventListener(
55
+ t._eventName,
56
+ t._throttleHandler,
57
+ t._listenerOptions
58
+ ), t._throttleTimer && clearTimeout(t._throttleTimer), t._unmounted = !0, t._trailingEvent = null;
59
+ }
60
+ };
61
+ export {
62
+ f as throttleClick
63
+ };
@@ -0,0 +1 @@
1
+ (function(i,a){typeof exports=="object"&&typeof module<"u"?a(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],a):(i=typeof globalThis<"u"?globalThis:i||self,a(i.VueDirective={},i.Vue))})(this,function(i,a){"use strict";const f={mounted(t,n){t._latestBinding=n,t._throttleTimer=null,t._hasCalledOnce=!1,t._trailingEvent=null,t._asyncPending=!1,t._unmounted=!1;const o=Object.getOwnPropertyNames(n.modifiers);t._throttleHandler=a.withModifiers(r=>{const{modifiers:e,value:s}=t._latestBinding;if(e.once&&t._hasCalledOnce)return;if(e.async&&t._asyncPending){e.trailing&&(t._trailingEvent=r);return}const d=typeof t._latestBinding.arg>"u"?300:Number(t._latestBinding.arg);if(d>0&&t._throttleTimer){e.trailing&&(t._trailingEvent=r);return}const _=u=>{t._hasCalledOnce=!0,t._trailingEvent=null,e.async?(t._asyncPending=!0,Promise.resolve(s==null?void 0:s(u)).finally(()=>{t._unmounted||(t._asyncPending=!1,e.trailing&&t._trailingEvent&&t._throttleHandler(t._trailingEvent))})):s==null||s(u)};if(d===0){_(r);return}_(r),t._throttleTimer=setTimeout(()=>{t._throttleTimer=null,!e.async&&e.trailing&&t._trailingEvent&&(t._throttleHandler(t._trailingEvent),t._trailingEvent=null)},d)},o),t._eventName=n.modifiers.right?"contextmenu":"click",t._listenerOptions={capture:n.modifiers.capture??!1,passive:n.modifiers.passive??!1},t.addEventListener(t._eventName,t._throttleHandler,t._listenerOptions)},updated(t,n){const o=n.modifiers.capture??!1,r=n.modifiers.passive??!1,e=t._listenerOptions;(o!==e.capture||r!==e.passive)&&(t.removeEventListener(t._eventName,t._throttleHandler,e),t._listenerOptions={capture:o,passive:r},t.addEventListener(t._eventName,t._throttleHandler,t._listenerOptions)),t._latestBinding=n},unmounted(t){t.removeEventListener(t._eventName,t._throttleHandler,t._listenerOptions),t._throttleTimer&&clearTimeout(t._throttleTimer),t._unmounted=!0,t._trailingEvent=null}};i.throttleClick=f,Object.defineProperty(i,Symbol.toStringTag,{value:"Module"})});
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "vuse-directive",
3
+ "version": "0.0.3",
4
+ "description": "Vue 3 directives collection",
5
+ "type": "module",
6
+ "main": "./dist/vue-directive.umd.cjs",
7
+ "module": "./dist/vue-directive.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/vue-directive.js",
12
+ "require": "./dist/vue-directive.umd.cjs",
13
+ "types": "./dist/index.d.ts"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "test": "jest",
21
+ "build": "vite build",
22
+ "dev": "vite",
23
+ "format": "biome format --write .",
24
+ "format:check": "biome format .",
25
+ "prepublishOnly": "npm run build",
26
+ "release": "node scripts/publish.js"
27
+ },
28
+ "peerDependencies": {
29
+ "vue": "^3.0.0"
30
+ },
31
+ "devDependencies": {
32
+ "@biomejs/biome": "^2.0.0",
33
+ "@types/jest": "^30.0.0",
34
+ "@types/node": "^25.3.0",
35
+ "@vue/test-utils": "^2.4.6",
36
+ "jest": "^30.2.0",
37
+ "jest-environment-jsdom": "^30.2.0",
38
+ "ts-jest": "^29.4.6",
39
+ "ts-node": "^10.9.2",
40
+ "typescript": "^5.3.3",
41
+ "vite": "^5.0.0",
42
+ "vite-plugin-dts": "^3.6.0",
43
+ "vue": "^3.4.0",
44
+ "vue-tsc": "^1.8.0"
45
+ },
46
+ "keywords": [
47
+ "vue",
48
+ "vue3",
49
+ "directive",
50
+ "directives"
51
+ ],
52
+ "sideEffects": false,
53
+ "author": "Stafan Hulk",
54
+ "license": "MIT",
55
+ "repository": {
56
+ "type": "git",
57
+ "url": "https://github.com/stafanhulk/vue-directive.git"
58
+ },
59
+ "homepage": "https://github.com/stafanhulk/vue-directive#readme",
60
+ "bugs": {
61
+ "url": "https://github.com/stafanhulk/vue-directive/issues"
62
+ },
63
+ "engines": {
64
+ "node": ">=18"
65
+ }
66
+ }