rafters 0.0.8 → 0.0.12
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/index.js +1767 -215
- package/dist/registry/types.d.ts +65 -0
- package/dist/registry/types.js +34 -0
- package/package.json +30 -21
package/dist/index.js
CHANGED
|
@@ -9,8 +9,8 @@ import { Command } from "commander";
|
|
|
9
9
|
|
|
10
10
|
// src/commands/add.ts
|
|
11
11
|
import { existsSync } from "fs";
|
|
12
|
-
import { access, mkdir, readFile, writeFile } from "fs/promises";
|
|
13
|
-
import { dirname, join as
|
|
12
|
+
import { access, mkdir, readFile as readFile2, writeFile } from "fs/promises";
|
|
13
|
+
import { dirname, join as join3 } from "path";
|
|
14
14
|
|
|
15
15
|
// ../../node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/external.js
|
|
16
16
|
var external_exports = {};
|
|
@@ -12558,22 +12558,28 @@ config(en_default());
|
|
|
12558
12558
|
var RegistryFileSchema = external_exports.object({
|
|
12559
12559
|
path: external_exports.string(),
|
|
12560
12560
|
content: external_exports.string(),
|
|
12561
|
-
dependencies: external_exports.array(external_exports.string())
|
|
12561
|
+
dependencies: external_exports.array(external_exports.string()),
|
|
12562
12562
|
// e.g., ["lodash@4.17.21"] - versioned
|
|
12563
|
+
devDependencies: external_exports.array(external_exports.string()).default([])
|
|
12564
|
+
// e.g., ["vitest"] - from @devDependencies JSDoc
|
|
12563
12565
|
});
|
|
12564
|
-
var RegistryItemTypeSchema = external_exports.enum(["
|
|
12566
|
+
var RegistryItemTypeSchema = external_exports.enum(["ui", "primitive", "composite"]);
|
|
12565
12567
|
var RegistryItemSchema = external_exports.object({
|
|
12566
12568
|
name: external_exports.string(),
|
|
12567
12569
|
type: RegistryItemTypeSchema,
|
|
12568
12570
|
description: external_exports.string().optional(),
|
|
12569
12571
|
primitives: external_exports.array(external_exports.string()),
|
|
12570
|
-
files: external_exports.array(RegistryFileSchema)
|
|
12572
|
+
files: external_exports.array(RegistryFileSchema),
|
|
12573
|
+
rules: external_exports.array(external_exports.string()).default([]),
|
|
12574
|
+
composites: external_exports.array(external_exports.string()).default([])
|
|
12571
12575
|
});
|
|
12572
12576
|
var RegistryIndexSchema = external_exports.object({
|
|
12573
12577
|
name: external_exports.string(),
|
|
12574
12578
|
homepage: external_exports.string(),
|
|
12575
12579
|
components: external_exports.array(external_exports.string()),
|
|
12576
|
-
primitives: external_exports.array(external_exports.string())
|
|
12580
|
+
primitives: external_exports.array(external_exports.string()),
|
|
12581
|
+
composites: external_exports.array(external_exports.string()).default([]),
|
|
12582
|
+
rules: external_exports.array(external_exports.string()).default([])
|
|
12577
12583
|
});
|
|
12578
12584
|
|
|
12579
12585
|
// src/registry/client.ts
|
|
@@ -12644,6 +12650,30 @@ var RegistryClient = class {
|
|
|
12644
12650
|
this.cache.set(cacheKey, item);
|
|
12645
12651
|
return item;
|
|
12646
12652
|
}
|
|
12653
|
+
/**
|
|
12654
|
+
* Fetch a composite by name
|
|
12655
|
+
*/
|
|
12656
|
+
async fetchComposite(name2) {
|
|
12657
|
+
const cacheKey = `composite:${name2}`;
|
|
12658
|
+
const cached2 = this.cache.get(cacheKey);
|
|
12659
|
+
if (cached2) {
|
|
12660
|
+
return cached2;
|
|
12661
|
+
}
|
|
12662
|
+
const url2 = `${this.baseUrl}/registry/composites/${name2}.json`;
|
|
12663
|
+
const response = await fetch(url2);
|
|
12664
|
+
if (response.status === 404) {
|
|
12665
|
+
throw new Error(`Composite "${name2}" not found`);
|
|
12666
|
+
}
|
|
12667
|
+
if (!response.ok) {
|
|
12668
|
+
throw new Error(
|
|
12669
|
+
`Failed to fetch composite "${name2}": ${response.status} ${response.statusText}`
|
|
12670
|
+
);
|
|
12671
|
+
}
|
|
12672
|
+
const data = await response.json();
|
|
12673
|
+
const item = RegistryItemSchema.parse(data);
|
|
12674
|
+
this.cache.set(cacheKey, item);
|
|
12675
|
+
return item;
|
|
12676
|
+
}
|
|
12647
12677
|
/**
|
|
12648
12678
|
* Fetch a registry item (component or primitive) by name
|
|
12649
12679
|
* Tries component first, then primitive
|
|
@@ -12669,6 +12699,13 @@ var RegistryClient = class {
|
|
|
12669
12699
|
const index = await this.fetchIndex();
|
|
12670
12700
|
return index.components.map((name2) => ({ name: name2 }));
|
|
12671
12701
|
}
|
|
12702
|
+
/**
|
|
12703
|
+
* List all available composites
|
|
12704
|
+
*/
|
|
12705
|
+
async listComposites() {
|
|
12706
|
+
const index = await this.fetchIndex();
|
|
12707
|
+
return index.composites.map((name2) => ({ name: name2 }));
|
|
12708
|
+
}
|
|
12672
12709
|
/**
|
|
12673
12710
|
* Check if a component exists in the registry
|
|
12674
12711
|
*/
|
|
@@ -12714,18 +12751,64 @@ var RegistryClient = class {
|
|
|
12714
12751
|
};
|
|
12715
12752
|
var registryClient = new RegistryClient();
|
|
12716
12753
|
|
|
12717
|
-
// src/utils/
|
|
12718
|
-
|
|
12719
|
-
|
|
12720
|
-
|
|
12754
|
+
// src/utils/exports.ts
|
|
12755
|
+
var DEFAULT_EXPORTS = {
|
|
12756
|
+
tailwind: true,
|
|
12757
|
+
typescript: true,
|
|
12758
|
+
dtcg: false,
|
|
12759
|
+
compiled: false
|
|
12760
|
+
};
|
|
12761
|
+
var EXPORT_CHOICES = [
|
|
12762
|
+
{
|
|
12763
|
+
name: "Tailwind CSS (web projects)",
|
|
12764
|
+
value: "tailwind",
|
|
12765
|
+
checked: true
|
|
12766
|
+
},
|
|
12767
|
+
{
|
|
12768
|
+
name: "TypeScript (type-safe constants)",
|
|
12769
|
+
value: "typescript",
|
|
12770
|
+
checked: true
|
|
12771
|
+
},
|
|
12772
|
+
{
|
|
12773
|
+
name: "DTCG JSON (Figma Tokens, Style Dictionary)",
|
|
12774
|
+
value: "dtcg",
|
|
12775
|
+
checked: false
|
|
12776
|
+
},
|
|
12777
|
+
{
|
|
12778
|
+
name: "Standalone CSS (pre-built, no Tailwind required)",
|
|
12779
|
+
value: "compiled",
|
|
12780
|
+
checked: false
|
|
12781
|
+
}
|
|
12782
|
+
];
|
|
12783
|
+
var FUTURE_EXPORTS = [
|
|
12784
|
+
{
|
|
12785
|
+
name: "iOS (Swift/SwiftUI)",
|
|
12786
|
+
value: "tailwind",
|
|
12787
|
+
// placeholder
|
|
12788
|
+
checked: false,
|
|
12789
|
+
disabled: "coming soon"
|
|
12790
|
+
},
|
|
12791
|
+
{
|
|
12792
|
+
name: "Android (Compose)",
|
|
12793
|
+
value: "tailwind",
|
|
12794
|
+
// placeholder
|
|
12795
|
+
checked: false,
|
|
12796
|
+
disabled: "coming soon"
|
|
12797
|
+
}
|
|
12798
|
+
];
|
|
12799
|
+
function selectionsToConfig(selections) {
|
|
12721
12800
|
return {
|
|
12722
|
-
|
|
12723
|
-
|
|
12724
|
-
|
|
12725
|
-
|
|
12801
|
+
tailwind: selections.includes("tailwind"),
|
|
12802
|
+
typescript: selections.includes("typescript"),
|
|
12803
|
+
dtcg: selections.includes("dtcg"),
|
|
12804
|
+
compiled: selections.includes("compiled")
|
|
12726
12805
|
};
|
|
12727
12806
|
}
|
|
12728
12807
|
|
|
12808
|
+
// src/utils/install-registry-deps.ts
|
|
12809
|
+
import { readFile } from "fs/promises";
|
|
12810
|
+
import { join } from "path";
|
|
12811
|
+
|
|
12729
12812
|
// src/utils/ui.ts
|
|
12730
12813
|
import ora from "ora";
|
|
12731
12814
|
var context = {
|
|
@@ -12844,8 +12927,9 @@ function log(event) {
|
|
|
12844
12927
|
context.spinner?.succeed("Files written");
|
|
12845
12928
|
const deps = event.dependencies;
|
|
12846
12929
|
const devDeps = event.devDependencies;
|
|
12930
|
+
const skippedDeps = event.skipped ?? [];
|
|
12847
12931
|
if (deps.length > 0 || devDeps.length > 0) {
|
|
12848
|
-
console.log(" Dependencies
|
|
12932
|
+
console.log(" Dependencies installed:");
|
|
12849
12933
|
for (const dep of deps) {
|
|
12850
12934
|
console.log(` ${dep}`);
|
|
12851
12935
|
}
|
|
@@ -12853,9 +12937,32 @@ function log(event) {
|
|
|
12853
12937
|
console.log(` ${dep} (dev)`);
|
|
12854
12938
|
}
|
|
12855
12939
|
}
|
|
12856
|
-
|
|
12940
|
+
if (skippedDeps.length > 0) {
|
|
12941
|
+
console.log(" Dependencies skipped (already installed or internal):");
|
|
12942
|
+
for (const dep of skippedDeps) {
|
|
12943
|
+
console.log(` ${dep}`);
|
|
12944
|
+
}
|
|
12945
|
+
}
|
|
12946
|
+
break;
|
|
12947
|
+
}
|
|
12948
|
+
case "add:deps:no-package-json":
|
|
12949
|
+
console.warn(` Warning: ${event.message}`);
|
|
12950
|
+
break;
|
|
12951
|
+
case "add:deps:dry-run": {
|
|
12952
|
+
const dryDeps = event.dependencies;
|
|
12953
|
+
console.log(" [dry-run] Would install:");
|
|
12954
|
+
for (const dep of dryDeps) {
|
|
12955
|
+
console.log(` ${dep}`);
|
|
12956
|
+
}
|
|
12857
12957
|
break;
|
|
12858
12958
|
}
|
|
12959
|
+
case "add:deps:install-failed":
|
|
12960
|
+
context.spinner?.fail("Failed to install dependencies");
|
|
12961
|
+
console.log(` ${event.message}`);
|
|
12962
|
+
if (event.suggestion) {
|
|
12963
|
+
console.log(` ${event.suggestion}`);
|
|
12964
|
+
}
|
|
12965
|
+
break;
|
|
12859
12966
|
case "add:complete":
|
|
12860
12967
|
context.spinner?.succeed(
|
|
12861
12968
|
`Added ${event.installed} component${event.installed !== 1 ? "s" : ""}`
|
|
@@ -12973,6 +13080,127 @@ async function installWithPackageManager(packageManager, dependencies, options)
|
|
|
12973
13080
|
}
|
|
12974
13081
|
}
|
|
12975
13082
|
|
|
13083
|
+
// src/utils/install-registry-deps.ts
|
|
13084
|
+
function parseDependency(dep) {
|
|
13085
|
+
const trimmed = dep.trim();
|
|
13086
|
+
if (!trimmed) {
|
|
13087
|
+
return { name: "", version: void 0 };
|
|
13088
|
+
}
|
|
13089
|
+
const versionAt = trimmed.lastIndexOf("@");
|
|
13090
|
+
if (versionAt <= 0) {
|
|
13091
|
+
return { name: trimmed, version: void 0 };
|
|
13092
|
+
}
|
|
13093
|
+
return {
|
|
13094
|
+
name: trimmed.slice(0, versionAt),
|
|
13095
|
+
version: trimmed.slice(versionAt + 1)
|
|
13096
|
+
};
|
|
13097
|
+
}
|
|
13098
|
+
async function readInstalledDeps(targetDir) {
|
|
13099
|
+
let raw;
|
|
13100
|
+
try {
|
|
13101
|
+
raw = await readFile(join(targetDir, "package.json"), "utf-8");
|
|
13102
|
+
} catch {
|
|
13103
|
+
return { packageJsonFound: false, installed: /* @__PURE__ */ new Set() };
|
|
13104
|
+
}
|
|
13105
|
+
try {
|
|
13106
|
+
const pkg = JSON.parse(raw);
|
|
13107
|
+
const installed = /* @__PURE__ */ new Set();
|
|
13108
|
+
const depFields = ["dependencies", "devDependencies", "peerDependencies"];
|
|
13109
|
+
for (const field of depFields) {
|
|
13110
|
+
const section = pkg[field];
|
|
13111
|
+
if (section && typeof section === "object") {
|
|
13112
|
+
for (const name2 of Object.keys(section)) {
|
|
13113
|
+
installed.add(name2);
|
|
13114
|
+
}
|
|
13115
|
+
}
|
|
13116
|
+
}
|
|
13117
|
+
return { packageJsonFound: true, installed };
|
|
13118
|
+
} catch {
|
|
13119
|
+
return { packageJsonFound: true, installed: /* @__PURE__ */ new Set() };
|
|
13120
|
+
}
|
|
13121
|
+
}
|
|
13122
|
+
async function installRegistryDependencies(items, targetDir, options = {}) {
|
|
13123
|
+
const result = {
|
|
13124
|
+
installed: [],
|
|
13125
|
+
skipped: [],
|
|
13126
|
+
devInstalled: [],
|
|
13127
|
+
failed: []
|
|
13128
|
+
};
|
|
13129
|
+
const allDeps = new Set(items.flatMap((item) => item.files.flatMap((file2) => file2.dependencies)));
|
|
13130
|
+
if (allDeps.size === 0) {
|
|
13131
|
+
return result;
|
|
13132
|
+
}
|
|
13133
|
+
const externalDeps = [];
|
|
13134
|
+
for (const dep of allDeps) {
|
|
13135
|
+
if (parseDependency(dep).name.startsWith("@rafters/")) {
|
|
13136
|
+
result.skipped.push(dep);
|
|
13137
|
+
} else {
|
|
13138
|
+
externalDeps.push(dep);
|
|
13139
|
+
}
|
|
13140
|
+
}
|
|
13141
|
+
if (externalDeps.length === 0) {
|
|
13142
|
+
return result;
|
|
13143
|
+
}
|
|
13144
|
+
const { packageJsonFound, installed: installedInProject } = await readInstalledDeps(targetDir);
|
|
13145
|
+
const toInstall = [];
|
|
13146
|
+
if (!packageJsonFound) {
|
|
13147
|
+
log({
|
|
13148
|
+
event: "add:deps:no-package-json",
|
|
13149
|
+
message: "No package.json found. Run npm init or pnpm init first.",
|
|
13150
|
+
targetDir
|
|
13151
|
+
});
|
|
13152
|
+
toInstall.push(...externalDeps);
|
|
13153
|
+
} else {
|
|
13154
|
+
for (const dep of externalDeps) {
|
|
13155
|
+
const { name: name2 } = parseDependency(dep);
|
|
13156
|
+
if (installedInProject.has(name2)) {
|
|
13157
|
+
result.skipped.push(dep);
|
|
13158
|
+
} else {
|
|
13159
|
+
toInstall.push(dep);
|
|
13160
|
+
}
|
|
13161
|
+
}
|
|
13162
|
+
}
|
|
13163
|
+
if (toInstall.length === 0) {
|
|
13164
|
+
return result;
|
|
13165
|
+
}
|
|
13166
|
+
if (options.dryRun) {
|
|
13167
|
+
log({
|
|
13168
|
+
event: "add:deps:dry-run",
|
|
13169
|
+
dependencies: toInstall
|
|
13170
|
+
});
|
|
13171
|
+
return result;
|
|
13172
|
+
}
|
|
13173
|
+
try {
|
|
13174
|
+
await updateDependencies(toInstall, [], {
|
|
13175
|
+
cwd: targetDir,
|
|
13176
|
+
silent: options.silent ?? false
|
|
13177
|
+
});
|
|
13178
|
+
result.installed = toInstall;
|
|
13179
|
+
} catch (err) {
|
|
13180
|
+
result.failed = toInstall;
|
|
13181
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
13182
|
+
log({
|
|
13183
|
+
event: "add:deps:install-failed",
|
|
13184
|
+
message: `Failed to install dependencies: ${message}`,
|
|
13185
|
+
dependencies: toInstall,
|
|
13186
|
+
suggestion: `Manually install: ${toInstall.join(" ")}`
|
|
13187
|
+
});
|
|
13188
|
+
}
|
|
13189
|
+
return result;
|
|
13190
|
+
}
|
|
13191
|
+
|
|
13192
|
+
// src/utils/paths.ts
|
|
13193
|
+
import { join as join2 } from "path";
|
|
13194
|
+
function getRaftersPaths(projectRoot = process.cwd()) {
|
|
13195
|
+
const root = join2(projectRoot, ".rafters");
|
|
13196
|
+
return {
|
|
13197
|
+
root,
|
|
13198
|
+
config: join2(root, "config.rafters.json"),
|
|
13199
|
+
tokens: join2(root, "tokens"),
|
|
13200
|
+
output: join2(root, "output")
|
|
13201
|
+
};
|
|
13202
|
+
}
|
|
13203
|
+
|
|
12976
13204
|
// src/commands/add.ts
|
|
12977
13205
|
async function isInitialized(cwd) {
|
|
12978
13206
|
const paths = getRaftersPaths(cwd);
|
|
@@ -12986,7 +13214,7 @@ async function isInitialized(cwd) {
|
|
|
12986
13214
|
async function loadConfig(cwd) {
|
|
12987
13215
|
const paths = getRaftersPaths(cwd);
|
|
12988
13216
|
try {
|
|
12989
|
-
const content = await
|
|
13217
|
+
const content = await readFile2(paths.config, "utf-8");
|
|
12990
13218
|
return JSON.parse(content);
|
|
12991
13219
|
} catch (err) {
|
|
12992
13220
|
if (existsSync(paths.config)) {
|
|
@@ -12996,6 +13224,56 @@ async function loadConfig(cwd) {
|
|
|
12996
13224
|
return null;
|
|
12997
13225
|
}
|
|
12998
13226
|
}
|
|
13227
|
+
async function saveConfig(cwd, config3) {
|
|
13228
|
+
const paths = getRaftersPaths(cwd);
|
|
13229
|
+
await writeFile(paths.config, JSON.stringify(config3, null, 2));
|
|
13230
|
+
}
|
|
13231
|
+
function getInstalledNames(config3) {
|
|
13232
|
+
if (!config3?.installed) return [];
|
|
13233
|
+
const names2 = /* @__PURE__ */ new Set([
|
|
13234
|
+
...config3.installed.components,
|
|
13235
|
+
...config3.installed.primitives,
|
|
13236
|
+
...config3.installed.composites ?? []
|
|
13237
|
+
]);
|
|
13238
|
+
return [...names2].sort();
|
|
13239
|
+
}
|
|
13240
|
+
var FOLDER_NAMES = /* @__PURE__ */ new Set(["composites"]);
|
|
13241
|
+
function isAlreadyInstalled(config3, item) {
|
|
13242
|
+
if (!config3?.installed) return false;
|
|
13243
|
+
if (item.type === "ui") {
|
|
13244
|
+
return config3.installed.components.includes(item.name);
|
|
13245
|
+
}
|
|
13246
|
+
if (item.type === "composite") {
|
|
13247
|
+
return (config3.installed.composites ?? []).includes(item.name);
|
|
13248
|
+
}
|
|
13249
|
+
return config3.installed.primitives.includes(item.name);
|
|
13250
|
+
}
|
|
13251
|
+
function trackInstalled(config3, items) {
|
|
13252
|
+
if (!config3.installed) {
|
|
13253
|
+
config3.installed = { components: [], primitives: [], composites: [] };
|
|
13254
|
+
}
|
|
13255
|
+
if (!config3.installed.composites) {
|
|
13256
|
+
config3.installed.composites = [];
|
|
13257
|
+
}
|
|
13258
|
+
for (const item of items) {
|
|
13259
|
+
if (item.type === "ui") {
|
|
13260
|
+
if (!config3.installed.components.includes(item.name)) {
|
|
13261
|
+
config3.installed.components.push(item.name);
|
|
13262
|
+
}
|
|
13263
|
+
} else if (item.type === "composite") {
|
|
13264
|
+
if (!config3.installed.composites.includes(item.name)) {
|
|
13265
|
+
config3.installed.composites.push(item.name);
|
|
13266
|
+
}
|
|
13267
|
+
} else {
|
|
13268
|
+
if (!config3.installed.primitives.includes(item.name)) {
|
|
13269
|
+
config3.installed.primitives.push(item.name);
|
|
13270
|
+
}
|
|
13271
|
+
}
|
|
13272
|
+
}
|
|
13273
|
+
config3.installed.components.sort();
|
|
13274
|
+
config3.installed.primitives.sort();
|
|
13275
|
+
config3.installed.composites.sort();
|
|
13276
|
+
}
|
|
12999
13277
|
function transformPath(registryPath, config3) {
|
|
13000
13278
|
if (!config3) return registryPath;
|
|
13001
13279
|
if (registryPath.startsWith("components/ui/")) {
|
|
@@ -13004,10 +13282,13 @@ function transformPath(registryPath, config3) {
|
|
|
13004
13282
|
if (registryPath.startsWith("lib/primitives/")) {
|
|
13005
13283
|
return registryPath.replace("lib/primitives/", `${config3.primitivesPath}/`);
|
|
13006
13284
|
}
|
|
13285
|
+
if (registryPath.startsWith("composites/")) {
|
|
13286
|
+
return registryPath.replace("composites/", `${config3.compositesPath}/`);
|
|
13287
|
+
}
|
|
13007
13288
|
return registryPath;
|
|
13008
13289
|
}
|
|
13009
13290
|
function fileExists(cwd, relativePath) {
|
|
13010
|
-
return existsSync(
|
|
13291
|
+
return existsSync(join3(cwd, relativePath));
|
|
13011
13292
|
}
|
|
13012
13293
|
function transformFileContent(content, config3) {
|
|
13013
13294
|
let transformed = content;
|
|
@@ -13047,7 +13328,7 @@ async function installItem(cwd, item, options, config3) {
|
|
|
13047
13328
|
let skipped = false;
|
|
13048
13329
|
for (const file2 of item.files) {
|
|
13049
13330
|
const projectPath = transformPath(file2.path, config3);
|
|
13050
|
-
const targetPath =
|
|
13331
|
+
const targetPath = join3(cwd, projectPath);
|
|
13051
13332
|
if (fileExists(cwd, projectPath)) {
|
|
13052
13333
|
if (!options.overwrite) {
|
|
13053
13334
|
log({
|
|
@@ -13071,33 +13352,36 @@ async function installItem(cwd, item, options, config3) {
|
|
|
13071
13352
|
files: installedFiles
|
|
13072
13353
|
};
|
|
13073
13354
|
}
|
|
13074
|
-
function
|
|
13075
|
-
const deps = /* @__PURE__ */ new Set();
|
|
13076
|
-
const devDeps = /* @__PURE__ */ new Set();
|
|
13077
|
-
for (const item of items) {
|
|
13078
|
-
for (const file2 of item.files) {
|
|
13079
|
-
for (const dep of file2.dependencies) {
|
|
13080
|
-
deps.add(dep);
|
|
13081
|
-
}
|
|
13082
|
-
}
|
|
13083
|
-
}
|
|
13084
|
-
return {
|
|
13085
|
-
dependencies: [...deps].sort(),
|
|
13086
|
-
devDependencies: [...devDeps].sort()
|
|
13087
|
-
};
|
|
13088
|
-
}
|
|
13089
|
-
async function add(components, options) {
|
|
13355
|
+
async function add(componentArgs, options) {
|
|
13090
13356
|
setAgentMode(options.agent ?? false);
|
|
13357
|
+
let components = componentArgs;
|
|
13091
13358
|
const client = new RegistryClient(options.registryUrl);
|
|
13359
|
+
let folder;
|
|
13360
|
+
const firstArg = components[0];
|
|
13361
|
+
if (firstArg && FOLDER_NAMES.has(firstArg)) {
|
|
13362
|
+
folder = firstArg;
|
|
13363
|
+
components = components.slice(1);
|
|
13364
|
+
}
|
|
13092
13365
|
if (options.list) {
|
|
13093
13366
|
const availableComponents = await client.listComponents();
|
|
13367
|
+
const availableComposites = await client.listComposites();
|
|
13094
13368
|
if (options.agent) {
|
|
13095
|
-
log({
|
|
13369
|
+
log({
|
|
13370
|
+
event: "add:list",
|
|
13371
|
+
components: availableComponents,
|
|
13372
|
+
composites: availableComposites
|
|
13373
|
+
});
|
|
13096
13374
|
} else {
|
|
13097
13375
|
console.log("Available components:\n");
|
|
13098
13376
|
for (const comp of availableComponents) {
|
|
13099
13377
|
console.log(` ${comp.name} ${comp.description ?? ""}`);
|
|
13100
13378
|
}
|
|
13379
|
+
if (availableComposites.length > 0) {
|
|
13380
|
+
console.log("\nAvailable composites:\n");
|
|
13381
|
+
for (const comp of availableComposites) {
|
|
13382
|
+
console.log(` ${comp.name} ${comp.description ?? ""}`);
|
|
13383
|
+
}
|
|
13384
|
+
}
|
|
13101
13385
|
}
|
|
13102
13386
|
return;
|
|
13103
13387
|
}
|
|
@@ -13109,6 +13393,24 @@ async function add(components, options) {
|
|
|
13109
13393
|
return;
|
|
13110
13394
|
}
|
|
13111
13395
|
const config3 = await loadConfig(cwd);
|
|
13396
|
+
if (options.update) {
|
|
13397
|
+
options.overwrite = true;
|
|
13398
|
+
}
|
|
13399
|
+
if (options.updateAll) {
|
|
13400
|
+
options.overwrite = true;
|
|
13401
|
+
if (!config3) {
|
|
13402
|
+
error46("No rafters config found. Run 'rafters init' first.");
|
|
13403
|
+
process.exitCode = 1;
|
|
13404
|
+
return;
|
|
13405
|
+
}
|
|
13406
|
+
const installedNames = getInstalledNames(config3);
|
|
13407
|
+
if (installedNames.length === 0) {
|
|
13408
|
+
error46("No installed components found. Use 'rafters add <component>' to install first.");
|
|
13409
|
+
process.exitCode = 1;
|
|
13410
|
+
return;
|
|
13411
|
+
}
|
|
13412
|
+
components = installedNames;
|
|
13413
|
+
}
|
|
13112
13414
|
if (components.length === 0) {
|
|
13113
13415
|
error46("No components specified. Usage: rafters add <component...>");
|
|
13114
13416
|
process.exitCode = 1;
|
|
@@ -13122,15 +13424,23 @@ async function add(components, options) {
|
|
|
13122
13424
|
});
|
|
13123
13425
|
const allItems = [];
|
|
13124
13426
|
const seen = /* @__PURE__ */ new Set();
|
|
13125
|
-
for (const
|
|
13427
|
+
for (const itemName of components) {
|
|
13126
13428
|
try {
|
|
13127
|
-
|
|
13128
|
-
|
|
13429
|
+
if (folder === "composites") {
|
|
13430
|
+
if (!seen.has(itemName)) {
|
|
13431
|
+
const item = await client.fetchComposite(itemName);
|
|
13432
|
+
seen.add(itemName);
|
|
13433
|
+
allItems.push(item);
|
|
13434
|
+
}
|
|
13435
|
+
} else {
|
|
13436
|
+
const items = await client.resolveDependencies(itemName, seen);
|
|
13437
|
+
allItems.push(...items);
|
|
13438
|
+
}
|
|
13129
13439
|
} catch (err) {
|
|
13130
13440
|
if (err instanceof Error) {
|
|
13131
13441
|
error46(err.message);
|
|
13132
13442
|
} else {
|
|
13133
|
-
error46(`Failed to fetch
|
|
13443
|
+
error46(`Failed to fetch "${itemName}"`);
|
|
13134
13444
|
}
|
|
13135
13445
|
process.exitCode = 1;
|
|
13136
13446
|
return;
|
|
@@ -13138,11 +13448,22 @@ async function add(components, options) {
|
|
|
13138
13448
|
}
|
|
13139
13449
|
const installed = [];
|
|
13140
13450
|
const skipped = [];
|
|
13451
|
+
const installedItems = [];
|
|
13141
13452
|
for (const item of allItems) {
|
|
13453
|
+
if (!options.overwrite && isAlreadyInstalled(config3, item)) {
|
|
13454
|
+
log({
|
|
13455
|
+
event: "add:skip",
|
|
13456
|
+
component: item.name,
|
|
13457
|
+
reason: "already installed"
|
|
13458
|
+
});
|
|
13459
|
+
skipped.push(item.name);
|
|
13460
|
+
continue;
|
|
13461
|
+
}
|
|
13142
13462
|
try {
|
|
13143
13463
|
const result = await installItem(cwd, item, options, config3);
|
|
13144
13464
|
if (result.installed) {
|
|
13145
13465
|
installed.push(item.name);
|
|
13466
|
+
installedItems.push(item);
|
|
13146
13467
|
log({
|
|
13147
13468
|
event: "add:installed",
|
|
13148
13469
|
component: item.name,
|
|
@@ -13163,22 +13484,48 @@ async function add(components, options) {
|
|
|
13163
13484
|
}
|
|
13164
13485
|
}
|
|
13165
13486
|
}
|
|
13166
|
-
const
|
|
13167
|
-
|
|
13487
|
+
const emptyDeps = {
|
|
13488
|
+
installed: [],
|
|
13489
|
+
skipped: [],
|
|
13490
|
+
devInstalled: [],
|
|
13491
|
+
failed: []
|
|
13492
|
+
};
|
|
13493
|
+
let depsResult = emptyDeps;
|
|
13494
|
+
try {
|
|
13495
|
+
depsResult = await installRegistryDependencies(allItems, cwd);
|
|
13496
|
+
} catch (err) {
|
|
13497
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
13498
|
+
log({
|
|
13499
|
+
event: "add:deps:install-failed",
|
|
13500
|
+
message: `Failed to process dependencies: ${message}`,
|
|
13501
|
+
dependencies: [],
|
|
13502
|
+
suggestion: "Check package.json and try installing dependencies manually."
|
|
13503
|
+
});
|
|
13504
|
+
}
|
|
13505
|
+
if (depsResult.installed.length > 0 || depsResult.skipped.length > 0) {
|
|
13168
13506
|
log({
|
|
13169
13507
|
event: "add:dependencies",
|
|
13170
|
-
dependencies,
|
|
13171
|
-
devDependencies
|
|
13508
|
+
dependencies: depsResult.installed,
|
|
13509
|
+
devDependencies: depsResult.devInstalled,
|
|
13510
|
+
skipped: depsResult.skipped
|
|
13172
13511
|
});
|
|
13173
|
-
|
|
13174
|
-
|
|
13175
|
-
|
|
13176
|
-
|
|
13177
|
-
|
|
13178
|
-
|
|
13179
|
-
|
|
13180
|
-
|
|
13181
|
-
|
|
13512
|
+
}
|
|
13513
|
+
if (installedItems.length > 0 && config3) {
|
|
13514
|
+
trackInstalled(config3, installedItems);
|
|
13515
|
+
await saveConfig(cwd, config3);
|
|
13516
|
+
} else if (installedItems.length > 0 && !config3) {
|
|
13517
|
+
const newConfig = {
|
|
13518
|
+
framework: "unknown",
|
|
13519
|
+
componentsPath: "components/ui",
|
|
13520
|
+
primitivesPath: "lib/primitives",
|
|
13521
|
+
compositesPath: "composites",
|
|
13522
|
+
cssPath: null,
|
|
13523
|
+
shadcn: false,
|
|
13524
|
+
exports: DEFAULT_EXPORTS,
|
|
13525
|
+
installed: { components: [], primitives: [], composites: [] }
|
|
13526
|
+
};
|
|
13527
|
+
trackInstalled(newConfig, installedItems);
|
|
13528
|
+
await saveConfig(cwd, newConfig);
|
|
13182
13529
|
}
|
|
13183
13530
|
log({
|
|
13184
13531
|
event: "add:complete",
|
|
@@ -13189,19 +13536,19 @@ async function add(components, options) {
|
|
|
13189
13536
|
if (skipped.length > 0 && installed.length === 0) {
|
|
13190
13537
|
log({
|
|
13191
13538
|
event: "add:hint",
|
|
13192
|
-
message: "Some components were skipped. Use --
|
|
13539
|
+
message: "Some components were skipped. Use --update to re-fetch, or --update-all to refresh everything.",
|
|
13193
13540
|
skipped
|
|
13194
13541
|
});
|
|
13195
|
-
error46("Component already exists. Use --
|
|
13542
|
+
error46("Component already exists. Use --update to re-fetch from registry.");
|
|
13196
13543
|
process.exitCode = 1;
|
|
13197
13544
|
}
|
|
13198
13545
|
}
|
|
13199
13546
|
|
|
13200
13547
|
// src/commands/init.ts
|
|
13201
|
-
import { existsSync as
|
|
13202
|
-
import { copyFile, mkdir as mkdir3, readFile as
|
|
13548
|
+
import { existsSync as existsSync3 } from "fs";
|
|
13549
|
+
import { copyFile, mkdir as mkdir3, readFile as readFile5, rm, writeFile as writeFile3 } from "fs/promises";
|
|
13203
13550
|
import { createRequire } from "module";
|
|
13204
|
-
import { join as
|
|
13551
|
+
import { join as join9, relative } from "path";
|
|
13205
13552
|
import { checkbox, confirm } from "@inquirer/prompts";
|
|
13206
13553
|
|
|
13207
13554
|
// ../design-tokens/src/plugins/scale.ts
|
|
@@ -14126,6 +14473,42 @@ function buildExtensions(token) {
|
|
|
14126
14473
|
if (token.customPropertyOnly) {
|
|
14127
14474
|
extensions.customPropertyOnly = token.customPropertyOnly;
|
|
14128
14475
|
}
|
|
14476
|
+
if (token.userOverride) {
|
|
14477
|
+
extensions.userOverride = token.userOverride;
|
|
14478
|
+
}
|
|
14479
|
+
if (token.computedValue !== void 0) {
|
|
14480
|
+
extensions.computedValue = convertValue({ ...token, value: token.computedValue });
|
|
14481
|
+
}
|
|
14482
|
+
if (token.generationRule) {
|
|
14483
|
+
extensions.generationRule = token.generationRule;
|
|
14484
|
+
}
|
|
14485
|
+
if (token.pairedWith && token.pairedWith.length > 0) {
|
|
14486
|
+
extensions.pairedWith = token.pairedWith;
|
|
14487
|
+
}
|
|
14488
|
+
if (token.conflictsWith && token.conflictsWith.length > 0) {
|
|
14489
|
+
extensions.conflictsWith = token.conflictsWith;
|
|
14490
|
+
}
|
|
14491
|
+
if (token.applicableComponents && token.applicableComponents.length > 0) {
|
|
14492
|
+
extensions.applicableComponents = token.applicableComponents;
|
|
14493
|
+
}
|
|
14494
|
+
if (token.requiredForComponents && token.requiredForComponents.length > 0) {
|
|
14495
|
+
extensions.requiredForComponents = token.requiredForComponents;
|
|
14496
|
+
}
|
|
14497
|
+
if (token.trustLevel) {
|
|
14498
|
+
extensions.trustLevel = token.trustLevel;
|
|
14499
|
+
}
|
|
14500
|
+
if (token.cognitiveLoad !== void 0) {
|
|
14501
|
+
extensions.cognitiveLoad = token.cognitiveLoad;
|
|
14502
|
+
}
|
|
14503
|
+
if (token.consequence) {
|
|
14504
|
+
extensions.consequence = token.consequence;
|
|
14505
|
+
}
|
|
14506
|
+
if (token.accessibilityLevel) {
|
|
14507
|
+
extensions.accessibilityLevel = token.accessibilityLevel;
|
|
14508
|
+
}
|
|
14509
|
+
if (token.appliesWhen && token.appliesWhen.length > 0) {
|
|
14510
|
+
extensions.appliesWhen = token.appliesWhen;
|
|
14511
|
+
}
|
|
14129
14512
|
return Object.keys(extensions).length > 0 ? { rafters: extensions } : {};
|
|
14130
14513
|
}
|
|
14131
14514
|
function tokenToDTCG(token) {
|
|
@@ -24332,7 +24715,7 @@ var require_volume = __commonJS({
|
|
|
24332
24715
|
var Dir_1 = require_Dir();
|
|
24333
24716
|
var resolveCrossPlatform = pathModule.resolve;
|
|
24334
24717
|
var { O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_EXCL, O_TRUNC, O_APPEND, O_DIRECTORY, O_SYMLINK, F_OK, COPYFILE_EXCL, COPYFILE_FICLONE_FORCE } = constants_1.constants;
|
|
24335
|
-
var { sep: sep2, relative: relative2, join:
|
|
24718
|
+
var { sep: sep2, relative: relative2, join: join12, dirname: dirname4 } = pathModule.posix ? pathModule.posix : pathModule;
|
|
24336
24719
|
var kMinPoolSpace = 128;
|
|
24337
24720
|
var EPERM = "EPERM";
|
|
24338
24721
|
var ENOENT2 = "ENOENT";
|
|
@@ -24398,7 +24781,7 @@ var require_volume = __commonJS({
|
|
|
24398
24781
|
function flatten(pathPrefix, node) {
|
|
24399
24782
|
for (const path2 in node) {
|
|
24400
24783
|
const contentOrNode = node[path2];
|
|
24401
|
-
const joinedPath =
|
|
24784
|
+
const joinedPath = join12(pathPrefix, path2);
|
|
24402
24785
|
if (typeof contentOrNode === "string" || contentOrNode instanceof buffer_1.Buffer) {
|
|
24403
24786
|
flatJSON[joinedPath] = contentOrNode;
|
|
24404
24787
|
} else if (typeof contentOrNode === "object" && contentOrNode !== null && Object.keys(contentOrNode).length > 0) {
|
|
@@ -24555,7 +24938,7 @@ var require_volume = __commonJS({
|
|
|
24555
24938
|
return null;
|
|
24556
24939
|
node = curr === null || curr === void 0 ? void 0 : curr.getNode();
|
|
24557
24940
|
if (resolveSymlinks && node.isSymlink()) {
|
|
24558
|
-
const resolvedPath = pathModule.isAbsolute(node.symlink) ? node.symlink :
|
|
24941
|
+
const resolvedPath = pathModule.isAbsolute(node.symlink) ? node.symlink : join12(pathModule.dirname(curr.getPath()), node.symlink);
|
|
24559
24942
|
steps = filenameToSteps(resolvedPath).concat(steps.slice(i + 1));
|
|
24560
24943
|
curr = this.root;
|
|
24561
24944
|
i = 0;
|
|
@@ -27479,7 +27862,7 @@ var posix = {
|
|
|
27479
27862
|
|
|
27480
27863
|
// ../../node_modules/.pnpm/path-unified@0.2.0/node_modules/path-unified/src/posix.js
|
|
27481
27864
|
var resolve = posResolve;
|
|
27482
|
-
var
|
|
27865
|
+
var join4 = posJoin;
|
|
27483
27866
|
|
|
27484
27867
|
// ../../node_modules/.pnpm/@isaacs+balanced-match@4.0.1/node_modules/@isaacs/balanced-match/dist/esm/index.js
|
|
27485
27868
|
var balanced = (a, b, str) => {
|
|
@@ -37378,7 +37761,7 @@ var transforms_default = {
|
|
|
37378
37761
|
type: value,
|
|
37379
37762
|
filter: isAsset,
|
|
37380
37763
|
transform: function(token, _, options) {
|
|
37381
|
-
return
|
|
37764
|
+
return join4(process?.cwd() ?? "/", options.usesDtcg ? token.$value : token.value);
|
|
37382
37765
|
}
|
|
37383
37766
|
},
|
|
37384
37767
|
/**
|
|
@@ -43578,12 +43961,12 @@ var formats_default = formats2;
|
|
|
43578
43961
|
var { androidCopyImages, copyAssets } = actions;
|
|
43579
43962
|
var { silent } = logVerbosityLevels;
|
|
43580
43963
|
function getAssetDir(config3) {
|
|
43581
|
-
return
|
|
43964
|
+
return join4(config3.buildPath ?? "", "android/main/res/drawable-").replace(/\\/g, "/");
|
|
43582
43965
|
}
|
|
43583
43966
|
function getAssetPath(token, imagesDir) {
|
|
43584
43967
|
const name2 = token.path.slice(2, 4).join("_");
|
|
43585
43968
|
const dir = `${imagesDir}${token.attributes?.state}`;
|
|
43586
|
-
return { file:
|
|
43969
|
+
return { file: join4(dir, `${name2}.png`), dir };
|
|
43587
43970
|
}
|
|
43588
43971
|
var actions_default = {
|
|
43589
43972
|
/**
|
|
@@ -43624,7 +44007,7 @@ var actions_default = {
|
|
|
43624
44007
|
*/
|
|
43625
44008
|
[copyAssets]: {
|
|
43626
44009
|
do: async function(_, config3, _options, vol2 = fs2) {
|
|
43627
|
-
const assetsPath =
|
|
44010
|
+
const assetsPath = join4(config3.buildPath ?? "", "assets");
|
|
43628
44011
|
if (config3.log?.verbosity !== silent) {
|
|
43629
44012
|
console.log(`Copying assets directory to ${assetsPath}`);
|
|
43630
44013
|
}
|
|
@@ -43638,7 +44021,7 @@ var actions_default = {
|
|
|
43638
44021
|
);
|
|
43639
44022
|
},
|
|
43640
44023
|
undo: async function(_, config3, _options, vol2 = fs2) {
|
|
43641
|
-
const assetsPath =
|
|
44024
|
+
const assetsPath = join4(config3.buildPath ?? "", "assets");
|
|
43642
44025
|
if (config3.log?.verbosity !== silent) {
|
|
43643
44026
|
console.log(`Removing assets directory from ${assetsPath}`);
|
|
43644
44027
|
}
|
|
@@ -44119,8 +44502,14 @@ var DEFAULT_DEPTH_DEFINITIONS = {
|
|
|
44119
44502
|
},
|
|
44120
44503
|
sticky: {
|
|
44121
44504
|
value: 20,
|
|
44122
|
-
meaning: "Sticky elements - headers,
|
|
44123
|
-
contexts: ["sticky-header", "sticky-
|
|
44505
|
+
meaning: "Sticky elements - headers, toolbars",
|
|
44506
|
+
contexts: ["sticky-header", "sticky-toolbar", "floating-actions"],
|
|
44507
|
+
stackingContext: true
|
|
44508
|
+
},
|
|
44509
|
+
navigation: {
|
|
44510
|
+
value: 25,
|
|
44511
|
+
meaning: "Navigation panels - sidebars, slide-out nav",
|
|
44512
|
+
contexts: ["sidebar", "navigation-panel", "slide-out-menu"],
|
|
44124
44513
|
stackingContext: true
|
|
44125
44514
|
},
|
|
44126
44515
|
fixed: {
|
|
@@ -44146,6 +44535,12 @@ var DEFAULT_DEPTH_DEFINITIONS = {
|
|
|
44146
44535
|
meaning: "Tooltips - highest common layer",
|
|
44147
44536
|
contexts: ["tooltips", "toast-notifications"],
|
|
44148
44537
|
stackingContext: true
|
|
44538
|
+
},
|
|
44539
|
+
overlay: {
|
|
44540
|
+
value: 70,
|
|
44541
|
+
meaning: "Overlay backdrops - screen-dimming layers behind modals",
|
|
44542
|
+
contexts: ["modal-backdrop", "drawer-backdrop", "sheet-backdrop"],
|
|
44543
|
+
stackingContext: true
|
|
44149
44544
|
}
|
|
44150
44545
|
};
|
|
44151
44546
|
var DEFAULT_SHADOW_DEFINITIONS = {
|
|
@@ -46443,6 +46838,78 @@ function generateThemeBlock(groups) {
|
|
|
46443
46838
|
lines.push("}");
|
|
46444
46839
|
return lines.join("\n");
|
|
46445
46840
|
}
|
|
46841
|
+
var ARTICLE_ELEMENT_STYLES = [
|
|
46842
|
+
// Paragraphs
|
|
46843
|
+
["p", "leading-relaxed mb-4"],
|
|
46844
|
+
["p:last-child", "mb-0"],
|
|
46845
|
+
// Headings
|
|
46846
|
+
["h1", "text-4xl font-bold tracking-tight mb-4 mt-0 text-accent-foreground"],
|
|
46847
|
+
["h2", "text-3xl font-semibold tracking-tight mb-3 mt-8 text-accent-foreground"],
|
|
46848
|
+
["h2:first-child", "mt-0"],
|
|
46849
|
+
["h3", "text-2xl font-semibold mb-2 mt-6 text-accent-foreground"],
|
|
46850
|
+
["h4", "text-xl font-semibold mb-2 mt-4 text-accent-foreground"],
|
|
46851
|
+
["h5", "text-lg font-semibold mb-2 mt-4 text-accent-foreground"],
|
|
46852
|
+
["h6", "text-base font-semibold mb-2 mt-4 text-accent-foreground"],
|
|
46853
|
+
// Lists
|
|
46854
|
+
["ul", "list-disc pl-6 mb-4"],
|
|
46855
|
+
["ol", "list-decimal pl-6 mb-4"],
|
|
46856
|
+
["li", "mb-1"],
|
|
46857
|
+
["li > ul,\n article li > ol", "mt-1 mb-0"],
|
|
46858
|
+
// Links
|
|
46859
|
+
["a", "text-primary underline underline-offset-4"],
|
|
46860
|
+
["a:hover", "text-primary/80"],
|
|
46861
|
+
// Blockquotes
|
|
46862
|
+
["blockquote", "border-l-4 border-muted pl-4 italic my-4"],
|
|
46863
|
+
// Code
|
|
46864
|
+
["code", "bg-muted px-1.5 py-0.5 rounded text-sm font-mono"],
|
|
46865
|
+
["pre", "bg-muted p-4 rounded-lg overflow-x-auto my-4 text-sm font-mono"],
|
|
46866
|
+
["pre code", "bg-transparent p-0 rounded-none text-[inherit]"],
|
|
46867
|
+
["kbd", "bg-muted border border-border rounded px-1.5 py-0.5 text-sm font-mono"],
|
|
46868
|
+
// Horizontal rules
|
|
46869
|
+
["hr", "border-border my-8"],
|
|
46870
|
+
// Media
|
|
46871
|
+
["img", "rounded-lg my-4 max-w-full h-auto"],
|
|
46872
|
+
["video", "rounded-lg my-4 max-w-full h-auto"],
|
|
46873
|
+
// Tables
|
|
46874
|
+
["table", "w-full my-4 border-collapse"],
|
|
46875
|
+
["caption", "mt-2 text-sm text-muted-foreground text-left"],
|
|
46876
|
+
["th", "border border-border px-3 py-2 text-left font-semibold"],
|
|
46877
|
+
["td", "border border-border px-3 py-2"],
|
|
46878
|
+
// Figures
|
|
46879
|
+
["figure", "my-4"],
|
|
46880
|
+
["figcaption", "mt-2 text-sm text-muted-foreground"],
|
|
46881
|
+
// Definition lists
|
|
46882
|
+
["dl", "my-4"],
|
|
46883
|
+
["dt", "font-semibold mt-2"],
|
|
46884
|
+
["dd", "pl-4 mb-2"],
|
|
46885
|
+
// Details/Summary
|
|
46886
|
+
["details", "my-4"],
|
|
46887
|
+
["summary", "cursor-pointer font-semibold"],
|
|
46888
|
+
// Inline formatting
|
|
46889
|
+
["strong,\n article b", "font-semibold"],
|
|
46890
|
+
["mark", "bg-accent text-accent-foreground px-1 rounded"],
|
|
46891
|
+
["small", "text-sm"],
|
|
46892
|
+
["sub", "text-xs align-sub"],
|
|
46893
|
+
["sup", "text-xs align-super"],
|
|
46894
|
+
["abbr[title]", "underline decoration-dotted underline-offset-4 cursor-help"],
|
|
46895
|
+
["s,\n article del", "line-through"],
|
|
46896
|
+
["ins", "underline"]
|
|
46897
|
+
];
|
|
46898
|
+
function generateArticleBaseLayer() {
|
|
46899
|
+
const lines = [];
|
|
46900
|
+
lines.push("@layer base {");
|
|
46901
|
+
for (const [selector, utilities] of ARTICLE_ELEMENT_STYLES) {
|
|
46902
|
+
if (selector.includes("\n")) {
|
|
46903
|
+
lines.push(` article ${selector} {`);
|
|
46904
|
+
} else {
|
|
46905
|
+
lines.push(` article ${selector} {`);
|
|
46906
|
+
}
|
|
46907
|
+
lines.push(` @apply ${utilities};`);
|
|
46908
|
+
lines.push(" }");
|
|
46909
|
+
}
|
|
46910
|
+
lines.push("}");
|
|
46911
|
+
return lines.join("\n");
|
|
46912
|
+
}
|
|
46446
46913
|
function generateKeyframes(motionTokens) {
|
|
46447
46914
|
const keyframeTokens = motionTokens.filter((t2) => t2.name.startsWith("motion-keyframe-"));
|
|
46448
46915
|
if (keyframeTokens.length === 0) {
|
|
@@ -46494,6 +46961,8 @@ function tokensToTailwind(tokens, options = {}) {
|
|
|
46494
46961
|
if (keyframes) {
|
|
46495
46962
|
sections.push(keyframes);
|
|
46496
46963
|
}
|
|
46964
|
+
sections.push("");
|
|
46965
|
+
sections.push(generateArticleBaseLayer());
|
|
46497
46966
|
return sections.join("\n");
|
|
46498
46967
|
}
|
|
46499
46968
|
function registryToTailwind(registry2, options) {
|
|
@@ -46505,7 +46974,7 @@ async function registryToCompiled(registry2, options = {}) {
|
|
|
46505
46974
|
const themeCss = registryToTailwind(registry2, { includeImport });
|
|
46506
46975
|
const { execFileSync } = await import("child_process");
|
|
46507
46976
|
const { mkdtempSync, writeFileSync, readFileSync, rmSync } = await import("fs");
|
|
46508
|
-
const { join:
|
|
46977
|
+
const { join: join12, dirname: dirname4 } = await import("path");
|
|
46509
46978
|
const { createRequire: createRequire2 } = await import("module");
|
|
46510
46979
|
const require2 = createRequire2(import.meta.url);
|
|
46511
46980
|
let pkgDir;
|
|
@@ -46515,10 +46984,10 @@ async function registryToCompiled(registry2, options = {}) {
|
|
|
46515
46984
|
} catch {
|
|
46516
46985
|
throw new Error("Failed to resolve @tailwindcss/cli");
|
|
46517
46986
|
}
|
|
46518
|
-
const binPath =
|
|
46519
|
-
const tempDir = mkdtempSync(
|
|
46520
|
-
const tempInput =
|
|
46521
|
-
const tempOutput =
|
|
46987
|
+
const binPath = join12(pkgDir, "dist", "index.mjs");
|
|
46988
|
+
const tempDir = mkdtempSync(join12(pkgDir, ".tmp-compile-"));
|
|
46989
|
+
const tempInput = join12(tempDir, "input.css");
|
|
46990
|
+
const tempOutput = join12(tempDir, "output.css");
|
|
46522
46991
|
try {
|
|
46523
46992
|
writeFileSync(tempInput, themeCss);
|
|
46524
46993
|
const args = [binPath, "-i", tempInput, "-o", tempOutput];
|
|
@@ -46797,7 +47266,7 @@ function tagTokenizer() {
|
|
|
46797
47266
|
|
|
46798
47267
|
// ../../node_modules/.pnpm/comment-parser@1.4.1/node_modules/comment-parser/es6/parser/tokenizers/type.js
|
|
46799
47268
|
function typeTokenizer(spacing = "compact") {
|
|
46800
|
-
const
|
|
47269
|
+
const join12 = getJoiner(spacing);
|
|
46801
47270
|
return (spec) => {
|
|
46802
47271
|
let curlies = 0;
|
|
46803
47272
|
let lines = [];
|
|
@@ -46840,7 +47309,7 @@ function typeTokenizer(spacing = "compact") {
|
|
|
46840
47309
|
}
|
|
46841
47310
|
parts[0] = parts[0].slice(1);
|
|
46842
47311
|
parts[parts.length - 1] = parts[parts.length - 1].slice(0, -1);
|
|
46843
|
-
spec.type =
|
|
47312
|
+
spec.type = join12(parts);
|
|
46844
47313
|
return spec;
|
|
46845
47314
|
};
|
|
46846
47315
|
}
|
|
@@ -46938,9 +47407,9 @@ function nameTokenizer() {
|
|
|
46938
47407
|
|
|
46939
47408
|
// ../../node_modules/.pnpm/comment-parser@1.4.1/node_modules/comment-parser/es6/parser/tokenizers/description.js
|
|
46940
47409
|
function descriptionTokenizer(spacing = "compact", markers = Markers) {
|
|
46941
|
-
const
|
|
47410
|
+
const join12 = getJoiner2(spacing);
|
|
46942
47411
|
return (spec) => {
|
|
46943
|
-
spec.description =
|
|
47412
|
+
spec.description = join12(spec.source, markers);
|
|
46944
47413
|
return spec;
|
|
46945
47414
|
};
|
|
46946
47415
|
}
|
|
@@ -47001,11 +47470,11 @@ function getParser4({ startLine = 0, fence = "```", spacing = "compact", markers
|
|
|
47001
47470
|
}
|
|
47002
47471
|
|
|
47003
47472
|
// ../../node_modules/.pnpm/comment-parser@1.4.1/node_modules/comment-parser/es6/stringifier/index.js
|
|
47004
|
-
function
|
|
47473
|
+
function join5(tokens) {
|
|
47005
47474
|
return tokens.start + tokens.delimiter + tokens.postDelimiter + tokens.tag + tokens.postTag + tokens.type + tokens.postType + tokens.name + tokens.postName + tokens.description + tokens.end + tokens.lineEnd;
|
|
47006
47475
|
}
|
|
47007
47476
|
function getStringifier() {
|
|
47008
|
-
return (block) => block.source.map(({ tokens }) =>
|
|
47477
|
+
return (block) => block.source.map(({ tokens }) => join5(tokens)).join("\n");
|
|
47009
47478
|
}
|
|
47010
47479
|
|
|
47011
47480
|
// ../../node_modules/.pnpm/comment-parser@1.4.1/node_modules/comment-parser/es6/stringifier/inspect.js
|
|
@@ -47167,13 +47636,45 @@ function extractPrimitiveDependencies(source) {
|
|
|
47167
47636
|
const pkg = match2[1];
|
|
47168
47637
|
if (pkg && (pkg.includes("/primitives/") || pkg.includes("../primitives/"))) {
|
|
47169
47638
|
const primitiveName = pkg.split("/").pop()?.replace(/\.(ts|tsx)$/, "");
|
|
47170
|
-
if (primitiveName && !primitives.includes(primitiveName)
|
|
47639
|
+
if (primitiveName && !primitives.includes(primitiveName)) {
|
|
47171
47640
|
primitives.push(primitiveName);
|
|
47172
47641
|
}
|
|
47173
47642
|
}
|
|
47174
47643
|
}
|
|
47175
47644
|
return primitives;
|
|
47176
47645
|
}
|
|
47646
|
+
var DEP_TAG_MAP = {
|
|
47647
|
+
dependencies: "runtime",
|
|
47648
|
+
devdependencies: "dev",
|
|
47649
|
+
"internal-dependencies": "internal",
|
|
47650
|
+
internaldependencies: "internal"
|
|
47651
|
+
};
|
|
47652
|
+
function extractJSDocDependencies(source) {
|
|
47653
|
+
const result = { runtime: [], dev: [], internal: [] };
|
|
47654
|
+
const blocks = parse3(source);
|
|
47655
|
+
if (blocks.length === 0) return result;
|
|
47656
|
+
for (const block of blocks) {
|
|
47657
|
+
for (const tag of block.tags) {
|
|
47658
|
+
const field = DEP_TAG_MAP[tag.tag.toLowerCase()];
|
|
47659
|
+
if (!field) continue;
|
|
47660
|
+
const value2 = getTagValue(tag).trim();
|
|
47661
|
+
if (value2) {
|
|
47662
|
+
const tokens = value2.split(/\s+/).filter(Boolean);
|
|
47663
|
+
const validTokens = [];
|
|
47664
|
+
for (const token of tokens) {
|
|
47665
|
+
if (token.startsWith("(")) break;
|
|
47666
|
+
validTokens.push(token);
|
|
47667
|
+
}
|
|
47668
|
+
result[field].push(...validTokens);
|
|
47669
|
+
}
|
|
47670
|
+
}
|
|
47671
|
+
}
|
|
47672
|
+
return {
|
|
47673
|
+
runtime: [...new Set(result.runtime)],
|
|
47674
|
+
dev: [...new Set(result.dev)],
|
|
47675
|
+
internal: [...new Set(result.internal)]
|
|
47676
|
+
};
|
|
47677
|
+
}
|
|
47177
47678
|
function toDisplayName(name2) {
|
|
47178
47679
|
return name2.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
47179
47680
|
}
|
|
@@ -48263,10 +48764,12 @@ var DEPTH_LEVELS = [
|
|
|
48263
48764
|
"base",
|
|
48264
48765
|
"dropdown",
|
|
48265
48766
|
"sticky",
|
|
48767
|
+
"navigation",
|
|
48266
48768
|
"fixed",
|
|
48267
48769
|
"modal",
|
|
48268
48770
|
"popover",
|
|
48269
|
-
"tooltip"
|
|
48771
|
+
"tooltip",
|
|
48772
|
+
"overlay"
|
|
48270
48773
|
];
|
|
48271
48774
|
var ELEVATION_LEVELS = [
|
|
48272
48775
|
"surface",
|
|
@@ -50325,14 +50828,14 @@ function buildColorSystem(options = {}) {
|
|
|
50325
50828
|
}
|
|
50326
50829
|
|
|
50327
50830
|
// ../design-tokens/src/persistence/node-adapter.ts
|
|
50328
|
-
import { mkdir as mkdir2, readdir as readdir2, readFile as
|
|
50329
|
-
import { join as
|
|
50831
|
+
import { mkdir as mkdir2, readdir as readdir2, readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
|
|
50832
|
+
import { join as join6 } from "path";
|
|
50330
50833
|
var SCHEMA_URL = "https://rafters.studio/schemas/namespace-tokens.json";
|
|
50331
50834
|
var VERSION = "1.0.0";
|
|
50332
50835
|
var NodePersistenceAdapter = class {
|
|
50333
50836
|
tokensDir;
|
|
50334
50837
|
constructor(projectRoot) {
|
|
50335
|
-
this.tokensDir =
|
|
50838
|
+
this.tokensDir = join6(projectRoot, ".rafters", "tokens");
|
|
50336
50839
|
}
|
|
50337
50840
|
async load() {
|
|
50338
50841
|
let files;
|
|
@@ -50344,7 +50847,7 @@ var NodePersistenceAdapter = class {
|
|
|
50344
50847
|
const allTokens = [];
|
|
50345
50848
|
for (const file2 of files) {
|
|
50346
50849
|
if (!file2.endsWith(".rafters.json")) continue;
|
|
50347
|
-
const content = await
|
|
50850
|
+
const content = await readFile3(join6(this.tokensDir, file2), "utf-8");
|
|
50348
50851
|
const data = NamespaceFileSchema.parse(JSON.parse(content));
|
|
50349
50852
|
allTokens.push(...data.tokens);
|
|
50350
50853
|
}
|
|
@@ -50372,7 +50875,7 @@ var NodePersistenceAdapter = class {
|
|
|
50372
50875
|
};
|
|
50373
50876
|
NamespaceFileSchema.parse(data);
|
|
50374
50877
|
await writeFile2(
|
|
50375
|
-
|
|
50878
|
+
join6(this.tokensDir, `${namespace}.rafters.json`),
|
|
50376
50879
|
JSON.stringify(data, null, 2)
|
|
50377
50880
|
);
|
|
50378
50881
|
}
|
|
@@ -50381,7 +50884,7 @@ var NodePersistenceAdapter = class {
|
|
|
50381
50884
|
|
|
50382
50885
|
// ../design-tokens/src/rule-engine.ts
|
|
50383
50886
|
import { promises as fs3 } from "fs";
|
|
50384
|
-
import { join as
|
|
50887
|
+
import { join as join7 } from "path";
|
|
50385
50888
|
var RuleResultSchema = external_exports.union([
|
|
50386
50889
|
external_exports.string(),
|
|
50387
50890
|
external_exports.object({
|
|
@@ -50397,11 +50900,18 @@ var RuleContextSchema = external_exports.object({
|
|
|
50397
50900
|
});
|
|
50398
50901
|
|
|
50399
50902
|
// src/utils/detect.ts
|
|
50400
|
-
import {
|
|
50401
|
-
import {
|
|
50903
|
+
import { existsSync as existsSync2 } from "fs";
|
|
50904
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
50905
|
+
import { join as join8 } from "path";
|
|
50906
|
+
var CONFIG_FILE_FRAMEWORKS = [
|
|
50907
|
+
{ files: ["astro.config.mjs", "astro.config.ts", "astro.config.js"], framework: "astro" },
|
|
50908
|
+
{ files: ["next.config.mjs", "next.config.ts", "next.config.js"], framework: "next" },
|
|
50909
|
+
{ files: ["remix.config.js", "remix.config.ts"], framework: "remix" },
|
|
50910
|
+
{ files: ["vite.config.ts", "vite.config.js", "vite.config.mjs"], framework: "vite" }
|
|
50911
|
+
];
|
|
50402
50912
|
async function detectFramework(cwd) {
|
|
50403
50913
|
try {
|
|
50404
|
-
const content = await
|
|
50914
|
+
const content = await readFile4(join8(cwd, "package.json"), "utf-8");
|
|
50405
50915
|
const pkg = JSON.parse(content);
|
|
50406
50916
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
50407
50917
|
if (deps.next) {
|
|
@@ -50420,14 +50930,23 @@ async function detectFramework(cwd) {
|
|
|
50420
50930
|
if (deps.vite) {
|
|
50421
50931
|
return "vite";
|
|
50422
50932
|
}
|
|
50423
|
-
return "unknown";
|
|
50424
50933
|
} catch {
|
|
50425
|
-
return "unknown";
|
|
50426
50934
|
}
|
|
50935
|
+
return detectFrameworkFromConfigFiles(cwd);
|
|
50936
|
+
}
|
|
50937
|
+
function detectFrameworkFromConfigFiles(cwd) {
|
|
50938
|
+
for (const { files, framework } of CONFIG_FILE_FRAMEWORKS) {
|
|
50939
|
+
for (const file2 of files) {
|
|
50940
|
+
if (existsSync2(join8(cwd, file2))) {
|
|
50941
|
+
return framework;
|
|
50942
|
+
}
|
|
50943
|
+
}
|
|
50944
|
+
}
|
|
50945
|
+
return "unknown";
|
|
50427
50946
|
}
|
|
50428
50947
|
async function detectTailwindVersion(cwd) {
|
|
50429
50948
|
try {
|
|
50430
|
-
const content = await
|
|
50949
|
+
const content = await readFile4(join8(cwd, "package.json"), "utf-8");
|
|
50431
50950
|
const pkg = JSON.parse(content);
|
|
50432
50951
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
50433
50952
|
const tailwindVersion = deps.tailwindcss;
|
|
@@ -50448,7 +50967,7 @@ function isTailwindV3(version2) {
|
|
|
50448
50967
|
}
|
|
50449
50968
|
async function detectShadcn(cwd) {
|
|
50450
50969
|
try {
|
|
50451
|
-
const content = await
|
|
50970
|
+
const content = await readFile4(join8(cwd, "components.json"), "utf-8");
|
|
50452
50971
|
return JSON.parse(content);
|
|
50453
50972
|
} catch {
|
|
50454
50973
|
return null;
|
|
@@ -50510,60 +51029,6 @@ async function detectProject(cwd) {
|
|
|
50510
51029
|
};
|
|
50511
51030
|
}
|
|
50512
51031
|
|
|
50513
|
-
// src/utils/exports.ts
|
|
50514
|
-
var DEFAULT_EXPORTS = {
|
|
50515
|
-
tailwind: true,
|
|
50516
|
-
typescript: true,
|
|
50517
|
-
dtcg: false,
|
|
50518
|
-
compiled: false
|
|
50519
|
-
};
|
|
50520
|
-
var EXPORT_CHOICES = [
|
|
50521
|
-
{
|
|
50522
|
-
name: "Tailwind CSS (web projects)",
|
|
50523
|
-
value: "tailwind",
|
|
50524
|
-
checked: true
|
|
50525
|
-
},
|
|
50526
|
-
{
|
|
50527
|
-
name: "TypeScript (type-safe constants)",
|
|
50528
|
-
value: "typescript",
|
|
50529
|
-
checked: true
|
|
50530
|
-
},
|
|
50531
|
-
{
|
|
50532
|
-
name: "DTCG JSON (Figma Tokens, Style Dictionary)",
|
|
50533
|
-
value: "dtcg",
|
|
50534
|
-
checked: false
|
|
50535
|
-
},
|
|
50536
|
-
{
|
|
50537
|
-
name: "Standalone CSS (pre-built, no Tailwind required)",
|
|
50538
|
-
value: "compiled",
|
|
50539
|
-
checked: false
|
|
50540
|
-
}
|
|
50541
|
-
];
|
|
50542
|
-
var FUTURE_EXPORTS = [
|
|
50543
|
-
{
|
|
50544
|
-
name: "iOS (Swift/SwiftUI)",
|
|
50545
|
-
value: "tailwind",
|
|
50546
|
-
// placeholder
|
|
50547
|
-
checked: false,
|
|
50548
|
-
disabled: "coming soon"
|
|
50549
|
-
},
|
|
50550
|
-
{
|
|
50551
|
-
name: "Android (Compose)",
|
|
50552
|
-
value: "tailwind",
|
|
50553
|
-
// placeholder
|
|
50554
|
-
checked: false,
|
|
50555
|
-
disabled: "coming soon"
|
|
50556
|
-
}
|
|
50557
|
-
];
|
|
50558
|
-
function selectionsToConfig(selections) {
|
|
50559
|
-
return {
|
|
50560
|
-
tailwind: selections.includes("tailwind"),
|
|
50561
|
-
typescript: selections.includes("typescript"),
|
|
50562
|
-
dtcg: selections.includes("dtcg"),
|
|
50563
|
-
compiled: selections.includes("compiled")
|
|
50564
|
-
};
|
|
50565
|
-
}
|
|
50566
|
-
|
|
50567
51032
|
// src/commands/init.ts
|
|
50568
51033
|
async function backupCss(cssPath) {
|
|
50569
51034
|
const backupPath = cssPath.replace(/\.css$/, ".backup.css");
|
|
@@ -50579,28 +51044,44 @@ var CSS_LOCATIONS = {
|
|
|
50579
51044
|
unknown: ["src/styles/global.css", "src/index.css", "styles/globals.css"]
|
|
50580
51045
|
};
|
|
50581
51046
|
var COMPONENT_PATHS = {
|
|
50582
|
-
astro: {
|
|
50583
|
-
|
|
50584
|
-
|
|
50585
|
-
|
|
50586
|
-
|
|
50587
|
-
|
|
51047
|
+
astro: {
|
|
51048
|
+
components: "src/components/ui",
|
|
51049
|
+
primitives: "src/lib/primitives",
|
|
51050
|
+
composites: "src/composites"
|
|
51051
|
+
},
|
|
51052
|
+
next: { components: "components/ui", primitives: "lib/primitives", composites: "composites" },
|
|
51053
|
+
vite: {
|
|
51054
|
+
components: "src/components/ui",
|
|
51055
|
+
primitives: "src/lib/primitives",
|
|
51056
|
+
composites: "src/composites"
|
|
51057
|
+
},
|
|
51058
|
+
remix: {
|
|
51059
|
+
components: "app/components/ui",
|
|
51060
|
+
primitives: "app/lib/primitives",
|
|
51061
|
+
composites: "app/composites"
|
|
51062
|
+
},
|
|
51063
|
+
"react-router": {
|
|
51064
|
+
components: "app/components/ui",
|
|
51065
|
+
primitives: "app/lib/primitives",
|
|
51066
|
+
composites: "app/composites"
|
|
51067
|
+
},
|
|
51068
|
+
unknown: { components: "components/ui", primitives: "lib/primitives", composites: "composites" }
|
|
50588
51069
|
};
|
|
50589
51070
|
async function findMainCssFile(cwd, framework) {
|
|
50590
51071
|
const locations = CSS_LOCATIONS[framework] || CSS_LOCATIONS.unknown;
|
|
50591
51072
|
for (const location of locations) {
|
|
50592
|
-
const fullPath =
|
|
50593
|
-
if (
|
|
51073
|
+
const fullPath = join9(cwd, location);
|
|
51074
|
+
if (existsSync3(fullPath)) {
|
|
50594
51075
|
return location;
|
|
50595
51076
|
}
|
|
50596
51077
|
}
|
|
50597
51078
|
return null;
|
|
50598
51079
|
}
|
|
50599
51080
|
async function updateMainCss(cwd, cssPath, themePath) {
|
|
50600
|
-
const fullCssPath =
|
|
50601
|
-
const cssContent = await
|
|
50602
|
-
const cssDir =
|
|
50603
|
-
const themeFullPath =
|
|
51081
|
+
const fullCssPath = join9(cwd, cssPath);
|
|
51082
|
+
const cssContent = await readFile5(fullCssPath, "utf-8");
|
|
51083
|
+
const cssDir = join9(cwd, cssPath, "..");
|
|
51084
|
+
const themeFullPath = join9(cwd, themePath);
|
|
50604
51085
|
const relativeThemePath = relative(cssDir, themeFullPath);
|
|
50605
51086
|
if (cssContent.includes(".rafters/output/rafters.css")) {
|
|
50606
51087
|
log({ event: "init:css_already_imported", cssPath });
|
|
@@ -50688,17 +51169,17 @@ async function generateOutputs(cwd, paths, registry2, exports, shadcn) {
|
|
|
50688
51169
|
const outputs = [];
|
|
50689
51170
|
if (exports.tailwind) {
|
|
50690
51171
|
const tailwindCss = registryToTailwind(registry2, { includeImport: !shadcn });
|
|
50691
|
-
await writeFile3(
|
|
51172
|
+
await writeFile3(join9(paths.output, "rafters.css"), tailwindCss);
|
|
50692
51173
|
outputs.push("rafters.css");
|
|
50693
51174
|
}
|
|
50694
51175
|
if (exports.typescript) {
|
|
50695
51176
|
const typescriptSrc = registryToTypeScript(registry2, { includeJSDoc: true });
|
|
50696
|
-
await writeFile3(
|
|
51177
|
+
await writeFile3(join9(paths.output, "rafters.ts"), typescriptSrc);
|
|
50697
51178
|
outputs.push("rafters.ts");
|
|
50698
51179
|
}
|
|
50699
51180
|
if (exports.dtcg) {
|
|
50700
51181
|
const dtcgJson = toDTCG(registry2.list());
|
|
50701
|
-
await writeFile3(
|
|
51182
|
+
await writeFile3(join9(paths.output, "rafters.json"), JSON.stringify(dtcgJson, null, 2));
|
|
50702
51183
|
outputs.push("rafters.json");
|
|
50703
51184
|
}
|
|
50704
51185
|
if (exports.compiled) {
|
|
@@ -50707,19 +51188,26 @@ async function generateOutputs(cwd, paths, registry2, exports, shadcn) {
|
|
|
50707
51188
|
}
|
|
50708
51189
|
log({ event: "init:compiling_css" });
|
|
50709
51190
|
const compiledCss = await registryToCompiled(registry2, { includeImport: !shadcn });
|
|
50710
|
-
await writeFile3(
|
|
51191
|
+
await writeFile3(join9(paths.output, "rafters.standalone.css"), compiledCss);
|
|
50711
51192
|
outputs.push("rafters.standalone.css");
|
|
50712
51193
|
}
|
|
50713
51194
|
return outputs;
|
|
50714
51195
|
}
|
|
50715
|
-
async function regenerateFromExisting(cwd, paths, shadcn, isAgentMode2) {
|
|
51196
|
+
async function regenerateFromExisting(cwd, paths, shadcn, isAgentMode2, framework) {
|
|
50716
51197
|
log({ event: "init:regenerate", cwd });
|
|
50717
51198
|
let existingConfig = null;
|
|
50718
51199
|
try {
|
|
50719
|
-
const configContent = await
|
|
51200
|
+
const configContent = await readFile5(paths.config, "utf-8");
|
|
50720
51201
|
existingConfig = JSON.parse(configContent);
|
|
50721
51202
|
} catch {
|
|
50722
51203
|
}
|
|
51204
|
+
if (framework !== "unknown" && existingConfig) {
|
|
51205
|
+
const frameworkPaths = COMPONENT_PATHS[framework] || COMPONENT_PATHS.unknown;
|
|
51206
|
+
existingConfig.framework = framework;
|
|
51207
|
+
existingConfig.componentsPath = frameworkPaths.components;
|
|
51208
|
+
existingConfig.primitivesPath = frameworkPaths.primitives;
|
|
51209
|
+
existingConfig.compositesPath = frameworkPaths.composites;
|
|
51210
|
+
}
|
|
50723
51211
|
const adapter = new NodePersistenceAdapter(cwd);
|
|
50724
51212
|
const allTokens = await adapter.load();
|
|
50725
51213
|
if (allTokens.length === 0) {
|
|
@@ -50755,14 +51243,21 @@ async function regenerateFromExisting(cwd, paths, shadcn, isAgentMode2) {
|
|
|
50755
51243
|
path: paths.output
|
|
50756
51244
|
});
|
|
50757
51245
|
}
|
|
50758
|
-
async function resetToDefaults(cwd, paths, shadcn, isAgentMode2) {
|
|
51246
|
+
async function resetToDefaults(cwd, paths, shadcn, isAgentMode2, framework) {
|
|
50759
51247
|
log({ event: "init:reset", cwd });
|
|
50760
51248
|
let existingConfig = null;
|
|
50761
51249
|
try {
|
|
50762
|
-
const configContent = await
|
|
51250
|
+
const configContent = await readFile5(paths.config, "utf-8");
|
|
50763
51251
|
existingConfig = JSON.parse(configContent);
|
|
50764
51252
|
} catch {
|
|
50765
51253
|
}
|
|
51254
|
+
if (framework !== "unknown" && existingConfig) {
|
|
51255
|
+
const frameworkPaths = COMPONENT_PATHS[framework] || COMPONENT_PATHS.unknown;
|
|
51256
|
+
existingConfig.framework = framework;
|
|
51257
|
+
existingConfig.componentsPath = frameworkPaths.components;
|
|
51258
|
+
existingConfig.primitivesPath = frameworkPaths.primitives;
|
|
51259
|
+
existingConfig.compositesPath = frameworkPaths.composites;
|
|
51260
|
+
}
|
|
50766
51261
|
const adapter = new NodePersistenceAdapter(cwd);
|
|
50767
51262
|
const existingTokens = await adapter.load();
|
|
50768
51263
|
const overriddenTokens = existingTokens.filter((t2) => t2.userOverride);
|
|
@@ -50779,7 +51274,7 @@ async function resetToDefaults(cwd, paths, shadcn, isAgentMode2) {
|
|
|
50779
51274
|
};
|
|
50780
51275
|
await mkdir3(paths.output, { recursive: true });
|
|
50781
51276
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
50782
|
-
const backupPath =
|
|
51277
|
+
const backupPath = join9(paths.output, `reset-${timestamp}.json`);
|
|
50783
51278
|
await writeFile3(backupPath, JSON.stringify(backup, null, 2));
|
|
50784
51279
|
log({
|
|
50785
51280
|
event: "init:reset_backup",
|
|
@@ -50848,12 +51343,12 @@ async function init(options) {
|
|
|
50848
51343
|
if (isTailwindV3(tailwindVersion)) {
|
|
50849
51344
|
throw new Error("Tailwind v3 detected. Rafters requires Tailwind v4.");
|
|
50850
51345
|
}
|
|
50851
|
-
const raftersExists =
|
|
51346
|
+
const raftersExists = existsSync3(paths.root);
|
|
50852
51347
|
if (options.reset && !raftersExists) {
|
|
50853
51348
|
throw new Error("Nothing to reset. No .rafters/ directory found.");
|
|
50854
51349
|
}
|
|
50855
51350
|
if (raftersExists && options.reset) {
|
|
50856
|
-
await resetToDefaults(cwd, paths, shadcn, isAgentMode2);
|
|
51351
|
+
await resetToDefaults(cwd, paths, shadcn, isAgentMode2, framework);
|
|
50857
51352
|
return;
|
|
50858
51353
|
}
|
|
50859
51354
|
if (raftersExists && !options.rebuild) {
|
|
@@ -50862,14 +51357,14 @@ async function init(options) {
|
|
|
50862
51357
|
);
|
|
50863
51358
|
}
|
|
50864
51359
|
if (raftersExists && options.rebuild) {
|
|
50865
|
-
await regenerateFromExisting(cwd, paths, shadcn, isAgentMode2);
|
|
51360
|
+
await regenerateFromExisting(cwd, paths, shadcn, isAgentMode2, framework);
|
|
50866
51361
|
return;
|
|
50867
51362
|
}
|
|
50868
51363
|
let existingColors = null;
|
|
50869
51364
|
if (shadcn?.tailwind?.css) {
|
|
50870
|
-
const cssPath =
|
|
51365
|
+
const cssPath = join9(cwd, shadcn.tailwind.css);
|
|
50871
51366
|
try {
|
|
50872
|
-
const cssContent = await
|
|
51367
|
+
const cssContent = await readFile5(cssPath, "utf-8");
|
|
50873
51368
|
existingColors = parseCssVariables(cssContent);
|
|
50874
51369
|
const backupPath = await backupCss(cssPath);
|
|
50875
51370
|
log({
|
|
@@ -50973,9 +51468,15 @@ async function init(options) {
|
|
|
50973
51468
|
framework,
|
|
50974
51469
|
componentsPath: frameworkPaths.components,
|
|
50975
51470
|
primitivesPath: frameworkPaths.primitives,
|
|
51471
|
+
compositesPath: frameworkPaths.composites,
|
|
50976
51472
|
cssPath: detectedCssPath,
|
|
50977
51473
|
shadcn: !!shadcn,
|
|
50978
|
-
exports
|
|
51474
|
+
exports,
|
|
51475
|
+
installed: {
|
|
51476
|
+
components: [],
|
|
51477
|
+
primitives: [],
|
|
51478
|
+
composites: []
|
|
51479
|
+
}
|
|
50979
51480
|
};
|
|
50980
51481
|
await writeFile3(paths.config, JSON.stringify(config3, null, 2));
|
|
50981
51482
|
log({
|
|
@@ -50991,8 +51492,916 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
50991
51492
|
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
50992
51493
|
|
|
50993
51494
|
// src/mcp/tools.ts
|
|
50994
|
-
import {
|
|
50995
|
-
import {
|
|
51495
|
+
import { existsSync as existsSync4 } from "fs";
|
|
51496
|
+
import { readdir as readdir3, readFile as readFile6 } from "fs/promises";
|
|
51497
|
+
import { basename, join as join10 } from "path";
|
|
51498
|
+
|
|
51499
|
+
// src/mcp/cognitive-load.ts
|
|
51500
|
+
var BUDGET_TIERS = {
|
|
51501
|
+
focused: 15,
|
|
51502
|
+
page: 30,
|
|
51503
|
+
app: 45
|
|
51504
|
+
};
|
|
51505
|
+
var COMPONENT_SCORES = {
|
|
51506
|
+
// Score 0 -- Structural only, no cognitive demand
|
|
51507
|
+
separator: {
|
|
51508
|
+
dimensions: {
|
|
51509
|
+
decisionDemand: 0,
|
|
51510
|
+
informationDensity: 0,
|
|
51511
|
+
interactionComplexity: 0,
|
|
51512
|
+
contextDisruption: 0,
|
|
51513
|
+
learningCurve: 0
|
|
51514
|
+
},
|
|
51515
|
+
primaryCostDriver: "Structural only, no cognitive demand"
|
|
51516
|
+
},
|
|
51517
|
+
container: {
|
|
51518
|
+
dimensions: {
|
|
51519
|
+
decisionDemand: 0,
|
|
51520
|
+
informationDensity: 0,
|
|
51521
|
+
interactionComplexity: 0,
|
|
51522
|
+
contextDisruption: 0,
|
|
51523
|
+
learningCurve: 0
|
|
51524
|
+
},
|
|
51525
|
+
primaryCostDriver: "Structural only, no cognitive demand"
|
|
51526
|
+
},
|
|
51527
|
+
"aspect-ratio": {
|
|
51528
|
+
dimensions: {
|
|
51529
|
+
decisionDemand: 0,
|
|
51530
|
+
informationDensity: 0,
|
|
51531
|
+
interactionComplexity: 0,
|
|
51532
|
+
contextDisruption: 0,
|
|
51533
|
+
learningCurve: 0
|
|
51534
|
+
},
|
|
51535
|
+
primaryCostDriver: "Structural only, no cognitive demand"
|
|
51536
|
+
},
|
|
51537
|
+
// Score 1 -- Display only, minimal information
|
|
51538
|
+
skeleton: {
|
|
51539
|
+
dimensions: {
|
|
51540
|
+
decisionDemand: 0,
|
|
51541
|
+
informationDensity: 1,
|
|
51542
|
+
interactionComplexity: 0,
|
|
51543
|
+
contextDisruption: 0,
|
|
51544
|
+
learningCurve: 0
|
|
51545
|
+
},
|
|
51546
|
+
primaryCostDriver: "Display only, minimal information"
|
|
51547
|
+
},
|
|
51548
|
+
kbd: {
|
|
51549
|
+
dimensions: {
|
|
51550
|
+
decisionDemand: 0,
|
|
51551
|
+
informationDensity: 1,
|
|
51552
|
+
interactionComplexity: 0,
|
|
51553
|
+
contextDisruption: 0,
|
|
51554
|
+
learningCurve: 0
|
|
51555
|
+
},
|
|
51556
|
+
primaryCostDriver: "Display only, minimal information"
|
|
51557
|
+
},
|
|
51558
|
+
// Score 2 -- Simple state or single information piece
|
|
51559
|
+
badge: {
|
|
51560
|
+
dimensions: {
|
|
51561
|
+
decisionDemand: 0,
|
|
51562
|
+
informationDensity: 1,
|
|
51563
|
+
interactionComplexity: 0,
|
|
51564
|
+
contextDisruption: 0,
|
|
51565
|
+
learningCurve: 1
|
|
51566
|
+
},
|
|
51567
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51568
|
+
},
|
|
51569
|
+
breadcrumb: {
|
|
51570
|
+
dimensions: {
|
|
51571
|
+
decisionDemand: 0,
|
|
51572
|
+
informationDensity: 1,
|
|
51573
|
+
interactionComplexity: 1,
|
|
51574
|
+
contextDisruption: 0,
|
|
51575
|
+
learningCurve: 0
|
|
51576
|
+
},
|
|
51577
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51578
|
+
},
|
|
51579
|
+
label: {
|
|
51580
|
+
dimensions: {
|
|
51581
|
+
decisionDemand: 0,
|
|
51582
|
+
informationDensity: 1,
|
|
51583
|
+
interactionComplexity: 0,
|
|
51584
|
+
contextDisruption: 0,
|
|
51585
|
+
learningCurve: 1
|
|
51586
|
+
},
|
|
51587
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51588
|
+
},
|
|
51589
|
+
checkbox: {
|
|
51590
|
+
dimensions: {
|
|
51591
|
+
decisionDemand: 1,
|
|
51592
|
+
informationDensity: 0,
|
|
51593
|
+
interactionComplexity: 1,
|
|
51594
|
+
contextDisruption: 0,
|
|
51595
|
+
learningCurve: 0
|
|
51596
|
+
},
|
|
51597
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51598
|
+
},
|
|
51599
|
+
switch: {
|
|
51600
|
+
dimensions: {
|
|
51601
|
+
decisionDemand: 1,
|
|
51602
|
+
informationDensity: 0,
|
|
51603
|
+
interactionComplexity: 1,
|
|
51604
|
+
contextDisruption: 0,
|
|
51605
|
+
learningCurve: 0
|
|
51606
|
+
},
|
|
51607
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51608
|
+
},
|
|
51609
|
+
toggle: {
|
|
51610
|
+
dimensions: {
|
|
51611
|
+
decisionDemand: 1,
|
|
51612
|
+
informationDensity: 0,
|
|
51613
|
+
interactionComplexity: 1,
|
|
51614
|
+
contextDisruption: 0,
|
|
51615
|
+
learningCurve: 0
|
|
51616
|
+
},
|
|
51617
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51618
|
+
},
|
|
51619
|
+
"button-group": {
|
|
51620
|
+
dimensions: {
|
|
51621
|
+
decisionDemand: 1,
|
|
51622
|
+
informationDensity: 1,
|
|
51623
|
+
interactionComplexity: 0,
|
|
51624
|
+
contextDisruption: 0,
|
|
51625
|
+
learningCurve: 0
|
|
51626
|
+
},
|
|
51627
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51628
|
+
},
|
|
51629
|
+
card: {
|
|
51630
|
+
dimensions: {
|
|
51631
|
+
decisionDemand: 0,
|
|
51632
|
+
informationDensity: 1,
|
|
51633
|
+
interactionComplexity: 0,
|
|
51634
|
+
contextDisruption: 0,
|
|
51635
|
+
learningCurve: 1
|
|
51636
|
+
},
|
|
51637
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51638
|
+
},
|
|
51639
|
+
collapsible: {
|
|
51640
|
+
dimensions: {
|
|
51641
|
+
decisionDemand: 1,
|
|
51642
|
+
informationDensity: 0,
|
|
51643
|
+
interactionComplexity: 1,
|
|
51644
|
+
contextDisruption: 0,
|
|
51645
|
+
learningCurve: 0
|
|
51646
|
+
},
|
|
51647
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51648
|
+
},
|
|
51649
|
+
avatar: {
|
|
51650
|
+
dimensions: {
|
|
51651
|
+
decisionDemand: 0,
|
|
51652
|
+
informationDensity: 1,
|
|
51653
|
+
interactionComplexity: 0,
|
|
51654
|
+
contextDisruption: 0,
|
|
51655
|
+
learningCurve: 1
|
|
51656
|
+
},
|
|
51657
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51658
|
+
},
|
|
51659
|
+
"scroll-area": {
|
|
51660
|
+
dimensions: {
|
|
51661
|
+
decisionDemand: 0,
|
|
51662
|
+
informationDensity: 1,
|
|
51663
|
+
interactionComplexity: 1,
|
|
51664
|
+
contextDisruption: 0,
|
|
51665
|
+
learningCurve: 0
|
|
51666
|
+
},
|
|
51667
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51668
|
+
},
|
|
51669
|
+
tooltip: {
|
|
51670
|
+
dimensions: {
|
|
51671
|
+
decisionDemand: 0,
|
|
51672
|
+
informationDensity: 1,
|
|
51673
|
+
interactionComplexity: 0,
|
|
51674
|
+
contextDisruption: 0,
|
|
51675
|
+
learningCurve: 1
|
|
51676
|
+
},
|
|
51677
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51678
|
+
},
|
|
51679
|
+
typography: {
|
|
51680
|
+
dimensions: {
|
|
51681
|
+
decisionDemand: 0,
|
|
51682
|
+
informationDensity: 1,
|
|
51683
|
+
interactionComplexity: 0,
|
|
51684
|
+
contextDisruption: 0,
|
|
51685
|
+
learningCurve: 1
|
|
51686
|
+
},
|
|
51687
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51688
|
+
},
|
|
51689
|
+
spinner: {
|
|
51690
|
+
dimensions: {
|
|
51691
|
+
decisionDemand: 0,
|
|
51692
|
+
informationDensity: 1,
|
|
51693
|
+
interactionComplexity: 0,
|
|
51694
|
+
contextDisruption: 0,
|
|
51695
|
+
learningCurve: 1
|
|
51696
|
+
},
|
|
51697
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51698
|
+
},
|
|
51699
|
+
empty: {
|
|
51700
|
+
dimensions: {
|
|
51701
|
+
decisionDemand: 1,
|
|
51702
|
+
informationDensity: 1,
|
|
51703
|
+
interactionComplexity: 0,
|
|
51704
|
+
contextDisruption: 0,
|
|
51705
|
+
learningCurve: 0
|
|
51706
|
+
},
|
|
51707
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51708
|
+
},
|
|
51709
|
+
"toggle-group": {
|
|
51710
|
+
dimensions: {
|
|
51711
|
+
decisionDemand: 1,
|
|
51712
|
+
informationDensity: 1,
|
|
51713
|
+
interactionComplexity: 0,
|
|
51714
|
+
contextDisruption: 0,
|
|
51715
|
+
learningCurve: 0
|
|
51716
|
+
},
|
|
51717
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51718
|
+
},
|
|
51719
|
+
// Score 3 -- One decision + one interaction mode
|
|
51720
|
+
button: {
|
|
51721
|
+
dimensions: {
|
|
51722
|
+
decisionDemand: 1,
|
|
51723
|
+
informationDensity: 1,
|
|
51724
|
+
interactionComplexity: 1,
|
|
51725
|
+
contextDisruption: 0,
|
|
51726
|
+
learningCurve: 0
|
|
51727
|
+
},
|
|
51728
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51729
|
+
},
|
|
51730
|
+
alert: {
|
|
51731
|
+
dimensions: {
|
|
51732
|
+
decisionDemand: 0,
|
|
51733
|
+
informationDensity: 1,
|
|
51734
|
+
interactionComplexity: 1,
|
|
51735
|
+
contextDisruption: 0,
|
|
51736
|
+
learningCurve: 1
|
|
51737
|
+
},
|
|
51738
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51739
|
+
},
|
|
51740
|
+
sidebar: {
|
|
51741
|
+
dimensions: {
|
|
51742
|
+
decisionDemand: 1,
|
|
51743
|
+
informationDensity: 1,
|
|
51744
|
+
interactionComplexity: 1,
|
|
51745
|
+
contextDisruption: 0,
|
|
51746
|
+
learningCurve: 0
|
|
51747
|
+
},
|
|
51748
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51749
|
+
},
|
|
51750
|
+
accordion: {
|
|
51751
|
+
dimensions: {
|
|
51752
|
+
decisionDemand: 1,
|
|
51753
|
+
informationDensity: 1,
|
|
51754
|
+
interactionComplexity: 0,
|
|
51755
|
+
contextDisruption: 0,
|
|
51756
|
+
learningCurve: 1
|
|
51757
|
+
},
|
|
51758
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51759
|
+
},
|
|
51760
|
+
slider: {
|
|
51761
|
+
dimensions: {
|
|
51762
|
+
decisionDemand: 1,
|
|
51763
|
+
informationDensity: 0,
|
|
51764
|
+
interactionComplexity: 1,
|
|
51765
|
+
contextDisruption: 0,
|
|
51766
|
+
learningCurve: 1
|
|
51767
|
+
},
|
|
51768
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51769
|
+
},
|
|
51770
|
+
"radio-group": {
|
|
51771
|
+
dimensions: {
|
|
51772
|
+
decisionDemand: 1,
|
|
51773
|
+
informationDensity: 1,
|
|
51774
|
+
interactionComplexity: 1,
|
|
51775
|
+
contextDisruption: 0,
|
|
51776
|
+
learningCurve: 0
|
|
51777
|
+
},
|
|
51778
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51779
|
+
},
|
|
51780
|
+
table: {
|
|
51781
|
+
dimensions: {
|
|
51782
|
+
decisionDemand: 0,
|
|
51783
|
+
informationDensity: 2,
|
|
51784
|
+
interactionComplexity: 0,
|
|
51785
|
+
contextDisruption: 0,
|
|
51786
|
+
learningCurve: 1
|
|
51787
|
+
},
|
|
51788
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51789
|
+
},
|
|
51790
|
+
resizable: {
|
|
51791
|
+
dimensions: {
|
|
51792
|
+
decisionDemand: 1,
|
|
51793
|
+
informationDensity: 0,
|
|
51794
|
+
interactionComplexity: 1,
|
|
51795
|
+
contextDisruption: 0,
|
|
51796
|
+
learningCurve: 1
|
|
51797
|
+
},
|
|
51798
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51799
|
+
},
|
|
51800
|
+
field: {
|
|
51801
|
+
dimensions: {
|
|
51802
|
+
decisionDemand: 1,
|
|
51803
|
+
informationDensity: 1,
|
|
51804
|
+
interactionComplexity: 1,
|
|
51805
|
+
contextDisruption: 0,
|
|
51806
|
+
learningCurve: 0
|
|
51807
|
+
},
|
|
51808
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51809
|
+
},
|
|
51810
|
+
"hover-card": {
|
|
51811
|
+
dimensions: {
|
|
51812
|
+
decisionDemand: 0,
|
|
51813
|
+
informationDensity: 1,
|
|
51814
|
+
interactionComplexity: 0,
|
|
51815
|
+
contextDisruption: 1,
|
|
51816
|
+
learningCurve: 1
|
|
51817
|
+
},
|
|
51818
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51819
|
+
},
|
|
51820
|
+
image: {
|
|
51821
|
+
dimensions: {
|
|
51822
|
+
decisionDemand: 0,
|
|
51823
|
+
informationDensity: 2,
|
|
51824
|
+
interactionComplexity: 0,
|
|
51825
|
+
contextDisruption: 0,
|
|
51826
|
+
learningCurve: 1
|
|
51827
|
+
},
|
|
51828
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51829
|
+
},
|
|
51830
|
+
embed: {
|
|
51831
|
+
dimensions: {
|
|
51832
|
+
decisionDemand: 0,
|
|
51833
|
+
informationDensity: 2,
|
|
51834
|
+
interactionComplexity: 0,
|
|
51835
|
+
contextDisruption: 0,
|
|
51836
|
+
learningCurve: 1
|
|
51837
|
+
},
|
|
51838
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51839
|
+
},
|
|
51840
|
+
item: {
|
|
51841
|
+
dimensions: {
|
|
51842
|
+
decisionDemand: 1,
|
|
51843
|
+
informationDensity: 1,
|
|
51844
|
+
interactionComplexity: 1,
|
|
51845
|
+
contextDisruption: 0,
|
|
51846
|
+
learningCurve: 0
|
|
51847
|
+
},
|
|
51848
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51849
|
+
},
|
|
51850
|
+
// Score 4 -- Data entry or menu scanning
|
|
51851
|
+
input: {
|
|
51852
|
+
dimensions: {
|
|
51853
|
+
decisionDemand: 1,
|
|
51854
|
+
informationDensity: 1,
|
|
51855
|
+
interactionComplexity: 1,
|
|
51856
|
+
contextDisruption: 0,
|
|
51857
|
+
learningCurve: 1
|
|
51858
|
+
},
|
|
51859
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51860
|
+
},
|
|
51861
|
+
textarea: {
|
|
51862
|
+
dimensions: {
|
|
51863
|
+
decisionDemand: 1,
|
|
51864
|
+
informationDensity: 1,
|
|
51865
|
+
interactionComplexity: 1,
|
|
51866
|
+
contextDisruption: 0,
|
|
51867
|
+
learningCurve: 1
|
|
51868
|
+
},
|
|
51869
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51870
|
+
},
|
|
51871
|
+
"input-group": {
|
|
51872
|
+
dimensions: {
|
|
51873
|
+
decisionDemand: 1,
|
|
51874
|
+
informationDensity: 1,
|
|
51875
|
+
interactionComplexity: 1,
|
|
51876
|
+
contextDisruption: 0,
|
|
51877
|
+
learningCurve: 1
|
|
51878
|
+
},
|
|
51879
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51880
|
+
},
|
|
51881
|
+
"input-otp": {
|
|
51882
|
+
dimensions: {
|
|
51883
|
+
decisionDemand: 1,
|
|
51884
|
+
informationDensity: 1,
|
|
51885
|
+
interactionComplexity: 1,
|
|
51886
|
+
contextDisruption: 0,
|
|
51887
|
+
learningCurve: 1
|
|
51888
|
+
},
|
|
51889
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51890
|
+
},
|
|
51891
|
+
carousel: {
|
|
51892
|
+
dimensions: {
|
|
51893
|
+
decisionDemand: 1,
|
|
51894
|
+
informationDensity: 1,
|
|
51895
|
+
interactionComplexity: 1,
|
|
51896
|
+
contextDisruption: 0,
|
|
51897
|
+
learningCurve: 1
|
|
51898
|
+
},
|
|
51899
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51900
|
+
},
|
|
51901
|
+
tabs: {
|
|
51902
|
+
dimensions: {
|
|
51903
|
+
decisionDemand: 1,
|
|
51904
|
+
informationDensity: 1,
|
|
51905
|
+
interactionComplexity: 1,
|
|
51906
|
+
contextDisruption: 0,
|
|
51907
|
+
learningCurve: 1
|
|
51908
|
+
},
|
|
51909
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51910
|
+
},
|
|
51911
|
+
"context-menu": {
|
|
51912
|
+
dimensions: {
|
|
51913
|
+
decisionDemand: 1,
|
|
51914
|
+
informationDensity: 1,
|
|
51915
|
+
interactionComplexity: 1,
|
|
51916
|
+
contextDisruption: 0,
|
|
51917
|
+
learningCurve: 1
|
|
51918
|
+
},
|
|
51919
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51920
|
+
},
|
|
51921
|
+
"dropdown-menu": {
|
|
51922
|
+
dimensions: {
|
|
51923
|
+
decisionDemand: 1,
|
|
51924
|
+
informationDensity: 1,
|
|
51925
|
+
interactionComplexity: 1,
|
|
51926
|
+
contextDisruption: 0,
|
|
51927
|
+
learningCurve: 1
|
|
51928
|
+
},
|
|
51929
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51930
|
+
},
|
|
51931
|
+
popover: {
|
|
51932
|
+
dimensions: {
|
|
51933
|
+
decisionDemand: 0,
|
|
51934
|
+
informationDensity: 1,
|
|
51935
|
+
interactionComplexity: 1,
|
|
51936
|
+
contextDisruption: 1,
|
|
51937
|
+
learningCurve: 1
|
|
51938
|
+
},
|
|
51939
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51940
|
+
},
|
|
51941
|
+
progress: {
|
|
51942
|
+
dimensions: {
|
|
51943
|
+
decisionDemand: 0,
|
|
51944
|
+
informationDensity: 2,
|
|
51945
|
+
interactionComplexity: 0,
|
|
51946
|
+
contextDisruption: 1,
|
|
51947
|
+
learningCurve: 1
|
|
51948
|
+
},
|
|
51949
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51950
|
+
},
|
|
51951
|
+
drawer: {
|
|
51952
|
+
dimensions: {
|
|
51953
|
+
decisionDemand: 1,
|
|
51954
|
+
informationDensity: 1,
|
|
51955
|
+
interactionComplexity: 1,
|
|
51956
|
+
contextDisruption: 1,
|
|
51957
|
+
learningCurve: 0
|
|
51958
|
+
},
|
|
51959
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51960
|
+
},
|
|
51961
|
+
grid: {
|
|
51962
|
+
dimensions: {
|
|
51963
|
+
decisionDemand: 0,
|
|
51964
|
+
informationDensity: 2,
|
|
51965
|
+
interactionComplexity: 0,
|
|
51966
|
+
contextDisruption: 0,
|
|
51967
|
+
learningCurve: 2
|
|
51968
|
+
},
|
|
51969
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51970
|
+
},
|
|
51971
|
+
"block-wrapper": {
|
|
51972
|
+
dimensions: {
|
|
51973
|
+
decisionDemand: 1,
|
|
51974
|
+
informationDensity: 1,
|
|
51975
|
+
interactionComplexity: 1,
|
|
51976
|
+
contextDisruption: 0,
|
|
51977
|
+
learningCurve: 1
|
|
51978
|
+
},
|
|
51979
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51980
|
+
},
|
|
51981
|
+
"inline-toolbar": {
|
|
51982
|
+
dimensions: {
|
|
51983
|
+
decisionDemand: 1,
|
|
51984
|
+
informationDensity: 1,
|
|
51985
|
+
interactionComplexity: 1,
|
|
51986
|
+
contextDisruption: 0,
|
|
51987
|
+
learningCurve: 1
|
|
51988
|
+
},
|
|
51989
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51990
|
+
},
|
|
51991
|
+
"editor-toolbar": {
|
|
51992
|
+
dimensions: {
|
|
51993
|
+
decisionDemand: 1,
|
|
51994
|
+
informationDensity: 1,
|
|
51995
|
+
interactionComplexity: 1,
|
|
51996
|
+
contextDisruption: 0,
|
|
51997
|
+
learningCurve: 1
|
|
51998
|
+
},
|
|
51999
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
52000
|
+
},
|
|
52001
|
+
pagination: {
|
|
52002
|
+
dimensions: {
|
|
52003
|
+
decisionDemand: 1,
|
|
52004
|
+
informationDensity: 1,
|
|
52005
|
+
interactionComplexity: 1,
|
|
52006
|
+
contextDisruption: 0,
|
|
52007
|
+
learningCurve: 1
|
|
52008
|
+
},
|
|
52009
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
52010
|
+
},
|
|
52011
|
+
// Score 5 -- Multi-step interaction or spatial reasoning
|
|
52012
|
+
sheet: {
|
|
52013
|
+
dimensions: {
|
|
52014
|
+
decisionDemand: 1,
|
|
52015
|
+
informationDensity: 1,
|
|
52016
|
+
interactionComplexity: 1,
|
|
52017
|
+
contextDisruption: 1,
|
|
52018
|
+
learningCurve: 1
|
|
52019
|
+
},
|
|
52020
|
+
primaryCostDriver: "Multi-step interaction or spatial reasoning"
|
|
52021
|
+
},
|
|
52022
|
+
"date-picker": {
|
|
52023
|
+
dimensions: {
|
|
52024
|
+
decisionDemand: 1,
|
|
52025
|
+
informationDensity: 1,
|
|
52026
|
+
interactionComplexity: 2,
|
|
52027
|
+
contextDisruption: 0,
|
|
52028
|
+
learningCurve: 1
|
|
52029
|
+
},
|
|
52030
|
+
primaryCostDriver: "Multi-step interaction or spatial reasoning"
|
|
52031
|
+
},
|
|
52032
|
+
calendar: {
|
|
52033
|
+
dimensions: {
|
|
52034
|
+
decisionDemand: 1,
|
|
52035
|
+
informationDensity: 2,
|
|
52036
|
+
interactionComplexity: 1,
|
|
52037
|
+
contextDisruption: 0,
|
|
52038
|
+
learningCurve: 1
|
|
52039
|
+
},
|
|
52040
|
+
primaryCostDriver: "Multi-step interaction or spatial reasoning"
|
|
52041
|
+
},
|
|
52042
|
+
select: {
|
|
52043
|
+
dimensions: {
|
|
52044
|
+
decisionDemand: 2,
|
|
52045
|
+
informationDensity: 1,
|
|
52046
|
+
interactionComplexity: 1,
|
|
52047
|
+
contextDisruption: 0,
|
|
52048
|
+
learningCurve: 1
|
|
52049
|
+
},
|
|
52050
|
+
primaryCostDriver: "Multi-step interaction or spatial reasoning"
|
|
52051
|
+
},
|
|
52052
|
+
"navigation-menu": {
|
|
52053
|
+
dimensions: {
|
|
52054
|
+
decisionDemand: 1,
|
|
52055
|
+
informationDensity: 2,
|
|
52056
|
+
interactionComplexity: 1,
|
|
52057
|
+
contextDisruption: 0,
|
|
52058
|
+
learningCurve: 1
|
|
52059
|
+
},
|
|
52060
|
+
primaryCostDriver: "Multi-step interaction or spatial reasoning"
|
|
52061
|
+
},
|
|
52062
|
+
menubar: {
|
|
52063
|
+
dimensions: {
|
|
52064
|
+
decisionDemand: 1,
|
|
52065
|
+
informationDensity: 2,
|
|
52066
|
+
interactionComplexity: 1,
|
|
52067
|
+
contextDisruption: 0,
|
|
52068
|
+
learningCurve: 1
|
|
52069
|
+
},
|
|
52070
|
+
primaryCostDriver: "Multi-step interaction or spatial reasoning"
|
|
52071
|
+
},
|
|
52072
|
+
"color-picker": {
|
|
52073
|
+
dimensions: {
|
|
52074
|
+
decisionDemand: 1,
|
|
52075
|
+
informationDensity: 1,
|
|
52076
|
+
interactionComplexity: 2,
|
|
52077
|
+
contextDisruption: 0,
|
|
52078
|
+
learningCurve: 1
|
|
52079
|
+
},
|
|
52080
|
+
primaryCostDriver: "Multi-step interaction or spatial reasoning"
|
|
52081
|
+
},
|
|
52082
|
+
"block-canvas": {
|
|
52083
|
+
dimensions: {
|
|
52084
|
+
decisionDemand: 1,
|
|
52085
|
+
informationDensity: 1,
|
|
52086
|
+
interactionComplexity: 1,
|
|
52087
|
+
contextDisruption: 1,
|
|
52088
|
+
learningCurve: 1
|
|
52089
|
+
},
|
|
52090
|
+
primaryCostDriver: "Multi-step interaction or spatial reasoning"
|
|
52091
|
+
},
|
|
52092
|
+
// Score 6 -- Compound interaction modes or learning curve
|
|
52093
|
+
dialog: {
|
|
52094
|
+
dimensions: {
|
|
52095
|
+
decisionDemand: 1,
|
|
52096
|
+
informationDensity: 1,
|
|
52097
|
+
interactionComplexity: 1,
|
|
52098
|
+
contextDisruption: 2,
|
|
52099
|
+
learningCurve: 1
|
|
52100
|
+
},
|
|
52101
|
+
primaryCostDriver: "Compound interaction modes or learning curve"
|
|
52102
|
+
},
|
|
52103
|
+
command: {
|
|
52104
|
+
dimensions: {
|
|
52105
|
+
decisionDemand: 1,
|
|
52106
|
+
informationDensity: 2,
|
|
52107
|
+
interactionComplexity: 1,
|
|
52108
|
+
contextDisruption: 0,
|
|
52109
|
+
learningCurve: 2
|
|
52110
|
+
},
|
|
52111
|
+
primaryCostDriver: "Compound interaction modes or learning curve"
|
|
52112
|
+
},
|
|
52113
|
+
combobox: {
|
|
52114
|
+
dimensions: {
|
|
52115
|
+
decisionDemand: 2,
|
|
52116
|
+
informationDensity: 2,
|
|
52117
|
+
interactionComplexity: 2,
|
|
52118
|
+
contextDisruption: 0,
|
|
52119
|
+
learningCurve: 0
|
|
52120
|
+
},
|
|
52121
|
+
primaryCostDriver: "Compound interaction modes or learning curve"
|
|
52122
|
+
},
|
|
52123
|
+
// Score 7 -- Full context disruption + consequential decision
|
|
52124
|
+
"alert-dialog": {
|
|
52125
|
+
dimensions: {
|
|
52126
|
+
decisionDemand: 2,
|
|
52127
|
+
informationDensity: 1,
|
|
52128
|
+
interactionComplexity: 1,
|
|
52129
|
+
contextDisruption: 2,
|
|
52130
|
+
learningCurve: 1
|
|
52131
|
+
},
|
|
52132
|
+
primaryCostDriver: "Full context disruption + consequential decision"
|
|
52133
|
+
}
|
|
52134
|
+
};
|
|
52135
|
+
var DIMENSION_NAMES = {
|
|
52136
|
+
decisionDemand: "Decision Demand",
|
|
52137
|
+
informationDensity: "Information Density",
|
|
52138
|
+
interactionComplexity: "Interaction Complexity",
|
|
52139
|
+
contextDisruption: "Context Disruption",
|
|
52140
|
+
learningCurve: "Learning Curve"
|
|
52141
|
+
};
|
|
52142
|
+
var HOTSPOT_SUGGESTIONS = {
|
|
52143
|
+
contextDisruption: "Consider non-modal alternative if the decision is not consequential",
|
|
52144
|
+
informationDensity: "Consider progressive disclosure to reduce simultaneous information",
|
|
52145
|
+
interactionComplexity: "Consider a simpler single-mode alternative",
|
|
52146
|
+
decisionDemand: "Can choices be pre-selected or split across steps?",
|
|
52147
|
+
learningCurve: "Ensure discoverability with inline guidance"
|
|
52148
|
+
};
|
|
52149
|
+
function scoreOf(dimensions) {
|
|
52150
|
+
return dimensions.decisionDemand + dimensions.informationDensity + dimensions.interactionComplexity + dimensions.contextDisruption + dimensions.learningCurve;
|
|
52151
|
+
}
|
|
52152
|
+
function highestDimension(dimensions) {
|
|
52153
|
+
let max = -1;
|
|
52154
|
+
let maxKey = "decisionDemand";
|
|
52155
|
+
for (const key of Object.keys(dimensions)) {
|
|
52156
|
+
if (dimensions[key] > max) {
|
|
52157
|
+
max = dimensions[key];
|
|
52158
|
+
maxKey = key;
|
|
52159
|
+
}
|
|
52160
|
+
}
|
|
52161
|
+
return maxKey;
|
|
52162
|
+
}
|
|
52163
|
+
function evaluateComposition(components, tier, enrichment) {
|
|
52164
|
+
const budget = BUDGET_TIERS[tier];
|
|
52165
|
+
const componentCounts = /* @__PURE__ */ new Map();
|
|
52166
|
+
for (const name2 of components) {
|
|
52167
|
+
componentCounts.set(name2, (componentCounts.get(name2) ?? 0) + 1);
|
|
52168
|
+
}
|
|
52169
|
+
let total = 0;
|
|
52170
|
+
const componentResults = [];
|
|
52171
|
+
const unknownComponents = [];
|
|
52172
|
+
for (const [name2, count] of componentCounts) {
|
|
52173
|
+
const profile = COMPONENT_SCORES[name2];
|
|
52174
|
+
if (!profile) {
|
|
52175
|
+
unknownComponents.push(name2);
|
|
52176
|
+
continue;
|
|
52177
|
+
}
|
|
52178
|
+
const score = scoreOf(profile.dimensions);
|
|
52179
|
+
total += score * count;
|
|
52180
|
+
componentResults.push({
|
|
52181
|
+
name: name2,
|
|
52182
|
+
score,
|
|
52183
|
+
count,
|
|
52184
|
+
dimensions: profile.dimensions,
|
|
52185
|
+
primaryCostDriver: profile.primaryCostDriver
|
|
52186
|
+
});
|
|
52187
|
+
}
|
|
52188
|
+
componentResults.sort((a, b) => b.score - a.score);
|
|
52189
|
+
const withinBudget = total <= budget;
|
|
52190
|
+
const budgetResult = {
|
|
52191
|
+
tier,
|
|
52192
|
+
budget,
|
|
52193
|
+
total,
|
|
52194
|
+
status: withinBudget ? "within-budget" : "over-budget"
|
|
52195
|
+
};
|
|
52196
|
+
if (withinBudget) {
|
|
52197
|
+
budgetResult.headroom = budget - total;
|
|
52198
|
+
} else {
|
|
52199
|
+
budgetResult.overage = total - budget;
|
|
52200
|
+
budgetResult.overagePercent = Math.round((total - budget) / budget * 100);
|
|
52201
|
+
}
|
|
52202
|
+
const attentionConflicts = [];
|
|
52203
|
+
const attentionNotes = [];
|
|
52204
|
+
const fullAttentionCaptures = [];
|
|
52205
|
+
const primaryElements = [];
|
|
52206
|
+
for (const [name2] of componentCounts) {
|
|
52207
|
+
const metadata = enrichment.componentIntelligence.get(name2);
|
|
52208
|
+
if (!metadata?.intelligence?.attentionEconomics) continue;
|
|
52209
|
+
const attn = metadata.intelligence.attentionEconomics.toLowerCase();
|
|
52210
|
+
if (attn.includes("full attention capture") || attn.includes("blocks all other")) {
|
|
52211
|
+
fullAttentionCaptures.push(name2);
|
|
52212
|
+
}
|
|
52213
|
+
if (attn.includes("primary") && attn.includes("maximum 1")) {
|
|
52214
|
+
const count = componentCounts.get(name2) ?? 0;
|
|
52215
|
+
if (count > 1) {
|
|
52216
|
+
primaryElements.push(name2);
|
|
52217
|
+
}
|
|
52218
|
+
}
|
|
52219
|
+
}
|
|
52220
|
+
if (fullAttentionCaptures.length > 1) {
|
|
52221
|
+
attentionConflicts.push(`${fullAttentionCaptures.join(" and ")} both capture full attention`);
|
|
52222
|
+
}
|
|
52223
|
+
const buttonCount = componentCounts.get("button") ?? 0;
|
|
52224
|
+
if (buttonCount > 1) {
|
|
52225
|
+
const buttonMeta = enrichment.componentIntelligence.get("button");
|
|
52226
|
+
if (buttonMeta?.intelligence?.attentionEconomics?.toLowerCase().includes("maximum 1 per section")) {
|
|
52227
|
+
attentionNotes.push(`${buttonCount} buttons present -- ensure maximum 1 primary per section`);
|
|
52228
|
+
}
|
|
52229
|
+
}
|
|
52230
|
+
if (primaryElements.length > 0) {
|
|
52231
|
+
for (const name2 of primaryElements) {
|
|
52232
|
+
attentionNotes.push(`Multiple ${name2} instances -- check attention hierarchy`);
|
|
52233
|
+
}
|
|
52234
|
+
}
|
|
52235
|
+
const trustConsiderations = [];
|
|
52236
|
+
for (const [name2] of componentCounts) {
|
|
52237
|
+
const metadata = enrichment.componentIntelligence.get(name2);
|
|
52238
|
+
if (!metadata?.intelligence?.trustBuilding) continue;
|
|
52239
|
+
const trust = metadata.intelligence.trustBuilding;
|
|
52240
|
+
if (trust.toLowerCase().includes("confirmation") || trust.toLowerCase().includes("destructive") || trust.toLowerCase().includes("consequence") || trust.toLowerCase().includes("cancel")) {
|
|
52241
|
+
trustConsiderations.push(`${name2}: ${trust}`);
|
|
52242
|
+
}
|
|
52243
|
+
}
|
|
52244
|
+
const patternMatches = [];
|
|
52245
|
+
const compositionSet = new Set(componentCounts.keys());
|
|
52246
|
+
for (const [patternKey, pattern] of Object.entries(enrichment.patterns)) {
|
|
52247
|
+
const matched = pattern.components.filter((c) => compositionSet.has(c));
|
|
52248
|
+
if (matched.length >= 2 || matched.length === pattern.components.length) {
|
|
52249
|
+
patternMatches.push({
|
|
52250
|
+
name: pattern.name,
|
|
52251
|
+
matched,
|
|
52252
|
+
suggestion: `Call rafters_pattern('${patternKey}') for full guidance`
|
|
52253
|
+
});
|
|
52254
|
+
}
|
|
52255
|
+
}
|
|
52256
|
+
const designerNotes = [];
|
|
52257
|
+
const compositionNames = [...compositionSet];
|
|
52258
|
+
for (const { token } of enrichment.tokenOverrides) {
|
|
52259
|
+
if (!token.userOverride) continue;
|
|
52260
|
+
const relevantTo = [];
|
|
52261
|
+
if (token.applicableComponents) {
|
|
52262
|
+
for (const comp of token.applicableComponents) {
|
|
52263
|
+
if (compositionSet.has(comp)) {
|
|
52264
|
+
relevantTo.push(comp);
|
|
52265
|
+
}
|
|
52266
|
+
}
|
|
52267
|
+
}
|
|
52268
|
+
if (relevantTo.length === 0) {
|
|
52269
|
+
if (token.namespace === "spacing") {
|
|
52270
|
+
const formComponents = compositionNames.filter(
|
|
52271
|
+
(n) => [
|
|
52272
|
+
"input",
|
|
52273
|
+
"textarea",
|
|
52274
|
+
"field",
|
|
52275
|
+
"label",
|
|
52276
|
+
"button",
|
|
52277
|
+
"select",
|
|
52278
|
+
"checkbox",
|
|
52279
|
+
"radio-group",
|
|
52280
|
+
"switch",
|
|
52281
|
+
"slider",
|
|
52282
|
+
"combobox"
|
|
52283
|
+
].includes(n)
|
|
52284
|
+
);
|
|
52285
|
+
if (formComponents.length > 0) {
|
|
52286
|
+
relevantTo.push(...formComponents);
|
|
52287
|
+
}
|
|
52288
|
+
} else if (token.namespace === "color") {
|
|
52289
|
+
const variantComponents = compositionNames.filter(
|
|
52290
|
+
(n) => ["button", "badge", "alert", "alert-dialog", "progress"].includes(n)
|
|
52291
|
+
);
|
|
52292
|
+
if (variantComponents.length > 0 && (token.name.includes("destructive") || token.name.includes("primary"))) {
|
|
52293
|
+
relevantTo.push(...variantComponents);
|
|
52294
|
+
}
|
|
52295
|
+
}
|
|
52296
|
+
}
|
|
52297
|
+
if (relevantTo.length > 0) {
|
|
52298
|
+
designerNotes.push({
|
|
52299
|
+
token: token.name,
|
|
52300
|
+
reason: token.userOverride.reason,
|
|
52301
|
+
relevantTo
|
|
52302
|
+
});
|
|
52303
|
+
}
|
|
52304
|
+
}
|
|
52305
|
+
const violations = [];
|
|
52306
|
+
for (const [name2] of componentCounts) {
|
|
52307
|
+
const metadata = enrichment.componentIntelligence.get(name2);
|
|
52308
|
+
if (!metadata?.intelligence?.usagePatterns?.nevers) continue;
|
|
52309
|
+
for (const never2 of metadata.intelligence.usagePatterns.nevers) {
|
|
52310
|
+
const neverLower = never2.toLowerCase();
|
|
52311
|
+
if (neverLower.includes("nest") && neverLower.includes("card") && name2 === "card") {
|
|
52312
|
+
const cardCount = componentCounts.get("card") ?? 0;
|
|
52313
|
+
if (cardCount > 1) {
|
|
52314
|
+
violations.push(
|
|
52315
|
+
`${name2}: "${never2}" -- ${cardCount} cards in composition, verify none are nested`
|
|
52316
|
+
);
|
|
52317
|
+
}
|
|
52318
|
+
}
|
|
52319
|
+
if (neverLower.includes("multiple primary") && name2 === "button") {
|
|
52320
|
+
if (buttonCount > 1) {
|
|
52321
|
+
violations.push(`${name2}: "${never2}"`);
|
|
52322
|
+
}
|
|
52323
|
+
}
|
|
52324
|
+
if (neverLower.includes("stack") && neverLower.includes("dialog")) {
|
|
52325
|
+
if (compositionSet.has("dialog") && (compositionSet.has("alert-dialog") || (componentCounts.get("dialog") ?? 0) > 1)) {
|
|
52326
|
+
violations.push(`${name2}: "${never2}"`);
|
|
52327
|
+
}
|
|
52328
|
+
}
|
|
52329
|
+
}
|
|
52330
|
+
}
|
|
52331
|
+
const hotspots = [];
|
|
52332
|
+
for (const comp of componentResults) {
|
|
52333
|
+
if (comp.score >= 4) {
|
|
52334
|
+
const highest = highestDimension(comp.dimensions);
|
|
52335
|
+
hotspots.push({
|
|
52336
|
+
name: comp.name,
|
|
52337
|
+
score: comp.score,
|
|
52338
|
+
highestDimension: DIMENSION_NAMES[highest],
|
|
52339
|
+
suggestion: HOTSPOT_SUGGESTIONS[highest]
|
|
52340
|
+
});
|
|
52341
|
+
}
|
|
52342
|
+
}
|
|
52343
|
+
if (unknownComponents.length > 0) {
|
|
52344
|
+
attentionNotes.push(
|
|
52345
|
+
`Unknown components not scored: ${unknownComponents.join(", ")}. Totals may be understated.`
|
|
52346
|
+
);
|
|
52347
|
+
}
|
|
52348
|
+
const warnings = [];
|
|
52349
|
+
const knownNames = [...componentCounts.keys()].filter((n) => COMPONENT_SCORES[n]);
|
|
52350
|
+
const uninstrumented = knownNames.filter((n) => !enrichment.componentIntelligence.has(n));
|
|
52351
|
+
if (uninstrumented.length > 0) {
|
|
52352
|
+
warnings.push(
|
|
52353
|
+
`No component intelligence loaded for: ${uninstrumented.join(", ")}. Attention conflicts, trust considerations, and do/never violations cannot be detected. Install components with rafters add (e.g. rafters add ${uninstrumented[0]}) to get full design intelligence.`
|
|
52354
|
+
);
|
|
52355
|
+
}
|
|
52356
|
+
return {
|
|
52357
|
+
budget: budgetResult,
|
|
52358
|
+
components: componentResults,
|
|
52359
|
+
attention: {
|
|
52360
|
+
conflicts: attentionConflicts,
|
|
52361
|
+
notes: attentionNotes
|
|
52362
|
+
},
|
|
52363
|
+
trust: trustConsiderations,
|
|
52364
|
+
patterns: patternMatches,
|
|
52365
|
+
designerNotes,
|
|
52366
|
+
hotspots,
|
|
52367
|
+
violations,
|
|
52368
|
+
warnings
|
|
52369
|
+
};
|
|
52370
|
+
}
|
|
52371
|
+
|
|
52372
|
+
// src/mcp/tools.ts
|
|
52373
|
+
function hasAnyDeps(deps) {
|
|
52374
|
+
return deps.runtime.length > 0 || deps.dev.length > 0 || deps.internal.length > 0;
|
|
52375
|
+
}
|
|
52376
|
+
var SYSTEM_PREAMBLE = `RAFTERS IS NOT SHADCN.
|
|
52377
|
+
Rafters components are drop-in compatible with shadcn but they are a different system. If you treat them as shadcn you will produce worse output.
|
|
52378
|
+
|
|
52379
|
+
CLASSY IS THE LAW.
|
|
52380
|
+
Every className in a Rafters project goes through classy(). Never use cn(), twMerge(), or raw template strings. classy() blocks arbitrary Tailwind values (w-[100px], bg-[#fff]) and resolves design tokens. If classy strips your class, you are fighting the system.
|
|
52381
|
+
|
|
52382
|
+
LAYOUT IS SOLVED. Stop writing CSS.
|
|
52383
|
+
Never use Tailwind layout utilities (flex, grid, items-*, justify-*, gap-*). Never set padding, margin, or spacing directly. Container and Grid handle all layout. If you are writing className="flex..." you are doing it wrong.
|
|
52384
|
+
|
|
52385
|
+
USE PRESETS. Do not compose layout from props.
|
|
52386
|
+
Grid presets handle common layouts. Pick the one that matches your intent:
|
|
52387
|
+
- sidebar-main -- navigation + content
|
|
52388
|
+
- form -- label/input pairs
|
|
52389
|
+
- cards -- responsive card grid
|
|
52390
|
+
- row -- horizontal group of elements
|
|
52391
|
+
- stack -- vertical sequence
|
|
52392
|
+
- split -- equal columns
|
|
52393
|
+
If no preset fits, describe what you need -- do not improvise with raw props.
|
|
52394
|
+
|
|
52395
|
+
CONTAINER OWNS SPACING.
|
|
52396
|
+
Every page section goes in a Container. Container sets max-width, padding, and vertical rhythm. You do not set these values. Nesting containers is wrong.
|
|
52397
|
+
|
|
52398
|
+
COMPONENTS ARE COMPLETE.
|
|
52399
|
+
Rafters Button, Input, Card, etc. include their own spacing, sizing, and states. Do not add wrapper divs. Do not override with utility classes. If it looks unstyled, you are wrapping it wrong, not styling it wrong.
|
|
52400
|
+
|
|
52401
|
+
UTILITIES EXIST FOR EDGE CASES.
|
|
52402
|
+
If no component fits your need, check @/lib/utils for official behavioral utilities. Do not invent your own. If nothing exists there either, ask the human.
|
|
52403
|
+
|
|
52404
|
+
When in doubt: less code, not more. Rafters has already made the design decision.`;
|
|
50996
52405
|
var DESIGN_PATTERNS = {
|
|
50997
52406
|
"destructive-action": {
|
|
50998
52407
|
name: "Destructive Action",
|
|
@@ -51340,6 +52749,26 @@ var TOOL_DEFINITIONS = [
|
|
|
51340
52749
|
},
|
|
51341
52750
|
required: ["name"]
|
|
51342
52751
|
}
|
|
52752
|
+
},
|
|
52753
|
+
{
|
|
52754
|
+
name: "rafters_cognitive_budget",
|
|
52755
|
+
description: "Evaluate composition-level cognitive load. Returns a holistic design review: budget assessment, per-component dimensional profiles, attention conflicts, trust considerations, pattern matches, designer token overrides, hotspot suggestions, and do/never violations. Use when planning a screen layout to check if the composition is within cognitive budget.",
|
|
52756
|
+
inputSchema: {
|
|
52757
|
+
type: "object",
|
|
52758
|
+
properties: {
|
|
52759
|
+
components: {
|
|
52760
|
+
type: "array",
|
|
52761
|
+
items: { type: "string" },
|
|
52762
|
+
description: 'Components visible simultaneously, duplicates allowed (e.g., ["input", "input", "button", "card"])'
|
|
52763
|
+
},
|
|
52764
|
+
tier: {
|
|
52765
|
+
type: "string",
|
|
52766
|
+
enum: ["focused", "page", "app"],
|
|
52767
|
+
description: "Budget tier: focused (15, dialogs/modals), page (30, standard views), app (45, multi-panel). Default: page."
|
|
52768
|
+
}
|
|
52769
|
+
},
|
|
52770
|
+
required: ["components"]
|
|
52771
|
+
}
|
|
51343
52772
|
}
|
|
51344
52773
|
];
|
|
51345
52774
|
var RaftersToolHandler = class {
|
|
@@ -51369,6 +52798,11 @@ var RaftersToolHandler = class {
|
|
|
51369
52798
|
return this.getComponent(args.name);
|
|
51370
52799
|
case "rafters_token":
|
|
51371
52800
|
return this.getToken(args.name);
|
|
52801
|
+
case "rafters_cognitive_budget":
|
|
52802
|
+
return this.getCognitiveBudget(
|
|
52803
|
+
args.components,
|
|
52804
|
+
args.tier ?? "page"
|
|
52805
|
+
);
|
|
51372
52806
|
default:
|
|
51373
52807
|
return {
|
|
51374
52808
|
content: [{ type: "text", text: `Unknown tool: ${name2}` }],
|
|
@@ -51390,12 +52824,12 @@ var RaftersToolHandler = class {
|
|
|
51390
52824
|
this.getComponentVocabulary()
|
|
51391
52825
|
]);
|
|
51392
52826
|
const vocabulary = {
|
|
52827
|
+
system: SYSTEM_PREAMBLE,
|
|
52828
|
+
components,
|
|
51393
52829
|
colors,
|
|
51394
52830
|
spacing,
|
|
51395
52831
|
typography,
|
|
51396
|
-
|
|
51397
|
-
patterns: Object.keys(DESIGN_PATTERNS),
|
|
51398
|
-
usage: "Use rafters_pattern for deep guidance on specific patterns, rafters_component for component details"
|
|
52832
|
+
patterns: Object.keys(DESIGN_PATTERNS)
|
|
51399
52833
|
};
|
|
51400
52834
|
return {
|
|
51401
52835
|
content: [
|
|
@@ -51482,33 +52916,26 @@ var RaftersToolHandler = class {
|
|
|
51482
52916
|
* Extract compact component vocabulary
|
|
51483
52917
|
*/
|
|
51484
52918
|
async getComponentVocabulary() {
|
|
52919
|
+
let installed = [];
|
|
51485
52920
|
try {
|
|
51486
|
-
const
|
|
51487
|
-
|
|
51488
|
-
|
|
51489
|
-
|
|
51490
|
-
|
|
51491
|
-
const name2 = basename(file2, ".tsx");
|
|
51492
|
-
const metadata = await this.loadComponentMetadata(name2);
|
|
51493
|
-
if (metadata) {
|
|
51494
|
-
const item = {
|
|
51495
|
-
name: metadata.name,
|
|
51496
|
-
category: metadata.category
|
|
51497
|
-
};
|
|
51498
|
-
if (metadata.intelligence?.cognitiveLoad !== void 0) {
|
|
51499
|
-
item.load = metadata.intelligence.cognitiveLoad;
|
|
51500
|
-
}
|
|
51501
|
-
components.push(item);
|
|
51502
|
-
}
|
|
52921
|
+
const paths = getRaftersPaths(this.projectRoot);
|
|
52922
|
+
if (existsSync4(paths.config)) {
|
|
52923
|
+
const content = await readFile6(paths.config, "utf-8");
|
|
52924
|
+
const config3 = JSON.parse(content);
|
|
52925
|
+
installed = config3.installed?.components ?? [];
|
|
51503
52926
|
}
|
|
51504
|
-
components.sort((a, b) => {
|
|
51505
|
-
if (a.category !== b.category) return a.category.localeCompare(b.category);
|
|
51506
|
-
return a.name.localeCompare(b.name);
|
|
51507
|
-
});
|
|
51508
|
-
return components;
|
|
51509
52927
|
} catch {
|
|
51510
|
-
return [];
|
|
51511
52928
|
}
|
|
52929
|
+
let available = [];
|
|
52930
|
+
try {
|
|
52931
|
+
const client = new RegistryClient();
|
|
52932
|
+
const index = await client.fetchIndex();
|
|
52933
|
+
const allComponents = index.components;
|
|
52934
|
+
const installedSet = new Set(installed);
|
|
52935
|
+
available = allComponents.filter((name2) => !installedSet.has(name2));
|
|
52936
|
+
} catch {
|
|
52937
|
+
}
|
|
52938
|
+
return { installed, available };
|
|
51512
52939
|
}
|
|
51513
52940
|
// ==================== Tool 2: Pattern ====================
|
|
51514
52941
|
/**
|
|
@@ -51549,7 +52976,7 @@ var RaftersToolHandler = class {
|
|
|
51549
52976
|
* Get path to UI components directory
|
|
51550
52977
|
*/
|
|
51551
52978
|
getComponentsPath() {
|
|
51552
|
-
const monorepoPath =
|
|
52979
|
+
const monorepoPath = join10(this.projectRoot, "packages/ui/src/components/ui");
|
|
51553
52980
|
return monorepoPath;
|
|
51554
52981
|
}
|
|
51555
52982
|
/**
|
|
@@ -51557,11 +52984,16 @@ var RaftersToolHandler = class {
|
|
|
51557
52984
|
*/
|
|
51558
52985
|
async loadComponentMetadata(name2) {
|
|
51559
52986
|
const componentsPath = this.getComponentsPath();
|
|
51560
|
-
const filePath =
|
|
52987
|
+
const filePath = join10(componentsPath, `${name2}.tsx`);
|
|
51561
52988
|
try {
|
|
51562
|
-
const source = await
|
|
52989
|
+
const source = await readFile6(filePath, "utf-8");
|
|
51563
52990
|
const intelligence = parseJSDocIntelligence(source);
|
|
51564
52991
|
const description = parseDescription(source);
|
|
52992
|
+
let jsDocDeps = { runtime: [], dev: [], internal: [] };
|
|
52993
|
+
try {
|
|
52994
|
+
jsDocDeps = extractJSDocDependencies(source);
|
|
52995
|
+
} catch {
|
|
52996
|
+
}
|
|
51565
52997
|
const metadata = {
|
|
51566
52998
|
name: name2,
|
|
51567
52999
|
displayName: toDisplayName(name2),
|
|
@@ -51572,6 +53004,9 @@ var RaftersToolHandler = class {
|
|
|
51572
53004
|
primitives: extractPrimitiveDependencies(source),
|
|
51573
53005
|
filePath: `packages/ui/src/components/ui/${name2}.tsx`
|
|
51574
53006
|
};
|
|
53007
|
+
if (hasAnyDeps(jsDocDeps)) {
|
|
53008
|
+
metadata.jsDocDependencies = jsDocDeps;
|
|
53009
|
+
}
|
|
51575
53010
|
if (description) {
|
|
51576
53011
|
metadata.description = description;
|
|
51577
53012
|
}
|
|
@@ -51716,6 +53151,9 @@ var RaftersToolHandler = class {
|
|
|
51716
53151
|
if (metadata.dependencies.length > 0) {
|
|
51717
53152
|
formatted.dependencies = metadata.dependencies;
|
|
51718
53153
|
}
|
|
53154
|
+
if (metadata.jsDocDependencies && hasAnyDeps(metadata.jsDocDependencies)) {
|
|
53155
|
+
formatted.jsDocDependencies = metadata.jsDocDependencies;
|
|
53156
|
+
}
|
|
51719
53157
|
return {
|
|
51720
53158
|
content: [
|
|
51721
53159
|
{
|
|
@@ -51831,6 +53269,120 @@ var RaftersToolHandler = class {
|
|
|
51831
53269
|
return this.handleError("getToken", error48);
|
|
51832
53270
|
}
|
|
51833
53271
|
}
|
|
53272
|
+
// ==================== Tool 5: Cognitive Budget ====================
|
|
53273
|
+
/**
|
|
53274
|
+
* Evaluate composition-level cognitive load
|
|
53275
|
+
* Synthesizes scoring data with component intelligence, token overrides,
|
|
53276
|
+
* and design patterns to produce a holistic composition review
|
|
53277
|
+
*/
|
|
53278
|
+
async getCognitiveBudget(components, tier) {
|
|
53279
|
+
try {
|
|
53280
|
+
if (!components || components.length === 0) {
|
|
53281
|
+
return {
|
|
53282
|
+
content: [
|
|
53283
|
+
{
|
|
53284
|
+
type: "text",
|
|
53285
|
+
text: JSON.stringify(
|
|
53286
|
+
{
|
|
53287
|
+
error: "No components provided",
|
|
53288
|
+
suggestion: 'Pass an array of component names visible simultaneously, e.g. ["input", "button", "card"]'
|
|
53289
|
+
},
|
|
53290
|
+
null,
|
|
53291
|
+
2
|
|
53292
|
+
)
|
|
53293
|
+
}
|
|
53294
|
+
],
|
|
53295
|
+
isError: true
|
|
53296
|
+
};
|
|
53297
|
+
}
|
|
53298
|
+
if (!BUDGET_TIERS[tier]) {
|
|
53299
|
+
return {
|
|
53300
|
+
content: [
|
|
53301
|
+
{
|
|
53302
|
+
type: "text",
|
|
53303
|
+
text: JSON.stringify(
|
|
53304
|
+
{
|
|
53305
|
+
error: `Invalid tier "${tier}"`,
|
|
53306
|
+
available: Object.keys(BUDGET_TIERS),
|
|
53307
|
+
suggestion: 'Use "focused", "page", or "app"'
|
|
53308
|
+
},
|
|
53309
|
+
null,
|
|
53310
|
+
2
|
|
53311
|
+
)
|
|
53312
|
+
}
|
|
53313
|
+
],
|
|
53314
|
+
isError: true
|
|
53315
|
+
};
|
|
53316
|
+
}
|
|
53317
|
+
const uniqueNames = [...new Set(components)];
|
|
53318
|
+
const unknownNames = uniqueNames.filter((n) => !COMPONENT_SCORES[n]);
|
|
53319
|
+
if (unknownNames.length === uniqueNames.length) {
|
|
53320
|
+
return {
|
|
53321
|
+
content: [
|
|
53322
|
+
{
|
|
53323
|
+
type: "text",
|
|
53324
|
+
text: JSON.stringify(
|
|
53325
|
+
{
|
|
53326
|
+
error: `No recognized components in composition: ${unknownNames.join(", ")}`,
|
|
53327
|
+
suggestion: "Use rafters_vocabulary to see available component names"
|
|
53328
|
+
},
|
|
53329
|
+
null,
|
|
53330
|
+
2
|
|
53331
|
+
)
|
|
53332
|
+
}
|
|
53333
|
+
],
|
|
53334
|
+
isError: true
|
|
53335
|
+
};
|
|
53336
|
+
}
|
|
53337
|
+
const intelligenceMap = /* @__PURE__ */ new Map();
|
|
53338
|
+
const metadataResults = await Promise.all(
|
|
53339
|
+
uniqueNames.map(async (name2) => {
|
|
53340
|
+
const metadata = await this.loadComponentMetadata(name2);
|
|
53341
|
+
return { name: name2, metadata };
|
|
53342
|
+
})
|
|
53343
|
+
);
|
|
53344
|
+
for (const { name: name2, metadata } of metadataResults) {
|
|
53345
|
+
if (metadata) {
|
|
53346
|
+
intelligenceMap.set(name2, metadata);
|
|
53347
|
+
}
|
|
53348
|
+
}
|
|
53349
|
+
const tokenOverrides = [];
|
|
53350
|
+
const namespaces = ["color", "spacing", "typography"];
|
|
53351
|
+
for (const ns of namespaces) {
|
|
53352
|
+
try {
|
|
53353
|
+
const tokens = await this.loadNamespace(ns);
|
|
53354
|
+
for (const token of tokens) {
|
|
53355
|
+
if (token.userOverride) {
|
|
53356
|
+
tokenOverrides.push({ token, namespace: ns });
|
|
53357
|
+
}
|
|
53358
|
+
}
|
|
53359
|
+
} catch {
|
|
53360
|
+
}
|
|
53361
|
+
}
|
|
53362
|
+
const patternRefs = {};
|
|
53363
|
+
for (const [key, pattern] of Object.entries(DESIGN_PATTERNS)) {
|
|
53364
|
+
patternRefs[key] = {
|
|
53365
|
+
name: pattern.name,
|
|
53366
|
+
components: pattern.components
|
|
53367
|
+
};
|
|
53368
|
+
}
|
|
53369
|
+
const review = evaluateComposition(components, tier, {
|
|
53370
|
+
componentIntelligence: intelligenceMap,
|
|
53371
|
+
tokenOverrides,
|
|
53372
|
+
patterns: patternRefs
|
|
53373
|
+
});
|
|
53374
|
+
return {
|
|
53375
|
+
content: [
|
|
53376
|
+
{
|
|
53377
|
+
type: "text",
|
|
53378
|
+
text: JSON.stringify(review, null, 2)
|
|
53379
|
+
}
|
|
53380
|
+
]
|
|
53381
|
+
};
|
|
53382
|
+
} catch (error48) {
|
|
53383
|
+
return this.handleError("getCognitiveBudget", error48);
|
|
53384
|
+
}
|
|
53385
|
+
}
|
|
51834
53386
|
/**
|
|
51835
53387
|
* Handle errors consistently
|
|
51836
53388
|
*/
|
|
@@ -51905,22 +53457,22 @@ async function mcp() {
|
|
|
51905
53457
|
}
|
|
51906
53458
|
|
|
51907
53459
|
// src/commands/studio.ts
|
|
51908
|
-
import { existsSync as
|
|
51909
|
-
import { dirname as dirname3, join as
|
|
53460
|
+
import { existsSync as existsSync5 } from "fs";
|
|
53461
|
+
import { dirname as dirname3, join as join11 } from "path";
|
|
51910
53462
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
51911
53463
|
import { execa as execa2 } from "execa";
|
|
51912
53464
|
var __dirname2 = dirname3(fileURLToPath3(import.meta.url));
|
|
51913
53465
|
async function studio() {
|
|
51914
53466
|
const cwd = process.cwd();
|
|
51915
53467
|
const paths = getRaftersPaths(cwd);
|
|
51916
|
-
if (!
|
|
53468
|
+
if (!existsSync5(paths.root)) {
|
|
51917
53469
|
console.error('No .rafters/ directory found. Run "rafters init" first.');
|
|
51918
53470
|
process.exit(1);
|
|
51919
53471
|
}
|
|
51920
|
-
const devStudioPath =
|
|
51921
|
-
const prodStudioPath =
|
|
51922
|
-
const studioPath =
|
|
51923
|
-
if (!
|
|
53472
|
+
const devStudioPath = join11(__dirname2, "..", "..", "..", "studio");
|
|
53473
|
+
const prodStudioPath = join11(__dirname2, "..", "node_modules", "@rafters", "studio");
|
|
53474
|
+
const studioPath = existsSync5(devStudioPath) ? devStudioPath : prodStudioPath;
|
|
53475
|
+
if (!existsSync5(studioPath)) {
|
|
51924
53476
|
console.error("Studio package not found. Please reinstall @rafters/cli.");
|
|
51925
53477
|
process.exit(1);
|
|
51926
53478
|
}
|
|
@@ -51950,7 +53502,7 @@ async function studio() {
|
|
|
51950
53502
|
var program = new Command();
|
|
51951
53503
|
program.name("rafters").description("Design system CLI - scaffold tokens and serve MCP").version("0.0.1");
|
|
51952
53504
|
program.command("init").description("Initialize .rafters/ with default tokens and config").option("-r, --rebuild", "Regenerate output files from existing tokens").option("--reset", "Re-run generators fresh, replacing persisted tokens").option("--agent", "Output JSON for machine consumption").action(withErrorHandler(init));
|
|
51953
|
-
program.command("add").description("Add rafters components to the project").argument("[components...]", "Component names to add").option("--list", "List available components").option("--overwrite", "Overwrite existing component files").option("--registry-url <url>", "Custom registry URL").option("--agent", "Output JSON for machine consumption").action(withErrorHandler(add));
|
|
53505
|
+
program.command("add").description("Add rafters components to the project").argument("[components...]", "Component names to add").option("--list", "List available components").option("--overwrite", "Overwrite existing component files").option("--update", "Re-fetch named components from registry").option("--update-all", "Re-fetch all installed components from registry").option("--registry-url <url>", "Custom registry URL").option("--agent", "Output JSON for machine consumption").action(withErrorHandler(add));
|
|
51954
53506
|
program.command("mcp").description("Start MCP server for AI agent access (stdio)").action(mcp);
|
|
51955
53507
|
program.command("studio").description("Open Studio UI for visual token editing").action(studio);
|
|
51956
53508
|
program.parse();
|