@maz-ui/mcp 5.0.0-beta.3 → 5.0.0-beta.30

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 (151) 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-btn.doc.md +3 -2
  7. package/docs/generated-docs/maz-checkbox.doc.md +16 -17
  8. package/docs/generated-docs/maz-circular-progress-bar.doc.md +1 -1
  9. package/docs/generated-docs/maz-code-highlight.doc.md +11 -0
  10. package/docs/generated-docs/maz-container.doc.md +1 -0
  11. package/docs/generated-docs/maz-date-picker.doc.md +41 -41
  12. package/docs/generated-docs/maz-drawer.doc.md +7 -8
  13. package/docs/generated-docs/maz-dropdown.doc.md +3 -0
  14. package/docs/generated-docs/maz-expand-animation.doc.md +4 -4
  15. package/docs/generated-docs/maz-fullscreen-loader.doc.md +5 -5
  16. package/docs/generated-docs/maz-gallery.doc.md +15 -15
  17. package/docs/generated-docs/maz-input-code.doc.md +16 -16
  18. package/docs/generated-docs/maz-input-phone-number.doc.md +42 -38
  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 +5 -5
  45. package/docs/generated-docs/maz-textarea.doc.md +25 -24
  46. package/docs/generated-docs/maz-ticker.doc.md +1 -1
  47. package/docs/generated-docs/maz-timeline.doc.md +4 -4
  48. package/docs/generated-docs/maz-window-mockup.doc.md +23 -0
  49. package/docs/src/blog/v4.md +1 -1
  50. package/docs/src/blog/v5.md +5 -7
  51. package/docs/src/components/maz-avatar.md +29 -0
  52. package/docs/src/components/maz-btn.md +1 -1
  53. package/docs/src/components/maz-code-highlight.md +233 -0
  54. package/docs/src/components/maz-container.md +2 -2
  55. package/docs/src/components/maz-date-picker.md +1 -1
  56. package/docs/src/components/maz-dialog.md +46 -0
  57. package/docs/src/components/maz-dropdown.md +32 -16
  58. package/docs/src/components/maz-icon.md +2 -2
  59. package/docs/src/components/maz-input-phone-number.md +106 -103
  60. package/docs/src/components/maz-markdown-editor.md +369 -0
  61. package/docs/src/components/maz-sidebar.md +719 -0
  62. package/docs/src/components/maz-textarea.md +27 -1
  63. package/docs/src/components/maz-timeline.md +60 -0
  64. package/docs/src/components/maz-window-mockup.md +249 -0
  65. package/docs/src/composables/use-form-validator.md +50 -11
  66. package/docs/src/directives/click-outside.md +8 -15
  67. package/docs/src/directives/fullscreen-img.md +1 -1
  68. package/docs/src/directives/lazy-img.md +5 -5
  69. package/docs/src/directives/tooltip.md +24 -1
  70. package/docs/src/directives/zoom-img.md +1 -1
  71. package/docs/src/ecosystem/eslint-config.md +95 -1
  72. package/docs/src/{guide/icons.md → ecosystem/icons/index.md} +1 -1
  73. package/docs/src/ecosystem/node/exec-promise.md +87 -0
  74. package/docs/src/ecosystem/node/index.md +53 -0
  75. package/docs/src/ecosystem/node/logger.md +146 -0
  76. package/docs/src/ecosystem/node/print-banner.md +93 -0
  77. package/docs/src/{guide → ecosystem}/nuxt.md +81 -47
  78. package/docs/src/{guide → ecosystem}/themes.md +153 -72
  79. package/docs/src/{guide → ecosystem}/translations.md +1 -1
  80. package/docs/src/ecosystem/utils/camel-case.md +31 -0
  81. package/docs/src/{helpers → ecosystem/utils}/capitalize.md +2 -3
  82. package/docs/src/ecosystem/utils/check-availability.md +79 -0
  83. package/docs/src/ecosystem/utils/cookie.md +80 -0
  84. package/docs/src/{helpers → ecosystem/utils}/currency.md +2 -2
  85. package/docs/src/{helpers → ecosystem/utils}/date.md +2 -2
  86. package/docs/src/ecosystem/utils/debounce-callback.md +38 -0
  87. package/docs/src/ecosystem/utils/debounce-id.md +69 -0
  88. package/docs/src/ecosystem/utils/debounce.md +65 -0
  89. package/docs/src/ecosystem/utils/fetch-locale-ip.md +33 -0
  90. package/docs/src/ecosystem/utils/format-json.md +33 -0
  91. package/docs/src/ecosystem/utils/format-phone-number.md +37 -0
  92. package/docs/src/ecosystem/utils/get-browser-locale.md +29 -0
  93. package/docs/src/ecosystem/utils/get-error-message.md +39 -0
  94. package/docs/src/ecosystem/utils/idle-timeout.md +90 -0
  95. package/docs/src/ecosystem/utils/index.md +60 -0
  96. package/docs/src/ecosystem/utils/is-client.md +32 -0
  97. package/docs/src/ecosystem/utils/is-equal.md +38 -0
  98. package/docs/src/ecosystem/utils/is-server.md +31 -0
  99. package/docs/src/ecosystem/utils/is-standalone-mode.md +43 -0
  100. package/docs/src/ecosystem/utils/kebab-case.md +36 -0
  101. package/docs/src/ecosystem/utils/normalize-string.md +77 -0
  102. package/docs/src/{helpers → ecosystem/utils}/number.md +2 -2
  103. package/docs/src/ecosystem/utils/pascal-case.md +35 -0
  104. package/docs/src/ecosystem/utils/script-loader.md +77 -0
  105. package/docs/src/ecosystem/utils/sleep.md +59 -0
  106. package/docs/src/ecosystem/utils/snake-case.md +36 -0
  107. package/docs/src/ecosystem/utils/swipe-handler.md +91 -0
  108. package/docs/src/ecosystem/utils/textarea-autogrow.md +41 -0
  109. package/docs/src/ecosystem/utils/throttle-id.md +48 -0
  110. package/docs/src/ecosystem/utils/throttle.md +57 -0
  111. package/docs/src/ecosystem/utils/truthy-filter.md +31 -0
  112. package/docs/src/ecosystem/utils/types/deep-key-of.md +48 -0
  113. package/docs/src/ecosystem/utils/types/deep-partial.md +42 -0
  114. package/docs/src/ecosystem/utils/types/deep-required.md +39 -0
  115. package/docs/src/ecosystem/utils/types/flatten-object-keys.md +44 -0
  116. package/docs/src/ecosystem/utils/types/generic-instance-type.md +42 -0
  117. package/docs/src/ecosystem/utils/types/infer-maybe-ref.md +35 -0
  118. package/docs/src/ecosystem/utils/upper-first.md +32 -0
  119. package/docs/src/ecosystem/utils/user-visibility.md +69 -0
  120. package/docs/src/guide/getting-started.md +15 -13
  121. package/docs/src/guide/global-defaults.md +101 -0
  122. package/docs/src/guide/maz-ui-provider.md +6 -3
  123. package/docs/src/guide/migration-v4.md +13 -9
  124. package/docs/src/guide/migration-v5.md +112 -13
  125. package/docs/src/guide/resolvers.md +7 -7
  126. package/docs/src/guide/tailwind.md +4 -0
  127. package/docs/src/guide/vue.md +4 -4
  128. package/docs/src/index.md +12 -12
  129. package/docs/src/plugins/aos.md +1 -1
  130. package/docs/src/plugins/wait.md +1 -1
  131. package/package.json +8 -7
  132. package/docs/src/helpers/camel-case.md +0 -14
  133. package/docs/src/helpers/check-availability.md +0 -14
  134. package/docs/src/helpers/debounce-callback.md +0 -14
  135. package/docs/src/helpers/debounce-id.md +0 -14
  136. package/docs/src/helpers/debounce.md +0 -14
  137. package/docs/src/helpers/is-client.md +0 -14
  138. package/docs/src/helpers/is-equal.md +0 -14
  139. package/docs/src/helpers/is-standalone-mode.md +0 -14
  140. package/docs/src/helpers/kebab-case.md +0 -14
  141. package/docs/src/helpers/normalize-string.md +0 -14
  142. package/docs/src/helpers/pascal-case.md +0 -14
  143. package/docs/src/helpers/script-loader.md +0 -14
  144. package/docs/src/helpers/sleep.md +0 -14
  145. package/docs/src/helpers/snake-case.md +0 -14
  146. package/docs/src/helpers/throttle-id.md +0 -14
  147. package/docs/src/helpers/throttle.md +0 -14
  148. /package/docs/src/{guide → ecosystem/icons}/icon-set.md +0 -0
  149. /package/docs/src/{guide → ecosystem}/mcp.md +0 -0
  150. /package/docs/src/{helpers → ecosystem/utils}/country-code-to-unicode-flag.md +0 -0
  151. /package/docs/src/{helpers → ecosystem/utils}/get-country-flag-url.md +0 -0
@@ -0,0 +1,48 @@
1
+ ---
2
+ title: throttleId
3
+ description: Throttle an async function with isolated state per identifier — runs immediately, then at most once per interval.
4
+ ---
5
+
6
+ # {{ $frontmatter.title }}
7
+
8
+ {{ $frontmatter.description }}
9
+
10
+ `throttleId` is the async, keyed counterpart of [`throttle`](./throttle). The first call runs immediately and returns its promise; further calls within `interval` are coalesced and resolve to the result of the last replayed call.
11
+
12
+ ## Usage
13
+
14
+ ```ts
15
+ import { throttleId } from '@maz-ui/utils'
16
+
17
+ const trackEvent = throttleId(
18
+ 'analytics',
19
+ async (event: { name: string }) => {
20
+ return fetch('/track', { method: 'POST', body: JSON.stringify(event) })
21
+ },
22
+ 1000,
23
+ )
24
+
25
+ trackEvent({ name: 'scroll' })
26
+ trackEvent({ name: 'scroll' }) // coalesced into the first call
27
+ ```
28
+
29
+ ## API
30
+
31
+ ```ts
32
+ function throttleId<T, Args extends unknown[]>(
33
+ identifier: string,
34
+ func: (...args: Args) => T | Promise<T>,
35
+ interval: number,
36
+ ): (...args: Args) => Promise<T>
37
+ ```
38
+
39
+ | Parameter | Type | Description |
40
+ | ------------ | ---------- | ------------------------------------------------------ |
41
+ | `identifier` | `string` | Unique key isolating this throttle from others |
42
+ | `func` | `Function` | The async (or sync) function to throttle |
43
+ | `interval` | `number` | Minimum interval between executions, in milliseconds |
44
+
45
+ ## Related
46
+
47
+ - [`debounceId`](./debounce-id) — wait for silence instead of rate-limiting.
48
+ - [`throttle`](./throttle) — non-async, single-instance throttle.
@@ -0,0 +1,57 @@
1
+ ---
2
+ title: throttle
3
+ description: Wrap a function so it runs immediately, then at most once every N milliseconds — perfect for scroll, mousemove and resize handlers.
4
+ ---
5
+
6
+ # {{ $frontmatter.title }}
7
+
8
+ {{ $frontmatter.description }}
9
+
10
+ Unlike [`debounce`](./debounce) — which waits for a quiet period — `throttle` lets the first call through and rate-limits the rest.
11
+
12
+ ## Usage
13
+
14
+ ```ts
15
+ import { throttle } from '@maz-ui/utils'
16
+
17
+ const onScroll = throttle(() => {
18
+ console.log('scroll position', window.scrollY)
19
+ }, 200)
20
+
21
+ window.addEventListener('scroll', onScroll)
22
+ ```
23
+
24
+ ## API
25
+
26
+ ```ts
27
+ function throttle<T extends (...args: any[]) => any>(
28
+ func: T,
29
+ limit: number,
30
+ ): (...args: Parameters<T>) => void
31
+ ```
32
+
33
+ | Parameter | Type | Description |
34
+ | --------- | ---------- | ------------------------------------------ |
35
+ | `func` | `Function` | The function to throttle |
36
+ | `limit` | `number` | Minimum interval between executions, in ms |
37
+
38
+ The first call always runs immediately. Subsequent calls within `limit` are coalesced — only the most recent set of arguments is replayed once the window elapses.
39
+
40
+ ## Examples
41
+
42
+ Throttle a window resize handler:
43
+
44
+ ```ts
45
+ import { throttle } from '@maz-ui/utils'
46
+
47
+ const onResize = throttle(() => {
48
+ console.log('width:', window.innerWidth)
49
+ }, 250)
50
+
51
+ window.addEventListener('resize', onResize)
52
+ ```
53
+
54
+ ## Related
55
+
56
+ - [`throttleId`](./throttle-id) — per-key throttle for async functions, returning a promise.
57
+ - [`debounce`](./debounce) — fires only once activity stops.
@@ -0,0 +1,31 @@
1
+ ---
2
+ title: truthyFilter
3
+ description: Type guard that filters out falsy values (`false`, `''`, `0`, `null`, `undefined`) while narrowing the TypeScript type.
4
+ ---
5
+
6
+ # {{ $frontmatter.title }}
7
+
8
+ {{ $frontmatter.description }}
9
+
10
+ Pass it directly to `Array.prototype.filter` to drop nullish/empty entries while telling TypeScript the result no longer contains those types.
11
+
12
+ ## Usage
13
+
14
+ ```ts
15
+ import { truthyFilter } from '@maz-ui/utils'
16
+
17
+ const items: (string | null | undefined)[] = ['a', null, 'b', undefined, '']
18
+ const cleaned = items.filter(truthyFilter)
19
+ // cleaned has type string[]
20
+ // cleaned = ['a', 'b']
21
+ ```
22
+
23
+ ## API
24
+
25
+ ```ts
26
+ type Truthy<T> = T extends false | '' | 0 | null | undefined ? never : T
27
+
28
+ function truthyFilter<T>(value: T): value is Truthy<T>
29
+ ```
30
+
31
+ The function returns `Boolean(value)` — its real value is in the type predicate, which narrows away the falsy variants for downstream type-checking.
@@ -0,0 +1,48 @@
1
+ ---
2
+ title: DeepKeyOf
3
+ description: Recursively build a union of dot-separated key paths for any nested object type.
4
+ ---
5
+
6
+ # {{ $frontmatter.title }}
7
+
8
+ {{ $frontmatter.description }}
9
+
10
+ Use it to type i18n keys, nested form paths, or any string that must reference a leaf of a known object shape.
11
+
12
+ ## Usage
13
+
14
+ ```ts
15
+ import type { DeepKeyOf } from '@maz-ui/utils'
16
+
17
+ interface Config {
18
+ app: {
19
+ name: string
20
+ theme: {
21
+ mode: 'light' | 'dark'
22
+ primary: string
23
+ }
24
+ }
25
+ version: number
26
+ }
27
+
28
+ type Keys = DeepKeyOf<Config>
29
+ // → 'app.name' | 'app.theme.mode' | 'app.theme.primary' | 'version'
30
+ ```
31
+
32
+ ## API
33
+
34
+ ```ts
35
+ type DeepKeyOf<T> = T extends object
36
+ ? { [K in keyof T]: K extends string
37
+ ? T[K] extends object
38
+ ? `${K}.${DeepKeyOf<T[K]>}`
39
+ : K
40
+ : never
41
+ }[keyof T]
42
+ : never
43
+ ```
44
+
45
+ ## Notes
46
+
47
+ - Numeric and symbol keys are excluded — only `string`-keyed properties are walked.
48
+ - Array types are objects, so `DeepKeyOf<{ items: string[] }>` produces `'items.0' | 'items.1' | …` only if the array has tuple typing. With a regular `string[]`, the recursion terminates at `'items'`.
@@ -0,0 +1,42 @@
1
+ ---
2
+ title: DeepPartial
3
+ description: Recursive variant of TypeScript's `Partial<T>` — every property at every depth becomes optional.
4
+ ---
5
+
6
+ # {{ $frontmatter.title }}
7
+
8
+ {{ $frontmatter.description }}
9
+
10
+ ## Usage
11
+
12
+ ```ts
13
+ import type { DeepPartial } from '@maz-ui/utils'
14
+
15
+ interface UserSettings {
16
+ notifications: {
17
+ email: boolean
18
+ push: boolean
19
+ }
20
+ theme: {
21
+ primary: string
22
+ secondary: string
23
+ }
24
+ }
25
+
26
+ const update: DeepPartial<UserSettings> = {
27
+ notifications: { email: false },
28
+ }
29
+ ```
30
+
31
+ ## API
32
+
33
+ ```ts
34
+ type DeepPartial<T> = T extends object
35
+ ? { [P in keyof T]?: DeepPartial<T[P]> }
36
+ : T
37
+ ```
38
+
39
+ ## Notes
40
+
41
+ - Primitives (`string`, `number`, `boolean`, `null`, `undefined`, …) are returned unchanged.
42
+ - Useful for partial-update payloads (`PATCH` requests, merge functions, default-options patterns).
@@ -0,0 +1,39 @@
1
+ ---
2
+ title: DeepRequired
3
+ description: Recursive variant of TypeScript's `Required<T>` — strips `?` from every property at every depth.
4
+ ---
5
+
6
+ # {{ $frontmatter.title }}
7
+
8
+ {{ $frontmatter.description }}
9
+
10
+ The mirror image of [`DeepPartial`](./deep-partial). Useful when you want a fully-resolved internal type derived from a public options interface.
11
+
12
+ ## Usage
13
+
14
+ ```ts
15
+ import type { DeepRequired } from '@maz-ui/utils'
16
+
17
+ interface Options {
18
+ cache?: {
19
+ ttl?: number
20
+ strategy?: 'memory' | 'disk'
21
+ }
22
+ }
23
+
24
+ type ResolvedOptions = DeepRequired<Options>
25
+ // {
26
+ // cache: {
27
+ // ttl: number
28
+ // strategy: 'memory' | 'disk'
29
+ // }
30
+ // }
31
+ ```
32
+
33
+ ## API
34
+
35
+ ```ts
36
+ type DeepRequired<T> = Required<{
37
+ [K in keyof T]: T[K] extends Required<T[K]> ? T[K] : DeepRequired<T[K]>
38
+ }>
39
+ ```
@@ -0,0 +1,44 @@
1
+ ---
2
+ title: FlattenObjectKeys
3
+ description: Build a union of dot-separated leaf paths for a nested object, with an optional prefix.
4
+ ---
5
+
6
+ # {{ $frontmatter.title }}
7
+
8
+ {{ $frontmatter.description }}
9
+
10
+ Similar to [`DeepKeyOf`](./deep-key-of) but only yields **leaf** paths (skips intermediate object keys), and accepts a `Prefix` parameter for namespacing.
11
+
12
+ ## Usage
13
+
14
+ ```ts
15
+ import type { FlattenObjectKeys } from '@maz-ui/utils'
16
+
17
+ interface Config {
18
+ app: {
19
+ name: string
20
+ version: number
21
+ }
22
+ debug: boolean
23
+ }
24
+
25
+ type Leaves = FlattenObjectKeys<Config>
26
+ // → 'app.name' | 'app.version' | 'debug'
27
+
28
+ type Namespaced = FlattenObjectKeys<Config, 'config.'>
29
+ // → 'config.app.name' | 'config.app.version' | 'config.debug'
30
+ ```
31
+
32
+ ## API
33
+
34
+ ```ts
35
+ type FlattenObjectKeys<T extends Record<string, any>, Prefix extends string = ''> = {
36
+ [K in keyof T]: T[K] extends Record<string, any>
37
+ ? FlattenObjectKeys<T[K], `${Prefix}${K extends string ? K : ''}.`>
38
+ : `${Prefix}${K extends string ? K : ''}`
39
+ }[keyof T]
40
+ ```
41
+
42
+ ## Notes
43
+
44
+ - Unlike `DeepKeyOf`, intermediate object keys (e.g. `'app'` in the example) are not included — only the paths that resolve to non-object leaves.
@@ -0,0 +1,42 @@
1
+ ---
2
+ title: GenericInstanceType
3
+ description: Extract the public instance type from a generic Vue component — solves the limitation where `InstanceType<typeof Component>` returns `any` for generic SFCs.
4
+ ---
5
+
6
+ # {{ $frontmatter.title }}
7
+
8
+ {{ $frontmatter.description }}
9
+
10
+ Vue's `InstanceType<typeof Component>` does not work on **generic** components (`<script setup lang="ts" generic="T">`). `GenericInstanceType` walks the type to recover the exposed methods/refs typing.
11
+
12
+ See the underlying TypeScript / Vue Language Tools issue: [vuejs/language-tools#3206](https://github.com/vuejs/language-tools/issues/3206).
13
+
14
+ ## Usage
15
+
16
+ ```ts
17
+ import type { GenericInstanceType } from '@maz-ui/utils'
18
+ import { ref } from 'vue'
19
+ import MyGenericList from './MyGenericList.vue'
20
+
21
+ const listRef = ref<GenericInstanceType<typeof MyGenericList> | null>(null)
22
+
23
+ // listRef.value.focus() is fully typed
24
+ ```
25
+
26
+ ## API
27
+
28
+ ```ts
29
+ type GenericInstanceType<T> = T extends new (...args: any[]) => infer R
30
+ ? R
31
+ : T extends (...args: any[]) => infer R
32
+ ? R extends { __ctx?: infer K }
33
+ ? Exclude<K, void> extends { expose: (...args: infer Y) => void }
34
+ ? Y[0] & InstanceType<DefineComponent>
35
+ : any
36
+ : any
37
+ : any
38
+ ```
39
+
40
+ ## Notes
41
+
42
+ - Use this only for generic components. For non-generic SFCs, plain `InstanceType<typeof Component>` already works and is clearer.
@@ -0,0 +1,35 @@
1
+ ---
2
+ title: InferMaybeRef
3
+ description: Unwrap a Vue `Ref<U>` to its inner `U` — leaves non-ref types unchanged.
4
+ ---
5
+
6
+ # {{ $frontmatter.title }}
7
+
8
+ {{ $frontmatter.description }}
9
+
10
+ Useful when authoring composables that accept either a plain value or a `Ref`, and you want a unified type for the inner value.
11
+
12
+ ## Usage
13
+
14
+ ```ts
15
+ import type { InferMaybeRef } from '@maz-ui/utils'
16
+ import { ref } from 'vue'
17
+
18
+ const a = ref(42)
19
+ const b = 42
20
+
21
+ type A = InferMaybeRef<typeof a> // number
22
+ type B = InferMaybeRef<typeof b> // number
23
+ ```
24
+
25
+ ## API
26
+
27
+ ```ts
28
+ import type { Ref } from 'vue'
29
+
30
+ type InferMaybeRef<T> = T extends Ref<infer U> ? U : T
31
+ ```
32
+
33
+ ## Notes
34
+
35
+ - Pairs well with Vue's built-in [`unref()`](https://vuejs.org/api/reactivity-utilities.html#unref), which provides the same behaviour at runtime.
@@ -0,0 +1,32 @@
1
+ ---
2
+ title: upperFirst
3
+ description: Uppercase the first character of a string and leave the rest unchanged.
4
+ ---
5
+
6
+ # {{ $frontmatter.title }}
7
+
8
+ {{ $frontmatter.description }}
9
+
10
+ ## Usage
11
+
12
+ ```ts
13
+ import { upperFirst } from '@maz-ui/utils'
14
+
15
+ upperFirst('hello') // → 'Hello'
16
+ upperFirst('hELLO') // → 'HELLO'
17
+ upperFirst('') // → ''
18
+ ```
19
+
20
+ ## API
21
+
22
+ ```ts
23
+ function upperFirst(value: string): string
24
+ ```
25
+
26
+ | Parameter | Type | Description |
27
+ | --------- | -------- | --------------------- |
28
+ | `value` | `string` | The string to process |
29
+
30
+ ## Notes
31
+
32
+ - Does **not** lowercase the remaining characters — use [`capitalize`](./capitalize) for the same behaviour when you control the input shape.
@@ -0,0 +1,69 @@
1
+ ---
2
+ title: UserVisibility
3
+ description: Track whether the user is currently looking at the tab using the Page Visibility API, with an optional grace timeout before declaring them away.
4
+ ---
5
+
6
+ # {{ $frontmatter.title }}
7
+
8
+ {{ $frontmatter.description }}
9
+
10
+ `UserVisibility` listens to `visibilitychange` events. When the tab becomes hidden, it waits `timeout` ms before invoking the callback with `isVisible: false` — this avoids spurious switches when the user briefly tabs away.
11
+
12
+ ## Usage
13
+
14
+ ```ts
15
+ import { UserVisibility } from '@maz-ui/utils'
16
+
17
+ const watcher = new UserVisibility(
18
+ ({ isVisible }) => {
19
+ if (isVisible) {
20
+ resumeVideo()
21
+ }
22
+ else {
23
+ pauseVideo()
24
+ }
25
+ },
26
+ { timeout: 3000 },
27
+ )
28
+
29
+ // later
30
+ watcher.destroy()
31
+ ```
32
+
33
+ ## API
34
+
35
+ ```ts
36
+ class UserVisibility {
37
+ constructor(callback: UserVisibilyCallback, options?: UserVisibilyOptions)
38
+
39
+ start(): void
40
+ destroy(): void
41
+ }
42
+
43
+ type UserVisibilyCallback = (payload: { isVisible: boolean }) => void
44
+ ```
45
+
46
+ ### Options
47
+
48
+ | Option | Type | Default | Description |
49
+ | ----------- | --------- | ------- | --------------------------------------------------------------------------------- |
50
+ | `timeout` | `number` | `5000` | Grace period in ms before a hidden tab fires the `isVisible: false` callback. |
51
+ | `immediate` | `boolean` | `true` | Fire the callback once on construction with the current visibility state. |
52
+ | `once` | `boolean` | `false` | Auto-destroy after the first callback invocation. |
53
+
54
+ ## Examples
55
+
56
+ Pause expensive timers when the user tabs away:
57
+
58
+ ```ts
59
+ new UserVisibility(
60
+ ({ isVisible }) => {
61
+ isVisible ? animations.resume() : animations.pause()
62
+ },
63
+ { timeout: 0 }, // react immediately
64
+ )
65
+ ```
66
+
67
+ ## Related
68
+
69
+ - [`IdleTimeout`](./idle-timeout) — track in-page activity instead of tab visibility.
@@ -55,7 +55,7 @@ Start by choosing your framework:
55
55
  </template>
56
56
  </MazCard>
57
57
  <MazCard
58
- href="/guide/nuxt"
58
+ href="/ecosystem/nuxt"
59
59
  class="maz:flex-1"
60
60
  content-title="Nuxt Users Guide"
61
61
  :gallery="{
@@ -70,7 +70,7 @@ Start by choosing your framework:
70
70
  </h3>
71
71
  </template>
72
72
  <template #footer>
73
- <MazBtn color="contrast" href="/guide/nuxt">
73
+ <MazBtn color="contrast" href="/ecosystem/nuxt">
74
74
  Nuxt guide
75
75
  </MazBtn>
76
76
  </template>
@@ -93,8 +93,9 @@ npm install @maz-ui/themes
93
93
 
94
94
  **Features:**
95
95
 
96
- - 🎨 OKLCh color system with perceptually uniform 11-step scales
97
- - 🌓 Smart dark mode detection and class/media/auto strategies
96
+ - 🎨 Native `light-dark()` + `color-scheme` + OKLCh scales via relative color syntax
97
+ - 🌓 Smart dark mode `class` or `media` strategies, with smooth transitions on toggle
98
+ - ✨ Optional animated theme switch via View Transitions (`setColorMode(..., { animate: true })`)
98
99
  - ⚡ `runtime` and `buildtime` rendering strategies
99
100
  - 🍪 Active preset persisted across reloads (opt-out)
100
101
  - 🛡️ Full TypeScript support
@@ -163,15 +164,6 @@ npm install @maz-ui/icons
163
164
  Maz-UI v5 is built with tree-shaking in mind. Import only what you need for optimal bundle sizes:
164
165
 
165
166
  ```typescript
166
- /**
167
- * Utilities
168
- */
169
-
170
- // ❌ Avoid importing everything
171
- import { formatCurrency, debounce } from '@maz-ui/utils'
172
- // ✅ Import from @maz-ui/utils
173
- import { formatCurrency, debounce } from '@maz-ui/utils'
174
-
175
167
  /**
176
168
  * Components
177
169
  */
@@ -215,6 +207,16 @@ import { vClickOutside } from 'maz-ui/directives/vClickOutside'
215
207
  import { MazUi } from 'maz-ui/plugins'
216
208
  // ✅✅ Direct plugin import (most optimized)
217
209
  import { MazUi } from 'maz-ui/plugins/maz-ui'
210
+
211
+ /**
212
+ * Utilities
213
+ */
214
+
215
+ // ❌ Avoid importing everything
216
+ import { formatCurrency, debounce } from '@maz-ui/utils'
217
+ // ✅ Import from @maz-ui/utils
218
+ import { debounce } from '@maz-ui/utils/helpers/debounce'
219
+ import { formatCurrency } from '@maz-ui/utils/helpers/formatCurrency'
218
220
  ```
219
221
 
220
222
  ::: tip Maximum Optimization
@@ -0,0 +1,101 @@
1
+ ---
2
+ title: Global component defaults
3
+ description: Set default prop values once for every Maz-UI component through the MazUi plugin or the Nuxt module
4
+ head:
5
+ - - meta
6
+ - name: keywords
7
+ content: maz-ui defaults, global props, default props, rounded size, component configuration, vue, nuxt
8
+ ---
9
+
10
+ # {{ $frontmatter.title }}
11
+
12
+ {{ $frontmatter.description }}
13
+
14
+ Instead of repeating the same prop on every instance (`<MazBtn rounded-size="lg" />` everywhere), you can set a default once and let every component pick it up.
15
+
16
+ ## Priority
17
+
18
+ A resolved prop always follows this order, from highest to lowest priority:
19
+
20
+ 1. The prop set on the component instance
21
+ 2. `defaults.<ComponentName>` (per-component default)
22
+ 3. `defaults.global` (cross-cutting default)
23
+ 4. The library's built-in default
24
+
25
+ A global default **never** overrides a prop set on the instance. Without any `defaults` config, every component keeps its built-in default, so this feature is fully opt-in and backward compatible.
26
+
27
+ ## Vue
28
+
29
+ Pass `defaults` to the `MazUi` plugin:
30
+
31
+ ```ts
32
+ import { MazUi } from 'maz-ui/plugins/maz-ui'
33
+ import { mazUi as mazUiPreset } from '@maz-ui/themes/presets/mazUi'
34
+ import 'maz-ui/style.css'
35
+
36
+ app.use(MazUi, {
37
+ theme: { preset: mazUiPreset },
38
+ defaults: {
39
+ global: { roundedSize: 'lg' },
40
+ MazBtn: { roundedSize: 'full' }, // wins over global for MazBtn
41
+ MazCard: { bordered: false, elevation: true },
42
+ MazContainer: { bordered: false },
43
+ },
44
+ })
45
+ ```
46
+
47
+ ## Nuxt
48
+
49
+ Set it in `nuxt.config` under the `mazUi` key:
50
+
51
+ ```ts
52
+ export default defineNuxtConfig({
53
+ modules: ['@maz-ui/nuxt'],
54
+ mazUi: {
55
+ defaults: {
56
+ global: { roundedSize: 'lg' },
57
+ MazBtn: { roundedSize: 'full' },
58
+ MazCard: { bordered: false, elevation: true },
59
+ },
60
+ },
61
+ })
62
+ ```
63
+
64
+ ## `global` vs per-component
65
+
66
+ - `defaults.global` holds **cross-cutting** props shared by many components: `roundedSize` and `size`. Set them once and every component that exposes them picks the value up.
67
+ - `defaults.<ComponentName>` holds **per-component** props (including booleans such as `bordered`, `elevation`, `padding`). A per-component entry always wins over `global`.
68
+
69
+ ```ts
70
+ defaults: {
71
+ global: { roundedSize: 'lg', size: 'sm' },
72
+ MazBtn: { roundedSize: 'full' }, // MazBtn is 'full', everything else 'lg'
73
+ }
74
+ ```
75
+
76
+ ## Type safety
77
+
78
+ `defaults` is fully typed. Each component entry is typed as `Partial<ComponentNameProps>`, so you get autocompletion and a TypeScript error on an unknown or mistyped prop:
79
+
80
+ ```ts
81
+ defaults: {
82
+ MazBtn: { roundedSiz: 'lg' }, // ❌ TS error: 'roundedSiz' does not exist
83
+ }
84
+ ```
85
+
86
+ ## Globalizable props
87
+
88
+ | Prop | Type | Components |
89
+ | --- | --- | --- |
90
+ | `roundedSize` | `MazRoundedSize` (`'none' \| 'sm' \| 'md' \| 'lg' \| 'xl' \| 'full'`) | `MazBtn`, `MazBtnGroup`, `MazContainer`, `MazInput`, `MazTextarea`, `MazTable`, `MazBadge`, `MazAlert`, `MazAvatar`, `MazSkeleton`, `MazTimeline` |
91
+ | `size` | `MazSize` (`'mini' \| 'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl'`) | `MazBtn`, `MazBtnGroup`, `MazBadge`, `MazInput`, `MazSelect`, `MazSelectCountry`, `MazInputNumber`, `MazInputTags`, `MazInputPhoneNumber`, `MazCheckbox`, `MazRadio`, `MazRadioButtons`, `MazDropdown`, `MazPagination`, `MazTable`, `MazTimeline` |
92
+ | `bordered`, `elevation`, `padding`, `transparent`, `overflowHidden` | `boolean` | `MazContainer` |
93
+ | `bordered`, `elevation`, `padding`, `radius`, `scale`, `overflowHidden` | `boolean` | `MazCard` |
94
+
95
+ ::: tip Note
96
+ Components whose `size` is a free CSS length (`MazSizeUnit`, e.g. `MazSpinner`, `MazAvatar`, `MazDrawer`, `MazSlider`, `MazCircularProgressBar`, `MazFullscreenLoader`) do not take the global `size` token - the value would not be valid for them. `MazAlert` and `MazTimeline` keep their own wider `roundedSize` scale; a `defaults.global.roundedSize` value still applies to them, and their extra steps (`2xl`, `3xl`) are reachable through their per-component entry.
97
+ :::
98
+
99
+ ## Relation to the theme system
100
+
101
+ This is **not** a duplicate of [`@maz-ui/themes`](/ecosystem/themes). The theme system controls *what a token looks like* (the CSS value of `rounded-md`, `shadow-elevation`, colors…). Global defaults control *which prop value a component selects by default* (whether `MazBtn` defaults to `roundedSize="lg"`). Both work together: the theme defines what `lg` renders as, the defaults decide which step a component uses.
@@ -97,12 +97,15 @@ The entire Maz-UI setup is now code-split into the Dashboard chunk.
97
97
 
98
98
  ```typescript
99
99
  interface ThemeOptions {
100
- preset: ThemePreset // Required - Theme preset (mazUi, ocean, pristine, obsidian, or custom)
101
- overrides?: ThemePresetOverrides // Partial overrides for colors, foundation, etc.
102
- strategy?: 'runtime' | 'buildtime' // CSS generation strategy (default: 'runtime')
100
+ preset: ThemePreset // Required - Theme preset (mazUi, ocean, pristine, obsidian, nova, or custom)
101
+ overrides?: ThemePresetOverrides // Partial overrides for colors, foundation, etc.
102
+ strategy?: 'runtime' | 'buildtime' // CSS generation strategy (default: 'runtime')
103
103
  darkModeStrategy?: 'class' | 'media' // Dark mode handling (default: 'class')
104
104
  colorMode?: 'light' | 'dark' | 'auto' // Initial color mode (default: 'auto')
105
105
  mode?: 'light' | 'dark' | 'both' // Supported color modes (default: 'both')
106
+ darkClass?: string // Class on <html> when colorMode === 'dark' (default: 'dark')
107
+ lightClass?: string // Class on <html> when colorMode === 'light' (default: 'light')
108
+ persistPreset?: boolean // Persist active preset in cookie (default: true)
106
109
  }
107
110
  ```
108
111