7onic 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +135 -24
- package/llms.txt +6 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1198,7 +1198,7 @@ function installDeps(deps, options) {
|
|
|
1198
1198
|
const commands = {
|
|
1199
1199
|
npm: `npm install${devFlag} ${deps.join(" ")}`,
|
|
1200
1200
|
pnpm: `pnpm add${devFlag} ${deps.join(" ")}`,
|
|
1201
|
-
yarn: `yarn add${devFlag} ${deps.join(" ")}`,
|
|
1201
|
+
yarn: `yarn add --ignore-engines${devFlag} ${deps.join(" ")}`,
|
|
1202
1202
|
bun: `bun add${devFlag} ${deps.join(" ")}`
|
|
1203
1203
|
};
|
|
1204
1204
|
(0, import_node_child_process.execSync)(commands[pm], { cwd, stdio: "pipe" });
|
|
@@ -1246,7 +1246,11 @@ var CSS_V3_IMPORTS = `@import '@7onic-ui/tokens/css/variables.css';
|
|
|
1246
1246
|
@import '@7onic-ui/tokens/css/themes/light.css';
|
|
1247
1247
|
@import '@7onic-ui/tokens/css/themes/dark.css';
|
|
1248
1248
|
`;
|
|
1249
|
-
var CSS_V4_IMPORTS = `@import
|
|
1249
|
+
var CSS_V4_IMPORTS = `@import "tailwindcss";
|
|
1250
|
+
@import '@7onic-ui/tokens/css/variables.css';
|
|
1251
|
+
@import '@7onic-ui/tokens/tailwind/v4.css';
|
|
1252
|
+
`;
|
|
1253
|
+
var CSS_V4_TOKEN_ONLY = `@import '@7onic-ui/tokens/css/variables.css';
|
|
1250
1254
|
@import '@7onic-ui/tokens/tailwind/v4.css';
|
|
1251
1255
|
`;
|
|
1252
1256
|
async function init(args) {
|
|
@@ -1281,15 +1285,37 @@ async function init(args) {
|
|
|
1281
1285
|
const tw = detectTailwindVersion(projectRoot);
|
|
1282
1286
|
const pm = detectPackageManager(projectRoot);
|
|
1283
1287
|
let hasPathAlias = false;
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
+
const TSCONFIG_CANDIDATES = ["tsconfig.json", "tsconfig.app.json"];
|
|
1289
|
+
for (const tc of TSCONFIG_CANDIDATES) {
|
|
1290
|
+
try {
|
|
1291
|
+
const raw = import_node_fs4.default.readFileSync(import_node_path4.default.join(projectRoot, tc), "utf-8");
|
|
1292
|
+
if (raw.includes('"@/')) {
|
|
1293
|
+
hasPathAlias = true;
|
|
1294
|
+
break;
|
|
1295
|
+
}
|
|
1296
|
+
} catch {
|
|
1297
|
+
}
|
|
1288
1298
|
}
|
|
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;
|
|
1301
|
+
let needsTypesNode = false;
|
|
1289
1302
|
if (!hasPathAlias) {
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1303
|
+
if (isViteProject) {
|
|
1304
|
+
const tscPatch = patchTsconfigApp(import_node_path4.default.join(projectRoot, "tsconfig.app.json"));
|
|
1305
|
+
const vitePatch = patchViteConfig(viteConfigPath);
|
|
1306
|
+
if (vitePatch) needsTypesNode = true;
|
|
1307
|
+
if (tscPatch || vitePatch) {
|
|
1308
|
+
O2.success("Configured @/ path alias in tsconfig.app.json and vite.config.ts");
|
|
1309
|
+
} else {
|
|
1310
|
+
O2.warn(
|
|
1311
|
+
'Could not auto-configure @/ path alias. Add manually:\n tsconfig.app.json \u2192 compilerOptions.paths: { "@/*": ["./src/*"] }\n vite.config.ts \u2192 resolve: { alias: { "@": path.resolve(__dirname, "./src") } }'
|
|
1312
|
+
);
|
|
1313
|
+
}
|
|
1314
|
+
} else {
|
|
1315
|
+
O2.warn(
|
|
1316
|
+
"No @/ path alias detected.\n Next.js: automatic (no action needed)\n Other: configure compilerOptions.paths in tsconfig.json"
|
|
1317
|
+
);
|
|
1318
|
+
}
|
|
1293
1319
|
}
|
|
1294
1320
|
try {
|
|
1295
1321
|
const pkgJson = JSON.parse(import_node_fs4.default.readFileSync(import_node_path4.default.join(projectRoot, "package.json"), "utf-8"));
|
|
@@ -1353,6 +1379,9 @@ async function init(args) {
|
|
|
1353
1379
|
s.start(`Installing dependencies (${pm})...`);
|
|
1354
1380
|
try {
|
|
1355
1381
|
installDeps(baseDeps, { cwd: projectRoot, pm });
|
|
1382
|
+
if (needsTypesNode) {
|
|
1383
|
+
installDeps(["@types/node"], { cwd: projectRoot, pm, dev: true });
|
|
1384
|
+
}
|
|
1356
1385
|
s.stop("Dependencies installed");
|
|
1357
1386
|
} catch (err) {
|
|
1358
1387
|
s.stop("Failed to install dependencies");
|
|
@@ -1360,18 +1389,30 @@ async function init(args) {
|
|
|
1360
1389
|
process.exit(1);
|
|
1361
1390
|
}
|
|
1362
1391
|
const cssFullPath = import_node_path4.default.join(projectRoot, config.cssPath);
|
|
1363
|
-
const cssImports = tailwindVersion === 3 ? CSS_V3_IMPORTS : CSS_V4_IMPORTS;
|
|
1364
1392
|
if (!import_node_fs4.default.existsSync(cssFullPath)) {
|
|
1365
1393
|
const cssDir = import_node_path4.default.dirname(cssFullPath);
|
|
1366
1394
|
if (!import_node_fs4.default.existsSync(cssDir)) {
|
|
1367
1395
|
import_node_fs4.default.mkdirSync(cssDir, { recursive: true });
|
|
1368
1396
|
}
|
|
1397
|
+
const cssImports = tailwindVersion === 3 ? CSS_V3_IMPORTS : CSS_V4_IMPORTS;
|
|
1369
1398
|
import_node_fs4.default.writeFileSync(cssFullPath, cssImports, "utf-8");
|
|
1370
1399
|
O2.success(`Created ${config.cssPath} with token imports`);
|
|
1371
1400
|
} else {
|
|
1372
1401
|
const cssContent = import_node_fs4.default.readFileSync(cssFullPath, "utf-8");
|
|
1373
1402
|
if (!cssContent.includes("@7onic-ui/tokens")) {
|
|
1374
|
-
|
|
1403
|
+
const tokenImports = tailwindVersion === 3 ? CSS_V3_IMPORTS : CSS_V4_TOKEN_ONLY;
|
|
1404
|
+
if (tailwindVersion === 4) {
|
|
1405
|
+
const twMatch = cssContent.match(/@import\s+["']tailwindcss["'].*\n/);
|
|
1406
|
+
if (twMatch) {
|
|
1407
|
+
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");
|
|
1410
|
+
} else {
|
|
1411
|
+
import_node_fs4.default.writeFileSync(cssFullPath, CSS_V4_IMPORTS + "\n" + cssContent, "utf-8");
|
|
1412
|
+
}
|
|
1413
|
+
} else {
|
|
1414
|
+
import_node_fs4.default.writeFileSync(cssFullPath, tokenImports + "\n" + cssContent, "utf-8");
|
|
1415
|
+
}
|
|
1375
1416
|
O2.success(`Added token imports to ${config.cssPath}`);
|
|
1376
1417
|
} else {
|
|
1377
1418
|
O2.info(`Token imports already present in ${config.cssPath}`);
|
|
@@ -1434,6 +1475,48 @@ async function init(args) {
|
|
|
1434
1475
|
O2.success("Created 7onic.json");
|
|
1435
1476
|
gt("Done! Run " + import_picocolors2.default.cyan("npx 7onic add <component>") + " to add components.");
|
|
1436
1477
|
}
|
|
1478
|
+
function patchTsconfigApp(tsconfigPath) {
|
|
1479
|
+
try {
|
|
1480
|
+
const raw = import_node_fs4.default.readFileSync(tsconfigPath, "utf-8");
|
|
1481
|
+
const clean = raw.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "").replace(/,(\s*[}\]])/g, "$1");
|
|
1482
|
+
const tc = JSON.parse(clean);
|
|
1483
|
+
if (!tc.compilerOptions) tc.compilerOptions = {};
|
|
1484
|
+
const existingPaths = tc.compilerOptions.paths ?? {};
|
|
1485
|
+
if (existingPaths["@/*"]) return false;
|
|
1486
|
+
tc.compilerOptions.paths = { "@/*": ["./src/*"], ...existingPaths };
|
|
1487
|
+
import_node_fs4.default.writeFileSync(tsconfigPath, JSON.stringify(tc, null, 2), "utf-8");
|
|
1488
|
+
return true;
|
|
1489
|
+
} catch {
|
|
1490
|
+
return false;
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
function patchViteConfig(viteConfigPath) {
|
|
1494
|
+
try {
|
|
1495
|
+
let content = import_node_fs4.default.readFileSync(viteConfigPath, "utf-8");
|
|
1496
|
+
if (content.includes("'@'") || content.includes('"@"') || content.includes("'@/*'") || content.includes('"@/*"') || content.includes("resolve:")) return false;
|
|
1497
|
+
if (!content.includes("import path from 'path'") && !content.includes('import path from "path"')) {
|
|
1498
|
+
const importMatches = [...content.matchAll(/^import .+$/gm)];
|
|
1499
|
+
const lastImport = importMatches.at(-1);
|
|
1500
|
+
if (lastImport?.index !== void 0) {
|
|
1501
|
+
const insertAt = lastImport.index + lastImport[0].length;
|
|
1502
|
+
content = content.slice(0, insertAt) + "\nimport path from 'path'" + content.slice(insertAt);
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
const lastClose = content.lastIndexOf("\n})");
|
|
1506
|
+
if (lastClose === -1) return false;
|
|
1507
|
+
const beforeClose = content.slice(0, lastClose).trimEnd();
|
|
1508
|
+
const comma = beforeClose.endsWith(",") ? "" : ",";
|
|
1509
|
+
const resolveBlock = `${comma}
|
|
1510
|
+
resolve: {
|
|
1511
|
+
alias: { '@': path.resolve(__dirname, './src') },
|
|
1512
|
+
},`;
|
|
1513
|
+
content = content.slice(0, lastClose) + resolveBlock + content.slice(lastClose);
|
|
1514
|
+
import_node_fs4.default.writeFileSync(viteConfigPath, content, "utf-8");
|
|
1515
|
+
return true;
|
|
1516
|
+
} catch {
|
|
1517
|
+
return false;
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1437
1520
|
function resolveAliasPath(projectRoot, alias) {
|
|
1438
1521
|
if (!alias.startsWith("@/")) return null;
|
|
1439
1522
|
const relative = alias.slice(2);
|
|
@@ -3223,12 +3306,6 @@ const CardRoot = React.forwardRef<HTMLDivElement, CardProps>(
|
|
|
3223
3306
|
CardRoot.displayName = 'Card'
|
|
3224
3307
|
|
|
3225
3308
|
// \u2500\u2500 Size-based padding map (responsive: mobile \u2192 desktop) \u2500\u2500
|
|
3226
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
3227
|
-
const sizePaddingMap = {
|
|
3228
|
-
sm: 'p-4', // 16px
|
|
3229
|
-
default: 'p-4 sm:p-6', // 16px \u2192 24px
|
|
3230
|
-
lg: 'p-6 sm:p-8', // 24px \u2192 32px
|
|
3231
|
-
} as const
|
|
3232
3309
|
|
|
3233
3310
|
const sizePaddingXMap = {
|
|
3234
3311
|
sm: 'px-4', // 16px
|
|
@@ -8780,8 +8857,9 @@ const PaginationRoot = React.forwardRef<HTMLElement, PaginationProps>(
|
|
|
8780
8857
|
color = 'default',
|
|
8781
8858
|
radius = 'md',
|
|
8782
8859
|
disabled = false,
|
|
8783
|
-
|
|
8784
|
-
|
|
8860
|
+
// Pre-declared API; conditional auto-rendering is tracked in COMPONENT-IMPROVEMENTS.md.
|
|
8861
|
+
withControls: _withControls = true,
|
|
8862
|
+
withEdges: _withEdges = false,
|
|
8785
8863
|
loop = false,
|
|
8786
8864
|
children,
|
|
8787
8865
|
...props
|
|
@@ -13028,7 +13106,6 @@ const ToastItem = React.memo(function ToastItem({
|
|
|
13028
13106
|
}: ToastItemProps) {
|
|
13029
13107
|
const [isExiting, setIsExiting] = React.useState(false)
|
|
13030
13108
|
const [isEntered, setIsEntered] = React.useState(false)
|
|
13031
|
-
const [isPaused, setIsPaused] = React.useState(false) // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
13032
13109
|
const timerRef = React.useRef<ReturnType<typeof setTimeout> | null>(null)
|
|
13033
13110
|
const remainingRef = React.useRef<number>(0)
|
|
13034
13111
|
const startTimeRef = React.useRef<number>(0)
|
|
@@ -13095,10 +13172,9 @@ const ToastItem = React.memo(function ToastItem({
|
|
|
13095
13172
|
}
|
|
13096
13173
|
}, [duration, handleAutoClose])
|
|
13097
13174
|
|
|
13098
|
-
// Pause/resume on hover
|
|
13175
|
+
// Pause/resume on hover (ref-only \u2014 no state update needed, avoids unnecessary re-renders)
|
|
13099
13176
|
const handleMouseEnter = React.useCallback(() => {
|
|
13100
13177
|
if (duration <= 0) return
|
|
13101
|
-
setIsPaused(true)
|
|
13102
13178
|
if (timerRef.current) {
|
|
13103
13179
|
clearTimeout(timerRef.current)
|
|
13104
13180
|
remainingRef.current -= Date.now() - startTimeRef.current
|
|
@@ -13107,7 +13183,6 @@ const ToastItem = React.memo(function ToastItem({
|
|
|
13107
13183
|
|
|
13108
13184
|
const handleMouseLeave = React.useCallback(() => {
|
|
13109
13185
|
if (duration <= 0) return
|
|
13110
|
-
setIsPaused(false)
|
|
13111
13186
|
startTimeRef.current = Date.now()
|
|
13112
13187
|
timerRef.current = setTimeout(handleAutoClose, Math.max(remainingRef.current, TOAST_MIN_RESUME_MS))
|
|
13113
13188
|
}, [duration, handleAutoClose])
|
|
@@ -14255,6 +14330,42 @@ async function add(args) {
|
|
|
14255
14330
|
addedCount++;
|
|
14256
14331
|
logger.success(`${entry.exists ? "Overwrote" : "Added"} ${entry.fileName}`);
|
|
14257
14332
|
}
|
|
14333
|
+
if (config.tailwind.version === 4 && addedCount > 0) {
|
|
14334
|
+
try {
|
|
14335
|
+
const cssFullPath = import_node_path5.default.join(projectRoot, config.tailwind.css);
|
|
14336
|
+
if (import_node_fs5.default.existsSync(cssFullPath)) {
|
|
14337
|
+
const cssContent = import_node_fs5.default.readFileSync(cssFullPath, "utf-8");
|
|
14338
|
+
const cssDir = import_node_path5.default.dirname(cssFullPath);
|
|
14339
|
+
const relRaw = import_node_path5.default.relative(cssDir, componentsDir).replace(/\\/g, "/");
|
|
14340
|
+
const relSource = relRaw.startsWith(".") ? relRaw : `./${relRaw}`;
|
|
14341
|
+
const sourcePattern = new RegExp(`@source\\s+["']${relSource.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}["']`);
|
|
14342
|
+
if (!sourcePattern.test(cssContent)) {
|
|
14343
|
+
const marker = "@7onic-ui/tokens";
|
|
14344
|
+
const lastIdx = cssContent.lastIndexOf(marker);
|
|
14345
|
+
if (lastIdx !== -1) {
|
|
14346
|
+
const lineEnd = cssContent.indexOf("\n", lastIdx);
|
|
14347
|
+
const insertAt = lineEnd !== -1 ? lineEnd + 1 : cssContent.length;
|
|
14348
|
+
const updated = cssContent.slice(0, insertAt) + `@source "${relSource}";
|
|
14349
|
+
` + cssContent.slice(insertAt);
|
|
14350
|
+
import_node_fs5.default.writeFileSync(cssFullPath, updated, "utf-8");
|
|
14351
|
+
O2.success(`Added @source "${relSource}" to ${config.tailwind.css}`);
|
|
14352
|
+
} else {
|
|
14353
|
+
O2.warn(
|
|
14354
|
+
`Could not find @7onic-ui/tokens import in ${config.tailwind.css}.
|
|
14355
|
+
Run ${import_picocolors3.default.cyan("npx 7onic init")} first, or manually add to your CSS:
|
|
14356
|
+
|
|
14357
|
+
@source "${relSource}";`
|
|
14358
|
+
);
|
|
14359
|
+
}
|
|
14360
|
+
}
|
|
14361
|
+
}
|
|
14362
|
+
} catch (err) {
|
|
14363
|
+
if (err instanceof Error && "code" in err && err.code === "ENOENT") {
|
|
14364
|
+
} else {
|
|
14365
|
+
O2.warn(`Failed to inject @source into ${config.tailwind.css}: ${err}`);
|
|
14366
|
+
}
|
|
14367
|
+
}
|
|
14368
|
+
}
|
|
14258
14369
|
if (depsToInstall.length > 0) {
|
|
14259
14370
|
const pm = detectPackageManager(projectRoot);
|
|
14260
14371
|
const s = fe();
|
|
@@ -14368,7 +14479,7 @@ function showSetupHints(names) {
|
|
|
14368
14479
|
|
|
14369
14480
|
// cli/src/index.ts
|
|
14370
14481
|
var import_picocolors4 = __toESM(require_picocolors());
|
|
14371
|
-
var VERSION = "0.1.
|
|
14482
|
+
var VERSION = "0.1.6";
|
|
14372
14483
|
var HELP = `
|
|
14373
14484
|
${import_picocolors4.default.bold("7onic")} \u2014 Add 7onic design system components to your project
|
|
14374
14485
|
|
package/llms.txt
CHANGED
|
@@ -25,14 +25,15 @@ npx 7onic init --tailwind v3 --yes # Explicit v3, skip prompts
|
|
|
25
25
|
**What it does:**
|
|
26
26
|
1. Detects Tailwind version (v3: config file exists, v4: no config) — or uses `--tailwind` flag
|
|
27
27
|
2. Detects package manager (npm/pnpm/yarn/bun)
|
|
28
|
-
3.
|
|
29
|
-
4.
|
|
30
|
-
5. Creates
|
|
31
|
-
6.
|
|
28
|
+
3. **Vite projects**: auto-configures `@/` path alias — patches `tsconfig.app.json` (JSONC-safe) and `vite.config.ts` (adds `import path` + `resolve.alias`), installs `@types/node`
|
|
29
|
+
4. Installs: `@7onic-ui/tokens`, `lucide-react`, `clsx`, `tailwind-merge`, `class-variance-authority`
|
|
30
|
+
5. Creates/updates CSS file with token imports (v4: auto-injects `@import "tailwindcss"` if missing)
|
|
31
|
+
6. Creates `cn()` utility at configured path
|
|
32
|
+
7. Writes `7onic.json` config
|
|
32
33
|
|
|
33
34
|
**Requirements:**
|
|
34
35
|
- TypeScript project (tsconfig.json required)
|
|
35
|
-
- `@/` path alias configured
|
|
36
|
+
- `@/` path alias — auto-configured for Vite; Next.js handles this automatically
|
|
36
37
|
|
|
37
38
|
### add
|
|
38
39
|
|