rafters 0.0.7 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +22 -28
- package/dist/index.js +1647 -208
- package/dist/registry/types.d.ts +61 -0
- package/dist/registry/types.js +34 -0
- package/package.json +28 -22
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,10 +12558,16 @@ 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([
|
|
12567
|
+
"registry:ui",
|
|
12568
|
+
"registry:primitive",
|
|
12569
|
+
"registry:composite"
|
|
12570
|
+
]);
|
|
12565
12571
|
var RegistryItemSchema = external_exports.object({
|
|
12566
12572
|
name: external_exports.string(),
|
|
12567
12573
|
type: RegistryItemTypeSchema,
|
|
@@ -12714,18 +12720,64 @@ var RegistryClient = class {
|
|
|
12714
12720
|
};
|
|
12715
12721
|
var registryClient = new RegistryClient();
|
|
12716
12722
|
|
|
12717
|
-
// src/utils/
|
|
12718
|
-
|
|
12719
|
-
|
|
12720
|
-
|
|
12723
|
+
// src/utils/exports.ts
|
|
12724
|
+
var DEFAULT_EXPORTS = {
|
|
12725
|
+
tailwind: true,
|
|
12726
|
+
typescript: true,
|
|
12727
|
+
dtcg: false,
|
|
12728
|
+
compiled: false
|
|
12729
|
+
};
|
|
12730
|
+
var EXPORT_CHOICES = [
|
|
12731
|
+
{
|
|
12732
|
+
name: "Tailwind CSS (web projects)",
|
|
12733
|
+
value: "tailwind",
|
|
12734
|
+
checked: true
|
|
12735
|
+
},
|
|
12736
|
+
{
|
|
12737
|
+
name: "TypeScript (type-safe constants)",
|
|
12738
|
+
value: "typescript",
|
|
12739
|
+
checked: true
|
|
12740
|
+
},
|
|
12741
|
+
{
|
|
12742
|
+
name: "DTCG JSON (Figma Tokens, Style Dictionary)",
|
|
12743
|
+
value: "dtcg",
|
|
12744
|
+
checked: false
|
|
12745
|
+
},
|
|
12746
|
+
{
|
|
12747
|
+
name: "Standalone CSS (pre-built, no Tailwind required)",
|
|
12748
|
+
value: "compiled",
|
|
12749
|
+
checked: false
|
|
12750
|
+
}
|
|
12751
|
+
];
|
|
12752
|
+
var FUTURE_EXPORTS = [
|
|
12753
|
+
{
|
|
12754
|
+
name: "iOS (Swift/SwiftUI)",
|
|
12755
|
+
value: "tailwind",
|
|
12756
|
+
// placeholder
|
|
12757
|
+
checked: false,
|
|
12758
|
+
disabled: "coming soon"
|
|
12759
|
+
},
|
|
12760
|
+
{
|
|
12761
|
+
name: "Android (Compose)",
|
|
12762
|
+
value: "tailwind",
|
|
12763
|
+
// placeholder
|
|
12764
|
+
checked: false,
|
|
12765
|
+
disabled: "coming soon"
|
|
12766
|
+
}
|
|
12767
|
+
];
|
|
12768
|
+
function selectionsToConfig(selections) {
|
|
12721
12769
|
return {
|
|
12722
|
-
|
|
12723
|
-
|
|
12724
|
-
|
|
12725
|
-
|
|
12770
|
+
tailwind: selections.includes("tailwind"),
|
|
12771
|
+
typescript: selections.includes("typescript"),
|
|
12772
|
+
dtcg: selections.includes("dtcg"),
|
|
12773
|
+
compiled: selections.includes("compiled")
|
|
12726
12774
|
};
|
|
12727
12775
|
}
|
|
12728
12776
|
|
|
12777
|
+
// src/utils/install-registry-deps.ts
|
|
12778
|
+
import { readFile } from "fs/promises";
|
|
12779
|
+
import { join } from "path";
|
|
12780
|
+
|
|
12729
12781
|
// src/utils/ui.ts
|
|
12730
12782
|
import ora from "ora";
|
|
12731
12783
|
var context = {
|
|
@@ -12735,6 +12787,9 @@ var context = {
|
|
|
12735
12787
|
function setAgentMode(agent) {
|
|
12736
12788
|
context.agent = agent;
|
|
12737
12789
|
}
|
|
12790
|
+
function isAgentMode() {
|
|
12791
|
+
return context.agent;
|
|
12792
|
+
}
|
|
12738
12793
|
function log(event) {
|
|
12739
12794
|
if (context.agent) {
|
|
12740
12795
|
console.log(JSON.stringify(event));
|
|
@@ -12841,8 +12896,9 @@ function log(event) {
|
|
|
12841
12896
|
context.spinner?.succeed("Files written");
|
|
12842
12897
|
const deps = event.dependencies;
|
|
12843
12898
|
const devDeps = event.devDependencies;
|
|
12899
|
+
const skippedDeps = event.skipped ?? [];
|
|
12844
12900
|
if (deps.length > 0 || devDeps.length > 0) {
|
|
12845
|
-
console.log(" Dependencies
|
|
12901
|
+
console.log(" Dependencies installed:");
|
|
12846
12902
|
for (const dep of deps) {
|
|
12847
12903
|
console.log(` ${dep}`);
|
|
12848
12904
|
}
|
|
@@ -12850,9 +12906,32 @@ function log(event) {
|
|
|
12850
12906
|
console.log(` ${dep} (dev)`);
|
|
12851
12907
|
}
|
|
12852
12908
|
}
|
|
12853
|
-
|
|
12909
|
+
if (skippedDeps.length > 0) {
|
|
12910
|
+
console.log(" Dependencies skipped (already installed or internal):");
|
|
12911
|
+
for (const dep of skippedDeps) {
|
|
12912
|
+
console.log(` ${dep}`);
|
|
12913
|
+
}
|
|
12914
|
+
}
|
|
12915
|
+
break;
|
|
12916
|
+
}
|
|
12917
|
+
case "add:deps:no-package-json":
|
|
12918
|
+
console.warn(` Warning: ${event.message}`);
|
|
12919
|
+
break;
|
|
12920
|
+
case "add:deps:dry-run": {
|
|
12921
|
+
const dryDeps = event.dependencies;
|
|
12922
|
+
console.log(" [dry-run] Would install:");
|
|
12923
|
+
for (const dep of dryDeps) {
|
|
12924
|
+
console.log(` ${dep}`);
|
|
12925
|
+
}
|
|
12854
12926
|
break;
|
|
12855
12927
|
}
|
|
12928
|
+
case "add:deps:install-failed":
|
|
12929
|
+
context.spinner?.fail("Failed to install dependencies");
|
|
12930
|
+
console.log(` ${event.message}`);
|
|
12931
|
+
if (event.suggestion) {
|
|
12932
|
+
console.log(` ${event.suggestion}`);
|
|
12933
|
+
}
|
|
12934
|
+
break;
|
|
12856
12935
|
case "add:complete":
|
|
12857
12936
|
context.spinner?.succeed(
|
|
12858
12937
|
`Added ${event.installed} component${event.installed !== 1 ? "s" : ""}`
|
|
@@ -12888,6 +12967,20 @@ function error46(message) {
|
|
|
12888
12967
|
context.spinner?.fail(message);
|
|
12889
12968
|
context.spinner = null;
|
|
12890
12969
|
}
|
|
12970
|
+
function withErrorHandler(action) {
|
|
12971
|
+
return async (...args) => {
|
|
12972
|
+
try {
|
|
12973
|
+
await action(...args);
|
|
12974
|
+
} catch (err) {
|
|
12975
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
12976
|
+
error46(message);
|
|
12977
|
+
if (process.env.DEBUG && err instanceof Error && err.stack) {
|
|
12978
|
+
console.error(err.stack);
|
|
12979
|
+
}
|
|
12980
|
+
process.exitCode = 1;
|
|
12981
|
+
}
|
|
12982
|
+
};
|
|
12983
|
+
}
|
|
12891
12984
|
|
|
12892
12985
|
// src/utils/update-dependencies.ts
|
|
12893
12986
|
import { execa } from "execa";
|
|
@@ -12956,6 +13049,127 @@ async function installWithPackageManager(packageManager, dependencies, options)
|
|
|
12956
13049
|
}
|
|
12957
13050
|
}
|
|
12958
13051
|
|
|
13052
|
+
// src/utils/install-registry-deps.ts
|
|
13053
|
+
function parseDependency(dep) {
|
|
13054
|
+
const trimmed = dep.trim();
|
|
13055
|
+
if (!trimmed) {
|
|
13056
|
+
return { name: "", version: void 0 };
|
|
13057
|
+
}
|
|
13058
|
+
const versionAt = trimmed.lastIndexOf("@");
|
|
13059
|
+
if (versionAt <= 0) {
|
|
13060
|
+
return { name: trimmed, version: void 0 };
|
|
13061
|
+
}
|
|
13062
|
+
return {
|
|
13063
|
+
name: trimmed.slice(0, versionAt),
|
|
13064
|
+
version: trimmed.slice(versionAt + 1)
|
|
13065
|
+
};
|
|
13066
|
+
}
|
|
13067
|
+
async function readInstalledDeps(targetDir) {
|
|
13068
|
+
let raw;
|
|
13069
|
+
try {
|
|
13070
|
+
raw = await readFile(join(targetDir, "package.json"), "utf-8");
|
|
13071
|
+
} catch {
|
|
13072
|
+
return { packageJsonFound: false, installed: /* @__PURE__ */ new Set() };
|
|
13073
|
+
}
|
|
13074
|
+
try {
|
|
13075
|
+
const pkg = JSON.parse(raw);
|
|
13076
|
+
const installed = /* @__PURE__ */ new Set();
|
|
13077
|
+
const depFields = ["dependencies", "devDependencies", "peerDependencies"];
|
|
13078
|
+
for (const field of depFields) {
|
|
13079
|
+
const section = pkg[field];
|
|
13080
|
+
if (section && typeof section === "object") {
|
|
13081
|
+
for (const name2 of Object.keys(section)) {
|
|
13082
|
+
installed.add(name2);
|
|
13083
|
+
}
|
|
13084
|
+
}
|
|
13085
|
+
}
|
|
13086
|
+
return { packageJsonFound: true, installed };
|
|
13087
|
+
} catch {
|
|
13088
|
+
return { packageJsonFound: true, installed: /* @__PURE__ */ new Set() };
|
|
13089
|
+
}
|
|
13090
|
+
}
|
|
13091
|
+
async function installRegistryDependencies(items, targetDir, options = {}) {
|
|
13092
|
+
const result = {
|
|
13093
|
+
installed: [],
|
|
13094
|
+
skipped: [],
|
|
13095
|
+
devInstalled: [],
|
|
13096
|
+
failed: []
|
|
13097
|
+
};
|
|
13098
|
+
const allDeps = new Set(items.flatMap((item) => item.files.flatMap((file2) => file2.dependencies)));
|
|
13099
|
+
if (allDeps.size === 0) {
|
|
13100
|
+
return result;
|
|
13101
|
+
}
|
|
13102
|
+
const externalDeps = [];
|
|
13103
|
+
for (const dep of allDeps) {
|
|
13104
|
+
if (parseDependency(dep).name.startsWith("@rafters/")) {
|
|
13105
|
+
result.skipped.push(dep);
|
|
13106
|
+
} else {
|
|
13107
|
+
externalDeps.push(dep);
|
|
13108
|
+
}
|
|
13109
|
+
}
|
|
13110
|
+
if (externalDeps.length === 0) {
|
|
13111
|
+
return result;
|
|
13112
|
+
}
|
|
13113
|
+
const { packageJsonFound, installed: installedInProject } = await readInstalledDeps(targetDir);
|
|
13114
|
+
const toInstall = [];
|
|
13115
|
+
if (!packageJsonFound) {
|
|
13116
|
+
log({
|
|
13117
|
+
event: "add:deps:no-package-json",
|
|
13118
|
+
message: "No package.json found. Run npm init or pnpm init first.",
|
|
13119
|
+
targetDir
|
|
13120
|
+
});
|
|
13121
|
+
toInstall.push(...externalDeps);
|
|
13122
|
+
} else {
|
|
13123
|
+
for (const dep of externalDeps) {
|
|
13124
|
+
const { name: name2 } = parseDependency(dep);
|
|
13125
|
+
if (installedInProject.has(name2)) {
|
|
13126
|
+
result.skipped.push(dep);
|
|
13127
|
+
} else {
|
|
13128
|
+
toInstall.push(dep);
|
|
13129
|
+
}
|
|
13130
|
+
}
|
|
13131
|
+
}
|
|
13132
|
+
if (toInstall.length === 0) {
|
|
13133
|
+
return result;
|
|
13134
|
+
}
|
|
13135
|
+
if (options.dryRun) {
|
|
13136
|
+
log({
|
|
13137
|
+
event: "add:deps:dry-run",
|
|
13138
|
+
dependencies: toInstall
|
|
13139
|
+
});
|
|
13140
|
+
return result;
|
|
13141
|
+
}
|
|
13142
|
+
try {
|
|
13143
|
+
await updateDependencies(toInstall, [], {
|
|
13144
|
+
cwd: targetDir,
|
|
13145
|
+
silent: options.silent ?? false
|
|
13146
|
+
});
|
|
13147
|
+
result.installed = toInstall;
|
|
13148
|
+
} catch (err) {
|
|
13149
|
+
result.failed = toInstall;
|
|
13150
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
13151
|
+
log({
|
|
13152
|
+
event: "add:deps:install-failed",
|
|
13153
|
+
message: `Failed to install dependencies: ${message}`,
|
|
13154
|
+
dependencies: toInstall,
|
|
13155
|
+
suggestion: `Manually install: ${toInstall.join(" ")}`
|
|
13156
|
+
});
|
|
13157
|
+
}
|
|
13158
|
+
return result;
|
|
13159
|
+
}
|
|
13160
|
+
|
|
13161
|
+
// src/utils/paths.ts
|
|
13162
|
+
import { join as join2 } from "path";
|
|
13163
|
+
function getRaftersPaths(projectRoot = process.cwd()) {
|
|
13164
|
+
const root = join2(projectRoot, ".rafters");
|
|
13165
|
+
return {
|
|
13166
|
+
root,
|
|
13167
|
+
config: join2(root, "config.rafters.json"),
|
|
13168
|
+
tokens: join2(root, "tokens"),
|
|
13169
|
+
output: join2(root, "output")
|
|
13170
|
+
};
|
|
13171
|
+
}
|
|
13172
|
+
|
|
12959
13173
|
// src/commands/add.ts
|
|
12960
13174
|
async function isInitialized(cwd) {
|
|
12961
13175
|
const paths = getRaftersPaths(cwd);
|
|
@@ -12969,7 +13183,7 @@ async function isInitialized(cwd) {
|
|
|
12969
13183
|
async function loadConfig(cwd) {
|
|
12970
13184
|
const paths = getRaftersPaths(cwd);
|
|
12971
13185
|
try {
|
|
12972
|
-
const content = await
|
|
13186
|
+
const content = await readFile2(paths.config, "utf-8");
|
|
12973
13187
|
return JSON.parse(content);
|
|
12974
13188
|
} catch (err) {
|
|
12975
13189
|
if (existsSync(paths.config)) {
|
|
@@ -12979,6 +13193,40 @@ async function loadConfig(cwd) {
|
|
|
12979
13193
|
return null;
|
|
12980
13194
|
}
|
|
12981
13195
|
}
|
|
13196
|
+
async function saveConfig(cwd, config3) {
|
|
13197
|
+
const paths = getRaftersPaths(cwd);
|
|
13198
|
+
await writeFile(paths.config, JSON.stringify(config3, null, 2));
|
|
13199
|
+
}
|
|
13200
|
+
function getInstalledNames(config3) {
|
|
13201
|
+
if (!config3?.installed) return [];
|
|
13202
|
+
const names2 = /* @__PURE__ */ new Set([...config3.installed.components, ...config3.installed.primitives]);
|
|
13203
|
+
return [...names2].sort();
|
|
13204
|
+
}
|
|
13205
|
+
function isAlreadyInstalled(config3, item) {
|
|
13206
|
+
if (!config3?.installed) return false;
|
|
13207
|
+
if (item.type === "registry:ui") {
|
|
13208
|
+
return config3.installed.components.includes(item.name);
|
|
13209
|
+
}
|
|
13210
|
+
return config3.installed.primitives.includes(item.name);
|
|
13211
|
+
}
|
|
13212
|
+
function trackInstalled(config3, items) {
|
|
13213
|
+
if (!config3.installed) {
|
|
13214
|
+
config3.installed = { components: [], primitives: [] };
|
|
13215
|
+
}
|
|
13216
|
+
for (const item of items) {
|
|
13217
|
+
if (item.type === "registry:ui") {
|
|
13218
|
+
if (!config3.installed.components.includes(item.name)) {
|
|
13219
|
+
config3.installed.components.push(item.name);
|
|
13220
|
+
}
|
|
13221
|
+
} else {
|
|
13222
|
+
if (!config3.installed.primitives.includes(item.name)) {
|
|
13223
|
+
config3.installed.primitives.push(item.name);
|
|
13224
|
+
}
|
|
13225
|
+
}
|
|
13226
|
+
}
|
|
13227
|
+
config3.installed.components.sort();
|
|
13228
|
+
config3.installed.primitives.sort();
|
|
13229
|
+
}
|
|
12982
13230
|
function transformPath(registryPath, config3) {
|
|
12983
13231
|
if (!config3) return registryPath;
|
|
12984
13232
|
if (registryPath.startsWith("components/ui/")) {
|
|
@@ -12990,7 +13238,7 @@ function transformPath(registryPath, config3) {
|
|
|
12990
13238
|
return registryPath;
|
|
12991
13239
|
}
|
|
12992
13240
|
function fileExists(cwd, relativePath) {
|
|
12993
|
-
return existsSync(
|
|
13241
|
+
return existsSync(join3(cwd, relativePath));
|
|
12994
13242
|
}
|
|
12995
13243
|
function transformFileContent(content, config3) {
|
|
12996
13244
|
let transformed = content;
|
|
@@ -13030,7 +13278,7 @@ async function installItem(cwd, item, options, config3) {
|
|
|
13030
13278
|
let skipped = false;
|
|
13031
13279
|
for (const file2 of item.files) {
|
|
13032
13280
|
const projectPath = transformPath(file2.path, config3);
|
|
13033
|
-
const targetPath =
|
|
13281
|
+
const targetPath = join3(cwd, projectPath);
|
|
13034
13282
|
if (fileExists(cwd, projectPath)) {
|
|
13035
13283
|
if (!options.overwrite) {
|
|
13036
13284
|
log({
|
|
@@ -13054,23 +13302,9 @@ async function installItem(cwd, item, options, config3) {
|
|
|
13054
13302
|
files: installedFiles
|
|
13055
13303
|
};
|
|
13056
13304
|
}
|
|
13057
|
-
function
|
|
13058
|
-
const deps = /* @__PURE__ */ new Set();
|
|
13059
|
-
const devDeps = /* @__PURE__ */ new Set();
|
|
13060
|
-
for (const item of items) {
|
|
13061
|
-
for (const file2 of item.files) {
|
|
13062
|
-
for (const dep of file2.dependencies) {
|
|
13063
|
-
deps.add(dep);
|
|
13064
|
-
}
|
|
13065
|
-
}
|
|
13066
|
-
}
|
|
13067
|
-
return {
|
|
13068
|
-
dependencies: [...deps].sort(),
|
|
13069
|
-
devDependencies: [...devDeps].sort()
|
|
13070
|
-
};
|
|
13071
|
-
}
|
|
13072
|
-
async function add(components, options) {
|
|
13305
|
+
async function add(componentArgs, options) {
|
|
13073
13306
|
setAgentMode(options.agent ?? false);
|
|
13307
|
+
let components = componentArgs;
|
|
13074
13308
|
const client = new RegistryClient(options.registryUrl);
|
|
13075
13309
|
if (options.list) {
|
|
13076
13310
|
const availableComponents = await client.listComponents();
|
|
@@ -13092,6 +13326,24 @@ async function add(components, options) {
|
|
|
13092
13326
|
return;
|
|
13093
13327
|
}
|
|
13094
13328
|
const config3 = await loadConfig(cwd);
|
|
13329
|
+
if (options.update) {
|
|
13330
|
+
options.overwrite = true;
|
|
13331
|
+
}
|
|
13332
|
+
if (options.updateAll) {
|
|
13333
|
+
options.overwrite = true;
|
|
13334
|
+
if (!config3) {
|
|
13335
|
+
error46("No rafters config found. Run 'rafters init' first.");
|
|
13336
|
+
process.exitCode = 1;
|
|
13337
|
+
return;
|
|
13338
|
+
}
|
|
13339
|
+
const installedNames = getInstalledNames(config3);
|
|
13340
|
+
if (installedNames.length === 0) {
|
|
13341
|
+
error46("No installed components found. Use 'rafters add <component>' to install first.");
|
|
13342
|
+
process.exitCode = 1;
|
|
13343
|
+
return;
|
|
13344
|
+
}
|
|
13345
|
+
components = installedNames;
|
|
13346
|
+
}
|
|
13095
13347
|
if (components.length === 0) {
|
|
13096
13348
|
error46("No components specified. Usage: rafters add <component...>");
|
|
13097
13349
|
process.exitCode = 1;
|
|
@@ -13121,11 +13373,22 @@ async function add(components, options) {
|
|
|
13121
13373
|
}
|
|
13122
13374
|
const installed = [];
|
|
13123
13375
|
const skipped = [];
|
|
13376
|
+
const installedItems = [];
|
|
13124
13377
|
for (const item of allItems) {
|
|
13378
|
+
if (!options.overwrite && isAlreadyInstalled(config3, item)) {
|
|
13379
|
+
log({
|
|
13380
|
+
event: "add:skip",
|
|
13381
|
+
component: item.name,
|
|
13382
|
+
reason: "already installed"
|
|
13383
|
+
});
|
|
13384
|
+
skipped.push(item.name);
|
|
13385
|
+
continue;
|
|
13386
|
+
}
|
|
13125
13387
|
try {
|
|
13126
13388
|
const result = await installItem(cwd, item, options, config3);
|
|
13127
13389
|
if (result.installed) {
|
|
13128
13390
|
installed.push(item.name);
|
|
13391
|
+
installedItems.push(item);
|
|
13129
13392
|
log({
|
|
13130
13393
|
event: "add:installed",
|
|
13131
13394
|
component: item.name,
|
|
@@ -13146,22 +13409,47 @@ async function add(components, options) {
|
|
|
13146
13409
|
}
|
|
13147
13410
|
}
|
|
13148
13411
|
}
|
|
13149
|
-
const
|
|
13150
|
-
|
|
13412
|
+
const emptyDeps = {
|
|
13413
|
+
installed: [],
|
|
13414
|
+
skipped: [],
|
|
13415
|
+
devInstalled: [],
|
|
13416
|
+
failed: []
|
|
13417
|
+
};
|
|
13418
|
+
let depsResult = emptyDeps;
|
|
13419
|
+
try {
|
|
13420
|
+
depsResult = await installRegistryDependencies(allItems, cwd);
|
|
13421
|
+
} catch (err) {
|
|
13422
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
13423
|
+
log({
|
|
13424
|
+
event: "add:deps:install-failed",
|
|
13425
|
+
message: `Failed to process dependencies: ${message}`,
|
|
13426
|
+
dependencies: [],
|
|
13427
|
+
suggestion: "Check package.json and try installing dependencies manually."
|
|
13428
|
+
});
|
|
13429
|
+
}
|
|
13430
|
+
if (depsResult.installed.length > 0 || depsResult.skipped.length > 0) {
|
|
13151
13431
|
log({
|
|
13152
13432
|
event: "add:dependencies",
|
|
13153
|
-
dependencies,
|
|
13154
|
-
devDependencies
|
|
13433
|
+
dependencies: depsResult.installed,
|
|
13434
|
+
devDependencies: depsResult.devInstalled,
|
|
13435
|
+
skipped: depsResult.skipped
|
|
13155
13436
|
});
|
|
13156
|
-
|
|
13157
|
-
|
|
13158
|
-
|
|
13159
|
-
|
|
13160
|
-
|
|
13161
|
-
|
|
13162
|
-
|
|
13163
|
-
|
|
13164
|
-
|
|
13437
|
+
}
|
|
13438
|
+
if (installedItems.length > 0 && config3) {
|
|
13439
|
+
trackInstalled(config3, installedItems);
|
|
13440
|
+
await saveConfig(cwd, config3);
|
|
13441
|
+
} else if (installedItems.length > 0 && !config3) {
|
|
13442
|
+
const newConfig = {
|
|
13443
|
+
framework: "unknown",
|
|
13444
|
+
componentsPath: "components/ui",
|
|
13445
|
+
primitivesPath: "lib/primitives",
|
|
13446
|
+
cssPath: null,
|
|
13447
|
+
shadcn: false,
|
|
13448
|
+
exports: DEFAULT_EXPORTS,
|
|
13449
|
+
installed: { components: [], primitives: [] }
|
|
13450
|
+
};
|
|
13451
|
+
trackInstalled(newConfig, installedItems);
|
|
13452
|
+
await saveConfig(cwd, newConfig);
|
|
13165
13453
|
}
|
|
13166
13454
|
log({
|
|
13167
13455
|
event: "add:complete",
|
|
@@ -13172,19 +13460,20 @@ async function add(components, options) {
|
|
|
13172
13460
|
if (skipped.length > 0 && installed.length === 0) {
|
|
13173
13461
|
log({
|
|
13174
13462
|
event: "add:hint",
|
|
13175
|
-
message: "Some components were skipped. Use --
|
|
13463
|
+
message: "Some components were skipped. Use --update to re-fetch, or --update-all to refresh everything.",
|
|
13176
13464
|
skipped
|
|
13177
13465
|
});
|
|
13178
|
-
error46("Component already exists. Use --
|
|
13466
|
+
error46("Component already exists. Use --update to re-fetch from registry.");
|
|
13179
13467
|
process.exitCode = 1;
|
|
13180
13468
|
}
|
|
13181
13469
|
}
|
|
13182
13470
|
|
|
13183
13471
|
// src/commands/init.ts
|
|
13184
13472
|
import { existsSync as existsSync2 } from "fs";
|
|
13185
|
-
import { copyFile, mkdir as mkdir3, readFile as
|
|
13186
|
-
import {
|
|
13187
|
-
import {
|
|
13473
|
+
import { copyFile, mkdir as mkdir3, readFile as readFile5, rm, writeFile as writeFile3 } from "fs/promises";
|
|
13474
|
+
import { createRequire } from "module";
|
|
13475
|
+
import { join as join9, relative } from "path";
|
|
13476
|
+
import { checkbox, confirm } from "@inquirer/prompts";
|
|
13188
13477
|
|
|
13189
13478
|
// ../design-tokens/src/plugins/scale.ts
|
|
13190
13479
|
function scale(registry2, tokenName, dependencies) {
|
|
@@ -24314,7 +24603,7 @@ var require_volume = __commonJS({
|
|
|
24314
24603
|
var Dir_1 = require_Dir();
|
|
24315
24604
|
var resolveCrossPlatform = pathModule.resolve;
|
|
24316
24605
|
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;
|
|
24317
|
-
var { sep: sep2, relative: relative2, join:
|
|
24606
|
+
var { sep: sep2, relative: relative2, join: join12, dirname: dirname4 } = pathModule.posix ? pathModule.posix : pathModule;
|
|
24318
24607
|
var kMinPoolSpace = 128;
|
|
24319
24608
|
var EPERM = "EPERM";
|
|
24320
24609
|
var ENOENT2 = "ENOENT";
|
|
@@ -24380,7 +24669,7 @@ var require_volume = __commonJS({
|
|
|
24380
24669
|
function flatten(pathPrefix, node) {
|
|
24381
24670
|
for (const path2 in node) {
|
|
24382
24671
|
const contentOrNode = node[path2];
|
|
24383
|
-
const joinedPath =
|
|
24672
|
+
const joinedPath = join12(pathPrefix, path2);
|
|
24384
24673
|
if (typeof contentOrNode === "string" || contentOrNode instanceof buffer_1.Buffer) {
|
|
24385
24674
|
flatJSON[joinedPath] = contentOrNode;
|
|
24386
24675
|
} else if (typeof contentOrNode === "object" && contentOrNode !== null && Object.keys(contentOrNode).length > 0) {
|
|
@@ -24537,7 +24826,7 @@ var require_volume = __commonJS({
|
|
|
24537
24826
|
return null;
|
|
24538
24827
|
node = curr === null || curr === void 0 ? void 0 : curr.getNode();
|
|
24539
24828
|
if (resolveSymlinks && node.isSymlink()) {
|
|
24540
|
-
const resolvedPath = pathModule.isAbsolute(node.symlink) ? node.symlink :
|
|
24829
|
+
const resolvedPath = pathModule.isAbsolute(node.symlink) ? node.symlink : join12(pathModule.dirname(curr.getPath()), node.symlink);
|
|
24541
24830
|
steps = filenameToSteps(resolvedPath).concat(steps.slice(i + 1));
|
|
24542
24831
|
curr = this.root;
|
|
24543
24832
|
i = 0;
|
|
@@ -27461,7 +27750,7 @@ var posix = {
|
|
|
27461
27750
|
|
|
27462
27751
|
// ../../node_modules/.pnpm/path-unified@0.2.0/node_modules/path-unified/src/posix.js
|
|
27463
27752
|
var resolve = posResolve;
|
|
27464
|
-
var
|
|
27753
|
+
var join4 = posJoin;
|
|
27465
27754
|
|
|
27466
27755
|
// ../../node_modules/.pnpm/@isaacs+balanced-match@4.0.1/node_modules/@isaacs/balanced-match/dist/esm/index.js
|
|
27467
27756
|
var balanced = (a, b, str) => {
|
|
@@ -37360,7 +37649,7 @@ var transforms_default = {
|
|
|
37360
37649
|
type: value,
|
|
37361
37650
|
filter: isAsset,
|
|
37362
37651
|
transform: function(token, _, options) {
|
|
37363
|
-
return
|
|
37652
|
+
return join4(process?.cwd() ?? "/", options.usesDtcg ? token.$value : token.value);
|
|
37364
37653
|
}
|
|
37365
37654
|
},
|
|
37366
37655
|
/**
|
|
@@ -43560,12 +43849,12 @@ var formats_default = formats2;
|
|
|
43560
43849
|
var { androidCopyImages, copyAssets } = actions;
|
|
43561
43850
|
var { silent } = logVerbosityLevels;
|
|
43562
43851
|
function getAssetDir(config3) {
|
|
43563
|
-
return
|
|
43852
|
+
return join4(config3.buildPath ?? "", "android/main/res/drawable-").replace(/\\/g, "/");
|
|
43564
43853
|
}
|
|
43565
43854
|
function getAssetPath(token, imagesDir) {
|
|
43566
43855
|
const name2 = token.path.slice(2, 4).join("_");
|
|
43567
43856
|
const dir = `${imagesDir}${token.attributes?.state}`;
|
|
43568
|
-
return { file:
|
|
43857
|
+
return { file: join4(dir, `${name2}.png`), dir };
|
|
43569
43858
|
}
|
|
43570
43859
|
var actions_default = {
|
|
43571
43860
|
/**
|
|
@@ -43606,7 +43895,7 @@ var actions_default = {
|
|
|
43606
43895
|
*/
|
|
43607
43896
|
[copyAssets]: {
|
|
43608
43897
|
do: async function(_, config3, _options, vol2 = fs2) {
|
|
43609
|
-
const assetsPath =
|
|
43898
|
+
const assetsPath = join4(config3.buildPath ?? "", "assets");
|
|
43610
43899
|
if (config3.log?.verbosity !== silent) {
|
|
43611
43900
|
console.log(`Copying assets directory to ${assetsPath}`);
|
|
43612
43901
|
}
|
|
@@ -43620,7 +43909,7 @@ var actions_default = {
|
|
|
43620
43909
|
);
|
|
43621
43910
|
},
|
|
43622
43911
|
undo: async function(_, config3, _options, vol2 = fs2) {
|
|
43623
|
-
const assetsPath =
|
|
43912
|
+
const assetsPath = join4(config3.buildPath ?? "", "assets");
|
|
43624
43913
|
if (config3.log?.verbosity !== silent) {
|
|
43625
43914
|
console.log(`Removing assets directory from ${assetsPath}`);
|
|
43626
43915
|
}
|
|
@@ -44101,8 +44390,14 @@ var DEFAULT_DEPTH_DEFINITIONS = {
|
|
|
44101
44390
|
},
|
|
44102
44391
|
sticky: {
|
|
44103
44392
|
value: 20,
|
|
44104
|
-
meaning: "Sticky elements - headers,
|
|
44105
|
-
contexts: ["sticky-header", "sticky-
|
|
44393
|
+
meaning: "Sticky elements - headers, toolbars",
|
|
44394
|
+
contexts: ["sticky-header", "sticky-toolbar", "floating-actions"],
|
|
44395
|
+
stackingContext: true
|
|
44396
|
+
},
|
|
44397
|
+
navigation: {
|
|
44398
|
+
value: 25,
|
|
44399
|
+
meaning: "Navigation panels - sidebars, slide-out nav",
|
|
44400
|
+
contexts: ["sidebar", "navigation-panel", "slide-out-menu"],
|
|
44106
44401
|
stackingContext: true
|
|
44107
44402
|
},
|
|
44108
44403
|
fixed: {
|
|
@@ -44128,6 +44423,12 @@ var DEFAULT_DEPTH_DEFINITIONS = {
|
|
|
44128
44423
|
meaning: "Tooltips - highest common layer",
|
|
44129
44424
|
contexts: ["tooltips", "toast-notifications"],
|
|
44130
44425
|
stackingContext: true
|
|
44426
|
+
},
|
|
44427
|
+
overlay: {
|
|
44428
|
+
value: 70,
|
|
44429
|
+
meaning: "Overlay backdrops - screen-dimming layers behind modals",
|
|
44430
|
+
contexts: ["modal-backdrop", "drawer-backdrop", "sheet-backdrop"],
|
|
44431
|
+
stackingContext: true
|
|
44131
44432
|
}
|
|
44132
44433
|
};
|
|
44133
44434
|
var DEFAULT_SHADOW_DEFINITIONS = {
|
|
@@ -46425,6 +46726,78 @@ function generateThemeBlock(groups) {
|
|
|
46425
46726
|
lines.push("}");
|
|
46426
46727
|
return lines.join("\n");
|
|
46427
46728
|
}
|
|
46729
|
+
var ARTICLE_ELEMENT_STYLES = [
|
|
46730
|
+
// Paragraphs
|
|
46731
|
+
["p", "leading-relaxed mb-4"],
|
|
46732
|
+
["p:last-child", "mb-0"],
|
|
46733
|
+
// Headings
|
|
46734
|
+
["h1", "text-4xl font-bold tracking-tight mb-4 mt-0 text-accent-foreground"],
|
|
46735
|
+
["h2", "text-3xl font-semibold tracking-tight mb-3 mt-8 text-accent-foreground"],
|
|
46736
|
+
["h2:first-child", "mt-0"],
|
|
46737
|
+
["h3", "text-2xl font-semibold mb-2 mt-6 text-accent-foreground"],
|
|
46738
|
+
["h4", "text-xl font-semibold mb-2 mt-4 text-accent-foreground"],
|
|
46739
|
+
["h5", "text-lg font-semibold mb-2 mt-4 text-accent-foreground"],
|
|
46740
|
+
["h6", "text-base font-semibold mb-2 mt-4 text-accent-foreground"],
|
|
46741
|
+
// Lists
|
|
46742
|
+
["ul", "list-disc pl-6 mb-4"],
|
|
46743
|
+
["ol", "list-decimal pl-6 mb-4"],
|
|
46744
|
+
["li", "mb-1"],
|
|
46745
|
+
["li > ul,\n article li > ol", "mt-1 mb-0"],
|
|
46746
|
+
// Links
|
|
46747
|
+
["a", "text-primary underline underline-offset-4"],
|
|
46748
|
+
["a:hover", "text-primary/80"],
|
|
46749
|
+
// Blockquotes
|
|
46750
|
+
["blockquote", "border-l-4 border-muted pl-4 italic my-4"],
|
|
46751
|
+
// Code
|
|
46752
|
+
["code", "bg-muted px-1.5 py-0.5 rounded text-sm font-mono"],
|
|
46753
|
+
["pre", "bg-muted p-4 rounded-lg overflow-x-auto my-4 text-sm font-mono"],
|
|
46754
|
+
["pre code", "bg-transparent p-0 rounded-none text-[inherit]"],
|
|
46755
|
+
["kbd", "bg-muted border border-border rounded px-1.5 py-0.5 text-sm font-mono"],
|
|
46756
|
+
// Horizontal rules
|
|
46757
|
+
["hr", "border-border my-8"],
|
|
46758
|
+
// Media
|
|
46759
|
+
["img", "rounded-lg my-4 max-w-full h-auto"],
|
|
46760
|
+
["video", "rounded-lg my-4 max-w-full h-auto"],
|
|
46761
|
+
// Tables
|
|
46762
|
+
["table", "w-full my-4 border-collapse"],
|
|
46763
|
+
["caption", "mt-2 text-sm text-muted-foreground text-left"],
|
|
46764
|
+
["th", "border border-border px-3 py-2 text-left font-semibold"],
|
|
46765
|
+
["td", "border border-border px-3 py-2"],
|
|
46766
|
+
// Figures
|
|
46767
|
+
["figure", "my-4"],
|
|
46768
|
+
["figcaption", "mt-2 text-sm text-muted-foreground"],
|
|
46769
|
+
// Definition lists
|
|
46770
|
+
["dl", "my-4"],
|
|
46771
|
+
["dt", "font-semibold mt-2"],
|
|
46772
|
+
["dd", "pl-4 mb-2"],
|
|
46773
|
+
// Details/Summary
|
|
46774
|
+
["details", "my-4"],
|
|
46775
|
+
["summary", "cursor-pointer font-semibold"],
|
|
46776
|
+
// Inline formatting
|
|
46777
|
+
["strong,\n article b", "font-semibold"],
|
|
46778
|
+
["mark", "bg-accent text-accent-foreground px-1 rounded"],
|
|
46779
|
+
["small", "text-sm"],
|
|
46780
|
+
["sub", "text-xs align-sub"],
|
|
46781
|
+
["sup", "text-xs align-super"],
|
|
46782
|
+
["abbr[title]", "underline decoration-dotted underline-offset-4 cursor-help"],
|
|
46783
|
+
["s,\n article del", "line-through"],
|
|
46784
|
+
["ins", "underline"]
|
|
46785
|
+
];
|
|
46786
|
+
function generateArticleBaseLayer() {
|
|
46787
|
+
const lines = [];
|
|
46788
|
+
lines.push("@layer base {");
|
|
46789
|
+
for (const [selector, utilities] of ARTICLE_ELEMENT_STYLES) {
|
|
46790
|
+
if (selector.includes("\n")) {
|
|
46791
|
+
lines.push(` article ${selector} {`);
|
|
46792
|
+
} else {
|
|
46793
|
+
lines.push(` article ${selector} {`);
|
|
46794
|
+
}
|
|
46795
|
+
lines.push(` @apply ${utilities};`);
|
|
46796
|
+
lines.push(" }");
|
|
46797
|
+
}
|
|
46798
|
+
lines.push("}");
|
|
46799
|
+
return lines.join("\n");
|
|
46800
|
+
}
|
|
46428
46801
|
function generateKeyframes(motionTokens) {
|
|
46429
46802
|
const keyframeTokens = motionTokens.filter((t2) => t2.name.startsWith("motion-keyframe-"));
|
|
46430
46803
|
if (keyframeTokens.length === 0) {
|
|
@@ -46476,6 +46849,8 @@ function tokensToTailwind(tokens, options = {}) {
|
|
|
46476
46849
|
if (keyframes) {
|
|
46477
46850
|
sections.push(keyframes);
|
|
46478
46851
|
}
|
|
46852
|
+
sections.push("");
|
|
46853
|
+
sections.push(generateArticleBaseLayer());
|
|
46479
46854
|
return sections.join("\n");
|
|
46480
46855
|
}
|
|
46481
46856
|
function registryToTailwind(registry2, options) {
|
|
@@ -46487,9 +46862,9 @@ async function registryToCompiled(registry2, options = {}) {
|
|
|
46487
46862
|
const themeCss = registryToTailwind(registry2, { includeImport });
|
|
46488
46863
|
const { execFileSync } = await import("child_process");
|
|
46489
46864
|
const { mkdtempSync, writeFileSync, readFileSync, rmSync } = await import("fs");
|
|
46490
|
-
const { join:
|
|
46491
|
-
const { createRequire } = await import("module");
|
|
46492
|
-
const require2 =
|
|
46865
|
+
const { join: join12, dirname: dirname4 } = await import("path");
|
|
46866
|
+
const { createRequire: createRequire2 } = await import("module");
|
|
46867
|
+
const require2 = createRequire2(import.meta.url);
|
|
46493
46868
|
let pkgDir;
|
|
46494
46869
|
try {
|
|
46495
46870
|
const pkgJsonPath = require2.resolve("@tailwindcss/cli/package.json");
|
|
@@ -46497,10 +46872,10 @@ async function registryToCompiled(registry2, options = {}) {
|
|
|
46497
46872
|
} catch {
|
|
46498
46873
|
throw new Error("Failed to resolve @tailwindcss/cli");
|
|
46499
46874
|
}
|
|
46500
|
-
const binPath =
|
|
46501
|
-
const tempDir = mkdtempSync(
|
|
46502
|
-
const tempInput =
|
|
46503
|
-
const tempOutput =
|
|
46875
|
+
const binPath = join12(pkgDir, "dist", "index.mjs");
|
|
46876
|
+
const tempDir = mkdtempSync(join12(pkgDir, ".tmp-compile-"));
|
|
46877
|
+
const tempInput = join12(tempDir, "input.css");
|
|
46878
|
+
const tempOutput = join12(tempDir, "output.css");
|
|
46504
46879
|
try {
|
|
46505
46880
|
writeFileSync(tempInput, themeCss);
|
|
46506
46881
|
const args = [binPath, "-i", tempInput, "-o", tempOutput];
|
|
@@ -46779,7 +47154,7 @@ function tagTokenizer() {
|
|
|
46779
47154
|
|
|
46780
47155
|
// ../../node_modules/.pnpm/comment-parser@1.4.1/node_modules/comment-parser/es6/parser/tokenizers/type.js
|
|
46781
47156
|
function typeTokenizer(spacing = "compact") {
|
|
46782
|
-
const
|
|
47157
|
+
const join12 = getJoiner(spacing);
|
|
46783
47158
|
return (spec) => {
|
|
46784
47159
|
let curlies = 0;
|
|
46785
47160
|
let lines = [];
|
|
@@ -46822,7 +47197,7 @@ function typeTokenizer(spacing = "compact") {
|
|
|
46822
47197
|
}
|
|
46823
47198
|
parts[0] = parts[0].slice(1);
|
|
46824
47199
|
parts[parts.length - 1] = parts[parts.length - 1].slice(0, -1);
|
|
46825
|
-
spec.type =
|
|
47200
|
+
spec.type = join12(parts);
|
|
46826
47201
|
return spec;
|
|
46827
47202
|
};
|
|
46828
47203
|
}
|
|
@@ -46920,9 +47295,9 @@ function nameTokenizer() {
|
|
|
46920
47295
|
|
|
46921
47296
|
// ../../node_modules/.pnpm/comment-parser@1.4.1/node_modules/comment-parser/es6/parser/tokenizers/description.js
|
|
46922
47297
|
function descriptionTokenizer(spacing = "compact", markers = Markers) {
|
|
46923
|
-
const
|
|
47298
|
+
const join12 = getJoiner2(spacing);
|
|
46924
47299
|
return (spec) => {
|
|
46925
|
-
spec.description =
|
|
47300
|
+
spec.description = join12(spec.source, markers);
|
|
46926
47301
|
return spec;
|
|
46927
47302
|
};
|
|
46928
47303
|
}
|
|
@@ -46983,11 +47358,11 @@ function getParser4({ startLine = 0, fence = "```", spacing = "compact", markers
|
|
|
46983
47358
|
}
|
|
46984
47359
|
|
|
46985
47360
|
// ../../node_modules/.pnpm/comment-parser@1.4.1/node_modules/comment-parser/es6/stringifier/index.js
|
|
46986
|
-
function
|
|
47361
|
+
function join5(tokens) {
|
|
46987
47362
|
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;
|
|
46988
47363
|
}
|
|
46989
47364
|
function getStringifier() {
|
|
46990
|
-
return (block) => block.source.map(({ tokens }) =>
|
|
47365
|
+
return (block) => block.source.map(({ tokens }) => join5(tokens)).join("\n");
|
|
46991
47366
|
}
|
|
46992
47367
|
|
|
46993
47368
|
// ../../node_modules/.pnpm/comment-parser@1.4.1/node_modules/comment-parser/es6/stringifier/inspect.js
|
|
@@ -47156,6 +47531,32 @@ function extractPrimitiveDependencies(source) {
|
|
|
47156
47531
|
}
|
|
47157
47532
|
return primitives;
|
|
47158
47533
|
}
|
|
47534
|
+
var DEP_TAG_MAP = {
|
|
47535
|
+
dependencies: "runtime",
|
|
47536
|
+
devdependencies: "dev",
|
|
47537
|
+
"internal-dependencies": "internal",
|
|
47538
|
+
internaldependencies: "internal"
|
|
47539
|
+
};
|
|
47540
|
+
function extractJSDocDependencies(source) {
|
|
47541
|
+
const result = { runtime: [], dev: [], internal: [] };
|
|
47542
|
+
const blocks = parse3(source);
|
|
47543
|
+
if (blocks.length === 0) return result;
|
|
47544
|
+
for (const block of blocks) {
|
|
47545
|
+
for (const tag of block.tags) {
|
|
47546
|
+
const field = DEP_TAG_MAP[tag.tag.toLowerCase()];
|
|
47547
|
+
if (!field) continue;
|
|
47548
|
+
const value2 = getTagValue(tag).trim();
|
|
47549
|
+
if (value2) {
|
|
47550
|
+
result[field].push(...value2.split(/\s+/).filter(Boolean));
|
|
47551
|
+
}
|
|
47552
|
+
}
|
|
47553
|
+
}
|
|
47554
|
+
return {
|
|
47555
|
+
runtime: [...new Set(result.runtime)],
|
|
47556
|
+
dev: [...new Set(result.dev)],
|
|
47557
|
+
internal: [...new Set(result.internal)]
|
|
47558
|
+
};
|
|
47559
|
+
}
|
|
47159
47560
|
function toDisplayName(name2) {
|
|
47160
47561
|
return name2.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
47161
47562
|
}
|
|
@@ -48245,10 +48646,12 @@ var DEPTH_LEVELS = [
|
|
|
48245
48646
|
"base",
|
|
48246
48647
|
"dropdown",
|
|
48247
48648
|
"sticky",
|
|
48649
|
+
"navigation",
|
|
48248
48650
|
"fixed",
|
|
48249
48651
|
"modal",
|
|
48250
48652
|
"popover",
|
|
48251
|
-
"tooltip"
|
|
48653
|
+
"tooltip",
|
|
48654
|
+
"overlay"
|
|
48252
48655
|
];
|
|
48253
48656
|
var ELEVATION_LEVELS = [
|
|
48254
48657
|
"surface",
|
|
@@ -50307,14 +50710,14 @@ function buildColorSystem(options = {}) {
|
|
|
50307
50710
|
}
|
|
50308
50711
|
|
|
50309
50712
|
// ../design-tokens/src/persistence/node-adapter.ts
|
|
50310
|
-
import { mkdir as mkdir2, readdir as readdir2, readFile as
|
|
50311
|
-
import { join as
|
|
50713
|
+
import { mkdir as mkdir2, readdir as readdir2, readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
|
|
50714
|
+
import { join as join6 } from "path";
|
|
50312
50715
|
var SCHEMA_URL = "https://rafters.studio/schemas/namespace-tokens.json";
|
|
50313
50716
|
var VERSION = "1.0.0";
|
|
50314
50717
|
var NodePersistenceAdapter = class {
|
|
50315
50718
|
tokensDir;
|
|
50316
50719
|
constructor(projectRoot) {
|
|
50317
|
-
this.tokensDir =
|
|
50720
|
+
this.tokensDir = join6(projectRoot, ".rafters", "tokens");
|
|
50318
50721
|
}
|
|
50319
50722
|
async load() {
|
|
50320
50723
|
let files;
|
|
@@ -50326,7 +50729,7 @@ var NodePersistenceAdapter = class {
|
|
|
50326
50729
|
const allTokens = [];
|
|
50327
50730
|
for (const file2 of files) {
|
|
50328
50731
|
if (!file2.endsWith(".rafters.json")) continue;
|
|
50329
|
-
const content = await
|
|
50732
|
+
const content = await readFile3(join6(this.tokensDir, file2), "utf-8");
|
|
50330
50733
|
const data = NamespaceFileSchema.parse(JSON.parse(content));
|
|
50331
50734
|
allTokens.push(...data.tokens);
|
|
50332
50735
|
}
|
|
@@ -50354,7 +50757,7 @@ var NodePersistenceAdapter = class {
|
|
|
50354
50757
|
};
|
|
50355
50758
|
NamespaceFileSchema.parse(data);
|
|
50356
50759
|
await writeFile2(
|
|
50357
|
-
|
|
50760
|
+
join6(this.tokensDir, `${namespace}.rafters.json`),
|
|
50358
50761
|
JSON.stringify(data, null, 2)
|
|
50359
50762
|
);
|
|
50360
50763
|
}
|
|
@@ -50363,7 +50766,7 @@ var NodePersistenceAdapter = class {
|
|
|
50363
50766
|
|
|
50364
50767
|
// ../design-tokens/src/rule-engine.ts
|
|
50365
50768
|
import { promises as fs3 } from "fs";
|
|
50366
|
-
import { join as
|
|
50769
|
+
import { join as join7 } from "path";
|
|
50367
50770
|
var RuleResultSchema = external_exports.union([
|
|
50368
50771
|
external_exports.string(),
|
|
50369
50772
|
external_exports.object({
|
|
@@ -50379,11 +50782,11 @@ var RuleContextSchema = external_exports.object({
|
|
|
50379
50782
|
});
|
|
50380
50783
|
|
|
50381
50784
|
// src/utils/detect.ts
|
|
50382
|
-
import { readFile as
|
|
50383
|
-
import { join as
|
|
50785
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
50786
|
+
import { join as join8 } from "path";
|
|
50384
50787
|
async function detectFramework(cwd) {
|
|
50385
50788
|
try {
|
|
50386
|
-
const content = await
|
|
50789
|
+
const content = await readFile4(join8(cwd, "package.json"), "utf-8");
|
|
50387
50790
|
const pkg = JSON.parse(content);
|
|
50388
50791
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
50389
50792
|
if (deps.next) {
|
|
@@ -50409,7 +50812,7 @@ async function detectFramework(cwd) {
|
|
|
50409
50812
|
}
|
|
50410
50813
|
async function detectTailwindVersion(cwd) {
|
|
50411
50814
|
try {
|
|
50412
|
-
const content = await
|
|
50815
|
+
const content = await readFile4(join8(cwd, "package.json"), "utf-8");
|
|
50413
50816
|
const pkg = JSON.parse(content);
|
|
50414
50817
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
50415
50818
|
const tailwindVersion = deps.tailwindcss;
|
|
@@ -50430,7 +50833,7 @@ function isTailwindV3(version2) {
|
|
|
50430
50833
|
}
|
|
50431
50834
|
async function detectShadcn(cwd) {
|
|
50432
50835
|
try {
|
|
50433
|
-
const content = await
|
|
50836
|
+
const content = await readFile4(join8(cwd, "components.json"), "utf-8");
|
|
50434
50837
|
return JSON.parse(content);
|
|
50435
50838
|
} catch {
|
|
50436
50839
|
return null;
|
|
@@ -50492,60 +50895,6 @@ async function detectProject(cwd) {
|
|
|
50492
50895
|
};
|
|
50493
50896
|
}
|
|
50494
50897
|
|
|
50495
|
-
// src/utils/exports.ts
|
|
50496
|
-
var DEFAULT_EXPORTS = {
|
|
50497
|
-
tailwind: true,
|
|
50498
|
-
typescript: true,
|
|
50499
|
-
dtcg: false,
|
|
50500
|
-
compiled: false
|
|
50501
|
-
};
|
|
50502
|
-
var EXPORT_CHOICES = [
|
|
50503
|
-
{
|
|
50504
|
-
name: "Tailwind CSS (web projects)",
|
|
50505
|
-
value: "tailwind",
|
|
50506
|
-
checked: true
|
|
50507
|
-
},
|
|
50508
|
-
{
|
|
50509
|
-
name: "TypeScript (type-safe constants)",
|
|
50510
|
-
value: "typescript",
|
|
50511
|
-
checked: true
|
|
50512
|
-
},
|
|
50513
|
-
{
|
|
50514
|
-
name: "DTCG JSON (Figma Tokens, Style Dictionary)",
|
|
50515
|
-
value: "dtcg",
|
|
50516
|
-
checked: false
|
|
50517
|
-
},
|
|
50518
|
-
{
|
|
50519
|
-
name: "Standalone CSS (pre-built, no Tailwind required)",
|
|
50520
|
-
value: "compiled",
|
|
50521
|
-
checked: false
|
|
50522
|
-
}
|
|
50523
|
-
];
|
|
50524
|
-
var FUTURE_EXPORTS = [
|
|
50525
|
-
{
|
|
50526
|
-
name: "iOS (Swift/SwiftUI)",
|
|
50527
|
-
value: "tailwind",
|
|
50528
|
-
// placeholder
|
|
50529
|
-
checked: false,
|
|
50530
|
-
disabled: "coming soon"
|
|
50531
|
-
},
|
|
50532
|
-
{
|
|
50533
|
-
name: "Android (Compose)",
|
|
50534
|
-
value: "tailwind",
|
|
50535
|
-
// placeholder
|
|
50536
|
-
checked: false,
|
|
50537
|
-
disabled: "coming soon"
|
|
50538
|
-
}
|
|
50539
|
-
];
|
|
50540
|
-
function selectionsToConfig(selections) {
|
|
50541
|
-
return {
|
|
50542
|
-
tailwind: selections.includes("tailwind"),
|
|
50543
|
-
typescript: selections.includes("typescript"),
|
|
50544
|
-
dtcg: selections.includes("dtcg"),
|
|
50545
|
-
compiled: selections.includes("compiled")
|
|
50546
|
-
};
|
|
50547
|
-
}
|
|
50548
|
-
|
|
50549
50898
|
// src/commands/init.ts
|
|
50550
50899
|
async function backupCss(cssPath) {
|
|
50551
50900
|
const backupPath = cssPath.replace(/\.css$/, ".backup.css");
|
|
@@ -50571,7 +50920,7 @@ var COMPONENT_PATHS = {
|
|
|
50571
50920
|
async function findMainCssFile(cwd, framework) {
|
|
50572
50921
|
const locations = CSS_LOCATIONS[framework] || CSS_LOCATIONS.unknown;
|
|
50573
50922
|
for (const location of locations) {
|
|
50574
|
-
const fullPath =
|
|
50923
|
+
const fullPath = join9(cwd, location);
|
|
50575
50924
|
if (existsSync2(fullPath)) {
|
|
50576
50925
|
return location;
|
|
50577
50926
|
}
|
|
@@ -50579,10 +50928,10 @@ async function findMainCssFile(cwd, framework) {
|
|
|
50579
50928
|
return null;
|
|
50580
50929
|
}
|
|
50581
50930
|
async function updateMainCss(cwd, cssPath, themePath) {
|
|
50582
|
-
const fullCssPath =
|
|
50583
|
-
const cssContent = await
|
|
50584
|
-
const cssDir =
|
|
50585
|
-
const themeFullPath =
|
|
50931
|
+
const fullCssPath = join9(cwd, cssPath);
|
|
50932
|
+
const cssContent = await readFile5(fullCssPath, "utf-8");
|
|
50933
|
+
const cssDir = join9(cwd, cssPath, "..");
|
|
50934
|
+
const themeFullPath = join9(cwd, themePath);
|
|
50586
50935
|
const relativeThemePath = relative(cssDir, themeFullPath);
|
|
50587
50936
|
if (cssContent.includes(".rafters/output/rafters.css")) {
|
|
50588
50937
|
log({ event: "init:css_already_imported", cssPath });
|
|
@@ -50634,36 +50983,71 @@ async function promptExportFormats(existingConfig) {
|
|
|
50634
50983
|
});
|
|
50635
50984
|
return selectionsToConfig(selections);
|
|
50636
50985
|
}
|
|
50637
|
-
|
|
50986
|
+
function isTailwindCliInstalled() {
|
|
50987
|
+
const require2 = createRequire(import.meta.url);
|
|
50988
|
+
try {
|
|
50989
|
+
require2.resolve("@tailwindcss/cli/package.json");
|
|
50990
|
+
return true;
|
|
50991
|
+
} catch (err) {
|
|
50992
|
+
if (err instanceof Error && "code" in err && err.code === "MODULE_NOT_FOUND") {
|
|
50993
|
+
return false;
|
|
50994
|
+
}
|
|
50995
|
+
throw err;
|
|
50996
|
+
}
|
|
50997
|
+
}
|
|
50998
|
+
async function ensureTailwindCli(cwd) {
|
|
50999
|
+
if (!isInteractive() || isAgentMode()) {
|
|
51000
|
+
throw new Error(
|
|
51001
|
+
"Standalone CSS export requires @tailwindcss/cli. Install it as a dev dependency in your project."
|
|
51002
|
+
);
|
|
51003
|
+
}
|
|
51004
|
+
const shouldInstall = await confirm({
|
|
51005
|
+
message: "Standalone CSS requires @tailwindcss/cli. Install it now?",
|
|
51006
|
+
default: true
|
|
51007
|
+
});
|
|
51008
|
+
if (!shouldInstall) {
|
|
51009
|
+
throw new Error("Standalone CSS export requires @tailwindcss/cli.");
|
|
51010
|
+
}
|
|
51011
|
+
await updateDependencies([], ["@tailwindcss/cli"], { cwd });
|
|
51012
|
+
if (!isTailwindCliInstalled()) {
|
|
51013
|
+
throw new Error(
|
|
51014
|
+
"@tailwindcss/cli was installed but cannot be resolved. Try installing at the workspace root."
|
|
51015
|
+
);
|
|
51016
|
+
}
|
|
51017
|
+
}
|
|
51018
|
+
async function generateOutputs(cwd, paths, registry2, exports, shadcn) {
|
|
50638
51019
|
const outputs = [];
|
|
50639
51020
|
if (exports.tailwind) {
|
|
50640
51021
|
const tailwindCss = registryToTailwind(registry2, { includeImport: !shadcn });
|
|
50641
|
-
await writeFile3(
|
|
51022
|
+
await writeFile3(join9(paths.output, "rafters.css"), tailwindCss);
|
|
50642
51023
|
outputs.push("rafters.css");
|
|
50643
51024
|
}
|
|
50644
51025
|
if (exports.typescript) {
|
|
50645
51026
|
const typescriptSrc = registryToTypeScript(registry2, { includeJSDoc: true });
|
|
50646
|
-
await writeFile3(
|
|
51027
|
+
await writeFile3(join9(paths.output, "rafters.ts"), typescriptSrc);
|
|
50647
51028
|
outputs.push("rafters.ts");
|
|
50648
51029
|
}
|
|
50649
51030
|
if (exports.dtcg) {
|
|
50650
51031
|
const dtcgJson = toDTCG(registry2.list());
|
|
50651
|
-
await writeFile3(
|
|
51032
|
+
await writeFile3(join9(paths.output, "rafters.json"), JSON.stringify(dtcgJson, null, 2));
|
|
50652
51033
|
outputs.push("rafters.json");
|
|
50653
51034
|
}
|
|
50654
51035
|
if (exports.compiled) {
|
|
51036
|
+
if (!isTailwindCliInstalled()) {
|
|
51037
|
+
await ensureTailwindCli(cwd);
|
|
51038
|
+
}
|
|
50655
51039
|
log({ event: "init:compiling_css" });
|
|
50656
51040
|
const compiledCss = await registryToCompiled(registry2, { includeImport: !shadcn });
|
|
50657
|
-
await writeFile3(
|
|
51041
|
+
await writeFile3(join9(paths.output, "rafters.standalone.css"), compiledCss);
|
|
50658
51042
|
outputs.push("rafters.standalone.css");
|
|
50659
51043
|
}
|
|
50660
51044
|
return outputs;
|
|
50661
51045
|
}
|
|
50662
|
-
async function regenerateFromExisting(cwd, paths, shadcn,
|
|
51046
|
+
async function regenerateFromExisting(cwd, paths, shadcn, isAgentMode2) {
|
|
50663
51047
|
log({ event: "init:regenerate", cwd });
|
|
50664
51048
|
let existingConfig = null;
|
|
50665
51049
|
try {
|
|
50666
|
-
const configContent = await
|
|
51050
|
+
const configContent = await readFile5(paths.config, "utf-8");
|
|
50667
51051
|
existingConfig = JSON.parse(configContent);
|
|
50668
51052
|
} catch {
|
|
50669
51053
|
}
|
|
@@ -50680,7 +51064,7 @@ async function regenerateFromExisting(cwd, paths, shadcn, isAgentMode) {
|
|
|
50680
51064
|
});
|
|
50681
51065
|
const registry2 = new TokenRegistry(allTokens);
|
|
50682
51066
|
let exports;
|
|
50683
|
-
if (
|
|
51067
|
+
if (isAgentMode2) {
|
|
50684
51068
|
exports = existingConfig?.exports ?? DEFAULT_EXPORTS;
|
|
50685
51069
|
log({ event: "init:exports_default", exports });
|
|
50686
51070
|
} else {
|
|
@@ -50691,7 +51075,7 @@ async function regenerateFromExisting(cwd, paths, shadcn, isAgentMode) {
|
|
|
50691
51075
|
log({ event: "init:exports_selected", exports });
|
|
50692
51076
|
}
|
|
50693
51077
|
await mkdir3(paths.output, { recursive: true });
|
|
50694
|
-
const outputs = await generateOutputs(paths, registry2, exports, shadcn);
|
|
51078
|
+
const outputs = await generateOutputs(cwd, paths, registry2, exports, shadcn);
|
|
50695
51079
|
if (existingConfig) {
|
|
50696
51080
|
existingConfig.exports = exports;
|
|
50697
51081
|
await writeFile3(paths.config, JSON.stringify(existingConfig, null, 2));
|
|
@@ -50702,11 +51086,11 @@ async function regenerateFromExisting(cwd, paths, shadcn, isAgentMode) {
|
|
|
50702
51086
|
path: paths.output
|
|
50703
51087
|
});
|
|
50704
51088
|
}
|
|
50705
|
-
async function resetToDefaults(cwd, paths, shadcn,
|
|
51089
|
+
async function resetToDefaults(cwd, paths, shadcn, isAgentMode2) {
|
|
50706
51090
|
log({ event: "init:reset", cwd });
|
|
50707
51091
|
let existingConfig = null;
|
|
50708
51092
|
try {
|
|
50709
|
-
const configContent = await
|
|
51093
|
+
const configContent = await readFile5(paths.config, "utf-8");
|
|
50710
51094
|
existingConfig = JSON.parse(configContent);
|
|
50711
51095
|
} catch {
|
|
50712
51096
|
}
|
|
@@ -50726,7 +51110,7 @@ async function resetToDefaults(cwd, paths, shadcn, isAgentMode) {
|
|
|
50726
51110
|
};
|
|
50727
51111
|
await mkdir3(paths.output, { recursive: true });
|
|
50728
51112
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
50729
|
-
const backupPath =
|
|
51113
|
+
const backupPath = join9(paths.output, `reset-${timestamp}.json`);
|
|
50730
51114
|
await writeFile3(backupPath, JSON.stringify(backup, null, 2));
|
|
50731
51115
|
log({
|
|
50732
51116
|
event: "init:reset_backup",
|
|
@@ -50735,7 +51119,7 @@ async function resetToDefaults(cwd, paths, shadcn, isAgentMode) {
|
|
|
50735
51119
|
});
|
|
50736
51120
|
}
|
|
50737
51121
|
let exports;
|
|
50738
|
-
if (
|
|
51122
|
+
if (isAgentMode2) {
|
|
50739
51123
|
exports = existingConfig?.exports ?? DEFAULT_EXPORTS;
|
|
50740
51124
|
log({ event: "init:exports_default", exports });
|
|
50741
51125
|
} else {
|
|
@@ -50768,7 +51152,7 @@ async function resetToDefaults(cwd, paths, shadcn, isAgentMode) {
|
|
|
50768
51152
|
namespaceCount
|
|
50769
51153
|
});
|
|
50770
51154
|
await mkdir3(paths.output, { recursive: true });
|
|
50771
|
-
const outputs = await generateOutputs(paths, registry2, exports, shadcn);
|
|
51155
|
+
const outputs = await generateOutputs(cwd, paths, registry2, exports, shadcn);
|
|
50772
51156
|
if (existingConfig) {
|
|
50773
51157
|
existingConfig.exports = exports;
|
|
50774
51158
|
await writeFile3(paths.config, JSON.stringify(existingConfig, null, 2));
|
|
@@ -50781,7 +51165,7 @@ async function resetToDefaults(cwd, paths, shadcn, isAgentMode) {
|
|
|
50781
51165
|
}
|
|
50782
51166
|
async function init(options) {
|
|
50783
51167
|
setAgentMode(options.agent ?? false);
|
|
50784
|
-
const
|
|
51168
|
+
const isAgentMode2 = options.agent ?? false;
|
|
50785
51169
|
const cwd = process.cwd();
|
|
50786
51170
|
const paths = getRaftersPaths(cwd);
|
|
50787
51171
|
log({ event: "init:start", cwd });
|
|
@@ -50800,7 +51184,7 @@ async function init(options) {
|
|
|
50800
51184
|
throw new Error("Nothing to reset. No .rafters/ directory found.");
|
|
50801
51185
|
}
|
|
50802
51186
|
if (raftersExists && options.reset) {
|
|
50803
|
-
await resetToDefaults(cwd, paths, shadcn,
|
|
51187
|
+
await resetToDefaults(cwd, paths, shadcn, isAgentMode2);
|
|
50804
51188
|
return;
|
|
50805
51189
|
}
|
|
50806
51190
|
if (raftersExists && !options.rebuild) {
|
|
@@ -50809,14 +51193,14 @@ async function init(options) {
|
|
|
50809
51193
|
);
|
|
50810
51194
|
}
|
|
50811
51195
|
if (raftersExists && options.rebuild) {
|
|
50812
|
-
await regenerateFromExisting(cwd, paths, shadcn,
|
|
51196
|
+
await regenerateFromExisting(cwd, paths, shadcn, isAgentMode2);
|
|
50813
51197
|
return;
|
|
50814
51198
|
}
|
|
50815
51199
|
let existingColors = null;
|
|
50816
51200
|
if (shadcn?.tailwind?.css) {
|
|
50817
|
-
const cssPath =
|
|
51201
|
+
const cssPath = join9(cwd, shadcn.tailwind.css);
|
|
50818
51202
|
try {
|
|
50819
|
-
const cssContent = await
|
|
51203
|
+
const cssContent = await readFile5(cssPath, "utf-8");
|
|
50820
51204
|
existingColors = parseCssVariables(cssContent);
|
|
50821
51205
|
const backupPath = await backupCss(cssPath);
|
|
50822
51206
|
log({
|
|
@@ -50833,7 +51217,7 @@ async function init(options) {
|
|
|
50833
51217
|
}
|
|
50834
51218
|
}
|
|
50835
51219
|
let exports;
|
|
50836
|
-
if (
|
|
51220
|
+
if (isAgentMode2) {
|
|
50837
51221
|
exports = DEFAULT_EXPORTS;
|
|
50838
51222
|
log({ event: "init:exports_default", exports });
|
|
50839
51223
|
} else {
|
|
@@ -50899,7 +51283,7 @@ async function init(options) {
|
|
|
50899
51283
|
path: paths.tokens,
|
|
50900
51284
|
namespaceCount
|
|
50901
51285
|
});
|
|
50902
|
-
const outputs = await generateOutputs(paths, registry2, exports, shadcn);
|
|
51286
|
+
const outputs = await generateOutputs(cwd, paths, registry2, exports, shadcn);
|
|
50903
51287
|
let detectedCssPath = null;
|
|
50904
51288
|
if (!shadcn && exports.tailwind) {
|
|
50905
51289
|
detectedCssPath = await findMainCssFile(cwd, framework);
|
|
@@ -50922,7 +51306,11 @@ async function init(options) {
|
|
|
50922
51306
|
primitivesPath: frameworkPaths.primitives,
|
|
50923
51307
|
cssPath: detectedCssPath,
|
|
50924
51308
|
shadcn: !!shadcn,
|
|
50925
|
-
exports
|
|
51309
|
+
exports,
|
|
51310
|
+
installed: {
|
|
51311
|
+
components: [],
|
|
51312
|
+
primitives: []
|
|
51313
|
+
}
|
|
50926
51314
|
};
|
|
50927
51315
|
await writeFile3(paths.config, JSON.stringify(config3, null, 2));
|
|
50928
51316
|
log({
|
|
@@ -50938,8 +51326,916 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
50938
51326
|
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
50939
51327
|
|
|
50940
51328
|
// src/mcp/tools.ts
|
|
50941
|
-
import {
|
|
50942
|
-
import {
|
|
51329
|
+
import { existsSync as existsSync3 } from "fs";
|
|
51330
|
+
import { readdir as readdir3, readFile as readFile6 } from "fs/promises";
|
|
51331
|
+
import { basename, join as join10 } from "path";
|
|
51332
|
+
|
|
51333
|
+
// src/mcp/cognitive-load.ts
|
|
51334
|
+
var BUDGET_TIERS = {
|
|
51335
|
+
focused: 15,
|
|
51336
|
+
page: 30,
|
|
51337
|
+
app: 45
|
|
51338
|
+
};
|
|
51339
|
+
var COMPONENT_SCORES = {
|
|
51340
|
+
// Score 0 -- Structural only, no cognitive demand
|
|
51341
|
+
separator: {
|
|
51342
|
+
dimensions: {
|
|
51343
|
+
decisionDemand: 0,
|
|
51344
|
+
informationDensity: 0,
|
|
51345
|
+
interactionComplexity: 0,
|
|
51346
|
+
contextDisruption: 0,
|
|
51347
|
+
learningCurve: 0
|
|
51348
|
+
},
|
|
51349
|
+
primaryCostDriver: "Structural only, no cognitive demand"
|
|
51350
|
+
},
|
|
51351
|
+
container: {
|
|
51352
|
+
dimensions: {
|
|
51353
|
+
decisionDemand: 0,
|
|
51354
|
+
informationDensity: 0,
|
|
51355
|
+
interactionComplexity: 0,
|
|
51356
|
+
contextDisruption: 0,
|
|
51357
|
+
learningCurve: 0
|
|
51358
|
+
},
|
|
51359
|
+
primaryCostDriver: "Structural only, no cognitive demand"
|
|
51360
|
+
},
|
|
51361
|
+
"aspect-ratio": {
|
|
51362
|
+
dimensions: {
|
|
51363
|
+
decisionDemand: 0,
|
|
51364
|
+
informationDensity: 0,
|
|
51365
|
+
interactionComplexity: 0,
|
|
51366
|
+
contextDisruption: 0,
|
|
51367
|
+
learningCurve: 0
|
|
51368
|
+
},
|
|
51369
|
+
primaryCostDriver: "Structural only, no cognitive demand"
|
|
51370
|
+
},
|
|
51371
|
+
// Score 1 -- Display only, minimal information
|
|
51372
|
+
skeleton: {
|
|
51373
|
+
dimensions: {
|
|
51374
|
+
decisionDemand: 0,
|
|
51375
|
+
informationDensity: 1,
|
|
51376
|
+
interactionComplexity: 0,
|
|
51377
|
+
contextDisruption: 0,
|
|
51378
|
+
learningCurve: 0
|
|
51379
|
+
},
|
|
51380
|
+
primaryCostDriver: "Display only, minimal information"
|
|
51381
|
+
},
|
|
51382
|
+
kbd: {
|
|
51383
|
+
dimensions: {
|
|
51384
|
+
decisionDemand: 0,
|
|
51385
|
+
informationDensity: 1,
|
|
51386
|
+
interactionComplexity: 0,
|
|
51387
|
+
contextDisruption: 0,
|
|
51388
|
+
learningCurve: 0
|
|
51389
|
+
},
|
|
51390
|
+
primaryCostDriver: "Display only, minimal information"
|
|
51391
|
+
},
|
|
51392
|
+
// Score 2 -- Simple state or single information piece
|
|
51393
|
+
badge: {
|
|
51394
|
+
dimensions: {
|
|
51395
|
+
decisionDemand: 0,
|
|
51396
|
+
informationDensity: 1,
|
|
51397
|
+
interactionComplexity: 0,
|
|
51398
|
+
contextDisruption: 0,
|
|
51399
|
+
learningCurve: 1
|
|
51400
|
+
},
|
|
51401
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51402
|
+
},
|
|
51403
|
+
breadcrumb: {
|
|
51404
|
+
dimensions: {
|
|
51405
|
+
decisionDemand: 0,
|
|
51406
|
+
informationDensity: 1,
|
|
51407
|
+
interactionComplexity: 1,
|
|
51408
|
+
contextDisruption: 0,
|
|
51409
|
+
learningCurve: 0
|
|
51410
|
+
},
|
|
51411
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51412
|
+
},
|
|
51413
|
+
label: {
|
|
51414
|
+
dimensions: {
|
|
51415
|
+
decisionDemand: 0,
|
|
51416
|
+
informationDensity: 1,
|
|
51417
|
+
interactionComplexity: 0,
|
|
51418
|
+
contextDisruption: 0,
|
|
51419
|
+
learningCurve: 1
|
|
51420
|
+
},
|
|
51421
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51422
|
+
},
|
|
51423
|
+
checkbox: {
|
|
51424
|
+
dimensions: {
|
|
51425
|
+
decisionDemand: 1,
|
|
51426
|
+
informationDensity: 0,
|
|
51427
|
+
interactionComplexity: 1,
|
|
51428
|
+
contextDisruption: 0,
|
|
51429
|
+
learningCurve: 0
|
|
51430
|
+
},
|
|
51431
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51432
|
+
},
|
|
51433
|
+
switch: {
|
|
51434
|
+
dimensions: {
|
|
51435
|
+
decisionDemand: 1,
|
|
51436
|
+
informationDensity: 0,
|
|
51437
|
+
interactionComplexity: 1,
|
|
51438
|
+
contextDisruption: 0,
|
|
51439
|
+
learningCurve: 0
|
|
51440
|
+
},
|
|
51441
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51442
|
+
},
|
|
51443
|
+
toggle: {
|
|
51444
|
+
dimensions: {
|
|
51445
|
+
decisionDemand: 1,
|
|
51446
|
+
informationDensity: 0,
|
|
51447
|
+
interactionComplexity: 1,
|
|
51448
|
+
contextDisruption: 0,
|
|
51449
|
+
learningCurve: 0
|
|
51450
|
+
},
|
|
51451
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51452
|
+
},
|
|
51453
|
+
"button-group": {
|
|
51454
|
+
dimensions: {
|
|
51455
|
+
decisionDemand: 1,
|
|
51456
|
+
informationDensity: 1,
|
|
51457
|
+
interactionComplexity: 0,
|
|
51458
|
+
contextDisruption: 0,
|
|
51459
|
+
learningCurve: 0
|
|
51460
|
+
},
|
|
51461
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51462
|
+
},
|
|
51463
|
+
card: {
|
|
51464
|
+
dimensions: {
|
|
51465
|
+
decisionDemand: 0,
|
|
51466
|
+
informationDensity: 1,
|
|
51467
|
+
interactionComplexity: 0,
|
|
51468
|
+
contextDisruption: 0,
|
|
51469
|
+
learningCurve: 1
|
|
51470
|
+
},
|
|
51471
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51472
|
+
},
|
|
51473
|
+
collapsible: {
|
|
51474
|
+
dimensions: {
|
|
51475
|
+
decisionDemand: 1,
|
|
51476
|
+
informationDensity: 0,
|
|
51477
|
+
interactionComplexity: 1,
|
|
51478
|
+
contextDisruption: 0,
|
|
51479
|
+
learningCurve: 0
|
|
51480
|
+
},
|
|
51481
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51482
|
+
},
|
|
51483
|
+
avatar: {
|
|
51484
|
+
dimensions: {
|
|
51485
|
+
decisionDemand: 0,
|
|
51486
|
+
informationDensity: 1,
|
|
51487
|
+
interactionComplexity: 0,
|
|
51488
|
+
contextDisruption: 0,
|
|
51489
|
+
learningCurve: 1
|
|
51490
|
+
},
|
|
51491
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51492
|
+
},
|
|
51493
|
+
"scroll-area": {
|
|
51494
|
+
dimensions: {
|
|
51495
|
+
decisionDemand: 0,
|
|
51496
|
+
informationDensity: 1,
|
|
51497
|
+
interactionComplexity: 1,
|
|
51498
|
+
contextDisruption: 0,
|
|
51499
|
+
learningCurve: 0
|
|
51500
|
+
},
|
|
51501
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51502
|
+
},
|
|
51503
|
+
tooltip: {
|
|
51504
|
+
dimensions: {
|
|
51505
|
+
decisionDemand: 0,
|
|
51506
|
+
informationDensity: 1,
|
|
51507
|
+
interactionComplexity: 0,
|
|
51508
|
+
contextDisruption: 0,
|
|
51509
|
+
learningCurve: 1
|
|
51510
|
+
},
|
|
51511
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51512
|
+
},
|
|
51513
|
+
typography: {
|
|
51514
|
+
dimensions: {
|
|
51515
|
+
decisionDemand: 0,
|
|
51516
|
+
informationDensity: 1,
|
|
51517
|
+
interactionComplexity: 0,
|
|
51518
|
+
contextDisruption: 0,
|
|
51519
|
+
learningCurve: 1
|
|
51520
|
+
},
|
|
51521
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51522
|
+
},
|
|
51523
|
+
spinner: {
|
|
51524
|
+
dimensions: {
|
|
51525
|
+
decisionDemand: 0,
|
|
51526
|
+
informationDensity: 1,
|
|
51527
|
+
interactionComplexity: 0,
|
|
51528
|
+
contextDisruption: 0,
|
|
51529
|
+
learningCurve: 1
|
|
51530
|
+
},
|
|
51531
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51532
|
+
},
|
|
51533
|
+
empty: {
|
|
51534
|
+
dimensions: {
|
|
51535
|
+
decisionDemand: 1,
|
|
51536
|
+
informationDensity: 1,
|
|
51537
|
+
interactionComplexity: 0,
|
|
51538
|
+
contextDisruption: 0,
|
|
51539
|
+
learningCurve: 0
|
|
51540
|
+
},
|
|
51541
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51542
|
+
},
|
|
51543
|
+
"toggle-group": {
|
|
51544
|
+
dimensions: {
|
|
51545
|
+
decisionDemand: 1,
|
|
51546
|
+
informationDensity: 1,
|
|
51547
|
+
interactionComplexity: 0,
|
|
51548
|
+
contextDisruption: 0,
|
|
51549
|
+
learningCurve: 0
|
|
51550
|
+
},
|
|
51551
|
+
primaryCostDriver: "Simple state or single information piece"
|
|
51552
|
+
},
|
|
51553
|
+
// Score 3 -- One decision + one interaction mode
|
|
51554
|
+
button: {
|
|
51555
|
+
dimensions: {
|
|
51556
|
+
decisionDemand: 1,
|
|
51557
|
+
informationDensity: 1,
|
|
51558
|
+
interactionComplexity: 1,
|
|
51559
|
+
contextDisruption: 0,
|
|
51560
|
+
learningCurve: 0
|
|
51561
|
+
},
|
|
51562
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51563
|
+
},
|
|
51564
|
+
alert: {
|
|
51565
|
+
dimensions: {
|
|
51566
|
+
decisionDemand: 0,
|
|
51567
|
+
informationDensity: 1,
|
|
51568
|
+
interactionComplexity: 1,
|
|
51569
|
+
contextDisruption: 0,
|
|
51570
|
+
learningCurve: 1
|
|
51571
|
+
},
|
|
51572
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51573
|
+
},
|
|
51574
|
+
sidebar: {
|
|
51575
|
+
dimensions: {
|
|
51576
|
+
decisionDemand: 1,
|
|
51577
|
+
informationDensity: 1,
|
|
51578
|
+
interactionComplexity: 1,
|
|
51579
|
+
contextDisruption: 0,
|
|
51580
|
+
learningCurve: 0
|
|
51581
|
+
},
|
|
51582
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51583
|
+
},
|
|
51584
|
+
accordion: {
|
|
51585
|
+
dimensions: {
|
|
51586
|
+
decisionDemand: 1,
|
|
51587
|
+
informationDensity: 1,
|
|
51588
|
+
interactionComplexity: 0,
|
|
51589
|
+
contextDisruption: 0,
|
|
51590
|
+
learningCurve: 1
|
|
51591
|
+
},
|
|
51592
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51593
|
+
},
|
|
51594
|
+
slider: {
|
|
51595
|
+
dimensions: {
|
|
51596
|
+
decisionDemand: 1,
|
|
51597
|
+
informationDensity: 0,
|
|
51598
|
+
interactionComplexity: 1,
|
|
51599
|
+
contextDisruption: 0,
|
|
51600
|
+
learningCurve: 1
|
|
51601
|
+
},
|
|
51602
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51603
|
+
},
|
|
51604
|
+
"radio-group": {
|
|
51605
|
+
dimensions: {
|
|
51606
|
+
decisionDemand: 1,
|
|
51607
|
+
informationDensity: 1,
|
|
51608
|
+
interactionComplexity: 1,
|
|
51609
|
+
contextDisruption: 0,
|
|
51610
|
+
learningCurve: 0
|
|
51611
|
+
},
|
|
51612
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51613
|
+
},
|
|
51614
|
+
table: {
|
|
51615
|
+
dimensions: {
|
|
51616
|
+
decisionDemand: 0,
|
|
51617
|
+
informationDensity: 2,
|
|
51618
|
+
interactionComplexity: 0,
|
|
51619
|
+
contextDisruption: 0,
|
|
51620
|
+
learningCurve: 1
|
|
51621
|
+
},
|
|
51622
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51623
|
+
},
|
|
51624
|
+
resizable: {
|
|
51625
|
+
dimensions: {
|
|
51626
|
+
decisionDemand: 1,
|
|
51627
|
+
informationDensity: 0,
|
|
51628
|
+
interactionComplexity: 1,
|
|
51629
|
+
contextDisruption: 0,
|
|
51630
|
+
learningCurve: 1
|
|
51631
|
+
},
|
|
51632
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51633
|
+
},
|
|
51634
|
+
field: {
|
|
51635
|
+
dimensions: {
|
|
51636
|
+
decisionDemand: 1,
|
|
51637
|
+
informationDensity: 1,
|
|
51638
|
+
interactionComplexity: 1,
|
|
51639
|
+
contextDisruption: 0,
|
|
51640
|
+
learningCurve: 0
|
|
51641
|
+
},
|
|
51642
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51643
|
+
},
|
|
51644
|
+
"hover-card": {
|
|
51645
|
+
dimensions: {
|
|
51646
|
+
decisionDemand: 0,
|
|
51647
|
+
informationDensity: 1,
|
|
51648
|
+
interactionComplexity: 0,
|
|
51649
|
+
contextDisruption: 1,
|
|
51650
|
+
learningCurve: 1
|
|
51651
|
+
},
|
|
51652
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51653
|
+
},
|
|
51654
|
+
image: {
|
|
51655
|
+
dimensions: {
|
|
51656
|
+
decisionDemand: 0,
|
|
51657
|
+
informationDensity: 2,
|
|
51658
|
+
interactionComplexity: 0,
|
|
51659
|
+
contextDisruption: 0,
|
|
51660
|
+
learningCurve: 1
|
|
51661
|
+
},
|
|
51662
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51663
|
+
},
|
|
51664
|
+
embed: {
|
|
51665
|
+
dimensions: {
|
|
51666
|
+
decisionDemand: 0,
|
|
51667
|
+
informationDensity: 2,
|
|
51668
|
+
interactionComplexity: 0,
|
|
51669
|
+
contextDisruption: 0,
|
|
51670
|
+
learningCurve: 1
|
|
51671
|
+
},
|
|
51672
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51673
|
+
},
|
|
51674
|
+
item: {
|
|
51675
|
+
dimensions: {
|
|
51676
|
+
decisionDemand: 1,
|
|
51677
|
+
informationDensity: 1,
|
|
51678
|
+
interactionComplexity: 1,
|
|
51679
|
+
contextDisruption: 0,
|
|
51680
|
+
learningCurve: 0
|
|
51681
|
+
},
|
|
51682
|
+
primaryCostDriver: "One decision + one interaction mode"
|
|
51683
|
+
},
|
|
51684
|
+
// Score 4 -- Data entry or menu scanning
|
|
51685
|
+
input: {
|
|
51686
|
+
dimensions: {
|
|
51687
|
+
decisionDemand: 1,
|
|
51688
|
+
informationDensity: 1,
|
|
51689
|
+
interactionComplexity: 1,
|
|
51690
|
+
contextDisruption: 0,
|
|
51691
|
+
learningCurve: 1
|
|
51692
|
+
},
|
|
51693
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51694
|
+
},
|
|
51695
|
+
textarea: {
|
|
51696
|
+
dimensions: {
|
|
51697
|
+
decisionDemand: 1,
|
|
51698
|
+
informationDensity: 1,
|
|
51699
|
+
interactionComplexity: 1,
|
|
51700
|
+
contextDisruption: 0,
|
|
51701
|
+
learningCurve: 1
|
|
51702
|
+
},
|
|
51703
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51704
|
+
},
|
|
51705
|
+
"input-group": {
|
|
51706
|
+
dimensions: {
|
|
51707
|
+
decisionDemand: 1,
|
|
51708
|
+
informationDensity: 1,
|
|
51709
|
+
interactionComplexity: 1,
|
|
51710
|
+
contextDisruption: 0,
|
|
51711
|
+
learningCurve: 1
|
|
51712
|
+
},
|
|
51713
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51714
|
+
},
|
|
51715
|
+
"input-otp": {
|
|
51716
|
+
dimensions: {
|
|
51717
|
+
decisionDemand: 1,
|
|
51718
|
+
informationDensity: 1,
|
|
51719
|
+
interactionComplexity: 1,
|
|
51720
|
+
contextDisruption: 0,
|
|
51721
|
+
learningCurve: 1
|
|
51722
|
+
},
|
|
51723
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51724
|
+
},
|
|
51725
|
+
carousel: {
|
|
51726
|
+
dimensions: {
|
|
51727
|
+
decisionDemand: 1,
|
|
51728
|
+
informationDensity: 1,
|
|
51729
|
+
interactionComplexity: 1,
|
|
51730
|
+
contextDisruption: 0,
|
|
51731
|
+
learningCurve: 1
|
|
51732
|
+
},
|
|
51733
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51734
|
+
},
|
|
51735
|
+
tabs: {
|
|
51736
|
+
dimensions: {
|
|
51737
|
+
decisionDemand: 1,
|
|
51738
|
+
informationDensity: 1,
|
|
51739
|
+
interactionComplexity: 1,
|
|
51740
|
+
contextDisruption: 0,
|
|
51741
|
+
learningCurve: 1
|
|
51742
|
+
},
|
|
51743
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51744
|
+
},
|
|
51745
|
+
"context-menu": {
|
|
51746
|
+
dimensions: {
|
|
51747
|
+
decisionDemand: 1,
|
|
51748
|
+
informationDensity: 1,
|
|
51749
|
+
interactionComplexity: 1,
|
|
51750
|
+
contextDisruption: 0,
|
|
51751
|
+
learningCurve: 1
|
|
51752
|
+
},
|
|
51753
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51754
|
+
},
|
|
51755
|
+
"dropdown-menu": {
|
|
51756
|
+
dimensions: {
|
|
51757
|
+
decisionDemand: 1,
|
|
51758
|
+
informationDensity: 1,
|
|
51759
|
+
interactionComplexity: 1,
|
|
51760
|
+
contextDisruption: 0,
|
|
51761
|
+
learningCurve: 1
|
|
51762
|
+
},
|
|
51763
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51764
|
+
},
|
|
51765
|
+
popover: {
|
|
51766
|
+
dimensions: {
|
|
51767
|
+
decisionDemand: 0,
|
|
51768
|
+
informationDensity: 1,
|
|
51769
|
+
interactionComplexity: 1,
|
|
51770
|
+
contextDisruption: 1,
|
|
51771
|
+
learningCurve: 1
|
|
51772
|
+
},
|
|
51773
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51774
|
+
},
|
|
51775
|
+
progress: {
|
|
51776
|
+
dimensions: {
|
|
51777
|
+
decisionDemand: 0,
|
|
51778
|
+
informationDensity: 2,
|
|
51779
|
+
interactionComplexity: 0,
|
|
51780
|
+
contextDisruption: 1,
|
|
51781
|
+
learningCurve: 1
|
|
51782
|
+
},
|
|
51783
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51784
|
+
},
|
|
51785
|
+
drawer: {
|
|
51786
|
+
dimensions: {
|
|
51787
|
+
decisionDemand: 1,
|
|
51788
|
+
informationDensity: 1,
|
|
51789
|
+
interactionComplexity: 1,
|
|
51790
|
+
contextDisruption: 1,
|
|
51791
|
+
learningCurve: 0
|
|
51792
|
+
},
|
|
51793
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51794
|
+
},
|
|
51795
|
+
grid: {
|
|
51796
|
+
dimensions: {
|
|
51797
|
+
decisionDemand: 0,
|
|
51798
|
+
informationDensity: 2,
|
|
51799
|
+
interactionComplexity: 0,
|
|
51800
|
+
contextDisruption: 0,
|
|
51801
|
+
learningCurve: 2
|
|
51802
|
+
},
|
|
51803
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51804
|
+
},
|
|
51805
|
+
"block-wrapper": {
|
|
51806
|
+
dimensions: {
|
|
51807
|
+
decisionDemand: 1,
|
|
51808
|
+
informationDensity: 1,
|
|
51809
|
+
interactionComplexity: 1,
|
|
51810
|
+
contextDisruption: 0,
|
|
51811
|
+
learningCurve: 1
|
|
51812
|
+
},
|
|
51813
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51814
|
+
},
|
|
51815
|
+
"inline-toolbar": {
|
|
51816
|
+
dimensions: {
|
|
51817
|
+
decisionDemand: 1,
|
|
51818
|
+
informationDensity: 1,
|
|
51819
|
+
interactionComplexity: 1,
|
|
51820
|
+
contextDisruption: 0,
|
|
51821
|
+
learningCurve: 1
|
|
51822
|
+
},
|
|
51823
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51824
|
+
},
|
|
51825
|
+
"editor-toolbar": {
|
|
51826
|
+
dimensions: {
|
|
51827
|
+
decisionDemand: 1,
|
|
51828
|
+
informationDensity: 1,
|
|
51829
|
+
interactionComplexity: 1,
|
|
51830
|
+
contextDisruption: 0,
|
|
51831
|
+
learningCurve: 1
|
|
51832
|
+
},
|
|
51833
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51834
|
+
},
|
|
51835
|
+
pagination: {
|
|
51836
|
+
dimensions: {
|
|
51837
|
+
decisionDemand: 1,
|
|
51838
|
+
informationDensity: 1,
|
|
51839
|
+
interactionComplexity: 1,
|
|
51840
|
+
contextDisruption: 0,
|
|
51841
|
+
learningCurve: 1
|
|
51842
|
+
},
|
|
51843
|
+
primaryCostDriver: "Data entry or menu scanning"
|
|
51844
|
+
},
|
|
51845
|
+
// Score 5 -- Multi-step interaction or spatial reasoning
|
|
51846
|
+
sheet: {
|
|
51847
|
+
dimensions: {
|
|
51848
|
+
decisionDemand: 1,
|
|
51849
|
+
informationDensity: 1,
|
|
51850
|
+
interactionComplexity: 1,
|
|
51851
|
+
contextDisruption: 1,
|
|
51852
|
+
learningCurve: 1
|
|
51853
|
+
},
|
|
51854
|
+
primaryCostDriver: "Multi-step interaction or spatial reasoning"
|
|
51855
|
+
},
|
|
51856
|
+
"date-picker": {
|
|
51857
|
+
dimensions: {
|
|
51858
|
+
decisionDemand: 1,
|
|
51859
|
+
informationDensity: 1,
|
|
51860
|
+
interactionComplexity: 2,
|
|
51861
|
+
contextDisruption: 0,
|
|
51862
|
+
learningCurve: 1
|
|
51863
|
+
},
|
|
51864
|
+
primaryCostDriver: "Multi-step interaction or spatial reasoning"
|
|
51865
|
+
},
|
|
51866
|
+
calendar: {
|
|
51867
|
+
dimensions: {
|
|
51868
|
+
decisionDemand: 1,
|
|
51869
|
+
informationDensity: 2,
|
|
51870
|
+
interactionComplexity: 1,
|
|
51871
|
+
contextDisruption: 0,
|
|
51872
|
+
learningCurve: 1
|
|
51873
|
+
},
|
|
51874
|
+
primaryCostDriver: "Multi-step interaction or spatial reasoning"
|
|
51875
|
+
},
|
|
51876
|
+
select: {
|
|
51877
|
+
dimensions: {
|
|
51878
|
+
decisionDemand: 2,
|
|
51879
|
+
informationDensity: 1,
|
|
51880
|
+
interactionComplexity: 1,
|
|
51881
|
+
contextDisruption: 0,
|
|
51882
|
+
learningCurve: 1
|
|
51883
|
+
},
|
|
51884
|
+
primaryCostDriver: "Multi-step interaction or spatial reasoning"
|
|
51885
|
+
},
|
|
51886
|
+
"navigation-menu": {
|
|
51887
|
+
dimensions: {
|
|
51888
|
+
decisionDemand: 1,
|
|
51889
|
+
informationDensity: 2,
|
|
51890
|
+
interactionComplexity: 1,
|
|
51891
|
+
contextDisruption: 0,
|
|
51892
|
+
learningCurve: 1
|
|
51893
|
+
},
|
|
51894
|
+
primaryCostDriver: "Multi-step interaction or spatial reasoning"
|
|
51895
|
+
},
|
|
51896
|
+
menubar: {
|
|
51897
|
+
dimensions: {
|
|
51898
|
+
decisionDemand: 1,
|
|
51899
|
+
informationDensity: 2,
|
|
51900
|
+
interactionComplexity: 1,
|
|
51901
|
+
contextDisruption: 0,
|
|
51902
|
+
learningCurve: 1
|
|
51903
|
+
},
|
|
51904
|
+
primaryCostDriver: "Multi-step interaction or spatial reasoning"
|
|
51905
|
+
},
|
|
51906
|
+
"color-picker": {
|
|
51907
|
+
dimensions: {
|
|
51908
|
+
decisionDemand: 1,
|
|
51909
|
+
informationDensity: 1,
|
|
51910
|
+
interactionComplexity: 2,
|
|
51911
|
+
contextDisruption: 0,
|
|
51912
|
+
learningCurve: 1
|
|
51913
|
+
},
|
|
51914
|
+
primaryCostDriver: "Multi-step interaction or spatial reasoning"
|
|
51915
|
+
},
|
|
51916
|
+
"block-canvas": {
|
|
51917
|
+
dimensions: {
|
|
51918
|
+
decisionDemand: 1,
|
|
51919
|
+
informationDensity: 1,
|
|
51920
|
+
interactionComplexity: 1,
|
|
51921
|
+
contextDisruption: 1,
|
|
51922
|
+
learningCurve: 1
|
|
51923
|
+
},
|
|
51924
|
+
primaryCostDriver: "Multi-step interaction or spatial reasoning"
|
|
51925
|
+
},
|
|
51926
|
+
// Score 6 -- Compound interaction modes or learning curve
|
|
51927
|
+
dialog: {
|
|
51928
|
+
dimensions: {
|
|
51929
|
+
decisionDemand: 1,
|
|
51930
|
+
informationDensity: 1,
|
|
51931
|
+
interactionComplexity: 1,
|
|
51932
|
+
contextDisruption: 2,
|
|
51933
|
+
learningCurve: 1
|
|
51934
|
+
},
|
|
51935
|
+
primaryCostDriver: "Compound interaction modes or learning curve"
|
|
51936
|
+
},
|
|
51937
|
+
command: {
|
|
51938
|
+
dimensions: {
|
|
51939
|
+
decisionDemand: 1,
|
|
51940
|
+
informationDensity: 2,
|
|
51941
|
+
interactionComplexity: 1,
|
|
51942
|
+
contextDisruption: 0,
|
|
51943
|
+
learningCurve: 2
|
|
51944
|
+
},
|
|
51945
|
+
primaryCostDriver: "Compound interaction modes or learning curve"
|
|
51946
|
+
},
|
|
51947
|
+
combobox: {
|
|
51948
|
+
dimensions: {
|
|
51949
|
+
decisionDemand: 2,
|
|
51950
|
+
informationDensity: 2,
|
|
51951
|
+
interactionComplexity: 2,
|
|
51952
|
+
contextDisruption: 0,
|
|
51953
|
+
learningCurve: 0
|
|
51954
|
+
},
|
|
51955
|
+
primaryCostDriver: "Compound interaction modes or learning curve"
|
|
51956
|
+
},
|
|
51957
|
+
// Score 7 -- Full context disruption + consequential decision
|
|
51958
|
+
"alert-dialog": {
|
|
51959
|
+
dimensions: {
|
|
51960
|
+
decisionDemand: 2,
|
|
51961
|
+
informationDensity: 1,
|
|
51962
|
+
interactionComplexity: 1,
|
|
51963
|
+
contextDisruption: 2,
|
|
51964
|
+
learningCurve: 1
|
|
51965
|
+
},
|
|
51966
|
+
primaryCostDriver: "Full context disruption + consequential decision"
|
|
51967
|
+
}
|
|
51968
|
+
};
|
|
51969
|
+
var DIMENSION_NAMES = {
|
|
51970
|
+
decisionDemand: "Decision Demand",
|
|
51971
|
+
informationDensity: "Information Density",
|
|
51972
|
+
interactionComplexity: "Interaction Complexity",
|
|
51973
|
+
contextDisruption: "Context Disruption",
|
|
51974
|
+
learningCurve: "Learning Curve"
|
|
51975
|
+
};
|
|
51976
|
+
var HOTSPOT_SUGGESTIONS = {
|
|
51977
|
+
contextDisruption: "Consider non-modal alternative if the decision is not consequential",
|
|
51978
|
+
informationDensity: "Consider progressive disclosure to reduce simultaneous information",
|
|
51979
|
+
interactionComplexity: "Consider a simpler single-mode alternative",
|
|
51980
|
+
decisionDemand: "Can choices be pre-selected or split across steps?",
|
|
51981
|
+
learningCurve: "Ensure discoverability with inline guidance"
|
|
51982
|
+
};
|
|
51983
|
+
function scoreOf(dimensions) {
|
|
51984
|
+
return dimensions.decisionDemand + dimensions.informationDensity + dimensions.interactionComplexity + dimensions.contextDisruption + dimensions.learningCurve;
|
|
51985
|
+
}
|
|
51986
|
+
function highestDimension(dimensions) {
|
|
51987
|
+
let max = -1;
|
|
51988
|
+
let maxKey = "decisionDemand";
|
|
51989
|
+
for (const key of Object.keys(dimensions)) {
|
|
51990
|
+
if (dimensions[key] > max) {
|
|
51991
|
+
max = dimensions[key];
|
|
51992
|
+
maxKey = key;
|
|
51993
|
+
}
|
|
51994
|
+
}
|
|
51995
|
+
return maxKey;
|
|
51996
|
+
}
|
|
51997
|
+
function evaluateComposition(components, tier, enrichment) {
|
|
51998
|
+
const budget = BUDGET_TIERS[tier];
|
|
51999
|
+
const componentCounts = /* @__PURE__ */ new Map();
|
|
52000
|
+
for (const name2 of components) {
|
|
52001
|
+
componentCounts.set(name2, (componentCounts.get(name2) ?? 0) + 1);
|
|
52002
|
+
}
|
|
52003
|
+
let total = 0;
|
|
52004
|
+
const componentResults = [];
|
|
52005
|
+
const unknownComponents = [];
|
|
52006
|
+
for (const [name2, count] of componentCounts) {
|
|
52007
|
+
const profile = COMPONENT_SCORES[name2];
|
|
52008
|
+
if (!profile) {
|
|
52009
|
+
unknownComponents.push(name2);
|
|
52010
|
+
continue;
|
|
52011
|
+
}
|
|
52012
|
+
const score = scoreOf(profile.dimensions);
|
|
52013
|
+
total += score * count;
|
|
52014
|
+
componentResults.push({
|
|
52015
|
+
name: name2,
|
|
52016
|
+
score,
|
|
52017
|
+
count,
|
|
52018
|
+
dimensions: profile.dimensions,
|
|
52019
|
+
primaryCostDriver: profile.primaryCostDriver
|
|
52020
|
+
});
|
|
52021
|
+
}
|
|
52022
|
+
componentResults.sort((a, b) => b.score - a.score);
|
|
52023
|
+
const withinBudget = total <= budget;
|
|
52024
|
+
const budgetResult = {
|
|
52025
|
+
tier,
|
|
52026
|
+
budget,
|
|
52027
|
+
total,
|
|
52028
|
+
status: withinBudget ? "within-budget" : "over-budget"
|
|
52029
|
+
};
|
|
52030
|
+
if (withinBudget) {
|
|
52031
|
+
budgetResult.headroom = budget - total;
|
|
52032
|
+
} else {
|
|
52033
|
+
budgetResult.overage = total - budget;
|
|
52034
|
+
budgetResult.overagePercent = Math.round((total - budget) / budget * 100);
|
|
52035
|
+
}
|
|
52036
|
+
const attentionConflicts = [];
|
|
52037
|
+
const attentionNotes = [];
|
|
52038
|
+
const fullAttentionCaptures = [];
|
|
52039
|
+
const primaryElements = [];
|
|
52040
|
+
for (const [name2] of componentCounts) {
|
|
52041
|
+
const metadata = enrichment.componentIntelligence.get(name2);
|
|
52042
|
+
if (!metadata?.intelligence?.attentionEconomics) continue;
|
|
52043
|
+
const attn = metadata.intelligence.attentionEconomics.toLowerCase();
|
|
52044
|
+
if (attn.includes("full attention capture") || attn.includes("blocks all other")) {
|
|
52045
|
+
fullAttentionCaptures.push(name2);
|
|
52046
|
+
}
|
|
52047
|
+
if (attn.includes("primary") && attn.includes("maximum 1")) {
|
|
52048
|
+
const count = componentCounts.get(name2) ?? 0;
|
|
52049
|
+
if (count > 1) {
|
|
52050
|
+
primaryElements.push(name2);
|
|
52051
|
+
}
|
|
52052
|
+
}
|
|
52053
|
+
}
|
|
52054
|
+
if (fullAttentionCaptures.length > 1) {
|
|
52055
|
+
attentionConflicts.push(`${fullAttentionCaptures.join(" and ")} both capture full attention`);
|
|
52056
|
+
}
|
|
52057
|
+
const buttonCount = componentCounts.get("button") ?? 0;
|
|
52058
|
+
if (buttonCount > 1) {
|
|
52059
|
+
const buttonMeta = enrichment.componentIntelligence.get("button");
|
|
52060
|
+
if (buttonMeta?.intelligence?.attentionEconomics?.toLowerCase().includes("maximum 1 per section")) {
|
|
52061
|
+
attentionNotes.push(`${buttonCount} buttons present -- ensure maximum 1 primary per section`);
|
|
52062
|
+
}
|
|
52063
|
+
}
|
|
52064
|
+
if (primaryElements.length > 0) {
|
|
52065
|
+
for (const name2 of primaryElements) {
|
|
52066
|
+
attentionNotes.push(`Multiple ${name2} instances -- check attention hierarchy`);
|
|
52067
|
+
}
|
|
52068
|
+
}
|
|
52069
|
+
const trustConsiderations = [];
|
|
52070
|
+
for (const [name2] of componentCounts) {
|
|
52071
|
+
const metadata = enrichment.componentIntelligence.get(name2);
|
|
52072
|
+
if (!metadata?.intelligence?.trustBuilding) continue;
|
|
52073
|
+
const trust = metadata.intelligence.trustBuilding;
|
|
52074
|
+
if (trust.toLowerCase().includes("confirmation") || trust.toLowerCase().includes("destructive") || trust.toLowerCase().includes("consequence") || trust.toLowerCase().includes("cancel")) {
|
|
52075
|
+
trustConsiderations.push(`${name2}: ${trust}`);
|
|
52076
|
+
}
|
|
52077
|
+
}
|
|
52078
|
+
const patternMatches = [];
|
|
52079
|
+
const compositionSet = new Set(componentCounts.keys());
|
|
52080
|
+
for (const [patternKey, pattern] of Object.entries(enrichment.patterns)) {
|
|
52081
|
+
const matched = pattern.components.filter((c) => compositionSet.has(c));
|
|
52082
|
+
if (matched.length >= 2 || matched.length === pattern.components.length) {
|
|
52083
|
+
patternMatches.push({
|
|
52084
|
+
name: pattern.name,
|
|
52085
|
+
matched,
|
|
52086
|
+
suggestion: `Call rafters_pattern('${patternKey}') for full guidance`
|
|
52087
|
+
});
|
|
52088
|
+
}
|
|
52089
|
+
}
|
|
52090
|
+
const designerNotes = [];
|
|
52091
|
+
const compositionNames = [...compositionSet];
|
|
52092
|
+
for (const { token } of enrichment.tokenOverrides) {
|
|
52093
|
+
if (!token.userOverride) continue;
|
|
52094
|
+
const relevantTo = [];
|
|
52095
|
+
if (token.applicableComponents) {
|
|
52096
|
+
for (const comp of token.applicableComponents) {
|
|
52097
|
+
if (compositionSet.has(comp)) {
|
|
52098
|
+
relevantTo.push(comp);
|
|
52099
|
+
}
|
|
52100
|
+
}
|
|
52101
|
+
}
|
|
52102
|
+
if (relevantTo.length === 0) {
|
|
52103
|
+
if (token.namespace === "spacing") {
|
|
52104
|
+
const formComponents = compositionNames.filter(
|
|
52105
|
+
(n) => [
|
|
52106
|
+
"input",
|
|
52107
|
+
"textarea",
|
|
52108
|
+
"field",
|
|
52109
|
+
"label",
|
|
52110
|
+
"button",
|
|
52111
|
+
"select",
|
|
52112
|
+
"checkbox",
|
|
52113
|
+
"radio-group",
|
|
52114
|
+
"switch",
|
|
52115
|
+
"slider",
|
|
52116
|
+
"combobox"
|
|
52117
|
+
].includes(n)
|
|
52118
|
+
);
|
|
52119
|
+
if (formComponents.length > 0) {
|
|
52120
|
+
relevantTo.push(...formComponents);
|
|
52121
|
+
}
|
|
52122
|
+
} else if (token.namespace === "color") {
|
|
52123
|
+
const variantComponents = compositionNames.filter(
|
|
52124
|
+
(n) => ["button", "badge", "alert", "alert-dialog", "progress"].includes(n)
|
|
52125
|
+
);
|
|
52126
|
+
if (variantComponents.length > 0 && (token.name.includes("destructive") || token.name.includes("primary"))) {
|
|
52127
|
+
relevantTo.push(...variantComponents);
|
|
52128
|
+
}
|
|
52129
|
+
}
|
|
52130
|
+
}
|
|
52131
|
+
if (relevantTo.length > 0) {
|
|
52132
|
+
designerNotes.push({
|
|
52133
|
+
token: token.name,
|
|
52134
|
+
reason: token.userOverride.reason,
|
|
52135
|
+
relevantTo
|
|
52136
|
+
});
|
|
52137
|
+
}
|
|
52138
|
+
}
|
|
52139
|
+
const violations = [];
|
|
52140
|
+
for (const [name2] of componentCounts) {
|
|
52141
|
+
const metadata = enrichment.componentIntelligence.get(name2);
|
|
52142
|
+
if (!metadata?.intelligence?.usagePatterns?.nevers) continue;
|
|
52143
|
+
for (const never2 of metadata.intelligence.usagePatterns.nevers) {
|
|
52144
|
+
const neverLower = never2.toLowerCase();
|
|
52145
|
+
if (neverLower.includes("nest") && neverLower.includes("card") && name2 === "card") {
|
|
52146
|
+
const cardCount = componentCounts.get("card") ?? 0;
|
|
52147
|
+
if (cardCount > 1) {
|
|
52148
|
+
violations.push(
|
|
52149
|
+
`${name2}: "${never2}" -- ${cardCount} cards in composition, verify none are nested`
|
|
52150
|
+
);
|
|
52151
|
+
}
|
|
52152
|
+
}
|
|
52153
|
+
if (neverLower.includes("multiple primary") && name2 === "button") {
|
|
52154
|
+
if (buttonCount > 1) {
|
|
52155
|
+
violations.push(`${name2}: "${never2}"`);
|
|
52156
|
+
}
|
|
52157
|
+
}
|
|
52158
|
+
if (neverLower.includes("stack") && neverLower.includes("dialog")) {
|
|
52159
|
+
if (compositionSet.has("dialog") && (compositionSet.has("alert-dialog") || (componentCounts.get("dialog") ?? 0) > 1)) {
|
|
52160
|
+
violations.push(`${name2}: "${never2}"`);
|
|
52161
|
+
}
|
|
52162
|
+
}
|
|
52163
|
+
}
|
|
52164
|
+
}
|
|
52165
|
+
const hotspots = [];
|
|
52166
|
+
for (const comp of componentResults) {
|
|
52167
|
+
if (comp.score >= 4) {
|
|
52168
|
+
const highest = highestDimension(comp.dimensions);
|
|
52169
|
+
hotspots.push({
|
|
52170
|
+
name: comp.name,
|
|
52171
|
+
score: comp.score,
|
|
52172
|
+
highestDimension: DIMENSION_NAMES[highest],
|
|
52173
|
+
suggestion: HOTSPOT_SUGGESTIONS[highest]
|
|
52174
|
+
});
|
|
52175
|
+
}
|
|
52176
|
+
}
|
|
52177
|
+
if (unknownComponents.length > 0) {
|
|
52178
|
+
attentionNotes.push(
|
|
52179
|
+
`Unknown components not scored: ${unknownComponents.join(", ")}. Totals may be understated.`
|
|
52180
|
+
);
|
|
52181
|
+
}
|
|
52182
|
+
const warnings = [];
|
|
52183
|
+
const knownNames = [...componentCounts.keys()].filter((n) => COMPONENT_SCORES[n]);
|
|
52184
|
+
const uninstrumented = knownNames.filter((n) => !enrichment.componentIntelligence.has(n));
|
|
52185
|
+
if (uninstrumented.length > 0) {
|
|
52186
|
+
warnings.push(
|
|
52187
|
+
`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.`
|
|
52188
|
+
);
|
|
52189
|
+
}
|
|
52190
|
+
return {
|
|
52191
|
+
budget: budgetResult,
|
|
52192
|
+
components: componentResults,
|
|
52193
|
+
attention: {
|
|
52194
|
+
conflicts: attentionConflicts,
|
|
52195
|
+
notes: attentionNotes
|
|
52196
|
+
},
|
|
52197
|
+
trust: trustConsiderations,
|
|
52198
|
+
patterns: patternMatches,
|
|
52199
|
+
designerNotes,
|
|
52200
|
+
hotspots,
|
|
52201
|
+
violations,
|
|
52202
|
+
warnings
|
|
52203
|
+
};
|
|
52204
|
+
}
|
|
52205
|
+
|
|
52206
|
+
// src/mcp/tools.ts
|
|
52207
|
+
function hasAnyDeps(deps) {
|
|
52208
|
+
return deps.runtime.length > 0 || deps.dev.length > 0 || deps.internal.length > 0;
|
|
52209
|
+
}
|
|
52210
|
+
var SYSTEM_PREAMBLE = `RAFTERS IS NOT SHADCN.
|
|
52211
|
+
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.
|
|
52212
|
+
|
|
52213
|
+
CLASSY IS THE LAW.
|
|
52214
|
+
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.
|
|
52215
|
+
|
|
52216
|
+
LAYOUT IS SOLVED. Stop writing CSS.
|
|
52217
|
+
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.
|
|
52218
|
+
|
|
52219
|
+
USE PRESETS. Do not compose layout from props.
|
|
52220
|
+
Grid presets handle common layouts. Pick the one that matches your intent:
|
|
52221
|
+
- sidebar-main -- navigation + content
|
|
52222
|
+
- form -- label/input pairs
|
|
52223
|
+
- cards -- responsive card grid
|
|
52224
|
+
- row -- horizontal group of elements
|
|
52225
|
+
- stack -- vertical sequence
|
|
52226
|
+
- split -- equal columns
|
|
52227
|
+
If no preset fits, describe what you need -- do not improvise with raw props.
|
|
52228
|
+
|
|
52229
|
+
CONTAINER OWNS SPACING.
|
|
52230
|
+
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.
|
|
52231
|
+
|
|
52232
|
+
COMPONENTS ARE COMPLETE.
|
|
52233
|
+
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.
|
|
52234
|
+
|
|
52235
|
+
UTILITIES EXIST FOR EDGE CASES.
|
|
52236
|
+
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.
|
|
52237
|
+
|
|
52238
|
+
When in doubt: less code, not more. Rafters has already made the design decision.`;
|
|
50943
52239
|
var DESIGN_PATTERNS = {
|
|
50944
52240
|
"destructive-action": {
|
|
50945
52241
|
name: "Destructive Action",
|
|
@@ -51287,6 +52583,26 @@ var TOOL_DEFINITIONS = [
|
|
|
51287
52583
|
},
|
|
51288
52584
|
required: ["name"]
|
|
51289
52585
|
}
|
|
52586
|
+
},
|
|
52587
|
+
{
|
|
52588
|
+
name: "rafters_cognitive_budget",
|
|
52589
|
+
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.",
|
|
52590
|
+
inputSchema: {
|
|
52591
|
+
type: "object",
|
|
52592
|
+
properties: {
|
|
52593
|
+
components: {
|
|
52594
|
+
type: "array",
|
|
52595
|
+
items: { type: "string" },
|
|
52596
|
+
description: 'Components visible simultaneously, duplicates allowed (e.g., ["input", "input", "button", "card"])'
|
|
52597
|
+
},
|
|
52598
|
+
tier: {
|
|
52599
|
+
type: "string",
|
|
52600
|
+
enum: ["focused", "page", "app"],
|
|
52601
|
+
description: "Budget tier: focused (15, dialogs/modals), page (30, standard views), app (45, multi-panel). Default: page."
|
|
52602
|
+
}
|
|
52603
|
+
},
|
|
52604
|
+
required: ["components"]
|
|
52605
|
+
}
|
|
51290
52606
|
}
|
|
51291
52607
|
];
|
|
51292
52608
|
var RaftersToolHandler = class {
|
|
@@ -51316,6 +52632,11 @@ var RaftersToolHandler = class {
|
|
|
51316
52632
|
return this.getComponent(args.name);
|
|
51317
52633
|
case "rafters_token":
|
|
51318
52634
|
return this.getToken(args.name);
|
|
52635
|
+
case "rafters_cognitive_budget":
|
|
52636
|
+
return this.getCognitiveBudget(
|
|
52637
|
+
args.components,
|
|
52638
|
+
args.tier ?? "page"
|
|
52639
|
+
);
|
|
51319
52640
|
default:
|
|
51320
52641
|
return {
|
|
51321
52642
|
content: [{ type: "text", text: `Unknown tool: ${name2}` }],
|
|
@@ -51337,12 +52658,12 @@ var RaftersToolHandler = class {
|
|
|
51337
52658
|
this.getComponentVocabulary()
|
|
51338
52659
|
]);
|
|
51339
52660
|
const vocabulary = {
|
|
52661
|
+
system: SYSTEM_PREAMBLE,
|
|
52662
|
+
components,
|
|
51340
52663
|
colors,
|
|
51341
52664
|
spacing,
|
|
51342
52665
|
typography,
|
|
51343
|
-
|
|
51344
|
-
patterns: Object.keys(DESIGN_PATTERNS),
|
|
51345
|
-
usage: "Use rafters_pattern for deep guidance on specific patterns, rafters_component for component details"
|
|
52666
|
+
patterns: Object.keys(DESIGN_PATTERNS)
|
|
51346
52667
|
};
|
|
51347
52668
|
return {
|
|
51348
52669
|
content: [
|
|
@@ -51429,33 +52750,26 @@ var RaftersToolHandler = class {
|
|
|
51429
52750
|
* Extract compact component vocabulary
|
|
51430
52751
|
*/
|
|
51431
52752
|
async getComponentVocabulary() {
|
|
52753
|
+
let installed = [];
|
|
51432
52754
|
try {
|
|
51433
|
-
const
|
|
51434
|
-
|
|
51435
|
-
|
|
51436
|
-
|
|
51437
|
-
|
|
51438
|
-
const name2 = basename(file2, ".tsx");
|
|
51439
|
-
const metadata = await this.loadComponentMetadata(name2);
|
|
51440
|
-
if (metadata) {
|
|
51441
|
-
const item = {
|
|
51442
|
-
name: metadata.name,
|
|
51443
|
-
category: metadata.category
|
|
51444
|
-
};
|
|
51445
|
-
if (metadata.intelligence?.cognitiveLoad !== void 0) {
|
|
51446
|
-
item.load = metadata.intelligence.cognitiveLoad;
|
|
51447
|
-
}
|
|
51448
|
-
components.push(item);
|
|
51449
|
-
}
|
|
52755
|
+
const paths = getRaftersPaths(this.projectRoot);
|
|
52756
|
+
if (existsSync3(paths.config)) {
|
|
52757
|
+
const content = await readFile6(paths.config, "utf-8");
|
|
52758
|
+
const config3 = JSON.parse(content);
|
|
52759
|
+
installed = config3.installed?.components ?? [];
|
|
51450
52760
|
}
|
|
51451
|
-
components.sort((a, b) => {
|
|
51452
|
-
if (a.category !== b.category) return a.category.localeCompare(b.category);
|
|
51453
|
-
return a.name.localeCompare(b.name);
|
|
51454
|
-
});
|
|
51455
|
-
return components;
|
|
51456
52761
|
} catch {
|
|
51457
|
-
return [];
|
|
51458
52762
|
}
|
|
52763
|
+
let available = [];
|
|
52764
|
+
try {
|
|
52765
|
+
const client = new RegistryClient();
|
|
52766
|
+
const index = await client.fetchIndex();
|
|
52767
|
+
const allComponents = index.components;
|
|
52768
|
+
const installedSet = new Set(installed);
|
|
52769
|
+
available = allComponents.filter((name2) => !installedSet.has(name2));
|
|
52770
|
+
} catch {
|
|
52771
|
+
}
|
|
52772
|
+
return { installed, available };
|
|
51459
52773
|
}
|
|
51460
52774
|
// ==================== Tool 2: Pattern ====================
|
|
51461
52775
|
/**
|
|
@@ -51496,7 +52810,7 @@ var RaftersToolHandler = class {
|
|
|
51496
52810
|
* Get path to UI components directory
|
|
51497
52811
|
*/
|
|
51498
52812
|
getComponentsPath() {
|
|
51499
|
-
const monorepoPath =
|
|
52813
|
+
const monorepoPath = join10(this.projectRoot, "packages/ui/src/components/ui");
|
|
51500
52814
|
return monorepoPath;
|
|
51501
52815
|
}
|
|
51502
52816
|
/**
|
|
@@ -51504,11 +52818,16 @@ var RaftersToolHandler = class {
|
|
|
51504
52818
|
*/
|
|
51505
52819
|
async loadComponentMetadata(name2) {
|
|
51506
52820
|
const componentsPath = this.getComponentsPath();
|
|
51507
|
-
const filePath =
|
|
52821
|
+
const filePath = join10(componentsPath, `${name2}.tsx`);
|
|
51508
52822
|
try {
|
|
51509
|
-
const source = await
|
|
52823
|
+
const source = await readFile6(filePath, "utf-8");
|
|
51510
52824
|
const intelligence = parseJSDocIntelligence(source);
|
|
51511
52825
|
const description = parseDescription(source);
|
|
52826
|
+
let jsDocDeps = { runtime: [], dev: [], internal: [] };
|
|
52827
|
+
try {
|
|
52828
|
+
jsDocDeps = extractJSDocDependencies(source);
|
|
52829
|
+
} catch {
|
|
52830
|
+
}
|
|
51512
52831
|
const metadata = {
|
|
51513
52832
|
name: name2,
|
|
51514
52833
|
displayName: toDisplayName(name2),
|
|
@@ -51519,6 +52838,9 @@ var RaftersToolHandler = class {
|
|
|
51519
52838
|
primitives: extractPrimitiveDependencies(source),
|
|
51520
52839
|
filePath: `packages/ui/src/components/ui/${name2}.tsx`
|
|
51521
52840
|
};
|
|
52841
|
+
if (hasAnyDeps(jsDocDeps)) {
|
|
52842
|
+
metadata.jsDocDependencies = jsDocDeps;
|
|
52843
|
+
}
|
|
51522
52844
|
if (description) {
|
|
51523
52845
|
metadata.description = description;
|
|
51524
52846
|
}
|
|
@@ -51663,6 +52985,9 @@ var RaftersToolHandler = class {
|
|
|
51663
52985
|
if (metadata.dependencies.length > 0) {
|
|
51664
52986
|
formatted.dependencies = metadata.dependencies;
|
|
51665
52987
|
}
|
|
52988
|
+
if (metadata.jsDocDependencies && hasAnyDeps(metadata.jsDocDependencies)) {
|
|
52989
|
+
formatted.jsDocDependencies = metadata.jsDocDependencies;
|
|
52990
|
+
}
|
|
51666
52991
|
return {
|
|
51667
52992
|
content: [
|
|
51668
52993
|
{
|
|
@@ -51778,6 +53103,120 @@ var RaftersToolHandler = class {
|
|
|
51778
53103
|
return this.handleError("getToken", error48);
|
|
51779
53104
|
}
|
|
51780
53105
|
}
|
|
53106
|
+
// ==================== Tool 5: Cognitive Budget ====================
|
|
53107
|
+
/**
|
|
53108
|
+
* Evaluate composition-level cognitive load
|
|
53109
|
+
* Synthesizes scoring data with component intelligence, token overrides,
|
|
53110
|
+
* and design patterns to produce a holistic composition review
|
|
53111
|
+
*/
|
|
53112
|
+
async getCognitiveBudget(components, tier) {
|
|
53113
|
+
try {
|
|
53114
|
+
if (!components || components.length === 0) {
|
|
53115
|
+
return {
|
|
53116
|
+
content: [
|
|
53117
|
+
{
|
|
53118
|
+
type: "text",
|
|
53119
|
+
text: JSON.stringify(
|
|
53120
|
+
{
|
|
53121
|
+
error: "No components provided",
|
|
53122
|
+
suggestion: 'Pass an array of component names visible simultaneously, e.g. ["input", "button", "card"]'
|
|
53123
|
+
},
|
|
53124
|
+
null,
|
|
53125
|
+
2
|
|
53126
|
+
)
|
|
53127
|
+
}
|
|
53128
|
+
],
|
|
53129
|
+
isError: true
|
|
53130
|
+
};
|
|
53131
|
+
}
|
|
53132
|
+
if (!BUDGET_TIERS[tier]) {
|
|
53133
|
+
return {
|
|
53134
|
+
content: [
|
|
53135
|
+
{
|
|
53136
|
+
type: "text",
|
|
53137
|
+
text: JSON.stringify(
|
|
53138
|
+
{
|
|
53139
|
+
error: `Invalid tier "${tier}"`,
|
|
53140
|
+
available: Object.keys(BUDGET_TIERS),
|
|
53141
|
+
suggestion: 'Use "focused", "page", or "app"'
|
|
53142
|
+
},
|
|
53143
|
+
null,
|
|
53144
|
+
2
|
|
53145
|
+
)
|
|
53146
|
+
}
|
|
53147
|
+
],
|
|
53148
|
+
isError: true
|
|
53149
|
+
};
|
|
53150
|
+
}
|
|
53151
|
+
const uniqueNames = [...new Set(components)];
|
|
53152
|
+
const unknownNames = uniqueNames.filter((n) => !COMPONENT_SCORES[n]);
|
|
53153
|
+
if (unknownNames.length === uniqueNames.length) {
|
|
53154
|
+
return {
|
|
53155
|
+
content: [
|
|
53156
|
+
{
|
|
53157
|
+
type: "text",
|
|
53158
|
+
text: JSON.stringify(
|
|
53159
|
+
{
|
|
53160
|
+
error: `No recognized components in composition: ${unknownNames.join(", ")}`,
|
|
53161
|
+
suggestion: "Use rafters_vocabulary to see available component names"
|
|
53162
|
+
},
|
|
53163
|
+
null,
|
|
53164
|
+
2
|
|
53165
|
+
)
|
|
53166
|
+
}
|
|
53167
|
+
],
|
|
53168
|
+
isError: true
|
|
53169
|
+
};
|
|
53170
|
+
}
|
|
53171
|
+
const intelligenceMap = /* @__PURE__ */ new Map();
|
|
53172
|
+
const metadataResults = await Promise.all(
|
|
53173
|
+
uniqueNames.map(async (name2) => {
|
|
53174
|
+
const metadata = await this.loadComponentMetadata(name2);
|
|
53175
|
+
return { name: name2, metadata };
|
|
53176
|
+
})
|
|
53177
|
+
);
|
|
53178
|
+
for (const { name: name2, metadata } of metadataResults) {
|
|
53179
|
+
if (metadata) {
|
|
53180
|
+
intelligenceMap.set(name2, metadata);
|
|
53181
|
+
}
|
|
53182
|
+
}
|
|
53183
|
+
const tokenOverrides = [];
|
|
53184
|
+
const namespaces = ["color", "spacing", "typography"];
|
|
53185
|
+
for (const ns of namespaces) {
|
|
53186
|
+
try {
|
|
53187
|
+
const tokens = await this.loadNamespace(ns);
|
|
53188
|
+
for (const token of tokens) {
|
|
53189
|
+
if (token.userOverride) {
|
|
53190
|
+
tokenOverrides.push({ token, namespace: ns });
|
|
53191
|
+
}
|
|
53192
|
+
}
|
|
53193
|
+
} catch {
|
|
53194
|
+
}
|
|
53195
|
+
}
|
|
53196
|
+
const patternRefs = {};
|
|
53197
|
+
for (const [key, pattern] of Object.entries(DESIGN_PATTERNS)) {
|
|
53198
|
+
patternRefs[key] = {
|
|
53199
|
+
name: pattern.name,
|
|
53200
|
+
components: pattern.components
|
|
53201
|
+
};
|
|
53202
|
+
}
|
|
53203
|
+
const review = evaluateComposition(components, tier, {
|
|
53204
|
+
componentIntelligence: intelligenceMap,
|
|
53205
|
+
tokenOverrides,
|
|
53206
|
+
patterns: patternRefs
|
|
53207
|
+
});
|
|
53208
|
+
return {
|
|
53209
|
+
content: [
|
|
53210
|
+
{
|
|
53211
|
+
type: "text",
|
|
53212
|
+
text: JSON.stringify(review, null, 2)
|
|
53213
|
+
}
|
|
53214
|
+
]
|
|
53215
|
+
};
|
|
53216
|
+
} catch (error48) {
|
|
53217
|
+
return this.handleError("getCognitiveBudget", error48);
|
|
53218
|
+
}
|
|
53219
|
+
}
|
|
51781
53220
|
/**
|
|
51782
53221
|
* Handle errors consistently
|
|
51783
53222
|
*/
|
|
@@ -51852,22 +53291,22 @@ async function mcp() {
|
|
|
51852
53291
|
}
|
|
51853
53292
|
|
|
51854
53293
|
// src/commands/studio.ts
|
|
51855
|
-
import { existsSync as
|
|
51856
|
-
import { dirname as dirname3, join as
|
|
53294
|
+
import { existsSync as existsSync4 } from "fs";
|
|
53295
|
+
import { dirname as dirname3, join as join11 } from "path";
|
|
51857
53296
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
51858
53297
|
import { execa as execa2 } from "execa";
|
|
51859
53298
|
var __dirname2 = dirname3(fileURLToPath3(import.meta.url));
|
|
51860
53299
|
async function studio() {
|
|
51861
53300
|
const cwd = process.cwd();
|
|
51862
53301
|
const paths = getRaftersPaths(cwd);
|
|
51863
|
-
if (!
|
|
53302
|
+
if (!existsSync4(paths.root)) {
|
|
51864
53303
|
console.error('No .rafters/ directory found. Run "rafters init" first.');
|
|
51865
53304
|
process.exit(1);
|
|
51866
53305
|
}
|
|
51867
|
-
const devStudioPath =
|
|
51868
|
-
const prodStudioPath =
|
|
51869
|
-
const studioPath =
|
|
51870
|
-
if (!
|
|
53306
|
+
const devStudioPath = join11(__dirname2, "..", "..", "..", "studio");
|
|
53307
|
+
const prodStudioPath = join11(__dirname2, "..", "node_modules", "@rafters", "studio");
|
|
53308
|
+
const studioPath = existsSync4(devStudioPath) ? devStudioPath : prodStudioPath;
|
|
53309
|
+
if (!existsSync4(studioPath)) {
|
|
51871
53310
|
console.error("Studio package not found. Please reinstall @rafters/cli.");
|
|
51872
53311
|
process.exit(1);
|
|
51873
53312
|
}
|
|
@@ -51896,8 +53335,8 @@ async function studio() {
|
|
|
51896
53335
|
// src/index.ts
|
|
51897
53336
|
var program = new Command();
|
|
51898
53337
|
program.name("rafters").description("Design system CLI - scaffold tokens and serve MCP").version("0.0.1");
|
|
51899
|
-
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(init);
|
|
51900
|
-
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(add);
|
|
53338
|
+
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));
|
|
53339
|
+
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));
|
|
51901
53340
|
program.command("mcp").description("Start MCP server for AI agent access (stdio)").action(mcp);
|
|
51902
53341
|
program.command("studio").description("Open Studio UI for visual token editing").action(studio);
|
|
51903
53342
|
program.parse();
|