@ansh-ui/cli 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +29 -4
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync, existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
2
3
|
import { parseArgs } from 'util';
|
|
3
|
-
import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
|
|
4
4
|
import { join, dirname, resolve } from 'path';
|
|
5
5
|
import { parseColor, generatePalette, rgbToOklch, toOklchString, toHex, createGradient, createScale, checkContrast, harmony, effects, behaviours } from '@ansh-ui/core';
|
|
6
6
|
|
|
@@ -65,6 +65,19 @@ function detectAlias(root) {
|
|
|
65
65
|
}
|
|
66
66
|
return null;
|
|
67
67
|
}
|
|
68
|
+
var KNOWN_INCONSISTENCIES = [
|
|
69
|
+
{
|
|
70
|
+
title: "License key prefix is still `aur_`",
|
|
71
|
+
detail: "A leftover from the Aurelis \u2192 Ansh rename (packages/license/src/public-key.ts). Changing it without a dual-prefix verification path would invalidate already-issued keys \u2014 needs a maintainer decision, not a drive-by fix. See STATUS.md \xA77."
|
|
72
|
+
}
|
|
73
|
+
];
|
|
74
|
+
function isAnshRepoRoot(root) {
|
|
75
|
+
const pkg = readJson(join(root, "package.json"));
|
|
76
|
+
return pkg?.name === "ansh" && existsSync(join(root, "packages/license/src/index.ts"));
|
|
77
|
+
}
|
|
78
|
+
function detectKnownInconsistencies(root) {
|
|
79
|
+
return isAnshRepoRoot(root) ? KNOWN_INCONSISTENCIES : [];
|
|
80
|
+
}
|
|
68
81
|
function installCommand(info, packages) {
|
|
69
82
|
const list = packages.join(" ");
|
|
70
83
|
switch (info.packageManager) {
|
|
@@ -98,8 +111,9 @@ var COMPONENT_NAMES = {
|
|
|
98
111
|
marquee: "Marquee",
|
|
99
112
|
"scroll-reveal": "ScrollReveal",
|
|
100
113
|
parallax: "Parallax",
|
|
101
|
-
"
|
|
114
|
+
"text-scramble": "ScrambleText"
|
|
102
115
|
};
|
|
116
|
+
var NO_COMPONENT = /* @__PURE__ */ new Set(["split-text"]);
|
|
103
117
|
function componentNameFor(name) {
|
|
104
118
|
return COMPONENT_NAMES[name] ?? name.replace(/(^|-)([a-z])/g, (_, __, letter) => letter.toUpperCase());
|
|
105
119
|
}
|
|
@@ -117,6 +131,7 @@ function listCatalogue(filter) {
|
|
|
117
131
|
}
|
|
118
132
|
if (filter !== "effect") {
|
|
119
133
|
for (const [name, definition] of Object.entries(behaviours)) {
|
|
134
|
+
if (NO_COMPONENT.has(name)) continue;
|
|
120
135
|
entries.push({
|
|
121
136
|
name,
|
|
122
137
|
kind: "behaviour",
|
|
@@ -389,7 +404,7 @@ var cyan = (text) => paint("36", text);
|
|
|
389
404
|
var green = (text) => paint("32", text);
|
|
390
405
|
var yellow = (text) => paint("33", text);
|
|
391
406
|
var red = (text) => paint("31", text);
|
|
392
|
-
var VERSION = "
|
|
407
|
+
var VERSION = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version;
|
|
393
408
|
function help() {
|
|
394
409
|
console.log(`
|
|
395
410
|
${bold("ansh")} ${dim(`v${VERSION}`)} \u2014 Motion, refined.
|
|
@@ -477,7 +492,7 @@ ${bold(entry.component)} ${dim(`(${entry.kind} "${entry.name}")`)}
|
|
|
477
492
|
}
|
|
478
493
|
console.log(
|
|
479
494
|
`
|
|
480
|
-
${dim(` Docs: https://ansh.
|
|
495
|
+
${dim(` Docs: https://ansh.techiesofepi.com/showcase`)}
|
|
481
496
|
${dim(` Add: ansh add ${entry.name}`)}
|
|
482
497
|
`
|
|
483
498
|
);
|
|
@@ -637,6 +652,16 @@ ${yellow("next")} ${installCommand(project, packages)}
|
|
|
637
652
|
} else {
|
|
638
653
|
console.log("");
|
|
639
654
|
}
|
|
655
|
+
const inconsistencies = detectKnownInconsistencies(project.root);
|
|
656
|
+
if (inconsistencies.length > 0) {
|
|
657
|
+
console.log(`${bold("KNOWN INCONSISTENCIES")}
|
|
658
|
+
`);
|
|
659
|
+
for (const { title, detail } of inconsistencies) {
|
|
660
|
+
console.log(` ${yellow("\u2022")} ${title}`);
|
|
661
|
+
console.log(` ${dim(detail)}
|
|
662
|
+
`);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
640
665
|
}
|
|
641
666
|
function swatch(hex) {
|
|
642
667
|
if (!useColor) return "\u25A0";
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/project.ts","../src/commands/list.ts","../src/commands/add.ts","../src/commands/palette.ts","../src/commands/theme.ts","../src/cli.ts"],"names":["join","existsSync","parseColor","rgbToOklch","toOklchString","toHex","mkdirSync","dirname","writeFileSync","effects","behaviours"],"mappings":";;;;;;AA4BA,SAAS,SAAS,GAAA,EAAqB;AACrC,EAAA,IAAI,OAAA,GAAU,QAAQ,GAAG,CAAA;AACzB,EAAA,KAAA,IAAS,KAAA,GAAQ,CAAA,EAAG,KAAA,GAAQ,EAAA,EAAI,KAAA,EAAA,EAAS;AACvC,IAAA,IAAI,WAAW,IAAA,CAAK,OAAA,EAAS,cAAc,CAAC,GAAG,OAAO,OAAA;AACtD,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,OAAA,EAAS,IAAI,CAAA;AACpC,IAAA,IAAI,WAAW,OAAA,EAAS;AACxB,IAAA,OAAA,GAAU,MAAA;AAAA,EACZ;AACA,EAAA,OAAO,QAAQ,GAAG,CAAA;AACpB;AAEA,SAAS,SAAS,IAAA,EAA8C;AAC9D,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,YAAA,CAAa,IAAA,EAAM,MAAM,CAAC,CAAA;AAAA,EAC9C,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEO,SAAS,aAAA,CAAc,GAAA,GAAM,OAAA,CAAQ,GAAA,EAAI,EAAgB;AAC9D,EAAA,MAAM,IAAA,GAAO,SAAS,GAAG,CAAA;AACzB,EAAA,MAAM,MAAM,QAAA,CAAS,IAAA,CAAK,MAAM,cAAc,CAAC,KAAK,EAAC;AAErD,EAAA,MAAM,IAAA,GAA+B;AAAA,IACnC,GAAK,GAAA,CAAI,YAAA,IAA2C,EAAC;AAAA,IACrD,GAAK,GAAA,CAAI,eAAA,IAA8C;AAAC,GAC1D;AAIA,EAAA,MAAM,SAAA,GAAuB,IAAA,CAAK,IAAA,GAC9B,MAAA,GACA,IAAA,CAAK,IAAA,GACH,MAAA,GACA,IAAA,CAAK,GAAA,GACH,KAAA,GACA,IAAA,CAAK,KAAA,GACH,OAAA,GACA,SAAA;AAEV,EAAA,MAAM,UAAA,GAAa,QAAQ,IAAA,CAAK,UAAU,KAAK,UAAA,CAAW,IAAA,CAAK,IAAA,EAAM,eAAe,CAAC,CAAA;AAErF,EAAA,MAAM,cAAA,GAAgD,UAAA,CAAW,IAAA,CAAK,IAAA,EAAM,gBAAgB,CAAC,CAAA,GACzF,MAAA,GACA,UAAA,CAAW,IAAA,CAAK,IAAA,EAAM,WAAW,CAAC,CAAA,IAAK,UAAA,CAAW,IAAA,CAAK,IAAA,EAAM,UAAU,CAAC,CAAA,GACtE,KAAA,GACA,UAAA,CAAW,IAAA,CAAK,IAAA,EAAM,WAAW,CAAC,CAAA,GAChC,MAAA,GACA,KAAA;AAER,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,SAAA;AAAA,IACA,UAAA;AAAA,IACA,aAAA,EAAe,mBAAA,CAAoB,IAAA,EAAM,SAAS,CAAA;AAAA,IAClD,KAAA,EAAO,YAAY,IAAI,CAAA;AAAA,IACvB,cAAA;AAAA,IACA,SAAA,EAAW,OAAA;AAAA,MACT,IAAA,CAAK,gBAAgB,CAAA,IACrB,IAAA,CAAK,cAAc,KACnB,IAAA,CAAK,eAAe,CAAA,IACpB,IAAA,CAAK,eAAe;AAAA;AACtB,GACF;AACF;AAQA,SAAS,mBAAA,CAAoB,MAAc,SAAA,EAA8B;AACvE,EAAA,MAAM,UAAA,GACJ,SAAA,KAAc,MAAA,GACV,CAAC,cAAc,gBAAA,EAAkB,gBAAgB,CAAA,GACjD,CAAC,gBAAA,EAAkB,YAAA,EAAc,gBAAA,EAAkB,oBAAA,EAAsB,UAAU,QAAQ,CAAA;AAEjG,EAAA,KAAA,MAAW,aAAa,UAAA,EAAY;AAClC,IAAA,IAAI,WAAW,IAAA,CAAK,IAAA,EAAM,SAAS,CAAC,GAAG,OAAO,SAAA;AAAA,EAChD;AAGA,EAAA,IAAI,WAAW,IAAA,CAAK,IAAA,EAAM,KAAK,CAAC,GAAG,OAAO,gBAAA;AAC1C,EAAA,IAAI,SAAA,KAAc,QAAQ,OAAO,YAAA;AACjC,EAAA,OAAO,YAAA;AACT;AAQA,SAAS,YAAY,IAAA,EAA6B;AAChD,EAAA,KAAA,MAAW,IAAA,IAAQ,CAAC,eAAA,EAAiB,eAAe,CAAA,EAAG;AACrD,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,IAAA,CAAK,IAAA,EAAM,IAAI,CAAC,CAAA;AACxC,IAAA,IAAI,CAAC,MAAA,EAAQ;AAEb,IAAA,MAAM,kBAAkB,MAAA,CAAO,eAAA;AAC/B,IAAA,MAAM,QAAQ,eAAA,EAAiB,KAAA;AAC/B,IAAA,IAAI,CAAC,KAAA,EAAO;AAEZ,IAAA,KAAA,MAAW,OAAA,IAAW,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,EAAG;AAExC,MAAA,IAAI,OAAA,CAAQ,SAAS,IAAI,CAAA,SAAU,OAAA,CAAQ,KAAA,CAAM,GAAG,EAAE,CAAA;AAAA,IACxD;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT;AAGO,SAAS,cAAA,CAAe,MAAmB,QAAA,EAA4B;AAC5E,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,IAAA,CAAK,GAAG,CAAA;AAC9B,EAAA,QAAQ,KAAK,cAAA;AAAgB,IAC3B,KAAK,MAAA;AACH,MAAA,OAAO,YAAY,IAAI,CAAA,CAAA;AAAA,IACzB,KAAK,MAAA;AACH,MAAA,OAAO,YAAY,IAAI,CAAA,CAAA;AAAA,IACzB,KAAK,KAAA;AACH,MAAA,OAAO,WAAW,IAAI,CAAA,CAAA;AAAA,IACxB;AACE,MAAA,OAAO,eAAe,IAAI,CAAA,CAAA;AAAA;AAEhC;AChIA,IAAM,eAAA,GAA0C;AAAA,EAC9C,MAAA,EAAQ,kBAAA;AAAA,EACR,eAAA,EAAiB,cAAA;AAAA,EACjB,mBAAA,EAAqB,kBAAA;AAAA,EACrB,gBAAA,EAAkB,eAAA;AAAA,EAClB,aAAA,EAAe,eAAA;AAAA,EACf,OAAA,EAAS,cAAA;AAAA,EACT,IAAA,EAAM,MAAA;AAAA,EACN,IAAA,EAAM,MAAA;AAAA,EACN,SAAA,EAAW,WAAA;AAAA,EACX,KAAA,EAAO,OAAA;AAAA,EACP,IAAA,EAAM,YAAA;AAAA,EACN,aAAA,EAAe,YAAA;AAAA,EACf,SAAA,EAAW,WAAA;AAAA,EACX,QAAA,EAAU,gBAAA;AAAA,EACV,IAAA,EAAM,UAAA;AAAA,EACN,MAAA,EAAQ,QAAA;AAAA,EACR,OAAA,EAAS,SAAA;AAAA,EACT,eAAA,EAAiB,cAAA;AAAA,EACjB,QAAA,EAAU,UAAA;AAAA,EACV,YAAA,EAAc;AAChB,CAAA;AAEO,SAAS,iBAAiB,IAAA,EAAsB;AACrD,EAAA,OACE,eAAA,CAAgB,IAAI,CAAA,IACpB,IAAA,CAAK,OAAA,CAAQ,eAAA,EAAiB,CAAC,CAAA,EAAG,EAAA,EAAI,MAAA,KAAmB,MAAA,CAAO,WAAA,EAAa,CAAA;AAEjF;AAEO,SAAS,cAAc,MAAA,EAAmD;AAC/E,EAAA,MAAM,UAA4B,EAAC;AAEnC,EAAA,IAAI,WAAW,WAAA,EAAa;AAC1B,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,UAAU,KAAK,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,EAAG;AACxD,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA;AAAA,QACA,IAAA,EAAM,QAAA;AAAA,QACN,SAAA,EAAW,iBAAiB,IAAI,CAAA;AAAA,QAChC,OAAA,EAAS,eAAA,CAAgB,UAAA,CAAW,QAAmC;AAAA,OACxE,CAAA;AAAA,IACH;AAAA,EACF;AAEA,EAAA,IAAI,WAAW,QAAA,EAAU;AACvB,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,UAAU,KAAK,MAAA,CAAO,OAAA,CAAQ,UAAU,CAAA,EAAG;AAC3D,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA;AAAA,QACA,IAAA,EAAM,WAAA;AAAA,QACN,SAAA,EAAW,iBAAiB,IAAI,CAAA;AAAA,QAChC,OAAA,EAAS,eAAA,CAAgB,UAAA,CAAW,QAAmC;AAAA,OACxE,CAAA;AAAA,IACH;AAAA,EACF;AAEA,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,EAAE,IAAA,CAAK,aAAA,CAAc,CAAA,CAAE,IAAI,CAAC,CAAA;AAC5D;AASA,SAAS,gBAAgB,QAAA,EAA8D;AACrF,EAAA,OAAO,MAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CAC3B,GAAA,CAAI,CAAC,CAAC,IAAA,EAAM,KAAK,CAAA,MAAO,EAAE,IAAA,EAAM,SAAS,KAAA,EAAM,CAAE,CAAA,CACjD,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,IAAA,CAAK,aAAA,CAAc,CAAA,CAAE,IAAI,CAAC,CAAA;AAChD;AAGO,SAAS,UAAU,KAAA,EAA2C;AACnE,EAAA,MAAM,MAAA,GAAS,MAAM,WAAA,EAAY;AACjC,EAAA,OAAO,eAAc,CAAE,IAAA;AAAA,IACrB,CAAC,KAAA,KAAU,KAAA,CAAM,IAAA,CAAK,WAAA,OAAkB,MAAA,IAAU,KAAA,CAAM,SAAA,CAAU,WAAA,EAAY,KAAM;AAAA,GACtF;AACF;;;ACrDO,SAAS,aAAa,OAAA,EAAgC;AAC3D,EAAA,MAAM,OAAA,GAAU,aAAA,CAAc,OAAA,CAAQ,GAAG,CAAA;AACzC,EAAA,MAAM,KAAA,GAAQ,SAAA,CAAU,OAAA,CAAQ,IAAI,CAAA;AAEpC,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,mBAAA,EAAsB,QAAQ,IAAI,CAAA,6CAAA;AAAA,KACpC;AAAA,EACF;AAEA,EAAA,IAAI,OAAA,CAAQ,cAAc,SAAA,EAAW;AACnC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KAEF;AAAA,EACF;AAEA,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,SAAA,KAAc,KAAA,IAAS,QAAQ,SAAA,KAAc,MAAA;AACnE,EAAA,MAAM,aAAA,GAAgB,OAAA,CAAQ,EAAA,IAAM,KAAA,CAAM,SAAA;AAC1C,EAAA,MAAM,SAAA,GAAY,KAAA,GAAQ,KAAA,GAAQ,OAAA,CAAQ,aAAa,KAAA,GAAQ,KAAA;AAE/D,EAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,GAAA,IAAO,OAAA,CAAQ,aAAA;AACzC,EAAA,MAAM,IAAA,GAAOA,KAAK,OAAA,CAAQ,IAAA,EAAM,WAAW,CAAA,EAAG,aAAa,CAAA,CAAA,EAAI,SAAS,CAAA,CAAE,CAAA;AAE1E,EAAA,MAAM,WAAW,KAAA,GACb,SAAA,CAAU,aAAA,EAAe,KAAA,CAAM,WAAW,KAAA,CAAM,OAAA,EAAS,OAAO,CAAA,GAChE,YAAY,aAAA,EAAe,KAAA,CAAM,SAAA,EAAW,KAAA,CAAM,SAAS,OAAO,CAAA;AAEtE,EAAA,MAAM,mBAAA,GAAsB,WAAW,OAAO,CAAA;AAE9C,EAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,IAAA,OAAO,EAAE,IAAA,EAAM,QAAA,EAAU,OAAA,EAAS,OAAO,mBAAA,EAAoB;AAAA,EAC/D;AAEA,EAAA,IAAIC,UAAAA,CAAW,IAAI,CAAA,IAAK,CAAC,QAAQ,KAAA,EAAO;AACtC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,EAAG,IAAI,CAAA,2CAAA,CAA6C,CAAA;AAAA,EACtE;AAEA,EAAA,SAAA,CAAU,QAAQ,IAAI,CAAA,EAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AAC5C,EAAA,aAAA,CAAc,IAAA,EAAM,UAAU,MAAM,CAAA;AAEpC,EAAA,OAAO,EAAE,IAAA,EAAM,QAAA,EAAU,OAAA,EAAS,MAAM,mBAAA,EAAoB;AAC9D;AAEA,SAAS,WAAW,OAAA,EAAgC;AAClD,EAAA,IAAI,OAAA,CAAQ,SAAA,EAAW,OAAO,EAAC;AAC/B,EAAA,QAAQ,QAAQ,SAAA;AAAW,IACzB,KAAK,MAAA;AACH,MAAA,OAAO,CAAC,eAAe,CAAA;AAAA,IACzB,KAAK,KAAA;AACH,MAAA,OAAO,CAAC,gBAAgB,iBAAiB,CAAA;AAAA,IAC3C;AACE,MAAA,OAAO,CAAC,kBAAkB,iBAAiB,CAAA;AAAA;AAEjD;AAQA,SAAS,QAAQ,KAAA,EAAwB;AACvC,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,IAAA,CAAK,UAAU,KAAK,CAAA;AAC1D,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG,OAAO,CAAA,CAAA,EAAI,KAAA,CAAM,GAAA,CAAI,OAAO,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,CAAA;AAClE,EAAA,IAAI,KAAA,KAAU,MAAM,OAAO,MAAA;AAC3B,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,IAAA,CAAK,UAAU,KAAK,CAAA;AAC1D,EAAA,OAAO,OAAO,KAAK,CAAA;AACrB;AASA,IAAM,mBAAA,uBAA0B,GAAA,CAAI;AAAA,EAClC,QAAA;AAAA,EACA,OAAA;AAAA,EACA,WAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,UAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAA;AAAA,EACA,UAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAC,CAAA;AAED,SAAS,aAAa,OAAA,EAAoD;AACxE,EAAA,OAAO,OAAA,CAAQ,OAAO,CAAC,MAAA,KAAW,oBAAoB,GAAA,CAAI,MAAA,CAAO,IAAI,CAAC,CAAA;AACxE;AAEA,SAAS,WAAA,CACP,aAAA,EACA,eAAA,EACA,OAAA,EACA,OAAA,EACQ;AACR,EAAA,MAAM,KAAK,OAAA,CAAQ,UAAA;AACnB,EAAA,MAAM,QAAA,GAAW,aAAa,OAAO,CAAA;AAErC,EAAA,MAAM,eAAe,QAAA,CAClB,GAAA,CAAI,CAAC,MAAA,KAAW,KAAK,MAAA,CAAO,IAAI,CAAA,EAAA,EAAK,OAAA,CAAQ,OAAO,OAAO,CAAC,CAAA,CAAA,CAAG,CAAA,CAC/D,KAAK,IAAI,CAAA;AAEZ,EAAA,MAAM,YAAY,EAAA,GACd;AAAA,KAAA,EAAU,aAAa,iCAAiC,eAAe,CAAA;AAAA,CAAA,GACvE,EAAA;AAEJ,EAAA,MAAM,SAAA,GAAY,KACd,CAAA,gBAAA,EAAmB,aAAa,4BAA4B,aAAa,CAAA,QAAA,CAAA,GACzE,mBAAmB,aAAa,CAAA,0BAAA,CAAA;AAEpC,EAAA,MAAM,aAAa,EAAA,GAAK,CAAA;AAAA,CAAA,GAAkD,EAAA;AAE1E,EAAA,OAAO,CAAA,EAAG,UAAU,CAAA,SAAA,EAAY,eAAe,CAAA;;AAAA;AAAA,GAAA,EAG5C,aAAa,iDAA4C,eAAe,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ3E,YAAY;AAAA;;AAAA,EAGZ,SAAS;AAAA,EACT,SAAS;AAAA;AAAA,KAAA,EAEJ,eAAe,CAAA;AAAA;AAAA,MAAA,EAEd,eAAe,CAAA;AAAA;AAAA;AAAA,CAAA;AAIvB;AAEA,SAAS,SAAA,CACP,aAAA,EACA,eAAA,EACA,OAAA,EACA,OAAA,EACQ;AACR,EAAA,MAAM,QAAA,GAAW,aAAa,OAAO,CAAA;AACrC,EAAA,MAAM,eAAe,QAAA,CAClB,GAAA,CAAI,CAAC,MAAA,KAAW,KAAK,MAAA,CAAO,IAAI,CAAA,EAAA,EAAK,OAAA,CAAQ,OAAO,OAAO,CAAC,CAAA,CAAA,CAAG,CAAA,CAC/D,KAAK,IAAI,CAAA;AAEZ,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,UAAA,GAAa,YAAA,GAAe,EAAA;AAIjD,EAAA,MAAM,UAAA,GACJ,QAAQ,SAAA,KAAc,MAAA,GAClB,MAAM,eAAe,CAAA,mCAAA,CAAA,GACrB,YAAY,eAAe,CAAA,sBAAA,CAAA;AAEjC,EAAA,OAAO,gBAAgB,IAAI,CAAA;AAAA,EAC3B,UAAU;;AAAA;AAAA,GAAA,EAGP,aAAa,iDAA4C,eAAe,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ3E,YAAY;AAAA;AAAA;;AAAA;AAAA,GAAA,EAKT,eAAe,CAAA;AAAA;AAAA,IAAA,EAEd,eAAe,CAAA;AAAA;AAAA,CAAA;AAGrB;AC5LO,SAAS,qBAAA,CAAsB,OAAA,GAAgC,EAAC,EAAkB;AACvF,EAAA,MAAM,SACJ,OAAA,CAAQ,MAAA,IAAU,OAAA,CAAQ,MAAA,CAAO,SAAS,CAAA,GACtC,OAAA,CAAQ,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,KAAU,UAAA,CAAW,KAAK,CAAC,IAC/C,eAAA,CAAgB;AAAA,IACd,KAAA,EAAO,QAAQ,KAAA,IAAS,CAAA;AAAA,IACxB,IAAA,EAAM,QAAQ,IAAA,IAAQ,CAAA;AAAA,IACtB,SAAA,EAAW,QAAQ,SAAA,IAAa,IAAA;AAAA,IAChC,UAAA,EAAY,QAAQ,UAAA,IAAc,IAAA;AAAA,IAClC,MAAA,EAAQ,QAAQ,MAAA,IAAU;AAAA,GAC3B,CAAA;AAEP,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,KAAU;AACnC,IAAA,MAAM,GAAA,GAAM,WAAW,KAAK,CAAA;AAC5B,IAAA,OAAO;AAAA,MACL,GAAA,EAAK,MAAM,KAAK,CAAA;AAAA,MAChB,KAAA,EAAO,cAAc,KAAK,CAAA;AAAA,MAC1B,WAAW,MAAA,CAAO,GAAA,CAAI,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAC,CAAA;AAAA,MAClC,QAAQ,MAAA,CAAO,GAAA,CAAI,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAC,CAAA;AAAA,MAC/B,KAAK,MAAA,CAAO,GAAA,CAAI,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAC;AAAA,KAC9B;AAAA,EACF,CAAC,CAAA;AAID,EAAA,MAAM,eAAA,GACJ,OAAA,CAAQ,QAAA,KAAa,KAAA,IAAS,MAAA,CAAO,SAAS,CAAA,GAC1C,EAAC,GACD,cAAA,CAAe,MAAA,EAAQ,EAAE,OAAO,OAAA,EAAS,CAAA,CACtC,MAAA,CAAO,CAAC,CAAA,CACR,IAAI,CAAC,KAAA,KAAU,KAAA,CAAM,KAAK,CAAC,CAAA;AAEpC,EAAA,MAAM,OAAA,GAAU,CAAA,SAAA,EAAY,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAA,EAAI,CAAA,CAAE,GAAG,CAAA,CAAA,CAAG,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA,EAAA,CAAA;AAEtE,EAAA,OAAO,EAAE,MAAA,EAAQ,eAAA,EAAiB,OAAA,EAAQ;AAC5C;AClCA,IAAM,aAAA,GAAgB,CAAC,IAAA,EAAM,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,KAAK,CAAA;AAE1F,SAAS,cAAc,OAAA,EAAoC;AAChE,EAAA,MAAM,IAAA,GAAOC,UAAAA,CAAW,OAAA,CAAQ,KAAK,CAAA;AACrC,EAAA,MAAM,aAAA,GAAgBC,UAAAA,CAAW,IAAI,CAAA,CAAE,CAAA;AAEvC,EAAA,MAAM,KAAA,GAAQ,YAAY,IAAA,EAAM;AAAA,IAC9B,KAAA,EAAO,EAAA;AAAA,IACP,QAAA,EAAU,QAAQ,QAAA,IAAY,CAAA;AAAA,IAC9B,aAAA,EAAe,QAAQ,aAAA,IAAiB;AAAA,GACzC,CAAA;AAED,EAAA,MAAM,gBAA0B,EAAC;AACjC,EAAA,MAAM,eAAyB,EAAC;AAEhC,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,IAAI,WAAA,GAAc,KAAA;AAClB,EAAA,IAAI,eAAA,GAAkB,QAAA;AAEtB,EAAA,KAAA,CAAM,MAAA,CAAO,OAAA,CAAQ,CAAC,KAAA,EAAO,KAAA,KAAU;AACrC,IAAA,MAAM,GAAA,GAAM,cAAc,KAAK,CAAA;AAC/B,IAAA,MAAM,OAAA,GAAU,aAAA,CAAc,KAAA,EAAO,SAAS,CAAA;AAC9C,IAAA,MAAM,MAAA,GAAS,aAAA,CAAc,KAAA,EAAO,SAAS,CAAA;AAE7C,IAAA,IAAI,CAAC,OAAA,CAAQ,MAAA,EAAQ,aAAA,CAAc,KAAK,GAAG,CAAA;AAC3C,IAAA,IAAI,CAAC,MAAA,CAAO,MAAA,EAAQ,YAAA,CAAa,KAAK,GAAG,CAAA;AAEzC,IAAA,MAAM,WAAW,IAAA,CAAK,GAAA,CAAIA,WAAW,KAAK,CAAA,CAAE,IAAI,aAAa,CAAA;AAC7D,IAAA,IAAI,WAAW,eAAA,EAAiB;AAC9B,MAAA,eAAA,GAAkB,QAAA;AAClB,MAAA,WAAA,GAAc,GAAA;AAAA,IAChB;AAIA,IAAA,KAAA,CAAM,IAAA;AAAA,MACJ,CAAA,eAAA,EAAkB,GAAG,CAAA,EAAA,EAAKC,aAAAA,CAAc,KAAK,CAAC,CAAA,KAAA,EACrCC,MAAM,KAAK,CAAC,cAAc,OAAA,CAAQ,KAAA,CAAM,QAAQ,CAAC,CAAC,gBAC3C,MAAA,CAAO,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAC,CAAA,KAAA;AAAA,KACzC;AAAA,EACF,CAAC,CAAA;AAED,EAAA,IAAI,WAAA,GAAc,EAAA;AAClB,EAAA,IAAI,QAAQ,UAAA,EAAY;AAItB,IAAA,MAAM,GAAG,MAAM,CAAA,GAAI,OAAA,CAAQ,MAAM,oBAAoB,CAAA;AACrD,IAAA,MAAM,cAAc,WAAA,CAAY,MAAA,EAAQ,EAAE,KAAA,EAAO,IAAI,CAAA;AACrD,IAAA,WAAA,GACE,4EACA,WAAA,CAAY,MAAA,CACT,IAAI,CAAC,KAAA,EAAO,UAAU,CAAA,gBAAA,EAAmB,aAAA,CAAc,KAAK,CAAC,CAAA,EAAA,EAAKD,cAAc,KAAK,CAAC,GAAG,CAAA,CACzF,IAAA,CAAK,IAAI,CAAA,GACZ,IAAA;AAAA,EACJ;AAEA,EAAA,MAAM,GAAA,GAAM,CAAA;AAAA;AAAA;AAAA,6BAAA,EAGiB,QAAQ,KAAK,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA,EAQ1C,KAAA,CAAM,IAAA,CAAK,IAAI,CAAC;AAAA,EAChB,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAwCX,EAAA,IAAI,QAAQ,GAAA,EAAK;AACf,IAAAE,SAAAA,CAAUC,QAAQ,OAAA,CAAQ,GAAG,GAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AACnD,IAAAC,aAAAA,CAAc,OAAA,CAAQ,GAAA,EAAK,GAAA,EAAK,MAAM,CAAA;AAAA,EACxC;AAEA,EAAA,OAAO,EAAE,GAAA,EAAK,aAAA,EAAe,YAAA,EAAc,WAAA,EAAY;AACzD;;;AChJA,IAAM,WAAW,OAAA,CAAQ,MAAA,CAAO,KAAA,IAAS,CAAC,QAAQ,GAAA,CAAI,QAAA;AAEtD,IAAM,KAAA,GAAQ,CAAC,IAAA,EAAc,IAAA,KAA0B,WAAW,CAAA,KAAA,EAAK,IAAI,CAAA,CAAA,EAAI,IAAI,CAAA,OAAA,CAAA,GAAS,IAAA;AAE5F,IAAM,IAAA,GAAO,CAAC,IAAA,KAAiB,KAAA,CAAM,KAAK,IAAI,CAAA;AAC9C,IAAM,GAAA,GAAM,CAAC,IAAA,KAAiB,KAAA,CAAM,KAAK,IAAI,CAAA;AAC7C,IAAM,IAAA,GAAO,CAAC,IAAA,KAAiB,KAAA,CAAM,MAAM,IAAI,CAAA;AAC/C,IAAM,KAAA,GAAQ,CAAC,IAAA,KAAiB,KAAA,CAAM,MAAM,IAAI,CAAA;AAChD,IAAM,MAAA,GAAS,CAAC,IAAA,KAAiB,KAAA,CAAM,MAAM,IAAI,CAAA;AACjD,IAAM,GAAA,GAAM,CAAC,IAAA,KAAiB,KAAA,CAAM,MAAM,IAAI,CAAA;AAE9C,IAAM,OAAA,GAAU,OAAA;AAEhB,SAAS,IAAA,GAAa;AACpB,EAAA,OAAA,CAAQ,GAAA,CAAI;AAAA,EACZ,IAAA,CAAK,MAAM,CAAC,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA,EAAI,OAAO,EAAE,CAAC,CAAA;;AAAA,EAElC,IAAA,CAAK,OAAO,CAAC;AAAA;;AAAA,EAGb,IAAA,CAAK,UAAU,CAAC;AAAA,EAAA,EACd,IAAA,CAAK,MAAM,CAAC,CAAA;AAAA,EAAA,EACZ,IAAA,CAAK,MAAM,CAAC,CAAA;AAAA,EAAA,EACZ,IAAA,CAAK,KAAK,CAAC,CAAA;AAAA,EAAA,EACX,IAAA,CAAK,OAAO,CAAC,CAAA;AAAA,EAAA,EACb,IAAA,CAAK,SAAS,CAAC,CAAA;AAAA,EAAA,EACf,IAAA,CAAK,QAAQ,CAAC,CAAA;;AAAA,EAEhB,IAAA,CAAK,UAAU,CAAC;AAAA,EAAA,EACd,GAAA,CAAI,yBAAyB,CAAC;AAAA;;AAAA,EAAA,EAG9B,GAAA,CAAI,8DAA8D,CAAC;AAAA;;AAAA,EAAA,EAGnE,GAAA,CAAI,gEAAgE,CAAC;AAAA;;AAAA,EAAA,EAGrE,GAAA,CAAI,sCAAsC,CAAC;AAAA;;AAAA,EAAA,EAG3C,GAAA,CAAI,kCAAkC,CAAC;AAAA;AAAA,CAE1C,CAAA;AACD;AAEA,SAAS,IAAA,CAAK,SAAiB,IAAA,EAAsB;AACnD,EAAA,OAAA,CAAQ,MAAM,CAAA,EAAG,GAAA,CAAI,OAAO,CAAC,CAAA,EAAA,EAAK,OAAO,CAAA,CAAE,CAAA;AAC3C,EAAA,IAAI,IAAA,UAAc,KAAA,CAAM,CAAA,EAAG,IAAI,MAAM,CAAC,CAAA,GAAA,EAAM,IAAI,CAAA,CAAE,CAAA;AAClD,EAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAChB;AAMA,SAAS,YAAY,IAAA,EAAsB;AACzC,EAAA,MAAM,EAAE,MAAA,EAAO,GAAI,SAAA,CAAU;AAAA,IAC3B,IAAA,EAAM,IAAA;AAAA,IACN,OAAA,EAAS;AAAA,MACP,OAAA,EAAS,EAAE,IAAA,EAAM,SAAA,EAAW,SAAS,KAAA,EAAM;AAAA,MAC3C,UAAA,EAAY,EAAE,IAAA,EAAM,SAAA,EAAW,SAAS,KAAA,EAAM;AAAA,MAC9C,IAAA,EAAM,EAAE,IAAA,EAAM,SAAA,EAAW,SAAS,KAAA;AAAM,KAC1C;AAAA,IACA,gBAAA,EAAkB;AAAA,GACnB,CAAA;AAED,EAAA,MAAM,SAAS,MAAA,CAAO,OAAA,GAAU,QAAA,GAAW,MAAA,CAAO,aAAa,WAAA,GAAc,MAAA;AAC7E,EAAA,MAAM,OAAA,GAAU,cAAc,MAAM,CAAA;AAEpC,EAAA,IAAI,OAAO,IAAA,EAAM;AACf,IAAA,OAAA,CAAQ,IAAI,IAAA,CAAK,SAAA,CAAU,OAAA,EAAS,IAAA,EAAM,CAAC,CAAC,CAAA;AAC5C,IAAA;AAAA,EACF;AAEA,EAAA,MAAMC,WAAU,OAAA,CAAQ,MAAA,CAAO,CAAC,KAAA,KAAU,KAAA,CAAM,SAAS,QAAQ,CAAA;AACjE,EAAA,MAAMC,cAAa,OAAA,CAAQ,MAAA,CAAO,CAAC,KAAA,KAAU,KAAA,CAAM,SAAS,WAAW,CAAA;AAEvE,EAAA,MAAM,KAAA,GAAQ,CAAC,KAAA,EAAe,IAAA,KAAyB;AACrD,IAAA,IAAI,IAAA,CAAK,WAAW,CAAA,EAAG;AACvB,IAAA,OAAA,CAAQ,GAAA,CAAI;AAAA,EAAK,IAAA,CAAK,KAAK,CAAC,CAAA,CAAE,CAAA;AAC9B,IAAA,KAAA,MAAW,SAAS,IAAA,EAAM;AACxB,MAAA,OAAA,CAAQ,GAAA;AAAA,QACN,CAAA,EAAA,EAAK,KAAK,KAAA,CAAM,IAAA,CAAK,OAAO,EAAE,CAAC,CAAC,CAAA,CAAA,EAAI,KAAA,CAAM,UAAU,MAAA,CAAO,EAAE,CAAC,CAAA,CAAA,CAAA,GAC5D,GAAA,CAAI,GAAG,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,QAAA,CAAU;AAAA,OACzC;AAAA,IACF;AAAA,EACF,CAAA;AAEA,EAAA,KAAA,CAAM,CAAA,SAAA,EAAY,GAAA,CAAI,UAAU,CAAC,IAAID,QAAO,CAAA;AAC5C,EAAA,KAAA,CAAM,CAAA,YAAA,EAAe,GAAA,CAAI,OAAO,CAAC,IAAIC,WAAU,CAAA;AAC/C,EAAA,OAAA,CAAQ,GAAA,CAAI;AAAA,EAAK,GAAA,CAAI,CAAA,EAAG,OAAA,CAAQ,MAAM,+CAA+C,CAAC;AAAA,CAAI,CAAA;AAC5F;AAEA,SAAS,YAAY,IAAA,EAAsB;AACzC,EAAA,MAAM,IAAA,GAAO,KAAK,CAAC,CAAA;AACnB,EAAA,IAAI,CAAC,IAAA,EAAM,IAAA,CAAK,yBAAA,EAA2B,kBAAkB,CAAA;AAE7D,EAAA,MAAM,KAAA,GAAQ,UAAU,IAAI,CAAA;AAC5B,EAAA,IAAI,CAAC,KAAA,EAAO,IAAA,CAAK,CAAA,mBAAA,EAAsB,IAAI,MAAM,2CAA2C,CAAA;AAE5F,EAAA,OAAA,CAAQ,GAAA,CAAI;AAAA,EAAK,IAAA,CAAK,KAAA,CAAM,SAAS,CAAC,CAAA,EAAA,EAAK,GAAA,CAAI,CAAA,CAAA,EAAI,KAAA,CAAM,IAAI,CAAA,EAAA,EAAK,KAAA,CAAM,IAAI,IAAI,CAAC;AAAA,CAAI,CAAA;AACrF,EAAA,OAAA,CAAQ,GAAA,CAAI,IAAA,CAAK,WAAW,CAAC,CAAA;AAE7B,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,GAAG,KAAA,CAAM,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,KAAW,MAAA,CAAO,IAAA,CAAK,MAAM,CAAC,CAAA;AAC3E,EAAA,KAAA,MAAW,MAAA,IAAU,MAAM,OAAA,EAAS;AAClC,IAAA,MAAM,QACJ,OAAO,MAAA,CAAO,OAAA,KAAY,QAAA,GACtB,IAAI,MAAA,CAAO,OAAO,CAAA,CAAA,CAAA,GAClB,KAAA,CAAM,QAAQ,MAAA,CAAO,OAAO,CAAA,GAC1B,CAAA,CAAA,EAAI,OAAO,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAO,OAAO,CAAA,KAAM,QAAA,GAAW,CAAA,CAAA,EAAI,CAAC,MAAM,MAAA,CAAO,CAAC,CAAE,CAAA,CAAE,KAAK,IAAI,CAAC,CAAA,CAAA,CAAA,GACxF,MAAA,CAAO,OAAO,OAAO,CAAA;AAC7B,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,IAAA,EAAO,MAAA,CAAO,IAAA,CAAK,OAAO,KAAK,CAAC,CAAA,EAAA,EAAK,GAAA,CAAI,GAAG,CAAC,CAAA,CAAA,EAAI,KAAA,CAAM,KAAK,CAAC,CAAA,CAAE,CAAA;AAAA,EAC7E;AAEA,EAAA,OAAA,CAAQ,GAAA;AAAA,IACN;AAAA,EAAK,GAAA,CAAI,CAAA,yCAAA,EAA4C,KAAA,CAAM,IAAI,EAAE,CAAC;AAAA,EAC7D,GAAA,CAAI,CAAA,iBAAA,EAAoB,KAAA,CAAM,IAAI,EAAE,CAAC;AAAA;AAAA,GAC5C;AACF;AAEA,SAAS,WAAW,IAAA,EAAsB;AACxC,EAAA,MAAM,EAAE,MAAA,EAAQ,WAAA,EAAY,GAAI,SAAA,CAAU;AAAA,IACxC,IAAA,EAAM,IAAA;AAAA,IACN,OAAA,EAAS;AAAA,MACP,EAAA,EAAI,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MACrB,GAAA,EAAK,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MACtB,KAAA,EAAO,EAAE,IAAA,EAAM,SAAA,EAAW,SAAS,KAAA,EAAM;AAAA,MACzC,SAAA,EAAW,EAAE,IAAA,EAAM,SAAA,EAAW,SAAS,KAAA;AAAM,KAC/C;AAAA,IACA,gBAAA,EAAkB;AAAA,GACnB,CAAA;AAED,EAAA,MAAM,IAAA,GAAO,YAAY,CAAC,CAAA;AAC1B,EAAA,IAAI,CAAC,IAAA,EAAM,IAAA,CAAK,yBAAA,EAA2B,qCAAqC,CAAA;AAEhF,EAAA,IAAI;AACF,IAAA,MAAM,SAAS,YAAA,CAAa;AAAA,MAC1B,IAAA;AAAA,MACA,IAAI,MAAA,CAAO,EAAA;AAAA,MACX,KAAK,MAAA,CAAO,GAAA;AAAA,MACZ,OAAO,MAAA,CAAO,KAAA;AAAA,MACd,MAAA,EAAQ,OAAO,SAAS;AAAA,KACzB,CAAA;AAED,IAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,MAAA,OAAA,CAAQ,IAAI,CAAA,EAAG,GAAA,CAAI,OAAO,MAAA,CAAO,IAAI,MAAM,CAAC;AAAA,CAAI,CAAA;AAChD,MAAA,OAAA,CAAQ,GAAA,CAAI,OAAO,QAAQ,CAAA;AAC3B,MAAA;AAAA,IACF;AAEA,IAAA,OAAA,CAAQ,GAAA,CAAI,GAAG,KAAA,CAAM,SAAS,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,IAAI,CAAA,CAAE,CAAA;AAEjD,IAAA,IAAI,MAAA,CAAO,mBAAA,CAAoB,MAAA,GAAS,CAAA,EAAG;AACzC,MAAA,MAAM,UAAU,aAAA,EAAc;AAC9B,MAAA,OAAA,CAAQ,GAAA;AAAA,QACN;AAAA,EAAK,MAAA,CAAO,MAAM,CAAC,CAAA;AAAA,SAAA,EACL,cAAA,CAAe,OAAA,EAAS,MAAA,CAAO,mBAAmB,CAAC,CAAA;AAAA,OACnE;AAAA,IACF;AAAA,EACF,SAAS,KAAA,EAAO;AACd,IAAA,IAAA,CAAK,iBAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,EAC7D;AACF;AAEA,SAAS,aAAa,IAAA,EAAsB;AAC1C,EAAA,MAAM,EAAE,MAAA,EAAQ,WAAA,EAAY,GAAI,SAAA,CAAU;AAAA,IACxC,IAAA,EAAM,IAAA;AAAA,IACN,OAAA,EAAS;AAAA,MACP,GAAA,EAAK,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MACtB,WAAA,EAAa,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MAC9B,gBAAA,EAAkB,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MACnC,aAAA,EAAe,EAAE,IAAA,EAAM,SAAA,EAAW,SAAS,KAAA;AAAM,KACnD;AAAA,IACA,gBAAA,EAAkB;AAAA,GACnB,CAAA;AAED,EAAA,MAAM,KAAA,GAAQ,YAAY,CAAC,CAAA;AAC3B,EAAA,IAAI,CAAC,KAAA,EAAO,IAAA,CAAK,uBAAA,EAAyB,sCAAsC,CAAA;AAEhF,EAAA,IAAI;AACF,IAAA,MAAM,SAAS,aAAA,CAAc;AAAA,MAC3B,KAAA;AAAA,MACA,KAAK,MAAA,CAAO,GAAA;AAAA,MACZ,QAAA,EAAU,OAAO,WAAW,CAAA,GAAI,OAAO,MAAA,CAAO,WAAW,CAAC,CAAA,GAAI,KAAA,CAAA;AAAA,MAC9D,aAAA,EAAe,OAAO,gBAAgB,CAAA,GAAI,OAAO,MAAA,CAAO,gBAAgB,CAAC,CAAA,GAAI,KAAA,CAAA;AAAA,MAC7E,UAAA,EAAY,OAAO,aAAa;AAAA,KACjC,CAAA;AAED,IAAA,IAAI,CAAC,OAAO,GAAA,EAAK;AACf,MAAA,OAAA,CAAQ,GAAA,CAAI,OAAO,GAAG,CAAA;AACtB,MAAA;AAAA,IACF;AAEA,IAAA,OAAA,CAAQ,GAAA,CAAI,GAAG,KAAA,CAAM,SAAS,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,GAAG,CAAA,CAAE,CAAA;AAChD,IAAA,OAAA,CAAQ,GAAA,CAAI,GAAG,GAAA,CAAI,SAAS,CAAC,CAAA,gCAAA,EAAmC,MAAA,CAAO,WAAW,CAAA,CAAE,CAAA;AAIpF,IAAA,IAAI,MAAA,CAAO,aAAA,CAAc,MAAA,GAAS,CAAA,EAAG;AACnC,MAAA,OAAA,CAAQ,GAAA;AAAA,QACN,CAAA,EAAG,OAAO,MAAM,CAAC,cAAc,MAAA,CAAO,aAAA,CAAc,IAAA,CAAK,IAAI,CAAC,CAAA,8EAAA;AAAA,OAEhE;AAAA,IACF;AACA,IAAA,IAAI,MAAA,CAAO,YAAA,CAAa,MAAA,GAAS,CAAA,EAAG;AAClC,MAAA,OAAA,CAAQ,GAAA;AAAA,QACN,CAAA,EAAG,OAAO,MAAM,CAAC,cAAc,MAAA,CAAO,YAAA,CAAa,IAAA,CAAK,IAAI,CAAC,CAAA,8BAAA;AAAA,OAC/D;AAAA,IACF;AAAA,EACF,SAAS,KAAA,EAAO;AACd,IAAA,IAAA,CAAK,iBAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,EAC7D;AACF;AAEA,SAAS,eAAe,IAAA,EAAsB;AAC5C,EAAA,MAAM,EAAE,MAAA,EAAQ,WAAA,EAAY,GAAI,SAAA,CAAU;AAAA,IACxC,IAAA,EAAM,IAAA;AAAA,IACN,OAAA,EAAS;AAAA,MACP,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MACxB,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MACvB,SAAA,EAAW,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MAC5B,UAAA,EAAY,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MAC7B,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MACzB,IAAA,EAAM,EAAE,IAAA,EAAM,SAAA,EAAW,SAAS,KAAA;AAAM,KAC1C;AAAA,IACA,gBAAA,EAAkB;AAAA,GACnB,CAAA;AAED,EAAA,IAAI;AACF,IAAA,MAAM,SAAS,qBAAA,CAAsB;AAAA,MACnC,MAAA,EAAQ,WAAA,CAAY,MAAA,GAAS,CAAA,GAAI,WAAA,GAAc,KAAA,CAAA;AAAA,MAC/C,OAAO,MAAA,CAAO,KAAA,GAAQ,MAAA,CAAO,MAAA,CAAO,KAAK,CAAA,GAAI,KAAA,CAAA;AAAA,MAC7C,MAAM,MAAA,CAAO,IAAA;AAAA,MACb,WAAW,MAAA,CAAO,SAAA,GAAY,MAAA,CAAO,MAAA,CAAO,SAAS,CAAA,GAAI,KAAA,CAAA;AAAA,MACzD,YAAY,MAAA,CAAO,UAAA,GAAa,MAAA,CAAO,MAAA,CAAO,UAAU,CAAA,GAAI,KAAA,CAAA;AAAA,MAC5D,QAAQ,MAAA,CAAO,MAAA,GAAS,MAAA,CAAO,MAAA,CAAO,MAAM,CAAA,GAAI,KAAA;AAAA,KACjD,CAAA;AAED,IAAA,IAAI,OAAO,IAAA,EAAM;AACf,MAAA,OAAA,CAAQ,IAAI,IAAA,CAAK,SAAA,CAAU,MAAA,EAAQ,IAAA,EAAM,CAAC,CAAC,CAAA;AAC3C,MAAA;AAAA,IACF;AAEA,IAAA,OAAA,CAAQ,GAAA,CAAI;AAAA,EAAK,IAAA,CAAK,SAAS,CAAC;AAAA,CAAI,CAAA;AACpC,IAAA,KAAA,MAAW,KAAA,IAAS,OAAO,MAAA,EAAQ;AACjC,MAAA,OAAA,CAAQ,GAAA;AAAA,QACN,KAAK,MAAA,CAAO,KAAA,CAAM,GAAG,CAAC,CAAA,CAAA,EAAI,MAAM,GAAA,CAAI,MAAA,CAAO,CAAC,CAAC,CAAA,CAAA,EAAI,IAAI,KAAA,CAAM,KAAA,CAAM,OAAO,EAAE,CAAC,CAAC,CAAA,CAAA,CAAA,GAC1E,GAAA;AAAA,UACE,KAAK,KAAA,CAAM,SAAA,CAAU,OAAA,CAAQ,CAAC,CAAC,CAAA,IAAA,EAAO,KAAA,CAAM,MAAA,CAAO,OAAA,CAAQ,CAAC,CAAC,CAAA,IAAA,EAAO,MAAM,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAC,CAAA;AAAA;AAC1F,OACJ;AAAA,IACF;AAEA,IAAA,IAAI,MAAA,CAAO,eAAA,CAAgB,MAAA,GAAS,CAAA,EAAG;AACrC,MAAA,OAAA,CAAQ,GAAA,CAAI;AAAA,EAAK,KAAK,UAAU,CAAC,CAAA,CAAA,EAAI,GAAA,CAAI,uBAAuB,CAAC;AAAA,CAAI,CAAA;AACrE,MAAA,OAAA,CAAQ,GAAA,CAAI,IAAA,GAAO,MAAA,CAAO,eAAA,CAAgB,GAAA,CAAI,CAAC,GAAA,KAAQ,MAAA,CAAO,GAAG,CAAC,CAAA,CAAE,IAAA,CAAK,EAAE,CAAC,CAAA;AAC5E,MAAA,OAAA,CAAQ,GAAA,CAAI,OAAO,GAAA,CAAI,MAAA,CAAO,gBAAgB,IAAA,CAAK,GAAG,CAAC,CAAC,CAAA;AAAA,IAC1D;AAEA,IAAA,OAAA,CAAQ,GAAA,CAAI;AAAA,EAAK,IAAA,CAAK,SAAS,CAAC;;AAAA,EAAA,EAAS,KAAA,CAAM,MAAA,CAAO,OAAO,CAAC;AAAA,CAAI,CAAA;AAAA,EACpE,SAAS,KAAA,EAAO;AACd,IAAA,IAAA,CAAK,iBAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,EAC7D;AACF;AAEA,SAAS,aAAA,GAAsB;AAC7B,EAAA,MAAM,UAAU,aAAA,EAAc;AAE9B,EAAA,OAAA,CAAQ,GAAA,CAAI;AAAA,EAAK,IAAA,CAAK,SAAS,CAAC;AAAA,CAAI,CAAA;AACpC,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,kBAAA,EAAqB,OAAA,CAAQ,IAAI,CAAA,CAAE,CAAA;AAC/C,EAAA,OAAA,CAAQ,GAAA;AAAA,IACN,CAAA,kBAAA,EAAqB,OAAA,CAAQ,SAAA,KAAc,SAAA,GAAY,MAAA,CAAO,cAAc,CAAA,GAAI,KAAA,CAAM,OAAA,CAAQ,SAAS,CAAC,CAAA;AAAA,GAC1G;AACA,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,kBAAA,EAAqB,OAAA,CAAQ,UAAA,GAAa,KAAA,CAAM,KAAK,CAAA,GAAI,GAAA,CAAI,IAAI,CAAC,CAAA,CAAE,CAAA;AAChF,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,kBAAA,EAAqB,OAAA,CAAQ,cAAc,CAAA,CAAE,CAAA;AACzD,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,kBAAA,EAAqB,OAAA,CAAQ,aAAa,CAAA,CAAE,CAAA;AACxD,EAAA,OAAA,CAAQ,IAAI,CAAA,kBAAA,EAAqB,OAAA,CAAQ,SAAS,GAAA,CAAI,MAAM,CAAC,CAAA,CAAE,CAAA;AAC/D,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,eAAA,EAAkB,OAAA,CAAQ,SAAA,GAAY,KAAA,CAAM,WAAW,CAAA,GAAI,MAAA,CAAO,eAAe,CAAC,CAAA,CAAE,CAAA;AAEhG,EAAA,IAAI,CAAC,QAAQ,SAAA,EAAW;AACtB,IAAA,MAAM,WACJ,OAAA,CAAQ,SAAA,KAAc,MAAA,GAClB,CAAC,eAAe,CAAA,GAChB,OAAA,CAAQ,SAAA,KAAc,KAAA,GACpB,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAClC,CAAC,kBAAkB,iBAAiB,CAAA;AAC5C,IAAA,OAAA,CAAQ,GAAA,CAAI;AAAA,EAAK,OAAO,MAAM,CAAC,KAAK,cAAA,CAAe,OAAA,EAAS,QAAQ,CAAC;AAAA,CAAI,CAAA;AAAA,EAC3E,CAAA,MAAO;AACL,IAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AAAA,EAChB;AACF;AAGA,SAAS,OAAO,GAAA,EAAqB;AACnC,EAAA,IAAI,CAAC,UAAU,OAAO,QAAA;AACtB,EAAA,MAAM,IAAI,QAAA,CAAS,GAAA,CAAI,MAAM,CAAA,EAAG,CAAC,GAAG,EAAE,CAAA;AACtC,EAAA,MAAM,IAAI,QAAA,CAAS,GAAA,CAAI,MAAM,CAAA,EAAG,CAAC,GAAG,EAAE,CAAA;AACtC,EAAA,MAAM,IAAI,QAAA,CAAS,GAAA,CAAI,MAAM,CAAA,EAAG,CAAC,GAAG,EAAE,CAAA;AACtC,EAAA,OAAO,CAAA,UAAA,EAAU,CAAC,CAAA,CAAA,EAAI,CAAC,IAAI,CAAC,CAAA,UAAA,CAAA;AAC9B;AAMA,SAAS,IAAA,GAAa;AACpB,EAAA,MAAM,CAAC,SAAS,GAAG,IAAI,IAAI,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAE/C,EAAA,QAAQ,OAAA;AAAS,IACf,KAAK,MAAA;AAAA,IACL,KAAK,IAAA;AACH,MAAA,OAAO,YAAY,IAAI,CAAA;AAAA,IACzB,KAAK,MAAA;AAAA,IACL,KAAK,MAAA;AACH,MAAA,OAAO,YAAY,IAAI,CAAA;AAAA,IACzB,KAAK,KAAA;AACH,MAAA,OAAO,WAAW,IAAI,CAAA;AAAA,IACxB,KAAK,OAAA;AACH,MAAA,OAAO,aAAa,IAAI,CAAA;AAAA,IAC1B,KAAK,SAAA;AACH,MAAA,OAAO,eAAe,IAAI,CAAA;AAAA,IAC5B,KAAK,QAAA;AACH,MAAA,OAAO,aAAA,EAAc;AAAA,IACvB,KAAK,WAAA;AAAA,IACL,KAAK,IAAA;AACH,MAAA,OAAA,CAAQ,IAAI,OAAO,CAAA;AACnB,MAAA;AAAA,IACF,KAAK,MAAA;AAAA,IACL,KAAK,MAAA;AAAA,IACL,KAAK,QAAA;AAAA,IACL,KAAK,IAAA;AACH,MAAA,OAAO,IAAA,EAAK;AAAA,IACd;AACE,MAAA,IAAA,CAAK,CAAA,iBAAA,EAAoB,OAAO,CAAA,EAAA,CAAA,EAAM,4CAA4C,CAAA;AAAA;AAExF;AAEA,IAAA,EAAK","file":"cli.js","sourcesContent":["import { existsSync, readFileSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\n\n/**\n * Project detection.\n *\n * The CLI needs to know which framework it is generating for, whether the project uses TypeScript,\n * and where components live. Asking the user all of that on every invocation is friction for\n * information that is sitting in `package.json` and on disk — so we detect it, and only prompt for\n * what we genuinely cannot infer.\n */\n\nexport type Framework = 'react' | 'vue' | 'nuxt' | 'next' | 'unknown'\n\nexport interface ProjectInfo {\n root: string\n framework: Framework\n typescript: boolean\n /** Where generated components should go, relative to `root`. */\n componentsDir: string\n /** Detected import alias for the source root, e.g. `'@/'`. `null` when none is configured. */\n alias: string | null\n packageManager: 'pnpm' | 'yarn' | 'npm' | 'bun'\n /** `true` when the relevant `@ansh-ui/*` package is already a dependency. */\n installed: boolean\n}\n\n/** Walk up from `cwd` looking for a `package.json`, so the CLI works from a subdirectory. */\nfunction findRoot(cwd: string): string {\n let current = resolve(cwd)\n for (let depth = 0; depth < 10; depth++) {\n if (existsSync(join(current, 'package.json'))) return current\n const parent = resolve(current, '..')\n if (parent === current) break\n current = parent\n }\n return resolve(cwd)\n}\n\nfunction readJson(path: string): Record<string, unknown> | null {\n try {\n return JSON.parse(readFileSync(path, 'utf8')) as Record<string, unknown>\n } catch {\n return null\n }\n}\n\nexport function detectProject(cwd = process.cwd()): ProjectInfo {\n const root = findRoot(cwd)\n const pkg = readJson(join(root, 'package.json')) ?? {}\n\n const deps: Record<string, string> = {\n ...((pkg.dependencies as Record<string, string>) ?? {}),\n ...((pkg.devDependencies as Record<string, string>) ?? {}),\n }\n\n // Order matters: Nuxt projects also depend on Vue, and Next projects on React. Checking the\n // meta-framework first gives the more specific — and more useful — answer.\n const framework: Framework = deps.nuxt\n ? 'nuxt'\n : deps.next\n ? 'next'\n : deps.vue\n ? 'vue'\n : deps.react\n ? 'react'\n : 'unknown'\n\n const typescript = Boolean(deps.typescript) || existsSync(join(root, 'tsconfig.json'))\n\n const packageManager: ProjectInfo['packageManager'] = existsSync(join(root, 'pnpm-lock.yaml'))\n ? 'pnpm'\n : existsSync(join(root, 'bun.lockb')) || existsSync(join(root, 'bun.lock'))\n ? 'bun'\n : existsSync(join(root, 'yarn.lock'))\n ? 'yarn'\n : 'npm'\n\n return {\n root,\n framework,\n typescript,\n componentsDir: detectComponentsDir(root, framework),\n alias: detectAlias(root),\n packageManager,\n installed: Boolean(\n deps['@ansh-ui/react'] ||\n deps['@ansh-ui/vue'] ||\n deps['@ansh-ui/nuxt'] ||\n deps['@ansh-ui/core'],\n ),\n }\n}\n\n/**\n * Find where components already live, rather than imposing a convention.\n *\n * Dropping a file into `src/components` in a project that uses `app/ui` is the kind of small\n * disrespect that makes a tool feel foreign. Candidates are ordered by how strong a signal they are.\n */\nfunction detectComponentsDir(root: string, framework: Framework): string {\n const candidates =\n framework === 'nuxt'\n ? ['components', 'app/components', 'src/components']\n : ['src/components', 'components', 'app/components', 'src/lib/components', 'app/ui', 'src/ui']\n\n for (const candidate of candidates) {\n if (existsSync(join(root, candidate))) return candidate\n }\n\n // Nothing exists yet: pick the convention that matches the project's existing shape.\n if (existsSync(join(root, 'src'))) return 'src/components'\n if (framework === 'nuxt') return 'components'\n return 'components'\n}\n\n/**\n * Read the source alias from `tsconfig.json` so generated imports match the project's style.\n *\n * A generated file that writes `../../lib/utils` in a project where everything else says\n * `@/lib/utils` is immediately identifiable as machine-written.\n */\nfunction detectAlias(root: string): string | null {\n for (const file of ['tsconfig.json', 'jsconfig.json']) {\n const config = readJson(join(root, file))\n if (!config) continue\n\n const compilerOptions = config.compilerOptions as Record<string, unknown> | undefined\n const paths = compilerOptions?.paths as Record<string, string[]> | undefined\n if (!paths) continue\n\n for (const pattern of Object.keys(paths)) {\n // Match a plain wildcard alias like `\"@/*\"` or `\"~/*\"` — the overwhelmingly common shape.\n if (pattern.endsWith('/*')) return pattern.slice(0, -1)\n }\n }\n return null\n}\n\n/** The install command for the detected package manager. */\nexport function installCommand(info: ProjectInfo, packages: string[]): string {\n const list = packages.join(' ')\n switch (info.packageManager) {\n case 'pnpm':\n return `pnpm add ${list}`\n case 'yarn':\n return `yarn add ${list}`\n case 'bun':\n return `bun add ${list}`\n default:\n return `npm install ${list}`\n }\n}\n","import { behaviours, effects } from '@ansh-ui/core'\n\n/**\n * Catalogue enumeration.\n *\n * Reads the registry rather than a hardcoded list, so a new effect appears in `ansh list` the\n * moment it is defined — no second place to update, and no possibility of the CLI advertising\n * something that doesn't exist or omitting something that does.\n */\n\nexport interface CatalogueEntry {\n name: string\n kind: 'effect' | 'behaviour'\n /** The component name in `@ansh-ui/react` and `@ansh-ui/vue`. */\n component: string\n /** Every option, with its default value, read from the definition. */\n options: Array<{ name: string; default: unknown }>\n}\n\n/**\n * Effect and behaviour names map to component names that read better than a mechanical\n * transformation would produce — `meteors` → `MeteorShower`, `blob` → `LiquidBlob`. Where a\n * definition isn't listed here, the name is PascalCased.\n */\nconst COMPONENT_NAMES: Record<string, string> = {\n aurora: 'AuroraBackground',\n 'mesh-gradient': 'MeshGradient',\n 'animated-gradient': 'AnimatedGradient',\n 'particle-field': 'ParticleField',\n constellation: 'Constellation',\n meteors: 'MeteorShower',\n rain: 'Rain',\n snow: 'Snow',\n fireflies: 'Fireflies',\n waves: 'Waves',\n blob: 'LiquidBlob',\n 'noise-layer': 'NoiseLayer',\n spotlight: 'Spotlight',\n magnetic: 'MagneticButton',\n tilt: 'TiltCard',\n ripple: 'Ripple',\n marquee: 'Marquee',\n 'scroll-reveal': 'ScrollReveal',\n parallax: 'Parallax',\n 'split-text': 'SplitText',\n}\n\nexport function componentNameFor(name: string): string {\n return (\n COMPONENT_NAMES[name] ??\n name.replace(/(^|-)([a-z])/g, (_, __, letter: string) => letter.toUpperCase())\n )\n}\n\nexport function listCatalogue(filter?: 'effect' | 'behaviour'): CatalogueEntry[] {\n const entries: CatalogueEntry[] = []\n\n if (filter !== 'behaviour') {\n for (const [name, definition] of Object.entries(effects)) {\n entries.push({\n name,\n kind: 'effect',\n component: componentNameFor(name),\n options: describeOptions(definition.defaults as Record<string, unknown>),\n })\n }\n }\n\n if (filter !== 'effect') {\n for (const [name, definition] of Object.entries(behaviours)) {\n entries.push({\n name,\n kind: 'behaviour',\n component: componentNameFor(name),\n options: describeOptions(definition.defaults as Record<string, unknown>),\n })\n }\n }\n\n return entries.sort((a, b) => a.name.localeCompare(b.name))\n}\n\n/**\n * Turn a `defaults` object into a documented option list.\n *\n * This is why {@link import('@ansh-ui/core').EffectDefinition}'s `defaults` is typed\n * `Required<Options>`: it makes \"every option has a documented default\" a compile-time guarantee,\n * which in turn makes this function complete by construction rather than by diligence.\n */\nfunction describeOptions(defaults: Record<string, unknown>): CatalogueEntry['options'] {\n return Object.entries(defaults)\n .map(([name, value]) => ({ name, default: value }))\n .sort((a, b) => a.name.localeCompare(b.name))\n}\n\n/** Look up a single entry by effect/behaviour name or by component name, case-insensitively. */\nexport function findEntry(query: string): CatalogueEntry | undefined {\n const needle = query.toLowerCase()\n return listCatalogue().find(\n (entry) => entry.name.toLowerCase() === needle || entry.component.toLowerCase() === needle,\n )\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { type ProjectInfo, detectProject } from '../project'\nimport { findEntry } from './list'\n\n/**\n * `ansh add <name>` — generate a local, editable wrapper for a component.\n *\n * ## Why a wrapper rather than a source copy\n *\n * shadcn/ui popularised copying component source into the project, and for *unstyled primitives*\n * that is exactly right: the value is in the markup and the styling, and you want to own both.\n *\n * Ansh is a different shape. The value is in the engine — an 800-line curl-noise particle system,\n * a spring solver, a colour pipeline — and copying that into an application would be actively\n * harmful: it would never receive a bug fix, and it would bloat the repository with code nobody on\n * the team intends to maintain.\n *\n * What developers actually want to own is the **configuration**: which colours, what intensity, what\n * it is called in their design system. So that is what this generates — a thin, fully-typed local\n * component with the project's own defaults baked in, importing the engine from the package.\n *\n * The result: `<HeroBackground />` in application code, one file to edit when the brand palette\n * changes, and engine fixes arrive through a normal dependency upgrade.\n */\n\nexport interface AddOptions {\n /** Effect or behaviour name, or component name. Case-insensitive. */\n name: string\n /** Local component name. Defaults to the catalogue's component name. */\n as?: string\n /** Target directory, relative to the project root. Defaults to the detected components dir. */\n dir?: string\n /** Overwrite an existing file. Default `false`. */\n force?: boolean\n /** Print the file instead of writing it. Default `false`. */\n dryRun?: boolean\n cwd?: string\n}\n\nexport interface AddResult {\n path: string\n contents: string\n written: boolean\n /** Packages the project needs but doesn't have. */\n missingDependencies: string[]\n}\n\nexport function addComponent(options: AddOptions): AddResult {\n const project = detectProject(options.cwd)\n const entry = findEntry(options.name)\n\n if (!entry) {\n throw new Error(\n `Unknown component \"${options.name}\". Run \\`ansh list\\` to see what's available.`,\n )\n }\n\n if (project.framework === 'unknown') {\n throw new Error(\n 'Could not detect a React, Next, Vue or Nuxt project. ' +\n 'Run this from your project root, or install the framework first.',\n )\n }\n\n const isVue = project.framework === 'vue' || project.framework === 'nuxt'\n const componentName = options.as ?? entry.component\n const extension = isVue ? 'vue' : project.typescript ? 'tsx' : 'jsx'\n\n const directory = options.dir ?? project.componentsDir\n const path = join(project.root, directory, `${componentName}.${extension}`)\n\n const contents = isVue\n ? renderVue(componentName, entry.component, entry.options, project)\n : renderReact(componentName, entry.component, entry.options, project)\n\n const missingDependencies = missingFor(project)\n\n if (options.dryRun) {\n return { path, contents, written: false, missingDependencies }\n }\n\n if (existsSync(path) && !options.force) {\n throw new Error(`${path} already exists. Pass --force to overwrite.`)\n }\n\n mkdirSync(dirname(path), { recursive: true })\n writeFileSync(path, contents, 'utf8')\n\n return { path, contents, written: true, missingDependencies }\n}\n\nfunction missingFor(project: ProjectInfo): string[] {\n if (project.installed) return []\n switch (project.framework) {\n case 'nuxt':\n return ['@ansh-ui/nuxt']\n case 'vue':\n return ['@ansh-ui/vue', '@ansh-ui/tokens']\n default:\n return ['@ansh-ui/react', '@ansh-ui/tokens']\n }\n}\n\n/**\n * Serialise a default value as source.\n *\n * Only the options worth surfacing are emitted — see {@link INTERESTING_OPTIONS}. Emitting all\n * twenty would produce a wall of noise that obscures the three an author will actually change.\n */\nfunction literal(value: unknown): string {\n if (typeof value === 'string') return JSON.stringify(value)\n if (Array.isArray(value)) return `[${value.map(literal).join(', ')}]`\n if (value === null) return 'null'\n if (typeof value === 'object') return JSON.stringify(value)\n return String(value)\n}\n\n/**\n * Options included in generated source.\n *\n * These are the ones that carry design intent — the knobs a designer asks to change. Structural and\n * performance options are omitted from the generated defaults but remain available as props, since\n * the wrapper spreads everything through.\n */\nconst INTERESTING_OPTIONS = new Set([\n 'colors',\n 'speed',\n 'intensity',\n 'opacity',\n 'blur',\n 'seed',\n 'strength',\n 'radius',\n 'max',\n 'distance',\n 'amount',\n 'count',\n])\n\nfunction pickDefaults(options: Array<{ name: string; default: unknown }>) {\n return options.filter((option) => INTERESTING_OPTIONS.has(option.name))\n}\n\nfunction renderReact(\n componentName: string,\n sourceComponent: string,\n options: Array<{ name: string; default: unknown }>,\n project: ProjectInfo,\n): string {\n const ts = project.typescript\n const defaults = pickDefaults(options)\n\n const defaultLines = defaults\n .map((option) => ` ${option.name}: ${literal(option.default)},`)\n .join('\\n')\n\n const propsType = ts\n ? `\\ntype ${componentName}Props = ComponentProps<typeof ${sourceComponent}>\\n`\n : ''\n\n const signature = ts\n ? `export function ${componentName}({ children, ...props }: ${componentName}Props) {`\n : `export function ${componentName}({ children, ...props }) {`\n\n const typeImport = ts ? `import type { ComponentProps } from 'react'\\n` : ''\n\n return `${typeImport}import { ${sourceComponent} } from '@ansh-ui/react'\n\n/**\n * ${componentName} — a project-local wrapper around Ansh's ${sourceComponent}.\n *\n * Edit the defaults below to match your design system. Every option remains overridable per\n * instance, because props spread after the defaults.\n *\n * Generated by \\`ansh add\\`. Safe to edit — it will not be regenerated unless you ask.\n */\nconst defaults = {\n${defaultLines}\n}\n\n${propsType}\n${signature}\n return (\n <${sourceComponent} {...defaults} {...props}>\n {children}\n </${sourceComponent}>\n )\n}\n`\n}\n\nfunction renderVue(\n componentName: string,\n sourceComponent: string,\n options: Array<{ name: string; default: unknown }>,\n project: ProjectInfo,\n): string {\n const defaults = pickDefaults(options)\n const defaultLines = defaults\n .map((option) => ` ${option.name}: ${literal(option.default)},`)\n .join('\\n')\n\n const lang = project.typescript ? ' lang=\"ts\"' : ''\n\n // Nuxt auto-imports Ansh components, so an explicit import there would be redundant — and\n // would shadow the auto-import in a way that breaks if the module's prefix option changes.\n const importLine =\n project.framework === 'nuxt'\n ? `// ${sourceComponent} is auto-imported by @ansh-ui/nuxt.`\n : `import { ${sourceComponent} } from '@ansh-ui/vue'`\n\n return `<script setup${lang}>\n${importLine}\n\n/**\n * ${componentName} — a project-local wrapper around Ansh's ${sourceComponent}.\n *\n * Edit the defaults below to match your design system. Every option remains overridable per\n * instance, because \\`$attrs\\` is bound after the defaults.\n *\n * Generated by \\`ansh add\\`. Safe to edit — it will not be regenerated unless you ask.\n */\nconst defaults = {\n${defaultLines}\n}\n</script>\n\n<template>\n <${sourceComponent} v-bind=\"{ ...defaults, ...$attrs }\">\n <slot />\n </${sourceComponent}>\n</template>\n`\n}\n","import {\n createGradient,\n generatePalette,\n parseColor,\n perceivedLightness,\n rgbToOklch,\n toHex,\n toOklchString,\n} from '@ansh-ui/core'\n\n/**\n * `ansh palette` — generate and inspect palettes.\n *\n * Two modes:\n *\n * - **Generate** — a seeded palette from scratch. The same seed always produces the same palette,\n * so a designer who likes seed 4821 can pin it and get that palette back next week.\n * - **Inspect** — report a supplied palette's OKLCH decomposition and the gradient it produces.\n * The useful part is seeing the *interpolated midpoints*: a palette can look fine as swatches and\n * produce a muddy gradient, and this shows that before it ships.\n */\n\nexport interface PaletteReportOptions {\n /** Colours to inspect. Generates a new palette when omitted. */\n colors?: string[]\n /** Number of colours to generate. Default `5`. */\n count?: number\n seed?: number | string\n /** Overall lightness in `[0, 1]`. Default `0.65`. */\n lightness?: number\n /** Chroma as a fraction of the maximum available. Default `0.85`. */\n saturation?: number\n /** Hue span in degrees. Default `120`. */\n spread?: number\n /** Also print interpolated gradient midpoints. Default `true`. */\n gradient?: boolean\n}\n\nexport interface PaletteReport {\n colors: Array<{ hex: string; oklch: string; lightness: number; chroma: number; hue: number }>\n /** Interpolated samples across the palette, showing what a gradient through it looks like. */\n gradientSamples: string[]\n /** Copy-pasteable literal for a `colors` prop. */\n snippet: string\n}\n\nexport function generatePaletteReport(options: PaletteReportOptions = {}): PaletteReport {\n const parsed =\n options.colors && options.colors.length > 0\n ? options.colors.map((color) => parseColor(color))\n : generatePalette({\n count: options.count ?? 5,\n seed: options.seed ?? 1,\n lightness: options.lightness ?? 0.65,\n saturation: options.saturation ?? 0.85,\n spread: options.spread ?? 120,\n })\n\n const colors = parsed.map((color) => {\n const lch = rgbToOklch(color)\n return {\n hex: toHex(color),\n oklch: toOklchString(color),\n lightness: Number(lch.l.toFixed(4)),\n chroma: Number(lch.c.toFixed(4)),\n hue: Number(lch.h.toFixed(2)),\n }\n })\n\n // Sampled in OKLCH rather than OKLab: for a gradient *through a palette* the goal is maximum\n // vividness across the transitions, which is what travelling the hue circle gives.\n const gradientSamples =\n options.gradient === false || parsed.length < 2\n ? []\n : createGradient(parsed, { space: 'oklch' })\n .sample(9)\n .map((color) => toHex(color))\n\n const snippet = `colors={[${colors.map((c) => `'${c.hex}'`).join(', ')}]}`\n\n return { colors, gradientSamples, snippet }\n}\n\n/**\n * Sort a palette by perceived lightness and report the ordering.\n *\n * Useful for layered effects, where the draw order should generally run dark to light so brighter\n * colours land on top and read as nearer.\n */\nexport function orderByLightness(colors: string[]): Array<{ hex: string; lightness: number }> {\n return colors\n .map((color) => ({ hex: toHex(parseColor(color)), lightness: perceivedLightness(color) }))\n .sort((a, b) => a.lightness - b.lightness)\n}\n","import { mkdirSync, writeFileSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport {\n checkContrast,\n createScale,\n harmony,\n parseColor,\n rgbToOklch,\n toHex,\n toOklchString,\n} from '@ansh-ui/core'\n\n/**\n * `ansh theme <color>` — generate a token override stylesheet from a brand colour.\n *\n * The job this does that hand-authoring doesn't: it **checks the result**. An 11-step scale\n * generated from a brand colour will, for certain hues, produce steps that fail contrast against\n * white or against each other — a saturated yellow at step 600 is a classic offender. Generating the\n * scale is easy; noticing that step 600 can't legally hold body text is the part people skip.\n *\n * So the emitted stylesheet carries contrast annotations as comments, and the report flags any step\n * that cannot be used for text.\n */\n\nexport interface ThemeOptions {\n /** Brand colour in any CSS syntax. */\n color: string\n /** Where to write the stylesheet. Prints to stdout when omitted. */\n out?: string\n /** Hue drift across the scale, in degrees. `0` keeps a single hue. Default `0`. */\n hueShift?: number\n /** Chroma falloff at the extremes, in `[0, 1]`. Default `0.35`. */\n chromaFalloff?: number\n /** Also emit a harmonious accent scale. Default `false`. */\n withAccent?: boolean\n}\n\nexport interface ThemeReport {\n css: string\n /** Steps whose contrast against white is below 4.5:1 — unusable for body text on light surfaces. */\n unsafeOnLight: string[]\n /** Steps whose contrast against near-black is below 4.5:1. */\n unsafeOnDark: string[]\n /** The step closest in lightness to the input colour. */\n nearestStep: string\n}\n\nconst TAILWIND_KEYS = ['50', '100', '200', '300', '400', '500', '600', '700', '800', '900', '950']\n\nexport function generateTheme(options: ThemeOptions): ThemeReport {\n const base = parseColor(options.color)\n const baseLightness = rgbToOklch(base).l\n\n const scale = createScale(base, {\n steps: 11,\n hueShift: options.hueShift ?? 0,\n chromaFalloff: options.chromaFalloff ?? 0.35,\n })\n\n const unsafeOnLight: string[] = []\n const unsafeOnDark: string[] = []\n\n const lines: string[] = []\n let nearestStep = '500'\n let nearestDistance = Infinity\n\n scale.colors.forEach((color, index) => {\n const key = TAILWIND_KEYS[index]\n const onLight = checkContrast(color, '#ffffff')\n const onDark = checkContrast(color, '#0b0b0f')\n\n if (!onLight.passes) unsafeOnLight.push(key)\n if (!onDark.passes) unsafeOnDark.push(key)\n\n const distance = Math.abs(rgbToOklch(color).l - baseLightness)\n if (distance < nearestDistance) {\n nearestDistance = distance\n nearestStep = key\n }\n\n // The comment carries the numbers, so a designer reviewing the file can see at a glance which\n // steps are safe for text without opening a contrast checker.\n lines.push(\n ` --ansh-brand-${key}: ${toOklchString(color)};` +\n ` /* ${toHex(color)} on-white ${onLight.ratio.toFixed(2)}:1` +\n ` on-black ${onDark.ratio.toFixed(2)}:1 */`,\n )\n })\n\n let accentLines = ''\n if (options.withAccent) {\n // A split-complementary partner: far enough from the brand hue to be clearly a different\n // colour, close enough to still look related. The straight complement is usually too harsh for\n // UI, which is why it isn't the default choice here.\n const [, accent] = harmony(base, 'splitComplementary')\n const accentScale = createScale(accent, { steps: 11 })\n accentLines =\n '\\n /* Accent — split-complementary partner to the brand hue. */\\n' +\n accentScale.colors\n .map((color, index) => ` --ansh-accent-${TAILWIND_KEYS[index]}: ${toOklchString(color)};`)\n .join('\\n') +\n '\\n'\n }\n\n const css = `/**\n * Ansh theme override.\n *\n * Generated by \\`ansh theme ${options.color}\\`.\n * Import this *after* \\`@ansh-ui/tokens/ansh.css\\` so it wins in the cascade.\n *\n * Contrast ratios are annotated per step. Steps marked unsafe cannot legally hold body text on the\n * corresponding surface — use them for fills, borders and large display type instead.\n */\n\n:root {\n${lines.join('\\n')}\n${accentLines}\n /* Wire the semantic accent tokens to the generated scale. */\n --ansh-accent-subtle: var(--ansh-brand-50);\n --ansh-accent-muted: var(--ansh-brand-100);\n --ansh-accent-default: var(--ansh-brand-600);\n --ansh-accent-hover: var(--ansh-brand-700);\n --ansh-accent-active: var(--ansh-brand-800);\n --ansh-accent-text: var(--ansh-brand-700);\n --ansh-border-focus: var(--ansh-brand-600);\n}\n\n/**\n * Dark theme.\n *\n * Not an inversion. Accents step *lighter* rather than mirroring their light-mode index, because\n * saturated colour reads as less vivid against a dark background (Helmholtz–Kohlrausch).\n */\n[data-theme='dark'] {\n --ansh-accent-subtle: color-mix(in oklab, var(--ansh-brand-950) 40%, transparent);\n --ansh-accent-muted: var(--ansh-brand-950);\n --ansh-accent-default: var(--ansh-brand-500);\n --ansh-accent-hover: var(--ansh-brand-400);\n --ansh-accent-active: var(--ansh-brand-300);\n --ansh-accent-text: var(--ansh-brand-300);\n --ansh-border-focus: var(--ansh-brand-400);\n}\n\n@media (prefers-color-scheme: dark) {\n :root:not([data-theme]) {\n --ansh-accent-subtle: color-mix(in oklab, var(--ansh-brand-950) 40%, transparent);\n --ansh-accent-muted: var(--ansh-brand-950);\n --ansh-accent-default: var(--ansh-brand-500);\n --ansh-accent-hover: var(--ansh-brand-400);\n --ansh-accent-active: var(--ansh-brand-300);\n --ansh-accent-text: var(--ansh-brand-300);\n --ansh-border-focus: var(--ansh-brand-400);\n }\n}\n`\n\n if (options.out) {\n mkdirSync(dirname(options.out), { recursive: true })\n writeFileSync(options.out, css, 'utf8')\n }\n\n return { css, unsafeOnLight, unsafeOnDark, nearestStep }\n}\n","import { parseArgs } from 'node:util'\nimport { addComponent } from './commands/add'\nimport { findEntry, listCatalogue } from './commands/list'\nimport { generatePaletteReport } from './commands/palette'\nimport { generateTheme } from './commands/theme'\nimport { detectProject, installCommand } from './project'\n\n/**\n * The Ansh CLI.\n *\n * Uses Node's built-in `parseArgs` rather than commander or yargs. A CLI is the one place where a\n * dependency is most visible to the user — it is what they wait for on `npx` — and this tool's\n * argument surface is small enough that 40 lines of dispatch beats a 200 KB install.\n *\n * Output is coloured only when stdout is a TTY and `NO_COLOR` is unset, so piping to a file or\n * running in CI produces clean text.\n */\n\nconst useColor = process.stdout.isTTY && !process.env.NO_COLOR\n\nconst paint = (code: string, text: string): string => (useColor ? `\u001b[${code}m${text}\u001b[0m` : text)\n\nconst bold = (text: string) => paint('1', text)\nconst dim = (text: string) => paint('2', text)\nconst cyan = (text: string) => paint('36', text)\nconst green = (text: string) => paint('32', text)\nconst yellow = (text: string) => paint('33', text)\nconst red = (text: string) => paint('31', text)\n\nconst VERSION = '0.1.0'\n\nfunction help(): void {\n console.log(`\n${bold('ansh')} ${dim(`v${VERSION}`)} — Motion, refined.\n\n${bold('USAGE')}\n ansh <command> [options]\n\n${bold('COMMANDS')}\n ${cyan('list')} [--effects|--behaviours] List the component catalogue\n ${cyan('info')} <name> Show a component's full option surface\n ${cyan('add')} <name> [--as <Name>] Generate a local wrapper component\n ${cyan('theme')} <color> [--out <file>] Generate a token override stylesheet\n ${cyan('palette')} [colors...] Generate or inspect a palette\n ${cyan('doctor')} Report the detected project setup\n\n${bold('EXAMPLES')}\n ${dim('# See what is available')}\n ansh list\n\n ${dim('# Generate a HeroBackground wrapper around the aurora effect')}\n ansh add aurora --as HeroBackground\n\n ${dim('# Build a theme from a brand colour, with contrast annotations')}\n ansh theme '#0275f4' --out src/styles/theme.css --with-accent\n\n ${dim('# Inspect how a palette interpolates')}\n ansh palette '#0275f4' '#9f0550'\n\n ${dim('# Reproducible generated palette')}\n ansh palette --count 5 --seed hero-section\n`)\n}\n\nfunction fail(message: string, hint?: string): never {\n console.error(`${red('error')} ${message}`)\n if (hint) console.error(`${dim('hint')} ${hint}`)\n process.exit(1)\n}\n\n// ---------------------------------------------------------------------------\n// Commands\n// ---------------------------------------------------------------------------\n\nfunction commandList(argv: string[]): void {\n const { values } = parseArgs({\n args: argv,\n options: {\n effects: { type: 'boolean', default: false },\n behaviours: { type: 'boolean', default: false },\n json: { type: 'boolean', default: false },\n },\n allowPositionals: true,\n })\n\n const filter = values.effects ? 'effect' : values.behaviours ? 'behaviour' : undefined\n const entries = listCatalogue(filter)\n\n if (values.json) {\n console.log(JSON.stringify(entries, null, 2))\n return\n }\n\n const effects = entries.filter((entry) => entry.kind === 'effect')\n const behaviours = entries.filter((entry) => entry.kind === 'behaviour')\n\n const print = (title: string, list: typeof entries) => {\n if (list.length === 0) return\n console.log(`\\n${bold(title)}`)\n for (const entry of list) {\n console.log(\n ` ${cyan(entry.name.padEnd(20))} ${entry.component.padEnd(20)} ` +\n dim(`${entry.options.length} options`),\n )\n }\n }\n\n print(`Effects ${dim('(canvas)')}`, effects)\n print(`Behaviours ${dim('(DOM)')}`, behaviours)\n console.log(`\\n${dim(`${entries.length} total. Run \\`ansh info <name>\\` for details.`)}\\n`)\n}\n\nfunction commandInfo(argv: string[]): void {\n const name = argv[0]\n if (!name) fail('Missing component name.', 'ansh info aurora')\n\n const entry = findEntry(name)\n if (!entry) fail(`Unknown component \"${name}\".`, 'Run `ansh list` to see what is available.')\n\n console.log(`\\n${bold(entry.component)} ${dim(`(${entry.kind} \"${entry.name}\")`)}\\n`)\n console.log(bold(' OPTIONS'))\n\n const width = Math.max(...entry.options.map((option) => option.name.length))\n for (const option of entry.options) {\n const value =\n typeof option.default === 'string'\n ? `'${option.default}'`\n : Array.isArray(option.default)\n ? `[${option.default.map((v) => (typeof v === 'string' ? `'${v}'` : String(v))).join(', ')}]`\n : String(option.default)\n console.log(` ${option.name.padEnd(width)} ${dim('=')} ${green(value)}`)\n }\n\n console.log(\n `\\n${dim(` Docs: https://ansh.dev/docs/components/${entry.name}`)}\\n` +\n `${dim(` Add: ansh add ${entry.name}`)}\\n`,\n )\n}\n\nfunction commandAdd(argv: string[]): void {\n const { values, positionals } = parseArgs({\n args: argv,\n options: {\n as: { type: 'string' },\n dir: { type: 'string' },\n force: { type: 'boolean', default: false },\n 'dry-run': { type: 'boolean', default: false },\n },\n allowPositionals: true,\n })\n\n const name = positionals[0]\n if (!name) fail('Missing component name.', 'ansh add aurora --as HeroBackground')\n\n try {\n const result = addComponent({\n name,\n as: values.as,\n dir: values.dir,\n force: values.force,\n dryRun: values['dry-run'],\n })\n\n if (!result.written) {\n console.log(`${dim(`--- ${result.path} ---`)}\\n`)\n console.log(result.contents)\n return\n }\n\n console.log(`${green('created')} ${result.path}`)\n\n if (result.missingDependencies.length > 0) {\n const project = detectProject()\n console.log(\n `\\n${yellow('next')} Install the runtime packages:\\n` +\n ` ${installCommand(project, result.missingDependencies)}`,\n )\n }\n } catch (error) {\n fail(error instanceof Error ? error.message : String(error))\n }\n}\n\nfunction commandTheme(argv: string[]): void {\n const { values, positionals } = parseArgs({\n args: argv,\n options: {\n out: { type: 'string' },\n 'hue-shift': { type: 'string' },\n 'chroma-falloff': { type: 'string' },\n 'with-accent': { type: 'boolean', default: false },\n },\n allowPositionals: true,\n })\n\n const color = positionals[0]\n if (!color) fail('Missing brand colour.', \"ansh theme '#0275f4' --out theme.css\")\n\n try {\n const report = generateTheme({\n color,\n out: values.out,\n hueShift: values['hue-shift'] ? Number(values['hue-shift']) : undefined,\n chromaFalloff: values['chroma-falloff'] ? Number(values['chroma-falloff']) : undefined,\n withAccent: values['with-accent'],\n })\n\n if (!values.out) {\n console.log(report.css)\n return\n }\n\n console.log(`${green('created')} ${values.out}`)\n console.log(`${dim('nearest')} your input is closest to step ${report.nearestStep}`)\n\n // Surfacing this is the point of the command. A generated scale that silently fails contrast is\n // worse than no generated scale, because it looks authoritative.\n if (report.unsafeOnLight.length > 0) {\n console.log(\n `${yellow('warn')} steps ${report.unsafeOnLight.join(', ')} are below 4.5:1 on white — ` +\n `use them for fills and borders, not body text`,\n )\n }\n if (report.unsafeOnDark.length > 0) {\n console.log(\n `${yellow('warn')} steps ${report.unsafeOnDark.join(', ')} are below 4.5:1 on near-black`,\n )\n }\n } catch (error) {\n fail(error instanceof Error ? error.message : String(error))\n }\n}\n\nfunction commandPalette(argv: string[]): void {\n const { values, positionals } = parseArgs({\n args: argv,\n options: {\n count: { type: 'string' },\n seed: { type: 'string' },\n lightness: { type: 'string' },\n saturation: { type: 'string' },\n spread: { type: 'string' },\n json: { type: 'boolean', default: false },\n },\n allowPositionals: true,\n })\n\n try {\n const report = generatePaletteReport({\n colors: positionals.length > 0 ? positionals : undefined,\n count: values.count ? Number(values.count) : undefined,\n seed: values.seed,\n lightness: values.lightness ? Number(values.lightness) : undefined,\n saturation: values.saturation ? Number(values.saturation) : undefined,\n spread: values.spread ? Number(values.spread) : undefined,\n })\n\n if (values.json) {\n console.log(JSON.stringify(report, null, 2))\n return\n }\n\n console.log(`\\n${bold('PALETTE')}\\n`)\n for (const color of report.colors) {\n console.log(\n ` ${swatch(color.hex)} ${color.hex.padEnd(9)} ${dim(color.oklch.padEnd(28))} ` +\n dim(\n `L ${color.lightness.toFixed(3)} C ${color.chroma.toFixed(3)} H ${color.hue.toFixed(1)}`,\n ),\n )\n }\n\n if (report.gradientSamples.length > 0) {\n console.log(`\\n${bold('GRADIENT')} ${dim('(OKLCH interpolation)')}\\n`)\n console.log(' ' + report.gradientSamples.map((hex) => swatch(hex)).join(''))\n console.log(' ' + dim(report.gradientSamples.join(' ')))\n }\n\n console.log(`\\n${bold('SNIPPET')}\\n\\n ${green(report.snippet)}\\n`)\n } catch (error) {\n fail(error instanceof Error ? error.message : String(error))\n }\n}\n\nfunction commandDoctor(): void {\n const project = detectProject()\n\n console.log(`\\n${bold('PROJECT')}\\n`)\n console.log(` root ${project.root}`)\n console.log(\n ` framework ${project.framework === 'unknown' ? yellow('not detected') : green(project.framework)}`,\n )\n console.log(` typescript ${project.typescript ? green('yes') : dim('no')}`)\n console.log(` package manager ${project.packageManager}`)\n console.log(` components dir ${project.componentsDir}`)\n console.log(` import alias ${project.alias ?? dim('none')}`)\n console.log(` ansh ${project.installed ? green('installed') : yellow('not installed')}`)\n\n if (!project.installed) {\n const packages =\n project.framework === 'nuxt'\n ? ['@ansh-ui/nuxt']\n : project.framework === 'vue'\n ? ['@ansh-ui/vue', '@ansh-ui/tokens']\n : ['@ansh-ui/react', '@ansh-ui/tokens']\n console.log(`\\n${yellow('next')} ${installCommand(project, packages)}\\n`)\n } else {\n console.log('')\n }\n}\n\n/** A coloured block for terminal swatches. Falls back to a filled square without colour support. */\nfunction swatch(hex: string): string {\n if (!useColor) return '■'\n const r = parseInt(hex.slice(1, 3), 16)\n const g = parseInt(hex.slice(3, 5), 16)\n const b = parseInt(hex.slice(5, 7), 16)\n return `\u001b[48;2;${r};${g};${b}m \u001b[0m`\n}\n\n// ---------------------------------------------------------------------------\n// Dispatch\n// ---------------------------------------------------------------------------\n\nfunction main(): void {\n const [command, ...rest] = process.argv.slice(2)\n\n switch (command) {\n case 'list':\n case 'ls':\n return commandList(rest)\n case 'info':\n case 'show':\n return commandInfo(rest)\n case 'add':\n return commandAdd(rest)\n case 'theme':\n return commandTheme(rest)\n case 'palette':\n return commandPalette(rest)\n case 'doctor':\n return commandDoctor()\n case '--version':\n case '-v':\n console.log(VERSION)\n return\n case undefined:\n case 'help':\n case '--help':\n case '-h':\n return help()\n default:\n fail(`Unknown command \"${command}\".`, 'Run `ansh help` to see available commands.')\n }\n}\n\nmain()\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/project.ts","../src/commands/list.ts","../src/commands/add.ts","../src/commands/palette.ts","../src/commands/theme.ts","../src/cli.ts"],"names":["join","existsSync","parseColor","rgbToOklch","toOklchString","toHex","mkdirSync","dirname","writeFileSync","readFileSync","effects","behaviours"],"mappings":"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","file":"cli.js","sourcesContent":["import { existsSync, readFileSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\n\n/**\n * Project detection.\n *\n * The CLI needs to know which framework it is generating for, whether the project uses TypeScript,\n * and where components live. Asking the user all of that on every invocation is friction for\n * information that is sitting in `package.json` and on disk — so we detect it, and only prompt for\n * what we genuinely cannot infer.\n */\n\nexport type Framework = 'react' | 'vue' | 'nuxt' | 'next' | 'unknown'\n\nexport interface ProjectInfo {\n root: string\n framework: Framework\n typescript: boolean\n /** Where generated components should go, relative to `root`. */\n componentsDir: string\n /** Detected import alias for the source root, e.g. `'@/'`. `null` when none is configured. */\n alias: string | null\n packageManager: 'pnpm' | 'yarn' | 'npm' | 'bun'\n /** `true` when the relevant `@ansh-ui/*` package is already a dependency. */\n installed: boolean\n}\n\n/** Walk up from `cwd` looking for a `package.json`, so the CLI works from a subdirectory. */\nfunction findRoot(cwd: string): string {\n let current = resolve(cwd)\n for (let depth = 0; depth < 10; depth++) {\n if (existsSync(join(current, 'package.json'))) return current\n const parent = resolve(current, '..')\n if (parent === current) break\n current = parent\n }\n return resolve(cwd)\n}\n\nfunction readJson(path: string): Record<string, unknown> | null {\n try {\n return JSON.parse(readFileSync(path, 'utf8')) as Record<string, unknown>\n } catch {\n return null\n }\n}\n\nexport function detectProject(cwd = process.cwd()): ProjectInfo {\n const root = findRoot(cwd)\n const pkg = readJson(join(root, 'package.json')) ?? {}\n\n const deps: Record<string, string> = {\n ...((pkg.dependencies as Record<string, string>) ?? {}),\n ...((pkg.devDependencies as Record<string, string>) ?? {}),\n }\n\n // Order matters: Nuxt projects also depend on Vue, and Next projects on React. Checking the\n // meta-framework first gives the more specific — and more useful — answer.\n const framework: Framework = deps.nuxt\n ? 'nuxt'\n : deps.next\n ? 'next'\n : deps.vue\n ? 'vue'\n : deps.react\n ? 'react'\n : 'unknown'\n\n const typescript = Boolean(deps.typescript) || existsSync(join(root, 'tsconfig.json'))\n\n const packageManager: ProjectInfo['packageManager'] = existsSync(join(root, 'pnpm-lock.yaml'))\n ? 'pnpm'\n : existsSync(join(root, 'bun.lockb')) || existsSync(join(root, 'bun.lock'))\n ? 'bun'\n : existsSync(join(root, 'yarn.lock'))\n ? 'yarn'\n : 'npm'\n\n return {\n root,\n framework,\n typescript,\n componentsDir: detectComponentsDir(root, framework),\n alias: detectAlias(root),\n packageManager,\n installed: Boolean(\n deps['@ansh-ui/react'] ||\n deps['@ansh-ui/vue'] ||\n deps['@ansh-ui/nuxt'] ||\n deps['@ansh-ui/core'],\n ),\n }\n}\n\n/**\n * Find where components already live, rather than imposing a convention.\n *\n * Dropping a file into `src/components` in a project that uses `app/ui` is the kind of small\n * disrespect that makes a tool feel foreign. Candidates are ordered by how strong a signal they are.\n */\nfunction detectComponentsDir(root: string, framework: Framework): string {\n const candidates =\n framework === 'nuxt'\n ? ['components', 'app/components', 'src/components']\n : ['src/components', 'components', 'app/components', 'src/lib/components', 'app/ui', 'src/ui']\n\n for (const candidate of candidates) {\n if (existsSync(join(root, candidate))) return candidate\n }\n\n // Nothing exists yet: pick the convention that matches the project's existing shape.\n if (existsSync(join(root, 'src'))) return 'src/components'\n if (framework === 'nuxt') return 'components'\n return 'components'\n}\n\n/**\n * Read the source alias from `tsconfig.json` so generated imports match the project's style.\n *\n * A generated file that writes `../../lib/utils` in a project where everything else says\n * `@/lib/utils` is immediately identifiable as machine-written.\n */\nfunction detectAlias(root: string): string | null {\n for (const file of ['tsconfig.json', 'jsconfig.json']) {\n const config = readJson(join(root, file))\n if (!config) continue\n\n const compilerOptions = config.compilerOptions as Record<string, unknown> | undefined\n const paths = compilerOptions?.paths as Record<string, string[]> | undefined\n if (!paths) continue\n\n for (const pattern of Object.keys(paths)) {\n // Match a plain wildcard alias like `\"@/*\"` or `\"~/*\"` — the overwhelmingly common shape.\n if (pattern.endsWith('/*')) return pattern.slice(0, -1)\n }\n }\n return null\n}\n\nexport interface KnownInconsistency {\n title: string\n detail: string\n}\n\n/**\n * Maintainer-facing issues logged in `docs/STATUS.md` §7 — restated here so a contributor\n * discovers them from `ansh doctor` output, not by reading a markdown file they may not know\n * exists. Kept in sync with STATUS.md by hand: this list should shrink exactly when that section\n * does, and for the same reason (the item was resolved), not because someone forgot one file.\n */\nconst KNOWN_INCONSISTENCIES: KnownInconsistency[] = [\n {\n title: 'License key prefix is still `aur_`',\n detail:\n 'A leftover from the Aurelis → Ansh rename (packages/license/src/public-key.ts). Changing it ' +\n 'without a dual-prefix verification path would invalidate already-issued keys — needs a ' +\n 'maintainer decision, not a drive-by fix. See STATUS.md §7.',\n },\n]\n\n/**\n * `ansh doctor` runs against whatever project it's invoked in — almost always a consumer's app.\n * The one exception worth detecting is the Ansh monorepo itself: a contributor running the CLI\n * from within its own source tree should see the maintainer-facing known-inconsistencies list\n * (above), which is meaningless noise for every other project `doctor` will ever run in.\n */\nexport function isAnshRepoRoot(root: string): boolean {\n const pkg = readJson(join(root, 'package.json'))\n return pkg?.name === 'ansh' && existsSync(join(root, 'packages/license/src/index.ts'))\n}\n\nexport function detectKnownInconsistencies(root: string): KnownInconsistency[] {\n return isAnshRepoRoot(root) ? KNOWN_INCONSISTENCIES : []\n}\n\n/** The install command for the detected package manager. */\nexport function installCommand(info: ProjectInfo, packages: string[]): string {\n const list = packages.join(' ')\n switch (info.packageManager) {\n case 'pnpm':\n return `pnpm add ${list}`\n case 'yarn':\n return `yarn add ${list}`\n case 'bun':\n return `bun add ${list}`\n default:\n return `npm install ${list}`\n }\n}\n","import { behaviours, effects } from '@ansh-ui/core'\n\n/**\n * Catalogue enumeration.\n *\n * Reads the registry rather than a hardcoded list, so a new effect appears in `ansh list` the\n * moment it is defined — no second place to update, and no possibility of the CLI advertising\n * something that doesn't exist or omitting something that does.\n */\n\nexport interface CatalogueEntry {\n name: string\n kind: 'effect' | 'behaviour'\n /** The component name in `@ansh-ui/react` and `@ansh-ui/vue`. */\n component: string\n /** Every option, with its default value, read from the definition. */\n options: Array<{ name: string; default: unknown }>\n}\n\n/**\n * Effect and behaviour names map to component names that read better than a mechanical\n * transformation would produce — `meteors` → `MeteorShower`, `blob` → `LiquidBlob`. Where a\n * definition isn't listed here, the name is PascalCased.\n */\nconst COMPONENT_NAMES: Record<string, string> = {\n aurora: 'AuroraBackground',\n 'mesh-gradient': 'MeshGradient',\n 'animated-gradient': 'AnimatedGradient',\n 'particle-field': 'ParticleField',\n constellation: 'Constellation',\n meteors: 'MeteorShower',\n rain: 'Rain',\n snow: 'Snow',\n fireflies: 'Fireflies',\n waves: 'Waves',\n blob: 'LiquidBlob',\n 'noise-layer': 'NoiseLayer',\n spotlight: 'Spotlight',\n magnetic: 'MagneticButton',\n tilt: 'TiltCard',\n ripple: 'Ripple',\n marquee: 'Marquee',\n 'scroll-reveal': 'ScrollReveal',\n parallax: 'Parallax',\n 'text-scramble': 'ScrambleText',\n}\n\n/**\n * Behaviours with no component in either binding. `split-text` is a building block (`AnimatedText`\n * does its own split so the markup server-renders), so `ansh add split-text` would generate an\n * import of a component that doesn't exist. Leaving it out of the catalogue is the honest answer.\n */\nconst NO_COMPONENT = new Set(['split-text'])\n\nexport function componentNameFor(name: string): string {\n return (\n COMPONENT_NAMES[name] ??\n name.replace(/(^|-)([a-z])/g, (_, __, letter: string) => letter.toUpperCase())\n )\n}\n\nexport function listCatalogue(filter?: 'effect' | 'behaviour'): CatalogueEntry[] {\n const entries: CatalogueEntry[] = []\n\n if (filter !== 'behaviour') {\n for (const [name, definition] of Object.entries(effects)) {\n entries.push({\n name,\n kind: 'effect',\n component: componentNameFor(name),\n options: describeOptions(definition.defaults as Record<string, unknown>),\n })\n }\n }\n\n if (filter !== 'effect') {\n for (const [name, definition] of Object.entries(behaviours)) {\n if (NO_COMPONENT.has(name)) continue\n entries.push({\n name,\n kind: 'behaviour',\n component: componentNameFor(name),\n options: describeOptions(definition.defaults as Record<string, unknown>),\n })\n }\n }\n\n return entries.sort((a, b) => a.name.localeCompare(b.name))\n}\n\n/**\n * Turn a `defaults` object into a documented option list.\n *\n * This is why {@link import('@ansh-ui/core').EffectDefinition}'s `defaults` is typed\n * `Required<Options>`: it makes \"every option has a documented default\" a compile-time guarantee,\n * which in turn makes this function complete by construction rather than by diligence.\n */\nfunction describeOptions(defaults: Record<string, unknown>): CatalogueEntry['options'] {\n return Object.entries(defaults)\n .map(([name, value]) => ({ name, default: value }))\n .sort((a, b) => a.name.localeCompare(b.name))\n}\n\n/** Look up a single entry by effect/behaviour name or by component name, case-insensitively. */\nexport function findEntry(query: string): CatalogueEntry | undefined {\n const needle = query.toLowerCase()\n return listCatalogue().find(\n (entry) => entry.name.toLowerCase() === needle || entry.component.toLowerCase() === needle,\n )\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { type ProjectInfo, detectProject } from '../project'\nimport { findEntry } from './list'\n\n/**\n * `ansh add <name>` — generate a local, editable wrapper for a component.\n *\n * ## Why a wrapper rather than a source copy\n *\n * shadcn/ui popularised copying component source into the project, and for *unstyled primitives*\n * that is exactly right: the value is in the markup and the styling, and you want to own both.\n *\n * Ansh is a different shape. The value is in the engine — an 800-line curl-noise particle system,\n * a spring solver, a colour pipeline — and copying that into an application would be actively\n * harmful: it would never receive a bug fix, and it would bloat the repository with code nobody on\n * the team intends to maintain.\n *\n * What developers actually want to own is the **configuration**: which colours, what intensity, what\n * it is called in their design system. So that is what this generates — a thin, fully-typed local\n * component with the project's own defaults baked in, importing the engine from the package.\n *\n * The result: `<HeroBackground />` in application code, one file to edit when the brand palette\n * changes, and engine fixes arrive through a normal dependency upgrade.\n */\n\nexport interface AddOptions {\n /** Effect or behaviour name, or component name. Case-insensitive. */\n name: string\n /** Local component name. Defaults to the catalogue's component name. */\n as?: string\n /** Target directory, relative to the project root. Defaults to the detected components dir. */\n dir?: string\n /** Overwrite an existing file. Default `false`. */\n force?: boolean\n /** Print the file instead of writing it. Default `false`. */\n dryRun?: boolean\n cwd?: string\n}\n\nexport interface AddResult {\n path: string\n contents: string\n written: boolean\n /** Packages the project needs but doesn't have. */\n missingDependencies: string[]\n}\n\nexport function addComponent(options: AddOptions): AddResult {\n const project = detectProject(options.cwd)\n const entry = findEntry(options.name)\n\n if (!entry) {\n throw new Error(\n `Unknown component \"${options.name}\". Run \\`ansh list\\` to see what's available.`,\n )\n }\n\n if (project.framework === 'unknown') {\n throw new Error(\n 'Could not detect a React, Next, Vue or Nuxt project. ' +\n 'Run this from your project root, or install the framework first.',\n )\n }\n\n const isVue = project.framework === 'vue' || project.framework === 'nuxt'\n const componentName = options.as ?? entry.component\n const extension = isVue ? 'vue' : project.typescript ? 'tsx' : 'jsx'\n\n const directory = options.dir ?? project.componentsDir\n const path = join(project.root, directory, `${componentName}.${extension}`)\n\n const contents = isVue\n ? renderVue(componentName, entry.component, entry.options, project)\n : renderReact(componentName, entry.component, entry.options, project)\n\n const missingDependencies = missingFor(project)\n\n if (options.dryRun) {\n return { path, contents, written: false, missingDependencies }\n }\n\n if (existsSync(path) && !options.force) {\n throw new Error(`${path} already exists. Pass --force to overwrite.`)\n }\n\n mkdirSync(dirname(path), { recursive: true })\n writeFileSync(path, contents, 'utf8')\n\n return { path, contents, written: true, missingDependencies }\n}\n\nfunction missingFor(project: ProjectInfo): string[] {\n if (project.installed) return []\n switch (project.framework) {\n case 'nuxt':\n return ['@ansh-ui/nuxt']\n case 'vue':\n return ['@ansh-ui/vue', '@ansh-ui/tokens']\n default:\n return ['@ansh-ui/react', '@ansh-ui/tokens']\n }\n}\n\n/**\n * Serialise a default value as source.\n *\n * Only the options worth surfacing are emitted — see {@link INTERESTING_OPTIONS}. Emitting all\n * twenty would produce a wall of noise that obscures the three an author will actually change.\n */\nfunction literal(value: unknown): string {\n if (typeof value === 'string') return JSON.stringify(value)\n if (Array.isArray(value)) return `[${value.map(literal).join(', ')}]`\n if (value === null) return 'null'\n if (typeof value === 'object') return JSON.stringify(value)\n return String(value)\n}\n\n/**\n * Options included in generated source.\n *\n * These are the ones that carry design intent — the knobs a designer asks to change. Structural and\n * performance options are omitted from the generated defaults but remain available as props, since\n * the wrapper spreads everything through.\n */\nconst INTERESTING_OPTIONS = new Set([\n 'colors',\n 'speed',\n 'intensity',\n 'opacity',\n 'blur',\n 'seed',\n 'strength',\n 'radius',\n 'max',\n 'distance',\n 'amount',\n 'count',\n])\n\nfunction pickDefaults(options: Array<{ name: string; default: unknown }>) {\n return options.filter((option) => INTERESTING_OPTIONS.has(option.name))\n}\n\nfunction renderReact(\n componentName: string,\n sourceComponent: string,\n options: Array<{ name: string; default: unknown }>,\n project: ProjectInfo,\n): string {\n const ts = project.typescript\n const defaults = pickDefaults(options)\n\n const defaultLines = defaults\n .map((option) => ` ${option.name}: ${literal(option.default)},`)\n .join('\\n')\n\n const propsType = ts\n ? `\\ntype ${componentName}Props = ComponentProps<typeof ${sourceComponent}>\\n`\n : ''\n\n const signature = ts\n ? `export function ${componentName}({ children, ...props }: ${componentName}Props) {`\n : `export function ${componentName}({ children, ...props }) {`\n\n const typeImport = ts ? `import type { ComponentProps } from 'react'\\n` : ''\n\n return `${typeImport}import { ${sourceComponent} } from '@ansh-ui/react'\n\n/**\n * ${componentName} — a project-local wrapper around Ansh's ${sourceComponent}.\n *\n * Edit the defaults below to match your design system. Every option remains overridable per\n * instance, because props spread after the defaults.\n *\n * Generated by \\`ansh add\\`. Safe to edit — it will not be regenerated unless you ask.\n */\nconst defaults = {\n${defaultLines}\n}\n\n${propsType}\n${signature}\n return (\n <${sourceComponent} {...defaults} {...props}>\n {children}\n </${sourceComponent}>\n )\n}\n`\n}\n\nfunction renderVue(\n componentName: string,\n sourceComponent: string,\n options: Array<{ name: string; default: unknown }>,\n project: ProjectInfo,\n): string {\n const defaults = pickDefaults(options)\n const defaultLines = defaults\n .map((option) => ` ${option.name}: ${literal(option.default)},`)\n .join('\\n')\n\n const lang = project.typescript ? ' lang=\"ts\"' : ''\n\n // Nuxt auto-imports Ansh components, so an explicit import there would be redundant — and\n // would shadow the auto-import in a way that breaks if the module's prefix option changes.\n const importLine =\n project.framework === 'nuxt'\n ? `// ${sourceComponent} is auto-imported by @ansh-ui/nuxt.`\n : `import { ${sourceComponent} } from '@ansh-ui/vue'`\n\n return `<script setup${lang}>\n${importLine}\n\n/**\n * ${componentName} — a project-local wrapper around Ansh's ${sourceComponent}.\n *\n * Edit the defaults below to match your design system. Every option remains overridable per\n * instance, because \\`$attrs\\` is bound after the defaults.\n *\n * Generated by \\`ansh add\\`. Safe to edit — it will not be regenerated unless you ask.\n */\nconst defaults = {\n${defaultLines}\n}\n</script>\n\n<template>\n <${sourceComponent} v-bind=\"{ ...defaults, ...$attrs }\">\n <slot />\n </${sourceComponent}>\n</template>\n`\n}\n","import {\n createGradient,\n generatePalette,\n parseColor,\n perceivedLightness,\n rgbToOklch,\n toHex,\n toOklchString,\n} from '@ansh-ui/core'\n\n/**\n * `ansh palette` — generate and inspect palettes.\n *\n * Two modes:\n *\n * - **Generate** — a seeded palette from scratch. The same seed always produces the same palette,\n * so a designer who likes seed 4821 can pin it and get that palette back next week.\n * - **Inspect** — report a supplied palette's OKLCH decomposition and the gradient it produces.\n * The useful part is seeing the *interpolated midpoints*: a palette can look fine as swatches and\n * produce a muddy gradient, and this shows that before it ships.\n */\n\nexport interface PaletteReportOptions {\n /** Colours to inspect. Generates a new palette when omitted. */\n colors?: string[]\n /** Number of colours to generate. Default `5`. */\n count?: number\n seed?: number | string\n /** Overall lightness in `[0, 1]`. Default `0.65`. */\n lightness?: number\n /** Chroma as a fraction of the maximum available. Default `0.85`. */\n saturation?: number\n /** Hue span in degrees. Default `120`. */\n spread?: number\n /** Also print interpolated gradient midpoints. Default `true`. */\n gradient?: boolean\n}\n\nexport interface PaletteReport {\n colors: Array<{ hex: string; oklch: string; lightness: number; chroma: number; hue: number }>\n /** Interpolated samples across the palette, showing what a gradient through it looks like. */\n gradientSamples: string[]\n /** Copy-pasteable literal for a `colors` prop. */\n snippet: string\n}\n\nexport function generatePaletteReport(options: PaletteReportOptions = {}): PaletteReport {\n const parsed =\n options.colors && options.colors.length > 0\n ? options.colors.map((color) => parseColor(color))\n : generatePalette({\n count: options.count ?? 5,\n seed: options.seed ?? 1,\n lightness: options.lightness ?? 0.65,\n saturation: options.saturation ?? 0.85,\n spread: options.spread ?? 120,\n })\n\n const colors = parsed.map((color) => {\n const lch = rgbToOklch(color)\n return {\n hex: toHex(color),\n oklch: toOklchString(color),\n lightness: Number(lch.l.toFixed(4)),\n chroma: Number(lch.c.toFixed(4)),\n hue: Number(lch.h.toFixed(2)),\n }\n })\n\n // Sampled in OKLCH rather than OKLab: for a gradient *through a palette* the goal is maximum\n // vividness across the transitions, which is what travelling the hue circle gives.\n const gradientSamples =\n options.gradient === false || parsed.length < 2\n ? []\n : createGradient(parsed, { space: 'oklch' })\n .sample(9)\n .map((color) => toHex(color))\n\n const snippet = `colors={[${colors.map((c) => `'${c.hex}'`).join(', ')}]}`\n\n return { colors, gradientSamples, snippet }\n}\n\n/**\n * Sort a palette by perceived lightness and report the ordering.\n *\n * Useful for layered effects, where the draw order should generally run dark to light so brighter\n * colours land on top and read as nearer.\n */\nexport function orderByLightness(colors: string[]): Array<{ hex: string; lightness: number }> {\n return colors\n .map((color) => ({ hex: toHex(parseColor(color)), lightness: perceivedLightness(color) }))\n .sort((a, b) => a.lightness - b.lightness)\n}\n","import { mkdirSync, writeFileSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport {\n checkContrast,\n createScale,\n harmony,\n parseColor,\n rgbToOklch,\n toHex,\n toOklchString,\n} from '@ansh-ui/core'\n\n/**\n * `ansh theme <color>` — generate a token override stylesheet from a brand colour.\n *\n * The job this does that hand-authoring doesn't: it **checks the result**. An 11-step scale\n * generated from a brand colour will, for certain hues, produce steps that fail contrast against\n * white or against each other — a saturated yellow at step 600 is a classic offender. Generating the\n * scale is easy; noticing that step 600 can't legally hold body text is the part people skip.\n *\n * So the emitted stylesheet carries contrast annotations as comments, and the report flags any step\n * that cannot be used for text.\n */\n\nexport interface ThemeOptions {\n /** Brand colour in any CSS syntax. */\n color: string\n /** Where to write the stylesheet. Prints to stdout when omitted. */\n out?: string\n /** Hue drift across the scale, in degrees. `0` keeps a single hue. Default `0`. */\n hueShift?: number\n /** Chroma falloff at the extremes, in `[0, 1]`. Default `0.35`. */\n chromaFalloff?: number\n /** Also emit a harmonious accent scale. Default `false`. */\n withAccent?: boolean\n}\n\nexport interface ThemeReport {\n css: string\n /** Steps whose contrast against white is below 4.5:1 — unusable for body text on light surfaces. */\n unsafeOnLight: string[]\n /** Steps whose contrast against near-black is below 4.5:1. */\n unsafeOnDark: string[]\n /** The step closest in lightness to the input colour. */\n nearestStep: string\n}\n\nconst TAILWIND_KEYS = ['50', '100', '200', '300', '400', '500', '600', '700', '800', '900', '950']\n\nexport function generateTheme(options: ThemeOptions): ThemeReport {\n const base = parseColor(options.color)\n const baseLightness = rgbToOklch(base).l\n\n const scale = createScale(base, {\n steps: 11,\n hueShift: options.hueShift ?? 0,\n chromaFalloff: options.chromaFalloff ?? 0.35,\n })\n\n const unsafeOnLight: string[] = []\n const unsafeOnDark: string[] = []\n\n const lines: string[] = []\n let nearestStep = '500'\n let nearestDistance = Infinity\n\n scale.colors.forEach((color, index) => {\n const key = TAILWIND_KEYS[index]\n const onLight = checkContrast(color, '#ffffff')\n const onDark = checkContrast(color, '#0b0b0f')\n\n if (!onLight.passes) unsafeOnLight.push(key)\n if (!onDark.passes) unsafeOnDark.push(key)\n\n const distance = Math.abs(rgbToOklch(color).l - baseLightness)\n if (distance < nearestDistance) {\n nearestDistance = distance\n nearestStep = key\n }\n\n // The comment carries the numbers, so a designer reviewing the file can see at a glance which\n // steps are safe for text without opening a contrast checker.\n lines.push(\n ` --ansh-brand-${key}: ${toOklchString(color)};` +\n ` /* ${toHex(color)} on-white ${onLight.ratio.toFixed(2)}:1` +\n ` on-black ${onDark.ratio.toFixed(2)}:1 */`,\n )\n })\n\n let accentLines = ''\n if (options.withAccent) {\n // A split-complementary partner: far enough from the brand hue to be clearly a different\n // colour, close enough to still look related. The straight complement is usually too harsh for\n // UI, which is why it isn't the default choice here.\n const [, accent] = harmony(base, 'splitComplementary')\n const accentScale = createScale(accent, { steps: 11 })\n accentLines =\n '\\n /* Accent — split-complementary partner to the brand hue. */\\n' +\n accentScale.colors\n .map((color, index) => ` --ansh-accent-${TAILWIND_KEYS[index]}: ${toOklchString(color)};`)\n .join('\\n') +\n '\\n'\n }\n\n const css = `/**\n * Ansh theme override.\n *\n * Generated by \\`ansh theme ${options.color}\\`.\n * Import this *after* \\`@ansh-ui/tokens/ansh.css\\` so it wins in the cascade.\n *\n * Contrast ratios are annotated per step. Steps marked unsafe cannot legally hold body text on the\n * corresponding surface — use them for fills, borders and large display type instead.\n */\n\n:root {\n${lines.join('\\n')}\n${accentLines}\n /* Wire the semantic accent tokens to the generated scale. */\n --ansh-accent-subtle: var(--ansh-brand-50);\n --ansh-accent-muted: var(--ansh-brand-100);\n --ansh-accent-default: var(--ansh-brand-600);\n --ansh-accent-hover: var(--ansh-brand-700);\n --ansh-accent-active: var(--ansh-brand-800);\n --ansh-accent-text: var(--ansh-brand-700);\n --ansh-border-focus: var(--ansh-brand-600);\n}\n\n/**\n * Dark theme.\n *\n * Not an inversion. Accents step *lighter* rather than mirroring their light-mode index, because\n * saturated colour reads as less vivid against a dark background (Helmholtz–Kohlrausch).\n */\n[data-theme='dark'] {\n --ansh-accent-subtle: color-mix(in oklab, var(--ansh-brand-950) 40%, transparent);\n --ansh-accent-muted: var(--ansh-brand-950);\n --ansh-accent-default: var(--ansh-brand-500);\n --ansh-accent-hover: var(--ansh-brand-400);\n --ansh-accent-active: var(--ansh-brand-300);\n --ansh-accent-text: var(--ansh-brand-300);\n --ansh-border-focus: var(--ansh-brand-400);\n}\n\n@media (prefers-color-scheme: dark) {\n :root:not([data-theme]) {\n --ansh-accent-subtle: color-mix(in oklab, var(--ansh-brand-950) 40%, transparent);\n --ansh-accent-muted: var(--ansh-brand-950);\n --ansh-accent-default: var(--ansh-brand-500);\n --ansh-accent-hover: var(--ansh-brand-400);\n --ansh-accent-active: var(--ansh-brand-300);\n --ansh-accent-text: var(--ansh-brand-300);\n --ansh-border-focus: var(--ansh-brand-400);\n }\n}\n`\n\n if (options.out) {\n mkdirSync(dirname(options.out), { recursive: true })\n writeFileSync(options.out, css, 'utf8')\n }\n\n return { css, unsafeOnLight, unsafeOnDark, nearestStep }\n}\n","import { readFileSync } from 'node:fs'\nimport { parseArgs } from 'node:util'\nimport { addComponent } from './commands/add'\nimport { findEntry, listCatalogue } from './commands/list'\nimport { generatePaletteReport } from './commands/palette'\nimport { generateTheme } from './commands/theme'\nimport { detectKnownInconsistencies, detectProject, installCommand } from './project'\n\n/**\n * The Ansh CLI.\n *\n * Uses Node's built-in `parseArgs` rather than commander or yargs. A CLI is the one place where a\n * dependency is most visible to the user — it is what they wait for on `npx` — and this tool's\n * argument surface is small enough that 40 lines of dispatch beats a 200 KB install.\n *\n * Output is coloured only when stdout is a TTY and `NO_COLOR` is unset, so piping to a file or\n * running in CI produces clean text.\n */\n\nconst useColor = process.stdout.isTTY && !process.env.NO_COLOR\n\nconst paint = (code: string, text: string): string => (useColor ? `\u001b[${code}m${text}\u001b[0m` : text)\n\nconst bold = (text: string) => paint('1', text)\nconst dim = (text: string) => paint('2', text)\nconst cyan = (text: string) => paint('36', text)\nconst green = (text: string) => paint('32', text)\nconst yellow = (text: string) => paint('33', text)\nconst red = (text: string) => paint('31', text)\n\n/**\n * Read from the package's own `package.json` rather than hardcoded — a literal here said `0.1.0` for\n * the whole 0.2 line. `../package.json` resolves to the package root from both `src/` and `dist/`.\n */\nconst VERSION = (\n JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')) as {\n version: string\n }\n).version\n\nfunction help(): void {\n console.log(`\n${bold('ansh')} ${dim(`v${VERSION}`)} — Motion, refined.\n\n${bold('USAGE')}\n ansh <command> [options]\n\n${bold('COMMANDS')}\n ${cyan('list')} [--effects|--behaviours] List the component catalogue\n ${cyan('info')} <name> Show a component's full option surface\n ${cyan('add')} <name> [--as <Name>] Generate a local wrapper component\n ${cyan('theme')} <color> [--out <file>] Generate a token override stylesheet\n ${cyan('palette')} [colors...] Generate or inspect a palette\n ${cyan('doctor')} Report the detected project setup\n\n${bold('EXAMPLES')}\n ${dim('# See what is available')}\n ansh list\n\n ${dim('# Generate a HeroBackground wrapper around the aurora effect')}\n ansh add aurora --as HeroBackground\n\n ${dim('# Build a theme from a brand colour, with contrast annotations')}\n ansh theme '#0275f4' --out src/styles/theme.css --with-accent\n\n ${dim('# Inspect how a palette interpolates')}\n ansh palette '#0275f4' '#9f0550'\n\n ${dim('# Reproducible generated palette')}\n ansh palette --count 5 --seed hero-section\n`)\n}\n\nfunction fail(message: string, hint?: string): never {\n console.error(`${red('error')} ${message}`)\n if (hint) console.error(`${dim('hint')} ${hint}`)\n process.exit(1)\n}\n\n// ---------------------------------------------------------------------------\n// Commands\n// ---------------------------------------------------------------------------\n\nfunction commandList(argv: string[]): void {\n const { values } = parseArgs({\n args: argv,\n options: {\n effects: { type: 'boolean', default: false },\n behaviours: { type: 'boolean', default: false },\n json: { type: 'boolean', default: false },\n },\n allowPositionals: true,\n })\n\n const filter = values.effects ? 'effect' : values.behaviours ? 'behaviour' : undefined\n const entries = listCatalogue(filter)\n\n if (values.json) {\n console.log(JSON.stringify(entries, null, 2))\n return\n }\n\n const effects = entries.filter((entry) => entry.kind === 'effect')\n const behaviours = entries.filter((entry) => entry.kind === 'behaviour')\n\n const print = (title: string, list: typeof entries) => {\n if (list.length === 0) return\n console.log(`\\n${bold(title)}`)\n for (const entry of list) {\n console.log(\n ` ${cyan(entry.name.padEnd(20))} ${entry.component.padEnd(20)} ` +\n dim(`${entry.options.length} options`),\n )\n }\n }\n\n print(`Effects ${dim('(canvas)')}`, effects)\n print(`Behaviours ${dim('(DOM)')}`, behaviours)\n console.log(`\\n${dim(`${entries.length} total. Run \\`ansh info <name>\\` for details.`)}\\n`)\n}\n\nfunction commandInfo(argv: string[]): void {\n const name = argv[0]\n if (!name) fail('Missing component name.', 'ansh info aurora')\n\n const entry = findEntry(name)\n if (!entry) fail(`Unknown component \"${name}\".`, 'Run `ansh list` to see what is available.')\n\n console.log(`\\n${bold(entry.component)} ${dim(`(${entry.kind} \"${entry.name}\")`)}\\n`)\n console.log(bold(' OPTIONS'))\n\n const width = Math.max(...entry.options.map((option) => option.name.length))\n for (const option of entry.options) {\n const value =\n typeof option.default === 'string'\n ? `'${option.default}'`\n : Array.isArray(option.default)\n ? `[${option.default.map((v) => (typeof v === 'string' ? `'${v}'` : String(v))).join(', ')}]`\n : String(option.default)\n console.log(` ${option.name.padEnd(width)} ${dim('=')} ${green(value)}`)\n }\n\n console.log(\n `\\n${dim(` Docs: https://ansh.techiesofepi.com/showcase`)}\\n` +\n `${dim(` Add: ansh add ${entry.name}`)}\\n`,\n )\n}\n\nfunction commandAdd(argv: string[]): void {\n const { values, positionals } = parseArgs({\n args: argv,\n options: {\n as: { type: 'string' },\n dir: { type: 'string' },\n force: { type: 'boolean', default: false },\n 'dry-run': { type: 'boolean', default: false },\n },\n allowPositionals: true,\n })\n\n const name = positionals[0]\n if (!name) fail('Missing component name.', 'ansh add aurora --as HeroBackground')\n\n try {\n const result = addComponent({\n name,\n as: values.as,\n dir: values.dir,\n force: values.force,\n dryRun: values['dry-run'],\n })\n\n if (!result.written) {\n console.log(`${dim(`--- ${result.path} ---`)}\\n`)\n console.log(result.contents)\n return\n }\n\n console.log(`${green('created')} ${result.path}`)\n\n if (result.missingDependencies.length > 0) {\n const project = detectProject()\n console.log(\n `\\n${yellow('next')} Install the runtime packages:\\n` +\n ` ${installCommand(project, result.missingDependencies)}`,\n )\n }\n } catch (error) {\n fail(error instanceof Error ? error.message : String(error))\n }\n}\n\nfunction commandTheme(argv: string[]): void {\n const { values, positionals } = parseArgs({\n args: argv,\n options: {\n out: { type: 'string' },\n 'hue-shift': { type: 'string' },\n 'chroma-falloff': { type: 'string' },\n 'with-accent': { type: 'boolean', default: false },\n },\n allowPositionals: true,\n })\n\n const color = positionals[0]\n if (!color) fail('Missing brand colour.', \"ansh theme '#0275f4' --out theme.css\")\n\n try {\n const report = generateTheme({\n color,\n out: values.out,\n hueShift: values['hue-shift'] ? Number(values['hue-shift']) : undefined,\n chromaFalloff: values['chroma-falloff'] ? Number(values['chroma-falloff']) : undefined,\n withAccent: values['with-accent'],\n })\n\n if (!values.out) {\n console.log(report.css)\n return\n }\n\n console.log(`${green('created')} ${values.out}`)\n console.log(`${dim('nearest')} your input is closest to step ${report.nearestStep}`)\n\n // Surfacing this is the point of the command. A generated scale that silently fails contrast is\n // worse than no generated scale, because it looks authoritative.\n if (report.unsafeOnLight.length > 0) {\n console.log(\n `${yellow('warn')} steps ${report.unsafeOnLight.join(', ')} are below 4.5:1 on white — ` +\n `use them for fills and borders, not body text`,\n )\n }\n if (report.unsafeOnDark.length > 0) {\n console.log(\n `${yellow('warn')} steps ${report.unsafeOnDark.join(', ')} are below 4.5:1 on near-black`,\n )\n }\n } catch (error) {\n fail(error instanceof Error ? error.message : String(error))\n }\n}\n\nfunction commandPalette(argv: string[]): void {\n const { values, positionals } = parseArgs({\n args: argv,\n options: {\n count: { type: 'string' },\n seed: { type: 'string' },\n lightness: { type: 'string' },\n saturation: { type: 'string' },\n spread: { type: 'string' },\n json: { type: 'boolean', default: false },\n },\n allowPositionals: true,\n })\n\n try {\n const report = generatePaletteReport({\n colors: positionals.length > 0 ? positionals : undefined,\n count: values.count ? Number(values.count) : undefined,\n seed: values.seed,\n lightness: values.lightness ? Number(values.lightness) : undefined,\n saturation: values.saturation ? Number(values.saturation) : undefined,\n spread: values.spread ? Number(values.spread) : undefined,\n })\n\n if (values.json) {\n console.log(JSON.stringify(report, null, 2))\n return\n }\n\n console.log(`\\n${bold('PALETTE')}\\n`)\n for (const color of report.colors) {\n console.log(\n ` ${swatch(color.hex)} ${color.hex.padEnd(9)} ${dim(color.oklch.padEnd(28))} ` +\n dim(\n `L ${color.lightness.toFixed(3)} C ${color.chroma.toFixed(3)} H ${color.hue.toFixed(1)}`,\n ),\n )\n }\n\n if (report.gradientSamples.length > 0) {\n console.log(`\\n${bold('GRADIENT')} ${dim('(OKLCH interpolation)')}\\n`)\n console.log(' ' + report.gradientSamples.map((hex) => swatch(hex)).join(''))\n console.log(' ' + dim(report.gradientSamples.join(' ')))\n }\n\n console.log(`\\n${bold('SNIPPET')}\\n\\n ${green(report.snippet)}\\n`)\n } catch (error) {\n fail(error instanceof Error ? error.message : String(error))\n }\n}\n\nfunction commandDoctor(): void {\n const project = detectProject()\n\n console.log(`\\n${bold('PROJECT')}\\n`)\n console.log(` root ${project.root}`)\n console.log(\n ` framework ${project.framework === 'unknown' ? yellow('not detected') : green(project.framework)}`,\n )\n console.log(` typescript ${project.typescript ? green('yes') : dim('no')}`)\n console.log(` package manager ${project.packageManager}`)\n console.log(` components dir ${project.componentsDir}`)\n console.log(` import alias ${project.alias ?? dim('none')}`)\n console.log(` ansh ${project.installed ? green('installed') : yellow('not installed')}`)\n\n if (!project.installed) {\n const packages =\n project.framework === 'nuxt'\n ? ['@ansh-ui/nuxt']\n : project.framework === 'vue'\n ? ['@ansh-ui/vue', '@ansh-ui/tokens']\n : ['@ansh-ui/react', '@ansh-ui/tokens']\n console.log(`\\n${yellow('next')} ${installCommand(project, packages)}\\n`)\n } else {\n console.log('')\n }\n\n const inconsistencies = detectKnownInconsistencies(project.root)\n if (inconsistencies.length > 0) {\n console.log(`${bold('KNOWN INCONSISTENCIES')}\\n`)\n for (const { title, detail } of inconsistencies) {\n console.log(` ${yellow('•')} ${title}`)\n console.log(` ${dim(detail)}\\n`)\n }\n }\n}\n\n/** A coloured block for terminal swatches. Falls back to a filled square without colour support. */\nfunction swatch(hex: string): string {\n if (!useColor) return '■'\n const r = parseInt(hex.slice(1, 3), 16)\n const g = parseInt(hex.slice(3, 5), 16)\n const b = parseInt(hex.slice(5, 7), 16)\n return `\u001b[48;2;${r};${g};${b}m \u001b[0m`\n}\n\n// ---------------------------------------------------------------------------\n// Dispatch\n// ---------------------------------------------------------------------------\n\nfunction main(): void {\n const [command, ...rest] = process.argv.slice(2)\n\n switch (command) {\n case 'list':\n case 'ls':\n return commandList(rest)\n case 'info':\n case 'show':\n return commandInfo(rest)\n case 'add':\n return commandAdd(rest)\n case 'theme':\n return commandTheme(rest)\n case 'palette':\n return commandPalette(rest)\n case 'doctor':\n return commandDoctor()\n case '--version':\n case '-v':\n console.log(VERSION)\n return\n case undefined:\n case 'help':\n case '--help':\n case '-h':\n return help()\n default:\n fail(`Unknown command \"${command}\".`, 'Run `ansh help` to see available commands.')\n }\n}\n\nmain()\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -158,4 +158,5 @@ interface ProjectInfo {
|
|
|
158
158
|
}
|
|
159
159
|
declare function detectProject(cwd?: string): ProjectInfo;
|
|
160
160
|
|
|
161
|
-
export {
|
|
161
|
+
export { addComponent, detectProject, generatePaletteReport, generateTheme, listCatalogue };
|
|
162
|
+
export type { AddOptions, AddResult, CatalogueEntry, Framework, PaletteReportOptions, ProjectInfo, ThemeOptions };
|
package/dist/index.js
CHANGED
|
@@ -84,8 +84,9 @@ var COMPONENT_NAMES = {
|
|
|
84
84
|
marquee: "Marquee",
|
|
85
85
|
"scroll-reveal": "ScrollReveal",
|
|
86
86
|
parallax: "Parallax",
|
|
87
|
-
"
|
|
87
|
+
"text-scramble": "ScrambleText"
|
|
88
88
|
};
|
|
89
|
+
var NO_COMPONENT = /* @__PURE__ */ new Set(["split-text"]);
|
|
89
90
|
function componentNameFor(name) {
|
|
90
91
|
return COMPONENT_NAMES[name] ?? name.replace(/(^|-)([a-z])/g, (_, __, letter) => letter.toUpperCase());
|
|
91
92
|
}
|
|
@@ -103,6 +104,7 @@ function listCatalogue(filter) {
|
|
|
103
104
|
}
|
|
104
105
|
if (filter !== "effect") {
|
|
105
106
|
for (const [name, definition] of Object.entries(behaviours)) {
|
|
107
|
+
if (NO_COMPONENT.has(name)) continue;
|
|
106
108
|
entries.push({
|
|
107
109
|
name,
|
|
108
110
|
kind: "behaviour",
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/project.ts","../src/commands/list.ts","../src/commands/add.ts","../src/commands/theme.ts","../src/commands/palette.ts"],"names":["join","existsSync","mkdirSync","dirname","writeFileSync","parseColor","rgbToOklch","toHex","toOklchString"],"mappings":"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","file":"index.js","sourcesContent":["import { existsSync, readFileSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\n\n/**\n * Project detection.\n *\n * The CLI needs to know which framework it is generating for, whether the project uses TypeScript,\n * and where components live. Asking the user all of that on every invocation is friction for\n * information that is sitting in `package.json` and on disk — so we detect it, and only prompt for\n * what we genuinely cannot infer.\n */\n\nexport type Framework = 'react' | 'vue' | 'nuxt' | 'next' | 'unknown'\n\nexport interface ProjectInfo {\n root: string\n framework: Framework\n typescript: boolean\n /** Where generated components should go, relative to `root`. */\n componentsDir: string\n /** Detected import alias for the source root, e.g. `'@/'`. `null` when none is configured. */\n alias: string | null\n packageManager: 'pnpm' | 'yarn' | 'npm' | 'bun'\n /** `true` when the relevant `@ansh-ui/*` package is already a dependency. */\n installed: boolean\n}\n\n/** Walk up from `cwd` looking for a `package.json`, so the CLI works from a subdirectory. */\nfunction findRoot(cwd: string): string {\n let current = resolve(cwd)\n for (let depth = 0; depth < 10; depth++) {\n if (existsSync(join(current, 'package.json'))) return current\n const parent = resolve(current, '..')\n if (parent === current) break\n current = parent\n }\n return resolve(cwd)\n}\n\nfunction readJson(path: string): Record<string, unknown> | null {\n try {\n return JSON.parse(readFileSync(path, 'utf8')) as Record<string, unknown>\n } catch {\n return null\n }\n}\n\nexport function detectProject(cwd = process.cwd()): ProjectInfo {\n const root = findRoot(cwd)\n const pkg = readJson(join(root, 'package.json')) ?? {}\n\n const deps: Record<string, string> = {\n ...((pkg.dependencies as Record<string, string>) ?? {}),\n ...((pkg.devDependencies as Record<string, string>) ?? {}),\n }\n\n // Order matters: Nuxt projects also depend on Vue, and Next projects on React. Checking the\n // meta-framework first gives the more specific — and more useful — answer.\n const framework: Framework = deps.nuxt\n ? 'nuxt'\n : deps.next\n ? 'next'\n : deps.vue\n ? 'vue'\n : deps.react\n ? 'react'\n : 'unknown'\n\n const typescript = Boolean(deps.typescript) || existsSync(join(root, 'tsconfig.json'))\n\n const packageManager: ProjectInfo['packageManager'] = existsSync(join(root, 'pnpm-lock.yaml'))\n ? 'pnpm'\n : existsSync(join(root, 'bun.lockb')) || existsSync(join(root, 'bun.lock'))\n ? 'bun'\n : existsSync(join(root, 'yarn.lock'))\n ? 'yarn'\n : 'npm'\n\n return {\n root,\n framework,\n typescript,\n componentsDir: detectComponentsDir(root, framework),\n alias: detectAlias(root),\n packageManager,\n installed: Boolean(\n deps['@ansh-ui/react'] ||\n deps['@ansh-ui/vue'] ||\n deps['@ansh-ui/nuxt'] ||\n deps['@ansh-ui/core'],\n ),\n }\n}\n\n/**\n * Find where components already live, rather than imposing a convention.\n *\n * Dropping a file into `src/components` in a project that uses `app/ui` is the kind of small\n * disrespect that makes a tool feel foreign. Candidates are ordered by how strong a signal they are.\n */\nfunction detectComponentsDir(root: string, framework: Framework): string {\n const candidates =\n framework === 'nuxt'\n ? ['components', 'app/components', 'src/components']\n : ['src/components', 'components', 'app/components', 'src/lib/components', 'app/ui', 'src/ui']\n\n for (const candidate of candidates) {\n if (existsSync(join(root, candidate))) return candidate\n }\n\n // Nothing exists yet: pick the convention that matches the project's existing shape.\n if (existsSync(join(root, 'src'))) return 'src/components'\n if (framework === 'nuxt') return 'components'\n return 'components'\n}\n\n/**\n * Read the source alias from `tsconfig.json` so generated imports match the project's style.\n *\n * A generated file that writes `../../lib/utils` in a project where everything else says\n * `@/lib/utils` is immediately identifiable as machine-written.\n */\nfunction detectAlias(root: string): string | null {\n for (const file of ['tsconfig.json', 'jsconfig.json']) {\n const config = readJson(join(root, file))\n if (!config) continue\n\n const compilerOptions = config.compilerOptions as Record<string, unknown> | undefined\n const paths = compilerOptions?.paths as Record<string, string[]> | undefined\n if (!paths) continue\n\n for (const pattern of Object.keys(paths)) {\n // Match a plain wildcard alias like `\"@/*\"` or `\"~/*\"` — the overwhelmingly common shape.\n if (pattern.endsWith('/*')) return pattern.slice(0, -1)\n }\n }\n return null\n}\n\n/** The install command for the detected package manager. */\nexport function installCommand(info: ProjectInfo, packages: string[]): string {\n const list = packages.join(' ')\n switch (info.packageManager) {\n case 'pnpm':\n return `pnpm add ${list}`\n case 'yarn':\n return `yarn add ${list}`\n case 'bun':\n return `bun add ${list}`\n default:\n return `npm install ${list}`\n }\n}\n","import { behaviours, effects } from '@ansh-ui/core'\n\n/**\n * Catalogue enumeration.\n *\n * Reads the registry rather than a hardcoded list, so a new effect appears in `ansh list` the\n * moment it is defined — no second place to update, and no possibility of the CLI advertising\n * something that doesn't exist or omitting something that does.\n */\n\nexport interface CatalogueEntry {\n name: string\n kind: 'effect' | 'behaviour'\n /** The component name in `@ansh-ui/react` and `@ansh-ui/vue`. */\n component: string\n /** Every option, with its default value, read from the definition. */\n options: Array<{ name: string; default: unknown }>\n}\n\n/**\n * Effect and behaviour names map to component names that read better than a mechanical\n * transformation would produce — `meteors` → `MeteorShower`, `blob` → `LiquidBlob`. Where a\n * definition isn't listed here, the name is PascalCased.\n */\nconst COMPONENT_NAMES: Record<string, string> = {\n aurora: 'AuroraBackground',\n 'mesh-gradient': 'MeshGradient',\n 'animated-gradient': 'AnimatedGradient',\n 'particle-field': 'ParticleField',\n constellation: 'Constellation',\n meteors: 'MeteorShower',\n rain: 'Rain',\n snow: 'Snow',\n fireflies: 'Fireflies',\n waves: 'Waves',\n blob: 'LiquidBlob',\n 'noise-layer': 'NoiseLayer',\n spotlight: 'Spotlight',\n magnetic: 'MagneticButton',\n tilt: 'TiltCard',\n ripple: 'Ripple',\n marquee: 'Marquee',\n 'scroll-reveal': 'ScrollReveal',\n parallax: 'Parallax',\n 'split-text': 'SplitText',\n}\n\nexport function componentNameFor(name: string): string {\n return (\n COMPONENT_NAMES[name] ??\n name.replace(/(^|-)([a-z])/g, (_, __, letter: string) => letter.toUpperCase())\n )\n}\n\nexport function listCatalogue(filter?: 'effect' | 'behaviour'): CatalogueEntry[] {\n const entries: CatalogueEntry[] = []\n\n if (filter !== 'behaviour') {\n for (const [name, definition] of Object.entries(effects)) {\n entries.push({\n name,\n kind: 'effect',\n component: componentNameFor(name),\n options: describeOptions(definition.defaults as Record<string, unknown>),\n })\n }\n }\n\n if (filter !== 'effect') {\n for (const [name, definition] of Object.entries(behaviours)) {\n entries.push({\n name,\n kind: 'behaviour',\n component: componentNameFor(name),\n options: describeOptions(definition.defaults as Record<string, unknown>),\n })\n }\n }\n\n return entries.sort((a, b) => a.name.localeCompare(b.name))\n}\n\n/**\n * Turn a `defaults` object into a documented option list.\n *\n * This is why {@link import('@ansh-ui/core').EffectDefinition}'s `defaults` is typed\n * `Required<Options>`: it makes \"every option has a documented default\" a compile-time guarantee,\n * which in turn makes this function complete by construction rather than by diligence.\n */\nfunction describeOptions(defaults: Record<string, unknown>): CatalogueEntry['options'] {\n return Object.entries(defaults)\n .map(([name, value]) => ({ name, default: value }))\n .sort((a, b) => a.name.localeCompare(b.name))\n}\n\n/** Look up a single entry by effect/behaviour name or by component name, case-insensitively. */\nexport function findEntry(query: string): CatalogueEntry | undefined {\n const needle = query.toLowerCase()\n return listCatalogue().find(\n (entry) => entry.name.toLowerCase() === needle || entry.component.toLowerCase() === needle,\n )\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { type ProjectInfo, detectProject } from '../project'\nimport { findEntry } from './list'\n\n/**\n * `ansh add <name>` — generate a local, editable wrapper for a component.\n *\n * ## Why a wrapper rather than a source copy\n *\n * shadcn/ui popularised copying component source into the project, and for *unstyled primitives*\n * that is exactly right: the value is in the markup and the styling, and you want to own both.\n *\n * Ansh is a different shape. The value is in the engine — an 800-line curl-noise particle system,\n * a spring solver, a colour pipeline — and copying that into an application would be actively\n * harmful: it would never receive a bug fix, and it would bloat the repository with code nobody on\n * the team intends to maintain.\n *\n * What developers actually want to own is the **configuration**: which colours, what intensity, what\n * it is called in their design system. So that is what this generates — a thin, fully-typed local\n * component with the project's own defaults baked in, importing the engine from the package.\n *\n * The result: `<HeroBackground />` in application code, one file to edit when the brand palette\n * changes, and engine fixes arrive through a normal dependency upgrade.\n */\n\nexport interface AddOptions {\n /** Effect or behaviour name, or component name. Case-insensitive. */\n name: string\n /** Local component name. Defaults to the catalogue's component name. */\n as?: string\n /** Target directory, relative to the project root. Defaults to the detected components dir. */\n dir?: string\n /** Overwrite an existing file. Default `false`. */\n force?: boolean\n /** Print the file instead of writing it. Default `false`. */\n dryRun?: boolean\n cwd?: string\n}\n\nexport interface AddResult {\n path: string\n contents: string\n written: boolean\n /** Packages the project needs but doesn't have. */\n missingDependencies: string[]\n}\n\nexport function addComponent(options: AddOptions): AddResult {\n const project = detectProject(options.cwd)\n const entry = findEntry(options.name)\n\n if (!entry) {\n throw new Error(\n `Unknown component \"${options.name}\". Run \\`ansh list\\` to see what's available.`,\n )\n }\n\n if (project.framework === 'unknown') {\n throw new Error(\n 'Could not detect a React, Next, Vue or Nuxt project. ' +\n 'Run this from your project root, or install the framework first.',\n )\n }\n\n const isVue = project.framework === 'vue' || project.framework === 'nuxt'\n const componentName = options.as ?? entry.component\n const extension = isVue ? 'vue' : project.typescript ? 'tsx' : 'jsx'\n\n const directory = options.dir ?? project.componentsDir\n const path = join(project.root, directory, `${componentName}.${extension}`)\n\n const contents = isVue\n ? renderVue(componentName, entry.component, entry.options, project)\n : renderReact(componentName, entry.component, entry.options, project)\n\n const missingDependencies = missingFor(project)\n\n if (options.dryRun) {\n return { path, contents, written: false, missingDependencies }\n }\n\n if (existsSync(path) && !options.force) {\n throw new Error(`${path} already exists. Pass --force to overwrite.`)\n }\n\n mkdirSync(dirname(path), { recursive: true })\n writeFileSync(path, contents, 'utf8')\n\n return { path, contents, written: true, missingDependencies }\n}\n\nfunction missingFor(project: ProjectInfo): string[] {\n if (project.installed) return []\n switch (project.framework) {\n case 'nuxt':\n return ['@ansh-ui/nuxt']\n case 'vue':\n return ['@ansh-ui/vue', '@ansh-ui/tokens']\n default:\n return ['@ansh-ui/react', '@ansh-ui/tokens']\n }\n}\n\n/**\n * Serialise a default value as source.\n *\n * Only the options worth surfacing are emitted — see {@link INTERESTING_OPTIONS}. Emitting all\n * twenty would produce a wall of noise that obscures the three an author will actually change.\n */\nfunction literal(value: unknown): string {\n if (typeof value === 'string') return JSON.stringify(value)\n if (Array.isArray(value)) return `[${value.map(literal).join(', ')}]`\n if (value === null) return 'null'\n if (typeof value === 'object') return JSON.stringify(value)\n return String(value)\n}\n\n/**\n * Options included in generated source.\n *\n * These are the ones that carry design intent — the knobs a designer asks to change. Structural and\n * performance options are omitted from the generated defaults but remain available as props, since\n * the wrapper spreads everything through.\n */\nconst INTERESTING_OPTIONS = new Set([\n 'colors',\n 'speed',\n 'intensity',\n 'opacity',\n 'blur',\n 'seed',\n 'strength',\n 'radius',\n 'max',\n 'distance',\n 'amount',\n 'count',\n])\n\nfunction pickDefaults(options: Array<{ name: string; default: unknown }>) {\n return options.filter((option) => INTERESTING_OPTIONS.has(option.name))\n}\n\nfunction renderReact(\n componentName: string,\n sourceComponent: string,\n options: Array<{ name: string; default: unknown }>,\n project: ProjectInfo,\n): string {\n const ts = project.typescript\n const defaults = pickDefaults(options)\n\n const defaultLines = defaults\n .map((option) => ` ${option.name}: ${literal(option.default)},`)\n .join('\\n')\n\n const propsType = ts\n ? `\\ntype ${componentName}Props = ComponentProps<typeof ${sourceComponent}>\\n`\n : ''\n\n const signature = ts\n ? `export function ${componentName}({ children, ...props }: ${componentName}Props) {`\n : `export function ${componentName}({ children, ...props }) {`\n\n const typeImport = ts ? `import type { ComponentProps } from 'react'\\n` : ''\n\n return `${typeImport}import { ${sourceComponent} } from '@ansh-ui/react'\n\n/**\n * ${componentName} — a project-local wrapper around Ansh's ${sourceComponent}.\n *\n * Edit the defaults below to match your design system. Every option remains overridable per\n * instance, because props spread after the defaults.\n *\n * Generated by \\`ansh add\\`. Safe to edit — it will not be regenerated unless you ask.\n */\nconst defaults = {\n${defaultLines}\n}\n\n${propsType}\n${signature}\n return (\n <${sourceComponent} {...defaults} {...props}>\n {children}\n </${sourceComponent}>\n )\n}\n`\n}\n\nfunction renderVue(\n componentName: string,\n sourceComponent: string,\n options: Array<{ name: string; default: unknown }>,\n project: ProjectInfo,\n): string {\n const defaults = pickDefaults(options)\n const defaultLines = defaults\n .map((option) => ` ${option.name}: ${literal(option.default)},`)\n .join('\\n')\n\n const lang = project.typescript ? ' lang=\"ts\"' : ''\n\n // Nuxt auto-imports Ansh components, so an explicit import there would be redundant — and\n // would shadow the auto-import in a way that breaks if the module's prefix option changes.\n const importLine =\n project.framework === 'nuxt'\n ? `// ${sourceComponent} is auto-imported by @ansh-ui/nuxt.`\n : `import { ${sourceComponent} } from '@ansh-ui/vue'`\n\n return `<script setup${lang}>\n${importLine}\n\n/**\n * ${componentName} — a project-local wrapper around Ansh's ${sourceComponent}.\n *\n * Edit the defaults below to match your design system. Every option remains overridable per\n * instance, because \\`$attrs\\` is bound after the defaults.\n *\n * Generated by \\`ansh add\\`. Safe to edit — it will not be regenerated unless you ask.\n */\nconst defaults = {\n${defaultLines}\n}\n</script>\n\n<template>\n <${sourceComponent} v-bind=\"{ ...defaults, ...$attrs }\">\n <slot />\n </${sourceComponent}>\n</template>\n`\n}\n","import { mkdirSync, writeFileSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport {\n checkContrast,\n createScale,\n harmony,\n parseColor,\n rgbToOklch,\n toHex,\n toOklchString,\n} from '@ansh-ui/core'\n\n/**\n * `ansh theme <color>` — generate a token override stylesheet from a brand colour.\n *\n * The job this does that hand-authoring doesn't: it **checks the result**. An 11-step scale\n * generated from a brand colour will, for certain hues, produce steps that fail contrast against\n * white or against each other — a saturated yellow at step 600 is a classic offender. Generating the\n * scale is easy; noticing that step 600 can't legally hold body text is the part people skip.\n *\n * So the emitted stylesheet carries contrast annotations as comments, and the report flags any step\n * that cannot be used for text.\n */\n\nexport interface ThemeOptions {\n /** Brand colour in any CSS syntax. */\n color: string\n /** Where to write the stylesheet. Prints to stdout when omitted. */\n out?: string\n /** Hue drift across the scale, in degrees. `0` keeps a single hue. Default `0`. */\n hueShift?: number\n /** Chroma falloff at the extremes, in `[0, 1]`. Default `0.35`. */\n chromaFalloff?: number\n /** Also emit a harmonious accent scale. Default `false`. */\n withAccent?: boolean\n}\n\nexport interface ThemeReport {\n css: string\n /** Steps whose contrast against white is below 4.5:1 — unusable for body text on light surfaces. */\n unsafeOnLight: string[]\n /** Steps whose contrast against near-black is below 4.5:1. */\n unsafeOnDark: string[]\n /** The step closest in lightness to the input colour. */\n nearestStep: string\n}\n\nconst TAILWIND_KEYS = ['50', '100', '200', '300', '400', '500', '600', '700', '800', '900', '950']\n\nexport function generateTheme(options: ThemeOptions): ThemeReport {\n const base = parseColor(options.color)\n const baseLightness = rgbToOklch(base).l\n\n const scale = createScale(base, {\n steps: 11,\n hueShift: options.hueShift ?? 0,\n chromaFalloff: options.chromaFalloff ?? 0.35,\n })\n\n const unsafeOnLight: string[] = []\n const unsafeOnDark: string[] = []\n\n const lines: string[] = []\n let nearestStep = '500'\n let nearestDistance = Infinity\n\n scale.colors.forEach((color, index) => {\n const key = TAILWIND_KEYS[index]\n const onLight = checkContrast(color, '#ffffff')\n const onDark = checkContrast(color, '#0b0b0f')\n\n if (!onLight.passes) unsafeOnLight.push(key)\n if (!onDark.passes) unsafeOnDark.push(key)\n\n const distance = Math.abs(rgbToOklch(color).l - baseLightness)\n if (distance < nearestDistance) {\n nearestDistance = distance\n nearestStep = key\n }\n\n // The comment carries the numbers, so a designer reviewing the file can see at a glance which\n // steps are safe for text without opening a contrast checker.\n lines.push(\n ` --ansh-brand-${key}: ${toOklchString(color)};` +\n ` /* ${toHex(color)} on-white ${onLight.ratio.toFixed(2)}:1` +\n ` on-black ${onDark.ratio.toFixed(2)}:1 */`,\n )\n })\n\n let accentLines = ''\n if (options.withAccent) {\n // A split-complementary partner: far enough from the brand hue to be clearly a different\n // colour, close enough to still look related. The straight complement is usually too harsh for\n // UI, which is why it isn't the default choice here.\n const [, accent] = harmony(base, 'splitComplementary')\n const accentScale = createScale(accent, { steps: 11 })\n accentLines =\n '\\n /* Accent — split-complementary partner to the brand hue. */\\n' +\n accentScale.colors\n .map((color, index) => ` --ansh-accent-${TAILWIND_KEYS[index]}: ${toOklchString(color)};`)\n .join('\\n') +\n '\\n'\n }\n\n const css = `/**\n * Ansh theme override.\n *\n * Generated by \\`ansh theme ${options.color}\\`.\n * Import this *after* \\`@ansh-ui/tokens/ansh.css\\` so it wins in the cascade.\n *\n * Contrast ratios are annotated per step. Steps marked unsafe cannot legally hold body text on the\n * corresponding surface — use them for fills, borders and large display type instead.\n */\n\n:root {\n${lines.join('\\n')}\n${accentLines}\n /* Wire the semantic accent tokens to the generated scale. */\n --ansh-accent-subtle: var(--ansh-brand-50);\n --ansh-accent-muted: var(--ansh-brand-100);\n --ansh-accent-default: var(--ansh-brand-600);\n --ansh-accent-hover: var(--ansh-brand-700);\n --ansh-accent-active: var(--ansh-brand-800);\n --ansh-accent-text: var(--ansh-brand-700);\n --ansh-border-focus: var(--ansh-brand-600);\n}\n\n/**\n * Dark theme.\n *\n * Not an inversion. Accents step *lighter* rather than mirroring their light-mode index, because\n * saturated colour reads as less vivid against a dark background (Helmholtz–Kohlrausch).\n */\n[data-theme='dark'] {\n --ansh-accent-subtle: color-mix(in oklab, var(--ansh-brand-950) 40%, transparent);\n --ansh-accent-muted: var(--ansh-brand-950);\n --ansh-accent-default: var(--ansh-brand-500);\n --ansh-accent-hover: var(--ansh-brand-400);\n --ansh-accent-active: var(--ansh-brand-300);\n --ansh-accent-text: var(--ansh-brand-300);\n --ansh-border-focus: var(--ansh-brand-400);\n}\n\n@media (prefers-color-scheme: dark) {\n :root:not([data-theme]) {\n --ansh-accent-subtle: color-mix(in oklab, var(--ansh-brand-950) 40%, transparent);\n --ansh-accent-muted: var(--ansh-brand-950);\n --ansh-accent-default: var(--ansh-brand-500);\n --ansh-accent-hover: var(--ansh-brand-400);\n --ansh-accent-active: var(--ansh-brand-300);\n --ansh-accent-text: var(--ansh-brand-300);\n --ansh-border-focus: var(--ansh-brand-400);\n }\n}\n`\n\n if (options.out) {\n mkdirSync(dirname(options.out), { recursive: true })\n writeFileSync(options.out, css, 'utf8')\n }\n\n return { css, unsafeOnLight, unsafeOnDark, nearestStep }\n}\n","import {\n createGradient,\n generatePalette,\n parseColor,\n perceivedLightness,\n rgbToOklch,\n toHex,\n toOklchString,\n} from '@ansh-ui/core'\n\n/**\n * `ansh palette` — generate and inspect palettes.\n *\n * Two modes:\n *\n * - **Generate** — a seeded palette from scratch. The same seed always produces the same palette,\n * so a designer who likes seed 4821 can pin it and get that palette back next week.\n * - **Inspect** — report a supplied palette's OKLCH decomposition and the gradient it produces.\n * The useful part is seeing the *interpolated midpoints*: a palette can look fine as swatches and\n * produce a muddy gradient, and this shows that before it ships.\n */\n\nexport interface PaletteReportOptions {\n /** Colours to inspect. Generates a new palette when omitted. */\n colors?: string[]\n /** Number of colours to generate. Default `5`. */\n count?: number\n seed?: number | string\n /** Overall lightness in `[0, 1]`. Default `0.65`. */\n lightness?: number\n /** Chroma as a fraction of the maximum available. Default `0.85`. */\n saturation?: number\n /** Hue span in degrees. Default `120`. */\n spread?: number\n /** Also print interpolated gradient midpoints. Default `true`. */\n gradient?: boolean\n}\n\nexport interface PaletteReport {\n colors: Array<{ hex: string; oklch: string; lightness: number; chroma: number; hue: number }>\n /** Interpolated samples across the palette, showing what a gradient through it looks like. */\n gradientSamples: string[]\n /** Copy-pasteable literal for a `colors` prop. */\n snippet: string\n}\n\nexport function generatePaletteReport(options: PaletteReportOptions = {}): PaletteReport {\n const parsed =\n options.colors && options.colors.length > 0\n ? options.colors.map((color) => parseColor(color))\n : generatePalette({\n count: options.count ?? 5,\n seed: options.seed ?? 1,\n lightness: options.lightness ?? 0.65,\n saturation: options.saturation ?? 0.85,\n spread: options.spread ?? 120,\n })\n\n const colors = parsed.map((color) => {\n const lch = rgbToOklch(color)\n return {\n hex: toHex(color),\n oklch: toOklchString(color),\n lightness: Number(lch.l.toFixed(4)),\n chroma: Number(lch.c.toFixed(4)),\n hue: Number(lch.h.toFixed(2)),\n }\n })\n\n // Sampled in OKLCH rather than OKLab: for a gradient *through a palette* the goal is maximum\n // vividness across the transitions, which is what travelling the hue circle gives.\n const gradientSamples =\n options.gradient === false || parsed.length < 2\n ? []\n : createGradient(parsed, { space: 'oklch' })\n .sample(9)\n .map((color) => toHex(color))\n\n const snippet = `colors={[${colors.map((c) => `'${c.hex}'`).join(', ')}]}`\n\n return { colors, gradientSamples, snippet }\n}\n\n/**\n * Sort a palette by perceived lightness and report the ordering.\n *\n * Useful for layered effects, where the draw order should generally run dark to light so brighter\n * colours land on top and read as nearer.\n */\nexport function orderByLightness(colors: string[]): Array<{ hex: string; lightness: number }> {\n return colors\n .map((color) => ({ hex: toHex(parseColor(color)), lightness: perceivedLightness(color) }))\n .sort((a, b) => a.lightness - b.lightness)\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/project.ts","../src/commands/list.ts","../src/commands/add.ts","../src/commands/theme.ts","../src/commands/palette.ts"],"names":["join","existsSync","mkdirSync","dirname","writeFileSync","parseColor","rgbToOklch","toHex","toOklchString"],"mappings":"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","file":"index.js","sourcesContent":["import { existsSync, readFileSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\n\n/**\n * Project detection.\n *\n * The CLI needs to know which framework it is generating for, whether the project uses TypeScript,\n * and where components live. Asking the user all of that on every invocation is friction for\n * information that is sitting in `package.json` and on disk — so we detect it, and only prompt for\n * what we genuinely cannot infer.\n */\n\nexport type Framework = 'react' | 'vue' | 'nuxt' | 'next' | 'unknown'\n\nexport interface ProjectInfo {\n root: string\n framework: Framework\n typescript: boolean\n /** Where generated components should go, relative to `root`. */\n componentsDir: string\n /** Detected import alias for the source root, e.g. `'@/'`. `null` when none is configured. */\n alias: string | null\n packageManager: 'pnpm' | 'yarn' | 'npm' | 'bun'\n /** `true` when the relevant `@ansh-ui/*` package is already a dependency. */\n installed: boolean\n}\n\n/** Walk up from `cwd` looking for a `package.json`, so the CLI works from a subdirectory. */\nfunction findRoot(cwd: string): string {\n let current = resolve(cwd)\n for (let depth = 0; depth < 10; depth++) {\n if (existsSync(join(current, 'package.json'))) return current\n const parent = resolve(current, '..')\n if (parent === current) break\n current = parent\n }\n return resolve(cwd)\n}\n\nfunction readJson(path: string): Record<string, unknown> | null {\n try {\n return JSON.parse(readFileSync(path, 'utf8')) as Record<string, unknown>\n } catch {\n return null\n }\n}\n\nexport function detectProject(cwd = process.cwd()): ProjectInfo {\n const root = findRoot(cwd)\n const pkg = readJson(join(root, 'package.json')) ?? {}\n\n const deps: Record<string, string> = {\n ...((pkg.dependencies as Record<string, string>) ?? {}),\n ...((pkg.devDependencies as Record<string, string>) ?? {}),\n }\n\n // Order matters: Nuxt projects also depend on Vue, and Next projects on React. Checking the\n // meta-framework first gives the more specific — and more useful — answer.\n const framework: Framework = deps.nuxt\n ? 'nuxt'\n : deps.next\n ? 'next'\n : deps.vue\n ? 'vue'\n : deps.react\n ? 'react'\n : 'unknown'\n\n const typescript = Boolean(deps.typescript) || existsSync(join(root, 'tsconfig.json'))\n\n const packageManager: ProjectInfo['packageManager'] = existsSync(join(root, 'pnpm-lock.yaml'))\n ? 'pnpm'\n : existsSync(join(root, 'bun.lockb')) || existsSync(join(root, 'bun.lock'))\n ? 'bun'\n : existsSync(join(root, 'yarn.lock'))\n ? 'yarn'\n : 'npm'\n\n return {\n root,\n framework,\n typescript,\n componentsDir: detectComponentsDir(root, framework),\n alias: detectAlias(root),\n packageManager,\n installed: Boolean(\n deps['@ansh-ui/react'] ||\n deps['@ansh-ui/vue'] ||\n deps['@ansh-ui/nuxt'] ||\n deps['@ansh-ui/core'],\n ),\n }\n}\n\n/**\n * Find where components already live, rather than imposing a convention.\n *\n * Dropping a file into `src/components` in a project that uses `app/ui` is the kind of small\n * disrespect that makes a tool feel foreign. Candidates are ordered by how strong a signal they are.\n */\nfunction detectComponentsDir(root: string, framework: Framework): string {\n const candidates =\n framework === 'nuxt'\n ? ['components', 'app/components', 'src/components']\n : ['src/components', 'components', 'app/components', 'src/lib/components', 'app/ui', 'src/ui']\n\n for (const candidate of candidates) {\n if (existsSync(join(root, candidate))) return candidate\n }\n\n // Nothing exists yet: pick the convention that matches the project's existing shape.\n if (existsSync(join(root, 'src'))) return 'src/components'\n if (framework === 'nuxt') return 'components'\n return 'components'\n}\n\n/**\n * Read the source alias from `tsconfig.json` so generated imports match the project's style.\n *\n * A generated file that writes `../../lib/utils` in a project where everything else says\n * `@/lib/utils` is immediately identifiable as machine-written.\n */\nfunction detectAlias(root: string): string | null {\n for (const file of ['tsconfig.json', 'jsconfig.json']) {\n const config = readJson(join(root, file))\n if (!config) continue\n\n const compilerOptions = config.compilerOptions as Record<string, unknown> | undefined\n const paths = compilerOptions?.paths as Record<string, string[]> | undefined\n if (!paths) continue\n\n for (const pattern of Object.keys(paths)) {\n // Match a plain wildcard alias like `\"@/*\"` or `\"~/*\"` — the overwhelmingly common shape.\n if (pattern.endsWith('/*')) return pattern.slice(0, -1)\n }\n }\n return null\n}\n\nexport interface KnownInconsistency {\n title: string\n detail: string\n}\n\n/**\n * Maintainer-facing issues logged in `docs/STATUS.md` §7 — restated here so a contributor\n * discovers them from `ansh doctor` output, not by reading a markdown file they may not know\n * exists. Kept in sync with STATUS.md by hand: this list should shrink exactly when that section\n * does, and for the same reason (the item was resolved), not because someone forgot one file.\n */\nconst KNOWN_INCONSISTENCIES: KnownInconsistency[] = [\n {\n title: 'License key prefix is still `aur_`',\n detail:\n 'A leftover from the Aurelis → Ansh rename (packages/license/src/public-key.ts). Changing it ' +\n 'without a dual-prefix verification path would invalidate already-issued keys — needs a ' +\n 'maintainer decision, not a drive-by fix. See STATUS.md §7.',\n },\n]\n\n/**\n * `ansh doctor` runs against whatever project it's invoked in — almost always a consumer's app.\n * The one exception worth detecting is the Ansh monorepo itself: a contributor running the CLI\n * from within its own source tree should see the maintainer-facing known-inconsistencies list\n * (above), which is meaningless noise for every other project `doctor` will ever run in.\n */\nexport function isAnshRepoRoot(root: string): boolean {\n const pkg = readJson(join(root, 'package.json'))\n return pkg?.name === 'ansh' && existsSync(join(root, 'packages/license/src/index.ts'))\n}\n\nexport function detectKnownInconsistencies(root: string): KnownInconsistency[] {\n return isAnshRepoRoot(root) ? KNOWN_INCONSISTENCIES : []\n}\n\n/** The install command for the detected package manager. */\nexport function installCommand(info: ProjectInfo, packages: string[]): string {\n const list = packages.join(' ')\n switch (info.packageManager) {\n case 'pnpm':\n return `pnpm add ${list}`\n case 'yarn':\n return `yarn add ${list}`\n case 'bun':\n return `bun add ${list}`\n default:\n return `npm install ${list}`\n }\n}\n","import { behaviours, effects } from '@ansh-ui/core'\n\n/**\n * Catalogue enumeration.\n *\n * Reads the registry rather than a hardcoded list, so a new effect appears in `ansh list` the\n * moment it is defined — no second place to update, and no possibility of the CLI advertising\n * something that doesn't exist or omitting something that does.\n */\n\nexport interface CatalogueEntry {\n name: string\n kind: 'effect' | 'behaviour'\n /** The component name in `@ansh-ui/react` and `@ansh-ui/vue`. */\n component: string\n /** Every option, with its default value, read from the definition. */\n options: Array<{ name: string; default: unknown }>\n}\n\n/**\n * Effect and behaviour names map to component names that read better than a mechanical\n * transformation would produce — `meteors` → `MeteorShower`, `blob` → `LiquidBlob`. Where a\n * definition isn't listed here, the name is PascalCased.\n */\nconst COMPONENT_NAMES: Record<string, string> = {\n aurora: 'AuroraBackground',\n 'mesh-gradient': 'MeshGradient',\n 'animated-gradient': 'AnimatedGradient',\n 'particle-field': 'ParticleField',\n constellation: 'Constellation',\n meteors: 'MeteorShower',\n rain: 'Rain',\n snow: 'Snow',\n fireflies: 'Fireflies',\n waves: 'Waves',\n blob: 'LiquidBlob',\n 'noise-layer': 'NoiseLayer',\n spotlight: 'Spotlight',\n magnetic: 'MagneticButton',\n tilt: 'TiltCard',\n ripple: 'Ripple',\n marquee: 'Marquee',\n 'scroll-reveal': 'ScrollReveal',\n parallax: 'Parallax',\n 'text-scramble': 'ScrambleText',\n}\n\n/**\n * Behaviours with no component in either binding. `split-text` is a building block (`AnimatedText`\n * does its own split so the markup server-renders), so `ansh add split-text` would generate an\n * import of a component that doesn't exist. Leaving it out of the catalogue is the honest answer.\n */\nconst NO_COMPONENT = new Set(['split-text'])\n\nexport function componentNameFor(name: string): string {\n return (\n COMPONENT_NAMES[name] ??\n name.replace(/(^|-)([a-z])/g, (_, __, letter: string) => letter.toUpperCase())\n )\n}\n\nexport function listCatalogue(filter?: 'effect' | 'behaviour'): CatalogueEntry[] {\n const entries: CatalogueEntry[] = []\n\n if (filter !== 'behaviour') {\n for (const [name, definition] of Object.entries(effects)) {\n entries.push({\n name,\n kind: 'effect',\n component: componentNameFor(name),\n options: describeOptions(definition.defaults as Record<string, unknown>),\n })\n }\n }\n\n if (filter !== 'effect') {\n for (const [name, definition] of Object.entries(behaviours)) {\n if (NO_COMPONENT.has(name)) continue\n entries.push({\n name,\n kind: 'behaviour',\n component: componentNameFor(name),\n options: describeOptions(definition.defaults as Record<string, unknown>),\n })\n }\n }\n\n return entries.sort((a, b) => a.name.localeCompare(b.name))\n}\n\n/**\n * Turn a `defaults` object into a documented option list.\n *\n * This is why {@link import('@ansh-ui/core').EffectDefinition}'s `defaults` is typed\n * `Required<Options>`: it makes \"every option has a documented default\" a compile-time guarantee,\n * which in turn makes this function complete by construction rather than by diligence.\n */\nfunction describeOptions(defaults: Record<string, unknown>): CatalogueEntry['options'] {\n return Object.entries(defaults)\n .map(([name, value]) => ({ name, default: value }))\n .sort((a, b) => a.name.localeCompare(b.name))\n}\n\n/** Look up a single entry by effect/behaviour name or by component name, case-insensitively. */\nexport function findEntry(query: string): CatalogueEntry | undefined {\n const needle = query.toLowerCase()\n return listCatalogue().find(\n (entry) => entry.name.toLowerCase() === needle || entry.component.toLowerCase() === needle,\n )\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { type ProjectInfo, detectProject } from '../project'\nimport { findEntry } from './list'\n\n/**\n * `ansh add <name>` — generate a local, editable wrapper for a component.\n *\n * ## Why a wrapper rather than a source copy\n *\n * shadcn/ui popularised copying component source into the project, and for *unstyled primitives*\n * that is exactly right: the value is in the markup and the styling, and you want to own both.\n *\n * Ansh is a different shape. The value is in the engine — an 800-line curl-noise particle system,\n * a spring solver, a colour pipeline — and copying that into an application would be actively\n * harmful: it would never receive a bug fix, and it would bloat the repository with code nobody on\n * the team intends to maintain.\n *\n * What developers actually want to own is the **configuration**: which colours, what intensity, what\n * it is called in their design system. So that is what this generates — a thin, fully-typed local\n * component with the project's own defaults baked in, importing the engine from the package.\n *\n * The result: `<HeroBackground />` in application code, one file to edit when the brand palette\n * changes, and engine fixes arrive through a normal dependency upgrade.\n */\n\nexport interface AddOptions {\n /** Effect or behaviour name, or component name. Case-insensitive. */\n name: string\n /** Local component name. Defaults to the catalogue's component name. */\n as?: string\n /** Target directory, relative to the project root. Defaults to the detected components dir. */\n dir?: string\n /** Overwrite an existing file. Default `false`. */\n force?: boolean\n /** Print the file instead of writing it. Default `false`. */\n dryRun?: boolean\n cwd?: string\n}\n\nexport interface AddResult {\n path: string\n contents: string\n written: boolean\n /** Packages the project needs but doesn't have. */\n missingDependencies: string[]\n}\n\nexport function addComponent(options: AddOptions): AddResult {\n const project = detectProject(options.cwd)\n const entry = findEntry(options.name)\n\n if (!entry) {\n throw new Error(\n `Unknown component \"${options.name}\". Run \\`ansh list\\` to see what's available.`,\n )\n }\n\n if (project.framework === 'unknown') {\n throw new Error(\n 'Could not detect a React, Next, Vue or Nuxt project. ' +\n 'Run this from your project root, or install the framework first.',\n )\n }\n\n const isVue = project.framework === 'vue' || project.framework === 'nuxt'\n const componentName = options.as ?? entry.component\n const extension = isVue ? 'vue' : project.typescript ? 'tsx' : 'jsx'\n\n const directory = options.dir ?? project.componentsDir\n const path = join(project.root, directory, `${componentName}.${extension}`)\n\n const contents = isVue\n ? renderVue(componentName, entry.component, entry.options, project)\n : renderReact(componentName, entry.component, entry.options, project)\n\n const missingDependencies = missingFor(project)\n\n if (options.dryRun) {\n return { path, contents, written: false, missingDependencies }\n }\n\n if (existsSync(path) && !options.force) {\n throw new Error(`${path} already exists. Pass --force to overwrite.`)\n }\n\n mkdirSync(dirname(path), { recursive: true })\n writeFileSync(path, contents, 'utf8')\n\n return { path, contents, written: true, missingDependencies }\n}\n\nfunction missingFor(project: ProjectInfo): string[] {\n if (project.installed) return []\n switch (project.framework) {\n case 'nuxt':\n return ['@ansh-ui/nuxt']\n case 'vue':\n return ['@ansh-ui/vue', '@ansh-ui/tokens']\n default:\n return ['@ansh-ui/react', '@ansh-ui/tokens']\n }\n}\n\n/**\n * Serialise a default value as source.\n *\n * Only the options worth surfacing are emitted — see {@link INTERESTING_OPTIONS}. Emitting all\n * twenty would produce a wall of noise that obscures the three an author will actually change.\n */\nfunction literal(value: unknown): string {\n if (typeof value === 'string') return JSON.stringify(value)\n if (Array.isArray(value)) return `[${value.map(literal).join(', ')}]`\n if (value === null) return 'null'\n if (typeof value === 'object') return JSON.stringify(value)\n return String(value)\n}\n\n/**\n * Options included in generated source.\n *\n * These are the ones that carry design intent — the knobs a designer asks to change. Structural and\n * performance options are omitted from the generated defaults but remain available as props, since\n * the wrapper spreads everything through.\n */\nconst INTERESTING_OPTIONS = new Set([\n 'colors',\n 'speed',\n 'intensity',\n 'opacity',\n 'blur',\n 'seed',\n 'strength',\n 'radius',\n 'max',\n 'distance',\n 'amount',\n 'count',\n])\n\nfunction pickDefaults(options: Array<{ name: string; default: unknown }>) {\n return options.filter((option) => INTERESTING_OPTIONS.has(option.name))\n}\n\nfunction renderReact(\n componentName: string,\n sourceComponent: string,\n options: Array<{ name: string; default: unknown }>,\n project: ProjectInfo,\n): string {\n const ts = project.typescript\n const defaults = pickDefaults(options)\n\n const defaultLines = defaults\n .map((option) => ` ${option.name}: ${literal(option.default)},`)\n .join('\\n')\n\n const propsType = ts\n ? `\\ntype ${componentName}Props = ComponentProps<typeof ${sourceComponent}>\\n`\n : ''\n\n const signature = ts\n ? `export function ${componentName}({ children, ...props }: ${componentName}Props) {`\n : `export function ${componentName}({ children, ...props }) {`\n\n const typeImport = ts ? `import type { ComponentProps } from 'react'\\n` : ''\n\n return `${typeImport}import { ${sourceComponent} } from '@ansh-ui/react'\n\n/**\n * ${componentName} — a project-local wrapper around Ansh's ${sourceComponent}.\n *\n * Edit the defaults below to match your design system. Every option remains overridable per\n * instance, because props spread after the defaults.\n *\n * Generated by \\`ansh add\\`. Safe to edit — it will not be regenerated unless you ask.\n */\nconst defaults = {\n${defaultLines}\n}\n\n${propsType}\n${signature}\n return (\n <${sourceComponent} {...defaults} {...props}>\n {children}\n </${sourceComponent}>\n )\n}\n`\n}\n\nfunction renderVue(\n componentName: string,\n sourceComponent: string,\n options: Array<{ name: string; default: unknown }>,\n project: ProjectInfo,\n): string {\n const defaults = pickDefaults(options)\n const defaultLines = defaults\n .map((option) => ` ${option.name}: ${literal(option.default)},`)\n .join('\\n')\n\n const lang = project.typescript ? ' lang=\"ts\"' : ''\n\n // Nuxt auto-imports Ansh components, so an explicit import there would be redundant — and\n // would shadow the auto-import in a way that breaks if the module's prefix option changes.\n const importLine =\n project.framework === 'nuxt'\n ? `// ${sourceComponent} is auto-imported by @ansh-ui/nuxt.`\n : `import { ${sourceComponent} } from '@ansh-ui/vue'`\n\n return `<script setup${lang}>\n${importLine}\n\n/**\n * ${componentName} — a project-local wrapper around Ansh's ${sourceComponent}.\n *\n * Edit the defaults below to match your design system. Every option remains overridable per\n * instance, because \\`$attrs\\` is bound after the defaults.\n *\n * Generated by \\`ansh add\\`. Safe to edit — it will not be regenerated unless you ask.\n */\nconst defaults = {\n${defaultLines}\n}\n</script>\n\n<template>\n <${sourceComponent} v-bind=\"{ ...defaults, ...$attrs }\">\n <slot />\n </${sourceComponent}>\n</template>\n`\n}\n","import { mkdirSync, writeFileSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport {\n checkContrast,\n createScale,\n harmony,\n parseColor,\n rgbToOklch,\n toHex,\n toOklchString,\n} from '@ansh-ui/core'\n\n/**\n * `ansh theme <color>` — generate a token override stylesheet from a brand colour.\n *\n * The job this does that hand-authoring doesn't: it **checks the result**. An 11-step scale\n * generated from a brand colour will, for certain hues, produce steps that fail contrast against\n * white or against each other — a saturated yellow at step 600 is a classic offender. Generating the\n * scale is easy; noticing that step 600 can't legally hold body text is the part people skip.\n *\n * So the emitted stylesheet carries contrast annotations as comments, and the report flags any step\n * that cannot be used for text.\n */\n\nexport interface ThemeOptions {\n /** Brand colour in any CSS syntax. */\n color: string\n /** Where to write the stylesheet. Prints to stdout when omitted. */\n out?: string\n /** Hue drift across the scale, in degrees. `0` keeps a single hue. Default `0`. */\n hueShift?: number\n /** Chroma falloff at the extremes, in `[0, 1]`. Default `0.35`. */\n chromaFalloff?: number\n /** Also emit a harmonious accent scale. Default `false`. */\n withAccent?: boolean\n}\n\nexport interface ThemeReport {\n css: string\n /** Steps whose contrast against white is below 4.5:1 — unusable for body text on light surfaces. */\n unsafeOnLight: string[]\n /** Steps whose contrast against near-black is below 4.5:1. */\n unsafeOnDark: string[]\n /** The step closest in lightness to the input colour. */\n nearestStep: string\n}\n\nconst TAILWIND_KEYS = ['50', '100', '200', '300', '400', '500', '600', '700', '800', '900', '950']\n\nexport function generateTheme(options: ThemeOptions): ThemeReport {\n const base = parseColor(options.color)\n const baseLightness = rgbToOklch(base).l\n\n const scale = createScale(base, {\n steps: 11,\n hueShift: options.hueShift ?? 0,\n chromaFalloff: options.chromaFalloff ?? 0.35,\n })\n\n const unsafeOnLight: string[] = []\n const unsafeOnDark: string[] = []\n\n const lines: string[] = []\n let nearestStep = '500'\n let nearestDistance = Infinity\n\n scale.colors.forEach((color, index) => {\n const key = TAILWIND_KEYS[index]\n const onLight = checkContrast(color, '#ffffff')\n const onDark = checkContrast(color, '#0b0b0f')\n\n if (!onLight.passes) unsafeOnLight.push(key)\n if (!onDark.passes) unsafeOnDark.push(key)\n\n const distance = Math.abs(rgbToOklch(color).l - baseLightness)\n if (distance < nearestDistance) {\n nearestDistance = distance\n nearestStep = key\n }\n\n // The comment carries the numbers, so a designer reviewing the file can see at a glance which\n // steps are safe for text without opening a contrast checker.\n lines.push(\n ` --ansh-brand-${key}: ${toOklchString(color)};` +\n ` /* ${toHex(color)} on-white ${onLight.ratio.toFixed(2)}:1` +\n ` on-black ${onDark.ratio.toFixed(2)}:1 */`,\n )\n })\n\n let accentLines = ''\n if (options.withAccent) {\n // A split-complementary partner: far enough from the brand hue to be clearly a different\n // colour, close enough to still look related. The straight complement is usually too harsh for\n // UI, which is why it isn't the default choice here.\n const [, accent] = harmony(base, 'splitComplementary')\n const accentScale = createScale(accent, { steps: 11 })\n accentLines =\n '\\n /* Accent — split-complementary partner to the brand hue. */\\n' +\n accentScale.colors\n .map((color, index) => ` --ansh-accent-${TAILWIND_KEYS[index]}: ${toOklchString(color)};`)\n .join('\\n') +\n '\\n'\n }\n\n const css = `/**\n * Ansh theme override.\n *\n * Generated by \\`ansh theme ${options.color}\\`.\n * Import this *after* \\`@ansh-ui/tokens/ansh.css\\` so it wins in the cascade.\n *\n * Contrast ratios are annotated per step. Steps marked unsafe cannot legally hold body text on the\n * corresponding surface — use them for fills, borders and large display type instead.\n */\n\n:root {\n${lines.join('\\n')}\n${accentLines}\n /* Wire the semantic accent tokens to the generated scale. */\n --ansh-accent-subtle: var(--ansh-brand-50);\n --ansh-accent-muted: var(--ansh-brand-100);\n --ansh-accent-default: var(--ansh-brand-600);\n --ansh-accent-hover: var(--ansh-brand-700);\n --ansh-accent-active: var(--ansh-brand-800);\n --ansh-accent-text: var(--ansh-brand-700);\n --ansh-border-focus: var(--ansh-brand-600);\n}\n\n/**\n * Dark theme.\n *\n * Not an inversion. Accents step *lighter* rather than mirroring their light-mode index, because\n * saturated colour reads as less vivid against a dark background (Helmholtz–Kohlrausch).\n */\n[data-theme='dark'] {\n --ansh-accent-subtle: color-mix(in oklab, var(--ansh-brand-950) 40%, transparent);\n --ansh-accent-muted: var(--ansh-brand-950);\n --ansh-accent-default: var(--ansh-brand-500);\n --ansh-accent-hover: var(--ansh-brand-400);\n --ansh-accent-active: var(--ansh-brand-300);\n --ansh-accent-text: var(--ansh-brand-300);\n --ansh-border-focus: var(--ansh-brand-400);\n}\n\n@media (prefers-color-scheme: dark) {\n :root:not([data-theme]) {\n --ansh-accent-subtle: color-mix(in oklab, var(--ansh-brand-950) 40%, transparent);\n --ansh-accent-muted: var(--ansh-brand-950);\n --ansh-accent-default: var(--ansh-brand-500);\n --ansh-accent-hover: var(--ansh-brand-400);\n --ansh-accent-active: var(--ansh-brand-300);\n --ansh-accent-text: var(--ansh-brand-300);\n --ansh-border-focus: var(--ansh-brand-400);\n }\n}\n`\n\n if (options.out) {\n mkdirSync(dirname(options.out), { recursive: true })\n writeFileSync(options.out, css, 'utf8')\n }\n\n return { css, unsafeOnLight, unsafeOnDark, nearestStep }\n}\n","import {\n createGradient,\n generatePalette,\n parseColor,\n perceivedLightness,\n rgbToOklch,\n toHex,\n toOklchString,\n} from '@ansh-ui/core'\n\n/**\n * `ansh palette` — generate and inspect palettes.\n *\n * Two modes:\n *\n * - **Generate** — a seeded palette from scratch. The same seed always produces the same palette,\n * so a designer who likes seed 4821 can pin it and get that palette back next week.\n * - **Inspect** — report a supplied palette's OKLCH decomposition and the gradient it produces.\n * The useful part is seeing the *interpolated midpoints*: a palette can look fine as swatches and\n * produce a muddy gradient, and this shows that before it ships.\n */\n\nexport interface PaletteReportOptions {\n /** Colours to inspect. Generates a new palette when omitted. */\n colors?: string[]\n /** Number of colours to generate. Default `5`. */\n count?: number\n seed?: number | string\n /** Overall lightness in `[0, 1]`. Default `0.65`. */\n lightness?: number\n /** Chroma as a fraction of the maximum available. Default `0.85`. */\n saturation?: number\n /** Hue span in degrees. Default `120`. */\n spread?: number\n /** Also print interpolated gradient midpoints. Default `true`. */\n gradient?: boolean\n}\n\nexport interface PaletteReport {\n colors: Array<{ hex: string; oklch: string; lightness: number; chroma: number; hue: number }>\n /** Interpolated samples across the palette, showing what a gradient through it looks like. */\n gradientSamples: string[]\n /** Copy-pasteable literal for a `colors` prop. */\n snippet: string\n}\n\nexport function generatePaletteReport(options: PaletteReportOptions = {}): PaletteReport {\n const parsed =\n options.colors && options.colors.length > 0\n ? options.colors.map((color) => parseColor(color))\n : generatePalette({\n count: options.count ?? 5,\n seed: options.seed ?? 1,\n lightness: options.lightness ?? 0.65,\n saturation: options.saturation ?? 0.85,\n spread: options.spread ?? 120,\n })\n\n const colors = parsed.map((color) => {\n const lch = rgbToOklch(color)\n return {\n hex: toHex(color),\n oklch: toOklchString(color),\n lightness: Number(lch.l.toFixed(4)),\n chroma: Number(lch.c.toFixed(4)),\n hue: Number(lch.h.toFixed(2)),\n }\n })\n\n // Sampled in OKLCH rather than OKLab: for a gradient *through a palette* the goal is maximum\n // vividness across the transitions, which is what travelling the hue circle gives.\n const gradientSamples =\n options.gradient === false || parsed.length < 2\n ? []\n : createGradient(parsed, { space: 'oklch' })\n .sample(9)\n .map((color) => toHex(color))\n\n const snippet = `colors={[${colors.map((c) => `'${c.hex}'`).join(', ')}]}`\n\n return { colors, gradientSamples, snippet }\n}\n\n/**\n * Sort a palette by perceived lightness and report the ordering.\n *\n * Useful for layered effects, where the draw order should generally run dark to light so brighter\n * colours land on top and read as nearer.\n */\nexport function orderByLightness(colors: string[]): Array<{ hex: string; lightness: number }> {\n return colors\n .map((color) => ({ hex: toHex(parseColor(color)), lightness: perceivedLightness(color) }))\n .sort((a, b) => a.lightness - b.lightness)\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ansh-ui/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "The Ansh CLI — scaffold components, generate themes and palettes, and inspect the catalogue.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
},
|
|
32
32
|
"types": "./dist/index.d.ts",
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@ansh-ui/core": "0.
|
|
35
|
-
"@ansh-ui/tokens": "0.
|
|
34
|
+
"@ansh-ui/core": "0.3.1",
|
|
35
|
+
"@ansh-ui/tokens": "0.3.1"
|
|
36
36
|
},
|
|
37
37
|
"engines": {
|
|
38
38
|
"node": ">=18.18.0"
|