@maz-ui/mcp 5.1.0 → 5.1.1

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/cli.mjs CHANGED
@@ -3,7 +3,7 @@ import 'node:path';
3
3
  import 'node:util';
4
4
  import '@maz-ui/node';
5
5
  import '@maz-ui/utils/helpers/getErrorMessage';
6
- export { H as HELP, m as main, i as runCli, k as runInit, n as runReview } from './shared/mcp.BFjMMLqy.mjs';
6
+ export { H as HELP, m as main, i as runCli, k as runInit, n as runReview } from './shared/mcp.cBFLVChV.mjs';
7
7
  import 'node:fs';
8
8
  import 'node:url';
9
9
  import 'zod';
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { D as DocSearch, K as Knowledge, T as TOOLS, b as buildInstructions, c as countBySeverity, a as createContext, d as createMazUiMcpServer, f as filterBySeverity, e as findProjectMazUi, g as formatFindings, l as loadKnowledge, m as main, r as reviewCode, h as reviewFiles, i as runCli, s as searchIcons, j as startStdioServer } from './shared/mcp.BFjMMLqy.mjs';
1
+ export { D as DocSearch, K as Knowledge, T as TOOLS, b as buildInstructions, c as countBySeverity, a as createContext, d as createMazUiMcpServer, f as filterBySeverity, e as findProjectMazUi, g as formatFindings, l as loadKnowledge, m as main, r as reviewCode, h as reviewFiles, i as runCli, s as searchIcons, j as startStdioServer } from './shared/mcp.cBFLVChV.mjs';
2
2
  export { setupAgents } from '@maz-ui/node';
3
3
  import 'node:buffer';
4
4
  import 'node:path';
@@ -1398,11 +1398,12 @@ function reportUnknownProp(name, offset, component, context) {
1398
1398
  const near = propSuggestions(name, component, { containing: !passthrough });
1399
1399
  if (passthrough && near.length === 0)
1400
1400
  return;
1401
+ const names = near.map((entry) => entry === "modelValue" ? "`v-model`" : `\`${toKebab(entry)}\``).join(" or ");
1401
1402
  context.report({
1402
1403
  rule: "unknown-prop",
1403
1404
  severity: "warning",
1404
- message: `${component.name} has no prop \`${name}\`${passthrough ? "" : ": it will only be forwarded as an HTML attribute"}.`,
1405
- suggestion: near.length > 0 ? `Did you mean ${near.map((entry) => entry === "modelValue" ? "`v-model`" : `\`${toKebab(entry)}\``).join(" or ")}? Check \`get_component_api({ names: ["${component.name}"] })\`.` : `Check the real API with \`get_component_api({ names: ["${component.name}"] })\`.`
1405
+ message: passthrough ? `\`${name}\` is not a prop of ${component.name}: it is only forwarded as an HTML attribute (the component may not use it).` : `${component.name} has no prop \`${name}\`: it will only be forwarded as an HTML attribute.`,
1406
+ suggestion: near.length > 0 ? `Did you mean ${names}? Check \`get_component_api({ names: ["${component.name}"] })\`.` : `Check the real API with \`get_component_api({ names: ["${component.name}"] })\`.`
1406
1407
  }, offset);
1407
1408
  }
1408
1409
  function checkModel(directive, component, context) {
@@ -1512,15 +1513,15 @@ function checkMazComponent(element, component, source, context) {
1512
1513
  }
1513
1514
  const SVG_SHAPES = /* @__PURE__ */ new Set(["path", "circle", "rect", "polyline", "polygon", "line", "ellipse"]);
1514
1515
  const ICON_MAX_VIEWBOX = 32;
1515
- function svgDescendants(element) {
1516
- return element.children.filter(isElement).flatMap((child) => [child, ...svgDescendants(child)]);
1516
+ function descendantsOf(element) {
1517
+ return element.children.filter(isElement).flatMap((child) => [child, ...descendantsOf(child)]);
1517
1518
  }
1518
1519
  function isAnimated(element) {
1519
1520
  const classes = staticAttribute(element, "class")?.value?.content ?? "";
1520
1521
  return element.tag.startsWith("animate") || /\banimate-|\[animation/.test(classes) || element.props.some((prop) => prop.name.startsWith("stroke-dash"));
1521
1522
  }
1522
1523
  function isIconLikeSvg(svg) {
1523
- const descendants = svgDescendants(svg);
1524
+ const descendants = descendantsOf(svg);
1524
1525
  if (!descendants.some((child) => SVG_SHAPES.has(child.tag)))
1525
1526
  return false;
1526
1527
  const viewBox = staticAttribute(svg, "viewBox")?.value?.content.trim().split(/[\s,]+/).map(Number);
@@ -1528,6 +1529,32 @@ function isIconLikeSvg(svg) {
1528
1529
  return false;
1529
1530
  return ![svg, ...descendants].some((node) => isAnimated(node) || node !== svg && node.props.some((prop) => prop.type === NodeTypes.DIRECTIVE));
1530
1531
  }
1532
+ const LAYOUT_TAGS = /* @__PURE__ */ new Set(["div", "p", "h1", "h2", "h3", "h4", "h5", "h6", "ul", "ol", "li", "dl", "img", "picture", "video", "canvas", "section", "article", "header", "footer", "figure", "table"]);
1533
+ const NEUTRAL_COMPONENTS = /* @__PURE__ */ new Set(["Transition", "TransitionGroup", "KeepAlive", "Teleport", "Suspense", "ClientOnly", "NuxtLink", "RouterLink"]);
1534
+ function contentOf(element) {
1535
+ return element.children.filter((child) => child.type !== NodeTypes.COMMENT && !(child.type === NodeTypes.TEXT && child.content.trim() === ""));
1536
+ }
1537
+ function isIconOrDecoration(element, context) {
1538
+ const pascal = toPascal(element.tag).replace(/^Lazy/, "");
1539
+ return element.tag === "svg" || element.tag === "component" || context.knowledge.iconNames.has(pascal) || pascal.endsWith("Icon") || ["i", "span"].includes(element.tag) && contentOf(element).length === 0;
1540
+ }
1541
+ function isComponentTag(element) {
1542
+ return /^[A-Z]/.test(element.tag) || element.tag.includes("-");
1543
+ }
1544
+ function isCompositeButton(button, context) {
1545
+ const descendants = descendantsOf(button);
1546
+ if (descendants.some((node) => LAYOUT_TAGS.has(node.tag)))
1547
+ return true;
1548
+ if (descendants.some((node) => isComponentTag(node) && !NEUTRAL_COMPONENTS.has(toPascal(node.tag)) && !isIconOrDecoration(node, context)))
1549
+ return true;
1550
+ return hasStackedLabels(button, context);
1551
+ }
1552
+ function hasStackedLabels(element, context) {
1553
+ const content = contentOf(element);
1554
+ const labels = content.filter((child) => isElement(child) && !isIconOrDecoration(child, context));
1555
+ const isSentence = content.some((child) => !isElement(child));
1556
+ return labels.length >= 2 && !isSentence || labels.some((label) => hasStackedLabels(label, context));
1557
+ }
1531
1558
  function checkNativeElement(element, context) {
1532
1559
  if (element.tag === "svg" && isIconLikeSvg(element)) {
1533
1560
  context.report({
@@ -1538,6 +1565,8 @@ function checkNativeElement(element, context) {
1538
1565
  }, element.loc.start.offset);
1539
1566
  return;
1540
1567
  }
1568
+ if (element.tag === "button" && (contentOf(element).length === 0 || isCompositeButton(element, context)))
1569
+ return;
1541
1570
  const replacement = nativeReplacement(element.tag, staticAttribute(element, "type")?.value?.content);
1542
1571
  if (replacement) {
1543
1572
  context.report({
@@ -288,7 +288,7 @@ type MazGalleryImage =
288
288
 
289
289
  ### Props
290
290
 
291
- - `orientation` (`"column" | "column-reverse" | "row" | "row-reverse"`, default: `"column"`): Card variant: Must be `column | row | row-reverse | column-reverse`.
291
+ - `orientation` (`"row" | "column" | "column-reverse" | "row-reverse"`, default: `"column"`): Card variant: Must be `column | row | row-reverse | column-reverse`.
292
292
  - `href` (`string`): Make card a link (footer area excluded).
293
293
  - `to` (`string | et | X`): Make card a link with a router-link or nuxt-link (footer area excluded).
294
294
  - `href-target` (`string`, default: `"_self"`): Target option of link: Muse be one of `_blank | _self | _parent | _top | framename`.
@@ -174,10 +174,10 @@ type Size = 'mini' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'
174
174
  - `message` (`string`): Dialog message displayed in the body.
175
175
  - `reject-text` (`string`): Text for the reject button - will be applied only if buttons props is not provided.
176
176
  - `reject-props` (`(Omit<MazBtnProps, "type"> & MazDialogConfirmButton)`, default: `{ color: 'destructive', type: 'reject', text: 'Cancel', response: 'reject' }`): Props for the reject button - will be applied only if buttons props is not provided.
177
- - `hide-reject-button` (`boolean`, default: `true`): Whether to display the reject button.
177
+ - `hide-reject-button` (`boolean`, default: `false`): Hide the reject button (unset: the value of `useMazDialogConfirm().data`, else shown).
178
178
  - `accept-text` (`string`): Text for the accept button.
179
179
  - `accept-props` (`(Omit<MazBtnProps, "type"> & MazDialogConfirmButton)`, default: `{ color: 'success', type: 'accept', text: 'Confirm', response: 'accept' }`): Props for the accept button - will be applied only if buttons props is not provided.
180
- - `hide-accept-button` (`boolean`, default: `true`): Whether to display the accept button.
180
+ - `hide-accept-button` (`boolean`, default: `false`): Hide the accept button (unset: the value of `useMazDialogConfirm().data`, else shown).
181
181
  - `buttons` (`MazDialogConfirmButton[]`): Buttons to display in the footer.
182
182
  - `model-value` (`boolean`): Modal's model value.
183
183
  - `hide-close-button` (`boolean`): Remove the close button in header.
@@ -130,7 +130,7 @@ If no `to` or `href` is provided, the component will be a `button` by default. Y
130
130
  - `target` (`string`, default: `"_self"`): The target of the link. Values: `'_blank'`, `'_self'`, `'_parent'`, `'_top'` (non exhaustive).
131
131
  - `download` (`string`): The download of the link.
132
132
  - `rel` (`string`): The rel of the link.
133
- - `aria-label` (`string`): The aria-label of the link.
133
+ - `aria-label` (`string`): The aria-label of the link (or of the button).
134
134
  - `underline` (`boolean`, default: `false`): Add an underline to the link.
135
135
  - `underline-hover` (`boolean`, default: `true`): Add an underline only on hover.
136
136
  - `auto-external` (`boolean`, default: `true`): Add an external icon to the link if target is '_blank'.
@@ -484,10 +484,10 @@ This ensures consistent internationalization across your application while provi
484
484
  - `required` (`boolean`): Make the input required in the form.
485
485
  - `placeholder` (`string`): The placeholder of the select.
486
486
  - `label` (`string`): The label of the select.
487
- - `search-function` (`((query: string, options: Option[]) => Option[] | undefined)`): Replace the default search function to provide a custom search function.
488
487
  - `transition` (`string`, default: `'scale-fade'`): The transition name of the panel list options.
489
488
  - `prefer-position` (`MazPopoverPreferPosition`, default: `'bottom-start'`): The prefer position of the list.
490
489
  - `fallback-position` (`MazPopoverFallbackPosition`, default: `'top-start'`): The fallback position of the list.
490
+ - `search-function` (`((query: string, options: Option[]) => Option[] | undefined)`): Replace the default search function to provide a custom search function.
491
491
  - `top-label` (`string`): Static label displayed above the input field. Unlike the floating label, this remains fixed.
492
492
  - `autocomplete` (`string`, default: `'off'`): The autocomplete attribute of the input.
493
493
  - `option-value-key` (`string`, default: `"code"`): The key of the option value.
@@ -26,7 +26,8 @@ More info about [dialog plugin](../plugins/dialog.md) in its documentation
26
26
 
27
27
  ```vue
28
28
  <script lang="ts" setup>
29
- import { useDialog, useToast } from 'maz-ui/composables'
29
+ import { useDialog } from 'maz-ui/composables/useDialog'
30
+ import { useToast } from 'maz-ui/composables/useToast'
30
31
 
31
32
  const dialog = useDialog()
32
33
 
@@ -79,16 +79,16 @@ import { MazCheck, MazHeart, MazUser } from '@maz-ui/icons'
79
79
 
80
80
  <template>
81
81
  <div>
82
- <MazCheck class="text-green-500" />
83
- <MazUser class="w-6 h-6" />
84
- <MazHeart class="text-red-500 hover:scale-110 transition-transform" />
82
+ <MazCheck class="text-success" />
83
+ <MazUser class="size-6" />
84
+ <MazHeart class="text-destructive hover:scale-110 transition-transform" />
85
85
  </div>
86
86
  </template>
87
87
  ```
88
88
 
89
89
  #### Lazy Icons
90
90
 
91
- Lazy icons are prefixed with `Lazy` and use `defineAsyncComponent` under the hood. Use them when you want to reduce your initial bundle size:
91
+ Lazy icons use `defineAsyncComponent` under the hood. Use them when you want to reduce your initial bundle size. From the `lazy/` sub-paths they keep their name; from the `@maz-ui/icons` root (and with the resolver) they are prefixed with `Lazy` (`LazyMazCheck`):
92
92
 
93
93
  ```vue
94
94
  <script setup lang="ts">
@@ -99,9 +99,9 @@ import { MazUser } from '@maz-ui/icons/lazy/MazUser'
99
99
 
100
100
  <template>
101
101
  <div>
102
- <LazyMazCheck class="text-green-500" />
103
- <LazyMazUser class="w-6 h-6" />
104
- <LazyMazHeart class="text-red-500 hover:scale-110 transition-transform" />
102
+ <MazCheck class="text-success" />
103
+ <MazUser class="size-6" />
104
+ <MazHeart class="text-destructive hover:scale-110 transition-transform" />
105
105
  </div>
106
106
  </template>
107
107
  ```
@@ -191,17 +191,17 @@ export default defineConfig({
191
191
  <!-- Static icons (eagerly loaded) -->
192
192
  <MazHome class="nav-icon" />
193
193
  <MazUser class="nav-icon" />
194
- <MazSettings class="nav-icon" />
194
+ <MazCog6Tooth class="nav-icon" />
195
195
 
196
196
  <!-- Lazy icons (async loaded) - prefix with "Lazy" -->
197
- <LazyMazLogout class="nav-icon" />
197
+ <LazyMazArrowRightStartOnRectangle class="nav-icon" />
198
198
  </div>
199
199
  </template>
200
200
 
201
201
  <style scoped>
202
202
  @reference "../../.vitepress/theme/main.css";
203
203
  .nav-icon {
204
- @apply w-6 h-6 text-gray-600 hover:text-blue-500 transition-colors cursor-pointer;
204
+ @apply size-6 text-muted hover:text-primary transition-colors cursor-pointer;
205
205
  }
206
206
  </style>
207
207
  ```
@@ -250,9 +250,9 @@ import UserIcon from '@maz-ui/icons/svg/user.svg?component'
250
250
 
251
251
  <template>
252
252
  <div class="flex items-center gap-2">
253
- <CheckIcon class="w-5 h-5 text-green-600" />
254
- <UserIcon class="w-6 h-6 text-blue-500" />
255
- <HeartIcon class="w-4 h-4 text-red-500 animate-pulse" />
253
+ <CheckIcon class="size-5 text-success" />
254
+ <UserIcon class="size-6 text-primary" />
255
+ <HeartIcon class="size-4 text-destructive animate-pulse" />
256
256
  </div>
257
257
  </template>
258
258
  ```
@@ -286,7 +286,7 @@ onMounted(async () => {
286
286
  <img src="@maz-ui/icons/svg/check.svg" alt="Check" class="w-6 h-6">
287
287
 
288
288
  <!-- Inline SVG with fetch -->
289
- <div class="text-blue-500" v-html="checkSvg" />
289
+ <div class="text-primary" v-html="checkSvg" />
290
290
  </div>
291
291
  </template>
292
292
  ```
@@ -311,19 +311,19 @@ Icons inherit the current text color and can be styled like any other element:
311
311
  <MazStar class="text-2xl" />
312
312
 
313
313
  <!-- Colors -->
314
- <MazHeart class="text-red-500" />
315
- <MazLeaf class="text-green-600" />
316
- <MazSky class="text-blue-400" />
314
+ <MazHeart class="text-destructive" />
315
+ <MazCheckCircle class="text-success" />
316
+ <MazSun class="text-warning" />
317
317
 
318
318
  <!-- Interactive states -->
319
- <MazBtn class="hover:text-blue-500 transition-colors cursor-pointer" />
319
+ <MazStar class="hover:text-primary transition-colors cursor-pointer" />
320
320
 
321
321
  <!-- Animations -->
322
322
  <MazSpinner class="animate-spin" />
323
323
  <MazHeart class="hover:scale-110 transition-transform" />
324
324
 
325
325
  <!-- With background -->
326
- <MazCheck class="p-2 bg-green-100 text-green-600 rounded-full" />
326
+ <MazCheck class="p-2 bg-success/15 text-success rounded-full" />
327
327
  </div>
328
328
  </template>
329
329
  ```
@@ -504,9 +504,9 @@ export function iconOptimizer(): Plugin {
504
504
  ```vue
505
505
  <template>
506
506
  <div class="flex items-center space-x-4">
507
- <MazHome class="w-5 h-5 text-gray-500 hover:text-blue-500 transition-colors" />
508
- <MazUser class="w-6 h-6 text-indigo-600" />
509
- <MazSettings class="w-4 h-4 text-gray-400 hover:text-gray-600" />
507
+ <MazHome class="size-5 text-muted hover:text-primary transition-colors" />
508
+ <MazUser class="size-6 text-secondary" />
509
+ <MazCog6Tooth class="size-4 text-muted hover:text-foreground" />
510
510
  </div>
511
511
  </template>
512
512
  ```
@@ -180,7 +180,7 @@ The command exits with an error code when it finds errors (or more warnings than
180
180
  | `boolean-prop-string` | error | `disabled="false"` (a truthy string) |
181
181
  | `unknown-model`, `unknown-event`, `unknown-slot` | error | `v-model:foo`, `@clik`, `<template #captions>` |
182
182
  | `unknown-icon` | error | An icon that does not exist in `@maz-ui/icons` |
183
- | `prefer-maz-component` | warning | `<button>`, `<input>`, `<select>`, `<textarea>`, `<dialog>`... |
183
+ | `prefer-maz-component` | warning | `<button>`, `<input>`, `<select>`, `<textarea>`, `<dialog>`... (a `<button>` that is a clickable card, with a layout, a component or a title and a subtitle, or an empty hit area, is left alone) |
184
184
  | `inline-svg` | warning | SVG icons written inline |
185
185
  | `prefer-ecosystem`, `prefer-utils` | warning / info | lodash, VueUse, toast, icon, tooltip, date picker... libraries that maz-ui already covers |
186
186
  | `theme-colors` | warning | Default Tailwind palette (`bg-blue-500`, `text-gray-600`, `bg-white`) |