@axis-ds/cli 1.6.1 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -1
- package/dist/{chunk-NNFSJISD.js → chunk-2PNCUPCG.js} +73 -34
- package/dist/chunk-HFMMK6R4.js +35 -0
- package/dist/{chunk-ZVVACWEW.js → chunk-LVMDBOXD.js} +32 -13
- package/dist/index.js +210 -100
- package/dist/monet.d.ts +4 -1
- package/dist/monet.js +2 -1
- package/dist/registry/agentic-agent-avatar.json +1 -1
- package/dist/registry/agentic-approval-card.json +1 -1
- package/dist/registry/agentic-attachment-card.json +1 -1
- package/dist/registry/agentic-code-block.json +1 -1
- package/dist/registry/agentic-context-panel.json +1 -1
- package/dist/registry/agentic-diff-viewer.json +1 -1
- package/dist/registry/agentic-feedback-buttons.json +1 -1
- package/dist/registry/agentic-message-bubble.json +1 -1
- package/dist/registry/agentic-plan-card.json +1 -1
- package/dist/registry/agentic-recovery-banner.json +1 -1
- package/dist/registry/agentic-run-progress.json +1 -1
- package/dist/registry/agentic-step-timeline.json +1 -1
- package/dist/registry/agentic-token-usage-indicator.json +1 -1
- package/dist/registry/agentic-tool-call-card.json +1 -1
- package/dist/registry/dialog.json +1 -1
- package/dist/registry/index.json +17 -17
- package/dist/registry/registry.json +17 -17
- package/dist/registry/toast.json +1 -1
- package/dist/v0.d.ts +8 -4
- package/dist/v0.js +2 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
MonetClient
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-LVMDBOXD.js";
|
|
5
5
|
import {
|
|
6
6
|
V0Client
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-2PNCUPCG.js";
|
|
8
|
+
import {
|
|
9
|
+
NonInteractiveError,
|
|
10
|
+
ask,
|
|
11
|
+
failNonInteractive,
|
|
12
|
+
isInteractive,
|
|
13
|
+
noteDefault
|
|
14
|
+
} from "./chunk-HFMMK6R4.js";
|
|
8
15
|
import {
|
|
9
16
|
registerSyncCommand
|
|
10
17
|
} from "./chunk-7CDXEBEE.js";
|
|
@@ -1106,17 +1113,59 @@ function toSearchItem(c) {
|
|
|
1106
1113
|
url: `/library/${c.category}/${c.slug}`
|
|
1107
1114
|
};
|
|
1108
1115
|
}
|
|
1116
|
+
var sourceTypeOf = (item) => typeof item.source === "string" ? item.source : item.source.type;
|
|
1117
|
+
function resolveRouteSlugs(items) {
|
|
1118
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1119
|
+
for (const item of items) {
|
|
1120
|
+
const key = `${item.category}/${item.slug}`;
|
|
1121
|
+
if (!groups.has(key)) groups.set(key, []);
|
|
1122
|
+
groups.get(key).push(item);
|
|
1123
|
+
}
|
|
1124
|
+
const result = /* @__PURE__ */ new Map();
|
|
1125
|
+
for (const [key, group] of groups) {
|
|
1126
|
+
if (group.length === 1) {
|
|
1127
|
+
result.set(group[0].id, group[0].slug);
|
|
1128
|
+
continue;
|
|
1129
|
+
}
|
|
1130
|
+
const axis = group.filter((i) => sourceTypeOf(i) === "axis");
|
|
1131
|
+
if (axis.length > 1) {
|
|
1132
|
+
throw new Error(`\uC0C1\uC138 \uC8FC\uC18C /library/${key} \uB97C AXIS \uD56D\uBAA9 ${axis.map((i) => i.id).join(", ")} \uAC00 \uD568\uAED8 \uC501\uB2C8\uB2E4`);
|
|
1133
|
+
}
|
|
1134
|
+
const keeper = axis[0] || group[0];
|
|
1135
|
+
for (const item of group) {
|
|
1136
|
+
result.set(item.id, item === keeper ? item.slug : `${sourceTypeOf(item)}-${item.slug}`);
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
const seen = /* @__PURE__ */ new Map();
|
|
1140
|
+
for (const item of items) {
|
|
1141
|
+
const key = `${item.category}/${result.get(item.id)}`;
|
|
1142
|
+
const other = seen.get(key);
|
|
1143
|
+
if (other !== void 0 && other !== item.id) {
|
|
1144
|
+
throw new Error(`slug \uB97C \uBC14\uAFBC \uB4A4\uC5D0\uB3C4 \uC0C1\uC138 \uC8FC\uC18C /library/${key} \uAC00 ${other}, ${item.id} \uC5D0\uC11C \uACB9\uCE69\uB2C8\uB2E4`);
|
|
1145
|
+
}
|
|
1146
|
+
seen.set(key, item.id);
|
|
1147
|
+
}
|
|
1148
|
+
return result;
|
|
1149
|
+
}
|
|
1150
|
+
function withRouteSlugs(items) {
|
|
1151
|
+
const slugs = resolveRouteSlugs(items);
|
|
1152
|
+
return items.map((item) => slugs.get(item.id) === item.slug ? item : { ...item, slug: slugs.get(item.id) });
|
|
1153
|
+
}
|
|
1154
|
+
function componentFileOf(item) {
|
|
1155
|
+
return `components/${item.id}.json`;
|
|
1156
|
+
}
|
|
1109
1157
|
var Publisher = class {
|
|
1110
1158
|
defaultOutputDir = "apps/web/public/library";
|
|
1111
1159
|
/**
|
|
1112
1160
|
* 라이브러리 인덱스를 사이트에 배치
|
|
1113
1161
|
*/
|
|
1114
|
-
async publish(
|
|
1162
|
+
async publish(input, options = {}) {
|
|
1115
1163
|
const outputDir = options.outputDir || this.defaultOutputDir;
|
|
1116
1164
|
const files = [];
|
|
1117
1165
|
const errors = [];
|
|
1118
1166
|
const spinner = ora("\uB77C\uC774\uBE0C\uB7EC\uB9AC \uBC30\uCE58 \uC911...").start();
|
|
1119
1167
|
try {
|
|
1168
|
+
const index = { ...input, components: withRouteSlugs(input.components) };
|
|
1120
1169
|
await fs3.ensureDir(outputDir);
|
|
1121
1170
|
const indexPath = path3.join(outputDir, "index.json");
|
|
1122
1171
|
await this.writeJson(indexPath, this.createPublicIndex(index), options.minify);
|
|
@@ -1143,7 +1192,7 @@ var Publisher = class {
|
|
|
1143
1192
|
const componentsDir = path3.join(outputDir, "components");
|
|
1144
1193
|
await fs3.ensureDir(componentsDir);
|
|
1145
1194
|
for (const component of index.components) {
|
|
1146
|
-
const componentPath = path3.join(
|
|
1195
|
+
const componentPath = path3.join(outputDir, componentFileOf(component));
|
|
1147
1196
|
await this.writeJson(componentPath, this.createPublicComponent(component), options.minify);
|
|
1148
1197
|
files.push(componentPath);
|
|
1149
1198
|
}
|
|
@@ -1400,6 +1449,25 @@ async function refreshAxisLibrary(options) {
|
|
|
1400
1449
|
}
|
|
1401
1450
|
for (const f of existingFiles.values()) if (f.data.source?.type === AXIS) oldAxisIds.add(f.data.id);
|
|
1402
1451
|
const removed = [...oldAxisIds].filter((id) => !axisIds.has(id)).sort();
|
|
1452
|
+
const routeSlugs = resolveRouteSlugs([...extOrder.map((id) => extCategory.get(id)), ...axisComponents]);
|
|
1453
|
+
const renamedSlugs = {};
|
|
1454
|
+
const renamedFrom = {};
|
|
1455
|
+
for (const id of extOrder) {
|
|
1456
|
+
const slug = routeSlugs.get(id);
|
|
1457
|
+
const full = extCategory.get(id);
|
|
1458
|
+
if (slug === full.slug) continue;
|
|
1459
|
+
renamedSlugs[id] = slug;
|
|
1460
|
+
renamedFrom[id] = full.slug;
|
|
1461
|
+
extCategory.set(id, { ...full, slug });
|
|
1462
|
+
extIndex.set(id, { ...extIndex.get(id), slug });
|
|
1463
|
+
const s = extSearch.get(id);
|
|
1464
|
+
extSearch.set(id, { ...s, slug, url: `/library/${s.category}/${slug}` });
|
|
1465
|
+
}
|
|
1466
|
+
for (const c of axisComponents) {
|
|
1467
|
+
const slug = routeSlugs.get(c.id);
|
|
1468
|
+
if (slug === c.slug) continue;
|
|
1469
|
+
throw new Error(`AXIS \uD56D\uBAA9 ${c.id} \uC758 slug \uAC00 ${slug} \uB85C \uBC14\uB00C\uC5B4\uC57C \uD569\uB2C8\uB2E4. \uC218\uC9D1 \uACB0\uACFC\uB97C \uD655\uC778\uD558\uC138\uC694`);
|
|
1470
|
+
}
|
|
1403
1471
|
const indexEntries = [
|
|
1404
1472
|
...extOrder.map((id) => extIndex.get(id)),
|
|
1405
1473
|
...axisComponents.map((c) => toIndexEntry(c))
|
|
@@ -1457,24 +1525,18 @@ async function refreshAxisLibrary(options) {
|
|
|
1457
1525
|
})
|
|
1458
1526
|
);
|
|
1459
1527
|
}
|
|
1460
|
-
const
|
|
1461
|
-
const
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
const existing = existingFiles.get(slug);
|
|
1467
|
-
const extForSlug = extOrder.map((id) => extCategory.get(id)).filter((c) => c.slug === slug);
|
|
1468
|
-
const existingIsExternal = !!existing && extForSlug.some((c) => c.id === existing.data.id);
|
|
1469
|
-
if (existingIsExternal) {
|
|
1470
|
-
if (axis) shadowedAxis.push(axis.id);
|
|
1471
|
-
continue;
|
|
1472
|
-
}
|
|
1473
|
-
if (axis) {
|
|
1474
|
-
outputs.set(`components/${slug}.json`, serialize(axis));
|
|
1528
|
+
const finalFiles = /* @__PURE__ */ new Set();
|
|
1529
|
+
for (const c of allPublic) {
|
|
1530
|
+
const rel3 = componentFileOf(c);
|
|
1531
|
+
finalFiles.add(rel3);
|
|
1532
|
+
if (c.source.type === AXIS) {
|
|
1533
|
+
outputs.set(rel3, serialize(c));
|
|
1475
1534
|
continue;
|
|
1476
1535
|
}
|
|
1477
|
-
|
|
1536
|
+
const same = (f) => f.data?.id === c.id && isDeepStrictEqual(f.data, c);
|
|
1537
|
+
const atKey = existingFiles.get(c.id);
|
|
1538
|
+
const kept = atKey && same(atKey) ? atKey : [...existingFiles.values()].find(same);
|
|
1539
|
+
outputs.set(rel3, kept ? kept.raw : serialize(c));
|
|
1478
1540
|
}
|
|
1479
1541
|
const writtenFiles = [];
|
|
1480
1542
|
for (const [rel3, content] of outputs) {
|
|
@@ -1485,13 +1547,13 @@ async function refreshAxisLibrary(options) {
|
|
|
1485
1547
|
if (!options.dryRun) await fs4.writeFile(file, content, "utf-8");
|
|
1486
1548
|
}
|
|
1487
1549
|
const removedFiles = [];
|
|
1488
|
-
for (const
|
|
1489
|
-
|
|
1490
|
-
|
|
1550
|
+
for (const key of existingFiles.keys()) {
|
|
1551
|
+
const rel3 = `components/${key}.json`;
|
|
1552
|
+
if (finalFiles.has(rel3)) continue;
|
|
1491
1553
|
removedFiles.push(rel3);
|
|
1492
1554
|
if (!options.dryRun) await fs4.remove(path4.join(libraryDir, rel3));
|
|
1493
1555
|
}
|
|
1494
|
-
return { added, changed, unchanged, removed,
|
|
1556
|
+
return { added, changed, unchanged, removed, renamedSlugs, renamedFrom, writtenFiles, removedFiles, stats };
|
|
1495
1557
|
}
|
|
1496
1558
|
function registerRefreshAxisCommand(libraryCmd2) {
|
|
1497
1559
|
libraryCmd2.command("refresh-axis").description("AXIS \uD56D\uBAA9\uB9CC \uC800\uC7A5\uC18C \uC18C\uC2A4\uC5D0\uC11C \uB2E4\uC2DC \uB9CC\uB4E6 (\uC678\uBD80 \uC18C\uC2A4 \uD56D\uBAA9\uC740 \uADF8\uB300\uB85C, \uB124\uD2B8\uC6CC\uD06C \uC5C6\uC74C)").option("--root <dir>", "\uC800\uC7A5\uC18C \uB8E8\uD2B8", process.cwd()).option("-o, --output <dir>", "library \uB514\uB809\uD130\uB9AC (\uB8E8\uD2B8 \uAE30\uC900)", "apps/web/public/library").option("--updated-at <iso>", "\uBC14\uB010 \uD56D\uBAA9\uC5D0 \uAE30\uB85D\uD560 \uC2DC\uAC01 (\uAE30\uBCF8: \uC624\uB298 KST \uB0A0\uC9DC\uC758 00:00:00.000Z)").option("--dry-run", "\uD30C\uC77C\uC744 \uC4F0\uC9C0 \uC54A\uACE0 \uBC14\uB014 \uB0B4\uC6A9\uB9CC \uCD9C\uB825").action(async (opts) => {
|
|
@@ -1511,9 +1573,12 @@ ${head}AXIS library \uC7AC\uC0DD\uC131`));
|
|
|
1511
1573
|
for (const id of result.added) console.log(chalk2.green(` + ${id}`));
|
|
1512
1574
|
for (const id of result.changed) console.log(chalk2.yellow(` ~ ${id}`));
|
|
1513
1575
|
for (const id of result.removed) console.log(chalk2.red(` - ${id}`));
|
|
1514
|
-
|
|
1576
|
+
const renamed = Object.entries(result.renamedSlugs);
|
|
1577
|
+
if (renamed.length > 0) {
|
|
1515
1578
|
console.log(
|
|
1516
|
-
chalk2.yellow(
|
|
1579
|
+
chalk2.yellow(
|
|
1580
|
+
` \uC0C1\uC138 \uC8FC\uC18C\uAC00 \uACB9\uCCD0 slug \uB97C \uBC14\uAFC8(WI-0060): ${renamed.map(([id, slug]) => `${id}: ${result.renamedFrom[id] ?? id} \u2192 ${slug}`).join(", ")}`
|
|
1581
|
+
)
|
|
1517
1582
|
);
|
|
1518
1583
|
}
|
|
1519
1584
|
console.log(` \uD30C\uC77C \uC4F0\uAE30 ${result.writtenFiles.length}\uAC1C \xB7 \uC0AD\uC81C ${result.removedFiles.length}\uAC1C`);
|
|
@@ -1748,7 +1813,6 @@ import fs8 from "fs-extra";
|
|
|
1748
1813
|
import path9 from "path";
|
|
1749
1814
|
import chalk5 from "chalk";
|
|
1750
1815
|
import ora3 from "ora";
|
|
1751
|
-
import prompts from "prompts";
|
|
1752
1816
|
|
|
1753
1817
|
// src/template/post-install.ts
|
|
1754
1818
|
import fs6 from "fs-extra";
|
|
@@ -2067,22 +2131,17 @@ function majorFromVersion(version) {
|
|
|
2067
2131
|
}
|
|
2068
2132
|
function detectTailwind(baseDirInput, pkg) {
|
|
2069
2133
|
const baseDir = resolve(baseDirInput);
|
|
2070
|
-
const installedFile = join(baseDir, "node_modules", "tailwindcss", "package.json");
|
|
2071
2134
|
const declared = pkg ? hasDependency2(pkg, "tailwindcss") : void 0;
|
|
2072
2135
|
const bounds = declared !== void 0 ? tailwindMajorBounds(declared) : void 0;
|
|
2073
2136
|
const declaredMajor = bounds?.lower;
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
const
|
|
2078
|
-
if (
|
|
2079
|
-
|
|
2080
|
-
if (declared !== void 0 && bounds !== void 0 && !majorWithin(major, bounds)) {
|
|
2081
|
-
found.mismatch = { declared, declaredMajor: bounds.lower };
|
|
2082
|
-
}
|
|
2083
|
-
return found;
|
|
2137
|
+
const version = isPnpProject(baseDir) ? void 0 : findInstalledPackage(baseDir, "tailwindcss")?.version;
|
|
2138
|
+
const major = majorFromVersion(version);
|
|
2139
|
+
if (version !== void 0 && major !== void 0) {
|
|
2140
|
+
const found = { major, source: "installed", value: version };
|
|
2141
|
+
if (declared !== void 0 && bounds !== void 0 && !majorWithin(major, bounds)) {
|
|
2142
|
+
found.mismatch = { declared, declaredMajor: bounds.lower };
|
|
2084
2143
|
}
|
|
2085
|
-
|
|
2144
|
+
return found;
|
|
2086
2145
|
}
|
|
2087
2146
|
if (declared !== void 0) {
|
|
2088
2147
|
if (declaredMajor !== void 0) return { major: declaredMajor, source: "declared", value: declared };
|
|
@@ -2225,19 +2284,9 @@ function rangeLowerAtLeast(range, min) {
|
|
|
2225
2284
|
if (!lower || !target) return void 0;
|
|
2226
2285
|
return compareLower(lower, target) >= 0;
|
|
2227
2286
|
}
|
|
2228
|
-
function
|
|
2229
|
-
if (
|
|
2230
|
-
|
|
2231
|
-
if (!/^v?\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(v) || /^v?0\.0\.0-/.test(v)) return void 0;
|
|
2232
|
-
return v;
|
|
2233
|
-
}
|
|
2234
|
-
function installedVersion(baseDir, name) {
|
|
2235
|
-
try {
|
|
2236
|
-
const parsed = JSON.parse(readFileSync2(join(baseDir, "node_modules", ...name.split("/"), "package.json"), "utf8"));
|
|
2237
|
-
return isPlainObject2(parsed) ? exactVersion(parsed.version) : void 0;
|
|
2238
|
-
} catch {
|
|
2239
|
-
return void 0;
|
|
2240
|
-
}
|
|
2287
|
+
function installedAxisVersion(baseDir, name) {
|
|
2288
|
+
if (isPnpProject(baseDir)) return void 0;
|
|
2289
|
+
return findInstalledPackage(baseDir, name)?.version;
|
|
2241
2290
|
}
|
|
2242
2291
|
function axisPackagesBelowTailwind4(pkg, baseDirInput) {
|
|
2243
2292
|
if (!pkg) return [];
|
|
@@ -2247,7 +2296,7 @@ function axisPackagesBelowTailwind4(pkg, baseDirInput) {
|
|
|
2247
2296
|
for (const name of TAILWIND4_AXIS_PACKAGES) {
|
|
2248
2297
|
const range = hasDependency2(pkg, name);
|
|
2249
2298
|
if (range === void 0 || range.trim().startsWith("workspace:")) continue;
|
|
2250
|
-
const installed = baseDir !== void 0 ?
|
|
2299
|
+
const installed = baseDir !== void 0 ? installedAxisVersion(baseDir, name) : void 0;
|
|
2251
2300
|
const installedLower = installed !== void 0 ? lowerOf(installed) : void 0;
|
|
2252
2301
|
if (installed !== void 0 && installedLower !== void 0) {
|
|
2253
2302
|
if (compareLower(installedLower, min) < 0) out.push({ name, range, status: "below", source: "installed", installed });
|
|
@@ -2834,12 +2883,23 @@ async function applyTemplate(slug, options) {
|
|
|
2834
2883
|
for (const c of conflicts) {
|
|
2835
2884
|
console.log(chalk5.gray(` - ${c}`));
|
|
2836
2885
|
}
|
|
2837
|
-
const
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2886
|
+
const interactive = options.interactive ?? isInteractive();
|
|
2887
|
+
if (!interactive) {
|
|
2888
|
+
failNonInteractive("\uCDA9\uB3CC \uD30C\uC77C\uC744 \uB36E\uC5B4\uC4F8\uC9C0 \uBB3C\uC744 \uC218 \uC5C6\uC5B4 \uC544\uBB34\uAC83\uB3C4 \uC4F0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.", [
|
|
2889
|
+
`\uB36E\uC5B4\uC4F0\uB824\uBA74: axis template apply ${slug} -y`,
|
|
2890
|
+
`\uBBF8\uB9AC\uBCF4\uAE30: axis template apply ${slug} --dry-run`
|
|
2891
|
+
]);
|
|
2892
|
+
return;
|
|
2893
|
+
}
|
|
2894
|
+
const { proceed } = await ask(
|
|
2895
|
+
{
|
|
2896
|
+
type: "confirm",
|
|
2897
|
+
name: "proceed",
|
|
2898
|
+
message: "\uCDA9\uB3CC \uD30C\uC77C\uC744 \uB36E\uC5B4\uC4F0\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
|
|
2899
|
+
initial: false
|
|
2900
|
+
},
|
|
2901
|
+
interactive
|
|
2902
|
+
);
|
|
2843
2903
|
if (!proceed) {
|
|
2844
2904
|
console.log(chalk5.gray("\uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4."));
|
|
2845
2905
|
return;
|
|
@@ -2891,20 +2951,31 @@ async function applyTemplate(slug, options) {
|
|
|
2891
2951
|
'${detail.name}' \uD15C\uD50C\uB9BF \uC801\uC6A9 \uC644\uB8CC!`));
|
|
2892
2952
|
}
|
|
2893
2953
|
async function initTemplate(slug, options) {
|
|
2954
|
+
const interactive = options.interactive ?? isInteractive();
|
|
2894
2955
|
let selectedSlug = slug;
|
|
2895
2956
|
if (!selectedSlug) {
|
|
2957
|
+
if (!interactive) {
|
|
2958
|
+
failNonInteractive("\uD15C\uD50C\uB9BF\uC744 \uACE0\uB97C \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uD15C\uD50C\uB9BF \uC774\uB984\uC744 \uC8FC\uC138\uC694.", [
|
|
2959
|
+
"\uC0AC\uC6A9\uBC95: axis template init <name> [--dir <path>] [-y]",
|
|
2960
|
+
"\uBAA9\uB85D: axis template list"
|
|
2961
|
+
]);
|
|
2962
|
+
return;
|
|
2963
|
+
}
|
|
2896
2964
|
const { fetchTemplateIndex: fetchTemplateIndex2 } = await import("./registry-client-6WSGKPF2.js");
|
|
2897
2965
|
const index = await fetchTemplateIndex2();
|
|
2898
|
-
const { choice } = await
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2966
|
+
const { choice } = await ask(
|
|
2967
|
+
{
|
|
2968
|
+
type: "select",
|
|
2969
|
+
name: "choice",
|
|
2970
|
+
message: "\uC0AC\uC6A9\uD560 \uD15C\uD50C\uB9BF\uC744 \uC120\uD0DD\uD558\uC138\uC694:",
|
|
2971
|
+
choices: index.templates.map((t) => ({
|
|
2972
|
+
title: `${t.name} (${t.category})`,
|
|
2973
|
+
description: t.description,
|
|
2974
|
+
value: t.slug
|
|
2975
|
+
}))
|
|
2976
|
+
},
|
|
2977
|
+
interactive
|
|
2978
|
+
);
|
|
2908
2979
|
if (!choice) {
|
|
2909
2980
|
console.log(chalk5.gray("\uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4."));
|
|
2910
2981
|
return;
|
|
@@ -2912,13 +2983,22 @@ async function initTemplate(slug, options) {
|
|
|
2912
2983
|
selectedSlug = choice;
|
|
2913
2984
|
}
|
|
2914
2985
|
let targetDir = options.dir;
|
|
2986
|
+
if (!targetDir && (!interactive || options.yes)) {
|
|
2987
|
+
targetDir = selectedSlug;
|
|
2988
|
+
const msg = `\uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD1A0\uB9AC\uB97C \uAE30\uBCF8\uAC12 '${targetDir}' \uB85C \uC815\uD588\uC2B5\uB2C8\uB2E4(\uBC14\uAFB8\uB824\uBA74 --dir <path>).`;
|
|
2989
|
+
if (interactive) console.log(chalk5.gray(`-y \uB77C ${msg}`));
|
|
2990
|
+
else noteDefault(msg);
|
|
2991
|
+
}
|
|
2915
2992
|
if (!targetDir) {
|
|
2916
|
-
const { dir } = await
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2993
|
+
const { dir } = await ask(
|
|
2994
|
+
{
|
|
2995
|
+
type: "text",
|
|
2996
|
+
name: "dir",
|
|
2997
|
+
message: "\uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD1A0\uB9AC:",
|
|
2998
|
+
initial: selectedSlug
|
|
2999
|
+
},
|
|
3000
|
+
interactive
|
|
3001
|
+
);
|
|
2922
3002
|
if (!dir) {
|
|
2923
3003
|
console.log(chalk5.gray("\uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4."));
|
|
2924
3004
|
return;
|
|
@@ -2929,13 +3009,26 @@ async function initTemplate(slug, options) {
|
|
|
2929
3009
|
if (await fs8.pathExists(resolved)) {
|
|
2930
3010
|
const entries = await fs8.readdir(resolved);
|
|
2931
3011
|
if (entries.length > 0) {
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
3012
|
+
if (options.yes) {
|
|
3013
|
+
console.log(chalk5.yellow(`! '${targetDir}'\uC5D0 \uC774\uBBF8 \uD30C\uC77C\uC774 \uC788\uC9C0\uB9CC -y \uB77C \uC9C4\uD589\uD569\uB2C8\uB2E4(\uD15C\uD50C\uB9BF\uACFC \uAC19\uC740 \uACBD\uB85C\uC758 \uD30C\uC77C\uC740 \uB36E\uC5B4\uC500).`));
|
|
3014
|
+
} else if (!interactive) {
|
|
3015
|
+
failNonInteractive(`'${targetDir}'\uC5D0 \uC774\uBBF8 \uD30C\uC77C\uC774 \uC788\uC5B4 \uACC4\uC18D\uD560\uC9C0 \uBB3C\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uC544\uBB34\uAC83\uB3C4 \uC4F0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.`, [
|
|
3016
|
+
`\uBE48 \uB514\uB809\uD130\uB9AC\uB97C \uC8FC\uC138\uC694: axis template init ${selectedSlug} --dir <path>`,
|
|
3017
|
+
`\uADF8\uB300\uB85C \uC9C4\uD589\uD558\uB824\uBA74(\uAC19\uC740 \uACBD\uB85C\uC758 \uD30C\uC77C\uC740 \uB36E\uC5B4\uC500): axis template init ${selectedSlug} --dir ${targetDir} -y`
|
|
3018
|
+
]);
|
|
3019
|
+
return;
|
|
3020
|
+
} else {
|
|
3021
|
+
const { proceed } = await ask(
|
|
3022
|
+
{
|
|
3023
|
+
type: "confirm",
|
|
3024
|
+
name: "proceed",
|
|
3025
|
+
message: `'${targetDir}'\uC5D0 \uC774\uBBF8 \uD30C\uC77C\uC774 \uC788\uC2B5\uB2C8\uB2E4. \uACC4\uC18D\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?`,
|
|
3026
|
+
initial: false
|
|
3027
|
+
},
|
|
3028
|
+
interactive
|
|
3029
|
+
);
|
|
3030
|
+
if (!proceed) return;
|
|
3031
|
+
}
|
|
2939
3032
|
}
|
|
2940
3033
|
} else {
|
|
2941
3034
|
await fs8.ensureDir(resolved);
|
|
@@ -3574,7 +3667,8 @@ function brandActivationResult(check) {
|
|
|
3574
3667
|
}
|
|
3575
3668
|
|
|
3576
3669
|
// src/template/index.ts
|
|
3577
|
-
function registerTemplateCommand(program2) {
|
|
3670
|
+
function registerTemplateCommand(program2, deps = {}) {
|
|
3671
|
+
const interactive = () => (deps.isInteractive ?? isInteractive)();
|
|
3578
3672
|
const tplCmd = program2.command("template").alias("tpl").description("\uD504\uB85C\uC81D\uD2B8 \uD15C\uD50C\uB9BF \uAD00\uB9AC");
|
|
3579
3673
|
tplCmd.command("list").alias("ls").description("\uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uD15C\uD50C\uB9BF \uBAA9\uB85D").option("--category <type>", "\uCE74\uD14C\uACE0\uB9AC \uD544\uD130").action(async (options) => {
|
|
3580
3674
|
const spinner = ora5("\uD15C\uD50C\uB9BF \uBAA9\uB85D \uAC00\uC838\uC624\uB294 \uC911...").start();
|
|
@@ -3640,12 +3734,12 @@ function registerTemplateCommand(program2) {
|
|
|
3640
3734
|
for (const f of detail.files) {
|
|
3641
3735
|
console.log(` ${chalk8.cyan(f.path)} ${chalk8.gray(`(${f.type})`)}`);
|
|
3642
3736
|
}
|
|
3643
|
-
const
|
|
3737
|
+
const deps2 = Object.keys(detail.dependencies || {});
|
|
3644
3738
|
const devDeps = Object.keys(detail.devDependencies || {});
|
|
3645
|
-
if (
|
|
3739
|
+
if (deps2.length > 0 || devDeps.length > 0) {
|
|
3646
3740
|
console.log(chalk8.bold("\n \uC758\uC874\uC131:"));
|
|
3647
|
-
if (
|
|
3648
|
-
console.log(` dependencies: ${
|
|
3741
|
+
if (deps2.length > 0) {
|
|
3742
|
+
console.log(` dependencies: ${deps2.join(", ")}`);
|
|
3649
3743
|
}
|
|
3650
3744
|
if (devDeps.length > 0) {
|
|
3651
3745
|
console.log(` devDependencies: ${devDeps.join(", ")}`);
|
|
@@ -3660,10 +3754,10 @@ function registerTemplateCommand(program2) {
|
|
|
3660
3754
|
}
|
|
3661
3755
|
});
|
|
3662
3756
|
tplCmd.command("apply <name>").description("\uD15C\uD50C\uB9BF\uC744 \uD604\uC7AC \uD504\uB85C\uC81D\uD2B8\uC5D0 \uC801\uC6A9").option("-y, --yes", "\uD655\uC778 \uC5C6\uC774 \uB36E\uC5B4\uC4F0\uAE30").option("--dry-run", "\uC2E4\uC81C \uD30C\uC77C \uC0DD\uC131 \uC5C6\uC774 \uBBF8\uB9AC\uBCF4\uAE30").option("--skip-deps", "\uC758\uC874\uC131 \uC548\uB0B4 \uC0DD\uB7B5").option("-d, --dir <path>", "\uB300\uC0C1 \uB514\uB809\uD1A0\uB9AC").action(async (name, options) => {
|
|
3663
|
-
await applyTemplate(name, options);
|
|
3757
|
+
await applyTemplate(name, { ...options, interactive: interactive() });
|
|
3664
3758
|
});
|
|
3665
|
-
tplCmd.command("init [name]").description("\uC0C8 \uD504\uB85C\uC81D\uD2B8\uB97C \uD15C\uD50C\uB9BF\uC73C\uB85C \uCD08\uAE30\uD654").option("-d, --dir <path>", "\uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD1A0\uB9AC").action(async (name, options) => {
|
|
3666
|
-
await initTemplate(name, options);
|
|
3759
|
+
tplCmd.command("init [name]").description("\uC0C8 \uD504\uB85C\uC81D\uD2B8\uB97C \uD15C\uD50C\uB9BF\uC73C\uB85C \uCD08\uAE30\uD654").option("-d, --dir <path>", "\uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD1A0\uB9AC(\uC5C6\uC73C\uBA74 \uD15C\uD50C\uB9BF \uC774\uB984)").option("-y, --yes", "\uC9C8\uBB38\uC744 \uAE30\uBCF8\uAC12\uC73C\uB85C \uB2F5\uD558\uACE0, \uBE44\uC5B4 \uC788\uC9C0 \uC54A\uC740 \uB514\uB809\uD1A0\uB9AC\uB3C4 \uC9C4\uD589(\uAC19\uC740 \uACBD\uB85C\uC758 \uD30C\uC77C\uC740 \uB36E\uC5B4\uC500)").action(async (name, options) => {
|
|
3760
|
+
await initTemplate(name, { ...options, interactive: interactive() });
|
|
3667
3761
|
});
|
|
3668
3762
|
tplCmd.command("diff <name>").description("\uB85C\uCEEC \uD504\uB85C\uC81D\uD2B8\uC640 \uD15C\uD50C\uB9BF\uC758 \uCC28\uC774 \uBE44\uAD50").option("--verbose", "\uB85C\uCEEC \uC804\uC6A9 \uD30C\uC77C\uB3C4 \uD45C\uC2DC").option("-d, --dir <path>", "\uB300\uC0C1 \uB514\uB809\uD1A0\uB9AC").action(async (name, options) => {
|
|
3669
3763
|
await diffTemplate(name, options);
|
|
@@ -4370,7 +4464,6 @@ function registerThemeCommand(program2) {
|
|
|
4370
4464
|
|
|
4371
4465
|
// src/init/index.ts
|
|
4372
4466
|
import chalk11 from "chalk";
|
|
4373
|
-
import prompts2 from "prompts";
|
|
4374
4467
|
|
|
4375
4468
|
// ../axis-registry-core/src/registry/schema.ts
|
|
4376
4469
|
import { createHash } from "crypto";
|
|
@@ -5228,7 +5321,7 @@ function planUtilsWrite(baseDirInput, utilsPath) {
|
|
|
5228
5321
|
}
|
|
5229
5322
|
return { action: "overwrite" };
|
|
5230
5323
|
}
|
|
5231
|
-
async function runInit(baseDirInput, answers, registryUrl, log = console.log) {
|
|
5324
|
+
async function runInit(baseDirInput, answers, registryUrl, log = console.log, options = {}) {
|
|
5232
5325
|
const baseDir = path15.resolve(baseDirInput);
|
|
5233
5326
|
const current = await existingConfig(baseDir);
|
|
5234
5327
|
const existingRegistry = nonEmptyString(current?.registry);
|
|
@@ -5275,6 +5368,12 @@ async function runInit(baseDirInput, answers, registryUrl, log = console.log) {
|
|
|
5275
5368
|
const utilsPath = path15.resolve(baseDir, answers.componentsDir, "utils.ts");
|
|
5276
5369
|
const utilsPlan = planUtilsWrite(baseDir, utilsPath);
|
|
5277
5370
|
if (utilsPlan.action === "reject") rejects.push(utilsPlan.reason);
|
|
5371
|
+
if (utilsPlan.action === "overwrite" && options.allowOverwrite === false) {
|
|
5372
|
+
const shown = path15.relative(baseDir, utilsPath).split(path15.sep).join("/") || utilsPath;
|
|
5373
|
+
rejects.push(
|
|
5374
|
+
`\uBE44\uB300\uD654\uD615 \uC2E4\uD589\uC774\uB77C \uB0B4\uC6A9\uC774 \uB2E4\uB978 \uAE30\uC874 ${shown} \uB97C \uB36E\uC5B4\uC4F0\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uB36E\uC5B4\uC368\uB3C4 \uB418\uBA74 axis init -y \uB85C \uB2E4\uC2DC \uC2E4\uD589\uD558\uAC70\uB098 \uB300\uD654\uD615 \uD130\uBBF8\uB110\uC5D0\uC11C \uC2E4\uD589\uD558\uC138\uC694`
|
|
5375
|
+
);
|
|
5376
|
+
}
|
|
5278
5377
|
if (rejects.length > 0) {
|
|
5279
5378
|
log(chalk10.red("\u2717 \uC4F8 \uC218 \uC5C6\uB294 \uD30C\uC77C\uC774 \uC788\uC5B4 \uC544\uBB34\uAC83\uB3C4 \uC4F0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4(axis.config.json \xB7 utils.ts \xB7 package.json \uADF8\uB300\uB85C)."));
|
|
5280
5379
|
for (const r of rejects) log(chalk10.red(` - ${r}`));
|
|
@@ -5379,14 +5478,20 @@ ${head}`));
|
|
|
5379
5478
|
}
|
|
5380
5479
|
|
|
5381
5480
|
// src/init/index.ts
|
|
5382
|
-
function registerInitCommand(program2, registryUrl = DEFAULT_REGISTRY_URL) {
|
|
5481
|
+
function registerInitCommand(program2, registryUrl = DEFAULT_REGISTRY_URL, deps = {}) {
|
|
5383
5482
|
program2.command("init").description("\uD504\uB85C\uC81D\uD2B8\uC5D0 AXIS Design System \uCD08\uAE30\uD654").option("-y, --yes", "\uAE30\uBCF8\uAC12\uC73C\uB85C \uC790\uB3D9 \uC124\uC815").action(async (options) => {
|
|
5384
5483
|
console.log(chalk11.blue("\n\u{1F3A8} AXIS Design System \uCD08\uAE30\uD654\n"));
|
|
5385
5484
|
const baseDir = process.cwd();
|
|
5386
5485
|
const tailwind4 = isTailwind4(planUtilsDependencies(baseDir).tailwind);
|
|
5387
5486
|
const resolved = await resolveInitAnswers(baseDir, tailwind4);
|
|
5388
5487
|
for (const note of resolved.notes) console.log(note.startsWith("!") ? chalk11.yellow(note) : chalk11.gray(note));
|
|
5389
|
-
const
|
|
5488
|
+
const interactive = (deps.isInteractive ?? isInteractive)();
|
|
5489
|
+
if (!options.yes && !interactive) {
|
|
5490
|
+
const a = resolved.answers;
|
|
5491
|
+
const values = [`componentsDir=${a.componentsDir}`, ...tailwind4 ? [] : [`tailwindConfig=${a.tailwindConfig}`], `globalCss=${a.globalCss}`];
|
|
5492
|
+
noteDefault(`\uAE30\uBCF8\uAC12\uC73C\uB85C \uC9C4\uD589\uD569\uB2C8\uB2E4(-y \uC640 \uAC19\uC74C): ${values.join(", ")}`);
|
|
5493
|
+
}
|
|
5494
|
+
const config = options.yes || !interactive ? { ...resolved.answers } : await ask([
|
|
5390
5495
|
{
|
|
5391
5496
|
type: "text",
|
|
5392
5497
|
name: "componentsDir",
|
|
@@ -5405,14 +5510,13 @@ function registerInitCommand(program2, registryUrl = DEFAULT_REGISTRY_URL) {
|
|
|
5405
5510
|
message: "\uAE00\uB85C\uBC8C CSS \uD30C\uC77C:",
|
|
5406
5511
|
initial: resolved.answers.globalCss
|
|
5407
5512
|
}
|
|
5408
|
-
]);
|
|
5409
|
-
await runInit(baseDir, config, registryUrl);
|
|
5513
|
+
], interactive);
|
|
5514
|
+
await runInit(baseDir, config, registryUrl, console.log, { allowOverwrite: options.yes === true || interactive });
|
|
5410
5515
|
});
|
|
5411
5516
|
}
|
|
5412
5517
|
|
|
5413
5518
|
// src/add/index.ts
|
|
5414
5519
|
import chalk12 from "chalk";
|
|
5415
|
-
import prompts3 from "prompts";
|
|
5416
5520
|
|
|
5417
5521
|
// ../axis-registry-core/src/add/add.ts
|
|
5418
5522
|
import { existsSync as existsSync8, readFileSync as readFileSync8, statSync as statSync5 } from "fs";
|
|
@@ -6477,7 +6581,7 @@ function configRegistryRejectedMessage(url, problem) {
|
|
|
6477
6581
|
function createConfirm(interactive) {
|
|
6478
6582
|
if (!interactive) return void 0;
|
|
6479
6583
|
return async (message) => {
|
|
6480
|
-
const { overwrite } = await
|
|
6584
|
+
const { overwrite } = await ask({ type: "confirm", name: "overwrite", message, initial: false }, interactive);
|
|
6481
6585
|
return overwrite === true;
|
|
6482
6586
|
};
|
|
6483
6587
|
}
|
|
@@ -6485,7 +6589,7 @@ var defaultCreateClient = (cwd) => createClientFor(cwd, (m) => console.warn(chal
|
|
|
6485
6589
|
function registerAddCommand(program2, deps = {}) {
|
|
6486
6590
|
program2.command("add <components...>").description("\uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC758 \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uD504\uB85C\uC81D\uD2B8\uC5D0 \uBCF5\uC0AC(registryDependencies \uD3EC\uD568)").option("--agentic", "\uC774\uB984 \uC55E\uC5D0 agentic- \uB97C \uBD99\uC5EC \uCC3E\uC74C(\uC804\uCCB4 \uC774\uB984\uB3C4 \uD5C8\uC6A9)").option("-y, --yes", "\uBB3B\uC9C0 \uC54A\uACE0 \uC9C4\uD589. \uB0B4\uC6A9\uC774 \uB2E4\uB978 \uAE30\uC874 \uD30C\uC77C\uC740 \uAC74\uB108\uB700").option("--overwrite", "\uB0B4\uC6A9\uC774 \uB2E4\uB978 \uAE30\uC874 \uD30C\uC77C\uC744 \uB36E\uC5B4\uC500").action(async (components, options) => {
|
|
6487
6591
|
const client = await (deps.createClient ?? defaultCreateClient)(process.cwd());
|
|
6488
|
-
const confirm = createConfirm((deps.isInteractive ??
|
|
6592
|
+
const confirm = createConfirm((deps.isInteractive ?? isInteractive)());
|
|
6489
6593
|
const result = await runAdd(process.cwd(), components, options, {
|
|
6490
6594
|
client,
|
|
6491
6595
|
log: (...a) => console.log(...a),
|
|
@@ -6728,4 +6832,10 @@ registerSyncCommand(program);
|
|
|
6728
6832
|
registerTemplateCommand(program);
|
|
6729
6833
|
registerCheckCommand(program);
|
|
6730
6834
|
registerThemeCommand(program);
|
|
6731
|
-
|
|
6835
|
+
try {
|
|
6836
|
+
await program.parseAsync();
|
|
6837
|
+
} catch (err) {
|
|
6838
|
+
if (!(err instanceof NonInteractiveError)) throw err;
|
|
6839
|
+
console.error(chalk13.red(err.message));
|
|
6840
|
+
process.exitCode = 1;
|
|
6841
|
+
}
|
package/dist/monet.d.ts
CHANGED
|
@@ -82,7 +82,10 @@ declare class MonetClient {
|
|
|
82
82
|
searchComponents(query: string): Promise<void>;
|
|
83
83
|
browseCategory(category: string): Promise<void>;
|
|
84
84
|
private getCategoryExamples;
|
|
85
|
-
|
|
85
|
+
/** opts.interactive: 질문을 띄울 수 있는지(WI-0075). 없으면 stdin 이 TTY 인지로 정합니다 */
|
|
86
|
+
importFromClipboard(opts?: {
|
|
87
|
+
interactive?: boolean;
|
|
88
|
+
}): Promise<void>;
|
|
86
89
|
}
|
|
87
90
|
declare function getMonetUrl(path: string): string;
|
|
88
91
|
declare function getMonetMcpConfig(): object;
|
package/dist/monet.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
{
|
|
14
14
|
"path": "components/agentic/agent-avatar.tsx",
|
|
15
15
|
"type": "registry:ui",
|
|
16
|
-
"content": "import * as React from \"react\";\nimport { cn } from \"@/registry/axis/lib/utils\";\nimport { AGENT_STATUS_LABELS } from \"@/registry/axis/lib/agentic-a11y-labels\";\n\nexport interface AgentAvatarProps {\n /** 에이전트 이름 */\n name: string;\n /** 이미지 URL */\n src?: string;\n /** 크기 */\n size?: \"sm\" | \"md\" | \"lg\" | \"xl\";\n /** 상태 표시 */\n status?: \"online\" | \"busy\" | \"offline\";\n /** 에이전트 타입 */\n type?: \"assistant\" | \"tool\" | \"system\";\n /** 추가 클래스 */\n className?: string;\n}\n\nconst sizeStyles = {\n sm: \"w-6 h-6 text-xs\",\n md: \"w-8 h-8 text-sm\",\n lg: \"w-10 h-10 text-base\",\n xl: \"w-12 h-12 text-lg\",\n};\n\nconst statusStyles = {\n online: \"bg-[var(--axis-
|
|
16
|
+
"content": "import * as React from \"react\";\nimport { cn } from \"@/registry/axis/lib/utils\";\nimport { AGENT_STATUS_LABELS } from \"@/registry/axis/lib/agentic-a11y-labels\";\n\nexport interface AgentAvatarProps {\n /** 에이전트 이름 */\n name: string;\n /** 이미지 URL */\n src?: string;\n /** 크기 */\n size?: \"sm\" | \"md\" | \"lg\" | \"xl\";\n /** 상태 표시 */\n status?: \"online\" | \"busy\" | \"offline\";\n /** 에이전트 타입 */\n type?: \"assistant\" | \"tool\" | \"system\";\n /** 추가 클래스 */\n className?: string;\n}\n\nconst sizeStyles = {\n sm: \"w-6 h-6 text-xs\",\n md: \"w-8 h-8 text-sm\",\n lg: \"w-10 h-10 text-base\",\n xl: \"w-12 h-12 text-lg\",\n};\n\nconst statusStyles = {\n online: \"bg-[var(--axis-text-success)]\",\n busy: \"bg-[var(--axis-text-warning)]\",\n offline: \"bg-[var(--axis-text-tertiary)]\",\n};\n\nconst typeColors = {\n assistant: \"bg-[var(--axis-agent-avatar-assistant)]\",\n tool: \"bg-[var(--axis-agent-avatar-tool)]\",\n system: \"bg-[var(--axis-agent-avatar-system)]\",\n};\n\n/**\n * 에이전트 아바타 컴포넌트\n */\nexport function AgentAvatar({\n name,\n src,\n size = \"md\",\n status,\n type = \"assistant\",\n className,\n}: AgentAvatarProps) {\n const initials = name\n .split(\" \")\n .map((n) => n[0])\n .join(\"\")\n .slice(0, 2)\n .toUpperCase();\n\n const statusLabel = status ? AGENT_STATUS_LABELS[status] : \"\";\n const ariaLabel = `${name}${statusLabel ? `, ${statusLabel}` : \"\"}`;\n\n return (\n <div\n role=\"img\"\n aria-label={ariaLabel}\n className={cn(\"relative inline-flex\", className)}\n >\n {src ? (\n <img\n src={src}\n alt=\"\"\n aria-hidden=\"true\"\n className={cn(\n \"rounded-full object-cover\",\n sizeStyles[size]\n )}\n />\n ) : (\n <div\n aria-hidden=\"true\"\n className={cn(\n \"rounded-full flex items-center justify-center font-medium text-[var(--axis-agent-avatar-text)]\",\n sizeStyles[size],\n typeColors[type]\n )}\n >\n {initials}\n </div>\n )}\n {status && (\n <span\n aria-hidden=\"true\"\n className={cn(\n \"absolute bottom-0 right-0 rounded-full border-2 border-[var(--axis-surface-default)]\",\n size === \"sm\" ? \"w-2 h-2\" : \"w-3 h-3\",\n statusStyles[status]\n )}\n />\n )}\n </div>\n );\n}\n"
|
|
17
17
|
}
|
|
18
18
|
]
|
|
19
19
|
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
{
|
|
14
14
|
"path": "components/agentic/approval-card.tsx",
|
|
15
15
|
"type": "registry:ui",
|
|
16
|
-
"content": "import * as React from \"react\";\nimport { cn } from \"@/registry/axis/lib/utils\";\nimport { SEVERITY_LABELS } from \"@/registry/axis/lib/agentic-a11y-labels\";\n\nexport type Severity = \"info\" | \"warning\" | \"error\";\n\nexport interface ApprovalAction {\n label: string;\n variant?: \"default\" | \"secondary\" | \"ghost\" | \"destructive\";\n onClick: () => void;\n}\n\nexport interface ApprovalCardProps {\n /** 고유 ID (접근성용) */\n id?: string;\n /** 제목 */\n title: string;\n /** 설명 */\n description?: string;\n /** 심각도 (색상 결정) */\n severity?: Severity;\n /** 액션 버튼 목록 */\n actions: ApprovalAction[];\n /** 추가 내용 */\n children?: React.ReactNode;\n /** 추가 클래스 */\n className?: string;\n}\n\nconst severityStyles: Record<Severity, { border: string; icon: string; bg: string }> = {\n info: {\n border: \"border-l-[var(--axis-status-info)]\",\n icon: \"text-[var(--axis-status-info)]\",\n bg: \"bg-[var(--axis-surface-info)]\",\n },\n warning: {\n border: \"border-l-[var(--axis-status-warning)]\",\n icon: \"text-[var(--axis-
|
|
16
|
+
"content": "import * as React from \"react\";\nimport { cn } from \"@/registry/axis/lib/utils\";\nimport { SEVERITY_LABELS } from \"@/registry/axis/lib/agentic-a11y-labels\";\n\nexport type Severity = \"info\" | \"warning\" | \"error\";\n\nexport interface ApprovalAction {\n label: string;\n variant?: \"default\" | \"secondary\" | \"ghost\" | \"destructive\";\n onClick: () => void;\n}\n\nexport interface ApprovalCardProps {\n /** 고유 ID (접근성용) */\n id?: string;\n /** 제목 */\n title: string;\n /** 설명 */\n description?: string;\n /** 심각도 (색상 결정) */\n severity?: Severity;\n /** 액션 버튼 목록 */\n actions: ApprovalAction[];\n /** 추가 내용 */\n children?: React.ReactNode;\n /** 추가 클래스 */\n className?: string;\n}\n\nconst severityStyles: Record<Severity, { border: string; icon: string; bg: string }> = {\n info: {\n border: \"border-l-[var(--axis-status-info)]\",\n icon: \"text-[var(--axis-status-info)]\",\n bg: \"bg-[var(--axis-surface-info)]\",\n },\n warning: {\n border: \"border-l-[var(--axis-status-warning)]\",\n icon: \"text-[var(--axis-text-warning)]\",\n bg: \"bg-[var(--axis-surface-warning)]\",\n },\n error: {\n border: \"border-l-[var(--axis-status-error)]\",\n icon: \"text-[var(--axis-text-error)]\",\n bg: \"bg-[var(--axis-surface-error)]\",\n },\n};\n\nconst severityIcons: Record<Severity, React.ReactNode> = {\n info: (\n <svg className=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\" />\n </svg>\n ),\n warning: (\n <svg className=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\" />\n </svg>\n ),\n error: (\n <svg className=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\" />\n </svg>\n ),\n};\n\nconst actionVariantStyles: Record<string, string> = {\n default: \"bg-[var(--axis-button-bg-default)] text-[var(--axis-button-text-default)] hover:bg-[var(--axis-button-bg-hover)]\",\n secondary: \"bg-[var(--axis-button-secondary-bg-default)] text-[var(--axis-text-primary)] hover:bg-[var(--axis-button-secondary-bg-hover)]\",\n ghost: \"bg-transparent text-[var(--axis-text-primary)] hover:bg-[var(--axis-surface-secondary)]\",\n destructive: \"bg-[var(--axis-button-destructive-bg-default)] text-[var(--axis-button-destructive-text-default)] hover:bg-[var(--axis-button-destructive-bg-hover)]\",\n};\n\n/**\n * 사용자 승인이 필요한 작업을 표시하는 카드 컴포넌트\n */\nexport function ApprovalCard({\n id,\n title,\n description,\n severity = \"info\",\n actions,\n children,\n className,\n}: ApprovalCardProps) {\n const styles = severityStyles[severity];\n const generatedId = React.useId();\n const baseId = id || generatedId;\n const titleId = `${baseId}-title`;\n const descId = `${baseId}-desc`;\n const severityLabel = SEVERITY_LABELS[severity];\n\n return (\n <div\n role=\"region\"\n aria-labelledby={titleId}\n aria-describedby={description ? descId : undefined}\n className={cn(\n \"rounded-lg border border-l-4 p-4\",\n \"bg-[var(--axis-surface-default)] border-[var(--axis-border-default)]\",\n styles.border,\n className\n )}\n >\n <div className=\"flex items-start gap-3\">\n <div className={cn(\"flex-shrink-0 mt-0.5\", styles.icon)} aria-hidden=\"true\">\n {severityIcons[severity]}\n </div>\n <div className=\"flex-1 min-w-0\">\n <span className=\"sr-only\">{severityLabel} 알림:</span>\n <h4 id={titleId} className=\"text-sm font-semibold text-[var(--axis-text-primary)]\">\n {title}\n </h4>\n {description && (\n <p id={descId} className=\"mt-1 text-sm text-[var(--axis-text-secondary)]\">\n {description}\n </p>\n )}\n {children && <div className=\"mt-3\">{children}</div>}\n <div className=\"flex flex-wrap gap-2 mt-4\">\n {actions.map((action, index) => (\n <button\n key={index}\n onClick={action.onClick}\n className={cn(\n \"px-3 py-1.5 text-sm font-medium rounded-md transition-colors\",\n actionVariantStyles[action.variant || \"default\"]\n )}\n >\n {action.label}\n </button>\n ))}\n </div>\n </div>\n </div>\n </div>\n );\n}\n"
|
|
17
17
|
}
|
|
18
18
|
]
|
|
19
19
|
}
|