@wireservers-ui/react-natives 2.0.0 → 2.0.1

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/CHANGELOG.md CHANGED
@@ -7,6 +7,19 @@ Versioning: [Semantic Versioning](https://semver.org/)
7
7
 
8
8
  ---
9
9
 
10
+ ## [2.0.1] - 2026-03-16
11
+
12
+ ### Added
13
+ - `bin/init.js` is now included in the published npm package (packaging parity with local source)
14
+
15
+ ### Fixed
16
+ - Published `@wireservers-ui/react-natives@2.0.0` artifact missed `bin/init.js`; this patch release includes it so CLI initialization helpers are available in installed package contents
17
+
18
+ ### Changed
19
+ - README now includes a release note section and direct changelog navigation guidance for npm/GitHub users
20
+
21
+ ---
22
+
10
23
  ## [2.0.0] - 2026-03-15
11
24
 
12
25
  ### Added
package/README.md CHANGED
@@ -2,13 +2,28 @@
2
2
 
3
3
  **A comprehensive React Native component library built with NativeWind and Tailwind Variants.**
4
4
 
5
- > **Note:** This project is in active development (v2.0.0). We're building out components, documentation, and tooling. Contributions and feedback are welcome!
5
+ > **Note:** This project is in active development (v2.0.1). We're building out components, documentation, and tooling. Contributions and feedback are welcome!
6
6
 
7
7
  [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
8
8
  [![npm version](https://img.shields.io/npm/v/@wireservers-ui/react-natives.svg)](https://www.npmjs.com/package/@wireservers-ui/react-natives)
9
9
 
10
10
  ---
11
11
 
12
+ ## Release Notes (v2.0.1)
13
+
14
+ ### What was updated
15
+
16
+ - Published package contents now include `bin/init.js` (packaging parity fix)
17
+ - This ensures the installed npm artifact contains the same CLI helper file expected by local package contents
18
+
19
+ ### Changelog
20
+
21
+ - Full changelog is included in the package at `CHANGELOG.md`
22
+ - GitHub: https://github.com/wireservers/wireservers-ui/blob/dev/packages/react-natives/CHANGELOG.md
23
+ - npm package page: open the `CHANGELOG.md` file from the package contents/files list
24
+
25
+ ---
26
+
12
27
  ## What is React-Natives?
13
28
 
14
29
  React-Natives is a collection of 70+ production-ready, accessible React Native components. Every component is TypeScript-first, themeable via CSS variables, and styled with NativeWind (Tailwind CSS for React Native).
@@ -44,7 +59,7 @@ Use this for the fastest first-time setup in a new Expo app.
44
59
  npx create-expo-app@latest wsui-init --template blank-typescript
45
60
  cd wsui-init
46
61
  npm install @wireservers-ui/react-natives@2.0.0
47
- npx @wireservers-ui/react-natives@2.0.0 init
62
+ npx @wireservers-ui/react-natives@2.0.1 init
48
63
  npx expo start --clear --web
49
64
  ```
50
65
 
@@ -62,7 +77,7 @@ Use this path if you want full control over every file.
62
77
  #### Step A: Install packages
63
78
 
64
79
  ```bash
65
- npm install @wireservers-ui/react-natives@2.0.0
80
+ npm install @wireservers-ui/react-natives@2.0.1
66
81
  npm install nativewind tailwindcss tailwind-variants tailwind-merge react-native-reanimated react-native-worklets react-native-svg react-native-web react-dom
67
82
  ```
68
83
 
package/bin/init.js ADDED
@@ -0,0 +1,324 @@
1
+ #!/usr/bin/env node
2
+
3
+ 'use strict';
4
+
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+ const { execSync } = require('child_process');
8
+
9
+ const cwd = process.cwd();
10
+ const force = process.argv.includes('--force');
11
+
12
+ const green = (s) => `\x1b[32m${s}\x1b[0m`;
13
+ const yellow = (s) => `\x1b[33m${s}\x1b[0m`;
14
+ const cyan = (s) => `\x1b[36m${s}\x1b[0m`;
15
+ const bold = (s) => `\x1b[1m${s}\x1b[0m`;
16
+ const dim = (s) => `\x1b[2m${s}\x1b[0m`;
17
+
18
+ function write(filename, content) {
19
+ const filepath = path.join(cwd, filename);
20
+ if (fs.existsSync(filepath) && !force) {
21
+ console.log(yellow(' skip ') + filename + dim(' (already exists — use --force to overwrite)'));
22
+ return;
23
+ }
24
+ fs.mkdirSync(path.dirname(filepath), { recursive: true });
25
+ fs.writeFileSync(filepath, content, 'utf8');
26
+ console.log(green(' create') + ' ' + filename);
27
+ }
28
+
29
+ // ─── Detect project type ──────────────────────────────────────────────────────
30
+
31
+ const hasExpoRouter = fs.existsSync(path.join(cwd, 'app'));
32
+
33
+ const tailwindContent = hasExpoRouter
34
+ ? [' "./app/**/*.{ts,tsx}"', ' "./components/**/*.{ts,tsx}"']
35
+ : [' "./App.{ts,tsx}"', ' "./components/**/*.{ts,tsx}"'];
36
+
37
+ // ─── Generated file contents ──────────────────────────────────────────────────
38
+
39
+ const TAILWIND_CONFIG = `const wirePreset = require("@wireservers-ui/react-natives/tailwind-preset");
40
+ module.exports = {
41
+ content: [
42
+ ${tailwindContent.join(',\n')},
43
+ "./node_modules/@wireservers-ui/react-natives/src/**/*.{ts,tsx}",
44
+ ],
45
+ presets: [wirePreset],
46
+ };
47
+ `;
48
+
49
+ const GLOBAL_CSS = `@tailwind base;
50
+ @tailwind components;
51
+ @tailwind utilities;
52
+
53
+ :root {
54
+ --color-primary-0: 228 228 255;
55
+ --color-primary-50: 206 204 255;
56
+ --color-primary-100: 183 180 255;
57
+ --color-primary-200: 159 155 255;
58
+ --color-primary-300: 134 128 255;
59
+ --color-primary-400: 108 99 243;
60
+ --color-primary-500: 80 70 230;
61
+ --color-primary-600: 62 53 205;
62
+ --color-primary-700: 46 38 180;
63
+ --color-primary-800: 33 26 155;
64
+ --color-primary-900: 22 17 130;
65
+ --color-primary-950: 15 10 105;
66
+
67
+ --color-secondary-0: 253 253 253;
68
+ --color-secondary-50: 243 243 243;
69
+ --color-secondary-100: 233 233 233;
70
+ --color-secondary-200: 213 213 213;
71
+ --color-secondary-300: 193 193 193;
72
+ --color-secondary-400: 163 163 163;
73
+ --color-secondary-500: 115 115 115;
74
+ --color-secondary-600: 82 82 82;
75
+ --color-secondary-700: 64 64 64;
76
+ --color-secondary-800: 38 38 38;
77
+ --color-secondary-900: 23 23 23;
78
+ --color-secondary-950: 10 10 10;
79
+
80
+ --color-tertiary-50: 255 244 236;
81
+ --color-tertiary-100: 255 225 204;
82
+ --color-tertiary-200: 255 197 153;
83
+ --color-tertiary-300: 255 168 102;
84
+ --color-tertiary-400: 255 140 51;
85
+ --color-tertiary-500: 255 111 0;
86
+ --color-tertiary-600: 219 93 0;
87
+ --color-tertiary-700: 183 76 0;
88
+ --color-tertiary-800: 146 60 0;
89
+ --color-tertiary-900: 110 44 0;
90
+ --color-tertiary-950: 73 29 0;
91
+
92
+ --color-error-0: 255 242 242;
93
+ --color-error-50: 254 226 226;
94
+ --color-error-100: 254 202 202;
95
+ --color-error-200: 252 165 165;
96
+ --color-error-300: 248 113 113;
97
+ --color-error-400: 239 68 68;
98
+ --color-error-500: 220 38 38;
99
+ --color-error-600: 185 28 28;
100
+ --color-error-700: 153 27 27;
101
+ --color-error-800: 127 29 29;
102
+ --color-error-900: 100 20 20;
103
+ --color-error-950: 69 10 10;
104
+
105
+ --color-success-0: 240 253 244;
106
+ --color-success-50: 220 252 231;
107
+ --color-success-100: 187 247 208;
108
+ --color-success-200: 134 239 172;
109
+ --color-success-300: 74 222 128;
110
+ --color-success-400: 34 197 94;
111
+ --color-success-500: 22 163 74;
112
+ --color-success-600: 21 128 61;
113
+ --color-success-700: 22 101 52;
114
+ --color-success-800: 20 83 45;
115
+ --color-success-900: 17 68 37;
116
+ --color-success-950: 5 46 22;
117
+
118
+ --color-warning-0: 255 252 240;
119
+ --color-warning-50: 254 249 195;
120
+ --color-warning-100: 254 240 138;
121
+ --color-warning-200: 253 224 71;
122
+ --color-warning-300: 250 204 21;
123
+ --color-warning-400: 234 179 8;
124
+ --color-warning-500: 202 138 4;
125
+ --color-warning-600: 161 98 7;
126
+ --color-warning-700: 133 77 14;
127
+ --color-warning-800: 113 63 18;
128
+ --color-warning-900: 90 52 18;
129
+ --color-warning-950: 66 32 6;
130
+
131
+ --color-info-0: 240 249 255;
132
+ --color-info-50: 224 242 254;
133
+ --color-info-100: 186 230 253;
134
+ --color-info-200: 125 211 252;
135
+ --color-info-300: 56 189 248;
136
+ --color-info-400: 14 165 233;
137
+ --color-info-500: 2 132 199;
138
+ --color-info-600: 3 105 161;
139
+ --color-info-700: 7 89 133;
140
+ --color-info-800: 12 74 110;
141
+ --color-info-900: 12 64 93;
142
+ --color-info-950: 8 47 73;
143
+
144
+ --color-typography-0: 255 255 255;
145
+ --color-typography-50: 245 245 245;
146
+ --color-typography-100: 229 229 229;
147
+ --color-typography-200: 212 212 212;
148
+ --color-typography-300: 163 163 163;
149
+ --color-typography-400: 140 140 140;
150
+ --color-typography-500: 115 115 115;
151
+ --color-typography-600: 82 82 82;
152
+ --color-typography-700: 64 64 64;
153
+ --color-typography-800: 38 38 38;
154
+ --color-typography-900: 23 23 23;
155
+ --color-typography-950: 10 10 10;
156
+
157
+ --color-outline-0: 255 255 255;
158
+ --color-outline-50: 245 245 245;
159
+ --color-outline-100: 229 229 229;
160
+ --color-outline-200: 212 212 212;
161
+ --color-outline-300: 163 163 163;
162
+ --color-outline-400: 140 140 140;
163
+ --color-outline-500: 115 115 115;
164
+ --color-outline-600: 82 82 82;
165
+ --color-outline-700: 64 64 64;
166
+ --color-outline-800: 38 38 38;
167
+ --color-outline-900: 23 23 23;
168
+ --color-outline-950: 10 10 10;
169
+
170
+ --color-background-0: 255 255 255;
171
+ --color-background-50: 246 246 246;
172
+ --color-background-100: 237 237 237;
173
+ --color-background-200: 219 219 219;
174
+ --color-background-300: 185 185 185;
175
+ --color-background-400: 163 163 163;
176
+ --color-background-500: 140 140 140;
177
+ --color-background-600: 115 115 115;
178
+ --color-background-700: 82 82 82;
179
+ --color-background-800: 64 64 64;
180
+ --color-background-900: 38 38 38;
181
+ --color-background-950: 23 23 23;
182
+ --color-background-error: 254 226 226;
183
+ --color-background-warning: 254 249 195;
184
+ --color-background-muted: 245 245 245;
185
+ --color-background-success: 220 252 231;
186
+ --color-background-info: 224 242 254;
187
+
188
+ --color-indicator-primary: 80 70 230;
189
+ --color-indicator-info: 2 132 199;
190
+ --color-indicator-error: 220 38 38;
191
+ }
192
+ `;
193
+
194
+ const METRO_CONFIG = `const { getDefaultConfig } = require("expo/metro-config");
195
+ const { withNativeWind } = require("nativewind/metro");
196
+ const config = getDefaultConfig(__dirname);
197
+ module.exports = withNativeWind(config, { input: "./global.css" });
198
+ `;
199
+
200
+ const BABEL_CONFIG = `module.exports = function (api) {
201
+ api.cache(true);
202
+ return {
203
+ presets: [
204
+ ["babel-preset-expo", { jsxImportSource: "nativewind" }],
205
+ "nativewind/babel",
206
+ ],
207
+ };
208
+ };
209
+ `;
210
+
211
+ const NATIVEWIND_ENV = `/// <reference types="nativewind/types" />\n`;
212
+
213
+ // ─── Metro Windows ESM patch ──────────────────────────────────────────────────
214
+ //
215
+ // Metro calls `await import(absolutePath)` with a raw Windows path (D:\...).
216
+ // Node 22+'s ESM loader requires file:// URLs on Windows, so this throws
217
+ // ERR_UNSUPPORTED_ESM_URL_SCHEME. The patch converts the path via pathToFileURL.
218
+ // It lives in .metro-patch.js and runs as a postinstall script so it survives
219
+ // future `npm install` calls that would overwrite node_modules.
220
+
221
+ const METRO_PATCH_SCRIPT = `#!/usr/bin/env node
222
+ 'use strict';
223
+ const fs = require('fs');
224
+ const path = require('path');
225
+
226
+ const target = path.join(__dirname, 'node_modules/metro-config/src/loadConfig.js');
227
+ if (!fs.existsSync(target)) process.exit(0);
228
+
229
+ const src = fs.readFileSync(target, 'utf8');
230
+ if (src.includes('pathToFileURL')) process.exit(0); // already patched
231
+
232
+ const patched = src.replace(
233
+ /await import\\(absolutePath\\)/g,
234
+ 'await import(require("url").pathToFileURL(absolutePath).href)'
235
+ );
236
+ if (patched === src) process.exit(0); // pattern not found — nothing to do
237
+
238
+ fs.writeFileSync(target, patched, 'utf8');
239
+ console.log(' patched metro-config/src/loadConfig.js (Windows ESM URL fix)');
240
+ `;
241
+
242
+ // ─── babel.config.js ─────────────────────────────────────────────────────────
243
+
244
+ function handleBabelConfig() {
245
+ const filepath = path.join(cwd, 'babel.config.js');
246
+
247
+ if (!fs.existsSync(filepath)) {
248
+ fs.writeFileSync(filepath, BABEL_CONFIG, 'utf8');
249
+ console.log(green(' create') + ' babel.config.js');
250
+ return;
251
+ }
252
+
253
+ const existing = fs.readFileSync(filepath, 'utf8');
254
+ if (existing.includes('jsxImportSource') && existing.includes('nativewind/babel')) {
255
+ console.log(green(' ok ') + ' babel.config.js');
256
+ return;
257
+ }
258
+
259
+ // create-expo-app ships a single-preset babel.config.js — overwrite it
260
+ if (/presets:\s*\[['"]babel-preset-expo['"]\]/.test(existing)) {
261
+ fs.writeFileSync(filepath, BABEL_CONFIG, 'utf8');
262
+ console.log(green(' update') + ' babel.config.js');
263
+ return;
264
+ }
265
+
266
+ // Complex existing config — show manual instructions
267
+ console.log(yellow(' manual') + ' babel.config.js — add NativeWind manually:');
268
+ console.log(dim(' presets: [["babel-preset-expo", { jsxImportSource: "nativewind" }], "nativewind/babel"]'));
269
+ }
270
+
271
+ // ─── package.json — add postinstall ──────────────────────────────────────────
272
+
273
+ function addPostinstall() {
274
+ const pkgPath = path.join(cwd, 'package.json');
275
+ if (!fs.existsSync(pkgPath)) return;
276
+
277
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
278
+ pkg.scripts = pkg.scripts || {};
279
+
280
+ const existing = pkg.scripts.postinstall || '';
281
+ if (existing.includes('.metro-patch.js')) {
282
+ console.log(green(' ok ') + ' package.json postinstall');
283
+ return;
284
+ }
285
+
286
+ pkg.scripts.postinstall = existing
287
+ ? `${existing} && node .metro-patch.js`
288
+ : 'node .metro-patch.js';
289
+
290
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf8');
291
+ console.log(green(' update') + ' package.json postinstall');
292
+ }
293
+
294
+ // ─── Install nativewind + tailwindcss ────────────────────────────────────────
295
+ //
296
+ // Runs npm install which also triggers postinstall, applying the Metro patch.
297
+
298
+ function installDeps() {
299
+ console.log(cyan('\n Installing nativewind and tailwindcss...\n'));
300
+ try {
301
+ execSync('npm install nativewind@4 tailwindcss@3', { cwd, stdio: 'inherit' });
302
+ } catch {
303
+ console.log(yellow('\n warn ') + ' npm install failed — run it manually to finish setup');
304
+ }
305
+ }
306
+
307
+ // ─── Run ─────────────────────────────────────────────────────────────────────
308
+
309
+ console.log(bold('\n@wireservers-ui/react-natives init\n'));
310
+
311
+ if (hasExpoRouter) {
312
+ console.log(cyan(' Detected Expo Router') + '\n');
313
+ }
314
+
315
+ write('tailwind.config.js', TAILWIND_CONFIG);
316
+ write('global.css', GLOBAL_CSS);
317
+ write('metro.config.js', METRO_CONFIG);
318
+ handleBabelConfig();
319
+ write('nativewind-env.d.ts', NATIVEWIND_ENV);
320
+ write('.metro-patch.js', METRO_PATCH_SCRIPT);
321
+ addPostinstall();
322
+ installDeps();
323
+
324
+ console.log('\n' + bold('Done.') + ' Run ' + cyan('npx expo start --clear') + ' to get started.\n');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wireservers-ui/react-natives",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "A comprehensive React Native component library built with NativeWind and Tailwind Variants",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",