Skip to content

Commit d267066

Browse files
committed
chore: add register script
1 parent 143be04 commit d267066

File tree

7 files changed

+233
-1
lines changed

7 files changed

+233
-1
lines changed

packages/ui/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626
"files": ["dist"],
2727
"scripts": {
2828
"build": "tsdown",
29-
"dev": "tsdown --watch ./src/index.ts"
29+
"build:registry": "shadcn build -o ../../playground/public/r",
30+
"dev": "tsdown --watch ./src/index.ts",
31+
"register": "tsx script/registry.ts"
3032
},
3133
"dependencies": {
3234
"@radix-ui/react-accordion": "^1.2.11",
@@ -56,7 +58,9 @@
5658
"@types/react": "19.1.0",
5759
"@types/react-dom": "19.1.1",
5860
"fast-glob": "^3.3.3",
61+
"shadcn": "^2.9.0",
5962
"tsdown": "^0.12.9",
63+
"tsx": "^4.20.3",
6064
"typescript": "5.8.2"
6165
}
6266
}

packages/ui/script/constants.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
export const registryComponentsDependencies: Record<
2+
string,
3+
{ dependencies: string[]; registryDependencies?: string[] }
4+
> = {
5+
accordion: {
6+
dependencies: ['@radix-ui/react-accordion', '@radix-ui/react-slot']
7+
},
8+
alert: {
9+
dependencies: ['@radix-ui/react-slot']
10+
},
11+
'alert-dialog': {
12+
dependencies: ['@radix-ui/react-alert-dialog', '@radix-ui/react-slot'],
13+
registryDependencies: ['button']
14+
},
15+
'aspect-ratio': {
16+
dependencies: ['@radix-ui/react-aspect-ratio']
17+
},
18+
avatar: {
19+
dependencies: ['@radix-ui/react-avatar']
20+
},
21+
breadcrumb: {
22+
dependencies: ['@radix-ui/react-slot']
23+
},
24+
button: {
25+
dependencies: ['@radix-ui/react-slot']
26+
},
27+
carousel: {
28+
dependencies: ['embla-carousel-react'],
29+
registryDependencies: ['button']
30+
},
31+
checkbox: {
32+
dependencies: ['@radix-ui/react-checkbox']
33+
},
34+
divider: {
35+
dependencies: ['@radix-ui/react-separator']
36+
},
37+
label: {
38+
dependencies: ['@radix-ui/react-label']
39+
},
40+
'scroll-area': {
41+
dependencies: ['@radix-ui/react-scroll-area']
42+
},
43+
sonner: {
44+
dependencies: ['sonner', 'next-themes']
45+
},
46+
tabs: {
47+
dependencies: ['@radix-ui/react-tabs', '@radix-ui/react-compose-refs']
48+
}
49+
} as const;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { type Registry } from 'shadcn/registry';
2+
3+
export const registerType: Registry['items'][number] = {
4+
files: [
5+
{
6+
path: 'src/types/other.ts',
7+
target: 'types/other.ts',
8+
type: 'registry:file'
9+
}
10+
],
11+
name: 'types',
12+
title: 'Types',
13+
type: 'registry:file'
14+
};

packages/ui/script/registry-ui.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import path from 'node:path';
2+
3+
import fg from 'fast-glob';
4+
import { type Registry } from 'shadcn/registry';
5+
6+
import { registryComponentsDependencies } from './constants';
7+
8+
const COMPONENTS_DIR = 'src/components';
9+
10+
function formatComponentName(str: string): string {
11+
return str
12+
.split('-')
13+
.map(part => part.charAt(0).toUpperCase() + part.slice(1))
14+
.join(' ');
15+
}
16+
17+
function getGroupedComponents(): Record<string, string[]> {
18+
const components = fg.sync(`${COMPONENTS_DIR}/**/*`);
19+
const grouped: Record<string, string[]> = {};
20+
21+
for (const fullPath of components) {
22+
const segments = fullPath.split(path.sep);
23+
const group = segments[2]; // 如 'accordion'
24+
const name = segments[3]; // 文件名
25+
26+
// eslint-disable-next-line no-continue
27+
if (!group || !name) continue;
28+
29+
if (!grouped[group]) grouped[group] = [];
30+
grouped[group].push(name);
31+
}
32+
33+
return grouped;
34+
}
35+
36+
function generateRegistryItems(grouped: Record<string, string[]>): Registry['items'] {
37+
const ui = Object.entries(grouped).map(([group, files]) => {
38+
const item = {
39+
files: files.map(file => ({
40+
path: `${COMPONENTS_DIR}/${group}/${file}`,
41+
target: `components/${group}/${file}`,
42+
type: 'registry:ui'
43+
})),
44+
name: group,
45+
title: formatComponentName(group),
46+
type: 'registry:block'
47+
};
48+
49+
if (registryComponentsDependencies[group]) {
50+
Object.assign(item, registryComponentsDependencies[group]);
51+
}
52+
53+
return item;
54+
}) as Registry['items'];
55+
56+
console.log('🎨 UI component conversion completed.');
57+
58+
return ui;
59+
}
60+
61+
export function getRegistryUi(): Registry['items'] {
62+
console.log('📦 Starting to collect components for registry...');
63+
const grouped = getGroupedComponents();
64+
65+
console.log('✅ Component collection completed.');
66+
67+
return generateRegistryItems(grouped);
68+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { type Registry } from 'shadcn/registry';
2+
3+
export const registryUtils: Registry['items'][number] = {
4+
dependencies: ['clsx', 'tailwind-merge'],
5+
files: [
6+
{
7+
path: 'src/lib/utils.ts',
8+
type: 'registry:lib'
9+
},
10+
{
11+
path: 'src/lib/typed.ts',
12+
type: 'registry:lib'
13+
}
14+
],
15+
name: 'utils',
16+
title: 'Utils',
17+
type: 'registry:lib'
18+
};

packages/ui/script/registry.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { exec } from 'node:child_process';
2+
import fs from 'node:fs/promises';
3+
import path from 'node:path';
4+
5+
import { registerType } from './registry-type';
6+
import { getRegistryUi } from './registry-ui';
7+
import { registryUtils } from './registry-utils';
8+
9+
const registry = {
10+
homepage: 'https://ui-playground.ohh-889.com/',
11+
items: [
12+
{
13+
cssVars: {},
14+
dependencies: ['tailwind-variants', 'lucide-react'],
15+
files: [],
16+
name: 'index',
17+
registryDependencies: ['utils'],
18+
type: 'registry:style'
19+
},
20+
...getRegistryUi(),
21+
registerType,
22+
registryUtils
23+
],
24+
name: 'soybean-react-ui'
25+
};
26+
27+
async function writeRegistry() {
28+
const registryJson = JSON.stringify(registry, null, 2);
29+
// eslint-disable-next-line n/prefer-global/process
30+
await fs.writeFile(path.join(process.cwd(), `registry.json`), registryJson);
31+
}
32+
33+
async function buildRegistry() {
34+
return new Promise((resolve, reject) => {
35+
const process = exec(`pnpm build:registry`);
36+
37+
process.on('exit', code => {
38+
if (code === 0) {
39+
resolve(undefined);
40+
} else {
41+
reject(new Error(`Process exited with code ${code}`));
42+
}
43+
});
44+
});
45+
}
46+
47+
async function main() {
48+
try {
49+
console.log('🔨 Starting registry build...');
50+
await writeRegistry();
51+
52+
await buildRegistry();
53+
console.log('✅ Registry build completed');
54+
} catch (error) {
55+
console.error('❌ Build failed with error:');
56+
console.error(error);
57+
if (error instanceof Error) {
58+
console.error('Error stack:', error.stack);
59+
}
60+
// eslint-disable-next-line n/prefer-global/process
61+
process.exit(1);
62+
}
63+
}
64+
65+
main();

playground/public/r/index.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
3+
"name": "index",
4+
"type": "registry:style",
5+
"dependencies": [
6+
"tailwind-variants",
7+
"lucide-react"
8+
],
9+
"registryDependencies": [
10+
"utils"
11+
],
12+
"files": [],
13+
"cssVars": {}
14+
}

0 commit comments

Comments
 (0)