directix 1.4.1 → 1.6.0
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 +912 -8
- package/dist/index.cjs +4998 -618
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1629 -17
- package/dist/index.iife.js +4889 -529
- package/dist/index.iife.js.map +1 -1
- package/dist/index.iife.min.js +2 -2
- package/dist/index.mjs +4890 -530
- package/dist/index.mjs.map +1 -1
- package/dist/nuxt/index.cjs +25083 -0
- package/dist/nuxt/index.cjs.map +7 -0
- package/dist/nuxt/index.d.ts +40 -0
- package/dist/nuxt/index.mjs +8736 -0
- package/dist/nuxt/index.mjs.map +7 -0
- package/dist/nuxt/runtime/plugin.mjs +8708 -0
- package/dist/nuxt/runtime/plugin.mjs.map +7 -0
- package/package.json +83 -6
package/README.md
CHANGED
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/directix)
|
|
5
5
|
[](https://github.com/saqqdy/directix/blob/master/LICENSE)
|
|
6
6
|
|
|
7
|
-
**[中文文档](README_CN.md)**
|
|
7
|
+
**English** | **[中文文档](README_CN.md)**
|
|
8
8
|
|
|
9
9
|
A comprehensive, easy-to-use, and high-performance Vue custom directives library supporting both Vue 2 and Vue 3.
|
|
10
10
|
|
|
11
11
|
## Features
|
|
12
12
|
|
|
13
|
-
- 🎯 **Comprehensive** -
|
|
13
|
+
- 🎯 **Comprehensive** - 57 commonly used directives and 57 composables
|
|
14
14
|
- 🔄 **Vue 2/3 Compatible** - Single codebase supports both Vue 2 and Vue 3
|
|
15
15
|
- 📦 **Tree-shakable** - Import only what you need
|
|
16
16
|
- 🔒 **TypeScript** - Full TypeScript support with type definitions
|
|
@@ -22,12 +22,12 @@ A comprehensive, easy-to-use, and high-performance Vue custom directives library
|
|
|
22
22
|
|
|
23
23
|
## Online Demo
|
|
24
24
|
|
|
25
|
-
Try it online with StackBlitz:
|
|
25
|
+
Try it online with StackBlitz or CodeSandbox:
|
|
26
26
|
|
|
27
|
-
| Demo |
|
|
28
|
-
|
|
29
|
-
| Vue 3 | [](https://stackblitz.com/github/saqqdy/directix/tree/master/examples/vue3) |
|
|
30
|
-
| Vue 2 | [](https://stackblitz.com/github/saqqdy/directix/tree/master/examples/vue2) |
|
|
27
|
+
| Demo | StackBlitz | CodeSandbox |
|
|
28
|
+
|------|------------|-------------|
|
|
29
|
+
| Vue 3 | [](https://stackblitz.com/github/saqqdy/directix/tree/master/examples/vue3) | [](https://codesandbox.io/p/sandbox/github/saqqdy/directix/tree/master/examples/vue3) |
|
|
30
|
+
| Vue 2 | [](https://stackblitz.com/github/saqqdy/directix/tree/master/examples/vue2) | [](https://codesandbox.io/p/sandbox/github/saqqdy/directix/tree/master/examples/vue2) |
|
|
31
31
|
|
|
32
32
|
## Installation
|
|
33
33
|
|
|
@@ -128,6 +128,66 @@ const { run: debouncedSearch } = useDebounce({ handler: search, wait: 500 })
|
|
|
128
128
|
|
|
129
129
|
See the [Composables](#composables) section below for all available composables.
|
|
130
130
|
|
|
131
|
+
## Nuxt Integration
|
|
132
|
+
|
|
133
|
+
Directix provides a Nuxt module for seamless integration with Nuxt 3 applications.
|
|
134
|
+
|
|
135
|
+
### Installation
|
|
136
|
+
|
|
137
|
+
The Nuxt module is included in the main package. Simply add it to your `nuxt.config.ts`:
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
// nuxt.config.ts
|
|
141
|
+
export default defineNuxtConfig({
|
|
142
|
+
modules: ['directix/nuxt'],
|
|
143
|
+
|
|
144
|
+
directix: {
|
|
145
|
+
// Enable/disable the module (default: true)
|
|
146
|
+
enabled: true,
|
|
147
|
+
|
|
148
|
+
// Only include specific directives (optional)
|
|
149
|
+
include: ['v-click-outside', 'v-copy', 'v-debounce'],
|
|
150
|
+
|
|
151
|
+
// Or exclude specific directives (optional)
|
|
152
|
+
exclude: ['v-ripple'],
|
|
153
|
+
|
|
154
|
+
// Default options for directives (optional)
|
|
155
|
+
directiveOptions: {
|
|
156
|
+
'v-permission': {
|
|
157
|
+
config: {
|
|
158
|
+
getPermissions: () => ['read', 'write']
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
|
|
163
|
+
// Auto-import composables (default: true)
|
|
164
|
+
autoImportComposables: true
|
|
165
|
+
}
|
|
166
|
+
})
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Usage in Nuxt
|
|
170
|
+
|
|
171
|
+
Directives are automatically registered and composables are auto-imported:
|
|
172
|
+
|
|
173
|
+
```vue
|
|
174
|
+
<template>
|
|
175
|
+
<div v-click-outside="handleClose">
|
|
176
|
+
<button v-copy="text">Copy</button>
|
|
177
|
+
</div>
|
|
178
|
+
</template>
|
|
179
|
+
|
|
180
|
+
<script setup>
|
|
181
|
+
// Composables are auto-imported, no need to import manually
|
|
182
|
+
const { copy, copied } = useCopy({ source: text })
|
|
183
|
+
const { isHovering } = useHover({ onEnter: handleEnter })
|
|
184
|
+
</script>
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### SSR Compatibility
|
|
188
|
+
|
|
189
|
+
Directives that are not SSR-compatible will only run on the client side. The Nuxt module handles this automatically.
|
|
190
|
+
|
|
131
191
|
## Available Directives
|
|
132
192
|
|
|
133
193
|
### Event Directives
|
|
@@ -214,6 +274,38 @@ See the [Composables](#composables) section below for all available composables.
|
|
|
214
274
|
| `v-countdown` | Countdown timer display | ✅ |
|
|
215
275
|
| `v-print` | Print element content | ❌ |
|
|
216
276
|
| `v-watermark` | Watermark overlay | ✅ |
|
|
277
|
+
| `v-skeleton` | Skeleton loading placeholder | ✅ |
|
|
278
|
+
| `v-progress` | Progress bar animation | ❌ |
|
|
279
|
+
| `v-counter` | Animated number counter | ✅ |
|
|
280
|
+
|
|
281
|
+
### Gesture Directives
|
|
282
|
+
|
|
283
|
+
| Directive | Description | SSR |
|
|
284
|
+
|-----------|-------------|-----|
|
|
285
|
+
| `v-pan` | Pan/drag gesture | ❌ |
|
|
286
|
+
| `v-pinch` | Pinch/zoom gesture | ❌ |
|
|
287
|
+
| `v-rotate-gesture` | Rotation gesture | ❌ |
|
|
288
|
+
|
|
289
|
+
### Visual Effect Directives
|
|
290
|
+
|
|
291
|
+
| Directive | Description | SSR |
|
|
292
|
+
|-----------|-------------|-----|
|
|
293
|
+
| `v-blur` | Background blur overlay | ❌ |
|
|
294
|
+
| `v-fade` | Fade in/out transition | ✅ |
|
|
295
|
+
| `v-parallax` | Parallax scrolling effect | ❌ |
|
|
296
|
+
| `v-lottie` | Lottie animation player | ❌ |
|
|
297
|
+
| `v-typewriter` | Typewriter animation | ✅ |
|
|
298
|
+
| `v-click-wave` | Click wave effect | ❌ |
|
|
299
|
+
|
|
300
|
+
### Data Directives
|
|
301
|
+
|
|
302
|
+
| Directive | Description | SSR |
|
|
303
|
+
|-----------|-------------|-----|
|
|
304
|
+
| `v-export` | Export data (CSV/JSON/HTML) | ❌ |
|
|
305
|
+
| `v-highlight` | Keyword highlighting | ✅ |
|
|
306
|
+
| `v-emoji` | Emoji input filter | ❌ |
|
|
307
|
+
| `v-context-menu` | Right-click context menu | ❌ |
|
|
308
|
+
| `v-fullscreen` | Fullscreen toggle | ❌ |
|
|
217
309
|
|
|
218
310
|
> ✅ = SSR compatible | ❌ = Not SSR compatible
|
|
219
311
|
|
|
@@ -290,6 +382,23 @@ Every directive has a corresponding composable function for use with the Composi
|
|
|
290
382
|
| `useCountdown` | Countdown timer |
|
|
291
383
|
| `usePrint` | Print content |
|
|
292
384
|
| `useWatermark` | Watermark overlay |
|
|
385
|
+
| `useSkeleton` | Skeleton loading state |
|
|
386
|
+
| `useProgress` | Progress bar control |
|
|
387
|
+
| `useCounter` | Animated number counter |
|
|
388
|
+
| `usePan` | Pan gesture detection |
|
|
389
|
+
| `usePinch` | Pinch gesture detection |
|
|
390
|
+
| `useRotateGesture` | Rotation gesture detection |
|
|
391
|
+
| `useBlur` | Blur overlay control |
|
|
392
|
+
| `useFade` | Fade transition control |
|
|
393
|
+
| `useParallax` | Parallax scrolling |
|
|
394
|
+
| `useLottie` | Lottie animation control |
|
|
395
|
+
| `useTypewriter` | Typewriter effect |
|
|
396
|
+
| `useExport` | Data export utilities |
|
|
397
|
+
| `useHighlight` | Keyword highlighting |
|
|
398
|
+
| `useEmoji` | Emoji filtering |
|
|
399
|
+
| `useContextMenu` | Context menu control |
|
|
400
|
+
| `useFullscreen` | Fullscreen mode control |
|
|
401
|
+
| `useClickWave` | Click wave effect |
|
|
293
402
|
|
|
294
403
|
### Composable Usage Example
|
|
295
404
|
|
|
@@ -343,12 +452,19 @@ Detect clicks outside an element, useful for closing dropdowns, modals, etc.
|
|
|
343
452
|
|
|
344
453
|
<script setup>
|
|
345
454
|
import { ref } from 'vue'
|
|
455
|
+
import { useClickOutside } from 'directix'
|
|
346
456
|
|
|
347
457
|
const show = ref(false)
|
|
348
458
|
|
|
349
459
|
function closeDropdown() {
|
|
350
460
|
show.value = false
|
|
351
461
|
}
|
|
462
|
+
|
|
463
|
+
// Composable usage
|
|
464
|
+
const containerRef = ref()
|
|
465
|
+
useClickOutside(containerRef, () => {
|
|
466
|
+
show.value = false
|
|
467
|
+
})
|
|
352
468
|
</script>
|
|
353
469
|
```
|
|
354
470
|
|
|
@@ -368,6 +484,9 @@ Copy text to clipboard with a simple directive.
|
|
|
368
484
|
</template>
|
|
369
485
|
|
|
370
486
|
<script setup>
|
|
487
|
+
import { ref } from 'vue'
|
|
488
|
+
import { useCopy } from 'directix'
|
|
489
|
+
|
|
371
490
|
const textToCopy = 'Hello, World!'
|
|
372
491
|
|
|
373
492
|
function handleSuccess(text) {
|
|
@@ -377,6 +496,10 @@ function handleSuccess(text) {
|
|
|
377
496
|
function handleError(error) {
|
|
378
497
|
console.error('Copy failed:', error)
|
|
379
498
|
}
|
|
499
|
+
|
|
500
|
+
// Composable usage
|
|
501
|
+
const sourceText = ref('Hello World')
|
|
502
|
+
const { copy, copied } = useCopy({ source: sourceText })
|
|
380
503
|
</script>
|
|
381
504
|
```
|
|
382
505
|
|
|
@@ -397,9 +520,17 @@ Debounce event handlers to limit execution frequency.
|
|
|
397
520
|
</template>
|
|
398
521
|
|
|
399
522
|
<script setup>
|
|
523
|
+
import { useDebounce } from 'directix'
|
|
524
|
+
|
|
400
525
|
function handleInput(event) {
|
|
401
526
|
console.log('Debounced input:', event.target.value)
|
|
402
527
|
}
|
|
528
|
+
|
|
529
|
+
// Composable usage
|
|
530
|
+
const { run: debouncedSearch, cancel } = useDebounce({
|
|
531
|
+
handler: (query) => fetchResults(query),
|
|
532
|
+
wait: 500
|
|
533
|
+
})
|
|
403
534
|
</script>
|
|
404
535
|
```
|
|
405
536
|
|
|
@@ -422,9 +553,17 @@ Throttle event handlers to limit execution frequency.
|
|
|
422
553
|
</template>
|
|
423
554
|
|
|
424
555
|
<script setup>
|
|
556
|
+
import { useThrottle } from 'directix'
|
|
557
|
+
|
|
425
558
|
function handleClick() {
|
|
426
559
|
console.log('Throttled click')
|
|
427
560
|
}
|
|
561
|
+
|
|
562
|
+
// Composable usage
|
|
563
|
+
const { run: throttledScroll, cancel } = useThrottle({
|
|
564
|
+
handler: (position) => updatePosition(position),
|
|
565
|
+
wait: 100
|
|
566
|
+
})
|
|
428
567
|
</script>
|
|
429
568
|
```
|
|
430
569
|
|
|
@@ -440,6 +579,13 @@ Auto focus an element when mounted.
|
|
|
440
579
|
<!-- With options -->
|
|
441
580
|
<input v-focus="{ focus: true, refocus: true }" />
|
|
442
581
|
</template>
|
|
582
|
+
|
|
583
|
+
<script setup>
|
|
584
|
+
import { useFocus } from 'directix'
|
|
585
|
+
|
|
586
|
+
// Composable usage
|
|
587
|
+
const { focus, blur, hasFocus } = useFocus()
|
|
588
|
+
</script>
|
|
443
589
|
```
|
|
444
590
|
|
|
445
591
|
### v-permission
|
|
@@ -466,7 +612,7 @@ Control element visibility based on user permissions.
|
|
|
466
612
|
</template>
|
|
467
613
|
|
|
468
614
|
<script setup>
|
|
469
|
-
import { configurePermission } from 'directix'
|
|
615
|
+
import { configurePermission, usePermission } from 'directix'
|
|
470
616
|
|
|
471
617
|
configurePermission({
|
|
472
618
|
getPermissions: () => ['read', 'write'],
|
|
@@ -476,6 +622,10 @@ configurePermission({
|
|
|
476
622
|
editor: ['read', 'write', 'edit']
|
|
477
623
|
}
|
|
478
624
|
})
|
|
625
|
+
|
|
626
|
+
// Composable usage
|
|
627
|
+
const { hasPermission, hasAnyPermission, hasAllPermissions } = usePermission()
|
|
628
|
+
const canEdit = hasPermission('edit')
|
|
479
629
|
</script>
|
|
480
630
|
```
|
|
481
631
|
|
|
@@ -491,6 +641,16 @@ Lazy load images when they enter the viewport.
|
|
|
491
641
|
<!-- With placeholder and error image -->
|
|
492
642
|
<img v-lazy="{ src: imageUrl, placeholder: '/placeholder.png', error: '/error.png' }" />
|
|
493
643
|
</template>
|
|
644
|
+
|
|
645
|
+
<script setup>
|
|
646
|
+
import { useLazy } from 'directix'
|
|
647
|
+
|
|
648
|
+
// Composable usage
|
|
649
|
+
const { load, state, loaded } = useLazy({
|
|
650
|
+
src: 'image.jpg',
|
|
651
|
+
preload: 100
|
|
652
|
+
})
|
|
653
|
+
</script>
|
|
494
654
|
```
|
|
495
655
|
|
|
496
656
|
### v-mask
|
|
@@ -508,6 +668,16 @@ Input masking for formatted input.
|
|
|
508
668
|
<!-- SSN -->
|
|
509
669
|
<input v-mask="{ mask: '###-##-####', placeholder: '_' }" placeholder="SSN" />
|
|
510
670
|
</template>
|
|
671
|
+
|
|
672
|
+
<script setup>
|
|
673
|
+
import { useMask } from 'directix'
|
|
674
|
+
|
|
675
|
+
// Composable usage
|
|
676
|
+
const { maskedValue, unmaskedValue, update } = useMask({
|
|
677
|
+
mask: '(###) ###-####',
|
|
678
|
+
value: '1234567890'
|
|
679
|
+
})
|
|
680
|
+
</script>
|
|
511
681
|
```
|
|
512
682
|
|
|
513
683
|
### v-loading
|
|
@@ -524,6 +694,19 @@ Show loading overlay on elements.
|
|
|
524
694
|
Content with locked scroll
|
|
525
695
|
</div>
|
|
526
696
|
</template>
|
|
697
|
+
|
|
698
|
+
<script setup>
|
|
699
|
+
import { ref } from 'vue'
|
|
700
|
+
import { useLoading } from 'directix'
|
|
701
|
+
|
|
702
|
+
const isLoading = ref(true)
|
|
703
|
+
|
|
704
|
+
// Composable usage
|
|
705
|
+
const { show, hide, setText } = useLoading({
|
|
706
|
+
text: 'Loading...',
|
|
707
|
+
lock: true
|
|
708
|
+
})
|
|
709
|
+
</script>
|
|
527
710
|
```
|
|
528
711
|
|
|
529
712
|
### v-sanitize
|
|
@@ -538,6 +721,16 @@ Sanitize HTML content to prevent XSS attacks.
|
|
|
538
721
|
<!-- With custom allowed tags -->
|
|
539
722
|
<div v-sanitize="{ html: userContent, allowedTags: ['b', 'i', 'u'] }"></div>
|
|
540
723
|
</template>
|
|
724
|
+
|
|
725
|
+
<script setup>
|
|
726
|
+
import { useSanitize } from 'directix'
|
|
727
|
+
|
|
728
|
+
// Composable usage
|
|
729
|
+
const { sanitize, setAllowedTags } = useSanitize({
|
|
730
|
+
allowedTags: ['b', 'i', 'u', 'a']
|
|
731
|
+
})
|
|
732
|
+
const cleanHtml = sanitize(dirtyHtml)
|
|
733
|
+
</script>
|
|
541
734
|
```
|
|
542
735
|
|
|
543
736
|
### v-tooltip
|
|
@@ -554,6 +747,16 @@ Display tooltips on hover or click.
|
|
|
554
747
|
Click me
|
|
555
748
|
</button>
|
|
556
749
|
</template>
|
|
750
|
+
|
|
751
|
+
<script setup>
|
|
752
|
+
import { useTooltip } from 'directix'
|
|
753
|
+
|
|
754
|
+
// Composable usage
|
|
755
|
+
const { show, hide, updateContent, updatePosition } = useTooltip({
|
|
756
|
+
content: 'Tooltip content',
|
|
757
|
+
placement: 'top'
|
|
758
|
+
})
|
|
759
|
+
</script>
|
|
557
760
|
```
|
|
558
761
|
|
|
559
762
|
### v-image-preview
|
|
@@ -568,6 +771,15 @@ Preview images with zoom and gesture support.
|
|
|
568
771
|
<!-- With options -->
|
|
569
772
|
<img v-image-preview="{ src: 'thumbnail.jpg', previewSrc: 'full.jpg', enablePinchZoom: true }" />
|
|
570
773
|
</template>
|
|
774
|
+
|
|
775
|
+
<script setup>
|
|
776
|
+
import { useImagePreview } from 'directix'
|
|
777
|
+
|
|
778
|
+
// Composable usage
|
|
779
|
+
const { open, close, zoom, rotate } = useImagePreview({
|
|
780
|
+
enablePinchZoom: true
|
|
781
|
+
})
|
|
782
|
+
</script>
|
|
571
783
|
```
|
|
572
784
|
|
|
573
785
|
### v-draggable
|
|
@@ -582,6 +794,16 @@ Make elements draggable.
|
|
|
582
794
|
<!-- With constraints -->
|
|
583
795
|
<div v-draggable="{ axis: 'x', bounds: 'parent' }">Horizontal drag only</div>
|
|
584
796
|
</template>
|
|
797
|
+
|
|
798
|
+
<script setup>
|
|
799
|
+
import { useDraggable } from 'directix'
|
|
800
|
+
|
|
801
|
+
// Composable usage
|
|
802
|
+
const { position, isDragging, reset } = useDraggable({
|
|
803
|
+
axis: 'x',
|
|
804
|
+
bounds: 'parent'
|
|
805
|
+
})
|
|
806
|
+
</script>
|
|
585
807
|
```
|
|
586
808
|
|
|
587
809
|
### v-uppercase / v-lowercase / v-capitalcase
|
|
@@ -594,6 +816,15 @@ Transform text case.
|
|
|
594
816
|
<input v-lowercase placeholder="Auto lowercase" />
|
|
595
817
|
<input v-capitalcase placeholder="Capitalize first letter" />
|
|
596
818
|
</template>
|
|
819
|
+
|
|
820
|
+
<script setup>
|
|
821
|
+
import { useUppercase, useLowercase, useCapitalcase } from 'directix'
|
|
822
|
+
|
|
823
|
+
// Composable usage
|
|
824
|
+
const { transform: toUppercase } = useUppercase()
|
|
825
|
+
const { transform: toLowercase } = useLowercase()
|
|
826
|
+
const { transform: toCapitalcase } = useCapitalcase()
|
|
827
|
+
</script>
|
|
597
828
|
```
|
|
598
829
|
|
|
599
830
|
### v-truncate
|
|
@@ -608,6 +839,14 @@ Truncate text with ellipsis.
|
|
|
608
839
|
<!-- With options -->
|
|
609
840
|
<p v-truncate="{ length: 100, suffix: '...', position: 'end' }">Long text...</p>
|
|
610
841
|
</template>
|
|
842
|
+
|
|
843
|
+
<script setup>
|
|
844
|
+
import { useTruncate } from 'directix'
|
|
845
|
+
|
|
846
|
+
// Composable usage
|
|
847
|
+
const { truncate } = useTruncate({ length: 100, suffix: '...' })
|
|
848
|
+
const shortText = truncate(longText)
|
|
849
|
+
</script>
|
|
611
850
|
```
|
|
612
851
|
|
|
613
852
|
### v-touch
|
|
@@ -622,6 +861,8 @@ Detect touch gestures.
|
|
|
622
861
|
</template>
|
|
623
862
|
|
|
624
863
|
<script setup>
|
|
864
|
+
import { useTouch } from 'directix'
|
|
865
|
+
|
|
625
866
|
function handleSwipe(direction) {
|
|
626
867
|
console.log('Swiped:', direction) // 'left', 'right', 'up', 'down'
|
|
627
868
|
}
|
|
@@ -629,6 +870,11 @@ function handleSwipe(direction) {
|
|
|
629
870
|
function handlePinch(scale) {
|
|
630
871
|
console.log('Pinched:', scale)
|
|
631
872
|
}
|
|
873
|
+
|
|
874
|
+
// Composable usage
|
|
875
|
+
const { onSwipe, onPinch, onRotate } = useTouch({
|
|
876
|
+
onSwipe: handleSwipe
|
|
877
|
+
})
|
|
632
878
|
</script>
|
|
633
879
|
```
|
|
634
880
|
|
|
@@ -644,6 +890,13 @@ Trim input whitespace.
|
|
|
644
890
|
<!-- Trim on input -->
|
|
645
891
|
<input v-trim="{ position: 'both', event: 'input' }" />
|
|
646
892
|
</template>
|
|
893
|
+
|
|
894
|
+
<script setup>
|
|
895
|
+
import { useTrim } from 'directix'
|
|
896
|
+
|
|
897
|
+
// Composable usage
|
|
898
|
+
const { trim, trimLeft, trimRight } = useTrim({ position: 'both' })
|
|
899
|
+
</script>
|
|
647
900
|
```
|
|
648
901
|
|
|
649
902
|
### v-money
|
|
@@ -654,6 +907,14 @@ Currency format input.
|
|
|
654
907
|
<template>
|
|
655
908
|
<input v-money="{ prefix: '$', precision: 2 }" placeholder="Enter amount" />
|
|
656
909
|
</template>
|
|
910
|
+
|
|
911
|
+
<script setup>
|
|
912
|
+
import { useMoney } from 'directix'
|
|
913
|
+
|
|
914
|
+
// Composable usage
|
|
915
|
+
const { format, parse } = useMoney({ prefix: '$', precision: 2 })
|
|
916
|
+
const formatted = format(1234.56) // "$1,234.56"
|
|
917
|
+
</script>
|
|
657
918
|
```
|
|
658
919
|
|
|
659
920
|
### v-number
|
|
@@ -664,6 +925,13 @@ Number format input.
|
|
|
664
925
|
<template>
|
|
665
926
|
<input v-number="{ precision: 2, min: 0, max: 100 }" placeholder="Enter number" />
|
|
666
927
|
</template>
|
|
928
|
+
|
|
929
|
+
<script setup>
|
|
930
|
+
import { useNumber } from 'directix'
|
|
931
|
+
|
|
932
|
+
// Composable usage
|
|
933
|
+
const { format, parse } = useNumber({ precision: 2, min: 0, max: 100 })
|
|
934
|
+
</script>
|
|
667
935
|
```
|
|
668
936
|
|
|
669
937
|
### v-click-delay
|
|
@@ -680,9 +948,17 @@ Delay click execution to prevent double clicks.
|
|
|
680
948
|
</template>
|
|
681
949
|
|
|
682
950
|
<script setup>
|
|
951
|
+
import { useClickDelay } from 'directix'
|
|
952
|
+
|
|
683
953
|
function handleClick() {
|
|
684
954
|
console.log('Clicked (delayed)')
|
|
685
955
|
}
|
|
956
|
+
|
|
957
|
+
// Composable usage
|
|
958
|
+
const { run: delayedClick, cancel } = useClickDelay({
|
|
959
|
+
handler: handleClick,
|
|
960
|
+
delay: 300
|
|
961
|
+
})
|
|
686
962
|
</script>
|
|
687
963
|
```
|
|
688
964
|
|
|
@@ -703,6 +979,8 @@ Countdown timer display.
|
|
|
703
979
|
</template>
|
|
704
980
|
|
|
705
981
|
<script setup>
|
|
982
|
+
import { useCountdown } from 'directix'
|
|
983
|
+
|
|
706
984
|
function handleTick(remaining) {
|
|
707
985
|
console.log('Remaining:', remaining)
|
|
708
986
|
}
|
|
@@ -710,6 +988,13 @@ function handleTick(remaining) {
|
|
|
710
988
|
function handleComplete() {
|
|
711
989
|
console.log('Countdown complete!')
|
|
712
990
|
}
|
|
991
|
+
|
|
992
|
+
// Composable usage
|
|
993
|
+
const { start, pause, reset, remaining } = useCountdown({
|
|
994
|
+
time: 60,
|
|
995
|
+
onTick: handleTick,
|
|
996
|
+
onComplete: handleComplete
|
|
997
|
+
})
|
|
713
998
|
</script>
|
|
714
999
|
```
|
|
715
1000
|
|
|
@@ -725,6 +1010,13 @@ Text ellipsis overflow with tooltip.
|
|
|
725
1010
|
<!-- With custom lines -->
|
|
726
1011
|
<div v-ellipsis="{ lines: 2 }">Multi-line text with ellipsis</div>
|
|
727
1012
|
</template>
|
|
1013
|
+
|
|
1014
|
+
<script setup>
|
|
1015
|
+
import { useEllipsis } from 'directix'
|
|
1016
|
+
|
|
1017
|
+
// Composable usage
|
|
1018
|
+
const { isEllipsisActive, checkEllipsis } = useEllipsis({ lines: 1 })
|
|
1019
|
+
</script>
|
|
728
1020
|
```
|
|
729
1021
|
|
|
730
1022
|
### v-hotkey
|
|
@@ -743,6 +1035,8 @@ Keyboard shortcut binding.
|
|
|
743
1035
|
</template>
|
|
744
1036
|
|
|
745
1037
|
<script setup>
|
|
1038
|
+
import { useHotkey } from 'directix'
|
|
1039
|
+
|
|
746
1040
|
function handleSave() {
|
|
747
1041
|
console.log('Saving...')
|
|
748
1042
|
}
|
|
@@ -750,6 +1044,11 @@ function handleSave() {
|
|
|
750
1044
|
function handleCopy() {
|
|
751
1045
|
console.log('Copying...')
|
|
752
1046
|
}
|
|
1047
|
+
|
|
1048
|
+
// Composable usage
|
|
1049
|
+
const { bind, unbind, unbindAll } = useHotkey({
|
|
1050
|
+
'ctrl+s': handleSave
|
|
1051
|
+
})
|
|
753
1052
|
</script>
|
|
754
1053
|
```
|
|
755
1054
|
|
|
@@ -766,6 +1065,19 @@ Print element content.
|
|
|
766
1065
|
<!-- Print self -->
|
|
767
1066
|
<div v-print="{ self: true }">Click to print this content</div>
|
|
768
1067
|
</template>
|
|
1068
|
+
|
|
1069
|
+
<script setup>
|
|
1070
|
+
import { ref } from 'vue'
|
|
1071
|
+
import { usePrint } from 'directix'
|
|
1072
|
+
|
|
1073
|
+
const printRef = ref()
|
|
1074
|
+
|
|
1075
|
+
// Composable usage
|
|
1076
|
+
const { print, printElement } = usePrint({
|
|
1077
|
+
onBefore: () => console.log('Printing...'),
|
|
1078
|
+
onComplete: () => console.log('Printed!')
|
|
1079
|
+
})
|
|
1080
|
+
</script>
|
|
769
1081
|
```
|
|
770
1082
|
|
|
771
1083
|
### v-pull-refresh
|
|
@@ -785,10 +1097,17 @@ Pull to refresh functionality.
|
|
|
785
1097
|
</template>
|
|
786
1098
|
|
|
787
1099
|
<script setup>
|
|
1100
|
+
import { usePullRefresh } from 'directix'
|
|
1101
|
+
|
|
788
1102
|
async function handleRefresh() {
|
|
789
1103
|
// Fetch new data
|
|
790
1104
|
await fetchData()
|
|
791
1105
|
}
|
|
1106
|
+
|
|
1107
|
+
// Composable usage
|
|
1108
|
+
const { isLoading, disable, enable } = usePullRefresh({
|
|
1109
|
+
handler: handleRefresh
|
|
1110
|
+
})
|
|
792
1111
|
</script>
|
|
793
1112
|
```
|
|
794
1113
|
|
|
@@ -809,9 +1128,17 @@ Swipe gesture detection with mouse support.
|
|
|
809
1128
|
</template>
|
|
810
1129
|
|
|
811
1130
|
<script setup>
|
|
1131
|
+
import { useSwipe } from 'directix'
|
|
1132
|
+
|
|
812
1133
|
function handleSwipe(direction) {
|
|
813
1134
|
console.log('Swiped:', direction) // 'left', 'right', 'up', 'down'
|
|
814
1135
|
}
|
|
1136
|
+
|
|
1137
|
+
// Composable usage
|
|
1138
|
+
const { direction, lengthX, lengthY } = useSwipe({
|
|
1139
|
+
onSwipe: handleSwipe,
|
|
1140
|
+
threshold: 50
|
|
1141
|
+
})
|
|
815
1142
|
</script>
|
|
816
1143
|
```
|
|
817
1144
|
|
|
@@ -830,6 +1157,14 @@ Virtual list for rendering large datasets efficiently.
|
|
|
830
1157
|
|
|
831
1158
|
<script setup>
|
|
832
1159
|
const list = Array.from({ length: 10000 }, (_, i) => ({ id: i, name: `Item ${i}` }))
|
|
1160
|
+
|
|
1161
|
+
import { useVirtualList } from 'directix'
|
|
1162
|
+
|
|
1163
|
+
// Composable usage
|
|
1164
|
+
const { list, containerProps, wrapperProps, scrollTo } = useVirtualList(
|
|
1165
|
+
largeList,
|
|
1166
|
+
{ itemHeight: 50 }
|
|
1167
|
+
)
|
|
833
1168
|
</script>
|
|
834
1169
|
```
|
|
835
1170
|
|
|
@@ -849,6 +1184,575 @@ Watermark overlay.
|
|
|
849
1184
|
Content with watermark
|
|
850
1185
|
</div>
|
|
851
1186
|
</template>
|
|
1187
|
+
|
|
1188
|
+
<script setup>
|
|
1189
|
+
import { useWatermark } from 'directix'
|
|
1190
|
+
|
|
1191
|
+
// Composable usage
|
|
1192
|
+
const { show, hide, update } = useWatermark({
|
|
1193
|
+
content: 'Confidential',
|
|
1194
|
+
fontSize: 16,
|
|
1195
|
+
color: '#ccc'
|
|
1196
|
+
})
|
|
1197
|
+
</script>
|
|
1198
|
+
```
|
|
1199
|
+
|
|
1200
|
+
### v-blur
|
|
1201
|
+
|
|
1202
|
+
Background blur overlay effect.
|
|
1203
|
+
|
|
1204
|
+
```vue
|
|
1205
|
+
<template>
|
|
1206
|
+
<!-- Simple blur -->
|
|
1207
|
+
<div v-blur="isBlurred">Content behind blur</div>
|
|
1208
|
+
|
|
1209
|
+
<!-- With radius -->
|
|
1210
|
+
<div v-blur="15">Blur with 15px radius</div>
|
|
1211
|
+
|
|
1212
|
+
<!-- With options -->
|
|
1213
|
+
<div v-blur="{
|
|
1214
|
+
visible: isBlurred,
|
|
1215
|
+
radius: 20,
|
|
1216
|
+
overlayColor: 'rgba(255, 255, 255, 0.3)',
|
|
1217
|
+
lockScroll: true
|
|
1218
|
+
}">
|
|
1219
|
+
Content
|
|
1220
|
+
</div>
|
|
1221
|
+
</template>
|
|
1222
|
+
|
|
1223
|
+
<script setup>
|
|
1224
|
+
import { ref } from 'vue'
|
|
1225
|
+
import { useBlur } from 'directix'
|
|
1226
|
+
|
|
1227
|
+
const isBlurred = ref(false)
|
|
1228
|
+
|
|
1229
|
+
// Composable usage
|
|
1230
|
+
const { show, hide, toggle } = useBlur({
|
|
1231
|
+
radius: 10,
|
|
1232
|
+
overlayColor: 'rgba(0, 0, 0, 0.5)'
|
|
1233
|
+
})
|
|
1234
|
+
</script>
|
|
1235
|
+
```
|
|
1236
|
+
|
|
1237
|
+
### v-fade
|
|
1238
|
+
|
|
1239
|
+
Fade in/out transition effect.
|
|
1240
|
+
|
|
1241
|
+
```vue
|
|
1242
|
+
<template>
|
|
1243
|
+
<!-- Toggle visibility with fade -->
|
|
1244
|
+
<div v-fade="isVisible">Fade content</div>
|
|
1245
|
+
|
|
1246
|
+
<!-- Fade in only -->
|
|
1247
|
+
<div v-fade="'in'">Fade in</div>
|
|
1248
|
+
|
|
1249
|
+
<!-- With options -->
|
|
1250
|
+
<div v-fade="{
|
|
1251
|
+
visible: isVisible,
|
|
1252
|
+
duration: 500,
|
|
1253
|
+
easing: 'ease-in-out',
|
|
1254
|
+
onComplete: () => console.log('Fade complete')
|
|
1255
|
+
}">
|
|
1256
|
+
Content
|
|
1257
|
+
</div>
|
|
1258
|
+
</template>
|
|
1259
|
+
|
|
1260
|
+
<script setup>
|
|
1261
|
+
import { ref } from 'vue'
|
|
1262
|
+
import { useFade } from 'directix'
|
|
1263
|
+
|
|
1264
|
+
const isVisible = ref(true)
|
|
1265
|
+
|
|
1266
|
+
// Composable usage
|
|
1267
|
+
const { fadeIn, fadeOut, toggle } = useFade({
|
|
1268
|
+
duration: 300,
|
|
1269
|
+
easing: 'ease'
|
|
1270
|
+
})
|
|
1271
|
+
</script>
|
|
1272
|
+
```
|
|
1273
|
+
|
|
1274
|
+
### v-parallax
|
|
1275
|
+
|
|
1276
|
+
Parallax scrolling effect.
|
|
1277
|
+
|
|
1278
|
+
```vue
|
|
1279
|
+
<template>
|
|
1280
|
+
<!-- Simple parallax -->
|
|
1281
|
+
<div v-parallax>Parallax content</div>
|
|
1282
|
+
|
|
1283
|
+
<!-- With speed factor -->
|
|
1284
|
+
<div v-parallax="0.3">Slower parallax</div>
|
|
1285
|
+
|
|
1286
|
+
<!-- With options -->
|
|
1287
|
+
<div v-parallax="{
|
|
1288
|
+
speed: 0.5,
|
|
1289
|
+
reverse: true,
|
|
1290
|
+
mobileBreakpoint: 768
|
|
1291
|
+
}">
|
|
1292
|
+
Reverse parallax, disabled on mobile
|
|
1293
|
+
</div>
|
|
1294
|
+
</template>
|
|
1295
|
+
|
|
1296
|
+
<script setup>
|
|
1297
|
+
import { useParallax } from 'directix'
|
|
1298
|
+
|
|
1299
|
+
// Composable usage
|
|
1300
|
+
const { offset, progress, enabled } = useParallax({
|
|
1301
|
+
speed: 0.5,
|
|
1302
|
+
reverse: false
|
|
1303
|
+
})
|
|
1304
|
+
</script>
|
|
1305
|
+
```
|
|
1306
|
+
|
|
1307
|
+
### v-lottie
|
|
1308
|
+
|
|
1309
|
+
Lottie animation player.
|
|
1310
|
+
|
|
1311
|
+
```vue
|
|
1312
|
+
<template>
|
|
1313
|
+
<!-- With URL -->
|
|
1314
|
+
<div v-lottie="'https://assets.example.com/animation.json'"></div>
|
|
1315
|
+
|
|
1316
|
+
<!-- With animation data -->
|
|
1317
|
+
<div v-lottie="animationData"></div>
|
|
1318
|
+
|
|
1319
|
+
<!-- With options -->
|
|
1320
|
+
<div v-lottie="{
|
|
1321
|
+
animationData: animationData,
|
|
1322
|
+
autoplay: true,
|
|
1323
|
+
loop: true,
|
|
1324
|
+
speed: 1.5,
|
|
1325
|
+
onComplete: () => console.log('Done')
|
|
1326
|
+
}"></div>
|
|
1327
|
+
</template>
|
|
1328
|
+
|
|
1329
|
+
<script setup>
|
|
1330
|
+
import animationData from './animation.json'
|
|
1331
|
+
import { useLottie } from 'directix'
|
|
1332
|
+
|
|
1333
|
+
// Composable usage
|
|
1334
|
+
const { play, pause, stop, setSpeed, setDirection } = useLottie({
|
|
1335
|
+
animationData,
|
|
1336
|
+
autoplay: true,
|
|
1337
|
+
loop: true
|
|
1338
|
+
})
|
|
1339
|
+
</script>
|
|
1340
|
+
```
|
|
1341
|
+
|
|
1342
|
+
### v-typewriter
|
|
1343
|
+
|
|
1344
|
+
Typewriter animation effect.
|
|
1345
|
+
|
|
1346
|
+
```vue
|
|
1347
|
+
<template>
|
|
1348
|
+
<!-- Simple usage -->
|
|
1349
|
+
<span v-typewriter="'Hello, World!'"></span>
|
|
1350
|
+
|
|
1351
|
+
<!-- With options -->
|
|
1352
|
+
<span v-typewriter="{
|
|
1353
|
+
text: 'Typing animation',
|
|
1354
|
+
speed: 100,
|
|
1355
|
+
cursor: '_',
|
|
1356
|
+
onComplete: () => console.log('Done!')
|
|
1357
|
+
}"></span>
|
|
1358
|
+
|
|
1359
|
+
<!-- Loop mode -->
|
|
1360
|
+
<span v-typewriter="{
|
|
1361
|
+
text: 'Loop animation',
|
|
1362
|
+
loop: true,
|
|
1363
|
+
deleteDelay: 1000
|
|
1364
|
+
}"></span>
|
|
1365
|
+
</template>
|
|
1366
|
+
|
|
1367
|
+
<script setup>
|
|
1368
|
+
import { useTypewriter } from 'directix'
|
|
1369
|
+
|
|
1370
|
+
// Composable usage
|
|
1371
|
+
const { start, stop, pause, resume } = useTypewriter({
|
|
1372
|
+
text: 'Hello World',
|
|
1373
|
+
speed: 50,
|
|
1374
|
+
loop: false
|
|
1375
|
+
})
|
|
1376
|
+
</script>
|
|
1377
|
+
```
|
|
1378
|
+
|
|
1379
|
+
### v-export
|
|
1380
|
+
|
|
1381
|
+
Export data (CSV/JSON/HTML/TXT).
|
|
1382
|
+
|
|
1383
|
+
```vue
|
|
1384
|
+
<template>
|
|
1385
|
+
<button v-export="exportData">Export CSV</button>
|
|
1386
|
+
|
|
1387
|
+
<button v-export="{ data: tableData, format: 'json', filename: 'my-data' }">
|
|
1388
|
+
Export JSON
|
|
1389
|
+
</button>
|
|
1390
|
+
|
|
1391
|
+
<button v-export="{
|
|
1392
|
+
data: tableData,
|
|
1393
|
+
format: 'csv',
|
|
1394
|
+
columns: ['name', 'email'],
|
|
1395
|
+
headers: { name: 'Name', email: 'Email Address' }
|
|
1396
|
+
}">
|
|
1397
|
+
Export with custom columns
|
|
1398
|
+
</button>
|
|
1399
|
+
</template>
|
|
1400
|
+
|
|
1401
|
+
<script setup>
|
|
1402
|
+
const tableData = [
|
|
1403
|
+
{ name: 'John', email: 'john@example.com', age: 30 },
|
|
1404
|
+
{ name: 'Jane', email: 'jane@example.com', age: 25 }
|
|
1405
|
+
]
|
|
1406
|
+
|
|
1407
|
+
import { useExport } from 'directix'
|
|
1408
|
+
|
|
1409
|
+
// Composable usage
|
|
1410
|
+
const { exportCSV, exportJSON, exportHTML } = useExport()
|
|
1411
|
+
</script>
|
|
1412
|
+
```
|
|
1413
|
+
|
|
1414
|
+
### v-highlight
|
|
1415
|
+
|
|
1416
|
+
Keyword highlighting.
|
|
1417
|
+
|
|
1418
|
+
```vue
|
|
1419
|
+
<template>
|
|
1420
|
+
<p v-highlight="'important'">This is an important message.</p>
|
|
1421
|
+
|
|
1422
|
+
<p v-highlight="['Vue', 'React']">Vue and React are popular frameworks.</p>
|
|
1423
|
+
|
|
1424
|
+
<p v-highlight="{
|
|
1425
|
+
keywords: 'highlight',
|
|
1426
|
+
className: 'my-highlight',
|
|
1427
|
+
style: 'background: yellow; color: black;',
|
|
1428
|
+
caseSensitive: true
|
|
1429
|
+
}">
|
|
1430
|
+
This will highlight the word.
|
|
1431
|
+
</p>
|
|
1432
|
+
</template>
|
|
1433
|
+
|
|
1434
|
+
<script setup>
|
|
1435
|
+
import { useHighlight } from 'directix'
|
|
1436
|
+
|
|
1437
|
+
// Composable usage
|
|
1438
|
+
const { highlight, clear } = useHighlight({
|
|
1439
|
+
keywords: ['important', 'key'],
|
|
1440
|
+
className: 'highlight'
|
|
1441
|
+
})
|
|
1442
|
+
</script>
|
|
1443
|
+
```
|
|
1444
|
+
|
|
1445
|
+
### v-emoji
|
|
1446
|
+
|
|
1447
|
+
Emoji input filter.
|
|
1448
|
+
|
|
1449
|
+
```vue
|
|
1450
|
+
<template>
|
|
1451
|
+
<!-- Strip all emojis -->
|
|
1452
|
+
<input v-emoji type="text" />
|
|
1453
|
+
|
|
1454
|
+
<!-- Strip emojis with replacement -->
|
|
1455
|
+
<input v-emoji="{ strip: true, replacement: '*' }" type="text" />
|
|
1456
|
+
|
|
1457
|
+
<!-- Allow specific emojis -->
|
|
1458
|
+
<input v-emoji="{ allowList: ['😊', '👍'] }" type="text" />
|
|
1459
|
+
|
|
1460
|
+
<!-- Block specific emojis -->
|
|
1461
|
+
<input v-emoji="{ blockList: ['🚫', '❌'] }" type="text" />
|
|
1462
|
+
</template>
|
|
1463
|
+
|
|
1464
|
+
<script setup>
|
|
1465
|
+
import { useEmoji } from 'directix'
|
|
1466
|
+
|
|
1467
|
+
// Composable usage
|
|
1468
|
+
const { stripEmojis, containsEmoji } = useEmoji({
|
|
1469
|
+
strip: true,
|
|
1470
|
+
allowList: ['😊', '👍']
|
|
1471
|
+
})
|
|
1472
|
+
</script>
|
|
1473
|
+
```
|
|
1474
|
+
|
|
1475
|
+
### v-context-menu
|
|
1476
|
+
|
|
1477
|
+
Right-click context menu.
|
|
1478
|
+
|
|
1479
|
+
```vue
|
|
1480
|
+
<template>
|
|
1481
|
+
<div v-context-menu="menuItems">Right click here</div>
|
|
1482
|
+
<div v-context-menu="{ items: menuItems, width: 200 }">Custom width</div>
|
|
1483
|
+
</template>
|
|
1484
|
+
|
|
1485
|
+
<script setup>
|
|
1486
|
+
import { useContextMenu } from 'directix'
|
|
1487
|
+
|
|
1488
|
+
const menuItems = [
|
|
1489
|
+
{ label: 'Copy', handler: () => console.log('Copy') },
|
|
1490
|
+
{ label: 'Paste', handler: () => console.log('Paste') },
|
|
1491
|
+
{ divider: true, label: '' },
|
|
1492
|
+
{ label: 'Delete', handler: () => console.log('Delete') }
|
|
1493
|
+
]
|
|
1494
|
+
|
|
1495
|
+
// Composable usage
|
|
1496
|
+
const { show, hide, setItems } = useContextMenu({
|
|
1497
|
+
items: menuItems
|
|
1498
|
+
})
|
|
1499
|
+
</script>
|
|
1500
|
+
```
|
|
1501
|
+
|
|
1502
|
+
### v-fullscreen
|
|
1503
|
+
|
|
1504
|
+
Fullscreen toggle.
|
|
1505
|
+
|
|
1506
|
+
```vue
|
|
1507
|
+
<template>
|
|
1508
|
+
<div v-fullscreen>
|
|
1509
|
+
Content to show in fullscreen
|
|
1510
|
+
<button @click="$el.toggleFullscreen()">Toggle</button>
|
|
1511
|
+
</div>
|
|
1512
|
+
|
|
1513
|
+
<div v-fullscreen="{ fullscreenClass: 'my-fullscreen' }">
|
|
1514
|
+
Custom fullscreen class
|
|
1515
|
+
</div>
|
|
1516
|
+
</template>
|
|
1517
|
+
|
|
1518
|
+
<script setup>
|
|
1519
|
+
import { useFullscreen } from 'directix'
|
|
1520
|
+
|
|
1521
|
+
// Composable usage
|
|
1522
|
+
const { isFullscreen, enter, exit, toggle } = useFullscreen({
|
|
1523
|
+
onEnter: () => console.log('Entered fullscreen'),
|
|
1524
|
+
onExit: () => console.log('Exited fullscreen')
|
|
1525
|
+
})
|
|
1526
|
+
</script>
|
|
1527
|
+
```
|
|
1528
|
+
|
|
1529
|
+
### v-skeleton
|
|
1530
|
+
|
|
1531
|
+
Skeleton loading placeholder.
|
|
1532
|
+
|
|
1533
|
+
```vue
|
|
1534
|
+
<template>
|
|
1535
|
+
<!-- Basic usage -->
|
|
1536
|
+
<div v-skeleton="isLoading">Content here</div>
|
|
1537
|
+
|
|
1538
|
+
<!-- With options -->
|
|
1539
|
+
<div v-skeleton="{ loading: isLoading, animation: 'pulse', width: 200, height: 20 }">
|
|
1540
|
+
Content here
|
|
1541
|
+
</div>
|
|
1542
|
+
</template>
|
|
1543
|
+
|
|
1544
|
+
<script setup>
|
|
1545
|
+
import { ref } from 'vue'
|
|
1546
|
+
import { useSkeleton } from 'directix'
|
|
1547
|
+
|
|
1548
|
+
const isLoading = ref(true)
|
|
1549
|
+
|
|
1550
|
+
// Composable usage
|
|
1551
|
+
const { show, hide, update } = useSkeleton({
|
|
1552
|
+
animation: 'wave',
|
|
1553
|
+
color: '#e8e8e8'
|
|
1554
|
+
})
|
|
1555
|
+
</script>
|
|
1556
|
+
```
|
|
1557
|
+
|
|
1558
|
+
### v-progress
|
|
1559
|
+
|
|
1560
|
+
Progress bar animation.
|
|
1561
|
+
|
|
1562
|
+
```vue
|
|
1563
|
+
<template>
|
|
1564
|
+
<div v-progress="50">Progress at 50%</div>
|
|
1565
|
+
|
|
1566
|
+
<div v-progress="{
|
|
1567
|
+
value: progressValue,
|
|
1568
|
+
color: '#42b883',
|
|
1569
|
+
height: 8,
|
|
1570
|
+
showText: true
|
|
1571
|
+
}">
|
|
1572
|
+
Content
|
|
1573
|
+
</div>
|
|
1574
|
+
|
|
1575
|
+
<div v-progress="{ indeterminate: true }">
|
|
1576
|
+
Loading...
|
|
1577
|
+
</div>
|
|
1578
|
+
</template>
|
|
1579
|
+
|
|
1580
|
+
<script setup>
|
|
1581
|
+
import { ref } from 'vue'
|
|
1582
|
+
import { useProgress } from 'directix'
|
|
1583
|
+
|
|
1584
|
+
const progressValue = ref(50)
|
|
1585
|
+
|
|
1586
|
+
// Composable usage
|
|
1587
|
+
const { setProgress, start, finish, fail } = useProgress({
|
|
1588
|
+
color: '#42b883',
|
|
1589
|
+
height: 4
|
|
1590
|
+
})
|
|
1591
|
+
</script>
|
|
1592
|
+
```
|
|
1593
|
+
|
|
1594
|
+
### v-counter
|
|
1595
|
+
|
|
1596
|
+
Animated number counter.
|
|
1597
|
+
|
|
1598
|
+
```vue
|
|
1599
|
+
<template>
|
|
1600
|
+
<span v-counter="1000">0</span>
|
|
1601
|
+
|
|
1602
|
+
<span v-counter="{
|
|
1603
|
+
value: 10000,
|
|
1604
|
+
duration: 3000,
|
|
1605
|
+
decimals: 2,
|
|
1606
|
+
useGrouping: true
|
|
1607
|
+
}">0</span>
|
|
1608
|
+
|
|
1609
|
+
<span v-counter="{
|
|
1610
|
+
value: targetValue,
|
|
1611
|
+
formatter: (v) => '$' + v.toFixed(2)
|
|
1612
|
+
}">0</span>
|
|
1613
|
+
</template>
|
|
1614
|
+
|
|
1615
|
+
<script setup>
|
|
1616
|
+
import { ref } from 'vue'
|
|
1617
|
+
import { useCounter } from 'directix'
|
|
1618
|
+
|
|
1619
|
+
const targetValue = ref(1000)
|
|
1620
|
+
|
|
1621
|
+
// Composable usage
|
|
1622
|
+
const { start, pause, reset, update } = useCounter({
|
|
1623
|
+
startValue: 0,
|
|
1624
|
+
endValue: 1000,
|
|
1625
|
+
duration: 2000,
|
|
1626
|
+
formatter: (v) => `$${v.toFixed(2)}`
|
|
1627
|
+
})
|
|
1628
|
+
</script>
|
|
1629
|
+
```
|
|
1630
|
+
|
|
1631
|
+
### v-click-wave
|
|
1632
|
+
|
|
1633
|
+
Click wave effect.
|
|
1634
|
+
|
|
1635
|
+
```vue
|
|
1636
|
+
<template>
|
|
1637
|
+
<button v-click-wave>Click me</button>
|
|
1638
|
+
<button v-click-wave="'rgba(255, 255, 255, 0.3)'">Custom color</button>
|
|
1639
|
+
<button v-click-wave="{ color: 'red', duration: 400 }">Custom options</button>
|
|
1640
|
+
</template>
|
|
1641
|
+
|
|
1642
|
+
<script setup>
|
|
1643
|
+
import { ref } from 'vue'
|
|
1644
|
+
import { useClickWave } from 'directix'
|
|
1645
|
+
|
|
1646
|
+
// Composable usage
|
|
1647
|
+
const buttonRef = ref(null)
|
|
1648
|
+
const { bind, trigger } = useClickWave({
|
|
1649
|
+
color: 'currentColor',
|
|
1650
|
+
duration: 500
|
|
1651
|
+
})
|
|
1652
|
+
|
|
1653
|
+
// Bind to element on mount
|
|
1654
|
+
onMounted(() => bind(buttonRef.value))
|
|
1655
|
+
</script>
|
|
1656
|
+
```
|
|
1657
|
+
|
|
1658
|
+
### v-pan
|
|
1659
|
+
|
|
1660
|
+
Pan/drag gesture.
|
|
1661
|
+
|
|
1662
|
+
```vue
|
|
1663
|
+
<template>
|
|
1664
|
+
<div v-pan="handlePan">Swipe me</div>
|
|
1665
|
+
|
|
1666
|
+
<div v-pan="{
|
|
1667
|
+
onPan: handlePan,
|
|
1668
|
+
direction: 'horizontal',
|
|
1669
|
+
threshold: 20
|
|
1670
|
+
}">
|
|
1671
|
+
Horizontal only
|
|
1672
|
+
</div>
|
|
1673
|
+
</template>
|
|
1674
|
+
|
|
1675
|
+
<script setup>
|
|
1676
|
+
import { usePan } from 'directix'
|
|
1677
|
+
|
|
1678
|
+
function handlePan(e) {
|
|
1679
|
+
console.log('Direction:', e.direction)
|
|
1680
|
+
console.log('Distance:', e.distance)
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1683
|
+
// Composable usage
|
|
1684
|
+
const { isPanning, deltaX, deltaY } = usePan({
|
|
1685
|
+
onPan: handlePan,
|
|
1686
|
+
direction: 'horizontal'
|
|
1687
|
+
})
|
|
1688
|
+
</script>
|
|
1689
|
+
```
|
|
1690
|
+
|
|
1691
|
+
### v-pinch
|
|
1692
|
+
|
|
1693
|
+
Pinch/zoom gesture.
|
|
1694
|
+
|
|
1695
|
+
```vue
|
|
1696
|
+
<template>
|
|
1697
|
+
<div v-pinch="handlePinch">Pinch to zoom</div>
|
|
1698
|
+
|
|
1699
|
+
<div v-pinch="{
|
|
1700
|
+
onPinch: handlePinch,
|
|
1701
|
+
enableTransform: true,
|
|
1702
|
+
minScale: 0.5,
|
|
1703
|
+
maxScale: 3
|
|
1704
|
+
}">
|
|
1705
|
+
Pinch to scale
|
|
1706
|
+
</div>
|
|
1707
|
+
</template>
|
|
1708
|
+
|
|
1709
|
+
<script setup>
|
|
1710
|
+
import { usePinch } from 'directix'
|
|
1711
|
+
|
|
1712
|
+
function handlePinch(e) {
|
|
1713
|
+
console.log('Scale:', e.scale)
|
|
1714
|
+
console.log('Center:', e.centerX, e.centerY)
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
// Composable usage
|
|
1718
|
+
const { scale, isPinching } = usePinch({
|
|
1719
|
+
onPinch: handlePinch,
|
|
1720
|
+
minScale: 0.5,
|
|
1721
|
+
maxScale: 3
|
|
1722
|
+
})
|
|
1723
|
+
</script>
|
|
1724
|
+
```
|
|
1725
|
+
|
|
1726
|
+
### v-rotate-gesture
|
|
1727
|
+
|
|
1728
|
+
Rotation gesture.
|
|
1729
|
+
|
|
1730
|
+
```vue
|
|
1731
|
+
<template>
|
|
1732
|
+
<div v-rotate-gesture="handleRotate">Rotate with two fingers</div>
|
|
1733
|
+
|
|
1734
|
+
<div v-rotate-gesture="{
|
|
1735
|
+
onRotate: handleRotate,
|
|
1736
|
+
enableTransform: true
|
|
1737
|
+
}">
|
|
1738
|
+
Rotate with transform
|
|
1739
|
+
</div>
|
|
1740
|
+
</template>
|
|
1741
|
+
|
|
1742
|
+
<script setup>
|
|
1743
|
+
import { useRotateGesture } from 'directix'
|
|
1744
|
+
|
|
1745
|
+
function handleRotate(e) {
|
|
1746
|
+
console.log('Rotation:', e.rotation)
|
|
1747
|
+
console.log('Angle:', e.angle)
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
// Composable usage
|
|
1751
|
+
const { angle, isRotating } = useRotateGesture({
|
|
1752
|
+
onRotate: handleRotate,
|
|
1753
|
+
enableTransform: true
|
|
1754
|
+
})
|
|
1755
|
+
</script>
|
|
852
1756
|
```
|
|
853
1757
|
|
|
854
1758
|
## API Reference
|