trix-ui 0.2.2 → 0.2.4
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 +306 -306
- package/dist/commands/build.js +104 -104
- package/dist/index.js +0 -0
- package/package.json +10 -10
- package/registry/index.json +203 -180
- package/templates/components/ui/badge.tsx +182 -182
- package/templates/composites/music-player-card.tsx +583 -208
- package/templates/sections/signature-hero.tsx +92 -0
- package/templates/wrappers/Interative-wrapper.tsx +1 -1
- package/templates/wrappers/progress-wrapper.tsx +248 -0
- package/templates/wrappers/reveal-wrap.tsx +136 -0
- package/templates/sections/modern-hero.tsx +0 -1226
package/dist/commands/build.js
CHANGED
|
@@ -1,105 +1,105 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { promises as fs } from "node:fs";
|
|
3
|
-
import { Command } from "commander";
|
|
4
|
-
import { Project } from "ts-morph";
|
|
5
|
-
import { registryIndexSchema, registrySchema } from "../schema/index.js";
|
|
6
|
-
import { transformIcons, transformMenu, transformRender } from "../utils/index.js";
|
|
7
|
-
const DEFAULT_ITEM_SCHEMA = "https://ui.
|
|
8
|
-
export const buildCommand = new Command("build")
|
|
9
|
-
.description("Build registry items into JSON files")
|
|
10
|
-
.argument("[registry]", "path to registry.json", "registry.json")
|
|
11
|
-
.option("--output <dir>", "output directory", "dist")
|
|
12
|
-
.option("--style <name>", "style name")
|
|
13
|
-
.option("--icon-library <name>", "icon library")
|
|
14
|
-
.option("--menu-color <name>", "menu color")
|
|
15
|
-
.option("--schema <url>", "registry item schema URL")
|
|
16
|
-
.action(async (registryArg, options) => {
|
|
17
|
-
try {
|
|
18
|
-
const cwd = process.cwd();
|
|
19
|
-
const registryPath = resolvePath(cwd, registryArg);
|
|
20
|
-
const { registry, items } = await loadRegistry(registryPath);
|
|
21
|
-
const outputDir = resolvePath(cwd, options.output ?? "dist");
|
|
22
|
-
const transformConfig = getTransformConfig(items, options);
|
|
23
|
-
const project = new Project({ useInMemoryFileSystem: true });
|
|
24
|
-
await fs.mkdir(outputDir, { recursive: true });
|
|
25
|
-
for (const item of items) {
|
|
26
|
-
const payload = await buildRegistryItem(cwd, project, item, transformConfig, options.schema);
|
|
27
|
-
const outputPath = path.join(outputDir, `${item.name}.json`);
|
|
28
|
-
await fs.writeFile(outputPath, JSON.stringify(payload, null, 2));
|
|
29
|
-
}
|
|
30
|
-
if (registry) {
|
|
31
|
-
const registryOutput = { ...registry, items };
|
|
32
|
-
await fs.writeFile(path.join(outputDir, "registry.json"), JSON.stringify(registryOutput, null, 2));
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
catch (error) {
|
|
36
|
-
console.error(error.message);
|
|
37
|
-
process.exit(1);
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
function resolvePath(cwd, value) {
|
|
41
|
-
return path.isAbsolute(value) ? value : path.resolve(cwd, value);
|
|
42
|
-
}
|
|
43
|
-
async function loadRegistry(registryPath) {
|
|
44
|
-
const raw = await fs.readFile(registryPath, "utf8");
|
|
45
|
-
const parsed = JSON.parse(raw);
|
|
46
|
-
if (Array.isArray(parsed)) {
|
|
47
|
-
return {
|
|
48
|
-
items: registryIndexSchema.parse(parsed)
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
const registry = registrySchema.parse(parsed);
|
|
52
|
-
return {
|
|
53
|
-
registry,
|
|
54
|
-
items: registry.items
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
function getTransformConfig(items, options) {
|
|
58
|
-
const config = {
|
|
59
|
-
style: options.style,
|
|
60
|
-
iconLibrary: options.iconLibrary,
|
|
61
|
-
menuColor: options.menuColor
|
|
62
|
-
};
|
|
63
|
-
const baseItem = items.find((item) => item.type === "registry:base");
|
|
64
|
-
if (baseItem?.config) {
|
|
65
|
-
config.style ??= baseItem.config.style;
|
|
66
|
-
config.iconLibrary ??= baseItem.config.iconLibrary;
|
|
67
|
-
config.menuColor ??= baseItem.config.menuColor;
|
|
68
|
-
}
|
|
69
|
-
return config;
|
|
70
|
-
}
|
|
71
|
-
async function buildRegistryItem(cwd, project, item, config, schemaOverride) {
|
|
72
|
-
const payload = { ...item };
|
|
73
|
-
const schemaValue = schemaOverride ?? DEFAULT_ITEM_SCHEMA;
|
|
74
|
-
if (!payload.$schema && schemaValue) {
|
|
75
|
-
payload.$schema = schemaValue;
|
|
76
|
-
}
|
|
77
|
-
if (item.files) {
|
|
78
|
-
payload.files = await Promise.all(item.files.map(async (file) => {
|
|
79
|
-
const sourcePath = resolvePath(cwd, file.path);
|
|
80
|
-
const raw = file.content ?? (await fs.readFile(sourcePath, "utf8"));
|
|
81
|
-
const content = isSourceFile(file.path)
|
|
82
|
-
? await transformSource(project, file.path, raw, config)
|
|
83
|
-
: raw;
|
|
84
|
-
return {
|
|
85
|
-
...file,
|
|
86
|
-
content
|
|
87
|
-
};
|
|
88
|
-
}));
|
|
89
|
-
}
|
|
90
|
-
return payload;
|
|
91
|
-
}
|
|
92
|
-
async function transformSource(project, filename, raw, config) {
|
|
93
|
-
const sourceFile = project.createSourceFile(filename, raw, {
|
|
94
|
-
overwrite: true
|
|
95
|
-
});
|
|
96
|
-
let next = await transformRender({ filename, raw, config, sourceFile });
|
|
97
|
-
next = await transformMenu({ filename, raw, config, sourceFile: next });
|
|
98
|
-
next = await transformIcons({ filename, raw, config, sourceFile: next });
|
|
99
|
-
return next.getFullText();
|
|
100
|
-
}
|
|
101
|
-
function isSourceFile(filePath) {
|
|
102
|
-
const ext = path.extname(filePath).toLowerCase();
|
|
103
|
-
return ext === ".ts" || ext === ".tsx" || ext === ".js" || ext === ".jsx";
|
|
104
|
-
}
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { promises as fs } from "node:fs";
|
|
3
|
+
import { Command } from "commander";
|
|
4
|
+
import { Project } from "ts-morph";
|
|
5
|
+
import { registryIndexSchema, registrySchema } from "../schema/index.js";
|
|
6
|
+
import { transformIcons, transformMenu, transformRender } from "../utils/index.js";
|
|
7
|
+
const DEFAULT_ITEM_SCHEMA = "https://ui.trix.com/schema/registry-item.json";
|
|
8
|
+
export const buildCommand = new Command("build")
|
|
9
|
+
.description("Build registry items into JSON files")
|
|
10
|
+
.argument("[registry]", "path to registry.json", "registry.json")
|
|
11
|
+
.option("--output <dir>", "output directory", "dist")
|
|
12
|
+
.option("--style <name>", "style name")
|
|
13
|
+
.option("--icon-library <name>", "icon library")
|
|
14
|
+
.option("--menu-color <name>", "menu color")
|
|
15
|
+
.option("--schema <url>", "registry item schema URL")
|
|
16
|
+
.action(async (registryArg, options) => {
|
|
17
|
+
try {
|
|
18
|
+
const cwd = process.cwd();
|
|
19
|
+
const registryPath = resolvePath(cwd, registryArg);
|
|
20
|
+
const { registry, items } = await loadRegistry(registryPath);
|
|
21
|
+
const outputDir = resolvePath(cwd, options.output ?? "dist");
|
|
22
|
+
const transformConfig = getTransformConfig(items, options);
|
|
23
|
+
const project = new Project({ useInMemoryFileSystem: true });
|
|
24
|
+
await fs.mkdir(outputDir, { recursive: true });
|
|
25
|
+
for (const item of items) {
|
|
26
|
+
const payload = await buildRegistryItem(cwd, project, item, transformConfig, options.schema);
|
|
27
|
+
const outputPath = path.join(outputDir, `${item.name}.json`);
|
|
28
|
+
await fs.writeFile(outputPath, JSON.stringify(payload, null, 2));
|
|
29
|
+
}
|
|
30
|
+
if (registry) {
|
|
31
|
+
const registryOutput = { ...registry, items };
|
|
32
|
+
await fs.writeFile(path.join(outputDir, "registry.json"), JSON.stringify(registryOutput, null, 2));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
console.error(error.message);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
function resolvePath(cwd, value) {
|
|
41
|
+
return path.isAbsolute(value) ? value : path.resolve(cwd, value);
|
|
42
|
+
}
|
|
43
|
+
async function loadRegistry(registryPath) {
|
|
44
|
+
const raw = await fs.readFile(registryPath, "utf8");
|
|
45
|
+
const parsed = JSON.parse(raw);
|
|
46
|
+
if (Array.isArray(parsed)) {
|
|
47
|
+
return {
|
|
48
|
+
items: registryIndexSchema.parse(parsed)
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const registry = registrySchema.parse(parsed);
|
|
52
|
+
return {
|
|
53
|
+
registry,
|
|
54
|
+
items: registry.items
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function getTransformConfig(items, options) {
|
|
58
|
+
const config = {
|
|
59
|
+
style: options.style,
|
|
60
|
+
iconLibrary: options.iconLibrary,
|
|
61
|
+
menuColor: options.menuColor
|
|
62
|
+
};
|
|
63
|
+
const baseItem = items.find((item) => item.type === "registry:base");
|
|
64
|
+
if (baseItem?.config) {
|
|
65
|
+
config.style ??= baseItem.config.style;
|
|
66
|
+
config.iconLibrary ??= baseItem.config.iconLibrary;
|
|
67
|
+
config.menuColor ??= baseItem.config.menuColor;
|
|
68
|
+
}
|
|
69
|
+
return config;
|
|
70
|
+
}
|
|
71
|
+
async function buildRegistryItem(cwd, project, item, config, schemaOverride) {
|
|
72
|
+
const payload = { ...item };
|
|
73
|
+
const schemaValue = schemaOverride ?? DEFAULT_ITEM_SCHEMA;
|
|
74
|
+
if (!payload.$schema && schemaValue) {
|
|
75
|
+
payload.$schema = schemaValue;
|
|
76
|
+
}
|
|
77
|
+
if (item.files) {
|
|
78
|
+
payload.files = await Promise.all(item.files.map(async (file) => {
|
|
79
|
+
const sourcePath = resolvePath(cwd, file.path);
|
|
80
|
+
const raw = file.content ?? (await fs.readFile(sourcePath, "utf8"));
|
|
81
|
+
const content = isSourceFile(file.path)
|
|
82
|
+
? await transformSource(project, file.path, raw, config)
|
|
83
|
+
: raw;
|
|
84
|
+
return {
|
|
85
|
+
...file,
|
|
86
|
+
content
|
|
87
|
+
};
|
|
88
|
+
}));
|
|
89
|
+
}
|
|
90
|
+
return payload;
|
|
91
|
+
}
|
|
92
|
+
async function transformSource(project, filename, raw, config) {
|
|
93
|
+
const sourceFile = project.createSourceFile(filename, raw, {
|
|
94
|
+
overwrite: true
|
|
95
|
+
});
|
|
96
|
+
let next = await transformRender({ filename, raw, config, sourceFile });
|
|
97
|
+
next = await transformMenu({ filename, raw, config, sourceFile: next });
|
|
98
|
+
next = await transformIcons({ filename, raw, config, sourceFile: next });
|
|
99
|
+
return next.getFullText();
|
|
100
|
+
}
|
|
101
|
+
function isSourceFile(filePath) {
|
|
102
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
103
|
+
return ext === ".ts" || ext === ".tsx" || ext === ".js" || ext === ".jsx";
|
|
104
|
+
}
|
|
105
105
|
//# sourceMappingURL=build.js.map
|
package/dist/index.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trix-ui",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "Lite UI CLI, registry tooling, and templates.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -33,14 +33,6 @@
|
|
|
33
33
|
"tailwind.css",
|
|
34
34
|
"README.md"
|
|
35
35
|
],
|
|
36
|
-
"scripts": {
|
|
37
|
-
"build": "tsc -p tsconfig.json",
|
|
38
|
-
"dev": "node --enable-source-maps --import tsx src/index.ts",
|
|
39
|
-
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
40
|
-
"pub:beta": "pnpm build && pnpm publish --no-git-checks --access public --tag beta",
|
|
41
|
-
"pub:release": "pnpm build && pnpm publish --access public",
|
|
42
|
-
"test": "vitest"
|
|
43
|
-
},
|
|
44
36
|
"dependencies": {
|
|
45
37
|
"@antfu/ni": "^28.2.0",
|
|
46
38
|
"chalk": "^5.6.2",
|
|
@@ -64,5 +56,13 @@
|
|
|
64
56
|
"@types/prompts": "^2.4.9",
|
|
65
57
|
"tsx": "^4.21.0",
|
|
66
58
|
"typescript": "^5.9.3"
|
|
59
|
+
},
|
|
60
|
+
"scripts": {
|
|
61
|
+
"build": "tsc -p tsconfig.json",
|
|
62
|
+
"dev": "node --enable-source-maps --import tsx src/index.ts",
|
|
63
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
64
|
+
"pub:beta": "pnpm build && pnpm publish --no-git-checks --access public --tag beta",
|
|
65
|
+
"pub:release": "pnpm build && pnpm publish --access public",
|
|
66
|
+
"test": "vitest"
|
|
67
67
|
}
|
|
68
|
-
}
|
|
68
|
+
}
|
package/registry/index.json
CHANGED
|
@@ -1,181 +1,204 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 1,
|
|
3
|
-
"components": [
|
|
4
|
-
{
|
|
5
|
-
"name": "avatar",
|
|
6
|
-
"description": "Avatar with image, fallback, and grouping helpers.",
|
|
7
|
-
"files": [
|
|
8
|
-
{
|
|
9
|
-
"source": "components/ui/avatar.tsx",
|
|
10
|
-
"target": "{{components}}/avatar.tsx"
|
|
11
|
-
}
|
|
12
|
-
],
|
|
13
|
-
"dependencies": {
|
|
14
|
-
"npm": ["@radix-ui/react-avatar", "clsx", "tailwind-merge"]
|
|
15
|
-
}
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
"name": "badge",
|
|
19
|
-
"description": "Badge with variants.",
|
|
20
|
-
"files": [
|
|
21
|
-
{
|
|
22
|
-
"source": "components/ui/badge.tsx",
|
|
23
|
-
"target": "{{components}}/badge.tsx"
|
|
24
|
-
}
|
|
25
|
-
],
|
|
26
|
-
"dependencies": {
|
|
27
|
-
"npm": ["clsx", "tailwind-merge"]
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
"name": "button",
|
|
32
|
-
"description": "Button with variants and focus ring.",
|
|
33
|
-
"files": [
|
|
34
|
-
{
|
|
35
|
-
"source": "components/ui/button.tsx",
|
|
36
|
-
"target": "{{components}}/button.tsx"
|
|
37
|
-
}
|
|
38
|
-
],
|
|
39
|
-
"dependencies": {
|
|
40
|
-
"npm": ["clsx", "tailwind-merge"]
|
|
41
|
-
}
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
"name": "card",
|
|
45
|
-
"description": "Card container with header/content/footer.",
|
|
46
|
-
"files": [
|
|
47
|
-
{
|
|
48
|
-
"source": "components/ui/card.tsx",
|
|
49
|
-
"target": "{{components}}/card.tsx"
|
|
50
|
-
}
|
|
51
|
-
],
|
|
52
|
-
"dependencies": {
|
|
53
|
-
"npm": ["clsx", "tailwind-merge"]
|
|
54
|
-
}
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
"name": "input",
|
|
58
|
-
"description": "Text input with consistent focus styles.",
|
|
59
|
-
"files": [
|
|
60
|
-
{
|
|
61
|
-
"source": "components/ui/input.tsx",
|
|
62
|
-
"target": "{{components}}/input.tsx"
|
|
63
|
-
}
|
|
64
|
-
],
|
|
65
|
-
"dependencies": {
|
|
66
|
-
"npm": ["clsx", "tailwind-merge"]
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
"name": "label",
|
|
71
|
-
"description": "Label with accessible focus and disabled styles.",
|
|
72
|
-
"files": [
|
|
73
|
-
{
|
|
74
|
-
"source": "components/ui/label.tsx",
|
|
75
|
-
"target": "{{components}}/label.tsx"
|
|
76
|
-
}
|
|
77
|
-
],
|
|
78
|
-
"dependencies": {
|
|
79
|
-
"npm": ["@radix-ui/react-label", "clsx", "tailwind-merge"]
|
|
80
|
-
}
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
"name": "tabs",
|
|
84
|
-
"description": "Tabs using Radix primitives.",
|
|
85
|
-
"files": [
|
|
86
|
-
{
|
|
87
|
-
"source": "components/ui/tabs.tsx",
|
|
88
|
-
"target": "{{components}}/tabs.tsx"
|
|
89
|
-
}
|
|
90
|
-
],
|
|
91
|
-
"dependencies": {
|
|
92
|
-
"npm": ["@radix-ui/react-tabs", "clsx", "tailwind-merge"]
|
|
93
|
-
}
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
"name": "textarea",
|
|
97
|
-
"description": "Textarea with consistent focus styles.",
|
|
98
|
-
"files": [
|
|
99
|
-
{
|
|
100
|
-
"source": "components/ui/textarea.tsx",
|
|
101
|
-
"target": "{{components}}/textarea.tsx"
|
|
102
|
-
}
|
|
103
|
-
],
|
|
104
|
-
"dependencies": {
|
|
105
|
-
"npm": ["clsx", "tailwind-merge"]
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
],
|
|
109
|
-
"sections": [
|
|
110
|
-
{
|
|
111
|
-
"name": "
|
|
112
|
-
"description": "
|
|
113
|
-
"files": [
|
|
114
|
-
{
|
|
115
|
-
"source": "sections/
|
|
116
|
-
"target": "{{sections}}/
|
|
117
|
-
}
|
|
118
|
-
]
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
"
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"components": [
|
|
4
|
+
{
|
|
5
|
+
"name": "avatar",
|
|
6
|
+
"description": "Avatar with image, fallback, and grouping helpers.",
|
|
7
|
+
"files": [
|
|
8
|
+
{
|
|
9
|
+
"source": "components/ui/avatar.tsx",
|
|
10
|
+
"target": "{{components}}/avatar.tsx"
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"npm": ["@radix-ui/react-avatar", "clsx", "tailwind-merge"]
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "badge",
|
|
19
|
+
"description": "Badge with variants.",
|
|
20
|
+
"files": [
|
|
21
|
+
{
|
|
22
|
+
"source": "components/ui/badge.tsx",
|
|
23
|
+
"target": "{{components}}/badge.tsx"
|
|
24
|
+
}
|
|
25
|
+
],
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"npm": ["clsx", "tailwind-merge"]
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"name": "button",
|
|
32
|
+
"description": "Button with variants and focus ring.",
|
|
33
|
+
"files": [
|
|
34
|
+
{
|
|
35
|
+
"source": "components/ui/button.tsx",
|
|
36
|
+
"target": "{{components}}/button.tsx"
|
|
37
|
+
}
|
|
38
|
+
],
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"npm": ["clsx", "tailwind-merge"]
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"name": "card",
|
|
45
|
+
"description": "Card container with header/content/footer.",
|
|
46
|
+
"files": [
|
|
47
|
+
{
|
|
48
|
+
"source": "components/ui/card.tsx",
|
|
49
|
+
"target": "{{components}}/card.tsx"
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"npm": ["clsx", "tailwind-merge"]
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"name": "input",
|
|
58
|
+
"description": "Text input with consistent focus styles.",
|
|
59
|
+
"files": [
|
|
60
|
+
{
|
|
61
|
+
"source": "components/ui/input.tsx",
|
|
62
|
+
"target": "{{components}}/input.tsx"
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
"dependencies": {
|
|
66
|
+
"npm": ["clsx", "tailwind-merge"]
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"name": "label",
|
|
71
|
+
"description": "Label with accessible focus and disabled styles.",
|
|
72
|
+
"files": [
|
|
73
|
+
{
|
|
74
|
+
"source": "components/ui/label.tsx",
|
|
75
|
+
"target": "{{components}}/label.tsx"
|
|
76
|
+
}
|
|
77
|
+
],
|
|
78
|
+
"dependencies": {
|
|
79
|
+
"npm": ["@radix-ui/react-label", "clsx", "tailwind-merge"]
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"name": "tabs",
|
|
84
|
+
"description": "Tabs using Radix primitives.",
|
|
85
|
+
"files": [
|
|
86
|
+
{
|
|
87
|
+
"source": "components/ui/tabs.tsx",
|
|
88
|
+
"target": "{{components}}/tabs.tsx"
|
|
89
|
+
}
|
|
90
|
+
],
|
|
91
|
+
"dependencies": {
|
|
92
|
+
"npm": ["@radix-ui/react-tabs", "clsx", "tailwind-merge"]
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"name": "textarea",
|
|
97
|
+
"description": "Textarea with consistent focus styles.",
|
|
98
|
+
"files": [
|
|
99
|
+
{
|
|
100
|
+
"source": "components/ui/textarea.tsx",
|
|
101
|
+
"target": "{{components}}/textarea.tsx"
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
"dependencies": {
|
|
105
|
+
"npm": ["clsx", "tailwind-merge"]
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
],
|
|
109
|
+
"sections": [
|
|
110
|
+
{
|
|
111
|
+
"name": "signature-hero",
|
|
112
|
+
"description": "Premium editorial hero with layered panels, glow accents, and CTAs.",
|
|
113
|
+
"files": [
|
|
114
|
+
{
|
|
115
|
+
"source": "sections/signature-hero.tsx",
|
|
116
|
+
"target": "{{sections}}/signature-hero.tsx"
|
|
117
|
+
}
|
|
118
|
+
]
|
|
119
|
+
}
|
|
120
|
+
],
|
|
121
|
+
"wrappers": [
|
|
122
|
+
{
|
|
123
|
+
"name": "interactive-wrap",
|
|
124
|
+
"description": "Interactive wrapper with hover glow and magnetic press.",
|
|
125
|
+
"files": [
|
|
126
|
+
{
|
|
127
|
+
"source": "wrappers/Interative-wrapper.tsx",
|
|
128
|
+
"target": "{{wrappers}}/interactive-wrap.tsx"
|
|
129
|
+
}
|
|
130
|
+
],
|
|
131
|
+
"dependencies": {
|
|
132
|
+
"npm": ["@radix-ui/react-slot", "clsx", "tailwind-merge"]
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"name": "reveal-wrap",
|
|
137
|
+
"description": "Scroll reveal wrapper with motion-safe transitions.",
|
|
138
|
+
"files": [
|
|
139
|
+
{
|
|
140
|
+
"source": "wrappers/reveal-wrap.tsx",
|
|
141
|
+
"target": "{{wrappers}}/reveal-wrap.tsx"
|
|
142
|
+
}
|
|
143
|
+
],
|
|
144
|
+
"dependencies": {
|
|
145
|
+
"npm": ["clsx", "tailwind-merge"]
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"name": "progress-wrap",
|
|
150
|
+
"description": "Scroll progress wrapper with render-prop state.",
|
|
151
|
+
"files": [
|
|
152
|
+
{
|
|
153
|
+
"source": "wrappers/progress-wrapper.tsx",
|
|
154
|
+
"target": "{{wrappers}}/progress-wrap.tsx"
|
|
155
|
+
}
|
|
156
|
+
],
|
|
157
|
+
"dependencies": {
|
|
158
|
+
"npm": ["clsx", "tailwind-merge"]
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
],
|
|
162
|
+
"composites": [
|
|
163
|
+
{
|
|
164
|
+
"name": "feature-collection-card",
|
|
165
|
+
"description": "Card for spotlighting a featured collection.",
|
|
166
|
+
"files": [
|
|
167
|
+
{
|
|
168
|
+
"source": "composites/feature-collection-card.tsx",
|
|
169
|
+
"target": "{{composites}}/feature-collection-card.tsx"
|
|
170
|
+
}
|
|
171
|
+
],
|
|
172
|
+
"dependencies": {
|
|
173
|
+
"npm": ["clsx", "tailwind-merge"]
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
"name": "music-player-card",
|
|
178
|
+
"description": "Premium music player card with transport controls.",
|
|
179
|
+
"files": [
|
|
180
|
+
{
|
|
181
|
+
"source": "composites/music-player-card.tsx",
|
|
182
|
+
"target": "{{composites}}/music-player-card.tsx"
|
|
183
|
+
}
|
|
184
|
+
],
|
|
185
|
+
"dependencies": {
|
|
186
|
+
"npm": ["lucide-react", "clsx", "tailwind-merge"]
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"name": "user-profile-card",
|
|
191
|
+
"description": "Profile card with avatar, tags, and action button.",
|
|
192
|
+
"files": [
|
|
193
|
+
{
|
|
194
|
+
"source": "composites/user-profile-card.tsx",
|
|
195
|
+
"target": "{{composites}}/user-profile-card.tsx"
|
|
196
|
+
}
|
|
197
|
+
],
|
|
198
|
+
"dependencies": {
|
|
199
|
+
"local": ["badge", "button", "card"],
|
|
200
|
+
"npm": ["lucide-react", "clsx", "tailwind-merge"]
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
]
|
|
181
204
|
}
|