rn-cn-ui 1.0.3 → 1.0.5
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 +63 -9
- package/bin/cli.js +54 -6
- package/package.json +1 -1
- package/src/components/ui/button.tsx +9 -9
- package/src/components/ui/card.tsx +1 -1
- package/src/components/ui/input.tsx +1 -1
- package/src/global.css +34 -34
package/README.md
CHANGED
|
@@ -6,7 +6,54 @@ A high-quality, open-source UI library for React Native, inspired by shadcn/ui.
|
|
|
6
6
|
## Prerequisites
|
|
7
7
|
|
|
8
8
|
1. **React Native** project (Expo or CLI).
|
|
9
|
-
2. **NativeWind
|
|
9
|
+
2. **NativeWind v4** configured.
|
|
10
|
+
|
|
11
|
+
### Important: Install Dependencies
|
|
12
|
+
|
|
13
|
+
NativeWind v4 requires `react-native-reanimated`. Ensure you have installed it and its peer dependencies:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install nativewind react-native-reanimated react-native-safe-area-context react-native-svg
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Configure Babel
|
|
20
|
+
|
|
21
|
+
Add `react-native-reanimated/plugin` to your `babel.config.js`. **It must be listed last.**
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
module.exports = function(api) {
|
|
25
|
+
api.cache(true);
|
|
26
|
+
return {
|
|
27
|
+
presets: [
|
|
28
|
+
["babel-preset-expo", { jsxImportSource: "nativewind" }],
|
|
29
|
+
"nativewind/babel",
|
|
30
|
+
],
|
|
31
|
+
plugins: [
|
|
32
|
+
"react-native-reanimated/plugin",
|
|
33
|
+
],
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
*Note: If you are using Expo, use `babel-preset-expo` instead of `module:metro-react-native-babel-preset`.*
|
|
39
|
+
|
|
40
|
+
## Setup
|
|
41
|
+
|
|
42
|
+
Run the init command to set up the base styles and utilities:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npx rn-cn-ui init
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
This will create:
|
|
49
|
+
- `src/global.css` (Base styles and theme variables)
|
|
50
|
+
- `src/lib/utils.ts` (Utility for class merging)
|
|
51
|
+
|
|
52
|
+
**Important:** Import `global.css` in your root file (e.g., `App.tsx` or `app/_layout.tsx`):
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
import "./src/global.css";
|
|
56
|
+
```
|
|
10
57
|
|
|
11
58
|
## Usage
|
|
12
59
|
|
|
@@ -42,22 +89,29 @@ export default function App() {
|
|
|
42
89
|
|
|
43
90
|
You can add any of the following components:
|
|
44
91
|
|
|
92
|
+
- `accordion`
|
|
93
|
+
- `alert`
|
|
94
|
+
- `aspect-ratio`
|
|
95
|
+
- `avatar`
|
|
96
|
+
- `badge`
|
|
45
97
|
- `button`
|
|
46
|
-
- `text`
|
|
47
|
-
- `input`
|
|
48
98
|
- `card`
|
|
49
|
-
- `
|
|
50
|
-
- `
|
|
99
|
+
- `checkbox`
|
|
100
|
+
- `dialog`
|
|
101
|
+
- `input`
|
|
51
102
|
- `label`
|
|
103
|
+
- `progress`
|
|
104
|
+
- `radio-group`
|
|
105
|
+
- `select`
|
|
52
106
|
- `separator`
|
|
53
107
|
- `skeleton`
|
|
54
108
|
- `spinner`
|
|
55
109
|
- `switch`
|
|
56
|
-
- `
|
|
57
|
-
- `
|
|
110
|
+
- `tabs`
|
|
111
|
+
- `text`
|
|
58
112
|
- `textarea`
|
|
59
|
-
- `
|
|
60
|
-
- `
|
|
113
|
+
- `toggle`
|
|
114
|
+
- `toggle-group`
|
|
61
115
|
|
|
62
116
|
## Configuration
|
|
63
117
|
|
package/bin/cli.js
CHANGED
|
@@ -3,25 +3,73 @@ const fs = require('fs');
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const { execSync } = require('child_process');
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
// Change this to your actual repo URL
|
|
7
|
+
const BASE_URL = "https://raw.githubusercontent.com/KaloyanBehov/rn-cn-ui/main";
|
|
7
8
|
|
|
8
|
-
const component = process.argv[2];
|
|
9
9
|
const command = process.argv[2];
|
|
10
|
-
|
|
11
10
|
let componentName = null;
|
|
12
|
-
|
|
11
|
+
|
|
12
|
+
if (command === 'init') {
|
|
13
|
+
// Handle init command
|
|
14
|
+
} else if (command === 'add') {
|
|
13
15
|
componentName = process.argv[3];
|
|
14
16
|
} else {
|
|
17
|
+
// Fallback for older usage: npx rn-cn-ui <component>
|
|
15
18
|
componentName = command;
|
|
16
19
|
}
|
|
17
20
|
|
|
18
|
-
if (!componentName) {
|
|
19
|
-
console.error('Usage:
|
|
21
|
+
if (!componentName && command !== 'init') {
|
|
22
|
+
console.error('Usage:');
|
|
23
|
+
console.error(' npx rn-cn-ui init (Initialize project with global.css and utils)');
|
|
24
|
+
console.error(' npx rn-cn-ui add <name> (Add a component)');
|
|
20
25
|
process.exit(1);
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
async function main() {
|
|
24
29
|
try {
|
|
30
|
+
if (command === 'init') {
|
|
31
|
+
console.log('Initializing project...');
|
|
32
|
+
|
|
33
|
+
// 1. Create src/lib/utils.ts
|
|
34
|
+
const utilsDir = path.join(process.cwd(), 'src', 'lib');
|
|
35
|
+
const utilsPath = path.join(utilsDir, 'utils.ts');
|
|
36
|
+
|
|
37
|
+
if (!fs.existsSync(utilsDir)) {
|
|
38
|
+
fs.mkdirSync(utilsDir, { recursive: true });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const utilsUrl = `${BASE_URL}/src/lib/utils.ts`;
|
|
42
|
+
const utilsResponse = await fetch(utilsUrl);
|
|
43
|
+
if (utilsResponse.ok) {
|
|
44
|
+
const utilsContent = await utilsResponse.text();
|
|
45
|
+
fs.writeFileSync(utilsPath, utilsContent);
|
|
46
|
+
console.log('✓ Created src/lib/utils.ts');
|
|
47
|
+
} else {
|
|
48
|
+
console.error('Failed to download utils.ts');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// 2. Create src/global.css
|
|
52
|
+
const srcDir = path.join(process.cwd(), 'src');
|
|
53
|
+
const cssPath = path.join(srcDir, 'global.css');
|
|
54
|
+
|
|
55
|
+
if (!fs.existsSync(srcDir)) {
|
|
56
|
+
fs.mkdirSync(srcDir, { recursive: true });
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const cssUrl = `${BASE_URL}/src/global.css`;
|
|
60
|
+
const cssResponse = await fetch(cssUrl);
|
|
61
|
+
if (cssResponse.ok) {
|
|
62
|
+
const cssContent = await cssResponse.text();
|
|
63
|
+
fs.writeFileSync(cssPath, cssContent);
|
|
64
|
+
console.log('✓ Created src/global.css');
|
|
65
|
+
} else {
|
|
66
|
+
console.error('Failed to download global.css');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
console.log('\nProject initialized! Don\'t forget to import global.css in your root layout/index file.');
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
25
73
|
// 1. Fetch registry
|
|
26
74
|
console.log('Fetching registry...');
|
|
27
75
|
const registryResponse = await fetch(`${BASE_URL}/registry.json`);
|
package/package.json
CHANGED
|
@@ -4,21 +4,21 @@ import { cva, type VariantProps } from "class-variance-authority"
|
|
|
4
4
|
import { cn } from "../../lib/utils"
|
|
5
5
|
|
|
6
6
|
const buttonVariants = cva(
|
|
7
|
-
"flex-row items-center justify-center rounded-md",
|
|
7
|
+
"flex-row items-center justify-center rounded-md gap-2",
|
|
8
8
|
{
|
|
9
9
|
variants: {
|
|
10
10
|
variant: {
|
|
11
|
-
default: "bg-primary",
|
|
12
|
-
destructive: "bg-destructive",
|
|
13
|
-
outline: "border border-input bg-background",
|
|
14
|
-
secondary: "bg-secondary",
|
|
15
|
-
ghost: "
|
|
16
|
-
link: "text-primary underline-offset-4
|
|
11
|
+
default: "bg-primary shadow-sm active:opacity-90",
|
|
12
|
+
destructive: "bg-destructive shadow-sm active:opacity-90",
|
|
13
|
+
outline: "border border-input bg-background shadow-sm active:bg-accent active:text-accent-foreground",
|
|
14
|
+
secondary: "bg-secondary shadow-sm active:opacity-80",
|
|
15
|
+
ghost: "active:bg-accent active:text-accent-foreground",
|
|
16
|
+
link: "text-primary underline-offset-4 active:underline",
|
|
17
17
|
},
|
|
18
18
|
size: {
|
|
19
|
-
default: "h-
|
|
19
|
+
default: "h-11 px-4 py-2",
|
|
20
20
|
sm: "h-9 rounded-md px-3",
|
|
21
|
-
lg: "h-
|
|
21
|
+
lg: "h-12 rounded-md px-8",
|
|
22
22
|
icon: "h-10 w-10",
|
|
23
23
|
},
|
|
24
24
|
},
|
|
@@ -11,7 +11,7 @@ const Input = React.forwardRef<React.ElementRef<typeof TextInput>, InputProps>(
|
|
|
11
11
|
<TextInput
|
|
12
12
|
ref={ref}
|
|
13
13
|
className={cn(
|
|
14
|
-
"flex h-
|
|
14
|
+
"flex h-12 w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
15
15
|
className
|
|
16
16
|
)}
|
|
17
17
|
placeholderTextColor={placeholderTextColor || "hsl(var(--muted-foreground))"}
|
package/src/global.css
CHANGED
|
@@ -5,46 +5,46 @@
|
|
|
5
5
|
@layer base {
|
|
6
6
|
:root {
|
|
7
7
|
--background: 0 0% 100%;
|
|
8
|
-
--foreground:
|
|
8
|
+
--foreground: 224 71.4% 4.1%;
|
|
9
9
|
--card: 0 0% 100%;
|
|
10
|
-
--card-foreground:
|
|
10
|
+
--card-foreground: 224 71.4% 4.1%;
|
|
11
11
|
--popover: 0 0% 100%;
|
|
12
|
-
--popover-foreground:
|
|
13
|
-
--primary:
|
|
14
|
-
--primary-foreground:
|
|
15
|
-
--secondary:
|
|
16
|
-
--secondary-foreground:
|
|
17
|
-
--muted:
|
|
18
|
-
--muted-foreground:
|
|
19
|
-
--accent:
|
|
20
|
-
--accent-foreground:
|
|
12
|
+
--popover-foreground: 224 71.4% 4.1%;
|
|
13
|
+
--primary: 262.1 83.3% 57.8%;
|
|
14
|
+
--primary-foreground: 210 20% 98%;
|
|
15
|
+
--secondary: 220 14.3% 95.9%;
|
|
16
|
+
--secondary-foreground: 220.9 39.3% 11%;
|
|
17
|
+
--muted: 220 14.3% 95.9%;
|
|
18
|
+
--muted-foreground: 220 8.9% 46.1%;
|
|
19
|
+
--accent: 220 14.3% 95.9%;
|
|
20
|
+
--accent-foreground: 220.9 39.3% 11%;
|
|
21
21
|
--destructive: 0 84.2% 60.2%;
|
|
22
|
-
--destructive-foreground:
|
|
23
|
-
--border:
|
|
24
|
-
--input:
|
|
25
|
-
--ring:
|
|
26
|
-
--radius: 0.
|
|
22
|
+
--destructive-foreground: 210 20% 98%;
|
|
23
|
+
--border: 220 13% 91%;
|
|
24
|
+
--input: 220 13% 91%;
|
|
25
|
+
--ring: 262.1 83.3% 57.8%;
|
|
26
|
+
--radius: 0.75rem;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
.dark {
|
|
30
|
-
--background:
|
|
31
|
-
--foreground:
|
|
32
|
-
--card:
|
|
33
|
-
--card-foreground:
|
|
34
|
-
--popover:
|
|
35
|
-
--popover-foreground:
|
|
36
|
-
--primary:
|
|
37
|
-
--primary-foreground:
|
|
38
|
-
--secondary:
|
|
39
|
-
--secondary-foreground:
|
|
40
|
-
--muted:
|
|
41
|
-
--muted-foreground:
|
|
42
|
-
--accent:
|
|
43
|
-
--accent-foreground:
|
|
30
|
+
--background: 224 71.4% 4.1%;
|
|
31
|
+
--foreground: 210 20% 98%;
|
|
32
|
+
--card: 224 71.4% 4.1%;
|
|
33
|
+
--card-foreground: 210 20% 98%;
|
|
34
|
+
--popover: 224 71.4% 4.1%;
|
|
35
|
+
--popover-foreground: 210 20% 98%;
|
|
36
|
+
--primary: 263.4 70% 50.4%;
|
|
37
|
+
--primary-foreground: 210 20% 98%;
|
|
38
|
+
--secondary: 215 27.9% 16.9%;
|
|
39
|
+
--secondary-foreground: 210 20% 98%;
|
|
40
|
+
--muted: 215 27.9% 16.9%;
|
|
41
|
+
--muted-foreground: 217.9 10.6% 64.9%;
|
|
42
|
+
--accent: 215 27.9% 16.9%;
|
|
43
|
+
--accent-foreground: 210 20% 98%;
|
|
44
44
|
--destructive: 0 62.8% 30.6%;
|
|
45
|
-
--destructive-foreground:
|
|
46
|
-
--border:
|
|
47
|
-
--input:
|
|
48
|
-
--ring:
|
|
45
|
+
--destructive-foreground: 210 20% 98%;
|
|
46
|
+
--border: 215 27.9% 16.9%;
|
|
47
|
+
--input: 215 27.9% 16.9%;
|
|
48
|
+
--ring: 263.4 70% 50.4%;
|
|
49
49
|
}
|
|
50
50
|
}
|