@dowel-ui/registry 0.7.0 → 0.8.0
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/build.js +2382 -355
- package/dist/build.js.map +1 -1
- package/dist/generate.d.ts.map +1 -1
- package/dist/generate.js +238 -12
- package/dist/generate.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/agent-docs.ts +4 -1
- package/src/generate.ts +120 -11
package/dist/generate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.d.ts","names":[],"sources":["../src/generate.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"generate.d.ts","names":[],"sources":["../src/generate.ts"],"mappings":";;UAsQiB;EACf,OAAO;;EAEP;;UAGe;;EAEf;;EAEA,QAAQ;;EAER,YAAY;;EAEZ;;EAEA;;UA8Ge;;EAEf;;EAEA;;iBAGc,OACd,gBACA,OAAO,eACP,UAAS,cACR;UAkEc;;EAEf;;;;;;;;;;EAUA;EACA;EACA;;;;;;;;;iBAUc,cAAc;;;;;;;;;iBAgBd,WAAW,MAAM,QAAQ,UAAS;;;;;;;;;iBAuDlC,YAAY,MAAM,QAAQ,UAAS"}
|
package/dist/generate.js
CHANGED
|
@@ -108,28 +108,67 @@ const SYNONYMS = {
|
|
|
108
108
|
invoices: ["billing"],
|
|
109
109
|
payment: ["billing"],
|
|
110
110
|
plan: ["pricing", "billing"],
|
|
111
|
-
plans: [
|
|
111
|
+
plans: [
|
|
112
|
+
"pricing",
|
|
113
|
+
"pricing-three-tier",
|
|
114
|
+
"pricing-two-tier",
|
|
115
|
+
"pricing-single-plan"
|
|
116
|
+
],
|
|
112
117
|
metrics: [
|
|
113
118
|
"analytics",
|
|
114
119
|
"dashboard",
|
|
115
120
|
"metric-delta"
|
|
116
121
|
],
|
|
117
|
-
chart: [
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
122
|
+
chart: [
|
|
123
|
+
"analytics",
|
|
124
|
+
"dither-bar",
|
|
125
|
+
"dither-line",
|
|
126
|
+
"dither-area",
|
|
127
|
+
"dither-donut"
|
|
128
|
+
],
|
|
129
|
+
charts: [
|
|
130
|
+
"analytics",
|
|
131
|
+
"dither-canvas",
|
|
132
|
+
"dither-bar",
|
|
133
|
+
"dither-line",
|
|
134
|
+
"dither-area",
|
|
135
|
+
"dither-donut",
|
|
136
|
+
"dither-heatmap"
|
|
137
|
+
],
|
|
138
|
+
graph: [
|
|
139
|
+
"analytics",
|
|
140
|
+
"dither-line",
|
|
141
|
+
"dither-area",
|
|
142
|
+
"contribution-graph"
|
|
143
|
+
],
|
|
144
|
+
stats: [
|
|
145
|
+
"dashboard",
|
|
146
|
+
"analytics",
|
|
147
|
+
"stats-grid",
|
|
148
|
+
"stats-trend-cards"
|
|
149
|
+
],
|
|
121
150
|
overview: ["dashboard"],
|
|
122
151
|
grid: ["data-table", "table"],
|
|
123
152
|
spreadsheet: ["data-table"],
|
|
124
153
|
list: ["table", "data-table"],
|
|
125
|
-
search: [
|
|
126
|
-
|
|
154
|
+
search: [
|
|
155
|
+
"command",
|
|
156
|
+
"combobox",
|
|
157
|
+
"expanding-search",
|
|
158
|
+
"faq-searchable"
|
|
159
|
+
],
|
|
160
|
+
palette: ["command", "palette-generator"],
|
|
127
161
|
shortcut: ["command", "shortcut-recorder"],
|
|
128
162
|
modal: ["dialog"],
|
|
129
163
|
popup: ["dialog", "popover"],
|
|
130
164
|
dropdown: ["dropdown-menu", "select"],
|
|
131
165
|
toast: ["toast"],
|
|
132
|
-
notification: [
|
|
166
|
+
notification: [
|
|
167
|
+
"toast",
|
|
168
|
+
"activity-feed",
|
|
169
|
+
"notification-badge",
|
|
170
|
+
"notify-button"
|
|
171
|
+
],
|
|
133
172
|
notifications: ["toast", "settings"],
|
|
134
173
|
upload: ["file-upload"],
|
|
135
174
|
file: ["file-upload"],
|
|
@@ -137,7 +176,12 @@ const SYNONYMS = {
|
|
|
137
176
|
time: ["time-range-picker"],
|
|
138
177
|
schedule: ["cron-editor"],
|
|
139
178
|
cron: ["cron-editor"],
|
|
140
|
-
team: [
|
|
179
|
+
team: [
|
|
180
|
+
"admin-users",
|
|
181
|
+
"settings",
|
|
182
|
+
"team-grid",
|
|
183
|
+
"team-carousel"
|
|
184
|
+
],
|
|
141
185
|
members: ["admin-users"],
|
|
142
186
|
users: ["admin-users"],
|
|
143
187
|
admin: ["admin-users"],
|
|
@@ -147,15 +191,197 @@ const SYNONYMS = {
|
|
|
147
191
|
preferences: ["settings"],
|
|
148
192
|
account: ["settings", "billing"],
|
|
149
193
|
setup: ["onboarding"],
|
|
150
|
-
checklist: [
|
|
151
|
-
|
|
194
|
+
checklist: [
|
|
195
|
+
"onboarding",
|
|
196
|
+
"animated-checklist",
|
|
197
|
+
"todo-tower"
|
|
198
|
+
],
|
|
199
|
+
wizard: ["onboarding", "stepper"],
|
|
152
200
|
logs: ["log-viewer"],
|
|
153
201
|
log: ["log-viewer"],
|
|
154
202
|
diff: ["diff-viewer", "record-diff"],
|
|
155
203
|
secret: ["secret-field"],
|
|
156
204
|
"api key": ["secret-field"],
|
|
157
205
|
key: ["secret-field"],
|
|
158
|
-
dns: ["dns-record"]
|
|
206
|
+
dns: ["dns-record"],
|
|
207
|
+
loader: [
|
|
208
|
+
"spinner",
|
|
209
|
+
"dots-loader",
|
|
210
|
+
"ring-loader",
|
|
211
|
+
"bar-loader",
|
|
212
|
+
"shape-loader",
|
|
213
|
+
"text-loader",
|
|
214
|
+
"grid-loader",
|
|
215
|
+
"ai-loader"
|
|
216
|
+
],
|
|
217
|
+
loaders: [
|
|
218
|
+
"dots-loader",
|
|
219
|
+
"ring-loader",
|
|
220
|
+
"bar-loader",
|
|
221
|
+
"shape-loader",
|
|
222
|
+
"text-loader",
|
|
223
|
+
"grid-loader"
|
|
224
|
+
],
|
|
225
|
+
loading: [
|
|
226
|
+
"spinner",
|
|
227
|
+
"dots-loader",
|
|
228
|
+
"ring-loader",
|
|
229
|
+
"bar-loader",
|
|
230
|
+
"skeleton",
|
|
231
|
+
"text-loader"
|
|
232
|
+
],
|
|
233
|
+
spinner: ["spinner", "ring-loader"],
|
|
234
|
+
animation: [
|
|
235
|
+
"text-effect",
|
|
236
|
+
"text-swap",
|
|
237
|
+
"shader-transition"
|
|
238
|
+
],
|
|
239
|
+
animated: [
|
|
240
|
+
"text-effect",
|
|
241
|
+
"morph-button",
|
|
242
|
+
"effect-button",
|
|
243
|
+
"number-flow"
|
|
244
|
+
],
|
|
245
|
+
"text animation": [
|
|
246
|
+
"text-effect",
|
|
247
|
+
"text-swap",
|
|
248
|
+
"shimmer-text",
|
|
249
|
+
"scramble-text",
|
|
250
|
+
"typewriter-text"
|
|
251
|
+
],
|
|
252
|
+
typewriter: ["typewriter-text"],
|
|
253
|
+
shimmer: ["shimmer-text", "skeleton"],
|
|
254
|
+
counter: ["number-flow", "drag-stepper"],
|
|
255
|
+
price: ["number-flow", "pricing"],
|
|
256
|
+
carousel: [
|
|
257
|
+
"carousel-3d",
|
|
258
|
+
"swipe-carousel",
|
|
259
|
+
"reviews-carousel",
|
|
260
|
+
"invite-carousel",
|
|
261
|
+
"time-stack"
|
|
262
|
+
],
|
|
263
|
+
slider: [
|
|
264
|
+
"slider",
|
|
265
|
+
"exposure-slider",
|
|
266
|
+
"slosh-slider",
|
|
267
|
+
"scrubber",
|
|
268
|
+
"range-dial"
|
|
269
|
+
],
|
|
270
|
+
slideshow: [
|
|
271
|
+
"carousel-3d",
|
|
272
|
+
"swipe-carousel",
|
|
273
|
+
"photo-stack"
|
|
274
|
+
],
|
|
275
|
+
marquee: ["marquee", "logo-marquee"],
|
|
276
|
+
ticker: ["marquee"],
|
|
277
|
+
cards: [
|
|
278
|
+
"card",
|
|
279
|
+
"card-spread",
|
|
280
|
+
"card-stack",
|
|
281
|
+
"glow-card",
|
|
282
|
+
"tilt-card",
|
|
283
|
+
"expandable-cards"
|
|
284
|
+
],
|
|
285
|
+
hero: [
|
|
286
|
+
"hero-grid",
|
|
287
|
+
"hero-product",
|
|
288
|
+
"hero-split-image",
|
|
289
|
+
"hero-perspective-grid",
|
|
290
|
+
"hero-spotlight",
|
|
291
|
+
"hero-minimal"
|
|
292
|
+
],
|
|
293
|
+
landing: [
|
|
294
|
+
"hero-grid",
|
|
295
|
+
"features-bento",
|
|
296
|
+
"cta-centered",
|
|
297
|
+
"footer-newsletter"
|
|
298
|
+
],
|
|
299
|
+
cta: [
|
|
300
|
+
"cta-centered",
|
|
301
|
+
"cta-split-image",
|
|
302
|
+
"cta-banner"
|
|
303
|
+
],
|
|
304
|
+
"call to action": [
|
|
305
|
+
"cta-centered",
|
|
306
|
+
"cta-split-image",
|
|
307
|
+
"cta-banner"
|
|
308
|
+
],
|
|
309
|
+
features: [
|
|
310
|
+
"features-icon-grid",
|
|
311
|
+
"features-bento",
|
|
312
|
+
"features-alternating"
|
|
313
|
+
],
|
|
314
|
+
logos: [
|
|
315
|
+
"logo-cloud-simple",
|
|
316
|
+
"logo-marquee",
|
|
317
|
+
"logo-links-marquee",
|
|
318
|
+
"logo-grid-tooltips"
|
|
319
|
+
],
|
|
320
|
+
testimonials: [
|
|
321
|
+
"testimonial-rotator",
|
|
322
|
+
"testimonial-spotlight",
|
|
323
|
+
"testimonial-star-grid",
|
|
324
|
+
"reviews-carousel"
|
|
325
|
+
],
|
|
326
|
+
reviews: ["reviews-carousel", "testimonial-star-grid"],
|
|
327
|
+
faq: [
|
|
328
|
+
"faq-accordion",
|
|
329
|
+
"faq-searchable",
|
|
330
|
+
"faq-categorized",
|
|
331
|
+
"faq-tabbed-grid"
|
|
332
|
+
],
|
|
333
|
+
footer: [
|
|
334
|
+
"footer-simple",
|
|
335
|
+
"footer-newsletter",
|
|
336
|
+
"footer-mega",
|
|
337
|
+
"footer-minimal"
|
|
338
|
+
],
|
|
339
|
+
newsletter: ["footer-newsletter", "footer-mega"],
|
|
340
|
+
heatmap: ["dither-heatmap", "contribution-graph"],
|
|
341
|
+
donut: ["dither-donut"],
|
|
342
|
+
pie: ["dither-donut"],
|
|
343
|
+
gauge: ["dither-gauge", "meter"],
|
|
344
|
+
funnel: ["dither-funnel"],
|
|
345
|
+
uptime: ["uptime-matrix"],
|
|
346
|
+
"status page": ["uptime-matrix"],
|
|
347
|
+
otp: ["otp-input"],
|
|
348
|
+
"one-time code": ["otp-input"],
|
|
349
|
+
"verification code": ["otp-input"],
|
|
350
|
+
steps: ["stepper"],
|
|
351
|
+
"context menu": ["context-menu"],
|
|
352
|
+
"right click": ["context-menu"],
|
|
353
|
+
reorder: ["reorder-list", "browser-tabs"],
|
|
354
|
+
sortable: ["reorder-list"],
|
|
355
|
+
drag: [
|
|
356
|
+
"reorder-list",
|
|
357
|
+
"goo-ball",
|
|
358
|
+
"swipe-carousel"
|
|
359
|
+
],
|
|
360
|
+
dock: ["magnify-dock"],
|
|
361
|
+
toolbar: ["canvas-toolbar", "magnify-dock"],
|
|
362
|
+
confirm: [
|
|
363
|
+
"slide-to-confirm",
|
|
364
|
+
"inline-confirm",
|
|
365
|
+
"confirm-typed"
|
|
366
|
+
],
|
|
367
|
+
delete: ["inline-confirm", "confirm-typed"],
|
|
368
|
+
toggle: ["switch", "liquid-toggle"],
|
|
369
|
+
copy: ["copy-button"],
|
|
370
|
+
clipboard: ["copy-button"],
|
|
371
|
+
refresh: ["pull-to-refresh"],
|
|
372
|
+
music: ["now-playing"],
|
|
373
|
+
player: ["now-playing"],
|
|
374
|
+
orb: ["gradient-orb", "orb-face"],
|
|
375
|
+
transition: ["shader-transition", "text-swap"],
|
|
376
|
+
badge: ["badge", "notification-badge"],
|
|
377
|
+
avatar: [
|
|
378
|
+
"avatar",
|
|
379
|
+
"avatar-group",
|
|
380
|
+
"pixel-avatar"
|
|
381
|
+
],
|
|
382
|
+
tweet: ["tweet-card"],
|
|
383
|
+
dial: ["dial", "range-dial"],
|
|
384
|
+
knob: ["dial"]
|
|
159
385
|
};
|
|
160
386
|
function normalise(prompt) {
|
|
161
387
|
return prompt.toLowerCase().replace(/[^a-z0-9\s-]/g, " ");
|
package/dist/generate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.js","names":[],"sources":["../src/generate.ts"],"sourcesContent":["import type { RegistryIndex, RegistryIndexEntry } from \"./schema\";\n\nexport type { RegistryIndex, RegistryIndexEntry } from \"./schema\";\n\n/**\n * Turning a description of a screen into a plan made of components that exist.\n *\n * The hard part of generating UI is not writing JSX. It is not inventing: a\n * model asked for a billing page will cheerfully produce `<PricingTable>` and\n * `<InvoiceList>` and a `variant=\"subtle\"` that was never implemented, and the\n * result reads perfectly and compiles nowhere.\n *\n * So this resolves a prompt against the registry first, and everything it\n * emits afterwards is drawn from what came back. It cannot name a component\n * that is not installable, because it only ever repeats names the registry\n * gave it.\n *\n * It does not guess at props. The registry publishes what a component *is* and\n * what it depends on, not the shape of its arguments, so the output stops at\n * the composition and points at the page where the props are documented.\n * Emitting a plausible prop is worse than emitting none — one is a gap, the\n * other is a bug that looks like working code.\n */\n\n/** Words that carry no signal about which component is wanted. */\nconst STOPWORDS = new Set([\n \"a\",\n \"an\",\n \"the\",\n \"and\",\n \"or\",\n \"of\",\n \"for\",\n \"with\",\n \"to\",\n \"in\",\n \"on\",\n \"at\",\n \"by\",\n \"is\",\n \"are\",\n \"be\",\n \"make\",\n \"build\",\n \"create\",\n \"want\",\n \"need\",\n \"add\",\n \"show\",\n \"page\",\n \"screen\",\n \"app\",\n \"application\",\n \"ui\",\n \"interface\",\n \"component\",\n \"components\",\n \"me\",\n \"my\",\n \"our\",\n \"i\",\n \"it\",\n \"that\",\n \"this\",\n \"some\",\n \"using\",\n \"use\",\n \"like\",\n]);\n\n/**\n * Words a reader would use that are not the words the registry uses.\n *\n * Hand-written, and deliberately so. \"Sign in\" is what someone types and\n * `login` is what the item is called; no amount of string similarity bridges\n * that, and pretending otherwise produces a matcher that works on the examples\n * it was tuned against and nothing else.\n */\nconst SYNONYMS: Record<string, string[]> = {\n \"sign in\": [\"login\"],\n signin: [\"login\"],\n \"log in\": [\"login\"],\n \"sign up\": [\"signup\"],\n register: [\"signup\"],\n registration: [\"signup\"],\n \"forgot password\": [\"forgot-password\"],\n \"reset password\": [\"forgot-password\"],\n chat: [\"ai-chat\", \"ai-conversation\", \"ai-prompt-input\"],\n conversation: [\"ai-chat\"],\n assistant: [\"ai-chat\"],\n copilot: [\"ai-chat\"],\n agent: [\"agent-console\", \"ai-agent-status\", \"ai-agent-plan\"],\n agents: [\"agent-console\"],\n tool: [\"ai-tool\"],\n approval: [\"ai-approval-request\"],\n approve: [\"ai-approval-request\"],\n undo: [\"ai-action-ledger\"],\n audit: [\"ai-action-ledger\", \"activity-feed\"],\n tokens: [\"ai-token-usage\"],\n spend: [\"ai-dashboard\", \"billing\"],\n cost: [\"ai-dashboard\", \"billing\"],\n usage: [\"ai-dashboard\", \"billing\"],\n subscription: [\"billing\", \"pricing\"],\n invoice: [\"billing\"],\n invoices: [\"billing\"],\n payment: [\"billing\"],\n plan: [\"pricing\", \"billing\"],\n plans: [\"pricing\"],\n metrics: [\"analytics\", \"dashboard\", \"metric-delta\"],\n chart: [\"analytics\"],\n charts: [\"analytics\"],\n graph: [\"analytics\"],\n stats: [\"dashboard\", \"analytics\"],\n overview: [\"dashboard\"],\n grid: [\"data-table\", \"table\"],\n spreadsheet: [\"data-table\"],\n list: [\"table\", \"data-table\"],\n search: [\"command\", \"combobox\"],\n palette: [\"command\"],\n shortcut: [\"command\", \"shortcut-recorder\"],\n modal: [\"dialog\"],\n popup: [\"dialog\", \"popover\"],\n dropdown: [\"dropdown-menu\", \"select\"],\n toast: [\"toast\"],\n notification: [\"toast\", \"activity-feed\"],\n notifications: [\"toast\", \"settings\"],\n upload: [\"file-upload\"],\n file: [\"file-upload\"],\n date: [\"date-picker\", \"calendar\"],\n time: [\"time-range-picker\"],\n schedule: [\"cron-editor\"],\n cron: [\"cron-editor\"],\n team: [\"admin-users\", \"settings\"],\n members: [\"admin-users\"],\n users: [\"admin-users\"],\n admin: [\"admin-users\"],\n permissions: [\"permission-matrix\"],\n roles: [\"permission-matrix\"],\n profile: [\"settings\"],\n preferences: [\"settings\"],\n account: [\"settings\", \"billing\"],\n setup: [\"onboarding\"],\n checklist: [\"onboarding\"],\n wizard: [\"onboarding\"],\n logs: [\"log-viewer\"],\n log: [\"log-viewer\"],\n diff: [\"diff-viewer\", \"record-diff\"],\n secret: [\"secret-field\"],\n \"api key\": [\"secret-field\"],\n key: [\"secret-field\"],\n dns: [\"dns-record\"],\n};\n\nexport interface PlanEntry {\n entry: RegistryIndexEntry;\n /** Why this was chosen, in words, so a wrong pick is arguable. */\n because: string;\n}\n\nexport interface UiPlan {\n /** The prompt, as given. */\n prompt: string;\n /** Whole sections, which bring their own components. */\n blocks: PlanEntry[];\n /** Individual components, none of which a chosen block already installs. */\n components: PlanEntry[];\n /** Everything to install, in one list. */\n install: string[];\n /** True when nothing matched, so callers can say so rather than emit nothing. */\n empty: boolean;\n}\n\nfunction normalise(prompt: string): string {\n return prompt.toLowerCase().replace(/[^a-z0-9\\s-]/g, \" \");\n}\n\nfunction words(prompt: string): string[] {\n return normalise(prompt)\n .split(/\\s+/)\n .filter((word) => word.length > 2 && !STOPWORDS.has(word));\n}\n\ninterface SynonymMatch {\n /** Item name to the phrase that selected it. */\n hits: Map<string, string>;\n /**\n * Words the table has already spoken for.\n *\n * Excluded from generic term matching afterwards. The table exists to say\n * that \"plan\" means pricing or billing; letting the generic matcher also\n * score every item with \"plan\" in its name puts `ai-agent-plan` on a billing\n * page and re-introduces exactly the ambiguity the table resolves.\n */\n consumed: Set<string>;\n}\n\nfunction synonymHits(prompt: string): SynonymMatch {\n const text = normalise(prompt);\n const hits = new Map<string, string>();\n const consumed = new Set<string>();\n\n for (const [phrase, names] of Object.entries(SYNONYMS)) {\n // Word-boundary matched, so \"keyboard\" does not trigger \"key\".\n const pattern = new RegExp(`(^|\\\\s)${phrase.replace(/\\s+/g, \"\\\\s+\")}(\\\\s|$)`);\n if (!pattern.test(text)) continue;\n\n for (const word of phrase.split(/\\s+/)) consumed.add(word);\n for (const name of names) {\n if (!hits.has(name)) hits.set(name, phrase);\n }\n }\n\n return { hits, consumed };\n}\n\n/** Below this a match is coincidence rather than intent. */\nconst MINIMUM_SCORE = 20;\n\ninterface Scored {\n entry: RegistryIndexEntry;\n /** What the prompt actually matched. Decides whether it qualifies at all. */\n score: number;\n /** Score plus the block preference. Decides order only. */\n rank: number;\n because: string;\n}\n\nfunction scoreEntry(\n entry: RegistryIndexEntry,\n terms: string[],\n synonyms: Map<string, string>,\n): Scored | undefined {\n const name = entry.name.toLowerCase();\n const title = entry.title.toLowerCase();\n const description = entry.description.toLowerCase();\n\n let score = 0;\n const reasons: string[] = [];\n\n const synonym = synonyms.get(entry.name);\n if (synonym) {\n score += 60;\n reasons.push(`\"${synonym}\"`);\n }\n\n for (const term of terms) {\n if (name === term) {\n score += 50;\n reasons.push(`named \"${term}\"`);\n } else if (name.split(\"-\").includes(term)) {\n score += 30;\n reasons.push(`\"${term}\" in its name`);\n } else if (title.includes(term)) {\n score += 20;\n reasons.push(`\"${term}\" in its title`);\n } else if (entry.category === term) {\n score += 12;\n reasons.push(`the ${term} category`);\n } else if (description.includes(term)) {\n score += 8;\n reasons.push(`\"${term}\" in its description`);\n }\n }\n\n if (score === 0) return undefined;\n\n // A block covers more of an intent than a component does, and installing one\n // brings the components anyway — so where both match, the block is the better\n // answer rather than merely an equal one.\n //\n // Kept out of `score` on purpose. Added there it would lift a block over the\n // qualifying floor on a description-only brush, which is how `ai-dashboard`\n // ended up recommended for an agent console because its prose contains the\n // word \"run\". A preference should order real matches, not manufacture one.\n const rank = score + (entry.type === \"registry:block\" ? 25 : 0);\n\n return { entry, score, rank, because: [...new Set(reasons)].slice(0, 3).join(\", \") };\n}\n\nexport interface PlanOptions {\n /** How many components to suggest beyond the blocks. */\n maxComponents?: number;\n /** How many blocks to suggest. */\n maxBlocks?: number;\n}\n\nexport function planUi(\n prompt: string,\n index: RegistryIndex,\n options: PlanOptions = {},\n): UiPlan {\n const { maxBlocks = 3, maxComponents = 6 } = options;\n\n const { hits: synonyms, consumed } = synonymHits(prompt);\n const terms = words(prompt).filter((term) => !consumed.has(term));\n\n const scored = index.items\n .filter((entry) => entry.type === \"registry:ui\" || entry.type === \"registry:block\")\n .map((entry) => scoreEntry(entry, terms, synonyms))\n .filter((candidate): candidate is Scored => candidate !== undefined)\n // A description-only brush (8) or a bare category hit (12) is not enough on\n // its own. Suggesting six components because the prompt shares a common\n // word with their prose makes the plan look like more work than it is, and\n // buries the ones that actually matched.\n .filter((candidate) => candidate.score >= MINIMUM_SCORE)\n .sort((a, b) => b.rank - a.rank || a.entry.name.localeCompare(b.entry.name));\n\n const blocks = scored\n .filter((candidate) => candidate.entry.type === \"registry:block\")\n .slice(0, maxBlocks);\n\n // Anything a chosen block already installs is not a separate suggestion:\n // listing Button beside a Dashboard that brings it is noise that makes the\n // plan look longer than the work.\n const covered = new Set(\n blocks.flatMap((candidate) => [\n candidate.entry.name,\n ...candidate.entry.registryDependencies,\n ]),\n );\n\n const components = scored\n .filter(\n (candidate) =>\n candidate.entry.type === \"registry:ui\" && !covered.has(candidate.entry.name),\n )\n .slice(0, maxComponents);\n\n const toEntry = (candidate: Scored): PlanEntry => ({\n entry: candidate.entry,\n because: candidate.because,\n });\n\n return {\n prompt,\n blocks: blocks.map(toEntry),\n components: components.map(toEntry),\n install: [...blocks, ...components].map((candidate) => candidate.entry.name),\n empty: blocks.length === 0 && components.length === 0,\n };\n}\n\n/** PascalCase export name for a registry name, e.g. \"ai-tool\" -> \"AiTool\". */\nfunction tag(name: string): string {\n return name\n .split(\"-\")\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\"\");\n}\n\n/** Blocks export a `…Block` component; components export their own name. */\nfunction componentName(entry: RegistryIndexEntry): string {\n const base = tag(entry.name);\n return entry.type === \"registry:block\" ? `${base}Block` : base;\n}\n\nexport interface RenderOptions {\n /** Where components are imported from in the target project. */\n importFrom?: string;\n /**\n * Where blocks are imported from.\n *\n * Separate because blocks are not exported from the component package at\n * all — they are only ever installed as source — so deriving their path from\n * a package specifier produces an import that does not exist. Derived from\n * `importFrom` when it is a project alias, and otherwise the conventional\n * install location.\n */\n blocksImportFrom?: string;\n cliPackage?: string;\n docsUrl?: string;\n}\n\n/**\n * Where an installed block lives.\n *\n * A project alias like `@/components/ui` has a sibling `@/components/blocks`. A\n * bare package specifier has no block path at all, so the conventional install\n * location is used instead of inventing one under the package.\n */\nexport function blocksPathFor(importFrom: string): string {\n if (importFrom.endsWith(\"/ui\")) return `${importFrom.slice(0, -3)}/blocks`;\n if (importFrom.startsWith(\"@/\") || importFrom.startsWith(\"~/\")) {\n return `${importFrom}/blocks`;\n }\n return \"@/components/blocks\";\n}\n\n/**\n * The plan as a starting file.\n *\n * Imports and composition only. Every element carries the page its props are\n * documented on, because the registry does not publish prop shapes and a\n * plausible invented prop is worse than an obvious gap — one is a TODO, the\n * other is a bug wearing the costume of working code.\n */\nexport function renderPlan(plan: UiPlan, options: RenderOptions = {}): string {\n const {\n importFrom = \"@/components/ui\",\n docsUrl = \"https://dowel-eight.vercel.app\",\n blocksImportFrom = blocksPathFor(importFrom),\n } = options;\n\n if (plan.empty) {\n return `// Nothing in the registry matched \"${plan.prompt}\".\\n`;\n }\n\n const chosen = [...plan.blocks, ...plan.components];\n\n const imports = chosen\n .map((item) => {\n const from =\n item.entry.type === \"registry:block\"\n ? `${blocksImportFrom}/${item.entry.name}`\n : `${importFrom}/${item.entry.name}`;\n return `import { ${componentName(item.entry)} } from \"${from}\";`;\n })\n .sort();\n\n const body = chosen\n .map((item) => {\n const name = componentName(item.entry);\n return [\n ` {/* ${item.entry.title} — props: ${docsUrl}/docs/${\n item.entry.type === \"registry:block\" ? \"blocks\" : \"components\"\n }/${item.entry.name} */}`,\n ` <${name} />`,\n ].join(\"\\n\");\n })\n .join(\"\\n\\n\");\n\n return `${imports.join(\"\\n\")}\n\nexport default function Page() {\n return (\n <div className=\"flex flex-col gap-6\">\n${body}\n </div>\n );\n}\n`;\n}\n\n/**\n * The plan as a brief for a coding agent.\n *\n * The most useful thing this can produce. The agent has the project, the\n * editor and the ability to write the props; what it lacks is the knowledge\n * that these components exist and that it must not invent others. That is\n * exactly what a grounded plan supplies.\n */\nexport function renderBrief(plan: UiPlan, options: RenderOptions = {}): string {\n const {\n cliPackage = \"@dowel-ui/cli\",\n docsUrl = \"https://dowel-eight.vercel.app\",\n importFrom = \"@/components/ui\",\n } = options;\n\n if (plan.empty) {\n return `Nothing in the registry matched \"${plan.prompt}\". Search the catalogue at ${docsUrl}/docs/components before building anything by hand.`;\n }\n\n const lines = [\n `Build: ${plan.prompt}`,\n \"\",\n \"Use these, which are already in the registry. Do not write your own versions,\",\n \"and do not use any component not listed here without checking the catalogue first.\",\n \"\",\n ];\n\n if (plan.blocks.length > 0) {\n lines.push(\"Blocks (whole sections — each installs its own components):\");\n for (const item of plan.blocks) {\n lines.push(`- ${item.entry.name} — ${item.entry.description}`);\n }\n lines.push(\"\");\n }\n\n if (plan.components.length > 0) {\n lines.push(\"Components:\");\n for (const item of plan.components) {\n lines.push(`- ${item.entry.name} — ${item.entry.description}`);\n }\n lines.push(\"\");\n }\n\n lines.push(\n \"Install first:\",\n \"\",\n ` npx ${cliPackage} add ${plan.install.join(\" \")}`,\n \"\",\n `Import from \\`${importFrom}\\`. Each component's props are on its page under`,\n `${docsUrl}/docs/components — read the page rather than guessing a prop name.`,\n \"\",\n \"Style with semantic tokens only (bg-background, text-muted-foreground). Never raw\",\n \"hex, never Tailwind's own palette — those do not follow the theme.\",\n );\n\n return lines.join(\"\\n\");\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"generate.js","names":[],"sources":["../src/generate.ts"],"sourcesContent":["import type { RegistryIndex, RegistryIndexEntry } from \"./schema\";\n\nexport type { RegistryIndex, RegistryIndexEntry } from \"./schema\";\n\n/**\n * Turning a description of a screen into a plan made of components that exist.\n *\n * The hard part of generating UI is not writing JSX. It is not inventing: a\n * model asked for a billing page will cheerfully produce `<PricingTable>` and\n * `<InvoiceList>` and a `variant=\"subtle\"` that was never implemented, and the\n * result reads perfectly and compiles nowhere.\n *\n * So this resolves a prompt against the registry first, and everything it\n * emits afterwards is drawn from what came back. It cannot name a component\n * that is not installable, because it only ever repeats names the registry\n * gave it.\n *\n * It does not guess at props. The registry publishes what a component *is* and\n * what it depends on, not the shape of its arguments, so the output stops at\n * the composition and points at the page where the props are documented.\n * Emitting a plausible prop is worse than emitting none — one is a gap, the\n * other is a bug that looks like working code.\n */\n\n/** Words that carry no signal about which component is wanted. */\nconst STOPWORDS = new Set([\n \"a\",\n \"an\",\n \"the\",\n \"and\",\n \"or\",\n \"of\",\n \"for\",\n \"with\",\n \"to\",\n \"in\",\n \"on\",\n \"at\",\n \"by\",\n \"is\",\n \"are\",\n \"be\",\n \"make\",\n \"build\",\n \"create\",\n \"want\",\n \"need\",\n \"add\",\n \"show\",\n \"page\",\n \"screen\",\n \"app\",\n \"application\",\n \"ui\",\n \"interface\",\n \"component\",\n \"components\",\n \"me\",\n \"my\",\n \"our\",\n \"i\",\n \"it\",\n \"that\",\n \"this\",\n \"some\",\n \"using\",\n \"use\",\n \"like\",\n]);\n\n/**\n * Words a reader would use that are not the words the registry uses.\n *\n * Hand-written, and deliberately so. \"Sign in\" is what someone types and\n * `login` is what the item is called; no amount of string similarity bridges\n * that, and pretending otherwise produces a matcher that works on the examples\n * it was tuned against and nothing else.\n */\nconst SYNONYMS: Record<string, string[]> = {\n \"sign in\": [\"login\"],\n signin: [\"login\"],\n \"log in\": [\"login\"],\n \"sign up\": [\"signup\"],\n register: [\"signup\"],\n registration: [\"signup\"],\n \"forgot password\": [\"forgot-password\"],\n \"reset password\": [\"forgot-password\"],\n chat: [\"ai-chat\", \"ai-conversation\", \"ai-prompt-input\"],\n conversation: [\"ai-chat\"],\n assistant: [\"ai-chat\"],\n copilot: [\"ai-chat\"],\n agent: [\"agent-console\", \"ai-agent-status\", \"ai-agent-plan\"],\n agents: [\"agent-console\"],\n tool: [\"ai-tool\"],\n approval: [\"ai-approval-request\"],\n approve: [\"ai-approval-request\"],\n undo: [\"ai-action-ledger\"],\n audit: [\"ai-action-ledger\", \"activity-feed\"],\n tokens: [\"ai-token-usage\"],\n spend: [\"ai-dashboard\", \"billing\"],\n cost: [\"ai-dashboard\", \"billing\"],\n usage: [\"ai-dashboard\", \"billing\"],\n subscription: [\"billing\", \"pricing\"],\n invoice: [\"billing\"],\n invoices: [\"billing\"],\n payment: [\"billing\"],\n plan: [\"pricing\", \"billing\"],\n plans: [\"pricing\", \"pricing-three-tier\", \"pricing-two-tier\", \"pricing-single-plan\"],\n metrics: [\"analytics\", \"dashboard\", \"metric-delta\"],\n chart: [\"analytics\", \"dither-bar\", \"dither-line\", \"dither-area\", \"dither-donut\"],\n charts: [\n \"analytics\",\n \"dither-canvas\",\n \"dither-bar\",\n \"dither-line\",\n \"dither-area\",\n \"dither-donut\",\n \"dither-heatmap\",\n ],\n graph: [\"analytics\", \"dither-line\", \"dither-area\", \"contribution-graph\"],\n stats: [\"dashboard\", \"analytics\", \"stats-grid\", \"stats-trend-cards\"],\n overview: [\"dashboard\"],\n grid: [\"data-table\", \"table\"],\n spreadsheet: [\"data-table\"],\n list: [\"table\", \"data-table\"],\n search: [\"command\", \"combobox\", \"expanding-search\", \"faq-searchable\"],\n palette: [\"command\", \"palette-generator\"],\n shortcut: [\"command\", \"shortcut-recorder\"],\n modal: [\"dialog\"],\n popup: [\"dialog\", \"popover\"],\n dropdown: [\"dropdown-menu\", \"select\"],\n toast: [\"toast\"],\n notification: [\"toast\", \"activity-feed\", \"notification-badge\", \"notify-button\"],\n notifications: [\"toast\", \"settings\"],\n upload: [\"file-upload\"],\n file: [\"file-upload\"],\n date: [\"date-picker\", \"calendar\"],\n time: [\"time-range-picker\"],\n schedule: [\"cron-editor\"],\n cron: [\"cron-editor\"],\n team: [\"admin-users\", \"settings\", \"team-grid\", \"team-carousel\"],\n members: [\"admin-users\"],\n users: [\"admin-users\"],\n admin: [\"admin-users\"],\n permissions: [\"permission-matrix\"],\n roles: [\"permission-matrix\"],\n profile: [\"settings\"],\n preferences: [\"settings\"],\n account: [\"settings\", \"billing\"],\n setup: [\"onboarding\"],\n checklist: [\"onboarding\", \"animated-checklist\", \"todo-tower\"],\n wizard: [\"onboarding\", \"stepper\"],\n logs: [\"log-viewer\"],\n log: [\"log-viewer\"],\n diff: [\"diff-viewer\", \"record-diff\"],\n secret: [\"secret-field\"],\n \"api key\": [\"secret-field\"],\n key: [\"secret-field\"],\n dns: [\"dns-record\"],\n loader: [\n \"spinner\",\n \"dots-loader\",\n \"ring-loader\",\n \"bar-loader\",\n \"shape-loader\",\n \"text-loader\",\n \"grid-loader\",\n \"ai-loader\",\n ],\n loaders: [\n \"dots-loader\",\n \"ring-loader\",\n \"bar-loader\",\n \"shape-loader\",\n \"text-loader\",\n \"grid-loader\",\n ],\n loading: [\"spinner\", \"dots-loader\", \"ring-loader\", \"bar-loader\", \"skeleton\", \"text-loader\"],\n spinner: [\"spinner\", \"ring-loader\"],\n animation: [\"text-effect\", \"text-swap\", \"shader-transition\"],\n animated: [\"text-effect\", \"morph-button\", \"effect-button\", \"number-flow\"],\n \"text animation\": [\n \"text-effect\",\n \"text-swap\",\n \"shimmer-text\",\n \"scramble-text\",\n \"typewriter-text\",\n ],\n typewriter: [\"typewriter-text\"],\n shimmer: [\"shimmer-text\", \"skeleton\"],\n counter: [\"number-flow\", \"drag-stepper\"],\n price: [\"number-flow\", \"pricing\"],\n carousel: [\n \"carousel-3d\",\n \"swipe-carousel\",\n \"reviews-carousel\",\n \"invite-carousel\",\n \"time-stack\",\n ],\n slider: [\"slider\", \"exposure-slider\", \"slosh-slider\", \"scrubber\", \"range-dial\"],\n slideshow: [\"carousel-3d\", \"swipe-carousel\", \"photo-stack\"],\n marquee: [\"marquee\", \"logo-marquee\"],\n ticker: [\"marquee\"],\n cards: [\"card\", \"card-spread\", \"card-stack\", \"glow-card\", \"tilt-card\", \"expandable-cards\"],\n hero: [\n \"hero-grid\",\n \"hero-product\",\n \"hero-split-image\",\n \"hero-perspective-grid\",\n \"hero-spotlight\",\n \"hero-minimal\",\n ],\n landing: [\"hero-grid\", \"features-bento\", \"cta-centered\", \"footer-newsletter\"],\n cta: [\"cta-centered\", \"cta-split-image\", \"cta-banner\"],\n \"call to action\": [\"cta-centered\", \"cta-split-image\", \"cta-banner\"],\n features: [\"features-icon-grid\", \"features-bento\", \"features-alternating\"],\n logos: [\"logo-cloud-simple\", \"logo-marquee\", \"logo-links-marquee\", \"logo-grid-tooltips\"],\n testimonials: [\n \"testimonial-rotator\",\n \"testimonial-spotlight\",\n \"testimonial-star-grid\",\n \"reviews-carousel\",\n ],\n reviews: [\"reviews-carousel\", \"testimonial-star-grid\"],\n faq: [\"faq-accordion\", \"faq-searchable\", \"faq-categorized\", \"faq-tabbed-grid\"],\n footer: [\"footer-simple\", \"footer-newsletter\", \"footer-mega\", \"footer-minimal\"],\n newsletter: [\"footer-newsletter\", \"footer-mega\"],\n heatmap: [\"dither-heatmap\", \"contribution-graph\"],\n donut: [\"dither-donut\"],\n pie: [\"dither-donut\"],\n gauge: [\"dither-gauge\", \"meter\"],\n funnel: [\"dither-funnel\"],\n uptime: [\"uptime-matrix\"],\n \"status page\": [\"uptime-matrix\"],\n otp: [\"otp-input\"],\n \"one-time code\": [\"otp-input\"],\n \"verification code\": [\"otp-input\"],\n steps: [\"stepper\"],\n \"context menu\": [\"context-menu\"],\n \"right click\": [\"context-menu\"],\n reorder: [\"reorder-list\", \"browser-tabs\"],\n sortable: [\"reorder-list\"],\n drag: [\"reorder-list\", \"goo-ball\", \"swipe-carousel\"],\n dock: [\"magnify-dock\"],\n toolbar: [\"canvas-toolbar\", \"magnify-dock\"],\n confirm: [\"slide-to-confirm\", \"inline-confirm\", \"confirm-typed\"],\n delete: [\"inline-confirm\", \"confirm-typed\"],\n toggle: [\"switch\", \"liquid-toggle\"],\n copy: [\"copy-button\"],\n clipboard: [\"copy-button\"],\n refresh: [\"pull-to-refresh\"],\n music: [\"now-playing\"],\n player: [\"now-playing\"],\n orb: [\"gradient-orb\", \"orb-face\"],\n transition: [\"shader-transition\", \"text-swap\"],\n badge: [\"badge\", \"notification-badge\"],\n avatar: [\"avatar\", \"avatar-group\", \"pixel-avatar\"],\n tweet: [\"tweet-card\"],\n dial: [\"dial\", \"range-dial\"],\n knob: [\"dial\"],\n};\n\nexport interface PlanEntry {\n entry: RegistryIndexEntry;\n /** Why this was chosen, in words, so a wrong pick is arguable. */\n because: string;\n}\n\nexport interface UiPlan {\n /** The prompt, as given. */\n prompt: string;\n /** Whole sections, which bring their own components. */\n blocks: PlanEntry[];\n /** Individual components, none of which a chosen block already installs. */\n components: PlanEntry[];\n /** Everything to install, in one list. */\n install: string[];\n /** True when nothing matched, so callers can say so rather than emit nothing. */\n empty: boolean;\n}\n\nfunction normalise(prompt: string): string {\n return prompt.toLowerCase().replace(/[^a-z0-9\\s-]/g, \" \");\n}\n\nfunction words(prompt: string): string[] {\n return normalise(prompt)\n .split(/\\s+/)\n .filter((word) => word.length > 2 && !STOPWORDS.has(word));\n}\n\ninterface SynonymMatch {\n /** Item name to the phrase that selected it. */\n hits: Map<string, string>;\n /**\n * Words the table has already spoken for.\n *\n * Excluded from generic term matching afterwards. The table exists to say\n * that \"plan\" means pricing or billing; letting the generic matcher also\n * score every item with \"plan\" in its name puts `ai-agent-plan` on a billing\n * page and re-introduces exactly the ambiguity the table resolves.\n */\n consumed: Set<string>;\n}\n\nfunction synonymHits(prompt: string): SynonymMatch {\n const text = normalise(prompt);\n const hits = new Map<string, string>();\n const consumed = new Set<string>();\n\n for (const [phrase, names] of Object.entries(SYNONYMS)) {\n // Word-boundary matched, so \"keyboard\" does not trigger \"key\".\n const pattern = new RegExp(`(^|\\\\s)${phrase.replace(/\\s+/g, \"\\\\s+\")}(\\\\s|$)`);\n if (!pattern.test(text)) continue;\n\n for (const word of phrase.split(/\\s+/)) consumed.add(word);\n for (const name of names) {\n if (!hits.has(name)) hits.set(name, phrase);\n }\n }\n\n return { hits, consumed };\n}\n\n/** Below this a match is coincidence rather than intent. */\nconst MINIMUM_SCORE = 20;\n\ninterface Scored {\n entry: RegistryIndexEntry;\n /** What the prompt actually matched. Decides whether it qualifies at all. */\n score: number;\n /** Score plus the block preference. Decides order only. */\n rank: number;\n because: string;\n}\n\nfunction scoreEntry(\n entry: RegistryIndexEntry,\n terms: string[],\n synonyms: Map<string, string>,\n): Scored | undefined {\n const name = entry.name.toLowerCase();\n const title = entry.title.toLowerCase();\n const description = entry.description.toLowerCase();\n\n let score = 0;\n const reasons: string[] = [];\n\n const synonym = synonyms.get(entry.name);\n if (synonym) {\n score += 60;\n reasons.push(`\"${synonym}\"`);\n }\n\n for (const term of terms) {\n if (name === term) {\n score += 50;\n reasons.push(`named \"${term}\"`);\n } else if (name.split(\"-\").includes(term)) {\n score += 30;\n reasons.push(`\"${term}\" in its name`);\n } else if (title.includes(term)) {\n score += 20;\n reasons.push(`\"${term}\" in its title`);\n } else if (entry.category === term) {\n score += 12;\n reasons.push(`the ${term} category`);\n } else if (description.includes(term)) {\n score += 8;\n reasons.push(`\"${term}\" in its description`);\n }\n }\n\n if (score === 0) return undefined;\n\n // A block covers more of an intent than a component does, and installing one\n // brings the components anyway — so where both match, the block is the better\n // answer rather than merely an equal one.\n //\n // Kept out of `score` on purpose. Added there it would lift a block over the\n // qualifying floor on a description-only brush, which is how `ai-dashboard`\n // ended up recommended for an agent console because its prose contains the\n // word \"run\". A preference should order real matches, not manufacture one.\n const rank = score + (entry.type === \"registry:block\" ? 25 : 0);\n\n return { entry, score, rank, because: [...new Set(reasons)].slice(0, 3).join(\", \") };\n}\n\nexport interface PlanOptions {\n /** How many components to suggest beyond the blocks. */\n maxComponents?: number;\n /** How many blocks to suggest. */\n maxBlocks?: number;\n}\n\nexport function planUi(\n prompt: string,\n index: RegistryIndex,\n options: PlanOptions = {},\n): UiPlan {\n const { maxBlocks = 3, maxComponents = 6 } = options;\n\n const { hits: synonyms, consumed } = synonymHits(prompt);\n const terms = words(prompt).filter((term) => !consumed.has(term));\n\n const scored = index.items\n .filter((entry) => entry.type === \"registry:ui\" || entry.type === \"registry:block\")\n .map((entry) => scoreEntry(entry, terms, synonyms))\n .filter((candidate): candidate is Scored => candidate !== undefined)\n // A description-only brush (8) or a bare category hit (12) is not enough on\n // its own. Suggesting six components because the prompt shares a common\n // word with their prose makes the plan look like more work than it is, and\n // buries the ones that actually matched.\n .filter((candidate) => candidate.score >= MINIMUM_SCORE)\n .sort((a, b) => b.rank - a.rank || a.entry.name.localeCompare(b.entry.name));\n\n const blocks = scored\n .filter((candidate) => candidate.entry.type === \"registry:block\")\n .slice(0, maxBlocks);\n\n // Anything a chosen block already installs is not a separate suggestion:\n // listing Button beside a Dashboard that brings it is noise that makes the\n // plan look longer than the work.\n const covered = new Set(\n blocks.flatMap((candidate) => [\n candidate.entry.name,\n ...candidate.entry.registryDependencies,\n ]),\n );\n\n const components = scored\n .filter(\n (candidate) =>\n candidate.entry.type === \"registry:ui\" && !covered.has(candidate.entry.name),\n )\n .slice(0, maxComponents);\n\n const toEntry = (candidate: Scored): PlanEntry => ({\n entry: candidate.entry,\n because: candidate.because,\n });\n\n return {\n prompt,\n blocks: blocks.map(toEntry),\n components: components.map(toEntry),\n install: [...blocks, ...components].map((candidate) => candidate.entry.name),\n empty: blocks.length === 0 && components.length === 0,\n };\n}\n\n/** PascalCase export name for a registry name, e.g. \"ai-tool\" -> \"AiTool\". */\nfunction tag(name: string): string {\n return name\n .split(\"-\")\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\"\");\n}\n\n/** Blocks export a `…Block` component; components export their own name. */\nfunction componentName(entry: RegistryIndexEntry): string {\n const base = tag(entry.name);\n return entry.type === \"registry:block\" ? `${base}Block` : base;\n}\n\nexport interface RenderOptions {\n /** Where components are imported from in the target project. */\n importFrom?: string;\n /**\n * Where blocks are imported from.\n *\n * Separate because blocks are not exported from the component package at\n * all — they are only ever installed as source — so deriving their path from\n * a package specifier produces an import that does not exist. Derived from\n * `importFrom` when it is a project alias, and otherwise the conventional\n * install location.\n */\n blocksImportFrom?: string;\n cliPackage?: string;\n docsUrl?: string;\n}\n\n/**\n * Where an installed block lives.\n *\n * A project alias like `@/components/ui` has a sibling `@/components/blocks`. A\n * bare package specifier has no block path at all, so the conventional install\n * location is used instead of inventing one under the package.\n */\nexport function blocksPathFor(importFrom: string): string {\n if (importFrom.endsWith(\"/ui\")) return `${importFrom.slice(0, -3)}/blocks`;\n if (importFrom.startsWith(\"@/\") || importFrom.startsWith(\"~/\")) {\n return `${importFrom}/blocks`;\n }\n return \"@/components/blocks\";\n}\n\n/**\n * The plan as a starting file.\n *\n * Imports and composition only. Every element carries the page its props are\n * documented on, because the registry does not publish prop shapes and a\n * plausible invented prop is worse than an obvious gap — one is a TODO, the\n * other is a bug wearing the costume of working code.\n */\nexport function renderPlan(plan: UiPlan, options: RenderOptions = {}): string {\n const {\n importFrom = \"@/components/ui\",\n docsUrl = \"https://dowel-eight.vercel.app\",\n blocksImportFrom = blocksPathFor(importFrom),\n } = options;\n\n if (plan.empty) {\n return `// Nothing in the registry matched \"${plan.prompt}\".\\n`;\n }\n\n const chosen = [...plan.blocks, ...plan.components];\n\n const imports = chosen\n .map((item) => {\n const from =\n item.entry.type === \"registry:block\"\n ? `${blocksImportFrom}/${item.entry.name}`\n : `${importFrom}/${item.entry.name}`;\n return `import { ${componentName(item.entry)} } from \"${from}\";`;\n })\n .sort();\n\n const body = chosen\n .map((item) => {\n const name = componentName(item.entry);\n return [\n ` {/* ${item.entry.title} — props: ${docsUrl}/docs/${\n item.entry.type === \"registry:block\" ? \"blocks\" : \"components\"\n }/${item.entry.name} */}`,\n ` <${name} />`,\n ].join(\"\\n\");\n })\n .join(\"\\n\\n\");\n\n return `${imports.join(\"\\n\")}\n\nexport default function Page() {\n return (\n <div className=\"flex flex-col gap-6\">\n${body}\n </div>\n );\n}\n`;\n}\n\n/**\n * The plan as a brief for a coding agent.\n *\n * The most useful thing this can produce. The agent has the project, the\n * editor and the ability to write the props; what it lacks is the knowledge\n * that these components exist and that it must not invent others. That is\n * exactly what a grounded plan supplies.\n */\nexport function renderBrief(plan: UiPlan, options: RenderOptions = {}): string {\n const {\n cliPackage = \"@dowel-ui/cli\",\n docsUrl = \"https://dowel-eight.vercel.app\",\n importFrom = \"@/components/ui\",\n } = options;\n\n if (plan.empty) {\n return `Nothing in the registry matched \"${plan.prompt}\". Search the catalogue at ${docsUrl}/docs/components before building anything by hand.`;\n }\n\n const lines = [\n `Build: ${plan.prompt}`,\n \"\",\n \"Use these, which are already in the registry. Do not write your own versions,\",\n \"and do not use any component not listed here without checking the catalogue first.\",\n \"\",\n ];\n\n if (plan.blocks.length > 0) {\n lines.push(\"Blocks (whole sections — each installs its own components):\");\n for (const item of plan.blocks) {\n lines.push(`- ${item.entry.name} — ${item.entry.description}`);\n }\n lines.push(\"\");\n }\n\n if (plan.components.length > 0) {\n lines.push(\"Components:\");\n for (const item of plan.components) {\n lines.push(`- ${item.entry.name} — ${item.entry.description}`);\n }\n lines.push(\"\");\n }\n\n lines.push(\n \"Install first:\",\n \"\",\n ` npx ${cliPackage} add ${plan.install.join(\" \")}`,\n \"\",\n `Import from \\`${importFrom}\\`. Each component's props are on its page under`,\n `${docsUrl}/docs/components — read the page rather than guessing a prop name.`,\n \"\",\n \"Style with semantic tokens only (bg-background, text-muted-foreground). Never raw\",\n \"hex, never Tailwind's own palette — those do not follow the theme.\",\n );\n\n return lines.join(\"\\n\");\n}\n"],"mappings":"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"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/custom.ts","../src/agent-docs.ts","../src/hash.ts"],"mappings":";;;;;;;;;;;;;;;;;;cAgCa,iBAAe,EAAA;;;;;;KAEhB,YAAY,EAAE,aAAa;cAS1B,kBAAgB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAqB3B,EAAA,KAAA;KAEU,aAAa,EAAE,aAAa;cAE3B,sBAAoB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAc/B,EAAA,KAAA;KAEU,iBAAiB,EAAE,aAAa;;iBAG5B,qBAAqB,QAAQ,iBAAiB;UAI7C;EACf,OAAO;;;;;;;;EAQP;;EAEA;;;;;;;;;iBAgKc,iBAAiB,OAAO;iBAkBlB,oBAAoB,QAAQ,iBAAiB,QAAQ;;;;;;;;;;;;;;;;UCxQ1D;EACf,OAAO;;;;;;;;EAQP,QAAQ;;EAER;;EAEA;;EAEA;EACA;;EAEA;;;;;;;;EAQA;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/custom.ts","../src/agent-docs.ts","../src/hash.ts"],"mappings":";;;;;;;;;;;;;;;;;;cAgCa,iBAAe,EAAA;;;;;;KAEhB,YAAY,EAAE,aAAa;cAS1B,kBAAgB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAqB3B,EAAA,KAAA;KAEU,aAAa,EAAE,aAAa;cAE3B,sBAAoB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAc/B,EAAA,KAAA;KAEU,iBAAiB,EAAE,aAAa;;iBAG5B,qBAAqB,QAAQ,iBAAiB;UAI7C;EACf,OAAO;;;;;;;;EAQP;;EAEA;;;;;;;;;iBAgKc,iBAAiB,OAAO;iBAkBlB,oBAAoB,QAAQ,iBAAiB,QAAQ;;;;;;;;;;;;;;;;UCxQ1D;EACf,OAAO;;;;;;;;EAQP,QAAQ;;EAER;;EAEA;;EAEA;EACA;;EAEA;;;;;;;;EAQA;;iBA8Ec,eAAe,SAAS;iBA6DxB,cAAc,SAAS;iBAmDvB,MAAM,SAAS;iBAqCf,UAAU,SAAS;;iBA2CnB,SAAS,SAAS;;iBAgElB,WAAW,SAAS;cAyBvB;cACA;;;;;;;;;iBAUG,cAAc,SAAS;;iBAuBvB,oBAAoB,kBAAkB;;;;;;;;iBAmBtC,QAAQ,SAAS;;iBA+CjB,YAAY,SAAS;;;;;;;;;iBC7erB,YAAY"}
|
package/dist/index.js
CHANGED
|
@@ -225,7 +225,8 @@ const CATEGORY_LABELS = {
|
|
|
225
225
|
data: "Data",
|
|
226
226
|
feedback: "Feedback",
|
|
227
227
|
layout: "Layout",
|
|
228
|
-
ai: "AI"
|
|
228
|
+
ai: "AI",
|
|
229
|
+
effects: "Effects"
|
|
229
230
|
};
|
|
230
231
|
const CATEGORY_ORDER = [
|
|
231
232
|
"foundation",
|
|
@@ -236,7 +237,8 @@ const CATEGORY_ORDER = [
|
|
|
236
237
|
"data",
|
|
237
238
|
"feedback",
|
|
238
239
|
"layout",
|
|
239
|
-
"ai"
|
|
240
|
+
"ai",
|
|
241
|
+
"effects"
|
|
240
242
|
];
|
|
241
243
|
function label(category) {
|
|
242
244
|
return CATEGORY_LABELS[category] ?? category;
|
|
@@ -418,7 +420,8 @@ change belongs in the token layer instead.
|
|
|
418
420
|
|
|
419
421
|
## Presets
|
|
420
422
|
|
|
421
|
-
\`default\`, \`ocean\`, \`emerald\`, \`violet\`, \`rose\`, \`amber\`, \`monochrome
|
|
423
|
+
\`default\`, \`ocean\`, \`emerald\`, \`violet\`, \`rose\`, \`amber\`, \`monochrome\`,
|
|
424
|
+
\`candy\`, \`indigo\`, \`blue\`, \`red\`, \`orange\`, \`green\`.
|
|
422
425
|
|
|
423
426
|
\`\`\`html
|
|
424
427
|
<html data-theme="ocean" class="dark">
|