@wireservers-ui/react-natives 2.0.1 → 2.0.2-rc.0

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.
Files changed (404) hide show
  1. package/CHANGELOG.md +87 -71
  2. package/LICENSE +21 -21
  3. package/README.md +642 -613
  4. package/bin/cli.js +83 -5
  5. package/bin/init.js +470 -324
  6. package/package.json +1 -1
  7. package/src/accordion/accordion-content.tsx +30 -30
  8. package/src/accordion/accordion-icon.tsx +54 -54
  9. package/src/accordion/accordion-item.tsx +37 -37
  10. package/src/accordion/accordion-title-text.tsx +24 -24
  11. package/src/accordion/accordion-trigger.tsx +38 -38
  12. package/src/accordion/accordion.tsx +91 -91
  13. package/src/accordion/index.ts +24 -24
  14. package/src/accordion/styles.ts +74 -74
  15. package/src/accordion/types.ts +56 -56
  16. package/src/actionsheet/actionsheet-backdrop.tsx +23 -23
  17. package/src/actionsheet/actionsheet-content.tsx +19 -19
  18. package/src/actionsheet/actionsheet-drag-indicator-wrapper.tsx +19 -19
  19. package/src/actionsheet/actionsheet-drag-indicator.tsx +19 -19
  20. package/src/actionsheet/actionsheet-item-text.tsx +19 -19
  21. package/src/actionsheet/actionsheet-item.tsx +20 -20
  22. package/src/actionsheet/actionsheet-scroll-view.tsx +12 -12
  23. package/src/actionsheet/actionsheet.tsx +45 -45
  24. package/src/actionsheet/index.ts +20 -20
  25. package/src/actionsheet/styles.ts +25 -25
  26. package/src/actionsheet/types.ts +49 -49
  27. package/src/alert/alert-body.tsx +19 -19
  28. package/src/alert/alert-close-button.tsx +23 -23
  29. package/src/alert/alert-icon.tsx +40 -40
  30. package/src/alert/alert-text.tsx +22 -22
  31. package/src/alert/alert.tsx +33 -33
  32. package/src/alert/index.ts +15 -15
  33. package/src/alert/styles.ts +112 -112
  34. package/src/alert/types.ts +36 -36
  35. package/src/alert-dialog/alert-dialog.tsx +54 -54
  36. package/src/alert-dialog/index.ts +2 -2
  37. package/src/alert-dialog/styles.ts +40 -40
  38. package/src/alert-dialog/types.ts +40 -40
  39. package/src/aspect-ratio/aspect-ratio.tsx +20 -20
  40. package/src/aspect-ratio/index.ts +2 -2
  41. package/src/aspect-ratio/styles.ts +6 -6
  42. package/src/aspect-ratio/types.ts +7 -7
  43. package/src/avatar/avatar-badge.tsx +22 -22
  44. package/src/avatar/avatar-fallback-text.tsx +33 -33
  45. package/src/avatar/avatar-group.tsx +53 -53
  46. package/src/avatar/avatar-image.tsx +21 -21
  47. package/src/avatar/avatar.tsx +27 -27
  48. package/src/avatar/index.ts +14 -14
  49. package/src/avatar/styles.ts +94 -94
  50. package/src/avatar/types.ts +35 -35
  51. package/src/badge/badge-icon.tsx +20 -20
  52. package/src/badge/badge-text.tsx +24 -24
  53. package/src/badge/badge.tsx +39 -39
  54. package/src/badge/index.ts +11 -11
  55. package/src/badge/styles.ts +175 -175
  56. package/src/badge/types.ts +37 -37
  57. package/src/blockquote/blockquote.tsx +21 -21
  58. package/src/blockquote/index.ts +2 -2
  59. package/src/blockquote/styles.ts +11 -11
  60. package/src/blockquote/types.ts +6 -6
  61. package/src/box/box.tsx +19 -19
  62. package/src/box/index.ts +2 -2
  63. package/src/box/styles.ts +6 -6
  64. package/src/box/types.ts +6 -6
  65. package/src/breadcrumb/breadcrumb-item.tsx +20 -20
  66. package/src/breadcrumb/breadcrumb-link.tsx +20 -20
  67. package/src/breadcrumb/breadcrumb-text.tsx +19 -19
  68. package/src/breadcrumb/breadcrumb.tsx +43 -43
  69. package/src/breadcrumb/index.ts +12 -12
  70. package/src/breadcrumb/styles.ts +36 -36
  71. package/src/breadcrumb/types.ts +33 -33
  72. package/src/button/button-group.tsx +35 -35
  73. package/src/button/button-icon.tsx +37 -37
  74. package/src/button/button-spinner.tsx +12 -12
  75. package/src/button/button-text.tsx +27 -27
  76. package/src/button/button.tsx +42 -42
  77. package/src/button/index.ts +19 -19
  78. package/src/button/styles.ts +250 -250
  79. package/src/button/types.ts +67 -67
  80. package/src/calendar/calendar-day-cell.tsx +67 -67
  81. package/src/calendar/calendar-day-view.tsx +66 -66
  82. package/src/calendar/calendar-event.tsx +59 -59
  83. package/src/calendar/calendar-header.tsx +60 -60
  84. package/src/calendar/calendar-horizontal-view.tsx +372 -372
  85. package/src/calendar/calendar-legend.tsx +41 -41
  86. package/src/calendar/calendar-month-view.tsx +47 -47
  87. package/src/calendar/calendar-vertical-view.tsx +395 -395
  88. package/src/calendar/calendar-view-switcher.tsx +65 -65
  89. package/src/calendar/calendar-week-view.tsx +52 -52
  90. package/src/calendar/calendar.tsx +74 -74
  91. package/src/calendar/index.ts +27 -27
  92. package/src/calendar/styles.ts +367 -367
  93. package/src/calendar/types.ts +101 -101
  94. package/src/calendar/use-calendar.ts +170 -170
  95. package/src/calendar/utils.ts +278 -278
  96. package/src/card/card-body.tsx +22 -22
  97. package/src/card/card-footer.tsx +19 -19
  98. package/src/card/card-header.tsx +22 -22
  99. package/src/card/card.tsx +27 -27
  100. package/src/card/index.ts +13 -13
  101. package/src/card/styles.ts +54 -54
  102. package/src/card/types.ts +31 -31
  103. package/src/carousel/carousel.tsx +436 -436
  104. package/src/carousel/index.ts +2 -2
  105. package/src/carousel/styles.ts +21 -21
  106. package/src/carousel/types.ts +41 -41
  107. package/src/center/center.tsx +19 -19
  108. package/src/center/index.ts +2 -2
  109. package/src/center/styles.ts +6 -6
  110. package/src/center/types.ts +6 -6
  111. package/src/checkbox/checkbox-group.tsx +63 -63
  112. package/src/checkbox/checkbox-icon.tsx +35 -35
  113. package/src/checkbox/checkbox-indicator.tsx +30 -30
  114. package/src/checkbox/checkbox-label.tsx +24 -24
  115. package/src/checkbox/checkbox.tsx +86 -86
  116. package/src/checkbox/index.ts +14 -14
  117. package/src/checkbox/styles.ts +69 -69
  118. package/src/checkbox/types.ts +55 -55
  119. package/src/circular-progress/circular-progress.tsx +82 -82
  120. package/src/circular-progress/index.ts +2 -2
  121. package/src/circular-progress/styles.ts +31 -31
  122. package/src/circular-progress/types.ts +18 -18
  123. package/src/code/code.tsx +36 -36
  124. package/src/code/index.ts +2 -2
  125. package/src/code/styles.ts +25 -25
  126. package/src/code/types.ts +13 -13
  127. package/src/collapsible/collapsible.tsx +58 -58
  128. package/src/collapsible/index.ts +2 -2
  129. package/src/collapsible/styles.ts +5 -5
  130. package/src/collapsible/types.ts +21 -21
  131. package/src/color-picker/color-picker-box.tsx +115 -115
  132. package/src/color-picker/color-picker-slider.tsx +98 -98
  133. package/src/color-picker/color-picker.tsx +162 -162
  134. package/src/color-picker/color-utils.ts +215 -215
  135. package/src/color-picker/index.ts +34 -34
  136. package/src/color-picker/styles.ts +32 -32
  137. package/src/color-picker/types.ts +49 -49
  138. package/src/color-picker/use-pointer-drag.ts +80 -80
  139. package/src/container/container.tsx +19 -19
  140. package/src/container/index.ts +2 -2
  141. package/src/container/styles.ts +21 -21
  142. package/src/container/types.ts +10 -10
  143. package/src/date-picker/date-picker.tsx +136 -136
  144. package/src/date-picker/index.ts +15 -15
  145. package/src/date-picker/styles.ts +18 -18
  146. package/src/date-picker/types.ts +33 -33
  147. package/src/divider/divider.tsx +21 -21
  148. package/src/divider/index.ts +2 -2
  149. package/src/divider/styles.ts +14 -14
  150. package/src/divider/types.ts +7 -7
  151. package/src/drawer/drawer-backdrop.tsx +23 -23
  152. package/src/drawer/drawer-body.tsx +19 -19
  153. package/src/drawer/drawer-close-button.tsx +29 -29
  154. package/src/drawer/drawer-content.tsx +142 -142
  155. package/src/drawer/drawer-footer.tsx +19 -19
  156. package/src/drawer/drawer-header.tsx +19 -19
  157. package/src/drawer/drawer.tsx +54 -54
  158. package/src/drawer/index.ts +22 -22
  159. package/src/drawer/styles.ts +36 -36
  160. package/src/drawer/types.ts +62 -62
  161. package/src/empty/empty.tsx +53 -53
  162. package/src/empty/index.ts +2 -2
  163. package/src/empty/styles.ts +26 -26
  164. package/src/empty/types.ts +22 -22
  165. package/src/fab/fab-icon.tsx +20 -20
  166. package/src/fab/fab-label.tsx +22 -22
  167. package/src/fab/fab.tsx +45 -45
  168. package/src/fab/index.ts +11 -11
  169. package/src/fab/styles.ts +57 -57
  170. package/src/fab/types.ts +33 -33
  171. package/src/form-control/form-control-error-icon.tsx +25 -25
  172. package/src/form-control/form-control-error-message.tsx +40 -40
  173. package/src/form-control/form-control-helper-text.tsx +25 -25
  174. package/src/form-control/form-control-label-text.tsx +25 -25
  175. package/src/form-control/form-control-label.tsx +36 -36
  176. package/src/form-control/form-control.tsx +46 -46
  177. package/src/form-control/index.ts +20 -20
  178. package/src/form-control/styles.ts +105 -105
  179. package/src/form-control/types.ts +45 -45
  180. package/src/heading/heading.tsx +21 -21
  181. package/src/heading/index.ts +2 -2
  182. package/src/heading/styles.ts +24 -24
  183. package/src/heading/types.ts +19 -19
  184. package/src/icon/icon.tsx +21 -21
  185. package/src/icon/index.ts +2 -2
  186. package/src/icon/styles.ts +18 -18
  187. package/src/icon/types.ts +8 -8
  188. package/src/icon-button/icon-button.tsx +23 -23
  189. package/src/icon-button/index.ts +2 -2
  190. package/src/icon-button/styles.ts +78 -78
  191. package/src/icon-button/types.ts +15 -15
  192. package/src/image/image.tsx +20 -20
  193. package/src/image/index.ts +2 -2
  194. package/src/image/styles.ts +28 -28
  195. package/src/image/types.ts +11 -11
  196. package/src/index.ts +1039 -1039
  197. package/src/input/index.ts +13 -13
  198. package/src/input/input-field.tsx +35 -35
  199. package/src/input/input-icon.tsx +25 -25
  200. package/src/input/input-slot.tsx +24 -24
  201. package/src/input/input.tsx +73 -73
  202. package/src/input/styles.ts +90 -90
  203. package/src/input/types.ts +39 -39
  204. package/src/kbd/index.ts +2 -2
  205. package/src/kbd/kbd.tsx +21 -21
  206. package/src/kbd/styles.ts +11 -11
  207. package/src/kbd/types.ts +7 -7
  208. package/src/link/index.ts +4 -4
  209. package/src/link/link-text.tsx +19 -19
  210. package/src/link/link.tsx +31 -31
  211. package/src/link/styles.ts +19 -19
  212. package/src/link/types.ts +13 -13
  213. package/src/list/index.ts +2 -2
  214. package/src/list/list.tsx +55 -55
  215. package/src/list/styles.ts +8 -8
  216. package/src/list/types.ts +17 -17
  217. package/src/menu/index.ts +2 -2
  218. package/src/menu/menu.tsx +99 -99
  219. package/src/menu/styles.ts +14 -14
  220. package/src/menu/types.ts +30 -30
  221. package/src/modal/index.ts +18 -18
  222. package/src/modal/modal-backdrop.tsx +23 -23
  223. package/src/modal/modal-body.tsx +19 -19
  224. package/src/modal/modal-close-button.tsx +29 -29
  225. package/src/modal/modal-content.tsx +22 -22
  226. package/src/modal/modal-footer.tsx +19 -19
  227. package/src/modal/modal-header.tsx +19 -19
  228. package/src/modal/modal.tsx +50 -50
  229. package/src/modal/styles.ts +37 -37
  230. package/src/modal/types.ts +49 -49
  231. package/src/nativewind-env.d.ts +1 -1
  232. package/src/number-input/index.ts +18 -18
  233. package/src/number-input/number-input.tsx +161 -161
  234. package/src/number-input/styles.ts +35 -35
  235. package/src/number-input/types.ts +44 -44
  236. package/src/overlay/index.ts +2 -2
  237. package/src/overlay/overlay.tsx +21 -21
  238. package/src/overlay/styles.ts +6 -6
  239. package/src/overlay/types.ts +7 -7
  240. package/src/pagination/index.ts +2 -2
  241. package/src/pagination/pagination.tsx +58 -58
  242. package/src/pagination/styles.ts +27 -27
  243. package/src/pagination/types.ts +19 -19
  244. package/src/password-input/index.ts +14 -14
  245. package/src/password-input/password-input.tsx +79 -79
  246. package/src/password-input/styles.ts +25 -25
  247. package/src/password-input/types.ts +24 -24
  248. package/src/pin-input/index.ts +12 -12
  249. package/src/pin-input/pin-input.tsx +96 -96
  250. package/src/pin-input/styles.ts +16 -16
  251. package/src/pin-input/types.ts +26 -26
  252. package/src/popover/index.ts +2 -2
  253. package/src/popover/popover.tsx +98 -98
  254. package/src/popover/styles.ts +31 -31
  255. package/src/popover/types.ts +46 -46
  256. package/src/portal/index.ts +2 -2
  257. package/src/portal/portal.tsx +8 -8
  258. package/src/portal/styles.ts +2 -2
  259. package/src/portal/types.ts +3 -3
  260. package/src/pressable/index.ts +2 -2
  261. package/src/pressable/pressable.tsx +20 -20
  262. package/src/pressable/styles.ts +10 -10
  263. package/src/pressable/types.ts +6 -6
  264. package/src/progress/index.ts +9 -9
  265. package/src/progress/progress-filled-track.tsx +26 -26
  266. package/src/progress/progress.tsx +52 -52
  267. package/src/progress/styles.ts +34 -34
  268. package/src/progress/types.ts +28 -28
  269. package/src/radio/index.ts +14 -14
  270. package/src/radio/radio-group.tsx +61 -61
  271. package/src/radio/radio-icon.tsx +24 -24
  272. package/src/radio/radio-indicator.tsx +30 -30
  273. package/src/radio/radio-label.tsx +24 -24
  274. package/src/radio/radio.tsx +68 -68
  275. package/src/radio/styles.ts +69 -69
  276. package/src/radio/types.ts +51 -51
  277. package/src/rating/index.ts +7 -7
  278. package/src/rating/rating.tsx +93 -93
  279. package/src/rating/styles.ts +13 -13
  280. package/src/rating/types.ts +29 -29
  281. package/src/search-input/index.ts +16 -16
  282. package/src/search-input/search-input.tsx +119 -119
  283. package/src/search-input/styles.ts +28 -28
  284. package/src/search-input/types.ts +31 -31
  285. package/src/segmented-control/index.ts +2 -2
  286. package/src/segmented-control/segmented-control.tsx +34 -34
  287. package/src/segmented-control/styles.ts +22 -22
  288. package/src/segmented-control/types.ts +22 -22
  289. package/src/select/index.ts +28 -28
  290. package/src/select/select-backdrop.tsx +25 -25
  291. package/src/select/select-content.tsx +49 -49
  292. package/src/select/select-drag-indicator.tsx +19 -19
  293. package/src/select/select-icon.tsx +25 -25
  294. package/src/select/select-input.tsx +32 -32
  295. package/src/select/select-item-text.tsx +30 -30
  296. package/src/select/select-item.tsx +72 -72
  297. package/src/select/select-portal.tsx +22 -22
  298. package/src/select/select-scroll-view.tsx +22 -22
  299. package/src/select/select-trigger.tsx +64 -64
  300. package/src/select/select.tsx +101 -101
  301. package/src/select/styles.ts +114 -114
  302. package/src/select/types.ts +92 -92
  303. package/src/skeleton/index.ts +2 -2
  304. package/src/skeleton/skeleton.tsx +29 -29
  305. package/src/skeleton/styles.ts +14 -14
  306. package/src/skeleton/types.ts +12 -12
  307. package/src/slider/index.ts +12 -12
  308. package/src/slider/slider-filled-track.tsx +31 -31
  309. package/src/slider/slider-thumb.tsx +52 -52
  310. package/src/slider/slider-track.tsx +154 -154
  311. package/src/slider/slider.tsx +193 -193
  312. package/src/slider/styles.ts +71 -71
  313. package/src/slider/types.ts +47 -47
  314. package/src/snackbar/index.ts +2 -2
  315. package/src/snackbar/snackbar.tsx +39 -39
  316. package/src/snackbar/styles.ts +29 -29
  317. package/src/snackbar/types.ts +21 -21
  318. package/src/spinner/index.ts +2 -2
  319. package/src/spinner/spinner.tsx +29 -29
  320. package/src/spinner/styles.ts +15 -15
  321. package/src/spinner/types.ts +10 -10
  322. package/src/stack/index.ts +2 -2
  323. package/src/stack/stack.tsx +49 -49
  324. package/src/stack/styles.ts +25 -25
  325. package/src/stack/types.ts +15 -15
  326. package/src/stat/index.ts +2 -2
  327. package/src/stat/stat.tsx +48 -48
  328. package/src/stat/styles.ts +34 -34
  329. package/src/stat/types.ts +24 -24
  330. package/src/stepper/index.ts +2 -2
  331. package/src/stepper/stepper.tsx +95 -95
  332. package/src/stepper/styles.ts +49 -49
  333. package/src/stepper/types.ts +20 -20
  334. package/src/switch/index.ts +2 -2
  335. package/src/switch/styles.ts +24 -24
  336. package/src/switch/switch.tsx +67 -67
  337. package/src/switch/types.ts +23 -23
  338. package/src/table/index.ts +2 -2
  339. package/src/table/styles.ts +12 -12
  340. package/src/table/table.tsx +52 -52
  341. package/src/table/types.ts +10 -10
  342. package/src/tabs/index.ts +18 -18
  343. package/src/tabs/styles.ts +113 -113
  344. package/src/tabs/tab-list.tsx +29 -29
  345. package/src/tabs/tab-panel.tsx +29 -29
  346. package/src/tabs/tab-panels.tsx +21 -21
  347. package/src/tabs/tab-text.tsx +26 -26
  348. package/src/tabs/tab.tsx +56 -56
  349. package/src/tabs/tabs.tsx +71 -71
  350. package/src/tabs/types.ts +53 -53
  351. package/src/tag/index.ts +14 -14
  352. package/src/tag/styles.ts +115 -115
  353. package/src/tag/tag-close-button.tsx +26 -26
  354. package/src/tag/tag-icon.tsx +20 -20
  355. package/src/tag/tag-text.tsx +22 -22
  356. package/src/tag/tag.tsx +40 -40
  357. package/src/tag/types.ts +33 -33
  358. package/src/tags-input/index.ts +18 -18
  359. package/src/tags-input/styles.ts +29 -29
  360. package/src/tags-input/tags-input.tsx +149 -149
  361. package/src/tags-input/types.ts +37 -37
  362. package/src/text/index.ts +2 -2
  363. package/src/text/styles.ts +54 -54
  364. package/src/text/text.tsx +51 -51
  365. package/src/text/types.ts +36 -36
  366. package/src/textarea/index.ts +2 -2
  367. package/src/textarea/styles.ts +37 -37
  368. package/src/textarea/textarea.tsx +68 -68
  369. package/src/textarea/types.ts +14 -14
  370. package/src/timeline/index.ts +2 -2
  371. package/src/timeline/styles.ts +57 -57
  372. package/src/timeline/timeline.tsx +52 -52
  373. package/src/timeline/types.ts +30 -30
  374. package/src/toast/index.ts +17 -17
  375. package/src/toast/styles.ts +118 -118
  376. package/src/toast/toast-description.tsx +22 -22
  377. package/src/toast/toast-provider.tsx +136 -136
  378. package/src/toast/toast-title.tsx +22 -22
  379. package/src/toast/toast.tsx +43 -43
  380. package/src/toast/types.ts +50 -50
  381. package/src/toast/use-toast.ts +7 -7
  382. package/src/toggle/index.ts +2 -2
  383. package/src/toggle/styles.ts +30 -30
  384. package/src/toggle/toggle.tsx +25 -25
  385. package/src/toggle/types.ts +15 -15
  386. package/src/toggle-group/index.ts +2 -2
  387. package/src/toggle-group/styles.ts +35 -35
  388. package/src/toggle-group/toggle-group.tsx +60 -60
  389. package/src/toggle-group/types.ts +29 -29
  390. package/src/tooltip/index.ts +11 -11
  391. package/src/tooltip/styles.ts +9 -9
  392. package/src/tooltip/tooltip-content.tsx +19 -19
  393. package/src/tooltip/tooltip-text.tsx +19 -19
  394. package/src/tooltip/tooltip.tsx +116 -116
  395. package/src/tooltip/types.ts +35 -35
  396. package/src/utils/brand.ts +5 -5
  397. package/src/utils/create-context.ts +17 -17
  398. package/src/utils/index.ts +8 -8
  399. package/src/utils/types.ts +20 -20
  400. package/src/visually-hidden/index.ts +2 -2
  401. package/src/visually-hidden/styles.ts +6 -6
  402. package/src/visually-hidden/types.ts +6 -6
  403. package/src/visually-hidden/visually-hidden.tsx +22 -22
  404. package/tailwind-preset.js +212 -203
package/bin/init.js CHANGED
@@ -1,324 +1,470 @@
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');
1
+ #!/usr/bin/env node
2
+ /* eslint-env node */
3
+ /* global require, process, console */
4
+
5
+ "use strict";
6
+
7
+ const fs = require("fs");
8
+ const path = require("path");
9
+ const { execSync } = require("child_process");
10
+
11
+ const cwd = process.cwd();
12
+ const force = process.argv.includes("--force");
13
+
14
+ const green = (s) => `\x1b[32m${s}\x1b[0m`;
15
+ const yellow = (s) => `\x1b[33m${s}\x1b[0m`;
16
+ const cyan = (s) => `\x1b[36m${s}\x1b[0m`;
17
+ const bold = (s) => `\x1b[1m${s}\x1b[0m`;
18
+ const dim = (s) => `\x1b[2m${s}\x1b[0m`;
19
+
20
+ function write(filename, content) {
21
+ const filepath = path.join(cwd, filename);
22
+ if (fs.existsSync(filepath) && !force) {
23
+ console.log(
24
+ yellow(" skip ") +
25
+ filename +
26
+ dim(" (already exists use --force to overwrite)"),
27
+ );
28
+ return;
29
+ }
30
+ fs.mkdirSync(path.dirname(filepath), { recursive: true });
31
+ fs.writeFileSync(filepath, content, "utf8");
32
+ console.log(green(" create") + " " + filename);
33
+ }
34
+
35
+ function writeStarter(filename, content) {
36
+ const filepath = path.join(cwd, filename);
37
+ if (!fs.existsSync(filepath) || force) {
38
+ fs.mkdirSync(path.dirname(filepath), { recursive: true });
39
+ fs.writeFileSync(filepath, content, "utf8");
40
+ console.log(green(" create") + " " + filename);
41
+ return;
42
+ }
43
+
44
+ const existing = fs.readFileSync(filepath, "utf8");
45
+ if (looksLikeDefaultExpoStarter(existing)) {
46
+ fs.writeFileSync(filepath, content, "utf8");
47
+ console.log(green(" update") + " " + filename);
48
+ return;
49
+ }
50
+
51
+ console.log(
52
+ yellow(" skip ") +
53
+ filename +
54
+ dim(" (custom content detected — use --force to overwrite)"),
55
+ );
56
+ }
57
+
58
+ function looksLikeDefaultExpoStarter(source) {
59
+ return (
60
+ source.includes("Open up App.tsx") ||
61
+ source.includes("Edit App.tsx") ||
62
+ source.includes("StatusBar") ||
63
+ source.includes("ParallaxScrollView") ||
64
+ source.includes("HelloWave")
65
+ );
66
+ }
67
+
68
+ // ─── Detect project type ──────────────────────────────────────────────────────
69
+
70
+ const hasExpoRouter = fs.existsSync(path.join(cwd, "app"));
71
+
72
+ const tailwindContent = hasExpoRouter
73
+ ? [' "./app/**/*.{ts,tsx}"', ' "./components/**/*.{ts,tsx}"']
74
+ : [' "./App.{ts,tsx}"', ' "./components/**/*.{ts,tsx}"'];
75
+
76
+ // ─── Generated file contents ──────────────────────────────────────────────────
77
+
78
+ const TAILWIND_CONFIG = `const wirePreset = require("@wireservers-ui/react-natives/tailwind-preset");
79
+ module.exports = {
80
+ content: [
81
+ ${tailwindContent.join(",\n")},
82
+ "./node_modules/@wireservers-ui/react-natives/src/**/*.{ts,tsx}",
83
+ ],
84
+ presets: [wirePreset],
85
+ };
86
+ `;
87
+
88
+ const GLOBAL_CSS = `@tailwind base;
89
+ @tailwind components;
90
+ @tailwind utilities;
91
+
92
+ :root {
93
+ --color-primary-0: 228 228 255;
94
+ --color-primary-50: 206 204 255;
95
+ --color-primary-100: 183 180 255;
96
+ --color-primary-200: 159 155 255;
97
+ --color-primary-300: 134 128 255;
98
+ --color-primary-400: 108 99 243;
99
+ --color-primary-500: 80 70 230;
100
+ --color-primary-600: 62 53 205;
101
+ --color-primary-700: 46 38 180;
102
+ --color-primary-800: 33 26 155;
103
+ --color-primary-900: 22 17 130;
104
+ --color-primary-950: 15 10 105;
105
+
106
+ --color-secondary-0: 253 253 253;
107
+ --color-secondary-50: 243 243 243;
108
+ --color-secondary-100: 233 233 233;
109
+ --color-secondary-200: 213 213 213;
110
+ --color-secondary-300: 193 193 193;
111
+ --color-secondary-400: 163 163 163;
112
+ --color-secondary-500: 115 115 115;
113
+ --color-secondary-600: 82 82 82;
114
+ --color-secondary-700: 64 64 64;
115
+ --color-secondary-800: 38 38 38;
116
+ --color-secondary-900: 23 23 23;
117
+ --color-secondary-950: 10 10 10;
118
+
119
+ --color-tertiary-50: 255 244 236;
120
+ --color-tertiary-100: 255 225 204;
121
+ --color-tertiary-200: 255 197 153;
122
+ --color-tertiary-300: 255 168 102;
123
+ --color-tertiary-400: 255 140 51;
124
+ --color-tertiary-500: 255 111 0;
125
+ --color-tertiary-600: 219 93 0;
126
+ --color-tertiary-700: 183 76 0;
127
+ --color-tertiary-800: 146 60 0;
128
+ --color-tertiary-900: 110 44 0;
129
+ --color-tertiary-950: 73 29 0;
130
+
131
+ --color-error-0: 255 242 242;
132
+ --color-error-50: 254 226 226;
133
+ --color-error-100: 254 202 202;
134
+ --color-error-200: 252 165 165;
135
+ --color-error-300: 248 113 113;
136
+ --color-error-400: 239 68 68;
137
+ --color-error-500: 220 38 38;
138
+ --color-error-600: 185 28 28;
139
+ --color-error-700: 153 27 27;
140
+ --color-error-800: 127 29 29;
141
+ --color-error-900: 100 20 20;
142
+ --color-error-950: 69 10 10;
143
+
144
+ --color-success-0: 240 253 244;
145
+ --color-success-50: 220 252 231;
146
+ --color-success-100: 187 247 208;
147
+ --color-success-200: 134 239 172;
148
+ --color-success-300: 74 222 128;
149
+ --color-success-400: 34 197 94;
150
+ --color-success-500: 22 163 74;
151
+ --color-success-600: 21 128 61;
152
+ --color-success-700: 22 101 52;
153
+ --color-success-800: 20 83 45;
154
+ --color-success-900: 17 68 37;
155
+ --color-success-950: 5 46 22;
156
+
157
+ --color-warning-0: 255 252 240;
158
+ --color-warning-50: 254 249 195;
159
+ --color-warning-100: 254 240 138;
160
+ --color-warning-200: 253 224 71;
161
+ --color-warning-300: 250 204 21;
162
+ --color-warning-400: 234 179 8;
163
+ --color-warning-500: 202 138 4;
164
+ --color-warning-600: 161 98 7;
165
+ --color-warning-700: 133 77 14;
166
+ --color-warning-800: 113 63 18;
167
+ --color-warning-900: 90 52 18;
168
+ --color-warning-950: 66 32 6;
169
+
170
+ --color-info-0: 240 249 255;
171
+ --color-info-50: 224 242 254;
172
+ --color-info-100: 186 230 253;
173
+ --color-info-200: 125 211 252;
174
+ --color-info-300: 56 189 248;
175
+ --color-info-400: 14 165 233;
176
+ --color-info-500: 2 132 199;
177
+ --color-info-600: 3 105 161;
178
+ --color-info-700: 7 89 133;
179
+ --color-info-800: 12 74 110;
180
+ --color-info-900: 12 64 93;
181
+ --color-info-950: 8 47 73;
182
+
183
+ --color-typography-0: 255 255 255;
184
+ --color-typography-50: 245 245 245;
185
+ --color-typography-100: 229 229 229;
186
+ --color-typography-200: 212 212 212;
187
+ --color-typography-300: 163 163 163;
188
+ --color-typography-400: 140 140 140;
189
+ --color-typography-500: 115 115 115;
190
+ --color-typography-600: 82 82 82;
191
+ --color-typography-700: 64 64 64;
192
+ --color-typography-800: 38 38 38;
193
+ --color-typography-900: 23 23 23;
194
+ --color-typography-950: 10 10 10;
195
+
196
+ --color-outline-0: 255 255 255;
197
+ --color-outline-50: 245 245 245;
198
+ --color-outline-100: 229 229 229;
199
+ --color-outline-200: 212 212 212;
200
+ --color-outline-300: 163 163 163;
201
+ --color-outline-400: 140 140 140;
202
+ --color-outline-500: 115 115 115;
203
+ --color-outline-600: 82 82 82;
204
+ --color-outline-700: 64 64 64;
205
+ --color-outline-800: 38 38 38;
206
+ --color-outline-900: 23 23 23;
207
+ --color-outline-950: 10 10 10;
208
+
209
+ --color-background-0: 255 255 255;
210
+ --color-background-50: 246 246 246;
211
+ --color-background-100: 237 237 237;
212
+ --color-background-200: 219 219 219;
213
+ --color-background-300: 185 185 185;
214
+ --color-background-400: 163 163 163;
215
+ --color-background-500: 140 140 140;
216
+ --color-background-600: 115 115 115;
217
+ --color-background-700: 82 82 82;
218
+ --color-background-800: 64 64 64;
219
+ --color-background-900: 38 38 38;
220
+ --color-background-950: 23 23 23;
221
+ --color-background-error: 254 226 226;
222
+ --color-background-warning: 254 249 195;
223
+ --color-background-muted: 245 245 245;
224
+ --color-background-success: 220 252 231;
225
+ --color-background-info: 224 242 254;
226
+
227
+ --color-indicator-primary: 80 70 230;
228
+ --color-indicator-info: 2 132 199;
229
+ --color-indicator-error: 220 38 38;
230
+ }
231
+ `;
232
+
233
+ const METRO_CONFIG = `/* eslint-env node */
234
+ const path = require("path");
235
+ const { getDefaultConfig } = require("expo/metro-config");
236
+ const { withNativeWind } = require("nativewind/metro");
237
+ const config = getDefaultConfig(__dirname);
238
+
239
+ config.resolver.unstable_enableSymlinks = true;
240
+ config.resolver.nodeModulesPaths = [path.resolve(__dirname, "node_modules")];
241
+
242
+ try {
243
+ const wsuiPackagePath = path.dirname(
244
+ require.resolve("@wireservers-ui/react-natives/package.json"),
245
+ );
246
+ config.watchFolders = [...new Set([...(config.watchFolders || []), wsuiPackagePath])];
247
+ } catch {
248
+ // No-op if package is not resolvable yet.
249
+ }
250
+
251
+ module.exports = withNativeWind(config, { input: "./global.css" });
252
+ `;
253
+
254
+ const BABEL_CONFIG = `module.exports = function (api) {
255
+ api.cache(true);
256
+ return {
257
+ presets: [
258
+ ["babel-preset-expo", { jsxImportSource: "nativewind" }],
259
+ "nativewind/babel",
260
+ ],
261
+ };
262
+ };
263
+ `;
264
+
265
+ const NATIVEWIND_ENV = `/// <reference types="nativewind/types" />\n`;
266
+
267
+ const APP_TSX = `import "./global.css";
268
+ import React, { useState } from "react";
269
+ import { View, Text } from "react-native";
270
+ import {
271
+ Slider,
272
+ SliderTrack,
273
+ SliderFilledTrack,
274
+ SliderThumb,
275
+ } from "@wireservers-ui/react-natives";
276
+
277
+ export default function App() {
278
+ const [value, setValue] = useState(50);
279
+
280
+ return (
281
+ <View className="flex-1 items-center justify-center bg-background-0 px-8">
282
+ <Text className="text-2xl font-bold text-typography-900 mb-2">
283
+ WireServers Slider
284
+ </Text>
285
+ <Text className="text-base text-typography-500 mb-8">{value}%</Text>
286
+
287
+ <View className="w-full max-w-xs">
288
+ <Slider value={value} onValueChange={setValue} min={0} max={100} size="lg">
289
+ <SliderTrack>
290
+ <SliderFilledTrack />
291
+ </SliderTrack>
292
+ <SliderThumb />
293
+ </Slider>
294
+ </View>
295
+ </View>
296
+ );
297
+ }
298
+ `;
299
+
300
+ const ROUTER_INDEX_TSX = `import "../global.css";
301
+ import React, { useState } from "react";
302
+ import { View, Text } from "react-native";
303
+ import {
304
+ Slider,
305
+ SliderTrack,
306
+ SliderFilledTrack,
307
+ SliderThumb,
308
+ } from "@wireservers-ui/react-natives";
309
+
310
+ export default function HomeScreen() {
311
+ const [value, setValue] = useState(50);
312
+
313
+ return (
314
+ <View className="flex-1 items-center justify-center bg-background-0 px-8">
315
+ <Text className="text-2xl font-bold text-typography-900 mb-2">
316
+ WireServers Slider
317
+ </Text>
318
+ <Text className="text-base text-typography-500 mb-8">{value}%</Text>
319
+
320
+ <View className="w-full max-w-xs">
321
+ <Slider value={value} onValueChange={setValue} min={0} max={100} size="lg">
322
+ <SliderTrack>
323
+ <SliderFilledTrack />
324
+ </SliderTrack>
325
+ <SliderThumb />
326
+ </Slider>
327
+ </View>
328
+ </View>
329
+ );
330
+ }
331
+ `;
332
+
333
+ // ─── Metro Windows ESM patch ──────────────────────────────────────────────────
334
+ //
335
+ // Metro calls `await import(absolutePath)` with a raw Windows path (D:\...).
336
+ // Node 22+'s ESM loader requires file:// URLs on Windows, so this throws
337
+ // ERR_UNSUPPORTED_ESM_URL_SCHEME. The patch converts the path via pathToFileURL.
338
+ // It lives in .metro-patch.js and runs as a postinstall script so it survives
339
+ // future `npm install` calls that would overwrite node_modules.
340
+
341
+ const METRO_PATCH_SCRIPT = `#!/usr/bin/env node
342
+ 'use strict';
343
+ const fs = require('fs');
344
+ const path = require('path');
345
+
346
+ const target = path.join(__dirname, 'node_modules/metro-config/src/loadConfig.js');
347
+ if (!fs.existsSync(target)) process.exit(0);
348
+
349
+ const src = fs.readFileSync(target, 'utf8');
350
+ if (src.includes('pathToFileURL')) process.exit(0); // already patched
351
+
352
+ const patched = src.replace(
353
+ /await import\\(absolutePath\\)/g,
354
+ 'await import(require("url").pathToFileURL(absolutePath).href)'
355
+ );
356
+ if (patched === src) process.exit(0); // pattern not found — nothing to do
357
+
358
+ fs.writeFileSync(target, patched, 'utf8');
359
+ console.log(' patched metro-config/src/loadConfig.js (Windows ESM URL fix)');
360
+ `;
361
+
362
+ // ─── babel.config.js ─────────────────────────────────────────────────────────
363
+
364
+ function handleBabelConfig() {
365
+ const filepath = path.join(cwd, "babel.config.js");
366
+
367
+ if (!fs.existsSync(filepath)) {
368
+ fs.writeFileSync(filepath, BABEL_CONFIG, "utf8");
369
+ console.log(green(" create") + " babel.config.js");
370
+ return;
371
+ }
372
+
373
+ const existing = fs.readFileSync(filepath, "utf8");
374
+ if (
375
+ existing.includes("jsxImportSource") &&
376
+ existing.includes("nativewind/babel")
377
+ ) {
378
+ console.log(green(" ok ") + " babel.config.js");
379
+ return;
380
+ }
381
+
382
+ // create-expo-app ships a single-preset babel.config.js — overwrite it
383
+ if (/presets:\s*\[['"]babel-preset-expo['"]\]/.test(existing)) {
384
+ fs.writeFileSync(filepath, BABEL_CONFIG, "utf8");
385
+ console.log(green(" update") + " babel.config.js");
386
+ return;
387
+ }
388
+
389
+ // Complex existing config — show manual instructions
390
+ console.log(
391
+ yellow(" manual") + " babel.config.js — add NativeWind manually:",
392
+ );
393
+ console.log(
394
+ dim(
395
+ ' presets: [["babel-preset-expo", { jsxImportSource: "nativewind" }], "nativewind/babel"]',
396
+ ),
397
+ );
398
+ }
399
+
400
+ // ─── package.json — add postinstall ──────────────────────────────────────────
401
+
402
+ function addPostinstall() {
403
+ const pkgPath = path.join(cwd, "package.json");
404
+ if (!fs.existsSync(pkgPath)) return;
405
+
406
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
407
+ pkg.scripts = pkg.scripts || {};
408
+
409
+ const existing = pkg.scripts.postinstall || "";
410
+ if (existing.includes(".metro-patch.js")) {
411
+ console.log(green(" ok ") + " package.json postinstall");
412
+ return;
413
+ }
414
+
415
+ pkg.scripts.postinstall = existing
416
+ ? `${existing} && node .metro-patch.js`
417
+ : "node .metro-patch.js";
418
+
419
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf8");
420
+ console.log(green(" update") + " package.json postinstall");
421
+ }
422
+
423
+ // ─── Install nativewind + tailwindcss ────────────────────────────────────────
424
+ //
425
+ // Runs npm install which also triggers postinstall, applying the Metro patch.
426
+
427
+ function installDeps() {
428
+ console.log(cyan("\n Installing required setup dependencies...\n"));
429
+ try {
430
+ execSync("npm install nativewind@4 tailwindcss@3 babel-preset-expo", {
431
+ cwd,
432
+ stdio: "inherit",
433
+ });
434
+ } catch {
435
+ console.log(
436
+ yellow("\n warn ") +
437
+ " npm install failed — run it manually to finish setup",
438
+ );
439
+ }
440
+ }
441
+
442
+ // ─── Run ─────────────────────────────────────────────────────────────────────
443
+
444
+ console.log(bold("\n@wireservers-ui/react-natives init\n"));
445
+
446
+ if (hasExpoRouter) {
447
+ console.log(cyan(" Detected Expo Router") + "\n");
448
+ }
449
+
450
+ write("tailwind.config.js", TAILWIND_CONFIG);
451
+ write("global.css", GLOBAL_CSS);
452
+ write("metro.config.js", METRO_CONFIG);
453
+ handleBabelConfig();
454
+ write("nativewind-env.d.ts", NATIVEWIND_ENV);
455
+ if (hasExpoRouter) {
456
+ writeStarter("app/index.tsx", ROUTER_INDEX_TSX);
457
+ } else {
458
+ writeStarter("App.tsx", APP_TSX);
459
+ }
460
+ write(".metro-patch.js", METRO_PATCH_SCRIPT);
461
+ addPostinstall();
462
+ installDeps();
463
+
464
+ console.log(
465
+ "\n" +
466
+ bold("Done.") +
467
+ " Run " +
468
+ cyan("npx expo start --clear") +
469
+ " to get started.\n",
470
+ );