@maz-ui/mcp 5.0.0-beta.49 → 5.0.0-beta.50

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/dist/mcp.mjs CHANGED
@@ -7,7 +7,7 @@ import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
7
7
  import { resolve, join, dirname } from 'node:path';
8
8
  import { fileURLToPath } from 'node:url';
9
9
 
10
- const version = "5.0.0-beta.48";
10
+ const version = "5.0.0-beta.49";
11
11
 
12
12
  class MetadataExtractor {
13
13
  extract(name, type, content, manualTags = []) {
@@ -1,31 +1,50 @@
1
1
  ## Props
2
2
 
3
- | Name | Description | Type | Required |
4
- | ---------------------- | ----------- | ---------------- | -------- |
5
- | **distance** | | `number` | No |
6
- | **offset** | | `number` | No |
7
- | **on-refresh** | | `TSFunctionType` | No |
8
- | **container-selector** | | `string` | No |
9
- | **header-class** | | `string` | No |
10
- | **spinner-color** | | `MazColor` | No |
11
- | **disabled** | | `boolean` | No |
12
- | **standalone-mode** | | `boolean` | No |
3
+ | Name | Description | Type | Required | Default |
4
+ | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -------- | ---------------------------------------- |
5
+ | **on-refresh** | Function called when the user releases after pulling far enough. The spinner stays visible until the returned promise settles. Without it, the component does nothing. | `TSFunctionType` | No | `undefined` |
6
+ | **distance** | Pull distance (in px, after resistance) required to trigger a refresh | `number` | No | `80` |
7
+ | **max-distance** | Maximum pull distance (in px), reached with a rubber band effect beyond `distance` | `number` | No | `distance * 1.6` |
8
+ | **resistance** | Ratio between the finger movement and the pull distance, between 0 and 1. Lower is stiffer. | `number` | No | `0.5` |
9
+ | **min-duration** | Minimum duration (in ms) of the refreshing state, so the feedback stays visible on fast refreshes | `number` | No | `400` |
10
+ | **container-selector** | CSS selector of the scroll container. By default, the closest scrollable ancestor of the component, or the window. The pull only starts when this container is scrolled to the top. | `string` | No | `undefined` |
11
+ | **header-class** | Class of the header that holds the indicator | `Native type` | No | `undefined` |
12
+ | **spinner-color** | Color of the progress ring and the spinner | `MazColor` | No | `primary` |
13
+ | **disabled** | Disable the pull to refresh | `boolean` | No | `false` |
14
+ | **standalone-mode** | Only enable the pull to refresh when the app runs as an installed PWA (standalone display mode), browsers already provide their own pull to refresh | `boolean` | No | `false` |
15
+ | **haptic** | Vibrate briefly when the pull reaches `distance` (devices supporting `navigator.vibrate`) | `boolean` | No | `true` |
16
+ | **translations** | Translations of the pull to refresh | `DeepPartial<MazUiTranslationsNestedSchema['pullToRefresh']>` | No | `Translations from @maz-ui/translations` |
17
+ | **offset** | | `number` | No | `undefined` |
13
18
 
14
19
  ## Events
15
20
 
16
- | Event name | Properties | Description |
17
- | ---------- | ---------- | ----------- |
18
- | loaded | |
19
- | start | |
20
- | error | |
21
- | finish | |
22
- | response | |
21
+ | Event name | Properties | Description |
22
+ | ---------- | ---------- | -------------------------------------------------------- |
23
+ | start | | Emitted when the refresh starts |
24
+ | loaded | | Emitted when `onRefresh` resolved |
25
+ | response | | Emitted with the value resolved by `onRefresh` |
26
+ | error | | Emitted when `onRefresh` threw or rejected |
27
+ | finish | | Emitted when the refresh ends, after `loaded` or `error` |
23
28
 
24
29
  ## Slots
25
30
 
26
31
  | Name | Description | Bindings |
27
32
  | ------------ | ----------- | -------- |
28
- | pull-before | | |
29
- | pull-ready | | |
30
- | pull-loading | | |
33
+ | pull-loading | | <br/> |
34
+ | pull-ready | | <br/> |
35
+ | pull-before | | <br/> |
31
36
  | default | | |
37
+
38
+ ## Expose
39
+
40
+ ### refresh
41
+
42
+ > Run the refresh programmatically (a "refresh" button for keyboard and mouse users)
43
+
44
+ ### isRefreshing
45
+
46
+ > `onRefresh` is running
47
+
48
+ ### progress
49
+
50
+ > Pull progress towards `distance`, from 0 to 1
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: MazPullToRefresh
3
- description: MazPullToRefresh is a standalone component to add pull to refresh feature
3
+ description: MazPullToRefresh adds a native-feeling pull to refresh gesture to your app or to any scroll container, with a progress ring, haptic feedback and translated, accessible feedback.
4
4
  ---
5
5
 
6
6
  # {{ $frontmatter.title }}
@@ -9,41 +9,200 @@ description: MazPullToRefresh is a standalone component to add pull to refresh f
9
9
 
10
10
  <!--@include: ./../../.vitepress/mixins/getting-started.md-->
11
11
 
12
+ ## Key Features
13
+
14
+ - Works on the window **and on any scroll container**: the closest scrollable ancestor is detected automatically, so it fits app shells with a fixed layout and a scrolling `<main>`
15
+ - Starts only when the container is scrolled to the top, never in the middle of a list
16
+ - Rubber band resistance beyond the trigger distance, and a progress ring that fills while pulling
17
+ - Ignores horizontal swipes and multi-touch gestures, and prevents the native bounce (and the browser's own pull to refresh) while pulling
18
+ - Haptic feedback when the trigger distance is reached (devices supporting `navigator.vibrate`)
19
+ - Texts from [@maz-ui/translations](./../ecosystem/translations.md), overridable with the `translations` prop or the slots
20
+ - Accessible: the refresh is announced to screen readers, `aria-busy` is set while refreshing, and `refresh()` is exposed for a button usable with a keyboard or a mouse
21
+ - Optional `standalone-mode` to enable it only in an installed PWA (browsers already have their own pull to refresh)
22
+ - Built on the headless [usePullToRefresh](./../composables/use-pull-to-refresh.md) composable
23
+
12
24
  ## Demo
13
25
 
14
- ![MazPullToRefresh](/img/maz-pull-to-refresh.gif)
26
+ <div class="maz:flex maz:flex-col maz:items-center maz:gap-3 vp-raw">
27
+ <p class="maz:text-sm maz:text-muted">
28
+ Pull down inside the box on a touch device (or with the touch emulation of your browser's device toolbar).
29
+ </p>
30
+ <div class="maz:h-80 maz:w-full maz:max-w-sm maz:overflow-y-auto maz:rounded-lg maz:border maz:border-divider maz:bg-container">
31
+ <MazPullToRefresh ref="demo" :on-refresh="refreshDemo">
32
+ <ul class="maz:m-0 maz:list-none maz:p-0">
33
+ <li v-for="item in items" :key="item" class="maz:border-b maz:border-divider maz:px-4 maz:py-3">
34
+ {{ item }}
35
+ </li>
36
+ </ul>
37
+ </MazPullToRefresh>
38
+ </div>
39
+ <MazBtn size="sm" :loading="demo?.isRefreshing" @click="demo?.refresh()">
40
+ Refresh ({{ refreshCount }})
41
+ </MazBtn>
42
+ </div>
43
+
44
+ <script lang="ts" setup>
45
+ import { ref, useTemplateRef } from 'vue'
46
+
47
+ const demo = useTemplateRef('demo')
48
+ const refreshCount = ref(0)
49
+ const items = ref(Array.from({ length: 20 }, (_, index) => `Item ${index + 1}`))
50
+
51
+ async function refreshDemo() {
52
+ await new Promise(resolve => setTimeout(resolve, 1000))
53
+ refreshCount.value++
54
+ items.value = [`New item ${refreshCount.value}`, ...items.value]
55
+ }
56
+ </script>
15
57
 
16
58
  ## Basic usage
17
59
 
18
- Wrap your app inside this component
60
+ Wrap your app (or a page) inside the component and give it the function that reloads your data. The spinner stays visible until the returned promise settles.
19
61
 
20
62
  ```vue
21
63
  <script lang="ts" setup>
22
64
  import MazPullToRefresh from 'maz-ui/components/MazPullToRefresh'
23
65
 
24
- async function pullToRefreshAction() {
25
- // do promise or just `window.location.reload()`
66
+ async function refresh() {
67
+ await fetchData()
26
68
  }
27
69
  </script>
28
70
 
71
+ <template>
72
+ <MazPullToRefresh :on-refresh="refresh">
73
+ <main>App content</main>
74
+ </MazPullToRefresh>
75
+ </template>
76
+ ```
77
+
78
+ With Nuxt, `refreshNuxtData` reloads every `useFetch` / `useAsyncData` of the page:
79
+
80
+ ```vue
81
+ <template>
82
+ <MazPullToRefresh :on-refresh="() => refreshNuxtData()" standalone-mode>
83
+ <NuxtPage />
84
+ </MazPullToRefresh>
85
+ </template>
86
+ ```
87
+
88
+ ## Inside a scroll container
89
+
90
+ The pull can only start when its scroll container is at the top. By default, the component uses its **closest scrollable ancestor** (`overflow-y: auto | scroll`), or the window if there is none. Typical app shells with a fixed layout and a scrolling `<main>` work without configuration:
91
+
92
+ ```vue
93
+ <template>
94
+ <div class="app-shell maz:fixed maz:inset-0 maz:flex maz:flex-col">
95
+ <header>…</header>
96
+ <main class="maz:flex-1 maz:overflow-y-auto">
97
+ <MazPullToRefresh :on-refresh="refresh">
98
+ <slot />
99
+ </MazPullToRefresh>
100
+ </main>
101
+ </div>
102
+ </template>
103
+ ```
104
+
105
+ Use `container-selector` when the scroll container is not an ancestor of the component:
106
+
107
+ ```vue
108
+ <template>
109
+ <MazPullToRefresh container-selector="#page-scroller" :on-refresh="refresh">
110
+ …
111
+ </MazPullToRefresh>
112
+ </template>
113
+ ```
114
+
115
+ ## Installed apps only
116
+
117
+ Browsers already provide their own pull to refresh. With `standalone-mode`, the component is only active when the app runs as an installed PWA (`display-mode: standalone`):
118
+
119
+ ```vue
120
+ <template>
121
+ <MazPullToRefresh standalone-mode :on-refresh="refresh">
122
+ …
123
+ </MazPullToRefresh>
124
+ </template>
125
+ ```
126
+
127
+ ## Tuning the gesture
128
+
129
+ | Prop | Default | Effect |
130
+ | -------------- | ---------------- | --------------------------------------------------------------------------------------- |
131
+ | `distance` | `80` | Pull distance (px, after resistance) needed to trigger a refresh |
132
+ | `max-distance` | `distance * 1.6` | Upper bound of the rubber band beyond `distance` |
133
+ | `resistance` | `0.5` | Ratio between the finger movement and the pull distance (lower is stiffer) |
134
+ | `min-duration` | `400` | Minimum duration (ms) of the refreshing state, so fast refreshes still show the feedback |
135
+ | `haptic` | `true` | Short vibration when `distance` is reached |
136
+
137
+ ## Customize the indicator
138
+
139
+ The three states have their own slot. Each one receives the pull `progress` (0 to 1) and the current `distance` in px.
140
+
141
+ ```vue
142
+ <template>
143
+ <MazPullToRefresh :on-refresh="refresh" header-class="maz:bg-surface-600">
144
+ <template #pull-before="{ progress }">
145
+ <span>{{ Math.round(progress * 100) }}%</span>
146
+ </template>
147
+ <template #pull-ready>
148
+ <span>Let go!</span>
149
+ </template>
150
+ <template #pull-loading>
151
+ <MazSpinner color="secondary" />
152
+ </template>
153
+
154
+ <main>App content</main>
155
+ </MazPullToRefresh>
156
+ </template>
157
+ ```
158
+
159
+ `spinner-color` sets the color of the progress ring, the ready arrow and the default spinner (`primary` by default).
160
+
161
+ ## Translations
162
+
163
+ Texts come from [@maz-ui/translations](./../ecosystem/translations.md) (`pullToRefresh.pull`, `pullToRefresh.release`, `pullToRefresh.refreshing`). Override them per instance with the `translations` prop:
164
+
165
+ ```vue
29
166
  <template>
30
167
  <MazPullToRefresh
31
- header-class="maz:bg-bg-dark maz:text-foreground-light"
32
- class="maz:flex maz:min-h-screen maz:w-full maz:flex-col"
33
- :on-refresh="pullToRefreshAction"
34
- spinner-color="contrast"
35
- standalone-mode
36
- :disabled="false"
168
+ :on-refresh="refresh"
169
+ :translations="{ pull: 'Swipe down', release: 'Release', refreshing: 'Updating…' }"
37
170
  >
38
- <div>
39
- App Content
40
- </div>
171
+ …
172
+ </MazPullToRefresh>
173
+ </template>
174
+ ```
175
+
176
+ ## Accessibility
177
+
178
+ The gesture is touch only. To give keyboard and mouse users the same action, call the exposed `refresh()` from a button: the indicator and the events behave exactly as with the gesture.
179
+
180
+ ```vue
181
+ <script lang="ts" setup>
182
+ import { useTemplateRef } from 'vue'
183
+
184
+ const pullToRefresh = useTemplateRef('pullToRefresh')
185
+ </script>
186
+
187
+ <template>
188
+ <MazBtn :loading="pullToRefresh?.isRefreshing" @click="pullToRefresh?.refresh()">
189
+ Refresh
190
+ </MazBtn>
191
+
192
+ <MazPullToRefresh ref="pullToRefresh" :on-refresh="refresh">
193
+ …
41
194
  </MazPullToRefresh>
42
195
  </template>
43
196
  ```
44
197
 
45
- ::: warning
46
- More documentation to come
47
- :::
198
+ While refreshing, the root element has `aria-busy="true"` and the refreshing text is announced through a polite live region. The visual indicator is hidden from assistive technologies.
199
+
200
+ ## Events
201
+
202
+ The events follow the life of a refresh: `start`, then `loaded` and `response` (with the value resolved by `on-refresh`) or `error`, and always `finish`. An error thrown by `on-refresh` is emitted, never thrown again.
203
+
204
+ ## Headless usage
205
+
206
+ Need a different indicator, or a gesture on an element without wrapping it? Use the [usePullToRefresh](./../composables/use-pull-to-refresh.md) composable.
48
207
 
49
208
  <!--@include: ./../../.vitepress/generated-docs/maz-pull-to-refresh.doc.md-->
@@ -0,0 +1,79 @@
1
+ ---
2
+ title: usePullToRefresh
3
+ description: usePullToRefresh is a headless Vue composable for the pull to refresh gesture on the window or any scroll container.
4
+ ---
5
+
6
+ # {{ $frontmatter.title }}
7
+
8
+ {{ $frontmatter.description }}
9
+
10
+ ## Introduction
11
+
12
+ `usePullToRefresh` tracks the pull to refresh gesture and gives you its state (distance, progress, ready, refreshing) to build your own indicator. It powers [MazPullToRefresh](./../components/maz-pull-to-refresh.md): use the component for a ready-made indicator, the composable when you need full control over the rendering.
13
+
14
+ The pull only starts when the target is scrolled to the top, follows a rubber band beyond the threshold, ignores horizontal and multi-touch gestures, and prevents the native bounce while pulling.
15
+
16
+ ## Basic usage
17
+
18
+ ```vue
19
+ <script lang="ts" setup>
20
+ import { usePullToRefresh } from 'maz-ui/composables'
21
+ import { useTemplateRef } from 'vue'
22
+
23
+ const scroller = useTemplateRef<HTMLElement>('scroller')
24
+
25
+ const { distance, progress, isReady, isRefreshing } = usePullToRefresh({
26
+ target: scroller,
27
+ onRefresh: () => fetchData(),
28
+ })
29
+ </script>
30
+
31
+ <template>
32
+ <div ref="scroller" class="maz:h-screen maz:overflow-y-auto">
33
+ <div class="maz:flex maz:items-end maz:justify-center maz:overflow-hidden" :style="{ height: `${distance}px` }">
34
+ <span v-if="isRefreshing">Refreshing…</span>
35
+ <span v-else-if="isReady">Release to refresh</span>
36
+ <span v-else :style="{ opacity: progress }">Pull to refresh</span>
37
+ </div>
38
+
39
+ <p>Content</p>
40
+ </div>
41
+ </template>
42
+ ```
43
+
44
+ Without `target`, the gesture is tracked on the window.
45
+
46
+ ## Options
47
+
48
+ | Option | Type | Default | Description |
49
+ | ------------- | -------------------------------------------- | ----------------- | ------------------------------------------------------------------------------------ |
50
+ | `onRefresh` | `() => unknown` | - | Called on release past the threshold, or by `refresh()` |
51
+ | `target` | `MaybeRefOrGetter<HTMLElement \| Window \| null>` | `window` | Scroll container receiving the gesture |
52
+ | `threshold` | `MaybeRefOrGetter<number>` | `80` | Pull distance (px, after resistance) needed to trigger a refresh |
53
+ | `maxDistance` | `MaybeRefOrGetter<number>` | `threshold * 1.6` | Upper bound of the rubber band |
54
+ | `resistance` | `MaybeRefOrGetter<number>` | `0.5` | Ratio between the finger movement and the pull distance |
55
+ | `minDuration` | `MaybeRefOrGetter<number>` | `400` | Minimum duration (ms) of the refreshing state |
56
+ | `haptic` | `MaybeRefOrGetter<boolean>` | `true` | Vibrate briefly when the threshold is reached |
57
+ | `disabled` | `MaybeRefOrGetter<boolean>` | `false` | Disable the gesture |
58
+ | `onError` | `(error: unknown) => void` | - | Called when `onRefresh` throws or rejects (the error is also exposed in `error`) |
59
+
60
+ ## Return
61
+
62
+ | Property | Type | Description |
63
+ | -------------- | --------------------------- | ------------------------------------------------------------ |
64
+ | `distance` | `Readonly<Ref<number>>` | Current pull distance in px |
65
+ | `progress` | `ComputedRef<number>` | Progress towards the threshold, from 0 to 1 |
66
+ | `isPulling` | `Readonly<Ref<boolean>>` | The user is pulling |
67
+ | `isReady` | `ComputedRef<boolean>` | Releasing now triggers a refresh |
68
+ | `isRefreshing` | `Readonly<Ref<boolean>>` | `onRefresh` is running |
69
+ | `error` | `Readonly<Ref<unknown>>` | Error of the last refresh, reset on each refresh |
70
+ | `refresh` | `() => Promise<void>` | Run the refresh programmatically (for a keyboard-usable button) |
71
+ | `start` | `() => void` | Attach the listeners (done automatically on mount) |
72
+ | `stop` | `() => void` | Detach the listeners (done automatically on unmount) |
73
+
74
+ ## Notes
75
+
76
+ - Inside a component, listeners are attached on mount and removed when the scope is disposed. Outside of a component, they are attached right away.
77
+ - When `target` changes (for example a ref resolved later), the listeners move to the new element.
78
+ - `refresh()` never throws: errors go to `error` and `onError`. Calling it while a refresh is running does nothing.
79
+ - SSR safe: nothing touches the DOM before mount.
@@ -365,6 +365,7 @@ const composables = {
365
365
  useReadingTime: true, // Reading time calculation
366
366
  useDisplayNames: true, // Display localized names
367
367
  useSwipe: true, // Swipe gestures
368
+ usePullToRefresh: true, // Pull to refresh gesture
368
369
 
369
370
  // 🔧 Advanced
370
371
  useFreezeValue: true, // Freeze reactive values
@@ -619,6 +619,15 @@ The upgrade tool rewrites this automatically on `<MazPullToRefresh>` tags (both
619
619
  rg "<MazPullToRefresh[^>]*\bon-?[Cc]lick" src/
620
620
  ```
621
621
 
622
+ The component was also rewritten on top of the new [usePullToRefresh](./../composables/use-pull-to-refresh.md) composable. Behavior changes to check:
623
+
624
+ - **The pull follows the scroll container.** It starts only when the closest scrollable ancestor (or `container-selector`, or the window) is at the top. In v4, only the window scroll was read, so a layout with a scrolling `<main>` refreshed in the middle of a list.
625
+ - **`distance` is now the indicator distance after resistance** (default `80`, was `100` of raw finger movement). With the default `resistance` of `0.5`, the trigger needs about 160px of finger movement. Lower `distance` or raise `resistance` for a shorter gesture.
626
+ - **`spinner-color` defaults to `primary`** (was `contrast`) and also colors the progress ring.
627
+ - **`offset` is deprecated** and has no effect.
628
+ - **Texts are translated** (`pullToRefresh.*` in `@maz-ui/translations`) instead of hard coded in English. The `pull-before`, `pull-ready` and `pull-loading` slots still replace them, and now receive `{ progress, distance }`.
629
+ - **An error thrown by `on-refresh` is emitted (`error`, then `finish`) and no longer thrown again**, so it does not end up as an unhandled rejection.
630
+
622
631
  ### 18. Root `maz-ui` import removed for utilities
623
632
 
624
633
  In v4, the bare `maz-ui` entry re-exported `@maz-ui/utils`, so you could write `import { sleep } from 'maz-ui'`. In v5 that root re-export is gone — import helpers from their package directly:
@@ -231,7 +231,7 @@ function showSuccess() {
231
231
  | -------------------- | --------------------------------------------------- |
232
232
  | **UI Management** | [`useToast`](./../composables/use-toast.md), [`useDialog`](./../composables/use-dialog.md), [`useTheme`](./../ecosystem/themes.md#usetheme-composable-api), [`useWait`](./../composables/use-wait.md) |
233
233
  | **Responsive** | [`useBreakpoints`](./../composables/use-breakpoints.md), [`useWindowSize`](./../composables/use-window-size.md) |
234
- | **User Interaction** | [`useUserVisibility`](./../composables/use-user-visibility.md), [`useIdleTimeout`](./../composables/use-idle-timeout.md), [`useSwipe`](./../composables/use-swipe.md) |
234
+ | **User Interaction** | [`useUserVisibility`](./../composables/use-user-visibility.md), [`useIdleTimeout`](./../composables/use-idle-timeout.md), [`useSwipe`](./../composables/use-swipe.md), [`usePullToRefresh`](./../composables/use-pull-to-refresh.md) |
235
235
  | **Form Handling** | [`useFormValidator`](./../composables/use-form-validator.md) |
236
236
  | **Advanced** | [`useTimer`](./../composables/use-timer.md), [`useStringMatching`](./../composables/use-string-matching.md) |
237
237
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@maz-ui/mcp",
3
3
  "type": "module",
4
- "version": "5.0.0-beta.49",
4
+ "version": "5.0.0-beta.50",
5
5
  "description": "Maz-UI ModelContextProtocol Client",
6
6
  "author": "Louis Mazel <me@loicmazuel.com>",
7
7
  "license": "MIT",
@@ -43,7 +43,7 @@
43
43
  "dependencies": {
44
44
  "@maz-ui/utils": "5.0.0-beta.46",
45
45
  "@modelcontextprotocol/sdk": "^1.32.0",
46
- "maz-ui": "5.0.0-beta.49"
46
+ "maz-ui": "5.0.0-beta.50"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@maz-ui/eslint-config": "5.0.0-beta.47",