Skip to content

Commit 49e6d53

Browse files
Improvements and chores - 5 Aug 2025 [OFFICIAL TS SUPPORT] (#1300)
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
1 parent f089588 commit 49e6d53

File tree

9 files changed

+250
-62
lines changed

9 files changed

+250
-62
lines changed

.husky/pre-commit

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
#!/usr/bin/env sh
22
. "$(dirname -- "$0")/_/husky.sh"
3-
4-
#!/bin/sh
5-
. ~/.zshrc # or ~/.bashrc if using bash
63
npm test
74

85
npm run lint:staged

README.md

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,8 @@ npm install @radui/ui
2323
```
2424

2525
Description: Rad UI is a React UI library that simplifies UI development, offering a collection of components and utilities to enhance the user experience. It addresses common challenges in building interfaces, making it easier for developers to create intuitive and visually appealing applications.
26-
27-
Technology stack: React
28-
Status: Beta
29-
Please note that Rad UI is under development and will receive a full official release soon in 2024 once significant production-ready components are readily available.
30-
What sets this apart: Rad UI stands out with its focus on simplicity, flexibility, and ease of integration into React projects.
3126
<!--
3227
33-
3428
## Dependencies
3529
3630
Describe any dependencies that must be installed for this software to work.
@@ -66,8 +60,8 @@ For more details, you can read on how to contribute to development of Rad UI in
6660

6761
[Setting Up Dev Environment](https://www.rad-ui.com/docs/contributing/setting-up-dev-environment)
6862

69-
7063
## Where can I get more help, if I need it?
64+
7165
[GitHub Discussions](https://github.com/rad-ui/ui/discussions)
7266
[Discord](https://discord.com/invite/nMaQfeEPNp)
7367

@@ -83,4 +77,4 @@ Node versions tested in 18.19.0 - 21.4.0
8377

8478
1. Project heavily inspired by RadixUI, Floating UI, shadcn/ui and many other libraries that defined the modern web that we know today
8579

86-
This project is tested with BrowserStack
80+
This project is tested with BrowserStack

package-lock.json

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 6 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,46 +4,7 @@
44
"description": "",
55
"main": "dist",
66
"type": "module",
7-
"exports": {
8-
"./themes/default.css": "./dist/themes/default.css",
9-
"./themes/tailwind-presets/default.js": "./dist/themes/tailwind-presets/default.js",
10-
"./Accordion": "./dist/components/Accordion.js",
11-
"./AlertDialog": "./dist/components/AlertDialog.js",
12-
"./AspectRatio": "./dist/components/AspectRatio.js",
13-
"./Avatar": "./dist/components/Avatar.js",
14-
"./AvatarGroup": "./dist/components/AvatarGroup.js",
15-
"./Badge": "./dist/components/Badge.js",
16-
"./BlockQuote": "./dist/components/BlockQuote.js",
17-
"./Button": "./dist/components/Button.js",
18-
"./Callout": "./dist/components/Callout.js",
19-
"./Card": "./dist/components/Card.js",
20-
"./Code": "./dist/components/Code.js",
21-
"./Collapsible": "./dist/components/Collapsible.js",
22-
"./DataList": "./dist/components/DataList.js",
23-
"./Dialog": "./dist/components/Dialog.js",
24-
"./Em": "./dist/components/Em.js",
25-
"./Heading": "./dist/components/Heading.js",
26-
"./HoverCard": "./dist/components/HoverCard.js",
27-
"./Kbd": "./dist/components/Kbd.js",
28-
"./Link": "./dist/components/Link.js",
29-
"./Progress": "./dist/components/Progress.js",
30-
"./Quote": "./dist/components/Quote.js",
31-
"./RadioGroup": "./dist/components/RadioGroup.js",
32-
"./ScrollArea": "./dist/components/ScrollArea.js",
33-
"./Separator": "./dist/components/Separator.js",
34-
"./Skeleton": "./dist/components/Skeleton.js",
35-
"./Strong": "./dist/components/Strong.js",
36-
"./Switch": "./dist/components/Switch.js",
37-
"./Table": "./dist/components/Table.js",
38-
"./Tabs": "./dist/components/Tabs.js",
39-
"./Text": "./dist/components/Text.js",
40-
"./TextArea": "./dist/components/TextArea.js",
41-
"./Theme": "./dist/components/Theme.js",
42-
"./Toggle": "./dist/components/Toggle.js",
43-
"./ToggleGroup": "./dist/components/ToggleGroup.js",
44-
"./Tooltip": "./dist/components/Tooltip.js",
45-
"./VisuallyHidden": "./dist/components/VisuallyHidden.js"
46-
},
7+
"exports": {},
478
"scripts": {
489
"test": "jest",
4910
"coverage": "jest --coverage",
@@ -57,11 +18,12 @@
5718
"generate-tokens": "tsx ./src/tokenGen/index.js",
5819
"bundle-tokens": "rollup --config rollup-tokens.config.js",
5920
"compile-components": "rollup -c rollup.config.cjs",
60-
"process-components": "mkdirp ./dist/components && cp -r ./dist/temp-cleanup/*js ./dist/components && rimraf dist/temp-cleanup",
21+
"process-components": "node scripts/process-components.cjs",
6122
"prebuild": "npm run test && npm run clean",
23+
"build:generate-exports": "node scripts/generate-exports.cjs",
6224
"build:css": "npm run generate-tokens && npm run bundle-tokens && npm run build-css",
6325
"build:components": "npm run compile-components && npm run process-components",
64-
"build:rollup": "npm run prebuild && npm run build:css && NODE_OPTIONS='--max-old-space-size=4076' npm run build:components",
26+
"build:rollup": "npm run prebuild && npm run build:css && NODE_OPTIONS='--max-old-space-size=4076' npm run build:components && npm run build:generate-exports",
6527
"compile-components:esbuild": "node build-components.cjs",
6628
"check:types": "tsc --noEmit",
6729
"build-components:esbuild": "npm run compile-components:esbuild && npm run process-components",
@@ -137,6 +99,7 @@
13799
"rimraf": "6.0.1",
138100
"rollup": "4.46.2",
139101
"rollup-plugin-banner2": "1.3.0",
102+
"rollup-plugin-dts": "^6.2.1",
140103
"rollup-plugin-postcss": "^4.0.2",
141104
"sass": "^1.77.2",
142105
"sass-loader": "16.0.4",
@@ -161,4 +124,4 @@
161124
"react": "^18.2.0",
162125
"react-dom": "^18.2.0"
163126
}
164-
}
127+
}

rollup.config.cjs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// rollup.config.cjs
21
const babel = require('@rollup/plugin-babel');
32
const resolve = require('@rollup/plugin-node-resolve');
43
const terser = require('@rollup/plugin-terser');
@@ -7,6 +6,7 @@ const alias = require('@rollup/plugin-alias');
76
const path = require('path');
87
const fs = require('fs');
98
const banner2 = require('rollup-plugin-banner2');
9+
const { dts } = require('rollup-plugin-dts');
1010

1111
// Function to dynamically get all component directories in the 'src/components' folder
1212
function getComponentDirectories() {
@@ -24,6 +24,7 @@ const components = getComponentDirectories();
2424
* Using it this way not only avoids the Javascript Heap Out of Memory error but also speeds up the build process
2525
*/
2626

27+
// Shared plugin instances
2728
const typescriptPluginInstance = typescript({ tsconfig: './tsconfig.json', sourceMap: false });
2829
const aliasPluginInstance = alias({
2930
entries: [
@@ -39,15 +40,13 @@ const terserPluginInstance = terser();
3940
const resolvePluginInstance = resolve();
4041
const bannerPluginInstance = banner2(() => '\'use client\';');
4142

42-
module.exports = components.map((component) => {
43+
// JS builds
44+
const jsBundles = components.map((component) => {
4345
const tsxFilePath = `src/components/ui/${component}/${component}.tsx`;
4446
return {
4547
input: tsxFilePath,
4648
onwarn(warning, warn) {
47-
// Suppress expected warnings
48-
if (warning.code === 'MODULE_LEVEL_DIRECTIVE') {
49-
return;
50-
}
49+
if (warning.code === 'MODULE_LEVEL_DIRECTIVE') return;
5150
warn(warning);
5251
},
5352
output: [
@@ -66,6 +65,20 @@ module.exports = components.map((component) => {
6665
bannerPluginInstance
6766
]
6867
};
69-
}
68+
});
69+
70+
// Type declarations builds
71+
const dtsBundles = components.map((component) => {
72+
const entry = `src/components/ui/${component}/${component}.tsx`;
73+
return {
74+
input: entry,
75+
output: {
76+
file: `dist/temp-cleanup/${component}.d.ts`,
77+
format: 'es'
78+
},
79+
plugins: [dts()],
80+
external: ['react', 'react-dom']
81+
};
82+
});
7083

71-
);
84+
module.exports = [...jsBundles, ...dtsBundles];

scripts/RELEASED_COMPONENTS.cjs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
const RELEASED_COMPONENTS = [
2+
// Released
3+
'Accordion',
4+
'Avatar',
5+
'AvatarGroup',
6+
'AlertDialog',
7+
'AspectRatio',
8+
'Badge',
9+
'Button',
10+
'BlockQuote',
11+
'Callout',
12+
'Card',
13+
'Code',
14+
'Dialog',
15+
'Em',
16+
'Heading',
17+
'Text',
18+
'Kbd',
19+
'Progress',
20+
'Separator',
21+
'Strong',
22+
'Switch',
23+
'Table',
24+
'Tabs',
25+
'Toggle',
26+
'ToggleGroup',
27+
'Tooltip',
28+
'VisuallyHidden',
29+
// Released but not documented officially
30+
'ScrollArea',
31+
'Theme',
32+
'Link'
33+
];
34+
35+
module.exports = RELEASED_COMPONENTS;

scripts/generate-exports.cjs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/**
2+
* Generate Exports Script for Rad UI
3+
*
4+
* WHAT THIS SCRIPT DOES:
5+
* This script automatically generates the "exports" field in package.json based on
6+
* the built components and theme files in the dist/ directory. It creates proper
7+
* import paths for both JavaScript and TypeScript users.
8+
*
9+
* WHY IT'S REQUIRED:
10+
* 1. Manual Maintenance: Without this script, we'd have to manually update package.json
11+
* exports every time we add/remove components, which is error-prone and time-consuming.
12+
*
13+
* 2. TypeScript Support: Generates proper "types" field for each component, enabling
14+
* TypeScript users to get proper type checking and IntelliSense.
15+
*
16+
* 3. Tree Shaking: Enables users to import individual components instead of the entire
17+
* library, reducing bundle sizes significantly.
18+
*
19+
* 4. Theme Exports: Ensures theme files (CSS and Tailwind presets) are properly
20+
* exported for styling support.
21+
*
22+
* 5. Consistency: Guarantees that all built components are automatically available
23+
* for import without manual configuration.
24+
*
25+
* USAGE:
26+
* This script runs automatically as part of the build process via:
27+
* npm run build:generate-exports
28+
*
29+
* OUTPUT:
30+
* Updates package.json with exports like:
31+
* {
32+
* "./Button": {
33+
* "import": "./dist/components/Button.js",
34+
* "types": "./dist/components/Button.d.ts"
35+
* },
36+
* "./themes/default.css": "./dist/themes/default.css"
37+
* }
38+
*/
39+
40+
const fs = require('fs');
41+
const path = require('path');
42+
const RELEASED_COMPONENTS = require('./RELEASED_COMPONENTS.cjs');
43+
44+
// Component exports
45+
const distPath = path.resolve(__dirname, '../dist/components');
46+
let files = [];
47+
try {
48+
files = fs.readdirSync(distPath);
49+
} catch (error) {
50+
console.warn(`Warning: ${distPath} not found. No components will be exported.`);
51+
files = [];
52+
}
53+
54+
const exportsMap = {};
55+
56+
// Add theme exports
57+
exportsMap['./themes/default.css'] = './dist/themes/default.css';
58+
exportsMap['./themes/tailwind-presets/default.js'] = './dist/themes/tailwind-presets/default.js';
59+
60+
const notReleasedComponents = [];
61+
62+
// Add component exports
63+
files.forEach(file => {
64+
const match = file.match(/^(.+)\.js$/);
65+
if (match) {
66+
const name = match[1];
67+
68+
if (!RELEASED_COMPONENTS.includes(name)) {
69+
notReleasedComponents.push(name);
70+
return;
71+
}
72+
73+
exportsMap[`./${name}`] = {
74+
import: `./dist/components/${name}.js`,
75+
types: `./dist/components/${name}.d.ts`
76+
};
77+
}
78+
});
79+
80+
if (notReleasedComponents.length > 0) {
81+
console.log(`Not released components: ${notReleasedComponents.join(', ')}`);
82+
}
83+
84+
const pkgPath = path.resolve(__dirname, '../package.json');
85+
86+
try {
87+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
88+
pkg.exports = exportsMap;
89+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
90+
console.log('✅ package.json exports updated!');
91+
} catch (error) {
92+
console.error('❌ Failed to update package.json exports:', error.message);
93+
process.exit(1);
94+
}

0 commit comments

Comments
 (0)