@create-ui/cli 0.5.7 → 0.5.9
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/{chunk-RMTTHCB3.js → chunk-2ELKDGGM.js} +3 -3
- package/dist/{chunk-RMTTHCB3.js.map → chunk-2ELKDGGM.js.map} +1 -1
- package/dist/chunk-643QI2I2.js +102 -0
- package/dist/chunk-643QI2I2.js.map +1 -0
- package/dist/{chunk-NQFMXHMH.js → chunk-KQTXDVKV.js} +3 -3
- package/dist/chunk-KQTXDVKV.js.map +1 -0
- package/dist/index.js +35 -35
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.js +1 -1
- package/dist/registry/index.js +1 -1
- package/dist/skills/createui/SKILL.md +201 -177
- package/dist/skills/createui/agents/openai.yml +1 -1
- package/dist/skills/createui/cli.md +42 -42
- package/dist/skills/createui/customization.md +20 -15
- package/dist/skills/createui/evals/evals.json +68 -5
- package/dist/skills/createui/mcp.md +14 -5
- package/dist/skills/createui/reference/accordion.md +127 -0
- package/dist/skills/createui/reference/app-store-badge.md +88 -0
- package/dist/skills/createui/reference/aspect-ratio.md +52 -0
- package/dist/skills/createui/reference/avatar.md +230 -0
- package/dist/skills/createui/reference/badge.md +110 -0
- package/dist/skills/createui/reference/breadcrumb.md +153 -0
- package/dist/skills/createui/reference/button-group.md +116 -0
- package/dist/skills/createui/reference/button.md +104 -0
- package/dist/skills/createui/reference/checkbox-group.md +118 -0
- package/dist/skills/createui/reference/checkbox.md +79 -0
- package/dist/skills/createui/reference/chip.md +115 -0
- package/dist/skills/createui/reference/close-button.md +83 -0
- package/dist/skills/createui/reference/command.md +69 -0
- package/dist/skills/createui/reference/country-flag.md +109 -0
- package/dist/skills/createui/reference/credit-card-input.md +76 -0
- package/dist/skills/createui/reference/date-input.md +71 -0
- package/dist/skills/createui/reference/dropdown-menu.md +164 -0
- package/dist/skills/createui/reference/field.md +186 -0
- package/dist/skills/createui/reference/info-tooltip.md +110 -0
- package/dist/skills/createui/reference/inline-alert.md +146 -0
- package/dist/skills/createui/reference/input-group.md +171 -0
- package/dist/skills/createui/reference/input-otp.md +130 -0
- package/dist/skills/createui/reference/input-stepper.md +120 -0
- package/dist/skills/createui/reference/input.md +118 -0
- package/dist/skills/createui/reference/label.md +121 -0
- package/dist/skills/createui/reference/pagination.md +157 -0
- package/dist/skills/createui/reference/password-strength.md +70 -0
- package/dist/skills/createui/reference/phone-input.md +77 -0
- package/dist/skills/createui/reference/progress.md +158 -0
- package/dist/skills/createui/reference/radio-group.md +133 -0
- package/dist/skills/createui/reference/radio.md +79 -0
- package/dist/skills/createui/reference/scroll-area.md +212 -0
- package/dist/skills/createui/reference/segmented-control.md +146 -0
- package/dist/skills/createui/reference/select.md +204 -0
- package/dist/skills/createui/reference/separator.md +99 -0
- package/dist/skills/createui/reference/social-login-button.md +130 -0
- package/dist/skills/createui/reference/spinner.md +68 -0
- package/dist/skills/createui/reference/status-badge.md +89 -0
- package/dist/skills/createui/reference/switch-group.md +122 -0
- package/dist/skills/createui/reference/switch.md +75 -0
- package/dist/skills/createui/reference/tab-menu.md +165 -0
- package/dist/skills/createui/reference/text-link.md +84 -0
- package/dist/skills/createui/reference/textarea.md +50 -0
- package/dist/skills/createui/reference/toast.md +162 -0
- package/dist/skills/createui/reference/tooltip.md +63 -0
- package/dist/skills/createui/rules/composition.md +41 -25
- package/dist/skills/createui/rules/design.md +266 -0
- package/dist/skills/createui/rules/forms.md +44 -15
- package/dist/skills/createui/rules/icons.md +64 -18
- package/dist/skills/createui/rules/styling.md +53 -14
- package/dist/utils/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-M5DYT2NE.js +0 -64
- package/dist/chunk-M5DYT2NE.js.map +0 -1
- package/dist/chunk-NQFMXHMH.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Styling & tokens
|
|
2
2
|
|
|
3
|
-
Create UI ships one unified styling system driven by semantic design tokens. Style with those tokens and each component's built-in props
|
|
3
|
+
Create UI ships one unified styling system driven by semantic design tokens. Style with those tokens and each component's built-in props - never reach for raw Tailwind colors or hand-rolled class overrides.
|
|
4
4
|
|
|
5
5
|
See [customization.md](../customization.md) for theming, CSS variables, and adding custom colors.
|
|
6
6
|
|
|
@@ -10,9 +10,11 @@ See [customization.md](../customization.md) for theming, CSS variables, and addi
|
|
|
10
10
|
- Status & state colors
|
|
11
11
|
- Built-in props first
|
|
12
12
|
- className for layout only
|
|
13
|
+
- Typography tokens
|
|
13
14
|
- Semantic spacing tokens
|
|
14
15
|
- No space-x-* / space-y-*
|
|
15
16
|
- Prefer size-* over w-* h-* when equal
|
|
17
|
+
- Loading placeholders reuse the loaded layout
|
|
16
18
|
- Prefer truncate shorthand
|
|
17
19
|
- No manual dark: color overrides
|
|
18
20
|
- Use cn() for conditional classes
|
|
@@ -23,12 +25,12 @@ See [customization.md](../customization.md) for theming, CSS variables, and addi
|
|
|
23
25
|
|
|
24
26
|
## Semantic color tokens
|
|
25
27
|
|
|
26
|
-
Create UI's tokens are HEX-backed CSS variables that swap automatically between light and dark via the `.dark` class. Use the semantic token names
|
|
28
|
+
Create UI's tokens are HEX-backed CSS variables that swap automatically between light and dark via the `.dark` class. Use the semantic token names - never raw palette colors and never invented utility names.
|
|
27
29
|
|
|
28
30
|
- Surfaces (weak → strong): `bg-weakest`, `bg-weak`, `bg-light`, `bg-medium`, `bg-heavy`, `bg-strong`, `bg-strongest`. Theme-swapping page/card surface: `bg-static`.
|
|
29
|
-
- Text: `text-body` (primary), `text-placeholder` (hints/secondary), `text-disabled`, `text-strongest` (high-contrast).
|
|
31
|
+
- Text: `text-body` (primary), `text-placeholder` (hints/secondary), `text-disabled`, `text-strongest` (high-contrast). **`text-static` / `text-static-white` are theme-RELATIVE and flip to black under `.dark`** - they are NOT "always white" (see "static tokens are theme-relative" below). The only never-swap text is the raw `text-white` / `text-black` palette.
|
|
30
32
|
- Borders: `border-weakest` … `border-strongest` (commonly `border-light` / `border-medium`).
|
|
31
|
-
- Primary scale: `bg-primary-500` (= `bg-primary-base`), `text-primary-base`, `bg-primary-alpha-16`, `bg-primary-alpha-48`.
|
|
33
|
+
- Primary scale: `bg-primary-500` (= `bg-primary-base`), `text-primary-base`, `bg-primary-alpha-16`, `bg-primary-alpha-48`. **`primary` IS the project's brand color** - chosen once at `init` (indigo / blue / lime / green / red / orange / yellow / cyan) and baked into these tokens. Just use them; never ask the user for a brand color, never invent one, and never hand-edit the token hex values to re-theme. A different theme is a re-run of `createui init --theme <name>`, not a CSS edit.
|
|
32
34
|
|
|
33
35
|
**Incorrect:**
|
|
34
36
|
|
|
@@ -63,7 +65,7 @@ Quick translation from generic utility names to Create UI tokens:
|
|
|
63
65
|
|
|
64
66
|
## Status & state colors
|
|
65
67
|
|
|
66
|
-
Each status family (`error`, `success`, `warning`, `info`) exposes `-weakest` … `-strongest` plus `-base`. Prefer these semantic tokens
|
|
68
|
+
Each status family (`error`, `success`, `warning`, `info`, `away`) exposes `-weakest` … `-strongest` plus `-base`. Prefer these semantic tokens - or a `StatusBadge` - for positive, negative, and informational indicators.
|
|
67
69
|
|
|
68
70
|
**Incorrect:**
|
|
69
71
|
|
|
@@ -79,7 +81,7 @@ Each status family (`error`, `success`, `warning`, `info`) exposes `-weakest`
|
|
|
79
81
|
<span className="text-error-base">Payment failed</span>
|
|
80
82
|
```
|
|
81
83
|
|
|
82
|
-
Create UI's own `Button` implements its `danger` / `success` variants with the raw red/green scales (`bg-red-600`, `bg-green-600`, `bg-red-alpha-16`), so those scales are acceptable for status work
|
|
84
|
+
Create UI's own `Button` implements its `danger` / `success` variants with the raw red/green scales (`bg-red-600`, `bg-green-600`, `bg-red-alpha-16`), so those scales are acceptable for status work - but prefer the semantic token (`text-error-base`, `bg-success-base`) unless you are intentionally matching that variant's exact look. For full status affordances, reach for `StatusBadge` rather than styling a raw `<span>`.
|
|
83
85
|
|
|
84
86
|
---
|
|
85
87
|
|
|
@@ -87,7 +89,7 @@ Create UI's own `Button` implements its `danger` / `success` variants with the r
|
|
|
87
89
|
|
|
88
90
|
Every primitive exposes its full visual range through typed props. Drive appearance through those props, not through manual `border` / `bg` / `hover:` class overrides.
|
|
89
91
|
|
|
90
|
-
`Button` has four styling axes (verify any other component's props from its installed source under the project's `ui` alias
|
|
92
|
+
`Button` has four styling axes (verify any other component's props from its installed source under the project's `ui` alias - e.g. `components/ui/<name>.tsx` - or with `npx @create-ui/cli view <name>`):
|
|
91
93
|
|
|
92
94
|
- `variant`: `primary` (default), `neutral-solid`, `neutral-light`, `danger`, `success`, `inverse-solid`, `inverse-light`
|
|
93
95
|
- `appearance`: `solid` (default), `outline`, `ghost`, `soft`
|
|
@@ -110,7 +112,7 @@ There is no `variant="outline"` / `variant="destructive"` / `variant="secondary"
|
|
|
110
112
|
<Button appearance="outline">Click me</Button>
|
|
111
113
|
```
|
|
112
114
|
|
|
113
|
-
`Button` also has a real `loading` prop
|
|
115
|
+
`Button` also has a real `loading` prop - it renders a `Spinner` and blocks interaction automatically. Don't hand-compose a spinner.
|
|
114
116
|
|
|
115
117
|
**Incorrect:**
|
|
116
118
|
|
|
@@ -132,9 +134,9 @@ There is no `variant="outline"` / `variant="destructive"` / `variant="secondary"
|
|
|
132
134
|
|
|
133
135
|
Use `className` for layout (e.g. `max-w-md`, `mx-auto`, `mt-4`), **not** for overriding component colors or typography. To change appearance, prefer these in order:
|
|
134
136
|
|
|
135
|
-
1. **Built-in props**
|
|
136
|
-
2. **Semantic tokens**
|
|
137
|
-
3. **CSS variables**
|
|
137
|
+
1. **Built-in props** - `appearance="outline"`, `variant="danger"`, `size="sm"`, etc.
|
|
138
|
+
2. **Semantic tokens** - `bg-static`, `text-placeholder`, `bg-primary-base`.
|
|
139
|
+
3. **CSS variables** - define or override `--color-*` in the project's global CSS file (see [customization.md](../customization.md)).
|
|
138
140
|
|
|
139
141
|
**Incorrect:**
|
|
140
142
|
|
|
@@ -150,11 +152,27 @@ Use `className` for layout (e.g. `max-w-md`, `mx-auto`, `mt-4`), **not** for ove
|
|
|
150
152
|
|
|
151
153
|
---
|
|
152
154
|
|
|
155
|
+
## Typography tokens
|
|
156
|
+
|
|
157
|
+
Free-standing text uses the Create UI type scale, not Tailwind's default sizes. Each token sets size, line-height, letter-spacing, and weight together:
|
|
158
|
+
|
|
159
|
+
- Headings: `text-heading-h1` … `text-heading-h6` (pair with a color token like `text-strongest` and adjust `font-*` only when the design calls for it).
|
|
160
|
+
- Body and captions: `text-body-xs` … `text-body-xl`.
|
|
161
|
+
- Long-form prose: `text-paragraph-*` (same size steps).
|
|
162
|
+
- Oversized display text: `text-display-lg` / `text-display-xl`.
|
|
163
|
+
- Control-adjacent text (inside components): `text-ui-*` - components set these themselves; don't add them manually. The one sanctioned free-standing use is the marketing overline / micro-caption pattern (`text-ui-overline-xs uppercase`, see rules/design.md).
|
|
164
|
+
|
|
165
|
+
**Incorrect:** `<h2 className="text-2xl font-bold">` · **Correct:** `<h2 className="text-heading-h4 text-strongest font-semibold">`
|
|
166
|
+
|
|
167
|
+
These tokens auto-scale across breakpoints like the spacing tokens - never add `md:` / `xl:` prefixes to them.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
153
171
|
## Semantic spacing tokens
|
|
154
172
|
|
|
155
173
|
Create UI mirrors Figma's spacing variables as Tailwind utilities: `gap-component-sm` (8px), `p-component-md` (12px), `gap-component-lg` (16px), `gap-layout-md` (64px), `p-layout-sm` (48px), and so on.
|
|
156
174
|
|
|
157
|
-
Use a semantic spacing class **only when Figma references that semantic token** (e.g. `var(--component/sm,8px)` → `gap-component-sm`). When Figma shows a static value (e.g. `space-space-4`), use the standard Tailwind class (`gap-4`). These tokens rescale across themes/breakpoints, so don't apply them where a fixed gap is intended, and never add `md:` / `xl:` prefixes to them
|
|
175
|
+
Use a semantic spacing class **only when Figma references that semantic token** (e.g. `var(--component/sm,8px)` → `gap-component-sm`). When Figma shows a static value (e.g. `space-space-4`), use the standard Tailwind class (`gap-4`). These tokens rescale across themes/breakpoints, so don't apply them where a fixed gap is intended, and never add `md:` / `xl:` prefixes to them - they auto-scale.
|
|
158
176
|
|
|
159
177
|
Prefer `px-component-none` over `px-0` when it is an intentional "no horizontal padding" override of a token, to keep the intent explicit.
|
|
160
178
|
|
|
@@ -180,6 +198,12 @@ Use `gap-*` instead. `space-y-4` → `flex flex-col gap-4`; `space-x-2` → `fle
|
|
|
180
198
|
|
|
181
199
|
---
|
|
182
200
|
|
|
201
|
+
## Loading placeholders reuse the loaded layout
|
|
202
|
+
|
|
203
|
+
A loading/pending state must render the same shell as the loaded content: same padding and gaps, with one token-sized stand-in per line (e.g. a `bg-weak h-5 w-24 rounded` bar where `text-body-sm` text will go) - never a hard-coded pixel height like `min-h-[140px]` around a centered `Spinner`. Typography and spacing tokens auto-scale at the 1279px/767px breakpoints (`--text-heading-h3` is 36 → 32 → 24px), so any fixed px approximation is wrong at some breakpoint and the layout jumps when data arrives.
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
183
207
|
## Prefer truncate shorthand
|
|
184
208
|
|
|
185
209
|
`truncate` not `overflow-hidden text-ellipsis whitespace-nowrap`.
|
|
@@ -188,7 +212,7 @@ Use `gap-*` instead. `space-y-4` → `flex flex-col gap-4`; `space-x-2` → `fle
|
|
|
188
212
|
|
|
189
213
|
## No manual dark: color overrides
|
|
190
214
|
|
|
191
|
-
Semantic tokens already swap with the `.dark` class
|
|
215
|
+
Semantic tokens already swap with the `.dark` class - don't write parallel `dark:` color utilities.
|
|
192
216
|
|
|
193
217
|
**Incorrect:**
|
|
194
218
|
|
|
@@ -202,6 +226,21 @@ Semantic tokens already swap with the `.dark` class — don't write parallel `da
|
|
|
202
226
|
<div className="bg-static text-body">
|
|
203
227
|
```
|
|
204
228
|
|
|
229
|
+
**`static` tokens are theme-relative, not absolute.** `bg-static` / `text-static` / `static-white` / `static-black` (and their `-alpha` variants) all FLIP under `.dark`: `static-white` is white in light but **black in dark**, `static` white → black, `static-black` the inverse. They are surface anchors, NOT "always white/black." Practical rule:
|
|
230
|
+
|
|
231
|
+
- Text or icon that must stay **white on a colored surface** (a `bg-primary-base` tile, a gradient, a brand mark) → raw `text-white` (the only never-swap white).
|
|
232
|
+
- Light primary text inside an always-`dark` island (a panel with the `dark` class) → `text-strongest` / `text-body` / `text-placeholder`; these resolve light under `.dark`. **Never** `text-static` / `text-static-white` there - they go black.
|
|
233
|
+
|
|
234
|
+
```tsx
|
|
235
|
+
// Incorrect - black text under .dark (dark island or colored tile)
|
|
236
|
+
<div className="dark ..."><h2 className="text-static-white">Title</h2></div>
|
|
237
|
+
<span className="bg-primary-base text-static-white">CU</span>
|
|
238
|
+
|
|
239
|
+
// Correct
|
|
240
|
+
<div className="dark ..."><h2 className="text-strongest">Title</h2></div>
|
|
241
|
+
<span className="bg-primary-base text-white">CU</span>
|
|
242
|
+
```
|
|
243
|
+
|
|
205
244
|
---
|
|
206
245
|
|
|
207
246
|
## Use cn() for conditional classes
|
|
@@ -240,7 +279,7 @@ Create UI focus styling is built on `outline`, not `ring`. The base is `outline-
|
|
|
240
279
|
<button className="outline-2 outline-transparent focus-visible:outline-primary-700">
|
|
241
280
|
```
|
|
242
281
|
|
|
243
|
-
Use `outline-primary-700` (or `outline-primary-500`) for primary controls and `outline-strong` / `outline-strongest` for neutral ones. Primitives already wire this up
|
|
282
|
+
Use `outline-primary-700` (or `outline-primary-500`) for primary controls and `outline-strong` / `outline-strongest` for neutral ones. Primitives already wire this up - you rarely need to set it yourself.
|
|
244
283
|
|
|
245
284
|
---
|
|
246
285
|
|
package/dist/utils/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {a}from'../chunk-VQCXAURP.js';import {Z}from'../chunk-
|
|
1
|
+
import {a}from'../chunk-VQCXAURP.js';import {Z}from'../chunk-KQTXDVKV.js';import'../chunk-Y7WZRQWW.js';import j from'postcss';import J from'postcss-selector-parser';import {z as z$1}from'zod';import {Project,ScriptKind,SyntaxKind,Node}from'ts-morph';var A="cn-",M=z$1.record(z$1.string().startsWith(A),z$1.string());function V(t){let e=j.parse(t),r={};return e.walkRules(s=>{let n=s.selectors??[];if(n.length===0)return;let i=R(s);if(i)for(let g of n){let l=v(g);J(o=>{o.each(a=>{let f=F(a);if(!f)return;let u=f.value;u.startsWith(A)&&(r[u]=r[u]?`${i} ${r[u]}`:i);});}).processSync(l);}}),M.parse(r)}function v(t){return t.replace(/\s*&\s*/g,"").trim()}function R(t){let e=[];for(let r of t.nodes||[])if(r.type==="atrule"&&r.name==="apply"){let s=r.params.trim();s&&e.push(s);}return e.length===0?null:e.join(" ")}function F(t){let e=[];return t.walkClasses(r=>{r.value.startsWith(A)&&e.push(r);}),e.length===0?null:e[e.length-1]}function p(t){return Node.isStringLiteral(t)||Node.isNoSubstitutionTemplateLiteral(t)}var P=async({sourceFile:t,styleMap:e})=>{let r=new Set;return $(t,e,r),z(t,e,r),w(t,e,r),t};function E(t,e,r){let s=t.getLiteralText(),n=S(s);if(n.length===0)return;let i=n.filter(l=>!r.has(l));if(i.length===0){let l=m(s);t.setLiteralValue(l);return}let g=i.map(l=>e[l]).filter(l=>!!l);if(g.length>0){let l=g.join(" "),o=m(d(l,s));t.setLiteralValue(o),i.forEach(a=>r.add(a));}else {let l=m(s);t.setLiteralValue(l);}}function $(t,e,r){t.forEachDescendant(s=>{if(!Node.isCallExpression(s))return;let n=s.getExpression();if(!Node.isIdentifier(n)||n.getText()!=="cva")return;let i=s.getArguments()[0];Node.isStringLiteral(i)&&E(i,e,r);let g=s.getArguments()[1];if(!g||!Node.isObjectLiteralExpression(g))return;let l=g.getProperties().find(a=>Node.isPropertyAssignment(a)&&Node.isIdentifier(a.getNameNode())&&a.getNameNode().getText()==="variants");if(!l||!Node.isPropertyAssignment(l))return;let o=l.getInitializer();!o||!Node.isObjectLiteralExpression(o)||o.getProperties().forEach(a=>{if(!Node.isPropertyAssignment(a))return;let f=a.getInitializer();!f||!Node.isObjectLiteralExpression(f)||f.getProperties().forEach(u=>{if(!Node.isPropertyAssignment(u))return;let x=u.getInitializer();x&&Node.isStringLiteral(x)&&E(x,e,r);});});});}function z(t,e,r){t.forEachDescendant(s=>{if(!Node.isJsxAttribute(s)||s.getNameNode().getText()!=="className")return;let n=s.getInitializer();if(!n)return;let i=D(n);if(i.length===0)return;let g=s.getParent()?.getParent();if(!g||!Node.isJsxOpeningElement(g)&&!Node.isJsxSelfClosingElement(g))return;let l=i.filter(a=>!r.has(a));if(l.length===0){I(n);return}let o=l.map(a=>e[a]).filter(a=>!!a);if(o.length>0){let a=o.join(" ");W(g,a);}else I(n);});}function D(t){let e=[];if(p(t))return S(t.getLiteralText());if(!Node.isJsxExpression(t))return e;let r=t.getExpression();if(!r)return e;if(p(r))return S(r.getLiteralText());if(Node.isCallExpression(r)&&T(r))for(let s of r.getArguments())p(s)&&e.push(...S(s.getLiteralText()));return e}function I(t){if(p(t)){let r=m(t.getLiteralText());t.setLiteralValue(r);return}if(!Node.isJsxExpression(t))return;let e=t.getExpression();if(e){if(p(e)){let r=m(e.getLiteralText());e.setLiteralValue(r);return}if(Node.isCallExpression(e)&&T(e)){for(let r of e.getArguments())if(p(r)){let s=m(r.getLiteralText());r.setLiteralValue(s);}C(e);}}}function S(t){let e=t.matchAll(/\bcn-[\w-]+\b/g);return Array.from(e,r=>r[0])}function m(t){return t.replace(/\bcn-[\w-]+\b/g,"").replace(/\s+/g," ").trim()}function C(t){if(!T(t))return;let e=t.getArguments(),r=e.filter(s=>p(s)?s.getLiteralText().trim()!=="":true);if(r.length!==e.length){let s=r.map(i=>i.getText()),n=t.getParent();n&&Node.isJsxExpression(n)?n.replaceWithText(`{cn(${s.join(", ")})}`):t.replaceWithText(`cn(${s.join(", ")})`);}}function W(t,e){if(!Node.isJsxOpeningElement(t)&&!Node.isJsxSelfClosingElement(t))return;let r=t.getAttributes().find(i=>Node.isJsxAttribute(i)&&i.getNameNode().getText()==="className");if(!r||!Node.isJsxAttribute(r)){t.addAttribute({name:"className",initializer:`{cn(${JSON.stringify(e)})}`});return}let s=r.getInitializer();if(!s){r.setInitializer(`{cn(${JSON.stringify(e)})}`);return}if(p(s)){let i=s.getLiteralText(),g=m(d(e,i));s.setLiteralValue(g);return}if(!Node.isJsxExpression(s))return;let n=s.getExpression();if(!n){r.setInitializer(`{cn(${JSON.stringify(e)})}`);return}if(p(n)){let i=n.getLiteralText(),g=m(d(e,i));n.setLiteralValue(g);return}if(Node.isCallExpression(n)&&T(n)){let i=n.getArguments()[0];if(p(i)){let o=i.getLiteralText(),a=m(d(e,o));i.setLiteralValue(a);for(let f=1;f<n.getArguments().length;f++){let u=n.getArguments()[f];if(p(u)){let x=u.getLiteralText(),y=m(x);y!==x&&u.setLiteralValue(y);}}C(n);return}let g=n.getArguments().map(o=>{if(p(o)){let a=m(o.getLiteralText());return a?JSON.stringify(a):null}return o.getText()}).filter(o=>o!==null),l=[JSON.stringify(e),...g];r.setInitializer(`{cn(${l.join(", ")})}`);return}r.setInitializer(`{cn(${JSON.stringify(e)}, ${n.getText()})}`);}function d(t,e){let r=e.split(/\s+/).filter(Boolean);return [...t.split(/\s+/).filter(Boolean),...r].join(" ").trim()}function T(t){let e=t.getExpression();return Node.isIdentifier(e)&&e.getText()==="cn"}function w(t,e,r){t.forEachDescendant(s=>{if(!Node.isCallExpression(s))return;let n=s.getExpression();if(!(!Node.isIdentifier(n)||n.getText()!=="mergeProps"))for(let i of s.getArguments()){if(!Node.isObjectLiteralExpression(i))continue;let g=i.getProperties().find(o=>Node.isPropertyAssignment(o)&&Node.isIdentifier(o.getNameNode())&&o.getNameNode().getText()==="className");if(!g||!Node.isPropertyAssignment(g))continue;let l=g.getInitializer();if(l&&Node.isCallExpression(l)&&T(l)){let o=B(l);if(o.length===0)continue;let a=o.filter(u=>!r.has(u));if(a.length===0){b(l);continue}let f=a.map(u=>e[u]).filter(u=>!!u);if(f.length>0){let u=f.join(" ");_(l,u,r,a);}else b(l);}}});}function B(t){let e=[];for(let r of t.getArguments())p(r)&&e.push(...S(r.getLiteralText()));return e}function b(t){for(let e of t.getArguments())if(p(e)){let r=m(e.getLiteralText());e.setLiteralValue(r);}C(t);}function _(t,e,r,s){let n=t.getArguments()[0];if(p(n)){let o=n.getLiteralText(),a=m(d(e,o));n.setLiteralValue(a),s.forEach(f=>r.add(f));for(let f=1;f<t.getArguments().length;f++){let u=t.getArguments()[f];if(p(u)){let x=u.getLiteralText(),y=m(x);y!==x&&u.setLiteralValue(y);}}C(t);return}let i=t.getArguments().map(o=>{if(p(o)){let a=m(o.getLiteralText());return a?JSON.stringify(a):null}return o.getText()}).filter(o=>o!==null),g=[JSON.stringify(e),...i];s.forEach(o=>r.add(o)),t.getParent()&&t.replaceWithText(`cn(${g.join(", ")})`);}async function Y(t,{styleMap:e,transformers:r=[P]}){let n=new Project({useInMemoryFileSystem:true}).createSourceFile("component.tsx",t,{scriptKind:ScriptKind.TSX,overwrite:true});for(let i of r)await i({sourceFile:n,styleMap:e});return n.getText()}var O="lucide",X=async({sourceFile:t,config:e})=>{if(!e.iconLibrary||!(e.iconLibrary in a))return t;let r=O,s=e.iconLibrary;if(r===s)return t;let n=await Z(),i=[];for(let g of t.getImportDeclarations()??[])if(g.getModuleSpecifier()?.getText()===`"${a[O].import}"`){for(let l of g.getNamedImports()??[]){let o=l.getName(),a=n[o]?.[s];!a||i.includes(a)||(i.push(a),l.remove(),t.getDescendantsOfKind(SyntaxKind.JsxSelfClosingElement).filter(f=>f.getTagNameNode()?.getText()===o).forEach(f=>f.getTagNameNode()?.replaceWithText(a)));}g.getNamedImports()?.length===0&&g.remove();}if(i.length>0){let g=t.addImportDeclaration({moduleSpecifier:a[s]?.import,namedImports:i.map(l=>({name:l}))});U(t)||g.replaceWithText(g.getText().replace(";",""));}return t};function U(t){return t.getImportDeclarations()?.[0]?.getText().endsWith(";")??false}export{V as createStyleMap,X as transformIcons,Y as transformStyle};//# sourceMappingURL=index.js.map
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
package/dist/chunk-M5DYT2NE.js
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import {a}from'./chunk-RMTTHCB3.js';import {V,G,f as f$1,F}from'./chunk-NQFMXHMH.js';import {Server}from'@modelcontextprotocol/sdk/server/index.js';import {ListToolsRequestSchema,CallToolRequestSchema}from'@modelcontextprotocol/sdk/types.js';import o from'dedent';import {z}from'zod';import {zodToJsonSchema}from'zod-to-json-schema';import {detect}from'@antfu/ni';async function v(r,{withFallback:e}={withFallback:false}){let n=await detect({programmatic:true,cwd:r});if(n==="yarn@berry")return "yarn";if(n==="pnpm@6")return "pnpm";if(n==="bun")return "bun";if(n==="deno")return "deno";if(!e)return n??"npm";let i=process.env.npm_config_user_agent||"";return i.startsWith("yarn")?"yarn":i.startsWith("pnpm")?"pnpm":i.startsWith("bun")?"bun":"npm"}async function $(r){let e=await v(r);return e==="pnpm"?"pnpm dlx":e==="bun"?"bunx":"npx"}var q="@create-ui/cli";async function u(r){return `${await $(process.cwd())} ${q} ${r}`}function y(r){return r.startsWith("@")&&r.includes("/")?r.slice(r.indexOf("/")+1):r}async function f(r=process.cwd()){try{let e=await f$1(r);if(e)return e}catch{}return F({})}async function x(r,e){let{query:n,registries:i}=e||{},s=await Promise.all(r.items.map(async c=>{let g=[`- ${c.name}`];return c.type&&g.push(`(${c.type})`),c.description&&g.push(`- ${c.description}`),c.registry&&g.push(`[${c.registry}]`),g.push(`
|
|
2
|
-
Add command: \`${await u(`add ${c.addCommandArgument}`)}\``),g.join(" ")})),a=`Found ${r.pagination.total} items`;n&&(a+=` matching "${n}"`),i&&i.length>0&&(a+=` in registries ${i.join(", ")}`),a+=":";let m=`Showing items ${r.pagination.offset+1}-${Math.min(r.pagination.offset+r.pagination.limit,r.pagination.total)} of ${r.pagination.total}:`,d=`${a}
|
|
3
|
-
|
|
4
|
-
${m}
|
|
5
|
-
|
|
6
|
-
${s.join(`
|
|
7
|
-
|
|
8
|
-
`)}`;return r.pagination.hasMore&&(d+=`
|
|
9
|
-
|
|
10
|
-
More items available. Use offset: ${r.pagination.offset+r.pagination.limit} to see the next page.`),d}function j(r){return r.map(e=>[`## ${e.name}`,e.description?`
|
|
11
|
-
${e.description}
|
|
12
|
-
`:"",e.type?`**Type:** ${e.type}`:"",e.files&&e.files.length>0?`**Files:** ${e.files.length} file(s)`:"",e.dependencies&&e.dependencies.length>0?`**Dependencies:** ${e.dependencies.join(", ")}`:"",e.devDependencies&&e.devDependencies.length>0?`**Dev Dependencies:** ${e.devDependencies.join(", ")}`:""].filter(Boolean).join(`
|
|
13
|
-
`))}function S(r,e){let n=r.map(s=>{let a=[`## Example: ${s.name}`,s.description?`
|
|
14
|
-
${s.description}
|
|
15
|
-
`:""];return s.files?.length&&s.files.forEach(m=>{m.content&&(a.push(`### Code (${m.path}):
|
|
16
|
-
`),a.push("```tsx"),a.push(m.content),a.push("```"));}),a.filter(Boolean).join(`
|
|
17
|
-
`)});return `# Usage Examples
|
|
18
|
-
|
|
19
|
-
Found ${r.length} example${r.length>1?"s":""} matching "${e}":
|
|
20
|
-
`+n.join(`
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
`)}var k=new Server({name:"createui",version:"1.0.0"},{capabilities:{resources:{},tools:{}}});k.setRequestHandler(ListToolsRequestSchema,async()=>({tools:[{name:"get_project_registries",description:"Get the registry used by this project. createui uses a single built-in @createui registry.",inputSchema:zodToJsonSchema(z.object({}))},{name:"list_items_in_registries",description:"List items from registries (requires components.json - use init_project if missing)",inputSchema:zodToJsonSchema(z.object({registries:z.array(z.string()).describe("Array of registry names to search (e.g., ['@createui', '@acme'])"),limit:z.number().optional().describe("Maximum number of items to return"),offset:z.number().optional().describe("Number of items to skip for pagination")}))},{name:"search_items_in_registries",description:"Search for components in registries using fuzzy matching (requires components.json). After finding an item, use get_item_examples_from_registries to see usage examples.",inputSchema:zodToJsonSchema(z.object({registries:z.array(z.string()).describe("Array of registry names to search (e.g., ['@createui', '@acme'])"),query:z.string().describe("Search query string for fuzzy matching against item names and descriptions"),limit:z.number().optional().describe("Maximum number of items to return"),offset:z.number().optional().describe("Number of items to skip for pagination")}))},{name:"view_items_in_registries",description:"View detailed information about specific registry items including the name, description, type and files content. For usage examples, use get_item_examples_from_registries instead.",inputSchema:zodToJsonSchema(z.object({items:z.array(z.string()).describe("Array of item names (e.g., ['button', 'card']). A '@createui/' prefix is also accepted.")}))},{name:"get_item_examples_from_registries",description:"Find usage examples and demos with their complete code. Search for patterns like 'accordion-demo', 'button example', 'card-demo', etc. Returns full implementation code with dependencies.",inputSchema:zodToJsonSchema(z.object({registries:z.array(z.string()).describe("Array of registry names to search (e.g., ['@createui', '@acme'])"),query:z.string().describe("Search query for examples (e.g., 'accordion-demo', 'button demo', 'card example', 'tooltip-demo', 'example-booking-form', 'example-hero'). Common patterns: '{item-name}-demo', '{item-name} example', 'example {item-name}'")}))},{name:"get_add_command_for_items",description:"Get the createui CLI add command for specific items in a registry. This is useful for adding one or more components to your project.",inputSchema:zodToJsonSchema(z.object({items:z.array(z.string()).describe("Array of items to get the add command for (e.g., ['button', 'card']). A '@createui/' prefix is also accepted.")}))},{name:"get_audit_checklist",description:"After creating new components or generating new code files, use this tool for a quick checklist to verify that everything is working as expected. Make sure to run the tool after all required steps have been completed.",inputSchema:zodToJsonSchema(z.object({}))}]}));k.setRequestHandler(CallToolRequestSchema,async r=>{try{if(!r.params.arguments)throw new Error("No tool arguments provided.");switch(r.params.name){case "get_project_registries":return {content:[{type:"text",text:o`This project uses the built-in \`@createui\` registry.
|
|
25
|
-
|
|
26
|
-
You can view an item by running:
|
|
27
|
-
\`${await u("view <item-name>")}\`
|
|
28
|
-
|
|
29
|
-
For example: \`${await u("view button")}\`.`}]};case "search_items_in_registries":{let n=z.object({registries:z.array(z.string()),query:z.string(),limit:z.number().optional(),offset:z.number().optional()}).parse(r.params.arguments),i=await a(n.registries,{query:n.query,limit:n.limit,offset:n.offset,config:await f(process.cwd()),useCache:!1});return i.items.length===0?{content:[{type:"text",text:o`No items found matching "${n.query}" in registries ${n.registries.join(", ")}, Try searching with a different query or registry.`}]}:{content:[{type:"text",text:await x(i,{query:n.query,registries:n.registries})}]}}case "list_items_in_registries":{let n=z.object({registries:z.array(z.string()),limit:z.number().optional(),offset:z.number().optional(),cwd:z.string().optional()}).parse(r.params.arguments),i=await a(n.registries,{limit:n.limit,offset:n.offset,config:await f(process.cwd()),useCache:!1});return i.items.length===0?{content:[{type:"text",text:o`No items found in registries ${n.registries.join(", ")}.`}]}:{content:[{type:"text",text:await x(i,{registries:n.registries})}]}}case "view_items_in_registries":{let n=z.object({items:z.array(z.string())}).parse(r.params.arguments),i=await V(n.items.map(y),{config:await f(process.cwd()),useCache:!1});if(i?.length===0)return {content:[{type:"text",text:o`No items found for: ${n.items.join(", ")}
|
|
30
|
-
|
|
31
|
-
Make sure the item names are correct (e.g., button, card).`}]};let s=j(i);return {content:[{type:"text",text:o`Item Details:
|
|
32
|
-
|
|
33
|
-
${s.join(`
|
|
34
|
-
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
`)}`}]}}case "get_item_examples_from_registries":{let n=z.object({query:z.string(),registries:z.array(z.string())}).parse(r.params.arguments),i=await f(),s=await a(n.registries,{query:n.query,config:i,useCache:!1});if(s.items.length===0)return {content:[{type:"text",text:o`No examples found for query "${n.query}".
|
|
38
|
-
|
|
39
|
-
Try searching with patterns like:
|
|
40
|
-
- "accordion-demo" for accordion examples
|
|
41
|
-
- "button demo" or "button example"
|
|
42
|
-
- Component name followed by "-demo" or "example"
|
|
43
|
-
|
|
44
|
-
You can also:
|
|
45
|
-
1. Use search_items_in_registries to find all items matching your query
|
|
46
|
-
2. View the main component with view_items_in_registries for inline usage documentation`}]};let a$1=s.items.map(d=>d.addCommandArgument),m=await V(a$1,{config:i,useCache:!1});return {content:[{type:"text",text:S(m,n.query)}]}}case "get_add_command_for_items":{let e=z.object({items:z.array(z.string())}).parse(r.params.arguments);return {content:[{type:"text",text:await u(`add ${e.items.map(y).join(" ")}`)}]}}case "get_audit_checklist":return {content:[{type:"text",text:o`## Component Audit Checklist
|
|
47
|
-
|
|
48
|
-
After adding or generating components, check the following common issues:
|
|
49
|
-
|
|
50
|
-
- [ ] Ensure imports are correct i.e named vs default imports
|
|
51
|
-
- [ ] If using next/image, ensure images.remotePatterns next.config.js is configured correctly.
|
|
52
|
-
- [ ] Ensure all dependencies are installed.
|
|
53
|
-
- [ ] Check for linting errors or warnings
|
|
54
|
-
- [ ] Check for TypeScript errors
|
|
55
|
-
- [ ] Use the Playwright MCP if available.
|
|
56
|
-
`}]};default:throw new Error(`Tool ${r.params.name} not found`)}}catch(e){if(e instanceof z.ZodError)return {content:[{type:"text",text:o`Invalid input parameters:
|
|
57
|
-
${e.errors.map(i=>`- ${i.path.join(".")}: ${i.message}`).join(`
|
|
58
|
-
`)}
|
|
59
|
-
`}],isError:true};if(e instanceof G){let i=e.message;return e.suggestion&&(i+=`
|
|
60
|
-
|
|
61
|
-
\u{1F4A1} ${e.suggestion}`),e.context&&(i+=`
|
|
62
|
-
|
|
63
|
-
Context: ${JSON.stringify(e.context,null,2)}`),{content:[{type:"text",text:o`Error (${e.code}): ${i}`}],isError:true}}let n=e instanceof Error?e.message:String(e);return {content:[{type:"text",text:o`Error: ${n}`}],isError:true}}});export{v as a,k as b};//# sourceMappingURL=chunk-M5DYT2NE.js.map
|
|
64
|
-
//# sourceMappingURL=chunk-M5DYT2NE.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/get-package-manager.ts","../src/mcp/utils.ts","../src/mcp/index.ts"],"names":["getPackageManager","targetDir","withFallback","packageManager","detect","userAgent","getPackageRunner","cwd","createui_CLI_COMMAND","npxcreateui","command","normalizeRegistryItemName","item","getMcpConfig","config","getConfig","configWithDefaults","formatSearchResultsWithPagination","results","options","query","registries","formattedItems","parts","header","showingRange","output","formatRegistryItems","items","formatItemExamples","sections","file","server","Server","ListToolsRequestSchema","zodToJsonSchema","z","CallToolRequestSchema","request","dedent","args","searchRegistries","registryItems","getRegistryItems","itemNames","fullItems","error","e","RegistryError","errorMessage"],"mappings":"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","file":"chunk-M5DYT2NE.js","sourcesContent":["import { detect } from \"@antfu/ni\"\n\nexport async function getPackageManager(\n targetDir: string,\n { withFallback }: { withFallback?: boolean } = {\n withFallback: false,\n }\n): Promise<\"yarn\" | \"pnpm\" | \"bun\" | \"npm\" | \"deno\"> {\n const packageManager = await detect({ programmatic: true, cwd: targetDir })\n\n if (packageManager === \"yarn@berry\") return \"yarn\"\n if (packageManager === \"pnpm@6\") return \"pnpm\"\n if (packageManager === \"bun\") return \"bun\"\n if (packageManager === \"deno\") return \"deno\"\n if (!withFallback) {\n return packageManager ?? \"npm\"\n }\n\n // Fallback to user agent if not detected.\n const userAgent = process.env.npm_config_user_agent || \"\"\n\n if (userAgent.startsWith(\"yarn\")) {\n return \"yarn\"\n }\n\n if (userAgent.startsWith(\"pnpm\")) {\n return \"pnpm\"\n }\n\n if (userAgent.startsWith(\"bun\")) {\n return \"bun\"\n }\n\n return \"npm\"\n}\n\nexport async function getPackageRunner(cwd: string) {\n const packageManager = await getPackageManager(cwd)\n\n if (packageManager === \"pnpm\") return \"pnpm dlx\"\n\n if (packageManager === \"bun\") return \"bunx\"\n\n return \"npx\"\n}\n","import { configWithDefaults } from \"@/src/registry/config\"\nimport { registryItemSchema, searchResultsSchema } from \"@/src/schema\"\nimport { getConfig } from \"@/src/utils/get-config\"\nimport { getPackageRunner } from \"@/src/utils/get-package-manager\"\nimport { z } from \"zod\"\n\nconst createui_CLI_COMMAND = \"@create-ui/cli\"\n\nexport async function npxcreateui(command: string) {\n const packageRunner = await getPackageRunner(process.cwd())\n return `${packageRunner} ${createui_CLI_COMMAND} ${command}`\n}\n\n// Single-provider: items resolve by bare name (e.g. \"button\"). The MCP tools\n// historically accepted a \"@registry/item\" convention, so strip an optional\n// leading \"@registry/\" prefix. URLs and local file paths are returned untouched.\nexport function normalizeRegistryItemName(item: string) {\n if (item.startsWith(\"@\") && item.includes(\"/\")) {\n return item.slice(item.indexOf(\"/\") + 1)\n }\n\n return item\n}\n\nexport async function getMcpConfig(cwd = process.cwd()) {\n try {\n const config = await getConfig(cwd)\n if (config) {\n return config\n }\n } catch {\n // Fall back to defaults when components.json is missing or invalid.\n }\n\n return configWithDefaults({})\n}\n\nexport async function formatSearchResultsWithPagination(\n results: z.infer<typeof searchResultsSchema>,\n options?: {\n query?: string\n registries?: string[]\n }\n) {\n const { query, registries } = options || {}\n\n const formattedItems = await Promise.all(\n results.items.map(async (item) => {\n const parts: string[] = [`- ${item.name}`]\n\n if (item.type) {\n parts.push(`(${item.type})`)\n }\n\n if (item.description) {\n parts.push(`- ${item.description}`)\n }\n\n if (item.registry) {\n parts.push(`[${item.registry}]`)\n }\n\n parts.push(\n `\\n Add command: \\`${await npxcreateui(\n `add ${item.addCommandArgument}`\n )}\\``\n )\n\n return parts.join(\" \")\n })\n )\n\n let header = `Found ${results.pagination.total} items`\n if (query) {\n header += ` matching \"${query}\"`\n }\n if (registries && registries.length > 0) {\n header += ` in registries ${registries.join(\", \")}`\n }\n header += \":\"\n\n const showingRange = `Showing items ${\n results.pagination.offset + 1\n }-${Math.min(\n results.pagination.offset + results.pagination.limit,\n results.pagination.total\n )} of ${results.pagination.total}:`\n\n let output = `${header}\\n\\n${showingRange}\\n\\n${formattedItems.join(\"\\n\\n\")}`\n\n if (results.pagination.hasMore) {\n output += `\\n\\nMore items available. Use offset: ${\n results.pagination.offset + results.pagination.limit\n } to see the next page.`\n }\n\n return output\n}\n\nexport function formatRegistryItems(\n items: z.infer<typeof registryItemSchema>[]\n) {\n return items.map((item) => {\n const parts: string[] = [\n `## ${item.name}`,\n item.description ? `\\n${item.description}\\n` : \"\",\n item.type ? `**Type:** ${item.type}` : \"\",\n item.files && item.files.length > 0\n ? `**Files:** ${item.files.length} file(s)`\n : \"\",\n item.dependencies && item.dependencies.length > 0\n ? `**Dependencies:** ${item.dependencies.join(\", \")}`\n : \"\",\n item.devDependencies && item.devDependencies.length > 0\n ? `**Dev Dependencies:** ${item.devDependencies.join(\", \")}`\n : \"\",\n ]\n return parts.filter(Boolean).join(\"\\n\")\n })\n}\n\nexport function formatItemExamples(\n items: z.infer<typeof registryItemSchema>[],\n query: string\n) {\n const sections = items.map((item) => {\n const parts: string[] = [\n `## Example: ${item.name}`,\n item.description ? `\\n${item.description}\\n` : \"\",\n ]\n\n if (item.files?.length) {\n item.files.forEach((file) => {\n if (file.content) {\n parts.push(`### Code (${file.path}):\\n`)\n parts.push(\"```tsx\")\n parts.push(file.content)\n parts.push(\"```\")\n }\n })\n }\n\n return parts.filter(Boolean).join(\"\\n\")\n })\n\n const header = `# Usage Examples\\n\\nFound ${items.length} example${\n items.length > 1 ? \"s\" : \"\"\n } matching \"${query}\":\\n`\n\n return header + sections.join(\"\\n\\n---\\n\\n\")\n}\n","import { getRegistryItems, searchRegistries } from \"@/src/registry\"\nimport { RegistryError } from \"@/src/registry/errors\"\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\"\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\"\nimport dedent from \"dedent\"\nimport { z } from \"zod\"\nimport { zodToJsonSchema } from \"zod-to-json-schema\"\n\nimport {\n formatItemExamples,\n formatRegistryItems,\n formatSearchResultsWithPagination,\n getMcpConfig,\n normalizeRegistryItemName,\n npxcreateui,\n} from \"./utils\"\n\nexport const server = new Server(\n {\n name: \"createui\",\n version: \"1.0.0\",\n },\n {\n capabilities: {\n resources: {},\n tools: {},\n },\n }\n)\n\nserver.setRequestHandler(ListToolsRequestSchema, async () => {\n return {\n tools: [\n {\n name: \"get_project_registries\",\n description:\n \"Get the registry used by this project. createui uses a single built-in @createui registry.\",\n inputSchema: zodToJsonSchema(z.object({})),\n },\n {\n name: \"list_items_in_registries\",\n description:\n \"List items from registries (requires components.json - use init_project if missing)\",\n inputSchema: zodToJsonSchema(\n z.object({\n registries: z\n .array(z.string())\n .describe(\n \"Array of registry names to search (e.g., ['@createui', '@acme'])\"\n ),\n limit: z\n .number()\n .optional()\n .describe(\"Maximum number of items to return\"),\n offset: z\n .number()\n .optional()\n .describe(\"Number of items to skip for pagination\"),\n })\n ),\n },\n {\n name: \"search_items_in_registries\",\n description:\n \"Search for components in registries using fuzzy matching (requires components.json). After finding an item, use get_item_examples_from_registries to see usage examples.\",\n inputSchema: zodToJsonSchema(\n z.object({\n registries: z\n .array(z.string())\n .describe(\n \"Array of registry names to search (e.g., ['@createui', '@acme'])\"\n ),\n query: z\n .string()\n .describe(\n \"Search query string for fuzzy matching against item names and descriptions\"\n ),\n limit: z\n .number()\n .optional()\n .describe(\"Maximum number of items to return\"),\n offset: z\n .number()\n .optional()\n .describe(\"Number of items to skip for pagination\"),\n })\n ),\n },\n {\n name: \"view_items_in_registries\",\n description:\n \"View detailed information about specific registry items including the name, description, type and files content. For usage examples, use get_item_examples_from_registries instead.\",\n inputSchema: zodToJsonSchema(\n z.object({\n items: z\n .array(z.string())\n .describe(\n \"Array of item names (e.g., ['button', 'card']). A '@createui/' prefix is also accepted.\"\n ),\n })\n ),\n },\n {\n name: \"get_item_examples_from_registries\",\n description:\n \"Find usage examples and demos with their complete code. Search for patterns like 'accordion-demo', 'button example', 'card-demo', etc. Returns full implementation code with dependencies.\",\n inputSchema: zodToJsonSchema(\n z.object({\n registries: z\n .array(z.string())\n .describe(\n \"Array of registry names to search (e.g., ['@createui', '@acme'])\"\n ),\n query: z\n .string()\n .describe(\n \"Search query for examples (e.g., 'accordion-demo', 'button demo', 'card example', 'tooltip-demo', 'example-booking-form', 'example-hero'). Common patterns: '{item-name}-demo', '{item-name} example', 'example {item-name}'\"\n ),\n })\n ),\n },\n {\n name: \"get_add_command_for_items\",\n description:\n \"Get the createui CLI add command for specific items in a registry. This is useful for adding one or more components to your project.\",\n inputSchema: zodToJsonSchema(\n z.object({\n items: z\n .array(z.string())\n .describe(\n \"Array of items to get the add command for (e.g., ['button', 'card']). A '@createui/' prefix is also accepted.\"\n ),\n })\n ),\n },\n {\n name: \"get_audit_checklist\",\n description:\n \"After creating new components or generating new code files, use this tool for a quick checklist to verify that everything is working as expected. Make sure to run the tool after all required steps have been completed.\",\n inputSchema: zodToJsonSchema(z.object({})),\n },\n ],\n }\n})\n\nserver.setRequestHandler(CallToolRequestSchema, async (request) => {\n try {\n if (!request.params.arguments) {\n throw new Error(\"No tool arguments provided.\")\n }\n\n switch (request.params.name) {\n case \"get_project_registries\": {\n return {\n content: [\n {\n type: \"text\",\n text: dedent`This project uses the built-in \\`@createui\\` registry.\n\n You can view an item by running:\n \\`${await npxcreateui(\"view <item-name>\")}\\`\n\n For example: \\`${await npxcreateui(\"view button\")}\\`.`,\n },\n ],\n }\n }\n\n case \"search_items_in_registries\": {\n const inputSchema = z.object({\n registries: z.array(z.string()),\n query: z.string(),\n limit: z.number().optional(),\n offset: z.number().optional(),\n })\n\n const args = inputSchema.parse(request.params.arguments)\n const results = await searchRegistries(args.registries, {\n query: args.query,\n limit: args.limit,\n offset: args.offset,\n config: await getMcpConfig(process.cwd()),\n useCache: false,\n })\n\n if (results.items.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: dedent`No items found matching \"${\n args.query\n }\" in registries ${args.registries.join(\n \", \"\n )}, Try searching with a different query or registry.`,\n },\n ],\n }\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: await formatSearchResultsWithPagination(results, {\n query: args.query,\n registries: args.registries,\n }),\n },\n ],\n }\n }\n\n case \"list_items_in_registries\": {\n const inputSchema = z.object({\n registries: z.array(z.string()),\n limit: z.number().optional(),\n offset: z.number().optional(),\n cwd: z.string().optional(),\n })\n\n const args = inputSchema.parse(request.params.arguments)\n const results = await searchRegistries(args.registries, {\n limit: args.limit,\n offset: args.offset,\n config: await getMcpConfig(process.cwd()),\n useCache: false,\n })\n\n if (results.items.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: dedent`No items found in registries ${args.registries.join(\n \", \"\n )}.`,\n },\n ],\n }\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: await formatSearchResultsWithPagination(results, {\n registries: args.registries,\n }),\n },\n ],\n }\n }\n\n case \"view_items_in_registries\": {\n const inputSchema = z.object({\n items: z.array(z.string()),\n })\n\n const args = inputSchema.parse(request.params.arguments)\n const registryItems = await getRegistryItems(\n args.items.map(normalizeRegistryItemName),\n {\n config: await getMcpConfig(process.cwd()),\n useCache: false,\n }\n )\n\n if (registryItems?.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: dedent`No items found for: ${args.items.join(\", \")}\n\n Make sure the item names are correct (e.g., button, card).`,\n },\n ],\n }\n }\n\n const formattedItems = formatRegistryItems(registryItems)\n\n return {\n content: [\n {\n type: \"text\",\n text: dedent`Item Details:\n\n ${formattedItems.join(\"\\n\\n---\\n\\n\")}`,\n },\n ],\n }\n }\n\n case \"get_item_examples_from_registries\": {\n const inputSchema = z.object({\n query: z.string(),\n registries: z.array(z.string()),\n })\n\n const args = inputSchema.parse(request.params.arguments)\n const config = await getMcpConfig()\n\n const results = await searchRegistries(args.registries, {\n query: args.query,\n config,\n useCache: false,\n })\n\n if (results.items.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: dedent`No examples found for query \"${args.query}\".\n\n Try searching with patterns like:\n - \"accordion-demo\" for accordion examples\n - \"button demo\" or \"button example\"\n - Component name followed by \"-demo\" or \"example\"\n\n You can also:\n 1. Use search_items_in_registries to find all items matching your query\n 2. View the main component with view_items_in_registries for inline usage documentation`,\n },\n ],\n }\n }\n\n const itemNames = results.items.map((item) => item.addCommandArgument)\n const fullItems = await getRegistryItems(itemNames, {\n config,\n useCache: false,\n })\n\n return {\n content: [\n {\n type: \"text\",\n text: formatItemExamples(fullItems, args.query),\n },\n ],\n }\n }\n\n case \"get_add_command_for_items\": {\n const args = z\n .object({\n items: z.array(z.string()),\n })\n .parse(request.params.arguments)\n\n return {\n content: [\n {\n type: \"text\",\n text: await npxcreateui(\n `add ${args.items.map(normalizeRegistryItemName).join(\" \")}`\n ),\n },\n ],\n }\n }\n\n case \"get_audit_checklist\": {\n return {\n content: [\n {\n type: \"text\",\n text: dedent`## Component Audit Checklist\n\n After adding or generating components, check the following common issues:\n\n - [ ] Ensure imports are correct i.e named vs default imports\n - [ ] If using next/image, ensure images.remotePatterns next.config.js is configured correctly.\n - [ ] Ensure all dependencies are installed.\n - [ ] Check for linting errors or warnings\n - [ ] Check for TypeScript errors\n - [ ] Use the Playwright MCP if available.\n `,\n },\n ],\n }\n }\n\n default:\n throw new Error(`Tool ${request.params.name} not found`)\n }\n } catch (error) {\n if (error instanceof z.ZodError) {\n return {\n content: [\n {\n type: \"text\",\n text: dedent`Invalid input parameters:\n ${error.errors\n .map((e) => `- ${e.path.join(\".\")}: ${e.message}`)\n .join(\"\\n\")}\n `,\n },\n ],\n isError: true,\n }\n }\n\n if (error instanceof RegistryError) {\n let errorMessage = error.message\n\n if (error.suggestion) {\n errorMessage += `\\n\\n💡 ${error.suggestion}`\n }\n\n if (error.context) {\n errorMessage += `\\n\\nContext: ${JSON.stringify(error.context, null, 2)}`\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: dedent`Error (${error.code}): ${errorMessage}`,\n },\n ],\n isError: true,\n }\n }\n\n const errorMessage = error instanceof Error ? error.message : String(error)\n return {\n content: [\n {\n type: \"text\",\n text: dedent`Error: ${errorMessage}`,\n },\n ],\n isError: true,\n }\n }\n})\n"]}
|