@create-ui/cli 0.6.0 → 0.6.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/chunk-KFQXWKJJ.js +19 -0
- package/dist/chunk-KFQXWKJJ.js.map +1 -0
- package/dist/{chunk-2ELKDGGM.js → chunk-OGAWGP7T.js} +3 -3
- package/dist/{chunk-2ELKDGGM.js.map → chunk-OGAWGP7T.js.map} +1 -1
- package/dist/chunk-OITQ46YK.js +99 -0
- package/dist/chunk-OITQ46YK.js.map +1 -0
- package/dist/index.js +16 -16
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.js +1 -1
- package/dist/registry/index.d.ts +3 -1
- package/dist/registry/index.js +1 -1
- package/dist/skills/createui/SKILL.md +81 -52
- package/dist/skills/createui/cli.md +1 -1
- package/dist/skills/createui/customization.md +14 -12
- package/dist/skills/createui/evals/evals.json +77 -0
- package/dist/skills/createui/mcp.md +12 -26
- package/dist/skills/createui/rules/a11y.md +148 -0
- package/dist/skills/createui/rules/composition.md +64 -26
- package/dist/skills/createui/rules/forms.md +2 -2
- package/dist/skills/createui/rules/icons.md +1 -1
- package/dist/skills/createui/rules/styling.md +2 -2
- package/dist/utils/index.js +1 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-643QI2I2.js +0 -102
- package/dist/chunk-643QI2I2.js.map +0 -1
- package/dist/chunk-KQTXDVKV.js +0 -19
- package/dist/chunk-KQTXDVKV.js.map +0 -1
- package/dist/skills/createui/reference/accordion.md +0 -127
- package/dist/skills/createui/reference/app-store-badge.md +0 -88
- package/dist/skills/createui/reference/aspect-ratio.md +0 -52
- package/dist/skills/createui/reference/avatar.md +0 -230
- package/dist/skills/createui/reference/badge.md +0 -110
- package/dist/skills/createui/reference/breadcrumb.md +0 -153
- package/dist/skills/createui/reference/button-group.md +0 -116
- package/dist/skills/createui/reference/button.md +0 -104
- package/dist/skills/createui/reference/checkbox-group.md +0 -118
- package/dist/skills/createui/reference/checkbox.md +0 -79
- package/dist/skills/createui/reference/chip.md +0 -115
- package/dist/skills/createui/reference/close-button.md +0 -83
- package/dist/skills/createui/reference/country-flag.md +0 -109
- package/dist/skills/createui/reference/credit-card-input.md +0 -76
- package/dist/skills/createui/reference/date-input.md +0 -71
- package/dist/skills/createui/reference/dropdown-menu.md +0 -164
- package/dist/skills/createui/reference/field.md +0 -186
- package/dist/skills/createui/reference/info-tooltip.md +0 -110
- package/dist/skills/createui/reference/inline-alert.md +0 -146
- package/dist/skills/createui/reference/input-group.md +0 -171
- package/dist/skills/createui/reference/input-otp.md +0 -130
- package/dist/skills/createui/reference/input-stepper.md +0 -120
- package/dist/skills/createui/reference/input.md +0 -118
- package/dist/skills/createui/reference/label.md +0 -121
- package/dist/skills/createui/reference/pagination.md +0 -157
- package/dist/skills/createui/reference/phone-input.md +0 -77
- package/dist/skills/createui/reference/progress.md +0 -158
- package/dist/skills/createui/reference/radio-group.md +0 -133
- package/dist/skills/createui/reference/radio.md +0 -79
- package/dist/skills/createui/reference/scroll-area.md +0 -212
- package/dist/skills/createui/reference/segmented-control.md +0 -146
- package/dist/skills/createui/reference/select.md +0 -204
- package/dist/skills/createui/reference/separator.md +0 -99
- package/dist/skills/createui/reference/social-login-button.md +0 -130
- package/dist/skills/createui/reference/spinner.md +0 -68
- package/dist/skills/createui/reference/status-badge.md +0 -89
- package/dist/skills/createui/reference/switch-group.md +0 -122
- package/dist/skills/createui/reference/switch.md +0 -75
- package/dist/skills/createui/reference/tab-menu.md +0 -165
- package/dist/skills/createui/reference/text-link.md +0 -84
- package/dist/skills/createui/reference/textarea.md +0 -50
- package/dist/skills/createui/reference/toast.md +0 -162
- package/dist/skills/createui/reference/tooltip.md +0 -63
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Accessibility
|
|
2
|
+
|
|
3
|
+
Create UI primitives are built on Radix, so the hard parts - focus traps, roles, keyboard handling - are already correct. Your job is to not undo them and to supply the human-authored pieces (names, labels, state) the component can't infer. The rules below are the ones that actually get missed.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
- Every icon-only control needs an accessible name
|
|
8
|
+
- Label every control
|
|
9
|
+
- Wire validation and state to the control, not just the Field
|
|
10
|
+
- Don't encode meaning in color alone
|
|
11
|
+
- Let overlays own their focus, roles, and stacking
|
|
12
|
+
- Decorative vs meaningful icons
|
|
13
|
+
- Focus must stay visible
|
|
14
|
+
- Respect reduced motion for custom animation
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Every icon-only control needs an accessible name
|
|
19
|
+
|
|
20
|
+
Any control whose only content is an icon (`Button iconOnly`, `CloseButton`, an icon-only `InputGroupButton`, `SegmentedControlItem iconOnly`) renders no text, so a screen reader has nothing to announce. Always pass `aria-label`.
|
|
21
|
+
|
|
22
|
+
**Incorrect:**
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
<Button iconOnly><RiMore2Line /></Button>
|
|
26
|
+
<InputGroupButton iconOnly><RiSearchLine /></InputGroupButton>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Correct:**
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
<Button iconOnly aria-label="More options"><RiMore2Line /></Button>
|
|
33
|
+
<InputGroupButton iconOnly aria-label="Search"><RiSearchLine /></InputGroupButton>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Label every control
|
|
39
|
+
|
|
40
|
+
- **Labelable controls** (`Input`, `Textarea`, `Select`, `Checkbox`, `Radio`, `Switch`): use `FieldLabel htmlFor="<id>"` matched to the control's `id`, so clicking the label focuses the control. For a visually hidden but announced label use `FieldLabel className="sr-only"`.
|
|
41
|
+
- **Non-labelable controls** (`SegmentedControl`, `RadioGroup`, a custom group): a `<label>` can't point at them. Use `FieldTitle id="…"` and connect with `aria-labelledby`.
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
<Field orientation="horizontal">
|
|
45
|
+
<FieldTitle id="theme-label">Theme</FieldTitle>
|
|
46
|
+
<SegmentedControl defaultValue="system" aria-labelledby="theme-label">
|
|
47
|
+
<SegmentedControlItem value="light">Light</SegmentedControlItem>
|
|
48
|
+
<SegmentedControlItem value="dark">Dark</SegmentedControlItem>
|
|
49
|
+
</SegmentedControl>
|
|
50
|
+
</Field>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Group related fields under `FieldSet` + `FieldLegend` rather than a `<div>` with a heading - the legend names the group for assistive tech. (See [forms.md](./forms.md).)
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Wire validation and state to the control, not just the Field
|
|
58
|
+
|
|
59
|
+
`Field` carries `invalid` / `disabled` / `loading` (and the matching `data-*` attributes) for *styling*, but the control itself still needs the real ARIA/DOM state so assistive tech and the control's own visuals reflect it. Set both, and render the message with `FieldError` (Field wires it up as the control's description).
|
|
60
|
+
|
|
61
|
+
**Incorrect** - only the Field knows:
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
<Field invalid>
|
|
65
|
+
<FieldLabel htmlFor="email">Email</FieldLabel>
|
|
66
|
+
<Input id="email" type="email" />
|
|
67
|
+
</Field>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Correct:**
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
<Field invalid>
|
|
74
|
+
<FieldLabel htmlFor="email">Email</FieldLabel>
|
|
75
|
+
<Input id="email" type="email" aria-invalid />
|
|
76
|
+
<FieldError>Enter a valid email address.</FieldError>
|
|
77
|
+
</Field>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Same for `disabled` (set `disabled` on the control) and `loading`.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Don't encode meaning in color alone
|
|
85
|
+
|
|
86
|
+
A color difference is invisible to many users. Status must also carry text or a shape. `StatusBadge` renders the dot only - always put a text label next to it; never communicate success/error with color on its own.
|
|
87
|
+
|
|
88
|
+
**Incorrect:**
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
<span className="bg-success-base size-2 rounded-full" />
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Correct:**
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
<span className="flex items-center gap-2">
|
|
98
|
+
<StatusBadge variant="success" />
|
|
99
|
+
<span className="text-body-sm text-body">Active</span>
|
|
100
|
+
</span>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Let overlays own their focus, roles, and stacking
|
|
106
|
+
|
|
107
|
+
`DropdownMenu`, `Tooltip`, `InfoTooltip`, and `CommandDialog` (and Pro `Modal` / `Popover`) ship the correct `role`, `aria-modal`, focus trap, return-focus, `Esc`-to-close, and arrow-key handling. Don't re-implement any of it.
|
|
108
|
+
|
|
109
|
+
- Never add `role="dialog"`, `aria-modal`, `tabIndex`, or manual focus calls onto these - you'll fight the built-in behavior.
|
|
110
|
+
- Never add `z-50` / `z-[999]` - they manage their own stacking (see [styling.md](./styling.md)).
|
|
111
|
+
- For a custom trigger, use `asChild` so the trigger's a11y wiring lands on your element:
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
<DropdownMenuTrigger asChild>
|
|
115
|
+
<Button appearance="ghost" iconOnly aria-label="Account menu">
|
|
116
|
+
<RiUserLine />
|
|
117
|
+
</Button>
|
|
118
|
+
</DropdownMenuTrigger>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Decorative vs meaningful icons
|
|
124
|
+
|
|
125
|
+
Icons passed through a component's `leadingIcon` / `trailingIcon` (or as menu-item children) sit next to text and are decorative - the text is the accessible name, leave them alone. An icon (or brand/flag/payment mark) that stands **alone** and carries meaning needs a name: give the control an `aria-label`, or the mark a `title` / `aria-label`. Purely ornamental standalone marks get `aria-hidden`.
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Focus must stay visible
|
|
130
|
+
|
|
131
|
+
Create UI focus is an `outline`, never a `ring`, and primitives wire it up themselves. Don't strip it. If you add focus styling to your own markup, use the transparent-base pattern - never `outline-none` with no replacement.
|
|
132
|
+
|
|
133
|
+
```tsx
|
|
134
|
+
// Correct - visible focus on a custom interactive element
|
|
135
|
+
<div tabIndex={0} className="outline-2 outline-transparent focus-visible:outline-primary-700">
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
See [styling.md](./styling.md) "Focus uses outline-*, never ring-*".
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Respect reduced motion for custom animation
|
|
143
|
+
|
|
144
|
+
Component animations already honor `prefers-reduced-motion`. For any animation you add yourself, gate it so it doesn't run for users who opted out - use Tailwind's `motion-safe:` / `motion-reduce:` variants rather than an unconditional `animate-*` or `transition`.
|
|
145
|
+
|
|
146
|
+
```tsx
|
|
147
|
+
<div className="motion-safe:transition-transform motion-safe:duration-200" />
|
|
148
|
+
```
|
|
@@ -8,10 +8,12 @@ How Create UI components fit together. Compose primitives - never reroll a `<sel
|
|
|
8
8
|
- Callouts use InlineAlert
|
|
9
9
|
- Toasts use the Toast component
|
|
10
10
|
- Choosing between overlay components
|
|
11
|
+
- Tables, cards, and other absent primitives
|
|
11
12
|
- Button has a `loading` prop - never hand-build a spinner button
|
|
12
13
|
- Tabbed navigation uses TabMenu
|
|
13
14
|
- Avatar composition (AvatarText, not AvatarFallback)
|
|
14
15
|
- Use existing components instead of custom markup
|
|
16
|
+
- Sizing across adjacent components
|
|
15
17
|
|
|
16
18
|
---
|
|
17
19
|
|
|
@@ -140,29 +142,7 @@ import {
|
|
|
140
142
|
|
|
141
143
|
`Toast` takes `variant` (`primary` | `neutral` | `danger` | `success` | `warning` | `info` | `away`) and `appearance` (`solid` | `soft` | `outline` | `default`), plus an `onDismiss` callback. Add `<ToastClose />` for an explicit close affordance and `<ToastProgress />` for an auto-dismiss countdown bar.
|
|
142
144
|
|
|
143
|
-
There is no provider, queue, or stacking system - you own the notification state and
|
|
144
|
-
|
|
145
|
-
```tsx
|
|
146
|
-
const [toasts, setToasts] = React.useState<AppToast[]>([])
|
|
147
|
-
|
|
148
|
-
<div className="fixed right-4 bottom-4 flex flex-col gap-2">
|
|
149
|
-
{toasts.map((t) => (
|
|
150
|
-
<Toast
|
|
151
|
-
key={t.id}
|
|
152
|
-
variant={t.variant}
|
|
153
|
-
appearance="solid"
|
|
154
|
-
onDismiss={() => setToasts((all) => all.filter((x) => x.id !== t.id))}
|
|
155
|
-
>
|
|
156
|
-
<ToastBody>
|
|
157
|
-
<ToastContent>
|
|
158
|
-
<ToastTitle>{t.title}</ToastTitle>
|
|
159
|
-
</ToastContent>
|
|
160
|
-
</ToastBody>
|
|
161
|
-
<ToastClose />
|
|
162
|
-
</Toast>
|
|
163
|
-
))}
|
|
164
|
-
</div>
|
|
165
|
-
```
|
|
145
|
+
There is no provider, queue, or stacking system - you own the notification state and placement: keep an array in state and `.map()` it into a fixed container (`<div className="fixed right-4 bottom-4 flex flex-col gap-2">`), each `Toast` wiring `onDismiss` to drop its id from the array.
|
|
166
146
|
|
|
167
147
|
---
|
|
168
148
|
|
|
@@ -176,8 +156,41 @@ Pick the overlay that matches the interaction - these are the overlays that exis
|
|
|
176
156
|
| "What is this?" helper next to a label | `InfoTooltip` |
|
|
177
157
|
| Action menu on a trigger | `DropdownMenu` |
|
|
178
158
|
| Command palette / quick switcher | `Command` (inline) / `CommandDialog` (modal) |
|
|
159
|
+
| Blocking dialog / focused task | `Modal` *(Pro - needs a developer seat)* |
|
|
160
|
+
| Anchored floating panel on a trigger | `Popover` *(Pro - needs a developer seat)* |
|
|
161
|
+
|
|
162
|
+
At the **free tier** there is no dialog, sheet, drawer, alert-dialog, or hover-card component, and the only modal surface is `CommandDialog` (shipped with `command`). **`Modal` and `Popover` exist only as Pro components**: a developer seat is required to install them (`add modal` returns 401 without one), so confirm their API with `get_component_reference('modal')` / `('popover')` first. When a seat isn't available, don't invent a lookalike from raw markup - surface the flow inline (an expanding section, a dedicated route, or an `InlineAlert` confirmation) or ask the user before hand-rolling an overlay.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Tables, cards, and other absent primitives
|
|
167
|
+
|
|
168
|
+
`Card`, `Table`, `Skeleton`, `Sheet`, `Drawer`, `Sidebar`, and `alert-banner` have **no primitive at any tier**. Don't fake them with styled-`<div>` soup - build from a semantic surface (`bg-static` / `bg-weak`, `border-light`, an elevation shadow, type tokens) and put primitives in the content (`Badge` for status, `Button` / `DropdownMenu` for actions). Raw palette colors and hex never appear.
|
|
179
169
|
|
|
180
|
-
|
|
170
|
+
- **Card** = a surface: `<div className="bg-static border-light shadow-neutral-sm rounded-xl border p-6">` with `text-heading-*` / `text-body-*` inside.
|
|
171
|
+
- **Skeleton** = reuse the loaded layout with token-sized `bg-weak` bars per line (see [styling.md](./styling.md) "Loading placeholders"), never a `Spinner` in a fixed-height box.
|
|
172
|
+
- **Empty state** = the same surface, centered, `text-placeholder` copy + one primary `Button` - not a bare "No data" string.
|
|
173
|
+
|
|
174
|
+
**Table** - a real semantic `<table>`: a `bg-weak` header with caption-scale labels, `border-light` row separators, and primitives in the cells:
|
|
175
|
+
|
|
176
|
+
```tsx
|
|
177
|
+
<div className="border-light overflow-hidden rounded-lg border">
|
|
178
|
+
<table className="w-full border-collapse text-left">
|
|
179
|
+
<thead className="bg-weak">
|
|
180
|
+
<tr>
|
|
181
|
+
<th className="text-ui-caption-md text-placeholder px-4 py-2 font-medium">Name</th>
|
|
182
|
+
<th className="text-ui-caption-md text-placeholder px-4 py-2 font-medium">Status</th>
|
|
183
|
+
</tr>
|
|
184
|
+
</thead>
|
|
185
|
+
<tbody>
|
|
186
|
+
<tr className="border-light border-t">
|
|
187
|
+
<td className="text-body-sm text-body px-4 py-3">Ada Lovelace</td>
|
|
188
|
+
<td className="px-4 py-3"><Badge variant="success" appearance="soft" size="sm">Active</Badge></td>
|
|
189
|
+
</tr>
|
|
190
|
+
</tbody>
|
|
191
|
+
</table>
|
|
192
|
+
</div>
|
|
193
|
+
```
|
|
181
194
|
|
|
182
195
|
---
|
|
183
196
|
|
|
@@ -230,7 +243,7 @@ const [tab, setTab] = React.useState("overview")
|
|
|
230
243
|
{tab === "overview" && <OverviewPanel />}
|
|
231
244
|
```
|
|
232
245
|
|
|
233
|
-
`variant` is `
|
|
246
|
+
At the free tier `variant` is `horizontal-line` - the default and only free value; the Pro tier adds `vertical-button`, `vertical-line`, and `horizontal-button`. `size` is `sm` | `md` | `lg`. `TabMenuItem` takes `label`, `leadingIcon` / `trailingIcon`, `disabled`, and `asChild` for link tabs.
|
|
234
247
|
|
|
235
248
|
---
|
|
236
249
|
|
|
@@ -259,7 +272,7 @@ Initials-only avatars pick a real color `variant`; presence comes from `AvatarBa
|
|
|
259
272
|
</Avatar>
|
|
260
273
|
```
|
|
261
274
|
|
|
262
|
-
See `
|
|
275
|
+
See `get_component_reference('avatar')` for the full prop tables (`size` `2xs`–`2xl`, `shape`, 55 color variants, `AvatarIcon`, `AvatarRing`).
|
|
263
276
|
|
|
264
277
|
---
|
|
265
278
|
|
|
@@ -274,3 +287,28 @@ If a primitive already covers the job, use it - don't reach for raw elements or
|
|
|
274
287
|
| A status dot built from a styled `<span>` | `<StatusBadge variant="success" />` (it renders the dot only - put the label next to it). `variant`: `primary`, `danger`, `success`, `warning`, `info`, `highlighted`, `away`, `verified`, `cyan`, `lime`, `neutral`, `white` - note `danger`, not `error` |
|
|
275
288
|
| A removable tag built from `<span>` + `<button>` | `<Chip onClose={…}>…</Chip>` |
|
|
276
289
|
| A hand-rolled `animate-spin` loading indicator | `<Spinner />` |
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
## Sizing across adjacent components
|
|
294
|
+
|
|
295
|
+
Each component owns its own `size` scale and **the names are not pixel-equal** - `Avatar md` ≠ `Button md` ≠ `Badge md` in height. So never harmonize a row by matching size *prop names*; match by **optical height**:
|
|
296
|
+
|
|
297
|
+
- **Prefer a size-owning container** - `Field` (its `Input` / `Select` / `Textarea` / labels inherit size), `InputGroup` (its control / button inherit), `Chip` (first-child icon or `Avatar` auto-sized), and icons inside `Button` / `Badge` / `TabMenuItem` (auto-sized). Inside one of these the sizes already match; only free-standing clusters need manual work.
|
|
298
|
+
- **Anchor on the text scale and move the cluster together.** Pick the body token first (`text-body-sm`), size the neighbors to it, and when you go denser or larger shift the *whole* set (avatar + text token + link size) - never one side.
|
|
299
|
+
- **Align, then space:** `flex items-center` + a gap from the spacing scale, not margins. Confirm exact heights with `get_component_reference`.
|
|
300
|
+
|
|
301
|
+
```tsx
|
|
302
|
+
<div className="flex items-center gap-3">
|
|
303
|
+
<Avatar size="lg">
|
|
304
|
+
<AvatarImage src="/me.png" alt="Jane Doe" />
|
|
305
|
+
<AvatarText>JD</AvatarText>
|
|
306
|
+
</Avatar>
|
|
307
|
+
<div className="flex flex-col gap-1">
|
|
308
|
+
<span className="text-body-sm text-strongest font-medium">Profile photo</span>
|
|
309
|
+
<TextLink variant="primary" size="sm">Change</TextLink>
|
|
310
|
+
</div>
|
|
311
|
+
</div>
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Rough pairing by text anchor (not pixel-identical - verify): `text-body-xs` → size `xs`, `text-body-sm` → `sm`, `text-body-md` → `md`. For a form control plus its trimmings, don't hand-tune at all - wrap it in `Field` / `InputGroup` (see [forms.md](./forms.md)).
|
|
@@ -85,7 +85,7 @@ Every control below exists in the registry. Pick by intent:
|
|
|
85
85
|
| Date | `DateInput` |
|
|
86
86
|
| Phone number | `PhoneInput` |
|
|
87
87
|
| Card details | `CreditCardInput` |
|
|
88
|
-
| Password
|
|
88
|
+
| Password | `Input type="password"` (add a show/hide toggle with `InputGroup` + `InputGroupButton`; there is no strength-meter primitive) |
|
|
89
89
|
|
|
90
90
|
---
|
|
91
91
|
|
|
@@ -237,7 +237,7 @@ The `Field` here must be `orientation="horizontal"` (or wrap the control in a pl
|
|
|
237
237
|
|
|
238
238
|
`Field` size does not cascade to `Switch` (it reads only `SwitchContext`) - pair them explicitly: a default (sm) `Field` row takes `<Switch size="sm">`, and a bare (md) `Switch` belongs in a `<Field size="md">` row. `SwitchGroup` pairs the two automatically.
|
|
239
239
|
|
|
240
|
-
Apply-immediately settings rows use `SwitchGroup` - one labelled row per switch; there is no `SwitchGroupItem` (compose `Switch` + `FieldContent` + `LabelMain` per `
|
|
240
|
+
Apply-immediately settings rows use `SwitchGroup` - one labelled row per switch; there is no `SwitchGroupItem` (compose `Switch` + `FieldContent` + `LabelMain` per `get_component_reference('switch-group')`). Inside a submit-to-save form prefer `Checkbox` / `CheckboxGroup`: a switch implies the setting takes effect the moment it flips. If a task explicitly demands toggles plus a Save button, keep the toggles deliberately - but don't present that as the default form pattern.
|
|
241
241
|
|
|
242
242
|
---
|
|
243
243
|
|
|
@@ -75,7 +75,7 @@ Subpaths: `icons` (Remix UI icons), `social`, `flags`, `payments`, `brands`, `ba
|
|
|
75
75
|
<TabMenuItem value="billing" label="Billing" leadingIcon={<RiBankCardLine />} />
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
-
The icon-as-children cases are: `iconOnly` mode on `Button`, `Badge`, `SegmentedControlItem`, and `ButtonGroupItem` (the icon IS the children there - `leadingIcon` / `trailingIcon` are ignored), and menu-ish items like `DropdownMenuItem` / `CommandItem`, where a bare `<RiIcon />` child before the text is the convention. All four `iconOnly` components follow the same rule, so `<SegmentedControlItem iconOnly aria-label="Grid"><RiLayoutGridFill /></SegmentedControlItem>`. When in doubt, check `
|
|
78
|
+
The icon-as-children cases are: `iconOnly` mode on `Button`, `Badge`, `SegmentedControlItem`, and `ButtonGroupItem` (the icon IS the children there - `leadingIcon` / `trailingIcon` are ignored), and menu-ish items like `DropdownMenuItem` / `CommandItem`, where a bare `<RiIcon />` child before the text is the convention. All four `iconOnly` components follow the same rule, so `<SegmentedControlItem iconOnly aria-label="Grid"><RiLayoutGridFill /></SegmentedControlItem>`. When in doubt, check `get_component_reference('<component>')`.
|
|
79
79
|
|
|
80
80
|
---
|
|
81
81
|
|
|
@@ -30,7 +30,7 @@ Create UI's tokens are HEX-backed CSS variables that swap automatically between
|
|
|
30
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`.
|
|
31
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.
|
|
32
32
|
- Borders: `border-weakest` … `border-strongest` (commonly `border-light` / `border-medium`).
|
|
33
|
-
- Primary
|
|
33
|
+
- Primary (brand) - use the **semantic, theme-swapping** tokens `bg-primary-base` / `text-primary-base` / `bg-primary-weak` / `border-primary-strong`; each resolves to a different ramp step in dark vs light (`primary-base` is `primary-500` in light, `primary-400` in dark), so it stays legible in both. The raw numeric ramp (`bg-primary-500`) and `primary-alpha-*` are **fixed** - they don't swap, so treat `bg-primary-500` like `bg-blue-500` and keep it out of your markup. **`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 for a brand color, invent one, or hand-edit the token hex to re-theme. A different theme is `createui init --theme <name>`, not a CSS edit.
|
|
34
34
|
|
|
35
35
|
**Incorrect:**
|
|
36
36
|
|
|
@@ -55,7 +55,7 @@ Quick translation from generic utility names to Create UI tokens:
|
|
|
55
55
|
| page / card surface | `bg-static` (or `bg-weakest` for subtle surfaces) |
|
|
56
56
|
| primary text | `text-body` |
|
|
57
57
|
| secondary / muted text | `text-placeholder` |
|
|
58
|
-
| primary accent fill | `bg-primary-base` (
|
|
58
|
+
| primary accent fill | `bg-primary-base` (swaps dark/light; not raw `bg-primary-500`) |
|
|
59
59
|
| text on a solid primary fill | `text-white` |
|
|
60
60
|
| default border | `border-light` or `border-medium` |
|
|
61
61
|
| subtle / muted fill | `bg-weak` |
|
package/dist/utils/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {a}from'../chunk-VQCXAURP.js';import {
|
|
1
|
+
import {a}from'../chunk-VQCXAURP.js';import {_ as _$1}from'../chunk-KFQXWKJJ.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 _$1(),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/dist/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/styles/create-style-map.ts","../../src/styles/transform-style-map.ts","../../src/styles/transform.ts","../../src/utils/transformers/transform-legacy-icons.ts"],"names":["CN_PREFIX","styleMapSchema","z","createStyleMap","input","root","postcss","result","rule","selectors","tailwindClasses","extractTailwindClasses","selector","normalizedSelector","normalizeSelector","selectorParser","selectorsRoot","sel","targetClass","findSubjectClass","className","classes","node","value","classNodes","classNode","isStringLiteralLike","Node","transformStyleMap","sourceFile","styleMap","matchedClasses","applyToCvaCalls","applyToClassNameAttributes","applyToMergePropsCalls","applyStyleToCvaString","stringNode","stringValue","cnClasses","extractCnClasses","unmatchedClasses","cnClass","updated","removeCnClasses","tailwindClassesToApply","mergedClasses","mergeClasses","expression","baseArg","configArg","variantsProp","prop","variantsObj","typeProp","typeObj","variantProp","variantValue","initializer","extractCnClassesFromAttribute","jsxElement","cleanCnClassesFromAttribute","applyClassesToElement","isCnCall","argument","cleaned","removeEmptyArgumentsFromCnCall","str","matches","match","callExpression","args","nonEmptyArgs","arg","argTexts","parent","element","attribute","attr","existing","firstArg","i","argText","argumentTexts","updatedArguments","newClasses","existingParts","call","classNameProp","classNameInitializer","extractCnClassesFromCnCall","cleanCnClassesFromCnCall","applyClassesToCnCall","cnCall","transformStyle","source","transformers","Project","ScriptKind","transformer","SOURCE_LIBRARY","transformLegacyIcons","config","LEGACY_ICON_LIBRARIES","sourceLibrary","targetLibrary","registryIcons","getRegistryIcons","targetedIcons","importDeclaration","specifier","iconName","targetedIcon","SyntaxKind","iconImportDeclaration","icon","_useSemicolon"],"mappings":"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","file":"index.js","sourcesContent":["import postcss from \"postcss\"\nimport selectorParser, {\n type ClassName,\n type Selector as SelectorNodeRoot,\n} from \"postcss-selector-parser\"\nimport { z } from \"zod\"\n\nconst CN_PREFIX = \"cn-\"\n\nexport const styleMapSchema = z.record(\n z.string().startsWith(CN_PREFIX),\n z.string()\n)\n\nexport type StyleMap = z.infer<typeof styleMapSchema>\n\nexport function createStyleMap(input: string) {\n const root = postcss.parse(input)\n\n const result: Record<string, string> = {}\n\n root.walkRules((rule) => {\n const selectors = rule.selectors ?? []\n\n if (selectors.length === 0) {\n return\n }\n\n const tailwindClasses = extractTailwindClasses(rule)\n\n if (!tailwindClasses) {\n return\n }\n\n for (const selector of selectors) {\n const normalizedSelector = normalizeSelector(selector)\n\n selectorParser((selectorsRoot) => {\n selectorsRoot.each((sel) => {\n const targetClass = findSubjectClass(sel)\n\n if (!targetClass) {\n return\n }\n\n const className = targetClass.value\n\n if (!className.startsWith(CN_PREFIX)) {\n return\n }\n\n result[className] = result[className]\n ? `${tailwindClasses} ${result[className]}`\n : tailwindClasses\n })\n }).processSync(normalizedSelector)\n }\n })\n\n return styleMapSchema.parse(result)\n}\n\nfunction normalizeSelector(selector: string) {\n return selector.replace(/\\s*&\\s*/g, \"\").trim()\n}\n\nfunction extractTailwindClasses(rule: postcss.Rule) {\n const classes: string[] = []\n\n for (const node of rule.nodes || []) {\n if (node.type === \"atrule\" && node.name === \"apply\") {\n const value = node.params.trim()\n if (value) {\n classes.push(value)\n }\n }\n }\n\n if (classes.length === 0) {\n return null\n }\n\n return classes.join(\" \")\n}\n\nfunction findSubjectClass(selector: SelectorNodeRoot) {\n const classNodes: ClassName[] = []\n\n selector.walkClasses((classNode) => {\n if (classNode.value.startsWith(CN_PREFIX)) {\n classNodes.push(classNode)\n }\n })\n\n if (classNodes.length === 0) {\n return null\n }\n\n return classNodes[classNodes.length - 1]\n}\n","import { TransformerStyle } from \"@/src/styles/transform\"\nimport {\n Node,\n type CallExpression,\n type NoSubstitutionTemplateLiteral,\n type SourceFile,\n type StringLiteral,\n} from \"ts-morph\"\n\nimport { type StyleMap } from \"./create-style-map\"\n\nfunction isStringLiteralLike(\n node: Node\n): node is StringLiteral | NoSubstitutionTemplateLiteral {\n return (\n Node.isStringLiteral(node) || Node.isNoSubstitutionTemplateLiteral(node)\n )\n}\n\nexport const transformStyleMap: TransformerStyle<SourceFile> = async ({\n sourceFile,\n styleMap,\n}) => {\n const matchedClasses = new Set<string>()\n\n applyToCvaCalls(sourceFile, styleMap, matchedClasses)\n applyToClassNameAttributes(sourceFile, styleMap, matchedClasses)\n applyToMergePropsCalls(sourceFile, styleMap, matchedClasses)\n\n return sourceFile\n}\n\nfunction applyStyleToCvaString(\n stringNode: StringLiteral,\n styleMap: StyleMap,\n matchedClasses: Set<string>\n) {\n const stringValue = stringNode.getLiteralText()\n const cnClasses = extractCnClasses(stringValue)\n\n if (cnClasses.length === 0) {\n return\n }\n\n // Process all cn-* classes, not just the first one\n const unmatchedClasses = cnClasses.filter(\n (cnClass) => !matchedClasses.has(cnClass)\n )\n\n if (unmatchedClasses.length === 0) {\n // All classes already matched, just clean up non-allowlisted ones\n const updated = removeCnClasses(stringValue)\n stringNode.setLiteralValue(updated)\n return\n }\n\n const tailwindClassesToApply = unmatchedClasses\n .map((cnClass) => styleMap[cnClass])\n .filter((classes): classes is string => Boolean(classes))\n\n if (tailwindClassesToApply.length > 0) {\n const mergedClasses = tailwindClassesToApply.join(\" \")\n const updated = removeCnClasses(mergeClasses(mergedClasses, stringValue))\n stringNode.setLiteralValue(updated)\n unmatchedClasses.forEach((cnClass) => matchedClasses.add(cnClass))\n } else {\n // No styles to apply, but still need to clean up non-allowlisted classes\n const updated = removeCnClasses(stringValue)\n stringNode.setLiteralValue(updated)\n }\n}\n\nfunction applyToCvaCalls(\n sourceFile: SourceFile,\n styleMap: StyleMap,\n matchedClasses: Set<string>\n) {\n sourceFile.forEachDescendant((node) => {\n if (!Node.isCallExpression(node)) {\n return\n }\n\n const expression = node.getExpression()\n if (!Node.isIdentifier(expression) || expression.getText() !== \"cva\") {\n return\n }\n\n const baseArg = node.getArguments()[0]\n if (Node.isStringLiteral(baseArg)) {\n applyStyleToCvaString(baseArg, styleMap, matchedClasses)\n }\n\n const configArg = node.getArguments()[1]\n if (!configArg || !Node.isObjectLiteralExpression(configArg)) {\n return\n }\n\n const variantsProp = configArg\n .getProperties()\n .find(\n (prop) =>\n Node.isPropertyAssignment(prop) &&\n Node.isIdentifier(prop.getNameNode()) &&\n prop.getNameNode().getText() === \"variants\"\n )\n\n if (!variantsProp || !Node.isPropertyAssignment(variantsProp)) {\n return\n }\n\n const variantsObj = variantsProp.getInitializer()\n if (!variantsObj || !Node.isObjectLiteralExpression(variantsObj)) {\n return\n }\n\n variantsObj.getProperties().forEach((typeProp) => {\n if (!Node.isPropertyAssignment(typeProp)) {\n return\n }\n\n const typeObj = typeProp.getInitializer()\n if (!typeObj || !Node.isObjectLiteralExpression(typeObj)) {\n return\n }\n\n typeObj.getProperties().forEach((variantProp) => {\n if (!Node.isPropertyAssignment(variantProp)) {\n return\n }\n\n const variantValue = variantProp.getInitializer()\n if (variantValue && Node.isStringLiteral(variantValue)) {\n applyStyleToCvaString(variantValue, styleMap, matchedClasses)\n }\n })\n })\n })\n}\n\nfunction applyToClassNameAttributes(\n sourceFile: SourceFile,\n styleMap: StyleMap,\n matchedClasses: Set<string>\n) {\n sourceFile.forEachDescendant((node) => {\n if (\n !Node.isJsxAttribute(node) ||\n node.getNameNode().getText() !== \"className\"\n ) {\n return\n }\n\n const initializer = node.getInitializer()\n if (!initializer) {\n return\n }\n\n const cnClasses = extractCnClassesFromAttribute(initializer)\n\n if (cnClasses.length === 0) {\n return\n }\n\n const jsxElement = node.getParent()?.getParent()\n if (\n !jsxElement ||\n (!Node.isJsxOpeningElement(jsxElement) &&\n !Node.isJsxSelfClosingElement(jsxElement))\n ) {\n return\n }\n\n const unmatchedClasses = cnClasses.filter(\n (cnClass) => !matchedClasses.has(cnClass)\n )\n\n if (unmatchedClasses.length === 0) {\n // Even if all classes are already matched, we still need to clean them up\n cleanCnClassesFromAttribute(initializer)\n return\n }\n\n const tailwindClassesToApply = unmatchedClasses\n .map((cnClass) => styleMap[cnClass])\n .filter((classes): classes is string => Boolean(classes))\n\n if (tailwindClassesToApply.length > 0) {\n const mergedClasses = tailwindClassesToApply.join(\" \")\n applyClassesToElement(jsxElement, mergedClasses)\n } else {\n cleanCnClassesFromAttribute(initializer)\n }\n })\n}\n\nfunction extractCnClassesFromAttribute(initializer: Node) {\n const classes: string[] = []\n\n if (isStringLiteralLike(initializer)) {\n return extractCnClasses(initializer.getLiteralText())\n }\n\n if (!Node.isJsxExpression(initializer)) {\n return classes\n }\n\n const expression = initializer.getExpression()\n if (!expression) {\n return classes\n }\n\n if (isStringLiteralLike(expression)) {\n return extractCnClasses(expression.getLiteralText())\n }\n\n if (Node.isCallExpression(expression) && isCnCall(expression)) {\n for (const argument of expression.getArguments()) {\n if (isStringLiteralLike(argument)) {\n classes.push(...extractCnClasses(argument.getLiteralText()))\n }\n }\n }\n\n return classes\n}\n\nfunction cleanCnClassesFromAttribute(initializer: Node) {\n if (isStringLiteralLike(initializer)) {\n const cleaned = removeCnClasses(initializer.getLiteralText())\n initializer.setLiteralValue(cleaned)\n return\n }\n\n if (!Node.isJsxExpression(initializer)) {\n return\n }\n\n const expression = initializer.getExpression()\n if (!expression) {\n return\n }\n\n if (isStringLiteralLike(expression)) {\n const cleaned = removeCnClasses(expression.getLiteralText())\n expression.setLiteralValue(cleaned)\n return\n }\n\n if (Node.isCallExpression(expression) && isCnCall(expression)) {\n for (const argument of expression.getArguments()) {\n if (isStringLiteralLike(argument)) {\n const cleaned = removeCnClasses(argument.getLiteralText())\n argument.setLiteralValue(cleaned)\n }\n }\n\n removeEmptyArgumentsFromCnCall(expression)\n }\n}\n\nfunction extractCnClasses(str: string) {\n const matches = str.matchAll(/\\bcn-[\\w-]+\\b/g)\n return Array.from(matches, (match) => match[0])\n}\n\nfunction extractCnClass(str: string) {\n const classes = extractCnClasses(str)\n return classes[0] ?? null\n}\n\nfunction removeCnClasses(str: string) {\n return str\n .replace(/\\bcn-[\\w-]+\\b/g, \"\")\n .replace(/\\s+/g, \" \")\n .trim()\n}\n\nfunction removeEmptyArgumentsFromCnCall(callExpression: CallExpression) {\n if (!isCnCall(callExpression)) {\n return\n }\n\n const args = callExpression.getArguments()\n const nonEmptyArgs = args.filter((arg) => {\n if (isStringLiteralLike(arg)) {\n const text = arg.getLiteralText().trim()\n return text !== \"\"\n }\n return true\n })\n\n if (nonEmptyArgs.length !== args.length) {\n const argTexts = nonEmptyArgs.map((arg) => arg.getText())\n const parent = callExpression.getParent()\n if (parent && Node.isJsxExpression(parent)) {\n parent.replaceWithText(`{cn(${argTexts.join(\", \")})}`)\n } else {\n callExpression.replaceWithText(`cn(${argTexts.join(\", \")})`)\n }\n }\n}\n\nfunction applyClassesToElement(element: Node, tailwindClasses: string) {\n if (\n !Node.isJsxOpeningElement(element) &&\n !Node.isJsxSelfClosingElement(element)\n ) {\n return\n }\n\n const attribute = element\n .getAttributes()\n .find(\n (attr) =>\n Node.isJsxAttribute(attr) &&\n attr.getNameNode().getText() === \"className\"\n )\n\n if (!attribute || !Node.isJsxAttribute(attribute)) {\n element.addAttribute({\n name: \"className\",\n initializer: `{cn(${JSON.stringify(tailwindClasses)})}`,\n })\n return\n }\n\n const initializer = attribute.getInitializer()\n\n if (!initializer) {\n attribute.setInitializer(`{cn(${JSON.stringify(tailwindClasses)})}`)\n return\n }\n\n if (isStringLiteralLike(initializer)) {\n const existing = initializer.getLiteralText()\n const updated = removeCnClasses(mergeClasses(tailwindClasses, existing))\n initializer.setLiteralValue(updated)\n return\n }\n\n if (!Node.isJsxExpression(initializer)) {\n return\n }\n\n const expression = initializer.getExpression()\n\n if (!expression) {\n attribute.setInitializer(`{cn(${JSON.stringify(tailwindClasses)})}`)\n return\n }\n\n if (isStringLiteralLike(expression)) {\n const existing = expression.getLiteralText()\n const updated = removeCnClasses(mergeClasses(tailwindClasses, existing))\n expression.setLiteralValue(updated)\n return\n }\n\n if (Node.isCallExpression(expression) && isCnCall(expression)) {\n const firstArg = expression.getArguments()[0]\n if (isStringLiteralLike(firstArg)) {\n const existing = firstArg.getLiteralText()\n const updated = removeCnClasses(mergeClasses(tailwindClasses, existing))\n firstArg.setLiteralValue(updated)\n\n for (let i = 1; i < expression.getArguments().length; i++) {\n const arg = expression.getArguments()[i]\n if (isStringLiteralLike(arg)) {\n const argText = arg.getLiteralText()\n const cleaned = removeCnClasses(argText)\n if (cleaned !== argText) {\n arg.setLiteralValue(cleaned)\n }\n }\n }\n\n removeEmptyArgumentsFromCnCall(expression)\n return\n }\n\n const argumentTexts = expression\n .getArguments()\n .map((argument) => {\n if (isStringLiteralLike(argument)) {\n const cleaned = removeCnClasses(argument.getLiteralText())\n return cleaned ? JSON.stringify(cleaned) : null\n }\n return argument.getText()\n })\n .filter((arg): arg is string => arg !== null)\n\n const updatedArguments = [JSON.stringify(tailwindClasses), ...argumentTexts]\n\n attribute.setInitializer(`{cn(${updatedArguments.join(\", \")})}`)\n return\n }\n\n attribute.setInitializer(\n `{cn(${JSON.stringify(tailwindClasses)}, ${expression.getText()})}`\n )\n}\n\nfunction mergeClasses(newClasses: string, existing: string) {\n const existingParts = existing.split(/\\s+/).filter(Boolean)\n const newParts = newClasses.split(/\\s+/).filter(Boolean)\n const combined = [...newParts, ...existingParts]\n return combined.join(\" \").trim()\n}\n\nfunction isCnCall(call: CallExpression) {\n const expression = call.getExpression()\n return Node.isIdentifier(expression) && expression.getText() === \"cn\"\n}\n\nfunction applyToMergePropsCalls(\n sourceFile: SourceFile,\n styleMap: StyleMap,\n matchedClasses: Set<string>\n) {\n sourceFile.forEachDescendant((node) => {\n if (!Node.isCallExpression(node)) {\n return\n }\n\n const expression = node.getExpression()\n if (\n !Node.isIdentifier(expression) ||\n expression.getText() !== \"mergeProps\"\n ) {\n return\n }\n\n // Look for object literals in mergeProps arguments\n for (const arg of node.getArguments()) {\n if (!Node.isObjectLiteralExpression(arg)) {\n continue\n }\n\n // Find className property in the object literal\n const classNameProp = arg\n .getProperties()\n .find(\n (prop) =>\n Node.isPropertyAssignment(prop) &&\n Node.isIdentifier(prop.getNameNode()) &&\n prop.getNameNode().getText() === \"className\"\n )\n\n if (!classNameProp || !Node.isPropertyAssignment(classNameProp)) {\n continue\n }\n\n const classNameInitializer = classNameProp.getInitializer()\n if (!classNameInitializer) {\n continue\n }\n\n // Handle cn() calls in className\n if (\n Node.isCallExpression(classNameInitializer) &&\n isCnCall(classNameInitializer)\n ) {\n const cnClasses = extractCnClassesFromCnCall(classNameInitializer)\n\n if (cnClasses.length === 0) {\n continue\n }\n\n const unmatchedClasses = cnClasses.filter(\n (cnClass) => !matchedClasses.has(cnClass)\n )\n\n if (unmatchedClasses.length === 0) {\n // Clean up cn-* classes even if already matched\n cleanCnClassesFromCnCall(classNameInitializer)\n continue\n }\n\n const tailwindClassesToApply = unmatchedClasses\n .map((cnClass) => styleMap[cnClass])\n .filter((classes): classes is string => Boolean(classes))\n\n if (tailwindClassesToApply.length > 0) {\n const mergedClasses = tailwindClassesToApply.join(\" \")\n applyClassesToCnCall(\n classNameInitializer,\n mergedClasses,\n matchedClasses,\n unmatchedClasses\n )\n } else {\n cleanCnClassesFromCnCall(classNameInitializer)\n }\n }\n }\n })\n}\n\nfunction extractCnClassesFromCnCall(cnCall: CallExpression): string[] {\n const classes: string[] = []\n\n for (const argument of cnCall.getArguments()) {\n if (isStringLiteralLike(argument)) {\n classes.push(...extractCnClasses(argument.getLiteralText()))\n }\n }\n\n return classes\n}\n\nfunction cleanCnClassesFromCnCall(cnCall: CallExpression) {\n for (const argument of cnCall.getArguments()) {\n if (isStringLiteralLike(argument)) {\n const cleaned = removeCnClasses(argument.getLiteralText())\n argument.setLiteralValue(cleaned)\n }\n }\n\n removeEmptyArgumentsFromCnCall(cnCall)\n}\n\nfunction applyClassesToCnCall(\n cnCall: CallExpression,\n tailwindClasses: string,\n matchedClasses: Set<string>,\n unmatchedClasses: string[]\n) {\n const firstArg = cnCall.getArguments()[0]\n\n if (isStringLiteralLike(firstArg)) {\n const existing = firstArg.getLiteralText()\n const updated = removeCnClasses(mergeClasses(tailwindClasses, existing))\n firstArg.setLiteralValue(updated)\n\n // Mark classes as matched\n unmatchedClasses.forEach((cnClass) => matchedClasses.add(cnClass))\n\n // Clean up cn-* classes from remaining arguments\n for (let i = 1; i < cnCall.getArguments().length; i++) {\n const arg = cnCall.getArguments()[i]\n if (isStringLiteralLike(arg)) {\n const argText = arg.getLiteralText()\n const cleaned = removeCnClasses(argText)\n if (cleaned !== argText) {\n arg.setLiteralValue(cleaned)\n }\n }\n }\n\n removeEmptyArgumentsFromCnCall(cnCall)\n return\n }\n\n // If first arg is not a string literal, prepend tailwind classes\n const argumentTexts = cnCall\n .getArguments()\n .map((argument) => {\n if (isStringLiteralLike(argument)) {\n const cleaned = removeCnClasses(argument.getLiteralText())\n return cleaned ? JSON.stringify(cleaned) : null\n }\n return argument.getText()\n })\n .filter((arg): arg is string => arg !== null)\n\n const updatedArguments = [JSON.stringify(tailwindClasses), ...argumentTexts]\n\n // Mark classes as matched\n unmatchedClasses.forEach((cnClass) => matchedClasses.add(cnClass))\n\n const parent = cnCall.getParent()\n if (parent) {\n cnCall.replaceWithText(`cn(${updatedArguments.join(\", \")})`)\n }\n}\n","import { Project, ScriptKind, type SourceFile } from \"ts-morph\"\n\nimport { type StyleMap } from \"./create-style-map\"\nimport { transformStyleMap } from \"./transform-style-map\"\n\nexport type TransformerStyle<Output = SourceFile> = (opts: {\n sourceFile: SourceFile\n styleMap: StyleMap\n}) => Promise<Output>\n\nexport async function transformStyle(\n source: string,\n {\n styleMap,\n transformers = [transformStyleMap],\n }: {\n styleMap: StyleMap\n transformers?: TransformerStyle<SourceFile>[]\n }\n) {\n const project = new Project({\n useInMemoryFileSystem: true,\n })\n\n const sourceFile = project.createSourceFile(\"component.tsx\", source, {\n scriptKind: ScriptKind.TSX,\n overwrite: true,\n })\n\n for (const transformer of transformers) {\n await transformer({ sourceFile, styleMap })\n }\n\n return sourceFile.getText()\n}\n","import { getRegistryIcons } from \"@/src/registry/api\"\nimport { LEGACY_ICON_LIBRARIES } from \"@/src/utils/legacy-icon-libraries\"\nimport { Transformer } from \"@/src/utils/transformers\"\nimport { SourceFile, SyntaxKind } from \"ts-morph\"\n\n// Lucide is the default icon library in the registry.\nconst SOURCE_LIBRARY = \"lucide\"\n\nexport const transformLegacyIcons: Transformer = async ({\n sourceFile,\n config,\n}) => {\n // No transform if we cannot read the icon library.\n if (!config.iconLibrary || !(config.iconLibrary in LEGACY_ICON_LIBRARIES)) {\n return sourceFile\n }\n\n const sourceLibrary = SOURCE_LIBRARY\n const targetLibrary = config.iconLibrary\n\n if (sourceLibrary === targetLibrary) {\n return sourceFile\n }\n\n const registryIcons = await getRegistryIcons()\n\n let targetedIcons: string[] = []\n for (const importDeclaration of sourceFile.getImportDeclarations() ?? []) {\n if (\n importDeclaration.getModuleSpecifier()?.getText() !==\n `\"${LEGACY_ICON_LIBRARIES[SOURCE_LIBRARY].import}\"`\n ) {\n continue\n }\n\n for (const specifier of importDeclaration.getNamedImports() ?? []) {\n const iconName = specifier.getName()\n\n const targetedIcon = registryIcons[iconName]?.[targetLibrary]\n\n if (!targetedIcon || targetedIcons.includes(targetedIcon)) {\n continue\n }\n\n targetedIcons.push(targetedIcon)\n\n // Remove the named import.\n specifier.remove()\n\n // Replace with the targeted icon.\n sourceFile\n .getDescendantsOfKind(SyntaxKind.JsxSelfClosingElement)\n .filter((node) => node.getTagNameNode()?.getText() === iconName)\n .forEach((node) => node.getTagNameNode()?.replaceWithText(targetedIcon))\n }\n\n // If the named import is empty, remove the import declaration.\n if (importDeclaration.getNamedImports()?.length === 0) {\n importDeclaration.remove()\n }\n }\n\n if (targetedIcons.length > 0) {\n const iconImportDeclaration = sourceFile.addImportDeclaration({\n moduleSpecifier:\n LEGACY_ICON_LIBRARIES[\n targetLibrary as keyof typeof LEGACY_ICON_LIBRARIES\n ]?.import,\n namedImports: targetedIcons.map((icon) => ({\n name: icon,\n })),\n })\n\n if (!_useSemicolon(sourceFile)) {\n iconImportDeclaration.replaceWithText(\n iconImportDeclaration.getText().replace(\";\", \"\")\n )\n }\n }\n\n return sourceFile\n}\n\nfunction _useSemicolon(sourceFile: SourceFile) {\n return (\n sourceFile.getImportDeclarations()?.[0]?.getText().endsWith(\";\") ?? false\n )\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/styles/create-style-map.ts","../../src/styles/transform-style-map.ts","../../src/styles/transform.ts","../../src/utils/transformers/transform-legacy-icons.ts"],"names":["CN_PREFIX","styleMapSchema","z","createStyleMap","input","root","postcss","result","rule","selectors","tailwindClasses","extractTailwindClasses","selector","normalizedSelector","normalizeSelector","selectorParser","selectorsRoot","sel","targetClass","findSubjectClass","className","classes","node","value","classNodes","classNode","isStringLiteralLike","Node","transformStyleMap","sourceFile","styleMap","matchedClasses","applyToCvaCalls","applyToClassNameAttributes","applyToMergePropsCalls","applyStyleToCvaString","stringNode","stringValue","cnClasses","extractCnClasses","unmatchedClasses","cnClass","updated","removeCnClasses","tailwindClassesToApply","mergedClasses","mergeClasses","expression","baseArg","configArg","variantsProp","prop","variantsObj","typeProp","typeObj","variantProp","variantValue","initializer","extractCnClassesFromAttribute","jsxElement","cleanCnClassesFromAttribute","applyClassesToElement","isCnCall","argument","cleaned","removeEmptyArgumentsFromCnCall","str","matches","match","callExpression","args","nonEmptyArgs","arg","argTexts","parent","element","attribute","attr","existing","firstArg","i","argText","argumentTexts","updatedArguments","newClasses","existingParts","call","classNameProp","classNameInitializer","extractCnClassesFromCnCall","cleanCnClassesFromCnCall","applyClassesToCnCall","cnCall","transformStyle","source","transformers","Project","ScriptKind","transformer","SOURCE_LIBRARY","transformLegacyIcons","config","LEGACY_ICON_LIBRARIES","sourceLibrary","targetLibrary","registryIcons","getRegistryIcons","targetedIcons","importDeclaration","specifier","iconName","targetedIcon","SyntaxKind","iconImportDeclaration","icon","_useSemicolon"],"mappings":"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","file":"index.js","sourcesContent":["import postcss from \"postcss\"\nimport selectorParser, {\n type ClassName,\n type Selector as SelectorNodeRoot,\n} from \"postcss-selector-parser\"\nimport { z } from \"zod\"\n\nconst CN_PREFIX = \"cn-\"\n\nexport const styleMapSchema = z.record(\n z.string().startsWith(CN_PREFIX),\n z.string()\n)\n\nexport type StyleMap = z.infer<typeof styleMapSchema>\n\nexport function createStyleMap(input: string) {\n const root = postcss.parse(input)\n\n const result: Record<string, string> = {}\n\n root.walkRules((rule) => {\n const selectors = rule.selectors ?? []\n\n if (selectors.length === 0) {\n return\n }\n\n const tailwindClasses = extractTailwindClasses(rule)\n\n if (!tailwindClasses) {\n return\n }\n\n for (const selector of selectors) {\n const normalizedSelector = normalizeSelector(selector)\n\n selectorParser((selectorsRoot) => {\n selectorsRoot.each((sel) => {\n const targetClass = findSubjectClass(sel)\n\n if (!targetClass) {\n return\n }\n\n const className = targetClass.value\n\n if (!className.startsWith(CN_PREFIX)) {\n return\n }\n\n result[className] = result[className]\n ? `${tailwindClasses} ${result[className]}`\n : tailwindClasses\n })\n }).processSync(normalizedSelector)\n }\n })\n\n return styleMapSchema.parse(result)\n}\n\nfunction normalizeSelector(selector: string) {\n return selector.replace(/\\s*&\\s*/g, \"\").trim()\n}\n\nfunction extractTailwindClasses(rule: postcss.Rule) {\n const classes: string[] = []\n\n for (const node of rule.nodes || []) {\n if (node.type === \"atrule\" && node.name === \"apply\") {\n const value = node.params.trim()\n if (value) {\n classes.push(value)\n }\n }\n }\n\n if (classes.length === 0) {\n return null\n }\n\n return classes.join(\" \")\n}\n\nfunction findSubjectClass(selector: SelectorNodeRoot) {\n const classNodes: ClassName[] = []\n\n selector.walkClasses((classNode) => {\n if (classNode.value.startsWith(CN_PREFIX)) {\n classNodes.push(classNode)\n }\n })\n\n if (classNodes.length === 0) {\n return null\n }\n\n return classNodes[classNodes.length - 1]\n}\n","import { TransformerStyle } from \"@/src/styles/transform\"\nimport {\n Node,\n type CallExpression,\n type NoSubstitutionTemplateLiteral,\n type SourceFile,\n type StringLiteral,\n} from \"ts-morph\"\n\nimport { type StyleMap } from \"./create-style-map\"\n\nfunction isStringLiteralLike(\n node: Node\n): node is StringLiteral | NoSubstitutionTemplateLiteral {\n return (\n Node.isStringLiteral(node) || Node.isNoSubstitutionTemplateLiteral(node)\n )\n}\n\nexport const transformStyleMap: TransformerStyle<SourceFile> = async ({\n sourceFile,\n styleMap,\n}) => {\n const matchedClasses = new Set<string>()\n\n applyToCvaCalls(sourceFile, styleMap, matchedClasses)\n applyToClassNameAttributes(sourceFile, styleMap, matchedClasses)\n applyToMergePropsCalls(sourceFile, styleMap, matchedClasses)\n\n return sourceFile\n}\n\nfunction applyStyleToCvaString(\n stringNode: StringLiteral,\n styleMap: StyleMap,\n matchedClasses: Set<string>\n) {\n const stringValue = stringNode.getLiteralText()\n const cnClasses = extractCnClasses(stringValue)\n\n if (cnClasses.length === 0) {\n return\n }\n\n // Process all cn-* classes, not just the first one\n const unmatchedClasses = cnClasses.filter(\n (cnClass) => !matchedClasses.has(cnClass)\n )\n\n if (unmatchedClasses.length === 0) {\n // All classes already matched, just clean up non-allowlisted ones\n const updated = removeCnClasses(stringValue)\n stringNode.setLiteralValue(updated)\n return\n }\n\n const tailwindClassesToApply = unmatchedClasses\n .map((cnClass) => styleMap[cnClass])\n .filter((classes): classes is string => Boolean(classes))\n\n if (tailwindClassesToApply.length > 0) {\n const mergedClasses = tailwindClassesToApply.join(\" \")\n const updated = removeCnClasses(mergeClasses(mergedClasses, stringValue))\n stringNode.setLiteralValue(updated)\n unmatchedClasses.forEach((cnClass) => matchedClasses.add(cnClass))\n } else {\n // No styles to apply, but still need to clean up non-allowlisted classes\n const updated = removeCnClasses(stringValue)\n stringNode.setLiteralValue(updated)\n }\n}\n\nfunction applyToCvaCalls(\n sourceFile: SourceFile,\n styleMap: StyleMap,\n matchedClasses: Set<string>\n) {\n sourceFile.forEachDescendant((node) => {\n if (!Node.isCallExpression(node)) {\n return\n }\n\n const expression = node.getExpression()\n if (!Node.isIdentifier(expression) || expression.getText() !== \"cva\") {\n return\n }\n\n const baseArg = node.getArguments()[0]\n if (Node.isStringLiteral(baseArg)) {\n applyStyleToCvaString(baseArg, styleMap, matchedClasses)\n }\n\n const configArg = node.getArguments()[1]\n if (!configArg || !Node.isObjectLiteralExpression(configArg)) {\n return\n }\n\n const variantsProp = configArg\n .getProperties()\n .find(\n (prop) =>\n Node.isPropertyAssignment(prop) &&\n Node.isIdentifier(prop.getNameNode()) &&\n prop.getNameNode().getText() === \"variants\"\n )\n\n if (!variantsProp || !Node.isPropertyAssignment(variantsProp)) {\n return\n }\n\n const variantsObj = variantsProp.getInitializer()\n if (!variantsObj || !Node.isObjectLiteralExpression(variantsObj)) {\n return\n }\n\n variantsObj.getProperties().forEach((typeProp) => {\n if (!Node.isPropertyAssignment(typeProp)) {\n return\n }\n\n const typeObj = typeProp.getInitializer()\n if (!typeObj || !Node.isObjectLiteralExpression(typeObj)) {\n return\n }\n\n typeObj.getProperties().forEach((variantProp) => {\n if (!Node.isPropertyAssignment(variantProp)) {\n return\n }\n\n const variantValue = variantProp.getInitializer()\n if (variantValue && Node.isStringLiteral(variantValue)) {\n applyStyleToCvaString(variantValue, styleMap, matchedClasses)\n }\n })\n })\n })\n}\n\nfunction applyToClassNameAttributes(\n sourceFile: SourceFile,\n styleMap: StyleMap,\n matchedClasses: Set<string>\n) {\n sourceFile.forEachDescendant((node) => {\n if (\n !Node.isJsxAttribute(node) ||\n node.getNameNode().getText() !== \"className\"\n ) {\n return\n }\n\n const initializer = node.getInitializer()\n if (!initializer) {\n return\n }\n\n const cnClasses = extractCnClassesFromAttribute(initializer)\n\n if (cnClasses.length === 0) {\n return\n }\n\n const jsxElement = node.getParent()?.getParent()\n if (\n !jsxElement ||\n (!Node.isJsxOpeningElement(jsxElement) &&\n !Node.isJsxSelfClosingElement(jsxElement))\n ) {\n return\n }\n\n const unmatchedClasses = cnClasses.filter(\n (cnClass) => !matchedClasses.has(cnClass)\n )\n\n if (unmatchedClasses.length === 0) {\n // Even if all classes are already matched, we still need to clean them up\n cleanCnClassesFromAttribute(initializer)\n return\n }\n\n const tailwindClassesToApply = unmatchedClasses\n .map((cnClass) => styleMap[cnClass])\n .filter((classes): classes is string => Boolean(classes))\n\n if (tailwindClassesToApply.length > 0) {\n const mergedClasses = tailwindClassesToApply.join(\" \")\n applyClassesToElement(jsxElement, mergedClasses)\n } else {\n cleanCnClassesFromAttribute(initializer)\n }\n })\n}\n\nfunction extractCnClassesFromAttribute(initializer: Node) {\n const classes: string[] = []\n\n if (isStringLiteralLike(initializer)) {\n return extractCnClasses(initializer.getLiteralText())\n }\n\n if (!Node.isJsxExpression(initializer)) {\n return classes\n }\n\n const expression = initializer.getExpression()\n if (!expression) {\n return classes\n }\n\n if (isStringLiteralLike(expression)) {\n return extractCnClasses(expression.getLiteralText())\n }\n\n if (Node.isCallExpression(expression) && isCnCall(expression)) {\n for (const argument of expression.getArguments()) {\n if (isStringLiteralLike(argument)) {\n classes.push(...extractCnClasses(argument.getLiteralText()))\n }\n }\n }\n\n return classes\n}\n\nfunction cleanCnClassesFromAttribute(initializer: Node) {\n if (isStringLiteralLike(initializer)) {\n const cleaned = removeCnClasses(initializer.getLiteralText())\n initializer.setLiteralValue(cleaned)\n return\n }\n\n if (!Node.isJsxExpression(initializer)) {\n return\n }\n\n const expression = initializer.getExpression()\n if (!expression) {\n return\n }\n\n if (isStringLiteralLike(expression)) {\n const cleaned = removeCnClasses(expression.getLiteralText())\n expression.setLiteralValue(cleaned)\n return\n }\n\n if (Node.isCallExpression(expression) && isCnCall(expression)) {\n for (const argument of expression.getArguments()) {\n if (isStringLiteralLike(argument)) {\n const cleaned = removeCnClasses(argument.getLiteralText())\n argument.setLiteralValue(cleaned)\n }\n }\n\n removeEmptyArgumentsFromCnCall(expression)\n }\n}\n\nfunction extractCnClasses(str: string) {\n const matches = str.matchAll(/\\bcn-[\\w-]+\\b/g)\n return Array.from(matches, (match) => match[0])\n}\n\nfunction extractCnClass(str: string) {\n const classes = extractCnClasses(str)\n return classes[0] ?? null\n}\n\nfunction removeCnClasses(str: string) {\n return str\n .replace(/\\bcn-[\\w-]+\\b/g, \"\")\n .replace(/\\s+/g, \" \")\n .trim()\n}\n\nfunction removeEmptyArgumentsFromCnCall(callExpression: CallExpression) {\n if (!isCnCall(callExpression)) {\n return\n }\n\n const args = callExpression.getArguments()\n const nonEmptyArgs = args.filter((arg) => {\n if (isStringLiteralLike(arg)) {\n const text = arg.getLiteralText().trim()\n return text !== \"\"\n }\n return true\n })\n\n if (nonEmptyArgs.length !== args.length) {\n const argTexts = nonEmptyArgs.map((arg) => arg.getText())\n const parent = callExpression.getParent()\n if (parent && Node.isJsxExpression(parent)) {\n parent.replaceWithText(`{cn(${argTexts.join(\", \")})}`)\n } else {\n callExpression.replaceWithText(`cn(${argTexts.join(\", \")})`)\n }\n }\n}\n\nfunction applyClassesToElement(element: Node, tailwindClasses: string) {\n if (\n !Node.isJsxOpeningElement(element) &&\n !Node.isJsxSelfClosingElement(element)\n ) {\n return\n }\n\n const attribute = element\n .getAttributes()\n .find(\n (attr) =>\n Node.isJsxAttribute(attr) &&\n attr.getNameNode().getText() === \"className\"\n )\n\n if (!attribute || !Node.isJsxAttribute(attribute)) {\n element.addAttribute({\n name: \"className\",\n initializer: `{cn(${JSON.stringify(tailwindClasses)})}`,\n })\n return\n }\n\n const initializer = attribute.getInitializer()\n\n if (!initializer) {\n attribute.setInitializer(`{cn(${JSON.stringify(tailwindClasses)})}`)\n return\n }\n\n if (isStringLiteralLike(initializer)) {\n const existing = initializer.getLiteralText()\n const updated = removeCnClasses(mergeClasses(tailwindClasses, existing))\n initializer.setLiteralValue(updated)\n return\n }\n\n if (!Node.isJsxExpression(initializer)) {\n return\n }\n\n const expression = initializer.getExpression()\n\n if (!expression) {\n attribute.setInitializer(`{cn(${JSON.stringify(tailwindClasses)})}`)\n return\n }\n\n if (isStringLiteralLike(expression)) {\n const existing = expression.getLiteralText()\n const updated = removeCnClasses(mergeClasses(tailwindClasses, existing))\n expression.setLiteralValue(updated)\n return\n }\n\n if (Node.isCallExpression(expression) && isCnCall(expression)) {\n const firstArg = expression.getArguments()[0]\n if (isStringLiteralLike(firstArg)) {\n const existing = firstArg.getLiteralText()\n const updated = removeCnClasses(mergeClasses(tailwindClasses, existing))\n firstArg.setLiteralValue(updated)\n\n for (let i = 1; i < expression.getArguments().length; i++) {\n const arg = expression.getArguments()[i]\n if (isStringLiteralLike(arg)) {\n const argText = arg.getLiteralText()\n const cleaned = removeCnClasses(argText)\n if (cleaned !== argText) {\n arg.setLiteralValue(cleaned)\n }\n }\n }\n\n removeEmptyArgumentsFromCnCall(expression)\n return\n }\n\n const argumentTexts = expression\n .getArguments()\n .map((argument) => {\n if (isStringLiteralLike(argument)) {\n const cleaned = removeCnClasses(argument.getLiteralText())\n return cleaned ? JSON.stringify(cleaned) : null\n }\n return argument.getText()\n })\n .filter((arg): arg is string => arg !== null)\n\n const updatedArguments = [JSON.stringify(tailwindClasses), ...argumentTexts]\n\n attribute.setInitializer(`{cn(${updatedArguments.join(\", \")})}`)\n return\n }\n\n attribute.setInitializer(\n `{cn(${JSON.stringify(tailwindClasses)}, ${expression.getText()})}`\n )\n}\n\nfunction mergeClasses(newClasses: string, existing: string) {\n const existingParts = existing.split(/\\s+/).filter(Boolean)\n const newParts = newClasses.split(/\\s+/).filter(Boolean)\n const combined = [...newParts, ...existingParts]\n return combined.join(\" \").trim()\n}\n\nfunction isCnCall(call: CallExpression) {\n const expression = call.getExpression()\n return Node.isIdentifier(expression) && expression.getText() === \"cn\"\n}\n\nfunction applyToMergePropsCalls(\n sourceFile: SourceFile,\n styleMap: StyleMap,\n matchedClasses: Set<string>\n) {\n sourceFile.forEachDescendant((node) => {\n if (!Node.isCallExpression(node)) {\n return\n }\n\n const expression = node.getExpression()\n if (\n !Node.isIdentifier(expression) ||\n expression.getText() !== \"mergeProps\"\n ) {\n return\n }\n\n // Look for object literals in mergeProps arguments\n for (const arg of node.getArguments()) {\n if (!Node.isObjectLiteralExpression(arg)) {\n continue\n }\n\n // Find className property in the object literal\n const classNameProp = arg\n .getProperties()\n .find(\n (prop) =>\n Node.isPropertyAssignment(prop) &&\n Node.isIdentifier(prop.getNameNode()) &&\n prop.getNameNode().getText() === \"className\"\n )\n\n if (!classNameProp || !Node.isPropertyAssignment(classNameProp)) {\n continue\n }\n\n const classNameInitializer = classNameProp.getInitializer()\n if (!classNameInitializer) {\n continue\n }\n\n // Handle cn() calls in className\n if (\n Node.isCallExpression(classNameInitializer) &&\n isCnCall(classNameInitializer)\n ) {\n const cnClasses = extractCnClassesFromCnCall(classNameInitializer)\n\n if (cnClasses.length === 0) {\n continue\n }\n\n const unmatchedClasses = cnClasses.filter(\n (cnClass) => !matchedClasses.has(cnClass)\n )\n\n if (unmatchedClasses.length === 0) {\n // Clean up cn-* classes even if already matched\n cleanCnClassesFromCnCall(classNameInitializer)\n continue\n }\n\n const tailwindClassesToApply = unmatchedClasses\n .map((cnClass) => styleMap[cnClass])\n .filter((classes): classes is string => Boolean(classes))\n\n if (tailwindClassesToApply.length > 0) {\n const mergedClasses = tailwindClassesToApply.join(\" \")\n applyClassesToCnCall(\n classNameInitializer,\n mergedClasses,\n matchedClasses,\n unmatchedClasses\n )\n } else {\n cleanCnClassesFromCnCall(classNameInitializer)\n }\n }\n }\n })\n}\n\nfunction extractCnClassesFromCnCall(cnCall: CallExpression): string[] {\n const classes: string[] = []\n\n for (const argument of cnCall.getArguments()) {\n if (isStringLiteralLike(argument)) {\n classes.push(...extractCnClasses(argument.getLiteralText()))\n }\n }\n\n return classes\n}\n\nfunction cleanCnClassesFromCnCall(cnCall: CallExpression) {\n for (const argument of cnCall.getArguments()) {\n if (isStringLiteralLike(argument)) {\n const cleaned = removeCnClasses(argument.getLiteralText())\n argument.setLiteralValue(cleaned)\n }\n }\n\n removeEmptyArgumentsFromCnCall(cnCall)\n}\n\nfunction applyClassesToCnCall(\n cnCall: CallExpression,\n tailwindClasses: string,\n matchedClasses: Set<string>,\n unmatchedClasses: string[]\n) {\n const firstArg = cnCall.getArguments()[0]\n\n if (isStringLiteralLike(firstArg)) {\n const existing = firstArg.getLiteralText()\n const updated = removeCnClasses(mergeClasses(tailwindClasses, existing))\n firstArg.setLiteralValue(updated)\n\n // Mark classes as matched\n unmatchedClasses.forEach((cnClass) => matchedClasses.add(cnClass))\n\n // Clean up cn-* classes from remaining arguments\n for (let i = 1; i < cnCall.getArguments().length; i++) {\n const arg = cnCall.getArguments()[i]\n if (isStringLiteralLike(arg)) {\n const argText = arg.getLiteralText()\n const cleaned = removeCnClasses(argText)\n if (cleaned !== argText) {\n arg.setLiteralValue(cleaned)\n }\n }\n }\n\n removeEmptyArgumentsFromCnCall(cnCall)\n return\n }\n\n // If first arg is not a string literal, prepend tailwind classes\n const argumentTexts = cnCall\n .getArguments()\n .map((argument) => {\n if (isStringLiteralLike(argument)) {\n const cleaned = removeCnClasses(argument.getLiteralText())\n return cleaned ? JSON.stringify(cleaned) : null\n }\n return argument.getText()\n })\n .filter((arg): arg is string => arg !== null)\n\n const updatedArguments = [JSON.stringify(tailwindClasses), ...argumentTexts]\n\n // Mark classes as matched\n unmatchedClasses.forEach((cnClass) => matchedClasses.add(cnClass))\n\n const parent = cnCall.getParent()\n if (parent) {\n cnCall.replaceWithText(`cn(${updatedArguments.join(\", \")})`)\n }\n}\n","import { Project, ScriptKind, type SourceFile } from \"ts-morph\"\n\nimport { type StyleMap } from \"./create-style-map\"\nimport { transformStyleMap } from \"./transform-style-map\"\n\nexport type TransformerStyle<Output = SourceFile> = (opts: {\n sourceFile: SourceFile\n styleMap: StyleMap\n}) => Promise<Output>\n\nexport async function transformStyle(\n source: string,\n {\n styleMap,\n transformers = [transformStyleMap],\n }: {\n styleMap: StyleMap\n transformers?: TransformerStyle<SourceFile>[]\n }\n) {\n const project = new Project({\n useInMemoryFileSystem: true,\n })\n\n const sourceFile = project.createSourceFile(\"component.tsx\", source, {\n scriptKind: ScriptKind.TSX,\n overwrite: true,\n })\n\n for (const transformer of transformers) {\n await transformer({ sourceFile, styleMap })\n }\n\n return sourceFile.getText()\n}\n","import { getRegistryIcons } from \"@/src/registry/api\"\nimport { LEGACY_ICON_LIBRARIES } from \"@/src/utils/legacy-icon-libraries\"\nimport { Transformer } from \"@/src/utils/transformers\"\nimport { SourceFile, SyntaxKind } from \"ts-morph\"\n\n// Lucide is the default icon library in the registry.\nconst SOURCE_LIBRARY = \"lucide\"\n\nexport const transformLegacyIcons: Transformer = async ({\n sourceFile,\n config,\n}) => {\n // No transform if we cannot read the icon library.\n if (!config.iconLibrary || !(config.iconLibrary in LEGACY_ICON_LIBRARIES)) {\n return sourceFile\n }\n\n const sourceLibrary = SOURCE_LIBRARY\n const targetLibrary = config.iconLibrary\n\n if (sourceLibrary === targetLibrary) {\n return sourceFile\n }\n\n const registryIcons = await getRegistryIcons()\n\n let targetedIcons: string[] = []\n for (const importDeclaration of sourceFile.getImportDeclarations() ?? []) {\n if (\n importDeclaration.getModuleSpecifier()?.getText() !==\n `\"${LEGACY_ICON_LIBRARIES[SOURCE_LIBRARY].import}\"`\n ) {\n continue\n }\n\n for (const specifier of importDeclaration.getNamedImports() ?? []) {\n const iconName = specifier.getName()\n\n const targetedIcon = registryIcons[iconName]?.[targetLibrary]\n\n if (!targetedIcon || targetedIcons.includes(targetedIcon)) {\n continue\n }\n\n targetedIcons.push(targetedIcon)\n\n // Remove the named import.\n specifier.remove()\n\n // Replace with the targeted icon.\n sourceFile\n .getDescendantsOfKind(SyntaxKind.JsxSelfClosingElement)\n .filter((node) => node.getTagNameNode()?.getText() === iconName)\n .forEach((node) => node.getTagNameNode()?.replaceWithText(targetedIcon))\n }\n\n // If the named import is empty, remove the import declaration.\n if (importDeclaration.getNamedImports()?.length === 0) {\n importDeclaration.remove()\n }\n }\n\n if (targetedIcons.length > 0) {\n const iconImportDeclaration = sourceFile.addImportDeclaration({\n moduleSpecifier:\n LEGACY_ICON_LIBRARIES[\n targetLibrary as keyof typeof LEGACY_ICON_LIBRARIES\n ]?.import,\n namedImports: targetedIcons.map((icon) => ({\n name: icon,\n })),\n })\n\n if (!_useSemicolon(sourceFile)) {\n iconImportDeclaration.replaceWithText(\n iconImportDeclaration.getText().replace(\";\", \"\")\n )\n }\n }\n\n return sourceFile\n}\n\nfunction _useSemicolon(sourceFile: SourceFile) {\n return (\n sourceFile.getImportDeclarations()?.[0]?.getText().endsWith(\";\") ?? false\n )\n}\n"]}
|