notionsoft-ui 1.0.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 +21 -0
- package/cli/index.cjs +165 -0
- package/package.json +33 -0
- package/src/templates/button/button.tsx +25 -0
- package/src/templates/card/card.tsx +20 -0
- package/src/utils/cn.js +15 -0
- package/src/utils/cn.ts +9 -0
- package/tsconfig.json +12 -0
package/README.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# ðĻ NotionSoft-UI
|
|
2
|
+
|
|
3
|
+
A **shadcn-style component installer** that copies React components directly into your project.
|
|
4
|
+
|
|
5
|
+
## âĻ Features
|
|
6
|
+
|
|
7
|
+
- ð Install components into your codebase
|
|
8
|
+
- ðĻ Tailwind CSS friendly
|
|
9
|
+
- ðŠķ Lightweight (no runtime dependencies)
|
|
10
|
+
- ð§ Full control of the components
|
|
11
|
+
- ðĶ Works with any React + TypeScript project
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## ðĶ Installation
|
|
16
|
+
|
|
17
|
+
Inside your project:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
npx notionsoft-ui init
|
|
21
|
+
```
|
package/cli/index.cjs
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { program } = require("commander");
|
|
4
|
+
const fs = require("fs-extra");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
const chalk = require("chalk");
|
|
7
|
+
const { execSync } = require("child_process");
|
|
8
|
+
|
|
9
|
+
/* ------------------------------
|
|
10
|
+
Helper: get template path
|
|
11
|
+
------------------------------- */
|
|
12
|
+
function getTemplateFile(component) {
|
|
13
|
+
// Library template: src/templates/button/button.tsx
|
|
14
|
+
return path.join(
|
|
15
|
+
__dirname,
|
|
16
|
+
"../src/templates",
|
|
17
|
+
component,
|
|
18
|
+
component + ".tsx"
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* ------------------------------
|
|
23
|
+
Install dependencies in project
|
|
24
|
+
------------------------------- */
|
|
25
|
+
function installDependencies() {
|
|
26
|
+
try {
|
|
27
|
+
console.log(chalk.cyan("Installing dependencies: clsx, tailwind-merge..."));
|
|
28
|
+
execSync("npm install clsx tailwind-merge", { stdio: "inherit" });
|
|
29
|
+
console.log(chalk.green("â Dependencies installed"));
|
|
30
|
+
} catch (err) {
|
|
31
|
+
console.log(chalk.red("â Failed to install dependencies"));
|
|
32
|
+
console.error(err);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* ------------------------------
|
|
37
|
+
Update tsconfig.json for absolute imports
|
|
38
|
+
------------------------------- */
|
|
39
|
+
function updateTsConfig() {
|
|
40
|
+
const tsconfigPath = path.join(process.cwd(), "tsconfig.json");
|
|
41
|
+
|
|
42
|
+
if (!fs.existsSync(tsconfigPath)) {
|
|
43
|
+
console.log(
|
|
44
|
+
chalk.yellow("â tsconfig.json not found, skipping baseUrl setup.")
|
|
45
|
+
);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const tsconfig = fs.readJsonSync(tsconfigPath);
|
|
50
|
+
tsconfig.compilerOptions = tsconfig.compilerOptions || {};
|
|
51
|
+
tsconfig.compilerOptions.baseUrl = "src";
|
|
52
|
+
tsconfig.compilerOptions.paths = tsconfig.compilerOptions.paths || {};
|
|
53
|
+
tsconfig.compilerOptions.paths["@utils/*"] = ["utils/*"];
|
|
54
|
+
tsconfig.compilerOptions.paths["@components/*"] = ["components/*"];
|
|
55
|
+
|
|
56
|
+
fs.writeJsonSync(tsconfigPath, tsconfig, { spaces: 2 });
|
|
57
|
+
console.log(
|
|
58
|
+
chalk.green(
|
|
59
|
+
"â tsconfig.json updated for absolute imports (@utils/*, @components/*)"
|
|
60
|
+
)
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/* ------------------------------
|
|
65
|
+
Command: init
|
|
66
|
+
------------------------------- */
|
|
67
|
+
program
|
|
68
|
+
.command("init")
|
|
69
|
+
.description("Initialize NotionSoft-UI in your project")
|
|
70
|
+
.action(() => {
|
|
71
|
+
const cwd = process.cwd();
|
|
72
|
+
const configPath = path.join(cwd, ".notionsoft-ui.json");
|
|
73
|
+
|
|
74
|
+
if (fs.existsSync(configPath)) {
|
|
75
|
+
console.log(chalk.yellow("â NotionSoft-UI already initialized."));
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Create config
|
|
80
|
+
fs.writeFileSync(
|
|
81
|
+
configPath,
|
|
82
|
+
JSON.stringify({ componentDir: "src/components/notion-ui" }, null, 2)
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
// Ensure component folder
|
|
86
|
+
const componentDir = path.join(cwd, "src/components/notion-ui");
|
|
87
|
+
fs.ensureDirSync(componentDir);
|
|
88
|
+
|
|
89
|
+
// Create utils folder and cn helper
|
|
90
|
+
const utilsDir = path.join(cwd, "src/utils");
|
|
91
|
+
fs.ensureDirSync(utilsDir);
|
|
92
|
+
const cnPath = path.join(utilsDir, "cn.ts");
|
|
93
|
+
|
|
94
|
+
if (!fs.existsSync(cnPath)) {
|
|
95
|
+
fs.writeFileSync(
|
|
96
|
+
cnPath,
|
|
97
|
+
`import { clsx } from "clsx";
|
|
98
|
+
import { twMerge } from "tailwind-merge";
|
|
99
|
+
|
|
100
|
+
export function cn(...inputs: Parameters<typeof clsx>) {
|
|
101
|
+
return twMerge(clsx(...inputs));
|
|
102
|
+
}`
|
|
103
|
+
);
|
|
104
|
+
console.log(chalk.green("â cn helper created at src/utils/cn.ts"));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Install dependencies
|
|
108
|
+
installDependencies();
|
|
109
|
+
|
|
110
|
+
// Update tsconfig.json for absolute imports
|
|
111
|
+
updateTsConfig();
|
|
112
|
+
|
|
113
|
+
console.log(chalk.green("â NotionSoft-UI initialized and ready!"));
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
/* ------------------------------
|
|
117
|
+
Command: add <component>
|
|
118
|
+
------------------------------- */
|
|
119
|
+
program
|
|
120
|
+
.command("add <component>")
|
|
121
|
+
.description("Install a NotionSoft-UI component")
|
|
122
|
+
.action((component) => {
|
|
123
|
+
const cwd = process.cwd();
|
|
124
|
+
const configFile = path.join(cwd, ".notionsoft-ui.json");
|
|
125
|
+
|
|
126
|
+
if (!fs.existsSync(configFile)) {
|
|
127
|
+
console.log(chalk.red("â Run `npx notionsoft-ui init` first."));
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const config = fs.readJSONSync(configFile);
|
|
132
|
+
const templateFile = getTemplateFile(component);
|
|
133
|
+
|
|
134
|
+
if (!fs.existsSync(templateFile)) {
|
|
135
|
+
console.log(chalk.red(`â Component '${component}' does not exist.`));
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Copy as a flat file into user's project
|
|
140
|
+
const destFile = path.join(config.componentDir, component + ".tsx");
|
|
141
|
+
fs.ensureDirSync(config.componentDir);
|
|
142
|
+
fs.copyFileSync(templateFile, destFile);
|
|
143
|
+
|
|
144
|
+
console.log(
|
|
145
|
+
chalk.green(`â Installed ${component} component as ${destFile}`)
|
|
146
|
+
);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
/* ------------------------------
|
|
150
|
+
Command: list
|
|
151
|
+
------------------------------- */
|
|
152
|
+
program
|
|
153
|
+
.command("list")
|
|
154
|
+
.description("List available components")
|
|
155
|
+
.action(() => {
|
|
156
|
+
const templatesDir = path.join(__dirname, "../src/templates");
|
|
157
|
+
const components = fs.readdirSync(templatesDir).filter((folder) => {
|
|
158
|
+
const file = path.join(templatesDir, folder, folder + ".tsx");
|
|
159
|
+
return fs.existsSync(file);
|
|
160
|
+
});
|
|
161
|
+
console.log(chalk.cyan("Available components:"));
|
|
162
|
+
components.forEach((c) => console.log(" âĒ " + c));
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
program.parse();
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "notionsoft-ui",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A React UI component installer (shadcn-style). Installs components directly into your project.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"notionsoft-ui": "./cli/index.cjs"
|
|
7
|
+
},
|
|
8
|
+
"author": "NotionSoft",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"keywords": [
|
|
11
|
+
"react",
|
|
12
|
+
"components",
|
|
13
|
+
"ui",
|
|
14
|
+
"tailwind",
|
|
15
|
+
"shadcn",
|
|
16
|
+
"installer",
|
|
17
|
+
"cli"
|
|
18
|
+
],
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"chalk": "^4.1.2",
|
|
21
|
+
"clsx": "^2.1.1",
|
|
22
|
+
"commander": "^12.0.0",
|
|
23
|
+
"fs-extra": "^11.2.0",
|
|
24
|
+
"react": "^19.2.0",
|
|
25
|
+
"react-dom": "^19.2.0",
|
|
26
|
+
"tailwind-merge": "^3.4.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/react": "^19.2.6",
|
|
30
|
+
"@types/react-dom": "^19.2.3",
|
|
31
|
+
"typescript": "^5.9.3"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { cn } from "@/utils/cn";
|
|
2
|
+
import React from "react";
|
|
3
|
+
|
|
4
|
+
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
5
|
+
variant?: "default" | "primary" | "secondary";
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const Button: React.FC<ButtonProps> = ({
|
|
9
|
+
variant = "default",
|
|
10
|
+
className,
|
|
11
|
+
...props
|
|
12
|
+
}) => {
|
|
13
|
+
return (
|
|
14
|
+
<button
|
|
15
|
+
className={cn(
|
|
16
|
+
"px-4 py-2 rounded-md font-medium transition-colors",
|
|
17
|
+
variant === "primary" && "bg-blue-500 text-white",
|
|
18
|
+
variant === "secondary" && "bg-gray-200 text-black",
|
|
19
|
+
className
|
|
20
|
+
)}
|
|
21
|
+
{...props}
|
|
22
|
+
/>
|
|
23
|
+
);
|
|
24
|
+
};
|
|
25
|
+
export default Button;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { cn } from "@/utils/cn";
|
|
2
|
+
import React from "react";
|
|
3
|
+
|
|
4
|
+
interface CardProps extends React.HTMLAttributes<HTMLDivElement> {}
|
|
5
|
+
|
|
6
|
+
const Card: React.FC<CardProps> = ({ className, children, ...props }) => {
|
|
7
|
+
return (
|
|
8
|
+
<div
|
|
9
|
+
className={cn(
|
|
10
|
+
"bg-card text-card-foreground border border-border rounded-lg p-4 shadow-sm",
|
|
11
|
+
className
|
|
12
|
+
)}
|
|
13
|
+
{...props}
|
|
14
|
+
>
|
|
15
|
+
{children}
|
|
16
|
+
</div>
|
|
17
|
+
);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default Card;
|
package/src/utils/cn.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cn = cn;
|
|
4
|
+
var clsx_1 = require("clsx");
|
|
5
|
+
var tailwind_merge_1 = require("tailwind-merge");
|
|
6
|
+
/**
|
|
7
|
+
* Merge Tailwind classes intelligently
|
|
8
|
+
*/
|
|
9
|
+
function cn() {
|
|
10
|
+
var inputs = [];
|
|
11
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
12
|
+
inputs[_i] = arguments[_i];
|
|
13
|
+
}
|
|
14
|
+
return (0, tailwind_merge_1.twMerge)(clsx_1.clsx.apply(void 0, inputs));
|
|
15
|
+
}
|
package/src/utils/cn.ts
ADDED