@maz-ui/mcp 4.1.2 → 4.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mcp.mjs CHANGED
@@ -7,7 +7,7 @@ import { existsSync, readFileSync, readdirSync } from 'node:fs';
7
7
  import { resolve, dirname, join } from 'node:path';
8
8
  import { fileURLToPath } from 'node:url';
9
9
 
10
- const version = "4.1.1";
10
+ const version = "4.1.2";
11
11
 
12
12
  const _dirname = dirname(fileURLToPath(import.meta.url));
13
13
  class DocumentationService {
@@ -404,7 +404,7 @@ class MazUiMcpServer {
404
404
  },
405
405
  {
406
406
  name: "list_composables",
407
- description: "List all Vue 3 composables (useToast, useDialog, etc.)",
407
+ description: "List all Vue or Nuxt composables (useToast, useDialog, etc.)",
408
408
  inputSchema: {
409
409
  type: "object",
410
410
  properties: {}
@@ -16,6 +16,7 @@
16
16
  | **success** | Whether the input is successful. | `boolean` | No | `undefined` | - |
17
17
  | **warning** | Whether there is a warning with the input. | `boolean` | No | `undefined` | - |
18
18
  | **hint** | The hint text to display below the input. | `string` | No | `undefined` | - |
19
+ | **size** | The size of the radio buttons | `MazSize` | No | `'md'` | - |
19
20
 
20
21
  ## Events
21
22
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: MazPopover
3
- description: MazPopover is a versatile Vue 3 component for displaying content in overlays that bypass overflow constraints of parent elements
3
+ description: MazPopover is a versatile Vue component for displaying content in overlays that bypass overflow constraints of parent elements
4
4
  ---
5
5
 
6
6
  # {{ $frontmatter.title }}
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: MazSelectCountry
3
- description: MazSelectCountry is a versatile Vue 3 component for selecting countries or languages with built-in internationalization support and customizable display options
3
+ description: MazSelectCountry is a versatile Vue component for selecting countries or languages with built-in internationalization support and customizable display options
4
4
  ---
5
5
 
6
6
  # {{ $frontmatter.title }}
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: useDisplayNames
3
- description: useDisplayNames is a Vue 3 composable specialized in displaying localized country names (regions) and language names. It supports various code formats including ISO 639-1 (language codes), ISO 3166-1 (country codes), and BCP 47 (language tags), using the Intl.DisplayNames API for internationalization.
3
+ description: useDisplayNames is a Vue composable specialized in displaying localized country names (regions) and language names. It supports various code formats including ISO 639-1 (language codes), ISO 3166-1 (country codes), and BCP 47 (language tags), using the Intl.DisplayNames API for internationalization.
4
4
  ---
5
5
 
6
6
  # {{ $frontmatter.title }}
@@ -20,7 +20,7 @@ Depending on your environment (client or node server) and the browser you are us
20
20
  ## Key Features
21
21
 
22
22
  - Displays localized country names (regions) and language names
23
- - Supports multiple code formats: ISO 639-1 (language codes), ISO 3166-1 (country codes), and BCP 47 (language tags)
23
+ - Supports multiple code formats: ISO 639-1 (language codes), ISO 3166-1 (country codes), and BCP 47 (language tags)
24
24
  - Works with any locale supported by the browser's Intl.DisplayNames API
25
25
  - Provides functions to get individual names or bulk retrieve all available names
26
26
  - Handles errors gracefully with fallback values
@@ -154,7 +154,7 @@ function getAllDisplayNames(options: {
154
154
 
155
155
  ## Notes
156
156
 
157
- - The `useDisplayNames` composable is designed to be used with Vue 3.
157
+ - The `useDisplayNames` composable is designed to be used with Vue.
158
158
  - The composable functions return `ComputedRef` values, which are reactive and will update automatically when their dependencies change.
159
159
  - Handle errors gracefully by providing fallback values when the display name cannot be fetched.
160
160
  - The `Intl.DisplayNames` API is used internally to fetch and format the display names based on the provided locale and code.
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  title: useFormValidator
3
- description: useFormValidator and useFormField are two Vue 3 composables designed to simplify form validation using Valibot as the validation library. These composables offer a flexible and typed approach to handle form validation in your Vue 3 applications.
3
+ description: useFormValidator and useFormField are two Vue composables designed to simplify form validation using Valibot as the validation library. These composables offer a flexible and typed approach to handle form validation in your Vue applications.
4
4
  ---
5
5
 
6
6
  # {{ $frontmatter.title }}
7
7
 
8
- `useFormValidator` and `useFormField` are two Vue 3 composables designed to simplify form validation using [Valibot](https://valibot.dev/guides/introduction/) as the validation library. These composables offer a flexible and typed approach to handle form validation in your Vue 3 applications.
8
+ `useFormValidator` and `useFormField` are two Vue composables designed to simplify form validation using [Valibot](https://valibot.dev/guides/introduction/) as the validation library. These composables offer a flexible and typed approach to handle form validation in your Vue applications.
9
9
 
10
10
  ## Introduction
11
11
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: useIdleTimeout
3
- description: A Vue 3 composable that provides an easy way to track user inactivity on your website and execute a callback function when the user becomes idle.
3
+ description: A Vue composable that provides an easy way to track user inactivity on your website and execute a callback function when the user becomes idle.
4
4
  ---
5
5
 
6
6
  # {{ $frontmatter.title }}
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: useSwipe
3
- description: useSwipe is a Vue 3 composable that simplifies the management of "swipe" interactions on HTML elements.
3
+ description: useSwipe is a Vue composable that simplifies the management of "swipe" interactions on HTML elements.
4
4
  ---
5
5
 
6
6
  # {{ $frontmatter.title }}
@@ -19,7 +19,7 @@ The composable provides the following functionality:
19
19
 
20
20
  The composable also includes cleanup logic using onBeforeUnmount to ensure that the timer is stopped when the component is unmounted.
21
21
 
22
- This composable can be used in Vue 3 components to handle timeouts in a flexible and reactive manner.
22
+ This composable can be used in Vue components to handle timeouts in a flexible and reactive manner.
23
23
 
24
24
  ## Usage
25
25
 
@@ -0,0 +1,167 @@
1
+ <script setup lang="ts">
2
+ /* eslint-disable style/max-statements-per-line */
3
+
4
+ import type { HSL } from '@maz-ui/themes'
5
+ import { computed, ref, watch } from 'vue'
6
+
7
+ interface Props {
8
+ modelValue: HSL
9
+ label?: string
10
+ disabled?: boolean
11
+ }
12
+
13
+ const props = withDefaults(defineProps<Props>(), {
14
+ disabled: false,
15
+ })
16
+
17
+ const emit = defineEmits<{
18
+ 'update:modelValue': [value: HSL]
19
+ }>()
20
+
21
+ const colorInput = ref<HTMLInputElement>()
22
+
23
+ function hslToHex(hsl: HSL): string {
24
+ const match = hsl.match(/(\d+(?:\.\d+)?)\s+(\d+(?:\.\d+)?)%\s+(\d+(?:\.\d+)?)%/)
25
+ if (!match)
26
+ return '#000000'
27
+
28
+ const h = Number.parseFloat(match[1]) / 360
29
+ const s = Number.parseFloat(match[2]) / 100
30
+ const l = Number.parseFloat(match[3]) / 100
31
+
32
+ const hue2rgb = (p: number, q: number, t: number) => {
33
+ if (t < 0)
34
+ t += 1
35
+ if (t > 1)
36
+ t -= 1
37
+ if (t < 1 / 6)
38
+ return p + (q - p) * 6 * t
39
+ if (t < 1 / 2)
40
+ return q
41
+ if (t < 2 / 3)
42
+ return p + (q - p) * (2 / 3 - t) * 6
43
+ return p
44
+ }
45
+
46
+ let r: number
47
+ let g: number
48
+ let b: number
49
+
50
+ if (s === 0) {
51
+ r = g = b = l
52
+ }
53
+ else {
54
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s
55
+ const p = 2 * l - q
56
+ r = hue2rgb(p, q, h + 1 / 3)
57
+ g = hue2rgb(p, q, h)
58
+ b = hue2rgb(p, q, h - 1 / 3)
59
+ }
60
+
61
+ const toHex = (c: number) => {
62
+ const hex = Math.round(c * 255).toString(16)
63
+ return hex.length === 1 ? `0${hex}` : hex
64
+ }
65
+
66
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`
67
+ }
68
+
69
+ function hexToHsl(hex: string): HSL {
70
+ const r = Number.parseInt(hex.slice(1, 3), 16) / 255
71
+ const g = Number.parseInt(hex.slice(3, 5), 16) / 255
72
+ const b = Number.parseInt(hex.slice(5, 7), 16) / 255
73
+
74
+ const max = Math.max(r, g, b)
75
+ const min = Math.min(r, g, b)
76
+ let h: number
77
+ let s: number
78
+ const l = (max + min) / 2
79
+
80
+ if (max === min) {
81
+ h = s = 0
82
+ }
83
+ else {
84
+ const d = max - min
85
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min)
86
+
87
+ switch (max) {
88
+ case r: h = (g - b) / d + (g < b ? 6 : 0); break
89
+ case g: h = (b - r) / d + 2; break
90
+ case b: h = (r - g) / d + 4; break
91
+ default: h = 0
92
+ }
93
+ h /= 6
94
+ }
95
+
96
+ const hue = Math.round(h * 360)
97
+ const saturation = Math.round(s * 100)
98
+ const lightness = Math.round(l * 100)
99
+
100
+ return `${hue} ${saturation}% ${lightness}%` as HSL
101
+ }
102
+
103
+ const hexValue = computed(() => hslToHex(props.modelValue))
104
+
105
+ function handleColorChange(event: Event) {
106
+ const target = event.target as HTMLInputElement
107
+ const hslValue = hexToHsl(target.value)
108
+ emit('update:modelValue', hslValue)
109
+ }
110
+
111
+ watch(() => props.modelValue, () => {
112
+ if (colorInput.value) {
113
+ colorInput.value.value = hexValue.value
114
+ }
115
+ }, { immediate: true })
116
+ </script>
117
+
118
+ <template>
119
+ <div class="color-picker">
120
+ <label v-if="label" for="input-color">
121
+ {{ label }}
122
+ </label>
123
+
124
+ <input
125
+ id="input-color"
126
+ ref="colorInput"
127
+ type="color"
128
+ :value="hexValue"
129
+ :disabled="disabled"
130
+ @change="handleColorChange"
131
+ >
132
+ </div>
133
+ </template>
134
+
135
+ <style lang="postcss" scoped>
136
+ .color-picker {
137
+ @apply maz-inline-flex maz-flex-col maz-gap-1;
138
+
139
+ label {
140
+ @apply maz-text-sm maz-font-medium maz-text-foreground maz-truncate;
141
+ }
142
+
143
+ input[type='color'] {
144
+ -webkit-appearance: none;
145
+ appearance: none;
146
+ background: none;
147
+ cursor: pointer;
148
+
149
+ @apply maz-h-10 maz-w-full maz-cursor-pointer maz-overflow-hidden maz-rounded maz-border maz-border-solid maz-border-divider disabled:maz-cursor-not-allowed disabled:maz-opacity-50;
150
+
151
+ &::-webkit-color-swatch-wrapper {
152
+ padding: 0;
153
+ @apply maz-rounded;
154
+ }
155
+
156
+ &::-webkit-color-swatch {
157
+ border: none;
158
+ @apply maz-rounded;
159
+ }
160
+
161
+ &::-moz-color-swatch {
162
+ border: none;
163
+ @apply maz-rounded;
164
+ }
165
+ }
166
+ }
167
+ </style>
@@ -2,7 +2,7 @@
2
2
  import dataLabels from 'chartjs-plugin-datalabels'
3
3
  import { ref } from 'vue'
4
4
 
5
- const { delay = 100 } = defineProps<{
5
+ const { delay = 0 } = defineProps<{
6
6
  delay?: number
7
7
  }>()
8
8
 
@@ -117,7 +117,6 @@ const tableHeaders = [
117
117
  color="success"
118
118
  size="3rem"
119
119
  :delay
120
- :once="false"
121
120
  />
122
121
  <div class="maz-truncate">
123
122
  <div class="maz-text-xl maz-font-bold">
@@ -126,7 +125,6 @@ const tableHeaders = [
126
125
  :count="28945"
127
126
  prefix="$"
128
127
  separator=","
129
- :once="false"
130
128
  />
131
129
  </div>
132
130
  <div class="maz-truncate maz-text-sm maz-text-muted">
@@ -143,7 +141,6 @@ const tableHeaders = [
143
141
  color="info"
144
142
  size="3rem"
145
143
  :delay
146
- :once="false"
147
144
  />
148
145
  <div class="maz-truncate">
149
146
  <div class="maz-text-xl maz-font-bold">
@@ -151,7 +148,6 @@ const tableHeaders = [
151
148
  :delay
152
149
  :count="384"
153
150
  separator=","
154
- :once="false"
155
151
  />
156
152
  </div>
157
153
  <div class="maz-truncate maz-text-sm maz-text-muted">
@@ -168,7 +164,6 @@ const tableHeaders = [
168
164
  color="warning"
169
165
  size="3rem"
170
166
  :delay
171
- :once="false"
172
167
  />
173
168
  <div class="maz-truncate">
174
169
  <div class="maz-text-xl maz-font-bold">
@@ -176,7 +171,6 @@ const tableHeaders = [
176
171
  :delay
177
172
  :count="1482"
178
173
  separator=","
179
- :once="false"
180
174
  />
181
175
  </div>
182
176
  <div class="maz-truncate maz-text-sm maz-text-muted">
@@ -193,7 +187,6 @@ const tableHeaders = [
193
187
  color="destructive"
194
188
  size="3rem"
195
189
  :delay
196
- :once="false"
197
190
  />
198
191
  <div class="maz-truncate">
199
192
  <div class="maz-text-xl maz-font-bold">
@@ -201,7 +194,6 @@ const tableHeaders = [
201
194
  :delay
202
195
  :count="94"
203
196
  suffix="%"
204
- :once="false"
205
197
  />
206
198
  </div>
207
199
  <div class="maz-truncate maz-text-sm maz-text-muted">
@@ -223,6 +215,7 @@ const tableHeaders = [
223
215
  input-size="sm"
224
216
  pagination
225
217
  selectable
218
+ scrollable
226
219
  >
227
220
  <template #cell-amount="{ value }">
228
221
  <span class="maz-font-semibold">
@@ -0,0 +1,396 @@
1
+ <script setup lang="ts">
2
+ import type { ThemePreset } from '@maz-ui/themes'
3
+ import { useTheme } from '@maz-ui/themes/composables/useTheme'
4
+ import { mazUi } from '@maz-ui/themes/presets/mazUi'
5
+ import { useToast } from 'maz-ui/composables'
6
+ import { codeToHtml } from 'shiki'
7
+ import { computed, nextTick, reactive, ref, watch } from 'vue'
8
+ import ColorPicker from './ColorPicker.vue'
9
+ import DemoAuthPage from './DemoAuthPage.vue'
10
+ import DemoDashboardPage from './DemoDashboardPage.vue'
11
+ import DemoProductPage from './DemoProductPage.vue'
12
+
13
+ const { updateTheme, isDark, toggleDarkMode, presetName } = useTheme()
14
+ const toast = useToast()
15
+
16
+ const currentTab = ref(1)
17
+ const editingMode = ref<'light' | 'dark'>('light')
18
+ const exportedCode = ref('')
19
+ const highlightedCode = ref('')
20
+ const showExportModal = ref(false)
21
+ const isTransitioning = ref(false)
22
+
23
+ const themeData = reactive<ThemePreset>({
24
+ name: mazUi.name,
25
+ foundation: { ...mazUi.foundation },
26
+ colors: {
27
+ light: { ...mazUi.colors.light },
28
+ dark: { ...mazUi.colors.dark },
29
+ },
30
+ })
31
+
32
+ const originalTheme = {
33
+ name: mazUi.name,
34
+ foundation: { ...mazUi.foundation },
35
+ colors: {
36
+ light: { ...mazUi.colors.light },
37
+ dark: { ...mazUi.colors.dark },
38
+ },
39
+ }
40
+
41
+ const colorCategories = [
42
+ {
43
+ name: 'Base Colors',
44
+ colors: ['background', 'foreground', 'border', 'muted', 'overlay', 'shadow'] as const,
45
+ },
46
+ {
47
+ name: 'Colors',
48
+ colors: ['primary', 'primary-foreground', 'secondary', 'secondary-foreground', 'accent', 'accent-foreground', 'success', 'success-foreground', 'warning', 'warning-foreground', 'destructive', 'destructive-foreground', 'info', 'info-foreground', 'contrast', 'contrast-foreground'] as const,
49
+ },
50
+ ]
51
+
52
+ watch([themeData, editingMode], async () => {
53
+ await nextTick()
54
+ await updateTheme(themeData)
55
+ }, { deep: true })
56
+
57
+ function handleThemeModeToggle() {
58
+ isTransitioning.value = true
59
+ toggleDarkMode()
60
+
61
+ setTimeout(() => {
62
+ isTransitioning.value = false
63
+ }, 500)
64
+ }
65
+
66
+ function resetTheme() {
67
+ Object.assign(themeData.foundation, originalTheme.foundation)
68
+ Object.assign(themeData.colors.light, originalTheme.colors.light)
69
+ Object.assign(themeData.colors.dark, originalTheme.colors.dark)
70
+ }
71
+
72
+ function copyToClipboard(text: string) {
73
+ navigator.clipboard.writeText(text).then(() => {
74
+ showExportModal.value = false
75
+ })
76
+
77
+ toast.success('Theme copied to clipboard', {
78
+ position: 'top',
79
+ })
80
+ }
81
+
82
+ async function exportTheme() {
83
+ const themeCode = `import type { ThemePreset } from '@maz-ui/themes'
84
+
85
+ export const customTheme: ThemePreset = ${JSON.stringify(themeData, null, 2)
86
+ // Escape single quotes within string values
87
+ .replace(/: "([^"]*)"/g, (match, value) => {
88
+ const escapedValue = value.replace(/'/g, '\\\'')
89
+ return `: '${escapedValue}'`
90
+ })
91
+ // Remove quotes from top-level keys and nested object keys
92
+ .replace(/^(\s*)"(name|foundation|colors)":/gm, '$1$2:')
93
+ .replace(/^(\s*)"(light|dark)":/gm, '$1$2:')}`
94
+
95
+ exportedCode.value = themeCode
96
+
97
+ try {
98
+ const html = await codeToHtml(themeCode, {
99
+ lang: 'typescript',
100
+ theme: isDark.value ? 'tokyo-night' : 'github-dark',
101
+ })
102
+ highlightedCode.value = html
103
+ }
104
+ catch (error) {
105
+ console.error('Failed to highlight code:', error)
106
+ highlightedCode.value = ''
107
+ }
108
+
109
+ showExportModal.value = true
110
+ }
111
+
112
+ const foundationInputs = computed(() => [
113
+ {
114
+ key: 'base-font-size',
115
+ label: 'Base Font Size',
116
+ type: 'text',
117
+ placeholder: '14px',
118
+ },
119
+ {
120
+ key: 'font-family',
121
+ label: 'Font Family',
122
+ type: 'text',
123
+ placeholder: 'Manrope, sans-serif',
124
+ },
125
+ {
126
+ key: 'radius',
127
+ label: 'Border Radius',
128
+ type: 'text',
129
+ placeholder: '0.7rem',
130
+ },
131
+ {
132
+ key: 'border-width',
133
+ label: 'Border Width',
134
+ type: 'text',
135
+ placeholder: '0.0625rem',
136
+ },
137
+ ])
138
+
139
+ const currentColors = computed(() => themeData.colors[editingMode.value])
140
+
141
+ function formatColorName(colorName: string): string {
142
+ return colorName
143
+ .split('-')
144
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1))
145
+ .join(' ')
146
+ }
147
+ </script>
148
+
149
+ <template>
150
+ <div class="vp-raw theme-configurator" :class="{ 'no-transitions': isTransitioning }">
151
+ <div class="maz-grid maz-min-h-[80vh] maz-grid-cols-1 maz-gap-4 lg:maz-grid-cols-12">
152
+ <!-- Editor Panel -->
153
+ <div class="maz-space-y-6 lg:maz-col-span-4 lg:maz-border-r lg:maz-pr-4">
154
+ <h2 class="maz-text-2xl maz-text-foreground">
155
+ Editor
156
+ </h2>
157
+
158
+ <div class="maz-flex maz-flex-col maz-gap-2 mob-l:maz-flex-row">
159
+ <MazBtn
160
+ size="md"
161
+ block
162
+ color="secondary"
163
+ @click="resetTheme"
164
+ >
165
+ Reset theme
166
+ </MazBtn>
167
+ <MazBtn
168
+ size="md"
169
+ block
170
+ color="primary"
171
+ @click="exportTheme"
172
+ >
173
+ Export theme
174
+ </MazBtn>
175
+ </div>
176
+
177
+ <MazCard block title="Base preset">
178
+ <MazRadioButtons
179
+ :model-value="presetName"
180
+ size="sm"
181
+ :options="[
182
+ {
183
+ label: 'Maz-UI',
184
+ value: 'maz-ui',
185
+ },
186
+ {
187
+ label: 'Pristine',
188
+ value: 'pristine',
189
+ },
190
+ {
191
+ label: 'Ocean',
192
+ value: 'ocean',
193
+ }, {
194
+ label: 'Obsidian',
195
+ value: 'obsidian',
196
+ }]"
197
+ @update:model-value="updateTheme($event)"
198
+ />
199
+ </MazCard>
200
+
201
+ <!-- Foundation Settings -->
202
+ <MazCard title="Foundation" block>
203
+ <div
204
+ class="maz-flex maz-flex-col maz-gap-3"
205
+ >
206
+ <template
207
+ v-for="input in foundationInputs"
208
+ :key="input.key"
209
+ >
210
+ <MazInput
211
+ v-model="themeData.foundation[input.key as keyof typeof themeData.foundation]"
212
+ :label="input.label"
213
+ :placeholder="input.placeholder"
214
+ size="sm"
215
+ block
216
+ debounce
217
+ />
218
+ </template>
219
+ </div>
220
+ </MazCard>
221
+
222
+ <!-- Colors Settings -->
223
+ <MazCard block>
224
+ <template #title>
225
+ <div class="maz-flex maz-w-full maz-items-center maz-justify-between">
226
+ <h3 class="maz-text-base">
227
+ Colors
228
+ </h3>
229
+
230
+ <div class="maz-flex maz-items-center maz-gap-2">
231
+ <label for="dark-mode-switch" class="maz-cursor-pointer maz-text-sm">
232
+ Edit dark colors
233
+ </label>
234
+ <MazSwitch
235
+ id="dark-mode-switch"
236
+ :model-value="editingMode === 'dark'"
237
+ @update:model-value="editingMode = $event ? 'dark' : 'light'; handleThemeModeToggle()"
238
+ />
239
+ </div>
240
+ </div>
241
+ </template>
242
+
243
+ <div class="maz-space-y-6">
244
+ <div
245
+ v-for="category in colorCategories"
246
+ :key="category.name"
247
+ class="maz-space-y-4"
248
+ >
249
+ <h4 class="maz-border-border maz-border-b maz-pb-2 maz-text-sm maz-font-semibold maz-text-foreground">
250
+ {{ category.name }}
251
+ </h4>
252
+
253
+ <div class="maz-grid maz-grid-cols-2 maz-gap-4">
254
+ <ColorPicker
255
+ v-for="colorKey in category.colors"
256
+ :key="`${editingMode}-${colorKey}`"
257
+ v-model="currentColors[colorKey]"
258
+ :label="formatColorName(colorKey)"
259
+ class="maz-w-full"
260
+ />
261
+ </div>
262
+ </div>
263
+ </div>
264
+ </MazCard>
265
+ </div>
266
+
267
+ <!-- Preview Panel -->
268
+ <div class="lg:maz-col-span-8">
269
+ <div class="maz-sticky maz-top-4">
270
+ <div class="maz-mb-4 maz-flex maz-items-center maz-justify-between">
271
+ <h2 class="maz-text-2xl maz-text-foreground">
272
+ Preview
273
+ </h2>
274
+ </div>
275
+
276
+ <MazTabs v-model="currentTab">
277
+ <MazTabsBar
278
+ :items="['Dashboard', 'Product', 'Authentication']"
279
+ class="maz-mb-4"
280
+ />
281
+
282
+ <MazTabsContent>
283
+ <MazTabsContentItem :tab="1">
284
+ <MazCard
285
+ bordered
286
+ :padding="false"
287
+ overflow-hidden
288
+ class="maz-max-h-[70vh] maz-w-full maz-overflow-y-auto"
289
+ >
290
+ <DemoDashboardPage :delay="0" />
291
+ </MazCard>
292
+ </MazTabsContentItem>
293
+
294
+ <MazTabsContentItem :tab="2">
295
+ <MazCard
296
+ bordered
297
+ :padding="false"
298
+ overflow-hidden
299
+ class="maz-max-h-[70vh] maz-w-full maz-overflow-y-auto"
300
+ >
301
+ <DemoProductPage />
302
+ </MazCard>
303
+ </MazTabsContentItem>
304
+
305
+ <MazTabsContentItem :tab="3">
306
+ <MazCard
307
+ bordered
308
+ :padding="false"
309
+ overflow-hidden
310
+ class="maz-max-h-[70vh] maz-w-full maz-overflow-y-auto"
311
+ >
312
+ <DemoAuthPage />
313
+ </MazCard>
314
+ </MazTabsContentItem>
315
+ </MazTabsContent>
316
+ </MazTabs>
317
+ </div>
318
+ </div>
319
+ </div>
320
+
321
+ <!-- Export Modal -->
322
+ <MazDialog v-model="showExportModal" scrollable title="Export Theme">
323
+ <div class="maz-space-y-4">
324
+ <p class="maz-text-muted">
325
+ Copy the generated TypeScript code below to use your custom theme:
326
+ </p>
327
+
328
+ <div class="maz-overflow-y-auto maz-rounded-md">
329
+ <div
330
+ v-if="highlightedCode"
331
+ class="shiki-wrapper"
332
+ v-html="highlightedCode"
333
+ />
334
+ <div
335
+ v-else
336
+ class="maz-bg-contrast maz-p-4 dark:maz-bg-surface-300"
337
+ >
338
+ <pre class="maz-whitespace-pre-wrap maz-font-mono maz-text-xs maz-text-contrast-foreground dark:maz-text-surface-foreground">{{ exportedCode }}</pre>
339
+ </div>
340
+ </div>
341
+ </div>
342
+
343
+ <template #footer>
344
+ <div class="maz-flex maz-gap-2">
345
+ <MazBtn color="primary" @click="copyToClipboard(exportedCode)">
346
+ Copy to Clipboard
347
+ </MazBtn>
348
+ </div>
349
+ </template>
350
+ </MazDialog>
351
+ </div>
352
+ </template>
353
+
354
+ <style lang="postcss" scoped>
355
+ @media (max-width: 1024px) {
356
+ .theme-configurator {
357
+ @apply maz-space-y-8;
358
+ }
359
+
360
+ .theme-configurator .maz-sticky {
361
+ @apply maz-static;
362
+ }
363
+ }
364
+ </style>
365
+
366
+ <style lang="postcss">
367
+ /* Global styles to disable transitions during theme mode switch */
368
+ .no-transitions *,
369
+ .no-transitions *::before,
370
+ .no-transitions *::after {
371
+ transition-duration: 0ms !important;
372
+ transition-delay: 0ms !important;
373
+ animation-duration: 0ms !important;
374
+ animation-delay: 0ms !important;
375
+ }
376
+
377
+ /* Shiki code highlighting styles */
378
+ .shiki-wrapper {
379
+ @apply maz-rounded-md maz-overflow-hidden maz-bg-contrast dark:maz-bg-surface-400;
380
+ }
381
+
382
+ .shiki-wrapper pre {
383
+ @apply maz-p-4 maz-m-0 maz-text-xs maz-overflow-x-auto;
384
+ font-family: 'Fira Code', 'Consolas', 'Monaco', monospace !important;
385
+ }
386
+
387
+ .shiki-wrapper code {
388
+ @apply maz-text-xs;
389
+ font-family: 'Fira Code', 'Consolas', 'Monaco', monospace !important;
390
+ }
391
+
392
+ /* Override shiki background to match theme */
393
+ .shiki-wrapper .shiki {
394
+ background-color: transparent !important;
395
+ }
396
+ </style>
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: vClickOutside
3
- description: vClickOutside is a Vue 3 directive to trigger a function when the user clicks outside an element
3
+ description: vClickOutside is a Vue directive to trigger a function when the user clicks outside an element
4
4
  ---
5
5
 
6
6
  # {{ $frontmatter.title }}
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: vLazyImg
3
- description: vLazyImg is a Vue 3 directive to lazy load images with many options. The image will be loaded on user's scroll
3
+ description: vLazyImg is a Vue directive to lazy load images with many options. The image will be loaded on user's scroll
4
4
  ---
5
5
 
6
6
  # {{ $frontmatter.title }}
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: vTooltip
3
- description: vTooltip is a Vue 3 directive to display a text when the user hovers an element
3
+ description: vTooltip is a Vue directive to display a text when the user hovers an element
4
4
  ---
5
5
 
6
6
  # {{ $frontmatter.title }}
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: vZoomImg
3
- description: vZoomImg is a Vue 3 directive to enlarge an image like a modal on click, if you have several images, you can pass them like a carousel
3
+ description: vZoomImg is a Vue directive to enlarge an image like a modal on click, if you have several images, you can pass them like a carousel
4
4
  ---
5
5
 
6
6
  # {{ $frontmatter.title }}
@@ -4,7 +4,7 @@ description: Build Vue and Nuxt applications faster with Maz-UI v4 - The modern,
4
4
  head:
5
5
  - - meta
6
6
  - name: keywords
7
- content: vue ui library, vue components, nuxt ui, maz-ui installation, vue 3 components
7
+ content: vue ui library, vue components, nuxt ui, maz-ui installation, components, nuxt, vue, themes, translations, icons, mcp, maz-ui
8
8
  ---
9
9
 
10
10
  # {{ $frontmatter.title }}
@@ -73,7 +73,7 @@ import { MazCheck, MazHeart, MazUser } from '@maz-ui/icons'
73
73
 
74
74
  - ✅ Tree-shaking - Only bundled icons are included
75
75
  - ✅ TypeScript support with full IntelliSense
76
- - ✅ Vue 3 optimized with `defineAsyncComponent`
76
+ - ✅ Vue optimized with `defineAsyncComponent`
77
77
  - ✅ Easy to style with CSS classes
78
78
 
79
79
  ### Method 2: Auto-import with Resolver
@@ -70,7 +70,7 @@ v4.0.0 separates functionality into specialized packages for better modularity:
70
70
  | **@maz-ui/utils** | JavaScript/TypeScript utilities | New |
71
71
  | **@maz-ui/icons** | SVG icons and flags (840+ icons) | New |
72
72
  | **@maz-ui/cli** | CLI for theme generation | Renamed |
73
- | **@maz-ui/nuxt** | Nuxt 3 module | New |
73
+ | **@maz-ui/nuxt** | Nuxt module | New |
74
74
  | **@maz-ui/mcp** | MCP server for IA agent | New |
75
75
 
76
76
  ## Migration Checklist
@@ -903,8 +903,8 @@ app.use(MazUi)
903
903
  - **[Official v4 Documentation](https://maz-ui.com)** - Complete documentation
904
904
  - **[Theme Guide](/guide/themes)** - Advanced theme system
905
905
  - **[Translation Guide](/guide/translations)** - Internationalization
906
- - **[Vue Installation Guide](/guide/vue)** - Vue 3 setup
907
- - **[Nuxt Installation Guide](/guide/nuxt)** - Nuxt 3 setup
906
+ - **[Vue Installation Guide](/guide/vue)** - Vue setup
907
+ - **[Nuxt Installation Guide](/guide/nuxt)** - Nuxt setup
908
908
  - **[Resolvers Guide](/guide/resolvers)** - Smart auto-imports
909
909
  - **[Complete Changelog](https://github.com/LouisMazel/maz-ui/blob/master/CHANGELOG.md)** - All changes
910
910
 
@@ -19,6 +19,10 @@ description: Modern and performant theme system for Maz-UI with TypeScript, HSL
19
19
  - **Zero FOUC** - Critical CSS injected inline to avoid flashes
20
20
  - **Flexible Presets** - Ready-to-use and customizable configurations
21
21
 
22
+ ## Theme Editor
23
+
24
+ Create your own theme with the [Theme Editor](./../theme-editor.md).
25
+
22
26
  ## Quick Usage
23
27
 
24
28
  ### 1. Plugin Configuration with `MazUi` plugin
package/docs/src/index.md CHANGED
@@ -435,7 +435,7 @@ description: Build amazing interfaces with Maz-UI - standalone components & tool
435
435
  </div>
436
436
  <h3 class="maz-text-base maz-font-semibold">useFormValidator</h3>
437
437
  <p class="dark:maz-text-gray-300 maz-text-muted maz-text-sm">
438
- A Vue 3 composable designed to simplify form validation using Valibot as the validation library. Offers a flexible and typed approach to handle form validation.
438
+ A Vue composable designed to simplify form validation using Valibot as the validation library. Offers a flexible and typed approach to handle form validation.
439
439
  </p>
440
440
  <div class="maz-flex-1"></div>
441
441
  <MazBtn color="background" outlined size="sm" block href="/composables/use-form-validator">Discover</MazBtn>
@@ -491,7 +491,7 @@ description: Build amazing interfaces with Maz-UI - standalone components & tool
491
491
  </div>
492
492
  <h3 class="maz-text-base maz-font-semibold">useDisplayNames</h3>
493
493
  <p class="dark:maz-text-gray-300 maz-text-muted maz-text-sm">
494
- A Vue 3 composable that provides functions to work with localized display names based on ISO codes, leveraging the Intl.DisplayNames API.
494
+ A Vue composable that provides functions to work with localized display names based on ISO codes, leveraging the Intl.DisplayNames API.
495
495
  </p>
496
496
  <div class="maz-flex-1"></div>
497
497
  <MazBtn color="background" outlined size="sm" block href="/composables/use-display-names">Discover</MazBtn>
@@ -0,0 +1,21 @@
1
+ ---
2
+ title: Theme Editor
3
+ description: Create your own theme for maz-ui and export it to use it in your project
4
+ layout: home
5
+ sidebar: false
6
+ ---
7
+
8
+ <br />
9
+ <br />
10
+
11
+ # {{ $frontmatter.title }}
12
+
13
+ {{ $frontmatter.description }}
14
+
15
+ <br />
16
+
17
+ <ThemeEditorPage />
18
+
19
+ <script setup lang="ts">
20
+ import ThemeEditorPage from './demo/ThemeEditorPage.vue'
21
+ </script>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@maz-ui/mcp",
3
3
  "type": "module",
4
- "version": "4.1.2",
4
+ "version": "4.1.3",
5
5
  "description": "Maz-UI ModelContextProtocol Client",
6
6
  "author": "Louis Mazel <me@loicmazuel.com>",
7
7
  "license": "MIT",
@@ -58,8 +58,8 @@
58
58
  "test:unit:coverage": "pnpm generate:docs && vitest run --coverage"
59
59
  },
60
60
  "dependencies": {
61
- "@maz-ui/node": "4.1.2",
62
- "@maz-ui/utils": "4.1.2",
61
+ "@maz-ui/node": "4.1.3",
62
+ "@maz-ui/utils": "4.1.3",
63
63
  "@modelcontextprotocol/sdk": "^1.17.2"
64
64
  },
65
65
  "devDependencies": {
@@ -80,5 +80,5 @@
80
80
  "lint-staged": {
81
81
  "*.{js,ts,mjs,mts,cjs,md,yml,json}": "cross-env NODE_ENV=production eslint --fix"
82
82
  },
83
- "gitHead": "7be37c69c61b31f83699a61039b407ff196facc4"
83
+ "gitHead": "09f62e1bb3a3faaaa1dc48ea6434f8da80a23d76"
84
84
  }