@maz-ui/mcp 5.0.0-beta.4 → 5.0.0-beta.41

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.
Files changed (157) hide show
  1. package/README.md +1 -1
  2. package/dist/mcp.d.mts +22 -9
  3. package/dist/mcp.d.ts +22 -9
  4. package/dist/mcp.mjs +160 -83
  5. package/docs/generated-docs/maz-avatar.doc.md +30 -30
  6. package/docs/generated-docs/maz-bottom-sheet.doc.md +16 -13
  7. package/docs/generated-docs/maz-btn.doc.md +21 -19
  8. package/docs/generated-docs/maz-checkbox.doc.md +16 -17
  9. package/docs/generated-docs/maz-circular-progress-bar.doc.md +1 -1
  10. package/docs/generated-docs/maz-code-highlight.doc.md +11 -0
  11. package/docs/generated-docs/maz-container.doc.md +1 -0
  12. package/docs/generated-docs/maz-date-picker.doc.md +41 -41
  13. package/docs/generated-docs/maz-drawer.doc.md +7 -8
  14. package/docs/generated-docs/maz-dropdown.doc.md +3 -0
  15. package/docs/generated-docs/maz-expand-animation.doc.md +4 -4
  16. package/docs/generated-docs/maz-fullscreen-loader.doc.md +5 -5
  17. package/docs/generated-docs/maz-gallery.doc.md +15 -15
  18. package/docs/generated-docs/maz-input-code.doc.md +16 -16
  19. package/docs/generated-docs/maz-input-price.doc.md +14 -14
  20. package/docs/generated-docs/maz-input-tags.doc.md +16 -16
  21. package/docs/generated-docs/maz-input.doc.md +33 -33
  22. package/docs/generated-docs/maz-lazy-img.doc.md +14 -14
  23. package/docs/generated-docs/maz-loading-bar.doc.md +4 -4
  24. package/docs/generated-docs/maz-markdown-editor.doc.md +65 -0
  25. package/docs/generated-docs/maz-popover.doc.md +1 -1
  26. package/docs/generated-docs/maz-pull-to-refresh.doc.md +10 -10
  27. package/docs/generated-docs/maz-radio-buttons.doc.md +17 -17
  28. package/docs/generated-docs/maz-radio.doc.md +16 -16
  29. package/docs/generated-docs/maz-reading-progress-bar.doc.md +4 -4
  30. package/docs/generated-docs/maz-sidebar-content.doc.md +5 -0
  31. package/docs/generated-docs/maz-sidebar-footer.doc.md +5 -0
  32. package/docs/generated-docs/maz-sidebar-group.doc.md +11 -0
  33. package/docs/generated-docs/maz-sidebar-header.doc.md +5 -0
  34. package/docs/generated-docs/maz-sidebar-menu-button.doc.md +27 -0
  35. package/docs/generated-docs/maz-sidebar-menu-item.doc.md +5 -0
  36. package/docs/generated-docs/maz-sidebar-menu-sub.doc.md +16 -0
  37. package/docs/generated-docs/maz-sidebar-menu.doc.md +5 -0
  38. package/docs/generated-docs/maz-sidebar-separator.doc.md +0 -0
  39. package/docs/generated-docs/maz-sidebar-trigger.doc.md +5 -0
  40. package/docs/generated-docs/maz-sidebar.doc.md +36 -0
  41. package/docs/generated-docs/maz-slider.doc.md +1 -1
  42. package/docs/generated-docs/maz-spinner.doc.md +4 -4
  43. package/docs/generated-docs/maz-switch.doc.md +14 -14
  44. package/docs/generated-docs/maz-table.doc.md +39 -37
  45. package/docs/generated-docs/maz-tabs-bar.doc.md +20 -9
  46. package/docs/generated-docs/maz-tabs.doc.md +6 -3
  47. package/docs/generated-docs/maz-textarea.doc.md +27 -25
  48. package/docs/generated-docs/maz-ticker.doc.md +1 -1
  49. package/docs/generated-docs/maz-timeline.doc.md +4 -4
  50. package/docs/generated-docs/maz-window-mockup.doc.md +23 -0
  51. package/docs/src/blog/v4.md +1 -1
  52. package/docs/src/blog/v5.md +5 -7
  53. package/docs/src/components/maz-avatar.md +52 -4
  54. package/docs/src/components/maz-bottom-sheet.md +300 -169
  55. package/docs/src/components/maz-btn.md +1 -1
  56. package/docs/src/components/maz-code-highlight.md +233 -0
  57. package/docs/src/components/maz-date-picker.md +1 -1
  58. package/docs/src/components/maz-dialog.md +46 -0
  59. package/docs/src/components/maz-dropdown.md +32 -16
  60. package/docs/src/components/maz-icon.md +2 -2
  61. package/docs/src/components/maz-lazy-img.md +64 -0
  62. package/docs/src/components/maz-markdown-editor.md +369 -0
  63. package/docs/src/components/maz-pull-to-refresh.md +1 -1
  64. package/docs/src/components/maz-sidebar.md +719 -0
  65. package/docs/src/components/maz-table.md +74 -0
  66. package/docs/src/components/maz-tabs.md +110 -3
  67. package/docs/src/components/maz-textarea.md +58 -0
  68. package/docs/src/components/maz-timeline.md +60 -0
  69. package/docs/src/components/maz-window-mockup.md +249 -0
  70. package/docs/src/composables/use-drag.md +239 -0
  71. package/docs/src/composables/use-form-validator.md +50 -11
  72. package/docs/src/composables/use-swipe.md +26 -11
  73. package/docs/src/directives/click-outside.md +8 -15
  74. package/docs/src/directives/fullscreen-img.md +1 -1
  75. package/docs/src/directives/lazy-img.md +44 -11
  76. package/docs/src/directives/tooltip.md +24 -1
  77. package/docs/src/directives/zoom-img.md +1 -1
  78. package/docs/src/ecosystem/eslint-config.md +95 -1
  79. package/docs/src/{guide/icons.md → ecosystem/icons/index.md} +1 -1
  80. package/docs/src/ecosystem/node/exec-promise.md +87 -0
  81. package/docs/src/ecosystem/node/index.md +53 -0
  82. package/docs/src/ecosystem/node/logger.md +146 -0
  83. package/docs/src/ecosystem/node/print-banner.md +93 -0
  84. package/docs/src/{guide → ecosystem}/nuxt.md +81 -47
  85. package/docs/src/{guide → ecosystem}/themes.md +152 -71
  86. package/docs/src/{guide → ecosystem}/translations.md +1 -1
  87. package/docs/src/ecosystem/utils/camel-case.md +31 -0
  88. package/docs/src/{helpers → ecosystem/utils}/capitalize.md +2 -3
  89. package/docs/src/ecosystem/utils/check-availability.md +79 -0
  90. package/docs/src/ecosystem/utils/cookie.md +80 -0
  91. package/docs/src/ecosystem/utils/debounce-callback.md +38 -0
  92. package/docs/src/ecosystem/utils/debounce-id.md +69 -0
  93. package/docs/src/ecosystem/utils/debounce.md +65 -0
  94. package/docs/src/ecosystem/utils/fetch-locale-ip.md +33 -0
  95. package/docs/src/ecosystem/utils/format-json.md +33 -0
  96. package/docs/src/ecosystem/utils/format-phone-number.md +37 -0
  97. package/docs/src/ecosystem/utils/get-browser-locale.md +29 -0
  98. package/docs/src/ecosystem/utils/get-error-message.md +39 -0
  99. package/docs/src/ecosystem/utils/idle-timeout.md +90 -0
  100. package/docs/src/ecosystem/utils/index.md +60 -0
  101. package/docs/src/ecosystem/utils/is-client.md +32 -0
  102. package/docs/src/ecosystem/utils/is-equal.md +38 -0
  103. package/docs/src/ecosystem/utils/is-server.md +31 -0
  104. package/docs/src/ecosystem/utils/is-standalone-mode.md +43 -0
  105. package/docs/src/ecosystem/utils/kebab-case.md +36 -0
  106. package/docs/src/ecosystem/utils/normalize-string.md +77 -0
  107. package/docs/src/ecosystem/utils/pascal-case.md +35 -0
  108. package/docs/src/ecosystem/utils/script-loader.md +77 -0
  109. package/docs/src/ecosystem/utils/sleep.md +59 -0
  110. package/docs/src/ecosystem/utils/snake-case.md +36 -0
  111. package/docs/src/ecosystem/utils/swipe-handler.md +91 -0
  112. package/docs/src/ecosystem/utils/textarea-autogrow.md +41 -0
  113. package/docs/src/ecosystem/utils/throttle-id.md +48 -0
  114. package/docs/src/ecosystem/utils/throttle.md +57 -0
  115. package/docs/src/ecosystem/utils/truthy-filter.md +31 -0
  116. package/docs/src/ecosystem/utils/types/deep-key-of.md +48 -0
  117. package/docs/src/ecosystem/utils/types/deep-partial.md +42 -0
  118. package/docs/src/ecosystem/utils/types/deep-required.md +39 -0
  119. package/docs/src/ecosystem/utils/types/flatten-object-keys.md +44 -0
  120. package/docs/src/ecosystem/utils/types/generic-instance-type.md +42 -0
  121. package/docs/src/ecosystem/utils/types/infer-maybe-ref.md +35 -0
  122. package/docs/src/ecosystem/utils/upper-first.md +32 -0
  123. package/docs/src/ecosystem/utils/user-visibility.md +69 -0
  124. package/docs/src/guide/getting-started.md +15 -13
  125. package/docs/src/guide/global-defaults.md +101 -0
  126. package/docs/src/guide/maz-ui-provider.md +6 -3
  127. package/docs/src/guide/migration-v4.md +13 -9
  128. package/docs/src/guide/migration-v5.md +112 -13
  129. package/docs/src/guide/resolvers.md +7 -7
  130. package/docs/src/guide/tailwind.md +4 -0
  131. package/docs/src/guide/vue.md +4 -4
  132. package/docs/src/index.md +12 -12
  133. package/docs/src/plugins/aos.md +1 -1
  134. package/package.json +8 -7
  135. package/docs/src/helpers/camel-case.md +0 -14
  136. package/docs/src/helpers/check-availability.md +0 -14
  137. package/docs/src/helpers/debounce-callback.md +0 -14
  138. package/docs/src/helpers/debounce-id.md +0 -14
  139. package/docs/src/helpers/debounce.md +0 -14
  140. package/docs/src/helpers/is-client.md +0 -14
  141. package/docs/src/helpers/is-equal.md +0 -14
  142. package/docs/src/helpers/is-standalone-mode.md +0 -14
  143. package/docs/src/helpers/kebab-case.md +0 -14
  144. package/docs/src/helpers/normalize-string.md +0 -14
  145. package/docs/src/helpers/pascal-case.md +0 -14
  146. package/docs/src/helpers/script-loader.md +0 -14
  147. package/docs/src/helpers/sleep.md +0 -14
  148. package/docs/src/helpers/snake-case.md +0 -14
  149. package/docs/src/helpers/throttle-id.md +0 -14
  150. package/docs/src/helpers/throttle.md +0 -14
  151. /package/docs/src/{guide → ecosystem/icons}/icon-set.md +0 -0
  152. /package/docs/src/{guide → ecosystem}/mcp.md +0 -0
  153. /package/docs/src/{helpers → ecosystem/utils}/country-code-to-unicode-flag.md +0 -0
  154. /package/docs/src/{helpers → ecosystem/utils}/currency.md +0 -0
  155. /package/docs/src/{helpers → ecosystem/utils}/date.md +0 -0
  156. /package/docs/src/{helpers → ecosystem/utils}/get-country-flag-url.md +0 -0
  157. /package/docs/src/{helpers → ecosystem/utils}/number.md +0 -0
@@ -0,0 +1,239 @@
1
+ ---
2
+ title: useDrag
3
+ description: useDrag is a Vue composable that tracks a pointer drag gesture (touch, mouse and pen) in real time, exposing the live offset, distance and direction.
4
+ ---
5
+
6
+ # {{ $frontmatter.title }}
7
+
8
+ {{ $frontmatter.description }}
9
+
10
+ ## Introduction
11
+
12
+ `useDrag` follows a pointer drag on an element and gives you the **live** offset, distance and direction, plus `onStart` / `onMove` / `onEnd` callbacks. It is the low-level gesture primitive behind components like [MazBottomSheet](../components/maz-bottom-sheet.md) (drag-to-dismiss), and it's useful to build sliders, sortable handles, swipeable cards, bottom sheets, custom carousels, etc.
13
+
14
+ It is built on top of [Pointer Events](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events), so it works with **touch, mouse and pen**.
15
+
16
+ ::: tip
17
+ For discrete directional swipe detection (left / right / up / down with a threshold) rather than real-time tracking, use [useSwipe](./use-swipe.md).
18
+ :::
19
+
20
+ ## Key Features
21
+
22
+ - Real-time pointer tracking (touch, mouse and pen)
23
+ - Live reactive state: `isDragging`, `offsetX`, `offsetY`, `distance`, `direction`
24
+ - `onStart` / `onMove` / `onEnd` callbacks with a full state snapshot
25
+ - Axis locking (`x`, `y` or `both`)
26
+ - Activation threshold, pointer-type filtering and reactive `disabled`
27
+ - Listeners are followed on the document, so the drag keeps working when the pointer leaves the element
28
+ - Automatically attaches/detaches when the target appears/disappears, and cleans up on unmount
29
+
30
+ ## Basic Usage
31
+
32
+ Drag the card down: it follows your pointer and snaps back on release.
33
+
34
+ <div class="drag-demo">
35
+ <div
36
+ ref="dragHandle"
37
+ class="drag-card"
38
+ :class="{ '--dragging': dragging }"
39
+ :style="{ transform: dragOffset ? `translateY(${dragOffset}px)` : undefined }"
40
+ >
41
+ {{ dragging ? `Dragging — ${Math.round(dragOffset)}px ${dragDirection ?? ''}` : 'Drag me down' }}
42
+ </div>
43
+ </div>
44
+
45
+ ```vue
46
+ <script lang="ts" setup>
47
+ import { useDrag } from 'maz-ui/composables'
48
+ import { ref } from 'vue'
49
+
50
+ const dragHandle = ref<HTMLElement>()
51
+ const dragOffset = ref(0)
52
+
53
+ const { isDragging: dragging, direction: dragDirection } = useDrag(dragHandle, {
54
+ axis: 'y',
55
+ onMove: ({ offsetY }) => {
56
+ dragOffset.value = Math.max(0, offsetY)
57
+ },
58
+ onEnd: ({ offsetY }) => {
59
+ if (offsetY > 150) {
60
+ // trigger an action when dragged far enough
61
+ }
62
+ dragOffset.value = 0
63
+ },
64
+ })
65
+ </script>
66
+
67
+ <template>
68
+ <div
69
+ ref="dragHandle"
70
+ class="drag-card"
71
+ :class="{ '--dragging': dragging }"
72
+ :style="{ transform: dragOffset ? `translateY(${dragOffset}px)` : undefined }"
73
+ >
74
+ {{ dragging ? `Dragging — ${Math.round(dragOffset)}px ${dragDirection ?? ''}` : 'Drag me down' }}
75
+ </div>
76
+ </template>
77
+
78
+ <style>
79
+ .drag-card {
80
+ touch-action: none;
81
+ cursor: grab;
82
+ user-select: none;
83
+ }
84
+ .drag-card:not(.--dragging) {
85
+ transition: transform 0.25s ease;
86
+ }
87
+ </style>
88
+ ```
89
+
90
+ ## Options
91
+
92
+ `useDrag(target, options)` - the `target` is a `MaybeRefOrGetter<HTMLElement | string | null | undefined>` and `options` accepts:
93
+
94
+ ```ts
95
+ interface UseDragOptions {
96
+ /**
97
+ * Restrict the tracking to a single axis. Off-axis movement is ignored.
98
+ * @default 'both'
99
+ */
100
+ axis?: 'x' | 'y' | 'both'
101
+ /**
102
+ * Minimum distance (px) the pointer must travel before the drag becomes active.
103
+ * @default 0
104
+ */
105
+ threshold?: number
106
+ /**
107
+ * Pointer types allowed to initiate the drag.
108
+ * @default ['mouse', 'touch', 'pen']
109
+ */
110
+ pointerTypes?: ('mouse' | 'touch' | 'pen')[]
111
+ /**
112
+ * Reactively disable the gesture.
113
+ * @default false
114
+ */
115
+ disabled?: MaybeRefOrGetter<boolean>
116
+ /**
117
+ * Call `event.preventDefault()` on each pointer move while dragging.
118
+ * @default false
119
+ */
120
+ preventDefault?: boolean
121
+ /**
122
+ * Call `event.stopPropagation()` on the pointer events.
123
+ * @default false
124
+ */
125
+ stopPropagation?: boolean
126
+ /**
127
+ * Attach the listeners as soon as the target is available. When `false`, call `start()` manually.
128
+ * @default true
129
+ */
130
+ immediate?: boolean
131
+ /** Called once when the drag becomes active (threshold reached). */
132
+ onStart?: (state: DragState) => void
133
+ /** Called on every pointer move while dragging. */
134
+ onMove?: (state: DragState) => void
135
+ /** Called when the drag ends (pointer up or cancel). */
136
+ onEnd?: (state: DragState) => void
137
+ }
138
+ ```
139
+
140
+ Each callback receives a `DragState` snapshot:
141
+
142
+ ```ts
143
+ interface DragState {
144
+ /** Pointer offset from the drag start on the X axis (`0` when axis is `'y'`). */
145
+ offsetX: number
146
+ /** Pointer offset from the drag start on the Y axis (`0` when axis is `'x'`). */
147
+ offsetY: number
148
+ /** Absolute distance dragged from the start. */
149
+ distance: number
150
+ /** Dominant direction of the drag. */
151
+ direction: 'up' | 'down' | 'left' | 'right' | undefined
152
+ /** Pointer position when the drag started. */
153
+ startX: number
154
+ startY: number
155
+ /** Current pointer position. */
156
+ x: number
157
+ y: number
158
+ /** The underlying pointer event. */
159
+ event: PointerEvent
160
+ }
161
+ ```
162
+
163
+ ## Composable Return
164
+
165
+ ```ts
166
+ interface UseDragReturn {
167
+ /** Whether a drag is currently active (threshold reached). */
168
+ isDragging: Readonly<Ref<boolean>>
169
+ /** Reactive pointer offset from the drag start on the X axis. */
170
+ offsetX: Readonly<Ref<number>>
171
+ /** Reactive pointer offset from the drag start on the Y axis. */
172
+ offsetY: Readonly<Ref<number>>
173
+ /** Reactive absolute distance dragged from the start. */
174
+ distance: Readonly<Ref<number>>
175
+ /** Reactive dominant direction of the drag. */
176
+ direction: Readonly<Ref<'up' | 'down' | 'left' | 'right' | undefined>>
177
+ /** Manually attach the listeners. */
178
+ start: () => void
179
+ /** Manually detach the listeners (also cancels an ongoing drag). */
180
+ stop: () => void
181
+ }
182
+ ```
183
+
184
+ ## Notes
185
+
186
+ - Add `touch-action: none` on the draggable element to prevent the browser from scrolling while dragging.
187
+ - The composable attaches automatically on mount (`immediate: true` by default) and cleans up on unmount; use `start()` / `stop()` for manual control.
188
+ - `onEnd` only fires when an actual drag happened (the threshold was reached), so a simple tap will not trigger it.
189
+ - The target can be a ref, a getter or a CSS selector string, and the listeners re-attach automatically when it changes.
190
+
191
+ <script lang="ts" setup>
192
+ import { useDrag } from 'maz-ui/composables/useDrag'
193
+ import { ref } from 'vue'
194
+
195
+ const dragHandle = ref()
196
+ const dragOffset = ref(0)
197
+
198
+ const { isDragging: dragging, direction: dragDirection } = useDrag(dragHandle, {
199
+ axis: 'y',
200
+ onMove: ({ offsetY }) => {
201
+ dragOffset.value = Math.max(0, offsetY)
202
+ },
203
+ onEnd: () => {
204
+ dragOffset.value = 0
205
+ },
206
+ })
207
+ </script>
208
+
209
+ <style>
210
+ .drag-demo {
211
+ border: 1px solid var(--vp-c-divider);
212
+ border-radius: 12px;
213
+ padding: 1rem;
214
+ height: 220px;
215
+ display: flex;
216
+ justify-content: center;
217
+ align-items: flex-start;
218
+ overflow: hidden;
219
+ }
220
+ .drag-card {
221
+ touch-action: none;
222
+ cursor: grab;
223
+ user-select: none;
224
+ width: 100%;
225
+ max-width: 320px;
226
+ padding: 2.5rem 1rem;
227
+ border-radius: 12px;
228
+ text-align: center;
229
+ font-size: 1.1rem;
230
+ color: white;
231
+ background: var(--vp-c-brand-1, #6366f1);
232
+ }
233
+ .drag-card:not(.--dragging) {
234
+ transition: transform 0.25s ease;
235
+ }
236
+ .drag-card.--dragging {
237
+ cursor: grabbing;
238
+ }
239
+ </style>
@@ -151,7 +151,7 @@ Each field in `fieldsStates` contains:
151
151
  v-model="stateModel.age"
152
152
  label="Age (18-100)"
153
153
  type="number"
154
- :hint="stateErrors.age"s
154
+ :hint="stateErrors.age"
155
155
  :error="!!stateErrors.age"
156
156
  :success="stateFields.age.valid"
157
157
  />
@@ -365,7 +365,7 @@ Requires `useFormField` with `ref` option or `validationEvents`.
365
365
  :success="eagerEmailValid"
366
366
  :class="{ 'has-error-eager': eagerEmailHasError }"
367
367
  />
368
- <MazBtn type="submit" :loading="eagerSubmitting">Submit</MazBtn>
368
+ <MazBtn type="submit" :loading="eagerSubmitting" :disabled="!eagerIsValid">Submit</MazBtn>
369
369
  </form>
370
370
 
371
371
  <template #code>
@@ -381,7 +381,7 @@ const schema = {
381
381
  email: pipe(string(), nonEmpty('Required'), email('Invalid email')),
382
382
  }
383
383
 
384
- const { isSubmitting, handleSubmit } = useFormValidator({
384
+ const { isSubmitting, handleSubmit, isValid } = useFormValidator({
385
385
  schema,
386
386
  options: {
387
387
  mode: 'eager',
@@ -430,6 +430,8 @@ const {
430
430
  :error="emailHasError"
431
431
  :success="emailValid"
432
432
  />
433
+
434
+ <MazBtn type="submit" :loading="isSubmitting" :disabled="!isValid">Submit</MazBtn>
433
435
  </form>
434
436
  </template>
435
437
  ```
@@ -614,6 +616,8 @@ const { value: name, hasError, errorMessage, isValid } = useFormField<string>('n
614
616
 
615
617
  Pass a template ref to `useFormField`. It will automatically detect interactive elements and attach blur listeners.
616
618
 
619
+ The `ref` option is **reactive**: if the field is rendered conditionally (e.g. with `v-if`), the blur listeners are attached automatically as soon as the element appears in the DOM, and removed when it is unmounted. You don't need to handle anything special.
620
+
617
621
  ```vue
618
622
  <script setup>
619
623
  import { useFormField } from 'maz-ui/composables'
@@ -635,6 +639,41 @@ const { value, errorMessage, hasError } = useFormField<string>('email', {
635
639
  </template>
636
640
  ```
637
641
 
642
+ Because it is reactive, the same code works even when the input is wrapped in a `v-if`:
643
+
644
+ ```vue
645
+ <script setup>
646
+ import { useFormField } from 'maz-ui/composables'
647
+ import { useTemplateRef, ref } from 'vue'
648
+
649
+ const isVisible = ref(false)
650
+
651
+ const { value, errorMessage, hasError } = useFormField<string>('email', {
652
+ ref: useTemplateRef('emailRef'),
653
+ formIdentifier: 'my-form',
654
+ })
655
+ </script>
656
+
657
+ <template>
658
+ <MazInput
659
+ v-if="isVisible"
660
+ ref="emailRef"
661
+ v-model="value"
662
+ :hint="errorMessage"
663
+ :error="hasError"
664
+ />
665
+ </template>
666
+ ```
667
+
668
+ You can also pass a raw `HTMLElement` directly. In that case it won't be reactive, so the element must already exist in the DOM:
669
+
670
+ ```ts
671
+ const { value } = useFormField<string>('email', {
672
+ ref: document.querySelector('input'),
673
+ formIdentifier: 'my-form',
674
+ })
675
+ ```
676
+
638
677
  #### Option 2: Using `validationEvents`
639
678
 
640
679
  If your component emits a `blur` event, you can use `v-bind` with `validationEvents`.
@@ -1074,7 +1113,7 @@ useFormField<FieldType>(
1074
1113
  options?: {
1075
1114
  defaultValue?: FieldType, // Default value for this field
1076
1115
  mode?: 'lazy' | 'aggressive' | 'eager' | 'blur' | 'progressive', // Override form mode
1077
- ref?: Ref<HTMLElement | ComponentInstance>, // Template ref for blur detection
1116
+ ref?: Ref<HTMLElement | ComponentInstance> | HTMLElement, // Reactive template ref (v-if friendly) or raw element
1078
1117
  formIdentifier?: string | symbol, // Must match useFormValidator's identifier
1079
1118
  }
1080
1119
  )
@@ -1113,7 +1152,7 @@ interface FormValidatorOptions<Model> {
1113
1152
  interface FormFieldOptions<FieldType> {
1114
1153
  defaultValue?: FieldType
1115
1154
  mode?: 'eager' | 'lazy' | 'aggressive' | 'blur' | 'progressive'
1116
- ref?: Ref<HTMLElement | ComponentInstance>
1155
+ ref?: Ref<HTMLElement | ComponentInstance> | HTMLElement
1117
1156
  formIdentifier?: string | symbol
1118
1157
  }
1119
1158
 
@@ -1166,14 +1205,13 @@ const { value, validationEvents } = useFormField<string>('name')
1166
1205
  // Then: v-bind="validationEvents" on your input
1167
1206
  ```
1168
1207
 
1169
- ### Element Not Found Warning
1208
+ ### Conditionally Rendered Fields (`v-if`)
1170
1209
 
1171
- **Problem**: `No element found for ref in field 'name'`
1210
+ The `ref` option is reactive, so a field wrapped in `v-if` works out of the box: blur listeners are attached as soon as the element is rendered and removed when it is unmounted.
1172
1211
 
1173
- **Solutions**:
1174
- 1. Ensure the ref is bound to an HTML element or Vue component
1175
- 2. Make sure the component has a `$el` property
1176
- 3. For custom components, add `data-interactive` attribute
1212
+ If blur validation still doesn't trigger:
1213
+ 1. Ensure the `ref` is bound to an HTML element or a Vue component exposing `$el`
1214
+ 2. For custom components, add the `data-interactive` attribute
1177
1215
 
1178
1216
  ### Mismatched Form Identifiers
1179
1217
 
@@ -1310,6 +1348,7 @@ const eagerSchema = {
1310
1348
  const {
1311
1349
  isSubmitting: eagerSubmitting,
1312
1350
  handleSubmit: handleEager,
1351
+ isValid: eagerIsValid,
1313
1352
  } = useFormValidator({
1314
1353
  schema: eagerSchema,
1315
1354
  options: { mode: 'eager', scrollToError: '.has-error-eager', identifier: 'form-eager' },
@@ -12,11 +12,19 @@ description: useSwipe is a Vue composable that simplifies the management of "swi
12
12
  `useSwipe` allows you to detect and react to swiping movements on an HTML element. It provides you with various information about the swipe movement, such as the direction, distance, start, and end coordinates.
13
13
  You can use this information to implement specific interactions in your application, such as scrolling a carousel, opening a side menu, etc.
14
14
 
15
+ It is built on top of [Pointer Events](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events), so it works with **touch, mouse and pen** out of the box.
16
+
17
+ ::: tip
18
+ For a real-time drag gesture (follow the pointer, snap back, drag-to-dismiss…) rather than discrete directional detection, use [useDrag](./use-drag.md).
19
+ :::
20
+
15
21
  ## Key Features
16
22
 
17
23
  - Detects swipes in all 4 directions (left, right, up, down)
24
+ - Works with touch, mouse and pen (Pointer Events)
18
25
  - Provides key information about the swipe movement (start/end coordinates, horizontal/vertical distance)
19
26
  - Allows you to configure callbacks for each swipe direction
27
+ - Restrict the gesture to specific pointer types
20
28
  - Possibility to customize the swipe detection threshold
21
29
  - Automatically handles the addition and removal of event listeners
22
30
  - Can be used with any HTML element
@@ -27,7 +35,7 @@ You can use this information to implement specific interactions in your applicat
27
35
  <p>
28
36
  Swipe in any direction<br>
29
37
  <span class="maz:text-xs maz:text-muted">
30
- (You should use a real device or a mobile simulator to test the swipe functionality)
38
+ (works with touch, mouse and pen)
31
39
  </span>
32
40
  <br><br>
33
41
  Last swipe direction: {{lastSwipeDirection || 'None'}}
@@ -74,7 +82,7 @@ onUnmounted(() => {
74
82
  <p>
75
83
  Swipe in any direction<br>
76
84
  <span class="maz:text-sm maz:text-muted">
77
- (You should use a real device or a mobile simulator to test the swipe functionality)
85
+ (works with touch, mouse and pen)
78
86
  </span>
79
87
  <br><br>
80
88
  Last swipe direction: {{ lastSwipeDirection || 'None' }}
@@ -153,35 +161,41 @@ interface UseSwipeOptions {
153
161
  */
154
162
  element: HTMLElement | string | Ref<HTMLElement>
155
163
  /** Callback executed when a left swipe is detected. */
156
- onLeft?: (event: TouchEvent) => void
164
+ onLeft?: (event: PointerEvent) => void
157
165
  /** Callback executed when a right swipe is detected. */
158
- onRight?: (event: TouchEvent) => void
166
+ onRight?: (event: PointerEvent) => void
159
167
  /** Callback executed when an up swipe is detected. */
160
- onUp?: (event: TouchEvent) => void
168
+ onUp?: (event: PointerEvent) => void
161
169
  /** Callback executed when a down swipe is detected. */
162
- onDown?: (event: TouchEvent) => void
170
+ onDown?: (event: PointerEvent) => void
163
171
  /**
164
172
  * The minimum distance the swipe must travel to be considered valid.
165
173
  * @default 50
166
174
  */
167
175
  threshold?: number
168
176
  /**
169
- * Whether to prevent the default behavior of the touchmove event.
177
+ * Pointer types that can trigger the swipe.
178
+ * @default ['mouse', 'touch', 'pen']
179
+ */
180
+ pointerTypes?: ('mouse' | 'touch' | 'pen')[]
181
+ /**
182
+ * Whether to prevent the default behavior of the pointer move event
183
+ * (the move listener becomes non-passive when enabled).
170
184
  * @default false
171
185
  */
172
- preventDefaultOnTouchMove?: boolean
186
+ preventDefaultOnMove?: boolean
173
187
  /**
174
188
  * Whether to prevent the default behavior of the mousewheel event.
175
189
  * @default false
176
190
  */
177
191
  preventDefaultOnMouseWheel?: boolean
178
192
  /**
179
- * Whether to trigger the swipe event immediately on touchstart/mousedown.
193
+ * Whether to start listening immediately on instantiation.
180
194
  * @default false
181
195
  */
182
196
  immediate?: boolean
183
197
  /**
184
- * Whether to trigger the swipe event only on touchend/mouseup.
198
+ * Whether to trigger the swipe event only on pointer up.
185
199
  * @default false
186
200
  */
187
201
  triggerOnEnd?: boolean
@@ -220,4 +234,5 @@ interface UseSwipeReturn {
220
234
  - If you use the composable in a Vue component, make sure to call it in the `setup()` and clean up the event listeners in the `onUnmounted()`.
221
235
  - The composable automatically handles the addition and removal of event listeners based on the provided options.
222
236
  - You can customize the swipe detection threshold by modifying the `threshold` option.
223
- - If you want to prevent the default behavior of touchmove or mousewheel events, you can set the `preventDefaultOnTouchMove` and `preventDefaultOnMouseWheel` options, respectively.
237
+ - If you want to prevent the default behavior of pointer move or mousewheel events, you can set the `preventDefaultOnMove` and `preventDefaultOnMouseWheel` options, respectively.
238
+ - Use the `pointerTypes` option to restrict the gesture to specific input types (e.g. `['touch']` for touch-only).
@@ -11,8 +11,7 @@ description: vClickOutside is a Vue directive to trigger a function when the use
11
11
 
12
12
  <ComponentDemo>
13
13
  <div
14
- style="padding: 50px; background-color: var(--maz-surface-300);"
15
- class="maz:flex maz:flex-center maz:rounded-md"
14
+ class="maz:flex maz:flex-center maz:rounded-md maz:p-12 maz:bg-surface-300"
16
15
  >
17
16
  <MazCard v-click-outside="clikedOutside">
18
17
  Click outside me
@@ -21,8 +20,7 @@ description: vClickOutside is a Vue directive to trigger a function when the use
21
20
 
22
21
  <div
23
22
  v-if="hasClikedOutside"
24
- style="padding: 16px; margin-top: 16px; background-color: var(--maz-success); color: black;"
25
- class="maz:flex maz:flex-center maz:rounded-md"
23
+ class="maz:flex maz:flex-center maz:rounded-md maz:bg-sucess maz:text-success-foreground maz:p-4 maz:mt-4"
26
24
  >
27
25
  You clicked outside
28
26
  </div>
@@ -44,8 +42,7 @@ function clikedOutside() {
44
42
 
45
43
  <template>
46
44
  <div
47
- style="padding: 50px; background-color: var(--maz-surface-300);"
48
- class="flex flex-center rounded"
45
+ class="maz:flex maz:flex-center maz:rounded-md maz:p-12 maz:bg-surface-300"
49
46
  >
50
47
  <MazCard v-click-outside="clikedOutside">
51
48
  Click outside me
@@ -54,8 +51,7 @@ function clikedOutside() {
54
51
 
55
52
  <div
56
53
  v-if="hasClikedOutside"
57
- style="padding: 16px; margin-top: 16px; background-color: var(--maz-success); color: black;"
58
- class="flex flex-center rounded"
54
+ class="maz:flex maz:flex-center maz:rounded-md maz:bg-sucess maz:text-success-foreground maz:p-4 maz:mt-4"
59
55
  >
60
56
  You clicked outside
61
57
  </div>
@@ -71,8 +67,7 @@ The directive can accept an options object to customize its behavior:
71
67
 
72
68
  <ComponentDemo>
73
69
  <div
74
- style="padding: 50px; background-color: var(--maz-surface-300);"
75
- class="maz:flex maz:flex-center maz:rounded-md"
70
+ class="maz:flex maz:flex-center maz:rounded-md maz:p-12 maz:bg-surface-300"
76
71
  >
77
72
  <MazCard v-click-outside="{ callback: clickedOutsideWithIgnore, ignore: ['.ignore-me'] }">
78
73
  <div class="maz:p-4">
@@ -86,8 +81,7 @@ The directive can accept an options object to customize its behavior:
86
81
 
87
82
  <div
88
83
  v-if="hasClickedOutsideWithIgnore"
89
- style="padding: 16px; margin-top: 16px; background-color: var(--maz-warning); color: black;"
90
- class="maz:flex maz:flex-center maz:rounded-md"
84
+ class="maz:flex maz:flex-center maz:rounded-md maz:bg-sucess maz:text-success-foreground maz:p-4 maz:mt-4"
91
85
  >
92
86
  You clicked outside (button clicks are ignored)
93
87
  </div>
@@ -128,8 +122,7 @@ The directive can be configured to trigger only once:
128
122
 
129
123
  <ComponentDemo>
130
124
  <div
131
- style="padding: 50px; background-color: var(--maz-surface-300);"
132
- class="maz:flex maz:flex-center maz:rounded-md"
125
+ class="maz:flex maz:flex-center maz:rounded-md maz:p-12 maz:bg-surface-300"
133
126
  >
134
127
  <MazCard v-click-outside="{ callback: clickedOnce, once: true }">
135
128
  Click outside me (works only once)
@@ -249,7 +242,7 @@ app.mount('#app')
249
242
 
250
243
  ### Nuxt
251
244
 
252
- Please refer to the [Nuxt module documentation](./../guide/nuxt.md) for more information.
245
+ Please refer to the [Nuxt module documentation](./../ecosystem/nuxt.md) for more information.
253
246
 
254
247
  <script lang="ts" setup>
255
248
  import { ref } from 'vue'
@@ -83,7 +83,7 @@ app.mount('#app')
83
83
 
84
84
  ### Nuxt
85
85
 
86
- Please refer to the [Nuxt module documentation](./../guide/nuxt.md) for more information.
86
+ Please refer to the [Nuxt module documentation](./../ecosystem/nuxt.md) for more information.
87
87
 
88
88
  ## Types
89
89