7onic 0.1.9 → 0.1.11

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.
Files changed (2) hide show
  1. package/dist/index.js +242 -63
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -155,8 +155,8 @@ var require_picocolors = __commonJS({
155
155
  });
156
156
 
157
157
  // cli/src/commands/init.ts
158
- var import_node_fs4 = __toESM(require("node:fs"));
159
- var import_node_path4 = __toESM(require("node:path"));
158
+ var import_node_fs5 = __toESM(require("node:fs"));
159
+ var import_node_path5 = __toESM(require("node:path"));
160
160
 
161
161
  // node_modules/@clack/core/dist/index.mjs
162
162
  var import_node_util = require("node:util");
@@ -1227,6 +1227,127 @@ var logger = {
1227
1227
  }
1228
1228
  };
1229
1229
 
1230
+ // cli/src/utils/vite-template-cleanup.ts
1231
+ var import_node_fs4 = __toESM(require("node:fs"));
1232
+ var import_node_path4 = __toESM(require("node:path"));
1233
+ var VITE_INDEX_CSS_PATTERNS = [
1234
+ {
1235
+ name: ":root (font/color/bg defaults)",
1236
+ pattern: /:root\s*\{[^}]*font-family:\s*system-ui,\s*Avenir,\s*Helvetica,\s*Arial,\s*sans-serif;[^}]*color-scheme:\s*light dark;[^}]*background-color:\s*#242424;[^}]*\}\s*/m
1237
+ },
1238
+ {
1239
+ name: "a (link colors)",
1240
+ pattern: /a\s*\{\s*font-weight:\s*500;\s*color:\s*#646cff;\s*text-decoration:\s*inherit;\s*\}\s*/m
1241
+ },
1242
+ {
1243
+ name: "a:hover",
1244
+ pattern: /a:hover\s*\{\s*color:\s*#535bf2;\s*\}\s*/m
1245
+ },
1246
+ {
1247
+ name: "body (flex centering)",
1248
+ pattern: /body\s*\{\s*margin:\s*0;\s*display:\s*flex;\s*place-items:\s*center;\s*min-width:\s*320px;\s*min-height:\s*100vh;\s*\}\s*/m
1249
+ },
1250
+ {
1251
+ name: "h1 (huge size)",
1252
+ pattern: /h1\s*\{\s*font-size:\s*3\.2em;\s*line-height:\s*1\.1;\s*\}\s*/m
1253
+ },
1254
+ {
1255
+ name: "button (default styles)",
1256
+ pattern: /button\s*\{\s*border-radius:\s*8px;\s*border:\s*1px solid transparent;\s*padding:\s*0\.6em 1\.2em;[^}]*background-color:\s*#1a1a1a;[^}]*\}\s*/m
1257
+ },
1258
+ {
1259
+ name: "button:hover",
1260
+ pattern: /button:hover\s*\{\s*border-color:\s*#646cff;\s*\}\s*/m
1261
+ },
1262
+ {
1263
+ name: "button:focus",
1264
+ pattern: /button:focus,\s*button:focus-visible\s*\{\s*outline:\s*4px auto -webkit-focus-ring-color;\s*\}\s*/m
1265
+ },
1266
+ {
1267
+ name: "@media light mode overrides",
1268
+ pattern: /@media\s*\(prefers-color-scheme:\s*light\)\s*\{\s*:root\s*\{\s*color:\s*#213547;\s*background-color:\s*#ffffff;\s*\}[^@]*?button\s*\{\s*background-color:\s*#f9f9f9;\s*\}\s*\}\s*/m
1269
+ }
1270
+ ];
1271
+ var VITE_APP_CSS_PATTERNS = [
1272
+ {
1273
+ name: "#root (max-width + text-align:center)",
1274
+ pattern: /#root\s*\{\s*max-width:\s*1280px;\s*margin:\s*0 auto;\s*padding:\s*2rem;\s*text-align:\s*center;\s*\}\s*/m
1275
+ },
1276
+ {
1277
+ name: ".logo (spin animation set)",
1278
+ pattern: /\.logo\s*\{[^}]*height:\s*6em;[^}]*padding:\s*1\.5em;[^}]*will-change:\s*filter;[^}]*\}\s*/m
1279
+ },
1280
+ {
1281
+ name: ".logo:hover",
1282
+ pattern: /\.logo:hover\s*\{\s*filter:\s*drop-shadow\(0 0 2em #646cffaa\);\s*\}\s*/m
1283
+ },
1284
+ {
1285
+ name: ".logo.react:hover",
1286
+ pattern: /\.logo\.react:hover\s*\{\s*filter:\s*drop-shadow\(0 0 2em #61dafbaa\);\s*\}\s*/m
1287
+ },
1288
+ {
1289
+ name: "@keyframes logo-spin",
1290
+ pattern: /@keyframes\s+logo-spin\s*\{\s*from\s*\{\s*transform:\s*rotate\(0deg\);\s*\}\s*to\s*\{\s*transform:\s*rotate\(360deg\);\s*\}\s*\}\s*/m
1291
+ },
1292
+ {
1293
+ name: "@media logo-spin animation",
1294
+ pattern: /@media\s*\(prefers-reduced-motion:\s*no-preference\)\s*\{\s*a:nth-of-type\(2\)\s*\.logo\s*\{\s*animation:\s*logo-spin[^}]*\}\s*\}\s*/m
1295
+ },
1296
+ {
1297
+ name: ".card",
1298
+ pattern: /\.card\s*\{\s*padding:\s*2em;\s*\}\s*/m
1299
+ },
1300
+ {
1301
+ name: ".read-the-docs",
1302
+ pattern: /\.read-the-docs\s*\{\s*color:\s*#888;\s*\}\s*/m
1303
+ }
1304
+ ];
1305
+ function scanFile(fullPath, relPath, patterns) {
1306
+ if (!import_node_fs4.default.existsSync(fullPath)) return null;
1307
+ const originalContent = import_node_fs4.default.readFileSync(fullPath, "utf-8");
1308
+ let cleanedContent = originalContent;
1309
+ const matches = [];
1310
+ for (const { name, pattern } of patterns) {
1311
+ const match = cleanedContent.match(pattern);
1312
+ if (match && match.index !== void 0) {
1313
+ const linesBefore = cleanedContent.slice(0, match.index).split("\n").length;
1314
+ const linesInMatch = match[0].split("\n").length;
1315
+ matches.push({
1316
+ file: relPath,
1317
+ name,
1318
+ startLine: linesBefore,
1319
+ endLine: linesBefore + linesInMatch - 1,
1320
+ preview: match[0].split("\n")[0].trim().slice(0, 60)
1321
+ });
1322
+ cleanedContent = cleanedContent.slice(0, match.index) + cleanedContent.slice(match.index + match[0].length);
1323
+ }
1324
+ }
1325
+ if (matches.length === 0) return null;
1326
+ cleanedContent = cleanedContent.replace(/\n{3,}/g, "\n\n").replace(/^\s+\n/gm, "\n").trimStart();
1327
+ return {
1328
+ file: relPath,
1329
+ fullPath,
1330
+ originalContent,
1331
+ cleanedContent,
1332
+ matches
1333
+ };
1334
+ }
1335
+ function scanViteTemplate(projectRoot) {
1336
+ const results = [];
1337
+ const indexCssPath = import_node_path4.default.join(projectRoot, "src/index.css");
1338
+ const indexResult = scanFile(indexCssPath, "src/index.css", VITE_INDEX_CSS_PATTERNS);
1339
+ if (indexResult) results.push(indexResult);
1340
+ const appCssPath = import_node_path4.default.join(projectRoot, "src/App.css");
1341
+ const appResult = scanFile(appCssPath, "src/App.css", VITE_APP_CSS_PATTERNS);
1342
+ if (appResult) results.push(appResult);
1343
+ return results;
1344
+ }
1345
+ function applyCleanup(result) {
1346
+ const backupPath = result.fullPath + ".bak";
1347
+ import_node_fs4.default.writeFileSync(backupPath, result.originalContent, "utf-8");
1348
+ import_node_fs4.default.writeFileSync(result.fullPath, result.cleanedContent, "utf-8");
1349
+ }
1350
+
1230
1351
  // cli/src/commands/init.ts
1231
1352
  var CSS_CANDIDATES = [
1232
1353
  "src/app/globals.css",
@@ -1242,9 +1363,13 @@ export function cn(...inputs: ClassValue[]) {
1242
1363
  return twMerge(clsx(inputs))
1243
1364
  }
1244
1365
  `;
1245
- var CSS_V3_IMPORTS = `@import '@7onic-ui/tokens/css/variables.css';
1246
- @import '@7onic-ui/tokens/css/themes/light.css';
1247
- @import '@7onic-ui/tokens/css/themes/dark.css';
1366
+ var CSS_V3_IMPORTS = `@import '@7onic-ui/tokens/css/all.css';
1367
+
1368
+ @tailwind base;
1369
+ @tailwind components;
1370
+ @tailwind utilities;
1371
+ `;
1372
+ var CSS_V3_TOKEN_ONLY = `@import '@7onic-ui/tokens/css/all.css';
1248
1373
  `;
1249
1374
  var CSS_V4_IMPORTS = `@import "tailwindcss";
1250
1375
  @import '@7onic-ui/tokens/css/variables.css';
@@ -1277,7 +1402,7 @@ async function init(args) {
1277
1402
  process.exit(0);
1278
1403
  }
1279
1404
  }
1280
- const hasTsConfig = import_node_fs4.default.existsSync(import_node_path4.default.join(projectRoot, "tsconfig.json"));
1405
+ const hasTsConfig = import_node_fs5.default.existsSync(import_node_path5.default.join(projectRoot, "tsconfig.json"));
1281
1406
  if (!hasTsConfig) {
1282
1407
  pt("tsconfig.json not found. 7onic requires TypeScript.");
1283
1408
  process.exit(1);
@@ -1288,7 +1413,7 @@ async function init(args) {
1288
1413
  const TSCONFIG_CANDIDATES = ["tsconfig.json", "tsconfig.app.json"];
1289
1414
  for (const tc of TSCONFIG_CANDIDATES) {
1290
1415
  try {
1291
- const raw = import_node_fs4.default.readFileSync(import_node_path4.default.join(projectRoot, tc), "utf-8");
1416
+ const raw = import_node_fs5.default.readFileSync(import_node_path5.default.join(projectRoot, tc), "utf-8");
1292
1417
  if (raw.includes('"@/')) {
1293
1418
  hasPathAlias = true;
1294
1419
  break;
@@ -1296,12 +1421,12 @@ async function init(args) {
1296
1421
  } catch {
1297
1422
  }
1298
1423
  }
1299
- const viteConfigPath = import_node_fs4.default.existsSync(import_node_path4.default.join(projectRoot, "vite.config.ts")) ? import_node_path4.default.join(projectRoot, "vite.config.ts") : import_node_fs4.default.existsSync(import_node_path4.default.join(projectRoot, "vite.config.js")) ? import_node_path4.default.join(projectRoot, "vite.config.js") : null;
1300
- const isViteProject = import_node_fs4.default.existsSync(import_node_path4.default.join(projectRoot, "tsconfig.app.json")) && viteConfigPath !== null;
1424
+ const viteConfigPath = import_node_fs5.default.existsSync(import_node_path5.default.join(projectRoot, "vite.config.ts")) ? import_node_path5.default.join(projectRoot, "vite.config.ts") : import_node_fs5.default.existsSync(import_node_path5.default.join(projectRoot, "vite.config.js")) ? import_node_path5.default.join(projectRoot, "vite.config.js") : null;
1425
+ const isViteProject = import_node_fs5.default.existsSync(import_node_path5.default.join(projectRoot, "tsconfig.app.json")) && viteConfigPath !== null;
1301
1426
  let needsTypesNode = false;
1302
1427
  if (!hasPathAlias) {
1303
1428
  if (isViteProject) {
1304
- const tscPatch = patchTsconfigApp(import_node_path4.default.join(projectRoot, "tsconfig.app.json"));
1429
+ const tscPatch = patchTsconfigApp(import_node_path5.default.join(projectRoot, "tsconfig.app.json"));
1305
1430
  const vitePatch = patchViteConfig(viteConfigPath);
1306
1431
  if (vitePatch) needsTypesNode = true;
1307
1432
  if (tscPatch || vitePatch) {
@@ -1318,7 +1443,7 @@ async function init(args) {
1318
1443
  }
1319
1444
  }
1320
1445
  try {
1321
- const pkgJson = JSON.parse(import_node_fs4.default.readFileSync(import_node_path4.default.join(projectRoot, "package.json"), "utf-8"));
1446
+ const pkgJson = JSON.parse(import_node_fs5.default.readFileSync(import_node_path5.default.join(projectRoot, "package.json"), "utf-8"));
1322
1447
  const allDeps = { ...pkgJson.dependencies, ...pkgJson.devDependencies };
1323
1448
  if (allDeps["@7onic-ui/react"]) {
1324
1449
  O2.info(
@@ -1327,7 +1452,7 @@ async function init(args) {
1327
1452
  }
1328
1453
  } catch {
1329
1454
  }
1330
- const cssDefault = CSS_CANDIDATES.find((c2) => import_node_fs4.default.existsSync(import_node_path4.default.join(projectRoot, c2))) || "src/app/globals.css";
1455
+ const cssDefault = CSS_CANDIDATES.find((c2) => import_node_fs5.default.existsSync(import_node_path5.default.join(projectRoot, c2))) || "src/app/globals.css";
1331
1456
  let config;
1332
1457
  if (flagYes) {
1333
1458
  const resolvedVersion = forcedTailwindVersion ?? tw.version;
@@ -1388,40 +1513,74 @@ async function init(args) {
1388
1513
  logger.error(String(err));
1389
1514
  process.exit(1);
1390
1515
  }
1391
- const cssFullPath = import_node_path4.default.join(projectRoot, config.cssPath);
1392
- if (!import_node_fs4.default.existsSync(cssFullPath)) {
1393
- const cssDir = import_node_path4.default.dirname(cssFullPath);
1394
- if (!import_node_fs4.default.existsSync(cssDir)) {
1395
- import_node_fs4.default.mkdirSync(cssDir, { recursive: true });
1516
+ const cssFullPath = import_node_path5.default.join(projectRoot, config.cssPath);
1517
+ if (!import_node_fs5.default.existsSync(cssFullPath)) {
1518
+ const cssDir = import_node_path5.default.dirname(cssFullPath);
1519
+ if (!import_node_fs5.default.existsSync(cssDir)) {
1520
+ import_node_fs5.default.mkdirSync(cssDir, { recursive: true });
1396
1521
  }
1397
1522
  const cssImports = tailwindVersion === 3 ? CSS_V3_IMPORTS : CSS_V4_IMPORTS;
1398
- import_node_fs4.default.writeFileSync(cssFullPath, cssImports, "utf-8");
1523
+ import_node_fs5.default.writeFileSync(cssFullPath, cssImports, "utf-8");
1399
1524
  O2.success(`Created ${config.cssPath} with token imports`);
1400
1525
  } else {
1401
- const cssContent = import_node_fs4.default.readFileSync(cssFullPath, "utf-8");
1526
+ const cssContent = import_node_fs5.default.readFileSync(cssFullPath, "utf-8");
1402
1527
  if (!cssContent.includes("@7onic-ui/tokens")) {
1403
- const tokenImports = tailwindVersion === 3 ? CSS_V3_IMPORTS : CSS_V4_TOKEN_ONLY;
1404
1528
  if (tailwindVersion === 4) {
1405
1529
  const twMatch = cssContent.match(/@import\s+["']tailwindcss["'].*\n/);
1406
1530
  if (twMatch) {
1407
1531
  const insertAt = twMatch.index + twMatch[0].length;
1408
- const updated = cssContent.slice(0, insertAt) + tokenImports + cssContent.slice(insertAt);
1409
- import_node_fs4.default.writeFileSync(cssFullPath, updated, "utf-8");
1532
+ const updated = cssContent.slice(0, insertAt) + CSS_V4_TOKEN_ONLY + cssContent.slice(insertAt);
1533
+ import_node_fs5.default.writeFileSync(cssFullPath, updated, "utf-8");
1410
1534
  } else {
1411
- import_node_fs4.default.writeFileSync(cssFullPath, CSS_V4_IMPORTS + "\n" + cssContent, "utf-8");
1535
+ import_node_fs5.default.writeFileSync(cssFullPath, CSS_V4_IMPORTS + "\n" + cssContent, "utf-8");
1412
1536
  }
1413
1537
  } else {
1414
- import_node_fs4.default.writeFileSync(cssFullPath, tokenImports + "\n" + cssContent, "utf-8");
1538
+ const hasTailwindDirectives = /@tailwind\s+(base|components|utilities)/.test(cssContent);
1539
+ const v3Imports = hasTailwindDirectives ? CSS_V3_TOKEN_ONLY : CSS_V3_IMPORTS;
1540
+ import_node_fs5.default.writeFileSync(cssFullPath, v3Imports + "\n" + cssContent, "utf-8");
1415
1541
  }
1416
1542
  O2.success(`Added token imports to ${config.cssPath}`);
1417
1543
  } else {
1418
1544
  O2.info(`Token imports already present in ${config.cssPath}`);
1419
1545
  }
1420
1546
  }
1547
+ if (isViteProject) {
1548
+ const scanResults = scanViteTemplate(projectRoot);
1549
+ if (scanResults.length > 0) {
1550
+ const totalMatches = scanResults.reduce((sum, r) => sum + r.matches.length, 0);
1551
+ const fileList = scanResults.map((r) => {
1552
+ const blockLines = r.matches.map((m) => ` \u2022 ${m.name} (L${m.startLine}\u2013${m.endLine})`).join("\n");
1553
+ return ` ${import_picocolors2.default.bold(r.file)}
1554
+ ${blockLines}`;
1555
+ }).join("\n");
1556
+ wt(
1557
+ `Detected ${totalMatches} Vite template block${totalMatches === 1 ? "" : "s"} that override 7onic utilities:
1558
+
1559
+ ` + fileList + "\n\n" + import_picocolors2.default.dim(" These blocks are from `npm create vite` boilerplate.\n") + import_picocolors2.default.dim(" A .bak backup will be created before changes."),
1560
+ "Vite Template Cleanup"
1561
+ );
1562
+ const approve = flagYes ? true : await ot2({
1563
+ message: "Remove Vite template boilerplate?",
1564
+ initialValue: true
1565
+ });
1566
+ if (q(approve)) {
1567
+ pt("Init cancelled.");
1568
+ process.exit(0);
1569
+ }
1570
+ if (approve) {
1571
+ for (const result of scanResults) {
1572
+ applyCleanup(result);
1573
+ O2.success(`Cleaned ${result.file} (${result.matches.length} block${result.matches.length === 1 ? "" : "s"}) \u2014 backup at ${result.file}.bak`);
1574
+ }
1575
+ } else {
1576
+ O2.info("Kept Vite template blocks. You may see style conflicts.");
1577
+ }
1578
+ }
1579
+ }
1421
1580
  if (tailwindVersion === 3 && tw.configPath) {
1422
- const configFullPath = import_node_path4.default.join(projectRoot, tw.configPath);
1423
- if (import_node_fs4.default.existsSync(configFullPath)) {
1424
- const configContent = import_node_fs4.default.readFileSync(configFullPath, "utf-8");
1581
+ const configFullPath = import_node_path5.default.join(projectRoot, tw.configPath);
1582
+ if (import_node_fs5.default.existsSync(configFullPath)) {
1583
+ const configContent = import_node_fs5.default.readFileSync(configFullPath, "utf-8");
1425
1584
  if (!configContent.includes("@7onic-ui/tokens/tailwind/v3-preset")) {
1426
1585
  wt(
1427
1586
  `Add the 7onic preset to your ${tw.configPath}:
@@ -1440,18 +1599,18 @@ async function init(args) {
1440
1599
  const utilsPath = resolveAliasPath(projectRoot, config.utilsAlias);
1441
1600
  if (utilsPath) {
1442
1601
  const utilsFullPath = utilsPath + ".ts";
1443
- if (!import_node_fs4.default.existsSync(utilsFullPath)) {
1444
- const utilsDir = import_node_path4.default.dirname(utilsFullPath);
1445
- if (!import_node_fs4.default.existsSync(utilsDir)) {
1446
- import_node_fs4.default.mkdirSync(utilsDir, { recursive: true });
1602
+ if (!import_node_fs5.default.existsSync(utilsFullPath)) {
1603
+ const utilsDir = import_node_path5.default.dirname(utilsFullPath);
1604
+ if (!import_node_fs5.default.existsSync(utilsDir)) {
1605
+ import_node_fs5.default.mkdirSync(utilsDir, { recursive: true });
1447
1606
  }
1448
- import_node_fs4.default.writeFileSync(utilsFullPath, CN_UTIL, "utf-8");
1449
- O2.success(`Created ${import_node_path4.default.relative(projectRoot, utilsFullPath)}`);
1607
+ import_node_fs5.default.writeFileSync(utilsFullPath, CN_UTIL, "utf-8");
1608
+ O2.success(`Created ${import_node_path5.default.relative(projectRoot, utilsFullPath)}`);
1450
1609
  } else {
1451
- const utilsContent = import_node_fs4.default.readFileSync(utilsFullPath, "utf-8");
1610
+ const utilsContent = import_node_fs5.default.readFileSync(utilsFullPath, "utf-8");
1452
1611
  if (!utilsContent.includes("tailwind-merge")) {
1453
1612
  O2.warn(
1454
- `${import_node_path4.default.relative(projectRoot, utilsFullPath)} exists but does not import tailwind-merge.
1613
+ `${import_node_path5.default.relative(projectRoot, utilsFullPath)} exists but does not import tailwind-merge.
1455
1614
  7onic components require cn() with tailwind-merge.`
1456
1615
  );
1457
1616
  } else {
@@ -1477,14 +1636,14 @@ async function init(args) {
1477
1636
  }
1478
1637
  function patchTsconfigApp(tsconfigPath) {
1479
1638
  try {
1480
- const raw = import_node_fs4.default.readFileSync(tsconfigPath, "utf-8");
1639
+ const raw = import_node_fs5.default.readFileSync(tsconfigPath, "utf-8");
1481
1640
  const clean = raw.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "").replace(/,(\s*[}\]])/g, "$1");
1482
1641
  const tc = JSON.parse(clean);
1483
1642
  if (!tc.compilerOptions) tc.compilerOptions = {};
1484
1643
  const existingPaths = tc.compilerOptions.paths ?? {};
1485
1644
  if (existingPaths["@/*"]) return false;
1486
1645
  tc.compilerOptions.paths = { "@/*": ["./src/*"], ...existingPaths };
1487
- import_node_fs4.default.writeFileSync(tsconfigPath, JSON.stringify(tc, null, 2), "utf-8");
1646
+ import_node_fs5.default.writeFileSync(tsconfigPath, JSON.stringify(tc, null, 2), "utf-8");
1488
1647
  return true;
1489
1648
  } catch {
1490
1649
  return false;
@@ -1492,7 +1651,7 @@ function patchTsconfigApp(tsconfigPath) {
1492
1651
  }
1493
1652
  function patchViteConfig(viteConfigPath) {
1494
1653
  try {
1495
- let content = import_node_fs4.default.readFileSync(viteConfigPath, "utf-8");
1654
+ let content = import_node_fs5.default.readFileSync(viteConfigPath, "utf-8");
1496
1655
  if (content.includes("'@'") || content.includes('"@"') || content.includes("'@/*'") || content.includes('"@/*"') || content.includes("resolve:")) return false;
1497
1656
  if (!content.includes("import path from 'path'") && !content.includes('import path from "path"')) {
1498
1657
  const importMatches = [...content.matchAll(/^import .+$/gm)];
@@ -1511,7 +1670,7 @@ function patchViteConfig(viteConfigPath) {
1511
1670
  alias: { '@': path.resolve(__dirname, './src') },
1512
1671
  },`;
1513
1672
  content = content.slice(0, lastClose) + resolveBlock + content.slice(lastClose);
1514
- import_node_fs4.default.writeFileSync(viteConfigPath, content, "utf-8");
1673
+ import_node_fs5.default.writeFileSync(viteConfigPath, content, "utf-8");
1515
1674
  return true;
1516
1675
  } catch {
1517
1676
  return false;
@@ -1521,17 +1680,17 @@ function resolveAliasPath(projectRoot, alias) {
1521
1680
  if (!alias.startsWith("@/")) return null;
1522
1681
  const relative = alias.slice(2);
1523
1682
  for (const srcDir of ["src", "app", "."]) {
1524
- const candidate = import_node_path4.default.join(projectRoot, srcDir, relative);
1525
- if (import_node_fs4.default.existsSync(import_node_path4.default.dirname(candidate)) || srcDir === "src") {
1526
- return import_node_path4.default.join(projectRoot, srcDir, relative);
1683
+ const candidate = import_node_path5.default.join(projectRoot, srcDir, relative);
1684
+ if (import_node_fs5.default.existsSync(import_node_path5.default.dirname(candidate)) || srcDir === "src") {
1685
+ return import_node_path5.default.join(projectRoot, srcDir, relative);
1527
1686
  }
1528
1687
  }
1529
- return import_node_path4.default.join(projectRoot, "src", relative);
1688
+ return import_node_path5.default.join(projectRoot, "src", relative);
1530
1689
  }
1531
1690
 
1532
1691
  // cli/src/commands/add.ts
1533
- var import_node_fs5 = __toESM(require("node:fs"));
1534
- var import_node_path5 = __toESM(require("node:path"));
1692
+ var import_node_fs6 = __toESM(require("node:fs"));
1693
+ var import_node_path6 = __toESM(require("node:path"));
1535
1694
  var import_picocolors3 = __toESM(require_picocolors());
1536
1695
 
1537
1696
  // cli/src/utils/rewrite-imports.ts
@@ -13863,8 +14022,8 @@ async function add(args) {
13863
14022
  for (const name of allComponents) {
13864
14023
  const item = registry[name];
13865
14024
  for (const file of item.files) {
13866
- const filePath = import_node_path5.default.join(componentsDir, file.path);
13867
- toAdd.push({ name, fileName: file.path, content: file.content, filePath, exists: import_node_fs5.default.existsSync(filePath) });
14025
+ const filePath = import_node_path6.default.join(componentsDir, file.path);
14026
+ toAdd.push({ name, fileName: file.path, content: file.content, filePath, exists: import_node_fs6.default.existsSync(filePath) });
13868
14027
  }
13869
14028
  }
13870
14029
  const newFiles = toAdd.filter((f) => !f.exists || flagOverwrite);
@@ -13879,8 +14038,8 @@ async function add(args) {
13879
14038
  allNpmDeps.add(dep);
13880
14039
  }
13881
14040
  }
13882
- const pkgJsonPath = import_node_path5.default.join(projectRoot, "package.json");
13883
- const pkgJson = JSON.parse(import_node_fs5.default.readFileSync(pkgJsonPath, "utf-8"));
14041
+ const pkgJsonPath = import_node_path6.default.join(projectRoot, "package.json");
14042
+ const pkgJson = JSON.parse(import_node_fs6.default.readFileSync(pkgJsonPath, "utf-8"));
13884
14043
  const installedDeps = { ...pkgJson.dependencies, ...pkgJson.devDependencies };
13885
14044
  const depsToInstall = [...allNpmDeps].filter((d3) => !installedDeps[d3]);
13886
14045
  if (!flagYes) {
@@ -13909,24 +14068,24 @@ async function add(args) {
13909
14068
  process.exit(0);
13910
14069
  }
13911
14070
  }
13912
- if (!import_node_fs5.default.existsSync(componentsDir)) {
13913
- import_node_fs5.default.mkdirSync(componentsDir, { recursive: true });
14071
+ if (!import_node_fs6.default.existsSync(componentsDir)) {
14072
+ import_node_fs6.default.mkdirSync(componentsDir, { recursive: true });
13914
14073
  }
13915
14074
  let addedCount = 0;
13916
14075
  for (const entry of toAdd) {
13917
14076
  if (entry.exists && !flagOverwrite) continue;
13918
14077
  const content = rewriteImports(entry.content, config.aliases.utils);
13919
- import_node_fs5.default.writeFileSync(entry.filePath, content, "utf-8");
14078
+ import_node_fs6.default.writeFileSync(entry.filePath, content, "utf-8");
13920
14079
  addedCount++;
13921
14080
  logger.success(`${entry.exists ? "Overwrote" : "Added"} ${entry.fileName}`);
13922
14081
  }
13923
14082
  if (config.tailwind.version === 4 && addedCount > 0) {
13924
14083
  try {
13925
- const cssFullPath = import_node_path5.default.join(projectRoot, config.tailwind.css);
13926
- if (import_node_fs5.default.existsSync(cssFullPath)) {
13927
- const cssContent = import_node_fs5.default.readFileSync(cssFullPath, "utf-8");
13928
- const cssDir = import_node_path5.default.dirname(cssFullPath);
13929
- const relRaw = import_node_path5.default.relative(cssDir, componentsDir).replace(/\\/g, "/");
14084
+ const cssFullPath = import_node_path6.default.join(projectRoot, config.tailwind.css);
14085
+ if (import_node_fs6.default.existsSync(cssFullPath)) {
14086
+ const cssContent = import_node_fs6.default.readFileSync(cssFullPath, "utf-8");
14087
+ const cssDir = import_node_path6.default.dirname(cssFullPath);
14088
+ const relRaw = import_node_path6.default.relative(cssDir, componentsDir).replace(/\\/g, "/");
13930
14089
  const relSource = relRaw.startsWith(".") ? relRaw : `./${relRaw}`;
13931
14090
  const sourcePattern = new RegExp(`@source\\s+["']${relSource.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}["']`);
13932
14091
  if (!sourcePattern.test(cssContent)) {
@@ -13937,7 +14096,7 @@ async function add(args) {
13937
14096
  const insertAt = lineEnd !== -1 ? lineEnd + 1 : cssContent.length;
13938
14097
  const updated = cssContent.slice(0, insertAt) + `@source "${relSource}";
13939
14098
  ` + cssContent.slice(insertAt);
13940
- import_node_fs5.default.writeFileSync(cssFullPath, updated, "utf-8");
14099
+ import_node_fs6.default.writeFileSync(cssFullPath, updated, "utf-8");
13941
14100
  O2.success(`Added @source "${relSource}" to ${config.tailwind.css}`);
13942
14101
  } else {
13943
14102
  O2.warn(
@@ -13970,6 +14129,7 @@ async function add(args) {
13970
14129
  }
13971
14130
  const addedNames = [...new Set(newFiles.map((f) => f.name))];
13972
14131
  showSetupHints(addedNames);
14132
+ showCompanionHints(addedNames);
13973
14133
  if (skippedFiles.length > 0) {
13974
14134
  logger.info(`${skippedFiles.length} file(s) skipped (already exist)`);
13975
14135
  }
@@ -13999,14 +14159,14 @@ function resolveDependencies(names) {
13999
14159
  }
14000
14160
  function resolveAliasToDir(projectRoot, alias) {
14001
14161
  if (!alias.startsWith("@/")) {
14002
- return import_node_path5.default.join(projectRoot, alias);
14162
+ return import_node_path6.default.join(projectRoot, alias);
14003
14163
  }
14004
14164
  const relative = alias.slice(2);
14005
14165
  for (const srcDir of ["src", "app", "."]) {
14006
- const candidate = import_node_path5.default.join(projectRoot, srcDir, relative);
14007
- if (import_node_fs5.default.existsSync(candidate)) return candidate;
14166
+ const candidate = import_node_path6.default.join(projectRoot, srcDir, relative);
14167
+ if (import_node_fs6.default.existsSync(candidate)) return candidate;
14008
14168
  }
14009
- return import_node_path5.default.join(projectRoot, "src", relative);
14169
+ return import_node_path6.default.join(projectRoot, "src", relative);
14010
14170
  }
14011
14171
  function findSimilar(input, candidates) {
14012
14172
  let best = null;
@@ -14066,10 +14226,29 @@ function showSetupHints(names) {
14066
14226
  );
14067
14227
  }
14068
14228
  }
14229
+ var COMPANION_HINTS = {
14230
+ "toggle": ["toggle-group"],
14231
+ "toggle-group": ["toggle"]
14232
+ };
14233
+ function showCompanionHints(names) {
14234
+ const added = new Set(names);
14235
+ const suggested = /* @__PURE__ */ new Set();
14236
+ for (const name of names) {
14237
+ for (const companion of COMPANION_HINTS[name] || []) {
14238
+ if (added.has(companion)) continue;
14239
+ suggested.add(companion);
14240
+ }
14241
+ }
14242
+ for (const name of suggested) {
14243
+ logger.info(
14244
+ `${import_picocolors3.default.dim("Tip:")} also using ${import_picocolors3.default.cyan(name)}? Run: ${import_picocolors3.default.green(`npx 7onic add ${name}`)}`
14245
+ );
14246
+ }
14247
+ }
14069
14248
 
14070
14249
  // cli/src/index.ts
14071
14250
  var import_picocolors4 = __toESM(require_picocolors());
14072
- var VERSION = "0.1.9";
14251
+ var VERSION = "0.1.11";
14073
14252
  var HELP = `
14074
14253
  ${import_picocolors4.default.bold("7onic")} \u2014 Add 7onic design system components to your project
14075
14254
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "7onic",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "CLI for adding 7onic design system components to your project",
5
5
  "bin": {
6
6
  "7onic": "./dist/index.js"