fluent-styles 1.54.0 → 1.56.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 (872) hide show
  1. package/README.md +3193 -77
  2. package/lib/commonjs/actionSheet/actionSheet.js +372 -0
  3. package/lib/commonjs/actionSheet/actionSheet.js.map +1 -0
  4. package/lib/commonjs/actionSheet/index.js +20 -0
  5. package/lib/commonjs/actionSheet/index.js.map +1 -0
  6. package/lib/commonjs/actionSheet/useActionSheet.js +89 -0
  7. package/lib/commonjs/actionSheet/useActionSheet.js.map +1 -0
  8. package/lib/commonjs/badge/index.js +148 -0
  9. package/lib/commonjs/badge/index.js.map +1 -0
  10. package/lib/commonjs/barChart/index.js +298 -0
  11. package/lib/commonjs/barChart/index.js.map +1 -0
  12. package/lib/commonjs/button/index.js +228 -0
  13. package/lib/commonjs/button/index.js.map +1 -0
  14. package/lib/commonjs/card/index.js +202 -0
  15. package/lib/commonjs/card/index.js.map +1 -0
  16. package/lib/commonjs/checkBox/index.js +90 -0
  17. package/lib/commonjs/checkBox/index.js.map +1 -0
  18. package/lib/commonjs/chips/index.js +239 -0
  19. package/lib/commonjs/chips/index.js.map +1 -0
  20. package/lib/commonjs/circularProgress/index.js +265 -0
  21. package/lib/commonjs/circularProgress/index.js.map +1 -0
  22. package/lib/commonjs/collapsible/Collapse.js +293 -0
  23. package/lib/commonjs/collapsible/Collapse.js.map +1 -0
  24. package/lib/commonjs/collapsible/CollapseGroup.js +137 -0
  25. package/lib/commonjs/collapsible/CollapseGroup.js.map +1 -0
  26. package/lib/commonjs/collapsible/index.js +64 -0
  27. package/lib/commonjs/collapsible/index.js.map +1 -0
  28. package/lib/commonjs/collapsible/interface.js +39 -0
  29. package/lib/commonjs/collapsible/interface.js.map +1 -0
  30. package/lib/commonjs/collapsible/style.js +161 -0
  31. package/lib/commonjs/collapsible/style.js.map +1 -0
  32. package/lib/commonjs/datePicker/index.js +915 -0
  33. package/lib/commonjs/datePicker/index.js.map +1 -0
  34. package/lib/commonjs/dialog/dialogue.js +205 -0
  35. package/lib/commonjs/dialog/dialogue.js.map +1 -0
  36. package/lib/commonjs/dialog/index.js +393 -0
  37. package/lib/commonjs/dialog/index.js.map +1 -0
  38. package/lib/commonjs/dialog/useDialogue.js +117 -0
  39. package/lib/commonjs/dialog/useDialogue.js.map +1 -0
  40. package/lib/commonjs/divider/index.js +37 -0
  41. package/lib/commonjs/divider/index.js.map +1 -0
  42. package/lib/commonjs/drawer/Drawer.js +587 -0
  43. package/lib/commonjs/drawer/Drawer.js.map +1 -0
  44. package/lib/commonjs/drawer/index.js +51 -0
  45. package/lib/commonjs/drawer/index.js.map +1 -0
  46. package/lib/commonjs/drawer/interface.js +84 -0
  47. package/lib/commonjs/drawer/interface.js.map +1 -0
  48. package/lib/commonjs/dropdown/index.js +859 -0
  49. package/lib/commonjs/dropdown/index.js.map +1 -0
  50. package/lib/commonjs/emptyState/index.js +231 -0
  51. package/lib/commonjs/emptyState/index.js.map +1 -0
  52. package/lib/commonjs/form/index.js +2 -0
  53. package/lib/commonjs/form/index.js.map +1 -0
  54. package/lib/commonjs/header/index.js +147 -0
  55. package/lib/commonjs/header/index.js.map +1 -0
  56. package/lib/commonjs/header/statusBar/index.js +20 -0
  57. package/lib/commonjs/header/statusBar/index.js.map +1 -0
  58. package/lib/commonjs/icons/backArrow.js +42 -0
  59. package/lib/commonjs/icons/backArrow.js.map +1 -0
  60. package/lib/commonjs/icons/bellFill.js +43 -0
  61. package/lib/commonjs/icons/bellFill.js.map +1 -0
  62. package/lib/commonjs/icons/bellOutline.js +43 -0
  63. package/lib/commonjs/icons/bellOutline.js.map +1 -0
  64. package/lib/commonjs/icons/checkmark.js +36 -0
  65. package/lib/commonjs/icons/checkmark.js.map +1 -0
  66. package/lib/commonjs/icons/delete.js +53 -0
  67. package/lib/commonjs/icons/delete.js.map +1 -0
  68. package/lib/commonjs/icons/downChevron.js +36 -0
  69. package/lib/commonjs/icons/downChevron.js.map +1 -0
  70. package/lib/commonjs/icons/error.js +41 -0
  71. package/lib/commonjs/icons/error.js.map +1 -0
  72. package/lib/commonjs/icons/forwardArrow.js +42 -0
  73. package/lib/commonjs/icons/forwardArrow.js.map +1 -0
  74. package/lib/commonjs/icons/index.js +111 -0
  75. package/lib/commonjs/icons/index.js.map +1 -0
  76. package/lib/commonjs/icons/info.js +48 -0
  77. package/lib/commonjs/icons/info.js.map +1 -0
  78. package/lib/commonjs/icons/leftChevron.js +36 -0
  79. package/lib/commonjs/icons/leftChevron.js.map +1 -0
  80. package/lib/commonjs/icons/rightChevron.js +36 -0
  81. package/lib/commonjs/icons/rightChevron.js.map +1 -0
  82. package/lib/commonjs/icons/save.js +50 -0
  83. package/lib/commonjs/icons/save.js.map +1 -0
  84. package/lib/commonjs/icons/success.js +43 -0
  85. package/lib/commonjs/icons/success.js.map +1 -0
  86. package/lib/commonjs/icons/upChevron.js +36 -0
  87. package/lib/commonjs/icons/upChevron.js.map +1 -0
  88. package/lib/commonjs/icons/warning.js +48 -0
  89. package/lib/commonjs/icons/warning.js.map +1 -0
  90. package/lib/commonjs/image/index.js +47 -0
  91. package/lib/commonjs/image/index.js.map +1 -0
  92. package/lib/commonjs/index.js +519 -138
  93. package/lib/commonjs/index.js.map +1 -1
  94. package/lib/commonjs/input/index.js +488 -0
  95. package/lib/commonjs/input/index.js.map +1 -0
  96. package/lib/commonjs/loading/circular.js +116 -0
  97. package/lib/commonjs/loading/circular.js.map +1 -0
  98. package/lib/commonjs/loading/index.js +34 -0
  99. package/lib/commonjs/loading/index.js.map +1 -0
  100. package/lib/commonjs/loading/loader.js +247 -0
  101. package/lib/commonjs/loading/loader.js.map +1 -0
  102. package/lib/commonjs/loading/spinner.js +90 -0
  103. package/lib/commonjs/loading/spinner.js.map +1 -0
  104. package/lib/commonjs/loading/useLoader.js +62 -0
  105. package/lib/commonjs/loading/useLoader.js.map +1 -0
  106. package/lib/commonjs/loading/useLoaderBinding.js +34 -0
  107. package/lib/commonjs/loading/useLoaderBinding.js.map +1 -0
  108. package/lib/commonjs/notification/index.js +269 -0
  109. package/lib/commonjs/notification/index.js.map +1 -0
  110. package/lib/commonjs/notification/useNotification.js +62 -0
  111. package/lib/commonjs/notification/useNotification.js.map +1 -0
  112. package/lib/commonjs/page/index.js +22 -0
  113. package/lib/commonjs/page/index.js.map +1 -0
  114. package/lib/commonjs/popup/Popup.js +332 -0
  115. package/lib/commonjs/popup/Popup.js.map +1 -0
  116. package/lib/commonjs/popup/helpers.js +168 -0
  117. package/lib/commonjs/popup/helpers.js.map +1 -0
  118. package/lib/commonjs/popup/index.js +51 -0
  119. package/lib/commonjs/popup/index.js.map +1 -0
  120. package/lib/commonjs/popup/interface.js +45 -0
  121. package/lib/commonjs/popup/interface.js.map +1 -0
  122. package/lib/commonjs/portal/GlobalPortalProvider.js +68 -0
  123. package/lib/commonjs/portal/GlobalPortalProvider.js.map +1 -0
  124. package/lib/commonjs/portal/PortalContext.js +38 -0
  125. package/lib/commonjs/portal/PortalContext.js.map +1 -0
  126. package/lib/commonjs/portal/PortalInstance.js +123 -0
  127. package/lib/commonjs/portal/PortalInstance.js.map +1 -0
  128. package/lib/commonjs/portal/PortalManager.js +87 -0
  129. package/lib/commonjs/portal/PortalManager.js.map +1 -0
  130. package/lib/commonjs/portal/PortalRenderer.js +57 -0
  131. package/lib/commonjs/portal/PortalRenderer.js.map +1 -0
  132. package/lib/commonjs/portal/index.js +54 -0
  133. package/lib/commonjs/portal/index.js.map +1 -0
  134. package/lib/commonjs/portal/portal.test.js +154 -0
  135. package/lib/commonjs/portal/portal.test.js.map +1 -0
  136. package/lib/commonjs/portal/types.js +6 -0
  137. package/lib/commonjs/portal/types.js.map +1 -0
  138. package/lib/commonjs/pressable/index.js +18 -0
  139. package/lib/commonjs/pressable/index.js.map +1 -0
  140. package/lib/commonjs/progressBar/index.js +512 -0
  141. package/lib/commonjs/progressBar/index.js.map +1 -0
  142. package/lib/commonjs/radio/index.js +368 -0
  143. package/lib/commonjs/radio/index.js.map +1 -0
  144. package/lib/commonjs/safeAreaProvider/index.js +12 -0
  145. package/lib/commonjs/safeAreaProvider/index.js.map +1 -0
  146. package/lib/commonjs/safeAreaView/index.js +14 -0
  147. package/lib/commonjs/safeAreaView/index.js.map +1 -0
  148. package/lib/commonjs/scrollView/index.js +14 -0
  149. package/lib/commonjs/scrollView/index.js.map +1 -0
  150. package/lib/commonjs/searchBar/index.js +356 -0
  151. package/lib/commonjs/searchBar/index.js.map +1 -0
  152. package/lib/commonjs/seperator/index.js +44 -0
  153. package/lib/commonjs/seperator/index.js.map +1 -0
  154. package/lib/commonjs/services/index.js +185 -0
  155. package/lib/commonjs/services/index.js.map +1 -0
  156. package/lib/commonjs/shape/index.js +36 -0
  157. package/lib/commonjs/shape/index.js.map +1 -0
  158. package/lib/commonjs/skeleton/index.js +430 -0
  159. package/lib/commonjs/skeleton/index.js.map +1 -0
  160. package/lib/commonjs/slider/index.js +499 -0
  161. package/lib/commonjs/slider/index.js.map +1 -0
  162. package/lib/commonjs/spacer/index.js +14 -0
  163. package/lib/commonjs/spacer/index.js.map +1 -0
  164. package/lib/commonjs/stack/index.js +52 -0
  165. package/lib/commonjs/stack/index.js.map +1 -0
  166. package/lib/commonjs/switch/Switch.js +289 -0
  167. package/lib/commonjs/switch/Switch.js.map +1 -0
  168. package/lib/commonjs/switch/_index.js +118 -0
  169. package/lib/commonjs/switch/_index.js.map +1 -0
  170. package/lib/commonjs/switch/index.js +26 -0
  171. package/lib/commonjs/switch/index.js.map +1 -0
  172. package/lib/commonjs/switch/interface.js +47 -0
  173. package/lib/commonjs/switch/interface.js.map +1 -0
  174. package/lib/commonjs/tabBar/TabBar.js +409 -0
  175. package/lib/commonjs/tabBar/TabBar.js.map +1 -0
  176. package/lib/commonjs/tabBar/TabBarUsage.js +441 -0
  177. package/lib/commonjs/tabBar/TabBarUsage.js.map +1 -0
  178. package/lib/commonjs/tabBar/index.js +26 -0
  179. package/lib/commonjs/tabBar/index.js.map +1 -0
  180. package/lib/commonjs/tabBar/interface.js +43 -0
  181. package/lib/commonjs/tabBar/interface.js.map +1 -0
  182. package/lib/commonjs/text/index.js +65 -0
  183. package/lib/commonjs/text/index.js.map +1 -0
  184. package/lib/commonjs/timeline/index.js +264 -0
  185. package/lib/commonjs/timeline/index.js.map +1 -0
  186. package/lib/commonjs/toast/index.js +203 -0
  187. package/lib/commonjs/toast/index.js.map +1 -0
  188. package/lib/commonjs/toast/useToast.js +82 -0
  189. package/lib/commonjs/toast/useToast.js.map +1 -0
  190. package/lib/commonjs/utiles/createIcon.js +49 -0
  191. package/lib/commonjs/utiles/createIcon.js.map +1 -0
  192. package/lib/commonjs/utiles/fontStyles.js +36 -0
  193. package/lib/commonjs/utiles/fontStyles.js.map +1 -0
  194. package/lib/commonjs/utiles/position.js +98 -0
  195. package/lib/commonjs/utiles/position.js.map +1 -0
  196. package/lib/commonjs/utiles/statusBar.js +425 -0
  197. package/lib/commonjs/utiles/statusBar.js.map +1 -0
  198. package/lib/commonjs/utiles/styled.js +42 -0
  199. package/lib/commonjs/utiles/styled.js.map +1 -0
  200. package/lib/commonjs/utiles/styles.js +30 -0
  201. package/lib/commonjs/utiles/styles.js.map +1 -0
  202. package/lib/commonjs/utiles/theme.js +680 -0
  203. package/lib/commonjs/utiles/theme.js.map +1 -0
  204. package/lib/commonjs/utiles/validators.js +31 -0
  205. package/lib/commonjs/utiles/validators.js.map +1 -0
  206. package/lib/commonjs/utiles/viewStyleProps.js +6 -0
  207. package/lib/commonjs/utiles/viewStyleProps.js.map +1 -0
  208. package/lib/commonjs/utiles/viewStyleVariants.js +546 -0
  209. package/lib/commonjs/utiles/viewStyleVariants.js.map +1 -0
  210. package/lib/module/actionSheet/actionSheet.js +368 -0
  211. package/lib/module/actionSheet/actionSheet.js.map +1 -0
  212. package/lib/module/actionSheet/index.js +5 -0
  213. package/lib/module/actionSheet/index.js.map +1 -0
  214. package/lib/module/actionSheet/useActionSheet.js +85 -0
  215. package/lib/module/actionSheet/useActionSheet.js.map +1 -0
  216. package/lib/module/badge/index.js +147 -0
  217. package/lib/module/badge/index.js.map +1 -0
  218. package/lib/module/barChart/index.js +292 -0
  219. package/lib/module/barChart/index.js.map +1 -0
  220. package/lib/module/button/index.js +224 -0
  221. package/lib/module/button/index.js.map +1 -0
  222. package/lib/module/card/index.js +198 -0
  223. package/lib/module/card/index.js.map +1 -0
  224. package/lib/module/checkBox/index.js +86 -0
  225. package/lib/module/checkBox/index.js.map +1 -0
  226. package/lib/module/chips/index.js +232 -0
  227. package/lib/module/chips/index.js.map +1 -0
  228. package/lib/module/circularProgress/index.js +259 -0
  229. package/lib/module/circularProgress/index.js.map +1 -0
  230. package/lib/module/collapsible/Collapse.js +288 -0
  231. package/lib/module/collapsible/Collapse.js.map +1 -0
  232. package/lib/module/collapsible/CollapseGroup.js +133 -0
  233. package/lib/module/collapsible/CollapseGroup.js.map +1 -0
  234. package/lib/module/collapsible/index.js +40 -0
  235. package/lib/module/collapsible/index.js.map +1 -0
  236. package/lib/module/collapsible/interface.js +35 -0
  237. package/lib/module/collapsible/interface.js.map +1 -0
  238. package/lib/module/collapsible/style.js +153 -0
  239. package/lib/module/collapsible/style.js.map +1 -0
  240. package/lib/module/datePicker/index.js +908 -0
  241. package/lib/module/datePicker/index.js.map +1 -0
  242. package/lib/module/dialog/dialogue.js +189 -0
  243. package/lib/module/dialog/dialogue.js.map +1 -0
  244. package/lib/module/dialog/index.js +386 -0
  245. package/lib/module/dialog/index.js.map +1 -0
  246. package/lib/module/dialog/useDialogue.js +113 -0
  247. package/lib/module/dialog/useDialogue.js.map +1 -0
  248. package/lib/module/divider/index.js +34 -0
  249. package/lib/module/divider/index.js.map +1 -0
  250. package/lib/module/drawer/Drawer.js +583 -0
  251. package/lib/module/drawer/Drawer.js.map +1 -0
  252. package/lib/module/drawer/index.js +60 -0
  253. package/lib/module/drawer/index.js.map +1 -0
  254. package/lib/module/drawer/interface.js +80 -0
  255. package/lib/module/drawer/interface.js.map +1 -0
  256. package/lib/module/dropdown/index.js +854 -0
  257. package/lib/module/dropdown/index.js.map +1 -0
  258. package/lib/module/emptyState/index.js +225 -0
  259. package/lib/module/emptyState/index.js.map +1 -0
  260. package/lib/module/form/index.js +2 -0
  261. package/lib/module/form/index.js.map +1 -0
  262. package/lib/module/header/index.js +143 -0
  263. package/lib/module/header/index.js.map +1 -0
  264. package/lib/module/header/statusBar/index.js +15 -0
  265. package/lib/module/header/statusBar/index.js.map +1 -0
  266. package/lib/module/icons/backArrow.js +37 -0
  267. package/lib/module/icons/backArrow.js.map +1 -0
  268. package/lib/module/icons/bellFill.js +38 -0
  269. package/lib/module/icons/bellFill.js.map +1 -0
  270. package/lib/module/icons/bellOutline.js +38 -0
  271. package/lib/module/icons/bellOutline.js.map +1 -0
  272. package/lib/module/icons/checkmark.js +31 -0
  273. package/lib/module/icons/checkmark.js.map +1 -0
  274. package/lib/module/icons/delete.js +48 -0
  275. package/lib/module/icons/delete.js.map +1 -0
  276. package/lib/module/icons/downChevron.js +31 -0
  277. package/lib/module/icons/downChevron.js.map +1 -0
  278. package/lib/module/icons/error.js +36 -0
  279. package/lib/module/icons/error.js.map +1 -0
  280. package/lib/module/icons/forwardArrow.js +37 -0
  281. package/lib/module/icons/forwardArrow.js.map +1 -0
  282. package/lib/module/icons/index.js +18 -0
  283. package/lib/module/icons/index.js.map +1 -0
  284. package/lib/module/icons/info.js +43 -0
  285. package/lib/module/icons/info.js.map +1 -0
  286. package/lib/module/icons/leftChevron.js +31 -0
  287. package/lib/module/icons/leftChevron.js.map +1 -0
  288. package/lib/module/icons/rightChevron.js +31 -0
  289. package/lib/module/icons/rightChevron.js.map +1 -0
  290. package/lib/module/icons/save.js +45 -0
  291. package/lib/module/icons/save.js.map +1 -0
  292. package/lib/module/icons/success.js +38 -0
  293. package/lib/module/icons/success.js.map +1 -0
  294. package/lib/module/icons/upChevron.js +31 -0
  295. package/lib/module/icons/upChevron.js.map +1 -0
  296. package/lib/module/icons/warning.js +43 -0
  297. package/lib/module/icons/warning.js.map +1 -0
  298. package/lib/module/image/index.js +43 -0
  299. package/lib/module/image/index.js.map +1 -0
  300. package/lib/module/index.js +56 -24
  301. package/lib/module/index.js.map +1 -1
  302. package/lib/module/input/index.js +483 -0
  303. package/lib/module/input/index.js.map +1 -0
  304. package/lib/module/loading/circular.js +111 -0
  305. package/lib/module/loading/circular.js.map +1 -0
  306. package/lib/module/loading/index.js +7 -0
  307. package/lib/module/loading/index.js.map +1 -0
  308. package/lib/module/loading/loader.js +242 -0
  309. package/lib/module/loading/loader.js.map +1 -0
  310. package/lib/module/loading/spinner.js +85 -0
  311. package/lib/module/loading/spinner.js.map +1 -0
  312. package/lib/module/loading/useLoader.js +58 -0
  313. package/lib/module/loading/useLoader.js.map +1 -0
  314. package/lib/module/loading/useLoaderBinding.js +28 -0
  315. package/lib/module/loading/useLoaderBinding.js.map +1 -0
  316. package/lib/module/notification/index.js +253 -0
  317. package/lib/module/notification/index.js.map +1 -0
  318. package/lib/module/notification/useNotification.js +58 -0
  319. package/lib/module/notification/useNotification.js.map +1 -0
  320. package/lib/module/page/index.js +17 -0
  321. package/lib/module/page/index.js.map +1 -0
  322. package/lib/module/popup/Popup.js +328 -0
  323. package/lib/module/popup/Popup.js.map +1 -0
  324. package/lib/module/popup/helpers.js +159 -0
  325. package/lib/module/popup/helpers.js.map +1 -0
  326. package/lib/module/popup/index.js +45 -0
  327. package/lib/module/popup/index.js.map +1 -0
  328. package/lib/module/popup/interface.js +41 -0
  329. package/lib/module/popup/interface.js.map +1 -0
  330. package/lib/module/portal/GlobalPortalProvider.js +62 -0
  331. package/lib/module/portal/GlobalPortalProvider.js.map +1 -0
  332. package/lib/module/portal/PortalContext.js +33 -0
  333. package/lib/module/portal/PortalContext.js.map +1 -0
  334. package/lib/module/portal/PortalInstance.js +118 -0
  335. package/lib/module/portal/PortalInstance.js.map +1 -0
  336. package/lib/module/portal/PortalManager.js +81 -0
  337. package/lib/module/portal/PortalManager.js.map +1 -0
  338. package/lib/module/portal/PortalRenderer.js +51 -0
  339. package/lib/module/portal/PortalRenderer.js.map +1 -0
  340. package/lib/module/portal/index.js +56 -0
  341. package/lib/module/portal/index.js.map +1 -0
  342. package/lib/module/portal/portal.test.js +155 -0
  343. package/lib/module/portal/portal.test.js.map +1 -0
  344. package/lib/module/portal/types.js +4 -0
  345. package/lib/module/portal/types.js.map +1 -0
  346. package/lib/module/pressable/index.js +15 -0
  347. package/lib/module/pressable/index.js.map +1 -0
  348. package/lib/module/progressBar/index.js +506 -0
  349. package/lib/module/progressBar/index.js.map +1 -0
  350. package/lib/module/radio/index.js +361 -0
  351. package/lib/module/radio/index.js.map +1 -0
  352. package/lib/module/safeAreaProvider/index.js +9 -0
  353. package/lib/module/safeAreaProvider/index.js.map +1 -0
  354. package/lib/module/safeAreaView/index.js +11 -0
  355. package/lib/module/safeAreaView/index.js.map +1 -0
  356. package/lib/module/scrollView/index.js +11 -0
  357. package/lib/module/scrollView/index.js.map +1 -0
  358. package/lib/module/searchBar/index.js +350 -0
  359. package/lib/module/searchBar/index.js.map +1 -0
  360. package/lib/module/seperator/index.js +40 -0
  361. package/lib/module/seperator/index.js.map +1 -0
  362. package/lib/module/services/index.js +181 -0
  363. package/lib/module/services/index.js.map +1 -0
  364. package/lib/module/shape/index.js +33 -0
  365. package/lib/module/shape/index.js.map +1 -0
  366. package/lib/module/skeleton/index.js +425 -0
  367. package/lib/module/skeleton/index.js.map +1 -0
  368. package/lib/module/slider/index.js +493 -0
  369. package/lib/module/slider/index.js.map +1 -0
  370. package/lib/module/spacer/index.js +11 -0
  371. package/lib/module/spacer/index.js.map +1 -0
  372. package/lib/module/stack/index.js +50 -0
  373. package/lib/module/stack/index.js.map +1 -0
  374. package/lib/module/switch/Switch.js +285 -0
  375. package/lib/module/switch/Switch.js.map +1 -0
  376. package/lib/module/switch/_index.js +114 -0
  377. package/lib/module/switch/_index.js.map +1 -0
  378. package/lib/module/switch/index.js +64 -0
  379. package/lib/module/switch/index.js.map +1 -0
  380. package/lib/module/switch/interface.js +43 -0
  381. package/lib/module/switch/interface.js.map +1 -0
  382. package/lib/module/tabBar/TabBar.js +405 -0
  383. package/lib/module/tabBar/TabBar.js.map +1 -0
  384. package/lib/module/tabBar/TabBarUsage.js +437 -0
  385. package/lib/module/tabBar/TabBarUsage.js.map +1 -0
  386. package/lib/module/tabBar/index.js +54 -0
  387. package/lib/module/tabBar/index.js.map +1 -0
  388. package/lib/module/tabBar/interface.js +39 -0
  389. package/lib/module/tabBar/interface.js.map +1 -0
  390. package/lib/module/text/index.js +62 -0
  391. package/lib/module/text/index.js.map +1 -0
  392. package/lib/module/timeline/index.js +258 -0
  393. package/lib/module/timeline/index.js.map +1 -0
  394. package/lib/module/toast/index.js +187 -0
  395. package/lib/module/toast/index.js.map +1 -0
  396. package/lib/module/toast/useToast.js +78 -0
  397. package/lib/module/toast/useToast.js.map +1 -0
  398. package/lib/module/utiles/createIcon.js +45 -0
  399. package/lib/module/utiles/createIcon.js.map +1 -0
  400. package/lib/module/utiles/fontStyles.js +31 -0
  401. package/lib/module/utiles/fontStyles.js.map +1 -0
  402. package/lib/module/utiles/position.js +94 -0
  403. package/lib/module/utiles/position.js.map +1 -0
  404. package/lib/module/utiles/statusBar.js +401 -0
  405. package/lib/module/utiles/statusBar.js.map +1 -0
  406. package/lib/module/utiles/styled.js +37 -0
  407. package/lib/module/utiles/styled.js.map +1 -0
  408. package/lib/module/utiles/styles.js +27 -0
  409. package/lib/module/utiles/styles.js.map +1 -0
  410. package/lib/module/{package → utiles}/theme.js +305 -17
  411. package/lib/module/utiles/theme.js.map +1 -0
  412. package/lib/module/utiles/validators.js +24 -0
  413. package/lib/module/utiles/validators.js.map +1 -0
  414. package/lib/module/utiles/viewStyleProps.js +4 -0
  415. package/lib/module/utiles/viewStyleProps.js.map +1 -0
  416. package/lib/module/utiles/viewStyleVariants.js +542 -0
  417. package/lib/module/utiles/viewStyleVariants.js.map +1 -0
  418. package/lib/typescript/actionSheet/actionSheet.d.ts +82 -0
  419. package/lib/typescript/actionSheet/actionSheet.d.ts.map +1 -0
  420. package/lib/typescript/actionSheet/index.d.ts +4 -0
  421. package/lib/typescript/actionSheet/index.d.ts.map +1 -0
  422. package/lib/typescript/actionSheet/useActionSheet.d.ts +82 -0
  423. package/lib/typescript/actionSheet/useActionSheet.d.ts.map +1 -0
  424. package/lib/typescript/badge/index.d.ts +37 -0
  425. package/lib/typescript/badge/index.d.ts.map +1 -0
  426. package/lib/typescript/barChart/index.d.ts +125 -0
  427. package/lib/typescript/barChart/index.d.ts.map +1 -0
  428. package/lib/typescript/button/index.d.ts +86 -0
  429. package/lib/typescript/button/index.d.ts.map +1 -0
  430. package/lib/typescript/card/index.d.ts +53 -0
  431. package/lib/typescript/card/index.d.ts.map +1 -0
  432. package/lib/typescript/checkBox/index.d.ts +28 -0
  433. package/lib/typescript/checkBox/index.d.ts.map +1 -0
  434. package/lib/typescript/chips/index.d.ts +104 -0
  435. package/lib/typescript/chips/index.d.ts.map +1 -0
  436. package/lib/typescript/circularProgress/index.d.ts +36 -0
  437. package/lib/typescript/circularProgress/index.d.ts.map +1 -0
  438. package/lib/typescript/collapsible/Collapse.d.ts +5 -0
  439. package/lib/typescript/collapsible/Collapse.d.ts.map +1 -0
  440. package/lib/typescript/collapsible/CollapseGroup.d.ts +49 -0
  441. package/lib/typescript/collapsible/CollapseGroup.d.ts.map +1 -0
  442. package/lib/typescript/collapsible/index.d.ts +38 -0
  443. package/lib/typescript/collapsible/index.d.ts.map +1 -0
  444. package/lib/typescript/collapsible/interface.d.ts +116 -0
  445. package/lib/typescript/collapsible/interface.d.ts.map +1 -0
  446. package/lib/typescript/collapsible/style.d.ts +92 -0
  447. package/lib/typescript/collapsible/style.d.ts.map +1 -0
  448. package/lib/typescript/datePicker/index.d.ts +91 -0
  449. package/lib/typescript/datePicker/index.d.ts.map +1 -0
  450. package/lib/typescript/dialog/dialogue.d.ts +20 -0
  451. package/lib/typescript/dialog/dialogue.d.ts.map +1 -0
  452. package/lib/typescript/dialog/index.d.ts +175 -0
  453. package/lib/typescript/dialog/index.d.ts.map +1 -0
  454. package/lib/typescript/dialog/useDialogue.d.ts +21 -0
  455. package/lib/typescript/dialog/useDialogue.d.ts.map +1 -0
  456. package/lib/typescript/divider/index.d.ts +12 -0
  457. package/lib/typescript/divider/index.d.ts.map +1 -0
  458. package/lib/typescript/drawer/Drawer.d.ts +4 -0
  459. package/lib/typescript/drawer/Drawer.d.ts.map +1 -0
  460. package/lib/typescript/drawer/index.d.ts +48 -0
  461. package/lib/typescript/drawer/index.d.ts.map +1 -0
  462. package/lib/typescript/drawer/interface.d.ts +232 -0
  463. package/lib/typescript/drawer/interface.d.ts.map +1 -0
  464. package/lib/typescript/dropdown/index.d.ts +54 -0
  465. package/lib/typescript/dropdown/index.d.ts.map +1 -0
  466. package/lib/typescript/emptyState/index.d.ts +57 -0
  467. package/lib/typescript/emptyState/index.d.ts.map +1 -0
  468. package/lib/typescript/form/index.d.ts +1 -0
  469. package/lib/typescript/form/index.d.ts.map +1 -0
  470. package/lib/typescript/header/index.d.ts +44 -0
  471. package/lib/typescript/header/index.d.ts.map +1 -0
  472. package/lib/typescript/header/statusBar/index.d.ts +6 -0
  473. package/lib/typescript/header/statusBar/index.d.ts.map +1 -0
  474. package/lib/typescript/icons/backArrow.d.ts +12 -0
  475. package/lib/typescript/icons/backArrow.d.ts.map +1 -0
  476. package/lib/typescript/icons/bellFill.d.ts +12 -0
  477. package/lib/typescript/icons/bellFill.d.ts.map +1 -0
  478. package/lib/typescript/icons/bellOutline.d.ts +12 -0
  479. package/lib/typescript/icons/bellOutline.d.ts.map +1 -0
  480. package/lib/typescript/icons/checkmark.d.ts +12 -0
  481. package/lib/typescript/icons/checkmark.d.ts.map +1 -0
  482. package/lib/typescript/icons/delete.d.ts +12 -0
  483. package/lib/typescript/icons/delete.d.ts.map +1 -0
  484. package/lib/typescript/icons/downChevron.d.ts +12 -0
  485. package/lib/typescript/icons/downChevron.d.ts.map +1 -0
  486. package/lib/typescript/icons/error.d.ts +12 -0
  487. package/lib/typescript/icons/error.d.ts.map +1 -0
  488. package/lib/typescript/icons/forwardArrow.d.ts +12 -0
  489. package/lib/typescript/icons/forwardArrow.d.ts.map +1 -0
  490. package/lib/typescript/icons/index.d.ts +16 -0
  491. package/lib/typescript/icons/index.d.ts.map +1 -0
  492. package/lib/typescript/icons/info.d.ts +12 -0
  493. package/lib/typescript/icons/info.d.ts.map +1 -0
  494. package/lib/typescript/icons/leftChevron.d.ts +12 -0
  495. package/lib/typescript/icons/leftChevron.d.ts.map +1 -0
  496. package/lib/typescript/icons/rightChevron.d.ts +12 -0
  497. package/lib/typescript/icons/rightChevron.d.ts.map +1 -0
  498. package/lib/typescript/icons/save.d.ts +12 -0
  499. package/lib/typescript/icons/save.d.ts.map +1 -0
  500. package/lib/typescript/icons/success.d.ts +12 -0
  501. package/lib/typescript/icons/success.d.ts.map +1 -0
  502. package/lib/typescript/icons/upChevron.d.ts +12 -0
  503. package/lib/typescript/icons/upChevron.d.ts.map +1 -0
  504. package/lib/typescript/icons/warning.d.ts +12 -0
  505. package/lib/typescript/icons/warning.d.ts.map +1 -0
  506. package/lib/typescript/image/index.d.ts +15 -0
  507. package/lib/typescript/image/index.d.ts.map +1 -0
  508. package/lib/typescript/index.d.ts +56 -0
  509. package/lib/typescript/index.d.ts.map +1 -0
  510. package/lib/typescript/input/index.d.ts +89 -0
  511. package/lib/typescript/input/index.d.ts.map +1 -0
  512. package/lib/typescript/loading/circular.d.ts +10 -0
  513. package/lib/typescript/loading/circular.d.ts.map +1 -0
  514. package/lib/typescript/loading/index.d.ts +7 -0
  515. package/lib/typescript/loading/index.d.ts.map +1 -0
  516. package/lib/typescript/loading/loader.d.ts +23 -0
  517. package/lib/typescript/loading/loader.d.ts.map +1 -0
  518. package/lib/typescript/loading/spinner.d.ts +22 -0
  519. package/lib/typescript/loading/spinner.d.ts.map +1 -0
  520. package/lib/typescript/loading/useLoader.d.ts +27 -0
  521. package/lib/typescript/loading/useLoader.d.ts.map +1 -0
  522. package/lib/typescript/loading/useLoaderBinding.d.ts +9 -0
  523. package/lib/typescript/loading/useLoaderBinding.d.ts.map +1 -0
  524. package/lib/typescript/notification/index.d.ts +21 -0
  525. package/lib/typescript/notification/index.d.ts.map +1 -0
  526. package/lib/typescript/notification/useNotification.d.ts +30 -0
  527. package/lib/typescript/notification/useNotification.d.ts.map +1 -0
  528. package/lib/typescript/page/index.d.ts +12 -0
  529. package/lib/typescript/page/index.d.ts.map +1 -0
  530. package/lib/typescript/popup/Popup.d.ts +4 -0
  531. package/lib/typescript/popup/Popup.d.ts.map +1 -0
  532. package/lib/typescript/popup/helpers.d.ts +9 -0
  533. package/lib/typescript/popup/helpers.d.ts.map +1 -0
  534. package/lib/typescript/popup/index.d.ts +43 -0
  535. package/lib/typescript/popup/index.d.ts.map +1 -0
  536. package/lib/typescript/popup/interface.d.ts +103 -0
  537. package/lib/typescript/popup/interface.d.ts.map +1 -0
  538. package/lib/typescript/portal/GlobalPortalProvider.d.ts +44 -0
  539. package/lib/typescript/portal/GlobalPortalProvider.d.ts.map +1 -0
  540. package/lib/typescript/portal/PortalContext.d.ts +25 -0
  541. package/lib/typescript/portal/PortalContext.d.ts.map +1 -0
  542. package/lib/typescript/portal/PortalInstance.d.ts +72 -0
  543. package/lib/typescript/portal/PortalInstance.d.ts.map +1 -0
  544. package/lib/typescript/portal/PortalManager.d.ts +7 -0
  545. package/lib/typescript/portal/PortalManager.d.ts.map +1 -0
  546. package/lib/typescript/portal/PortalRenderer.d.ts +27 -0
  547. package/lib/typescript/portal/PortalRenderer.d.ts.map +1 -0
  548. package/lib/typescript/portal/index.d.ts +43 -0
  549. package/lib/typescript/portal/index.d.ts.map +1 -0
  550. package/lib/typescript/portal/portal.test.d.ts +11 -0
  551. package/lib/typescript/portal/portal.test.d.ts.map +1 -0
  552. package/lib/typescript/portal/types.d.ts +30 -0
  553. package/lib/typescript/portal/types.d.ts.map +1 -0
  554. package/lib/typescript/pressable/index.d.ts +8 -0
  555. package/lib/typescript/pressable/index.d.ts.map +1 -0
  556. package/lib/typescript/progressBar/index.d.ts +155 -0
  557. package/lib/typescript/progressBar/index.d.ts.map +1 -0
  558. package/lib/typescript/radio/index.d.ts +144 -0
  559. package/lib/typescript/radio/index.d.ts.map +1 -0
  560. package/lib/typescript/safeAreaProvider/index.d.ts +7 -0
  561. package/lib/typescript/safeAreaProvider/index.d.ts.map +1 -0
  562. package/lib/typescript/safeAreaView/index.d.ts +8 -0
  563. package/lib/typescript/safeAreaView/index.d.ts.map +1 -0
  564. package/lib/typescript/scrollView/index.d.ts +8 -0
  565. package/lib/typescript/scrollView/index.d.ts.map +1 -0
  566. package/lib/typescript/searchBar/index.d.ts +70 -0
  567. package/lib/typescript/searchBar/index.d.ts.map +1 -0
  568. package/lib/typescript/seperator/index.d.ts +13 -0
  569. package/lib/typescript/seperator/index.d.ts.map +1 -0
  570. package/lib/typescript/services/index.d.ts +56 -0
  571. package/lib/typescript/services/index.d.ts.map +1 -0
  572. package/lib/typescript/shape/index.d.ts +11 -0
  573. package/lib/typescript/shape/index.d.ts.map +1 -0
  574. package/lib/typescript/skeleton/index.d.ts +63 -0
  575. package/lib/typescript/skeleton/index.d.ts.map +1 -0
  576. package/lib/typescript/slider/index.d.ts +60 -0
  577. package/lib/typescript/slider/index.d.ts.map +1 -0
  578. package/lib/typescript/spacer/index.d.ts +8 -0
  579. package/lib/typescript/spacer/index.d.ts.map +1 -0
  580. package/lib/typescript/stack/index.d.ts +24 -0
  581. package/lib/typescript/stack/index.d.ts.map +1 -0
  582. package/lib/typescript/switch/Switch.d.ts +6 -0
  583. package/lib/typescript/switch/Switch.d.ts.map +1 -0
  584. package/lib/typescript/switch/_index.d.ts +11 -0
  585. package/lib/typescript/switch/_index.d.ts.map +1 -0
  586. package/lib/typescript/switch/index.d.ts +62 -0
  587. package/lib/typescript/switch/index.d.ts.map +1 -0
  588. package/lib/typescript/switch/interface.d.ts +74 -0
  589. package/lib/typescript/switch/interface.d.ts.map +1 -0
  590. package/lib/typescript/tabBar/TabBar.d.ts +5 -0
  591. package/lib/typescript/tabBar/TabBar.d.ts.map +1 -0
  592. package/lib/typescript/tabBar/TabBarUsage.d.ts +6 -0
  593. package/lib/typescript/tabBar/TabBarUsage.d.ts.map +1 -0
  594. package/lib/typescript/tabBar/index.d.ts +52 -0
  595. package/lib/typescript/tabBar/index.d.ts.map +1 -0
  596. package/lib/typescript/tabBar/interface.d.ts +119 -0
  597. package/lib/typescript/tabBar/interface.d.ts.map +1 -0
  598. package/lib/typescript/text/index.d.ts +16 -0
  599. package/lib/typescript/text/index.d.ts.map +1 -0
  600. package/lib/typescript/timeline/index.d.ts +125 -0
  601. package/lib/typescript/timeline/index.d.ts.map +1 -0
  602. package/lib/typescript/toast/index.d.ts +28 -0
  603. package/lib/typescript/toast/index.d.ts.map +1 -0
  604. package/lib/typescript/toast/useToast.d.ts +31 -0
  605. package/lib/typescript/toast/useToast.d.ts.map +1 -0
  606. package/lib/typescript/utiles/createIcon.d.ts +39 -0
  607. package/lib/typescript/utiles/createIcon.d.ts.map +1 -0
  608. package/lib/typescript/utiles/fontStyles.d.ts +9 -0
  609. package/lib/typescript/utiles/fontStyles.d.ts.map +1 -0
  610. package/lib/typescript/utiles/position.d.ts +13 -0
  611. package/lib/typescript/utiles/position.d.ts.map +1 -0
  612. package/lib/typescript/utiles/statusBar.d.ts +128 -0
  613. package/lib/typescript/utiles/statusBar.d.ts.map +1 -0
  614. package/lib/typescript/utiles/styled.d.ts +14 -0
  615. package/lib/typescript/utiles/styled.d.ts.map +1 -0
  616. package/lib/typescript/utiles/styles.d.ts +31 -0
  617. package/lib/typescript/utiles/styles.d.ts.map +1 -0
  618. package/lib/typescript/utiles/theme.d.ts +918 -0
  619. package/lib/typescript/utiles/theme.d.ts.map +1 -0
  620. package/lib/typescript/utiles/validators.d.ts +14 -0
  621. package/lib/typescript/utiles/validators.d.ts.map +1 -0
  622. package/lib/typescript/utiles/viewStyleProps.d.ts +4 -0
  623. package/lib/typescript/utiles/viewStyleProps.d.ts.map +1 -0
  624. package/lib/typescript/utiles/viewStyleVariants.d.ts +121 -0
  625. package/lib/typescript/utiles/viewStyleVariants.d.ts.map +1 -0
  626. package/package.json +146 -52
  627. package/src/actionSheet/actionSheet.tsx +471 -0
  628. package/src/actionSheet/index.tsx +3 -0
  629. package/src/actionSheet/useActionSheet.tsx +140 -0
  630. package/src/badge/index.tsx +185 -0
  631. package/src/barChart/index.tsx +386 -0
  632. package/src/button/index.tsx +335 -0
  633. package/src/card/index.tsx +220 -0
  634. package/src/checkBox/index.tsx +137 -0
  635. package/src/chips/index.tsx +293 -0
  636. package/src/circularProgress/index.tsx +349 -0
  637. package/src/collapsible/Collapse.tsx +366 -0
  638. package/src/collapsible/CollapseGroup.tsx +161 -0
  639. package/src/collapsible/index.ts +48 -0
  640. package/src/collapsible/interface.ts +187 -0
  641. package/src/collapsible/style.ts +130 -0
  642. package/src/datePicker/index.tsx +961 -0
  643. package/src/dialog/dialogue.tsx +155 -0
  644. package/src/dialog/index.tsx +604 -0
  645. package/src/dialog/useDialogue.tsx +158 -0
  646. package/src/divider/index.tsx +45 -0
  647. package/src/drawer/Drawer.tsx +655 -0
  648. package/src/drawer/index.ts +60 -0
  649. package/src/drawer/interface.ts +391 -0
  650. package/src/dropdown/index.tsx +1081 -0
  651. package/src/emptyState/index.tsx +287 -0
  652. package/src/form/index.tsx +0 -0
  653. package/src/header/index.tsx +217 -0
  654. package/src/header/statusBar/index.tsx +11 -0
  655. package/src/icons/backArrow.tsx +17 -0
  656. package/src/icons/bellFill.tsx +19 -0
  657. package/src/icons/bellOutline.tsx +18 -0
  658. package/src/icons/checkmark.tsx +18 -0
  659. package/src/icons/delete.tsx +19 -0
  660. package/src/icons/downChevron.tsx +18 -0
  661. package/src/icons/error.tsx +17 -0
  662. package/src/icons/forwardArrow.tsx +19 -0
  663. package/src/icons/index.ts +15 -0
  664. package/src/icons/info.tsx +19 -0
  665. package/src/icons/leftChevron.tsx +18 -0
  666. package/src/icons/rightChevron.tsx +18 -0
  667. package/src/icons/save.tsx +18 -0
  668. package/src/icons/success.tsx +17 -0
  669. package/src/icons/upChevron.tsx +18 -0
  670. package/src/icons/warning.tsx +19 -0
  671. package/src/image/index.tsx +45 -0
  672. package/src/index.ts +72 -0
  673. package/src/input/index.tsx +668 -0
  674. package/src/loading/circular.tsx +141 -0
  675. package/src/loading/index.tsx +6 -0
  676. package/src/loading/loader.tsx +191 -0
  677. package/src/loading/spinner.tsx +126 -0
  678. package/src/loading/useLoader.tsx +78 -0
  679. package/src/loading/useLoaderBinding.tsx +38 -0
  680. package/src/notification/index.tsx +189 -0
  681. package/src/notification/useNotification.tsx +64 -0
  682. package/src/page/index.tsx +19 -0
  683. package/src/popup/Popup.tsx +398 -0
  684. package/src/popup/helpers.ts +123 -0
  685. package/src/popup/index.ts +45 -0
  686. package/src/popup/interface.ts +178 -0
  687. package/src/portal/GlobalPortalProvider.tsx +63 -0
  688. package/src/portal/PortalContext.ts +37 -0
  689. package/src/portal/PortalInstance.ts +118 -0
  690. package/src/portal/PortalManager.tsx +84 -0
  691. package/src/portal/PortalRenderer.tsx +72 -0
  692. package/src/portal/index.ts +60 -0
  693. package/src/portal/portal.test.ts +157 -0
  694. package/src/portal/types.ts +49 -0
  695. package/src/pressable/index.tsx +19 -0
  696. package/src/progressBar/index.tsx +564 -0
  697. package/src/radio/index.tsx +469 -0
  698. package/src/safeAreaProvider/index.ts +16 -0
  699. package/src/safeAreaView/index.tsx +17 -0
  700. package/src/scrollView/index.ts +15 -0
  701. package/src/searchBar/index.tsx +383 -0
  702. package/src/seperator/index.tsx +59 -0
  703. package/src/services/index.ts +149 -0
  704. package/src/shape/index.tsx +38 -0
  705. package/src/skeleton/index.tsx +350 -0
  706. package/src/slider/index.tsx +637 -0
  707. package/src/spacer/index.ts +29 -0
  708. package/src/stack/index.ts +58 -0
  709. package/src/switch/Switch.tsx +343 -0
  710. package/src/switch/_index.tsx +135 -0
  711. package/src/switch/index.ts +62 -0
  712. package/src/switch/interface.ts +120 -0
  713. package/src/tabBar/TabBar.tsx +503 -0
  714. package/src/tabBar/TabBarUsage.tsx +366 -0
  715. package/src/tabBar/index.ts +59 -0
  716. package/src/tabBar/interface.ts +196 -0
  717. package/src/text/index.ts +73 -0
  718. package/src/timeline/index.tsx +374 -0
  719. package/src/toast/index.tsx +172 -0
  720. package/src/toast/useToast.tsx +93 -0
  721. package/src/utiles/createIcon.ts +44 -0
  722. package/src/utiles/fontStyles.js +31 -0
  723. package/src/utiles/position.ts +100 -0
  724. package/src/utiles/statusBar.ts +410 -0
  725. package/src/utiles/styled.tsx +48 -0
  726. package/src/utiles/styles.ts +25 -0
  727. package/src/utiles/theme.ts +727 -0
  728. package/src/utiles/validators.ts +21 -0
  729. package/src/utiles/viewStyleProps.ts +41 -0
  730. package/src/utiles/viewStyleVariants.ts +411 -0
  731. package/lib/commonjs/assets/img/blank_1.png +0 -0
  732. package/lib/commonjs/assets/img/blank_2.png +0 -0
  733. package/lib/commonjs/assets/img/doctor.png +0 -0
  734. package/lib/commonjs/package/badge/index.js +0 -161
  735. package/lib/commonjs/package/badge/index.js.map +0 -1
  736. package/lib/commonjs/package/button/index.js +0 -99
  737. package/lib/commonjs/package/button/index.js.map +0 -1
  738. package/lib/commonjs/package/card/index.js +0 -46
  739. package/lib/commonjs/package/card/index.js.map +0 -1
  740. package/lib/commonjs/package/checkBox/index.js +0 -97
  741. package/lib/commonjs/package/checkBox/index.js.map +0 -1
  742. package/lib/commonjs/package/cycle/index.js +0 -43
  743. package/lib/commonjs/package/cycle/index.js.map +0 -1
  744. package/lib/commonjs/package/dialog/index.js +0 -216
  745. package/lib/commonjs/package/dialog/index.js.map +0 -1
  746. package/lib/commonjs/package/dropdown/index.js +0 -112
  747. package/lib/commonjs/package/dropdown/index.js.map +0 -1
  748. package/lib/commonjs/package/form/index.js +0 -190
  749. package/lib/commonjs/package/form/index.js.map +0 -1
  750. package/lib/commonjs/package/header/index.js +0 -99
  751. package/lib/commonjs/package/header/index.js.map +0 -1
  752. package/lib/commonjs/package/image/index.js +0 -326
  753. package/lib/commonjs/package/image/index.js.map +0 -1
  754. package/lib/commonjs/package/radioButton/index.js +0 -75
  755. package/lib/commonjs/package/radioButton/index.js.map +0 -1
  756. package/lib/commonjs/package/safeAreaView/index.js +0 -26
  757. package/lib/commonjs/package/safeAreaView/index.js.map +0 -1
  758. package/lib/commonjs/package/scrollView/index.js +0 -23
  759. package/lib/commonjs/package/scrollView/index.js.map +0 -1
  760. package/lib/commonjs/package/separator/index.js +0 -33
  761. package/lib/commonjs/package/separator/index.js.map +0 -1
  762. package/lib/commonjs/package/spacer/index.js +0 -18
  763. package/lib/commonjs/package/spacer/index.js.map +0 -1
  764. package/lib/commonjs/package/spinner/index.js +0 -43
  765. package/lib/commonjs/package/spinner/index.js.map +0 -1
  766. package/lib/commonjs/package/stack/__test__/index.test.js +0 -91
  767. package/lib/commonjs/package/stack/__test__/index.test.js.map +0 -1
  768. package/lib/commonjs/package/stack/index.js +0 -54
  769. package/lib/commonjs/package/stack/index.js.map +0 -1
  770. package/lib/commonjs/package/styled/__test__/index.test.js +0 -161
  771. package/lib/commonjs/package/styled/__test__/index.test.js.map +0 -1
  772. package/lib/commonjs/package/styled/index.js +0 -42
  773. package/lib/commonjs/package/styled/index.js.map +0 -1
  774. package/lib/commonjs/package/switch/index.js +0 -43
  775. package/lib/commonjs/package/switch/index.js.map +0 -1
  776. package/lib/commonjs/package/text/index.js +0 -81
  777. package/lib/commonjs/package/text/index.js.map +0 -1
  778. package/lib/commonjs/package/theme.js +0 -385
  779. package/lib/commonjs/package/theme.js.map +0 -1
  780. package/lib/commonjs/package/utils/index.js +0 -130
  781. package/lib/commonjs/package/utils/index.js.map +0 -1
  782. package/lib/commonjs/package/utils/statusBar.js +0 -70
  783. package/lib/commonjs/package/utils/statusBar.js.map +0 -1
  784. package/lib/commonjs/package/utils/validator.js +0 -40
  785. package/lib/commonjs/package/utils/validator.js.map +0 -1
  786. package/lib/commonjs/styled.code-workspace +0 -9
  787. package/lib/module/assets/img/blank_1.png +0 -0
  788. package/lib/module/assets/img/blank_2.png +0 -0
  789. package/lib/module/assets/img/doctor.png +0 -0
  790. package/lib/module/package/badge/index.js +0 -153
  791. package/lib/module/package/badge/index.js.map +0 -1
  792. package/lib/module/package/button/index.js +0 -92
  793. package/lib/module/package/button/index.js.map +0 -1
  794. package/lib/module/package/card/index.js +0 -39
  795. package/lib/module/package/card/index.js.map +0 -1
  796. package/lib/module/package/checkBox/index.js +0 -88
  797. package/lib/module/package/checkBox/index.js.map +0 -1
  798. package/lib/module/package/cycle/index.js +0 -36
  799. package/lib/module/package/cycle/index.js.map +0 -1
  800. package/lib/module/package/dialog/index.js +0 -206
  801. package/lib/module/package/dialog/index.js.map +0 -1
  802. package/lib/module/package/dropdown/index.js +0 -102
  803. package/lib/module/package/dropdown/index.js.map +0 -1
  804. package/lib/module/package/form/index.js +0 -182
  805. package/lib/module/package/form/index.js.map +0 -1
  806. package/lib/module/package/header/index.js +0 -93
  807. package/lib/module/package/header/index.js.map +0 -1
  808. package/lib/module/package/image/index.js +0 -315
  809. package/lib/module/package/image/index.js.map +0 -1
  810. package/lib/module/package/radioButton/index.js +0 -66
  811. package/lib/module/package/radioButton/index.js.map +0 -1
  812. package/lib/module/package/safeAreaView/index.js +0 -21
  813. package/lib/module/package/safeAreaView/index.js.map +0 -1
  814. package/lib/module/package/scrollView/index.js +0 -18
  815. package/lib/module/package/scrollView/index.js.map +0 -1
  816. package/lib/module/package/separator/index.js +0 -26
  817. package/lib/module/package/separator/index.js.map +0 -1
  818. package/lib/module/package/spacer/index.js +0 -11
  819. package/lib/module/package/spacer/index.js.map +0 -1
  820. package/lib/module/package/spinner/index.js +0 -36
  821. package/lib/module/package/spinner/index.js.map +0 -1
  822. package/lib/module/package/stack/__test__/index.test.js +0 -89
  823. package/lib/module/package/stack/__test__/index.test.js.map +0 -1
  824. package/lib/module/package/stack/index.js +0 -49
  825. package/lib/module/package/stack/index.js.map +0 -1
  826. package/lib/module/package/styled/__test__/index.test.js +0 -158
  827. package/lib/module/package/styled/__test__/index.test.js.map +0 -1
  828. package/lib/module/package/styled/index.js +0 -35
  829. package/lib/module/package/styled/index.js.map +0 -1
  830. package/lib/module/package/switch/index.js +0 -36
  831. package/lib/module/package/switch/index.js.map +0 -1
  832. package/lib/module/package/text/index.js +0 -76
  833. package/lib/module/package/text/index.js.map +0 -1
  834. package/lib/module/package/theme.js.map +0 -1
  835. package/lib/module/package/utils/index.js +0 -120
  836. package/lib/module/package/utils/index.js.map +0 -1
  837. package/lib/module/package/utils/statusBar.js +0 -57
  838. package/lib/module/package/utils/statusBar.js.map +0 -1
  839. package/lib/module/package/utils/validator.js +0 -34
  840. package/lib/module/package/utils/validator.js.map +0 -1
  841. package/lib/module/styled.code-workspace +0 -9
  842. package/src/assets/img/blank_1.png +0 -0
  843. package/src/assets/img/blank_2.png +0 -0
  844. package/src/assets/img/doctor.png +0 -0
  845. package/src/index.js +0 -24
  846. package/src/package/badge/index.jsx +0 -135
  847. package/src/package/button/index.jsx +0 -83
  848. package/src/package/card/index.jsx +0 -52
  849. package/src/package/checkBox/index.jsx +0 -102
  850. package/src/package/cycle/index.jsx +0 -49
  851. package/src/package/dialog/index.jsx +0 -263
  852. package/src/package/dropdown/index.jsx +0 -101
  853. package/src/package/form/index.jsx +0 -144
  854. package/src/package/header/index.jsx +0 -96
  855. package/src/package/image/index.jsx +0 -300
  856. package/src/package/radioButton/index.jsx +0 -74
  857. package/src/package/safeAreaView/index.jsx +0 -20
  858. package/src/package/scrollView/index.jsx +0 -17
  859. package/src/package/separator/index.jsx +0 -27
  860. package/src/package/spacer/index.jsx +0 -13
  861. package/src/package/spinner/index.jsx +0 -33
  862. package/src/package/stack/__test__/index.test.js +0 -68
  863. package/src/package/stack/index.jsx +0 -50
  864. package/src/package/styled/__test__/index.test.js +0 -132
  865. package/src/package/styled/index.js +0 -32
  866. package/src/package/switch/index.jsx +0 -33
  867. package/src/package/text/index.jsx +0 -67
  868. package/src/package/theme.js +0 -377
  869. package/src/package/utils/index.js +0 -109
  870. package/src/package/utils/statusBar.js +0 -65
  871. package/src/package/utils/validator.js +0 -38
  872. package/src/styled.code-workspace +0 -9
package/README.md CHANGED
@@ -1,77 +1,3193 @@
1
- # fluent-styles
2
-
3
- Fluent-styles is a library designed to simplify the development of styled variants on UI components for both React and React Native projects. It enables developers to easily manage and apply base and variant styles to components dynamically based on props.
4
-
5
- ## Features
6
-
7
- - **Dynamic Styling**: Easily apply and switch styles based on the props of the components.
8
- - **Support for React and React Native**: Can be used seamlessly across web and mobile platforms.
9
-
10
- ## Installation
11
-
12
- Install fluent-styles using npm:
13
-
14
- ```bash
15
- npm install fluent-styles
16
-
17
- Or using yarn:
18
-
19
- yarn add fluent-styles
20
-
21
- Usage
22
- After installing the package, you can use it to wrap your components with styled functionality. Below is a basic example of how to use fluent-styles in a React application:
23
-
24
- React Example
25
-
26
- import React from 'react';
27
- import styled from 'fluent-styles';
28
-
29
- const baseStyles = {
30
- padding: '20px',
31
- color: 'white'
32
- };
33
-
34
- const variants = {
35
- mood: {
36
- happy: { backgroundColor: 'yellow' },
37
- sad: { backgroundColor: 'blue' }
38
- }
39
- };
40
-
41
- const MoodText = styled('div', { base: baseStyles, variants });
42
-
43
- function App() {
44
- return (
45
- <MoodText mood="happy">I am happy!</MoodText>
46
- );
47
- }
48
-
49
- export default App;
50
-
51
- React Native Example
52
- import React from 'react';
53
- import { Text } from 'react-native';
54
- import styled from 'style-ease';
55
-
56
- const baseStyles = {
57
- padding: 10,
58
- color: 'white'
59
- };
60
-
61
- const variants = {
62
- mood: {
63
- happy: { backgroundColor: 'yellow' },
64
- sad: { backgroundColor: 'blue' }
65
- }
66
- };
67
-
68
- const MoodText = styled(Text, { base: baseStyles, variants });
69
-
70
- function App() {
71
- return (
72
- <MoodText mood="happy">I am happy!</MoodText>
73
- );
74
- }
75
-
76
- export default App;
77
-
1
+ # Fluent Styles
2
+
3
+ A comprehensive, TypeScript-first React Native UI library providing production-ready components, hooks, and an imperative service layer all powered by a portal-based rendering system.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/fluent-styles)](https://www.npmjs.com/package/fluent-styles)
6
+ [![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
7
+
8
+ ---
9
+
10
+ ## Table of Contents
11
+
12
+ - [Installation](#installation)
13
+ - [Quick Start](#quick-start)
14
+ - [Portal System](#portal-system)
15
+ - [Components](#components)
16
+ - [StyledButton](#styledbutton)
17
+ - [StyledTextInput](#styledtextinput)
18
+ - [Switch](#switch)
19
+ - [StyledCheckBox](#styledcheckbox)
20
+ - [StyledCard](#styledcard)
21
+ - [StyledBadge / BadgeWithIcon](#styledbadge--badgewithicon)
22
+ - [StyledImage / StyledImageBackground](#styledimage--styledimagebackground)
23
+ - [StyledHeader / FullHeader](#styledheader--fullheader)
24
+ - [StyledDropdown / StyledMultiSelectDropdown](#styleddropdown--styledmultiselectdropdown)
25
+ - [Popup](#popup)
26
+ - [Drawer](#drawer)
27
+ - [Collapse / CollapseGroup](#collapse--collapsegroup)
28
+ - [TabBar](#tabbar)
29
+ - [StyledDivider](#styleddivider)
30
+ - [StyledSeperator](#styledseperator)
31
+ - [Stack](#stack)
32
+ - [StyledText](#styledtext)
33
+ - [StyledPressable](#styledpressable)
34
+ - [StyledPage / StyledScrollView](#styledpage--styledscrollview)
35
+ - [StyledSafeAreaView](#styledsafeareaview)
36
+ - [Spacer](#spacer)
37
+ - [StyledShape](#styledshape)
38
+ - [Loader](#loader)
39
+ - [StyledCircularProgress](#styledcircularprogress)
40
+ - [StyledChip](#styledchip)
41
+ - [StyledBar](#styledbar)
42
+ - [StyledTimeline](#styledtimeline)
43
+ - [StyledRadio / StyledRadioGroup](#styledradio--styledradiogroup)
44
+ - [StyledProgressBar](#styledprogressbar)
45
+ - [StyledSlider](#styledslider)
46
+ - [StyledDatePicker](#styleddatepicker)
47
+ - [Hooks](#hooks)
48
+ - [useToast](#usetoast)
49
+ - [useNotification](#usenotification)
50
+ - [useDialogue](#usedialogue)
51
+ - [useActionSheet](#useactionsheet)
52
+ - [useLoader](#useloader)
53
+ - [Imperative Services](#imperative-services)
54
+ - [toastService](#toastservice)
55
+ - [notificationService](#notificationservice)
56
+ - [dialogueService](#dialogueservice)
57
+ - [actionSheetService](#actionsheetservice)
58
+ - [loaderService](#loaderservice)
59
+ - [Theme & Tokens](#theme--tokens)
60
+ - [Contributing](#contributing)
61
+ - [License](#license)
62
+
63
+ ---
64
+
65
+ ## Installation
66
+
67
+ ```bash
68
+ npm install fluent-styles
69
+ # or
70
+ yarn add fluent-styles
71
+ ```
72
+
73
+ Peer dependencies (install separately if not already present):
74
+
75
+ ```bash
76
+ npm install react-native-safe-area-context
77
+ ```
78
+
79
+ ---
80
+
81
+ ## Quick Start
82
+
83
+ Wrap your root component with `GlobalPortalProvider`. This single wrapper enables **all** portal-based UI — toasts, notifications, loaders, dialogues, drawers, and action sheets.
84
+
85
+ ```tsx
86
+ import { GlobalPortalProvider } from 'fluent-styles'
87
+
88
+ export default function App() {
89
+ return (
90
+ <GlobalPortalProvider>
91
+ <YourNavigator />
92
+ </GlobalPortalProvider>
93
+ )
94
+ }
95
+ ```
96
+
97
+ If you also use the declarative hooks (`useToast`, `useDialogue`, etc.) inside descendant components, nest a `PortalManager` as well:
98
+
99
+ ```tsx
100
+ import { GlobalPortalProvider, PortalManager } from 'fluent-styles'
101
+
102
+ export default function App() {
103
+ return (
104
+ <GlobalPortalProvider>
105
+ <PortalManager>
106
+ <YourNavigator />z
107
+ </PortalManager>
108
+ </GlobalPortalProvider>
109
+ )
110
+ }
111
+ ```
112
+
113
+ ---
114
+
115
+ ## Portal System
116
+
117
+ Fluent Styles uses a dual-layer portal architecture:
118
+
119
+ | Layer | Provider | Use case |
120
+ |---|---|---|
121
+ | **Global singleton** | `GlobalPortalProvider` | Imperative services (`toastService`, `loaderService`, etc.) — usable outside React |
122
+ | **Declarative hooks** | `PortalManager` | Hook APIs (`useToast`, `useDialogue`, etc.) — usable inside React components |
123
+
124
+ The low-level `portal` singleton is also exported for advanced use:
125
+
126
+ ```ts
127
+ import { portal } from 'fluent-styles'
128
+
129
+ const id = portal.show(<MyWidget />, { position: 'top', backdrop: false })
130
+ setTimeout(() => portal.hide(id), 3000)
131
+ ```
132
+
133
+ ---
134
+
135
+ ## Components
136
+
137
+ ### StyledButton
138
+
139
+ A fully themed button with variant, shape, size, and icon support.
140
+
141
+ ```tsx
142
+ import { StyledButton, theme } from 'fluent-styles'
143
+
144
+ // Variants (compact style)
145
+ <StyledButton primary compact>
146
+ <StyledButton.Text color={theme.colors.white} fontSize={theme.fontSize.small} fontWeight={theme.fontWeight.semiBold}>
147
+ Primary
148
+ </StyledButton.Text>
149
+ </StyledButton>
150
+ <StyledButton secondary compact>Secondary</StyledButton>
151
+ <StyledButton outline compact>Outline</StyledButton>
152
+ <StyledButton ghost compact>Ghost</StyledButton>
153
+ <StyledButton link compact>Link</StyledButton>
154
+ <StyledButton danger compact>Danger</StyledButton>
155
+ <StyledButton success compact>Success</StyledButton>
156
+ <StyledButton warning compact>Warning</StyledButton>
157
+ <StyledButton disabled compact>Disabled</StyledButton>
158
+
159
+ // Sizes: xs | sm | md | lg | xl
160
+ {(['xs', 'sm', 'md', 'lg', 'xl'] as const).map((s) => (
161
+ <StyledButton key={s} primary compact {...{ [s]: true }}>
162
+ <StyledButton.Text color={theme.colors.white}>{s.toUpperCase()}</StyledButton.Text>
163
+ </StyledButton>
164
+ ))}
165
+
166
+ // Shapes
167
+ <StyledButton primary compact pill>Pill</StyledButton>
168
+ <StyledButton primary compact rounded>Rounded</StyledButton>
169
+ <StyledButton backgroundColor={theme.colors.yellow[500]} borderWidth={0} square>Square</StyledButton>
170
+
171
+ // Icons — left, right, or both
172
+ <StyledButton primary compact leftIcon={<Icon emoji="🚀" />}>Deploy</StyledButton>
173
+ <StyledButton outline compact rightIcon={<Icon emoji="→" />}>Continue</StyledButton>
174
+ <StyledButton secondary compact leftIcon={<Icon emoji="⬇" />} rightIcon={<Icon emoji="📦" />}>
175
+ Download package
176
+ </StyledButton>
177
+
178
+ // Icon-only circular buttons
179
+ <StyledButton icon backgroundColor={theme.colors.indigo[500]}><Icon emoji="✉️" size={18} /></StyledButton>
180
+ <StyledButton icon backgroundColor={theme.colors.amber[400]}><Icon emoji="🔔" size={18} /></StyledButton>
181
+ <StyledButton icon backgroundColor={theme.colors.red[500]}><Icon emoji="🗑️" size={18} /></StyledButton>
182
+
183
+ // Loading state (async example)
184
+ const [loading, setLoading] = useState(false)
185
+ <StyledButton primary compact loading={loading} onPress={() => { setLoading(true); setTimeout(() => setLoading(false), 2000) }}>
186
+ <StyledButton.Text color={theme.colors.white}>{loading ? 'Saving…' : 'Save changes'}</StyledButton.Text>
187
+ </StyledButton>
188
+
189
+ // Full-width block
190
+ <StyledButton primary block>
191
+ <StyledButton.Text color={theme.colors.white} fontSize={theme.fontSize.medium} fontWeight={theme.fontWeight.bold}>
192
+ Create account
193
+ </StyledButton.Text>
194
+ </StyledButton>
195
+ <StyledButton outline block>
196
+ <StyledButton.Text color={theme.colors.gray[800]} fontSize={theme.fontSize.medium}>Sign in instead</StyledButton.Text>
197
+ </StyledButton>
198
+
199
+ // Disabled
200
+ <StyledButton primary disabled>Disabled</StyledButton>
201
+ ```
202
+
203
+ Accepts all `TouchableOpacityProps` and flat `ViewStyle` props.
204
+
205
+ ---
206
+
207
+ ### StyledTextInput
208
+
209
+ A rich text input with label, validation, addons, and an imperative ref handle.
210
+
211
+ ```tsx
212
+ import { StyledTextInput } from 'fluent-styles'
213
+
214
+ // Variants: outline | filled | underline | ghost
215
+ <StyledTextInput variant="outline" label="Email" placeholder="you@example.com" />
216
+
217
+ // Sizes: sm | md | lg
218
+ <StyledTextInput size="md" label="Medium" />
219
+
220
+ // Floating label (Material Design style)
221
+ <StyledTextInput floatLabel label="Floating Label" />
222
+
223
+ // Validation
224
+ <StyledTextInput
225
+ label="Username"
226
+ required
227
+ helperText="Must be unique"
228
+ errorMessage="Already taken"
229
+ error
230
+ />
231
+
232
+ // Character counter
233
+ <StyledTextInput label="Bio" showCounter maxLength={200} multiline />
234
+
235
+ // Icons & addons
236
+ <StyledTextInput leftIcon={<SearchIcon />} placeholder="Search…" />
237
+ <StyledTextInput
238
+ leftAddon={{ text: 'https://', bg: '#f4f4f5' }}
239
+ rightAddon={{ text: '.com', bg: '#f4f4f5' }}
240
+ placeholder="yoursite"
241
+ />
242
+
243
+ // States
244
+ <StyledTextInput clearable value={value} onChangeText={setValue} />
245
+ <StyledTextInput loading />
246
+
247
+ // Imperative handle
248
+ const inputRef = useRef<StyledTextInputHandle>(null)
249
+ <StyledTextInput ref={inputRef} label="Password" secureTextEntry />
250
+ inputRef.current?.focus()
251
+ inputRef.current?.clear()
252
+ inputRef.current?.isFocused()
253
+ ```
254
+
255
+ **Key props:**
256
+
257
+ | Prop | Type | Description |
258
+ |---|---|---|
259
+ | `label` | `string` | Input label |
260
+ | `floatLabel` | `boolean` | Animated floating label |
261
+ | `required` | `boolean` | Appends `*` to label |
262
+ | `helperText` | `string` | Hint text below input |
263
+ | `errorMessage` | `string` | Error text (visible when `error` is true) |
264
+ | `error` | `boolean` | Activates error state |
265
+ | `showCounter` | `boolean` | Character counter (requires `maxLength`) |
266
+ | `variant` | `outline \| filled \| underline \| ghost` | Visual style |
267
+ | `size` | `sm \| md \| lg` | Input size |
268
+ | `leftIcon / rightIcon` | `ReactNode` | Icon slots |
269
+ | `leftAddon / rightAddon` | `{ text?, node?, bg?, color?, onPress? }` | Prefix/suffix addons |
270
+ | `clearable` | `boolean` | Clear button when value is present |
271
+ | `loading` | `boolean` | Right-side activity spinner |
272
+ | `focusColor` | `string` | Border colour on focus |
273
+
274
+ ---
275
+
276
+ ### Switch
277
+
278
+ A generic animated toggle with async confirmation guard and customisable labels.
279
+
280
+ ```tsx
281
+ import { Switch } from 'fluent-styles'
282
+
283
+ // Uncontrolled boolean
284
+ <Switch defaultValue={false} onChange={(val) => console.log(val)} />
285
+
286
+ // Controlled
287
+ <Switch value={isOn} onChange={setIsOn} />
288
+
289
+ // Non-boolean (generic types)
290
+ <Switch<'yes', 'no'>
291
+ activeValue="yes"
292
+ inactiveValue="no"
293
+ defaultValue="no"
294
+ onChange={(val) => console.log(val)}
295
+ />
296
+
297
+ // Sizes: sm | md | lg
298
+ <Switch size="lg" defaultValue />
299
+
300
+ // Async guard — return false to cancel toggle
301
+ <Switch
302
+ beforeChange={async (next) => {
303
+ const ok = await confirmDialog()
304
+ return ok
305
+ }}
306
+ />
307
+
308
+ // Inline labels & colours
309
+ <Switch activeLabel="ON" inactiveLabel="OFF" />
310
+ <Switch activeColor="#10b981" inactiveColor="#d4d4d8" />
311
+
312
+ // Fine-grained color token overrides
313
+ <Switch
314
+ defaultValue
315
+ colors={{
316
+ activeTrack: palettes.rose[500],
317
+ inactiveTrack: palettes.rose[100],
318
+ inactiveBorder: palettes.rose[200],
319
+ activeLabelText: '#fff',
320
+ }}
321
+ />
322
+ <Switch defaultValue activeColor={palettes.amber[400]} inactiveColor={palettes.amber[100]} />
323
+
324
+ // Teal with labels
325
+ <Switch
326
+ size="lg"
327
+ defaultValue
328
+ activeLabel="ON"
329
+ inactiveLabel="OFF"
330
+ colors={{
331
+ activeTrack: palettes.teal[500],
332
+ inactiveTrack: palettes.teal[100],
333
+ activeLabelText: '#fff',
334
+ inactiveLabelText: palettes.teal[400],
335
+ }}
336
+ />
337
+
338
+ // On a dark background (slate palette)
339
+ <Switch
340
+ defaultValue
341
+ colors={{
342
+ activeTrack: palettes.indigo[400],
343
+ inactiveTrack: palettes.blueGray[700],
344
+ inactiveBorder: palettes.blueGray[600],
345
+ thumb: '#ffffff',
346
+ }}
347
+ />
348
+
349
+ // Always-rejected guard (demonstrates async guard returning false)
350
+ <Switch defaultValue={false} beforeChange={() => Promise.resolve(false)} />
351
+
352
+ // States
353
+ <Switch loading />
354
+ <Switch disabled />
355
+ ```
356
+
357
+ **Key props:**
358
+
359
+ | Prop | Type | Description |
360
+ |---|---|---|
361
+ | `value` | `T` | Controlled value |
362
+ | `defaultValue` | `T` | Uncontrolled initial value |
363
+ | `activeValue / inactiveValue` | `T` | Values for on/off (default `true`/`false`) |
364
+ | `onChange` | `(val: T) => void` | Change callback |
365
+ | `beforeChange` | `(next: T) => boolean \| Promise<boolean>` | Async guard |
366
+ | `size` | `sm \| md \| lg` | Track size preset |
367
+ | `activeLabel / inactiveLabel` | `string \| ReactNode` | Label inside track |
368
+ | `activeColor / inactiveColor` | `string` | Track colour overrides |
369
+ | `loading` | `boolean` | Replaces thumb with a spinner |
370
+ | `disabled` | `boolean` | Disables interaction |
371
+ | `colors` | `Partial<SwitchColors>` | Fine-grained token overrides |
372
+
373
+ ---
374
+
375
+ ### StyledCheckBox
376
+
377
+ An accessible checkbox with customisable size and colour.
378
+
379
+ ```tsx
380
+ import { StyledCheckBox, StyledCard, StyledText, Stack, theme } from 'fluent-styles'
381
+
382
+ // Basic
383
+ <StyledCheckBox checked={isChecked} onCheck={setChecked} />
384
+
385
+ // Sizes: 18 | 24 | 32 | 40
386
+ <Stack horizontal gap={16} alignItems="center">
387
+ <StyledCheckBox checked size={18} onCheck={() => {}} />
388
+ <StyledCheckBox checked size={24} onCheck={() => {}} />
389
+ <StyledCheckBox checked size={32} onCheck={() => {}} />
390
+ <StyledCheckBox checked size={40} onCheck={() => {}} />
391
+ </Stack>
392
+
393
+ // Custom colors
394
+ <StyledCheckBox checked checkedColor={theme.colors.green[500]} checkMarkColor="#fff" onCheck={() => {}} />
395
+ <StyledCheckBox checked checkedColor={theme.colors.blue[600]} checkMarkColor="#fff" onCheck={() => {}} />
396
+ <StyledCheckBox checked checkedColor={theme.colors.rose[500]} checkMarkColor="#fff" onCheck={() => {}} />
397
+
398
+ // Disabled states
399
+ <StyledCheckBox checked={false} disabled onCheck={() => {}} />
400
+ <StyledCheckBox checked disabled onCheck={() => {}} />
401
+
402
+ // --- Real-world: Settings preferences card ---
403
+ <StyledCard backgroundColor={theme.colors.white} borderRadius={18} padding={16} shadow="light">
404
+ <Stack gap={18}>
405
+ <StyledText fontSize={18} fontWeight={800}>Preferences</StyledText>
406
+ {[{ label: 'Product updates', checked: updates, setter: setUpdates },
407
+ { label: 'Marketing emails', checked: marketing, setter: setMarketing },
408
+ { label: 'Push notifications', checked: notifs, setter: setNotifs }]
409
+ .map(({ label, checked, setter }) => (
410
+ <Stack key={label} horizontal alignItems="center" gap={12}>
411
+ <StyledCheckBox checked={checked} onCheck={setter} />
412
+ <StyledText fontSize={15} fontWeight={600}>{label}</StyledText>
413
+ </Stack>
414
+ ))}
415
+ </Stack>
416
+ </StyledCard>
417
+
418
+ // --- Real-world: Task list with green checkmarks ---
419
+ <Stack gap={16}>
420
+ {tasks.map(({ key, label, helper }) => (
421
+ <Stack key={key} horizontal alignItems="center" gap={12}>
422
+ <StyledCheckBox
423
+ checked={done[key]}
424
+ onCheck={(v) => setDone(prev => ({ ...prev, [key]: v }))}
425
+ checkedColor={theme.colors.green[500]}
426
+ checkMarkColor="#fff"
427
+ />
428
+ <Stack flex={1}>
429
+ <StyledText fontSize={15} fontWeight={600}>{label}</StyledText>
430
+ {helper && <StyledText fontSize={13} color={theme.colors.gray[500]}>{helper}</StyledText>}
431
+ </Stack>
432
+ </Stack>
433
+ ))}
434
+ </Stack>
435
+
436
+ // --- Compact inline usage ---
437
+ <Stack horizontal alignItems="center" gap={10}>
438
+ <StyledCheckBox checked={remember} onCheck={setRemember} size={20} />
439
+ <StyledText>Remember me</StyledText>
440
+ </Stack>
441
+ ```
442
+
443
+ ---
444
+
445
+ ### StyledCard
446
+
447
+ A flexible container with optional shadow levels and pressable wrapper.
448
+
449
+ ```tsx
450
+ import { StyledCard } from 'fluent-styles'
451
+
452
+ <StyledCard shadow="light" padding={16} borderRadius={12}>
453
+ <StyledText>Card content</StyledText>
454
+ </StyledCard>
455
+
456
+ // Pressable card
457
+ <StyledCard
458
+ shadow="medium"
459
+ pressable
460
+ pressableProps={{ onPress: () => navigate('Detail') }}
461
+ >
462
+ <StyledText>Tap me</StyledText>
463
+ </StyledCard>
464
+ ```
465
+
466
+ **Shadow levels:** `light` | `lightMedium` | `medium` | `mediumDark` | `dark` | `veryDark`
467
+
468
+ Accepts all `ViewProps` and flat `ViewStyle` props.
469
+
470
+ ---
471
+
472
+ ### StyledBadge / BadgeWithIcon / BadgeIcon
473
+
474
+ Styled text badges, icon badges, and notification count overlays.
475
+
476
+ ```tsx
477
+ import { StyledBadge, BadgeWithIcon, BadgeIcon, StyledImage, Stack, theme } from 'fluent-styles'
478
+
479
+ // --- Pill status badges ---
480
+ <Stack horizontal gap={10} flexWrap="wrap">
481
+ <StyledBadge
482
+ backgroundColor={theme.colors.green[50]}
483
+ color={theme.colors.green[700]}
484
+ paddingHorizontal={10} paddingVertical={6} borderRadius={999}
485
+ >Active</StyledBadge>
486
+
487
+ <StyledBadge
488
+ backgroundColor={theme.colors.red[50]}
489
+ color={theme.colors.red[600]}
490
+ paddingHorizontal={10} paddingVertical={6} borderRadius={999}
491
+ >Rejected</StyledBadge>
492
+
493
+ <StyledBadge
494
+ backgroundColor={theme.colors.blue[50]}
495
+ color={theme.colors.blue[700]}
496
+ paddingHorizontal={10} paddingVertical={6} borderRadius={999}
497
+ >New</StyledBadge>
498
+ </Stack>
499
+
500
+ // --- Link badge ---
501
+ <StyledBadge link>View details</StyledBadge>
502
+
503
+ // --- BadgeWithIcon: feature / status badges ---
504
+ <BadgeWithIcon
505
+ title="Featured"
506
+ iconLeft={<Text>⭐</Text>}
507
+ backgroundColor={theme.colors.yellow[50]}
508
+ paddingHorizontal={12} paddingVertical={7} borderRadius={999} gap={6}
509
+ />
510
+ <BadgeWithIcon
511
+ title="Verified"
512
+ iconLeft={<Text>✅</Text>}
513
+ backgroundColor={theme.colors.green[50]}
514
+ paddingHorizontal={12} paddingVertical={7} borderRadius={999} gap={6}
515
+ />
516
+
517
+ // --- Status badges (workflow states) ---
518
+ <BadgeWithIcon title="In progress" iconLeft={<Text>🟡</Text>} color={theme.colors.yellow[700]}
519
+ backgroundColor={theme.colors.yellow[50]} paddingHorizontal={12} paddingVertical={8} borderRadius={999} gap={6} />
520
+ <BadgeWithIcon title="Completed" iconLeft={<Text>🟢</Text>} color={theme.colors.green[700]}
521
+ backgroundColor={theme.colors.green[50]} paddingHorizontal={12} paddingVertical={8} borderRadius={999} gap={6} />
522
+ <BadgeWithIcon title="Blocked" iconLeft={<Text>🔴</Text>} color={theme.colors.red[700]}
523
+ backgroundColor={theme.colors.red[50]} paddingHorizontal={12} paddingVertical={8} borderRadius={999} gap={6} />
524
+
525
+ // --- BadgeIcon: count bubbles ---
526
+ <Stack horizontal gap={24} alignItems="center">
527
+ <BadgeIcon char="1" size={24} />
528
+ <BadgeIcon char="3" backgroundColor={theme.colors.blue[600]} size={24} />
529
+ <BadgeIcon char="9+" backgroundColor={theme.colors.gray[800]} size={24} />
530
+ </Stack>
531
+
532
+ // --- BadgeIcon over an icon (notification dot) ---
533
+ <BadgeIcon icon={<Text style={{ fontSize: 24 }}>🔔</Text>} char="2" right={20} top={-12} size={16} />
534
+ <BadgeIcon icon={<Text style={{ fontSize: 24 }}>🛒</Text>} char="4" backgroundColor={theme.colors.green[600]} right={16} top={-12} size={16} />
535
+
536
+ // --- Overlay badge on an image ---
537
+ <Stack>
538
+ <StyledImage source={{ uri: '…' }} width={220} height={150} borderRadius={18} />
539
+ <Stack position="absolute" top={10} right={10}>
540
+ <StyledBadge backgroundColor="rgba(17,24,39,0.78)" color="#fff"
541
+ paddingHorizontal={10} paddingVertical={6} borderRadius={999} fontWeight="700">New</StyledBadge>
542
+ </Stack>
543
+ </Stack>
544
+
545
+ // --- Avatar with notification count ---
546
+ <Stack>
547
+ <StyledImage source={{ uri: '…' }} cycle size={64} borderRadius={999} />
548
+ <Stack position="absolute" top={2} right={2}>
549
+ <BadgeIcon char="3" size={18} />
550
+ </Stack>
551
+ </Stack>
552
+
553
+ // --- Product badges ---
554
+ <Stack horizontal gap={10} flexWrap="wrap">
555
+ <StyledBadge backgroundColor={theme.colors.red[50]} color={theme.colors.red[600]}
556
+ paddingHorizontal={10} paddingVertical={6} borderRadius={999} fontWeight="700">Sale</StyledBadge>
557
+ <StyledBadge backgroundColor={theme.colors.gray[900]} color={theme.colors.white}
558
+ paddingHorizontal={10} paddingVertical={6} borderRadius={999} fontWeight="700">Limited</StyledBadge>
559
+ <BadgeWithIcon title="Free delivery" iconLeft={<Text>🚚</Text>} backgroundColor={theme.colors.green[50]}
560
+ paddingHorizontal={12} paddingVertical={7} borderRadius={999} gap={6} />
561
+ </Stack>
562
+ ```
563
+
564
+ **`BadgeIcon` props:** `char`, `icon?`, `size?`, `backgroundColor?`, `top?`, `right?`
565
+
566
+ ---
567
+
568
+ ### StyledImage / StyledImageBackground
569
+
570
+ Styled wrappers around React Native's `Image` and `ImageBackground`.
571
+
572
+ ```tsx
573
+ import { StyledImage, StyledImageBackground } from 'fluent-styles'
574
+
575
+ // Fixed dimensions
576
+ <StyledImage source={{ uri: 'https://…' }} width={120} height={80} borderRadius={8} />
577
+
578
+ // Circular avatar (cycle + size)
579
+ <StyledImage source={{ uri: 'https://…' }} cycle size={64} />
580
+
581
+ // Background image with overlay
582
+ <StyledImageBackground source={require('./assets/hero.jpg')} height={200} borderRadius={12}>
583
+ <StyledText color="#fff">Overlay text</StyledText>
584
+ </StyledImageBackground>
585
+ ```
586
+
587
+ ---
588
+
589
+ ### StyledHeader / FullHeader
590
+
591
+ A pre-built navigation header with optional status bar management.
592
+
593
+ ```tsx
594
+ import { StyledHeader, FullHeader } from 'fluent-styles'
595
+
596
+ <StyledHeader
597
+ title="Settings"
598
+ titleAlignment="center"
599
+ showBackArrow
600
+ onBackPress={() => navigation.goBack()}
601
+ rightIcon={<SettingsIcon />}
602
+ />
603
+
604
+ // Custom back button styling
605
+ <StyledHeader
606
+ title="Profile"
607
+ showBackArrow
608
+ backArrowProps={{ size: 20, color: '#6366f1', onPress: () => navigation.goBack() }}
609
+ />
610
+
611
+ // Full header — manages status bar spacer automatically
612
+ <FullHeader statusBarProps={{ barStyle: 'dark-content' }}>
613
+ <MyCustomHeaderContent />
614
+ </FullHeader>
615
+ ```
616
+
617
+ | Prop | Type | Description |
618
+ |---|---|---|
619
+ | `title` | `string` | Header title |
620
+ | `titleAlignment` | `left \| center \| right` | Title alignment |
621
+ | `showBackArrow` | `boolean` | Renders a back arrow |
622
+ | `onBackPress` | `() => void` | Back arrow handler |
623
+ | `leftIcon / rightIcon` | `ReactNode` | Custom icon slots |
624
+ | `backArrowProps` | `BackArrowProps` | Size, colour, custom press handler |
625
+ | `showStatusBar` | `boolean` | Include status bar spacer |
626
+
627
+ ---
628
+
629
+ ### StyledDropdown / StyledMultiSelectDropdown
630
+
631
+ Modal-based dropdowns with optional search, icons, and subtitles.
632
+
633
+ ```tsx
634
+ import { StyledDropdown, StyledMultiSelectDropdown } from 'fluent-styles'
635
+
636
+ const options = [
637
+ { value: 'react', label: 'React Native' },
638
+ { value: 'flutter', label: 'Flutter', subtitle: 'by Google' },
639
+ { value: 'ionic', label: 'Ionic', disabled: true },
640
+ ]
641
+
642
+ // Single-select
643
+ <StyledDropdown
644
+ label="Framework"
645
+ placeholder="Pick one…"
646
+ options={options}
647
+ value={selected}
648
+ onChange={(item) => setSelected(item.value)}
649
+ variant="outline"
650
+ size="md"
651
+ />
652
+
653
+ // With search
654
+ <StyledDropdown label="Country" options={countryOptions} searchable searchPlaceholder="Filter…" />
655
+
656
+ // Multi-select
657
+ <StyledMultiSelectDropdown label="Tags" options={options} value={selectedTags} onChange={setSelectedTags} />
658
+ ```
659
+
660
+ **DropdownOptionItem:** `value`, `label`, `icon?`, `subtitle?`, `disabled?`, `meta?`
661
+
662
+ **Trigger props:** `variant` (`outline | filled | underline | ghost`), `size` (`sm | md | lg`), `label`, `placeholder`, `disabled`
663
+
664
+ ---
665
+
666
+ ### Popup
667
+
668
+ A versatile overlay with multiple positions, animation styles, and a built-in header.
669
+
670
+ ```tsx
671
+ import { Popup } from 'fluent-styles'
672
+
673
+ // --- Bottom sheet variants ---
674
+ <Popup visible={visible} onClose={hide}>Plain content — no header</Popup>
675
+ <Popup visible={visible} onClose={hide} title="Post options" showClose><ActionList /></Popup>
676
+ <Popup visible={visible} onClose={hide} title="Share post" subtitle="Choose where to send" showClose><ShareList /></Popup>
677
+ <Popup visible={visible} onClose={hide} title="Safe area" showClose safeAreaBottom>…</Popup>
678
+
679
+ // No backdrop
680
+ <Popup visible={visible} onClose={hide} title="No backdrop" overlay={false} showClose>…</Popup>
681
+
682
+ // Prevent dismiss on backdrop tap
683
+ <Popup visible={visible} onClose={hide} title="Tap overlay — nothing" showClose closeOnPressOverlay={false}>…</Popup>
684
+
685
+ // --- Positions ---
686
+ <Popup visible={visible} onClose={hide} position="top" title="Notification" showClose>…</Popup>
687
+ <Popup visible={visible} onClose={hide} position="left" title="Side menu" showClose>…</Popup>
688
+ <Popup visible={visible} onClose={hide} position="right" title="Filters" showClose>…</Popup>
689
+ <Popup visible={visible} onClose={hide} position="center" title="Confirm" showClose round>…</Popup>
690
+
691
+ // --- Animation styles ---
692
+ <Popup visible={visible} onClose={hide} animation="slide" title="Slide" showClose>…</Popup>
693
+ <Popup visible={visible} onClose={hide} animation="fade" title="Fade" showClose>…</Popup>
694
+ <Popup visible={visible} onClose={hide} position="center" animation="scale" title="Scale" showClose round>…</Popup>
695
+ <Popup visible={visible} onClose={hide} animation="none" title="Instant" showClose>…</Popup>
696
+
697
+ // Spring physics
698
+ <Popup visible={visible} onClose={hide} title="Spring" showClose spring={{ damping: 18, stiffness: 280 }}>…</Popup>
699
+
700
+ // --- Corner rounding ---
701
+ <Popup visible={visible} onClose={hide} round title="Default 20 px" showClose>…</Popup>
702
+ <Popup visible={visible} onClose={hide} round={false} title="Square corners" showClose>…</Popup>
703
+ <Popup visible={visible} onClose={hide} round roundRadius={36} title="Large radius" showClose>…</Popup>
704
+
705
+ // --- Render strategy ---
706
+ <Popup visible={visible} onClose={hide} lazyRender title="Lazy (default)" showClose>…</Popup>
707
+ <Popup visible={visible} onClose={hide} destroyOnClose title="Destroy on close" showClose>…</Popup>
708
+
709
+ // --- Color token overrides ---
710
+ <Popup
711
+ visible={visible} onClose={hide}
712
+ title="Dark slate" subtitle="Token overrides" showClose
713
+ colors={{
714
+ background: palettes.blueGray[900],
715
+ overlay: 'rgba(0,0,0,0.75)',
716
+ handle: palettes.blueGray[600],
717
+ headerTitle: palettes.blueGray[100],
718
+ headerSubtitle: palettes.blueGray[400],
719
+ headerBorder: palettes.blueGray[700],
720
+ closeIcon: palettes.blueGray[300],
721
+ closeIconBg: palettes.blueGray[700],
722
+ }}
723
+ >…</Popup>
724
+
725
+ <Popup
726
+ visible={visible} onClose={hide} title="Indigo surface" showClose
727
+ colors={{ background: palettes.indigo[50], headerTitle: palettes.indigo[900], handle: palettes.indigo[300], closeIconBg: palettes.indigo[100] }}
728
+ >…</Popup>
729
+
730
+ // --- Lifecycle callbacks ---
731
+ <Popup
732
+ visible={visible} onClose={hide} title="Lifecycle" showClose
733
+ onOpen={() => console.log('onOpen')}
734
+ onOpened={() => console.log('onOpened — animation done')}
735
+ onClosed={() => console.log('onClosed — animation done')}
736
+ >…</Popup>
737
+ ```
738
+
739
+ | Prop | Type | Default | Description |
740
+ |---|---|---|---|
741
+ | `visible` | `boolean` | — | Controls visibility |
742
+ | `position` | `top \| bottom \| left \| right \| center` | `bottom` | Entry edge |
743
+ | `animation` | `slide \| fade \| scale \| none` | auto | Animation style |
744
+ | `overlay` | `boolean` | `true` | Show backdrop |
745
+ | `closeOnPressOverlay` | `boolean` | `true` | Dismiss on backdrop tap |
746
+ | `round / roundRadius` | `boolean / number` | `true / 20` | Rounded interior corners |
747
+ | `title / subtitle` | `ReactNode` | — | Built-in header content |
748
+ | `showHandle` | `boolean` | auto | Drag handle pill |
749
+ | `showClose` | `boolean` | `false` | Close (×) button |
750
+ | `safeAreaBottom` | `boolean` | `false` | Padding for home bar |
751
+ | `lazyRender` | `boolean` | `true` | Mount children on first open |
752
+ | `destroyOnClose` | `boolean` | `false` | Unmount children when closed |
753
+ | `spring` | `{ damping, stiffness, mass? }` | — | Spring physics override |
754
+ | `colors` | `Partial<PopupColors>` | — | Token overrides |
755
+
756
+ **Lifecycle callbacks:** `onOpen`, `onOpened`, `onClose`, `onClosed`
757
+
758
+ ---
759
+
760
+ ### Drawer
761
+
762
+ A swipeable side panel with built-in navigation list, header, and footer slot.
763
+
764
+ ```tsx
765
+ import { Drawer } from 'fluent-styles'
766
+
767
+ <Drawer
768
+ visible={isOpen}
769
+ side="left"
770
+ title="Menu"
771
+ onClose={() => setOpen(false)}
772
+ navItems={[
773
+ { key: 'home', label: 'Home', icon: '🏠', active: true, onPress: () => navigate('Home') },
774
+ { key: 'profile', label: 'Profile', icon: '👤', onPress: () => navigate('Profile') },
775
+ { key: 'logout', label: 'Logout', icon: '🚪', section: 'Account', onPress: logout },
776
+ ]}
777
+ footer={<UserProfileRow />}
778
+ />
779
+ ```
780
+
781
+ | Prop | Type | Default | Description |
782
+ |---|---|---|---|
783
+ | `visible` | `boolean` | — | Controls visibility |
784
+ | `side` | `left \| right` | `left` | Entry edge |
785
+ | `width` | `number \| string` | `'78%'` | Drawer width |
786
+ | `navItems` | `DrawerNavItem[]` | — | Built-in nav list (auto-grouped by `section`) |
787
+ | `footer` | `ReactNode` | — | Pinned footer content |
788
+ | `swipeToClose` | `boolean` | `true` | Pan gesture dismiss |
789
+ | `swipeThreshold` | `number` | `0.4` | Fraction of width to trigger dismiss |
790
+ | `title / subtitle` | `ReactNode` | — | Header content |
791
+ | `headerRight` | `ReactNode` | — | Header right slot |
792
+ | `colors` | `Partial<DrawerColors>` | — | Token overrides |
793
+
794
+ **DrawerNavItem:** `key`, `label`, `icon?`, `badge?`, `section?`, `active?`, `disabled?`, `onPress?`
795
+
796
+ ---
797
+
798
+ ### Collapse / CollapseGroup
799
+
800
+ Animated accordion panels with full render-slot control.
801
+
802
+ ```tsx
803
+ import { Collapse, CollapseGroup, CollapseItem, palettes, theme } from 'fluent-styles'
804
+
805
+ // --- Variants ---
806
+ <Collapse title="Cell (default)" variant="cell">…</Collapse>
807
+ <Collapse title="Card" subtitle="Shadow + radius" variant="card">…</Collapse>
808
+ <Collapse title="Bordered" variant="bordered">…</Collapse>
809
+ <Collapse title="Ghost" variant="ghost">…</Collapse>
810
+
811
+ // --- Sizes ---
812
+ <Collapse title="Small" variant="bordered" size="sm">…</Collapse>
813
+ <Collapse title="Medium" variant="bordered" size="md">…</Collapse>
814
+ <Collapse title="Large" variant="bordered" size="lg">…</Collapse>
815
+
816
+ // --- Header slots: leading · subtitle · trailing ---
817
+ <Collapse
818
+ variant="card"
819
+ leading={<Text style={{ fontSize: 20 }}>📦</Text>}
820
+ title="Leading icon"
821
+ subtitle="Any ReactNode on the left"
822
+ >…</Collapse>
823
+
824
+ <Collapse
825
+ variant="card"
826
+ title="Trailing badge"
827
+ trailing={<View style={{ backgroundColor: palettes.indigo[500], borderRadius: 10, paddingHorizontal: 8 }}><Text style={{ color: '#fff', fontWeight: '700' }}>NEW</Text></View>}
828
+ >…</Collapse>
829
+
830
+ // --- Active header tint ---
831
+ <Collapse title="Tints when open" variant="bordered" activeHeader>…</Collapse>
832
+
833
+ // --- Disabled ---
834
+ <Collapse title="Premium feature" subtitle="Upgrade to unlock" variant="bordered" disabled>…</Collapse>
835
+
836
+ // --- Default open (uncontrolled) ---
837
+ <Collapse title="Starts expanded" variant="card" defaultCollapse>…</Collapse>
838
+
839
+ // --- Controlled open state ---
840
+ const [open, setOpen] = useState(false)
841
+ <Collapse
842
+ title="Externally driven"
843
+ variant="bordered"
844
+ collapse={open}
845
+ onCollapse={setOpen}
846
+ >…</Collapse>
847
+
848
+ // --- Custom header renderer ---
849
+ <Collapse
850
+ variant="card"
851
+ renderHeader={(open) => (
852
+ <View style={{ padding: 14, backgroundColor: open ? '#eef2ff' : '#f2f2f7' }}>
853
+ <Text style={{ fontWeight: '600' }}>{open ? '▲ Open' : '▼ Closed'}</Text>
854
+ </View>
855
+ )}
856
+ >…</Collapse>
857
+
858
+ // --- Custom header right (keep title, replace right side) ---
859
+ <Collapse
860
+ title="Custom right"
861
+ variant="bordered"
862
+ renderHeaderRight={(open, chevron) => (
863
+ <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
864
+ <Text style={{ color: open ? '#6366f1' : '#8e8e93' }}>{open ? 'Open' : 'Closed'}</Text>
865
+ {chevron}
866
+ </View>
867
+ )}
868
+ >…</Collapse>
869
+
870
+ // --- Color token overrides ---
871
+ <Collapse
872
+ title="Dark slate theme"
873
+ variant="card"
874
+ colors={{
875
+ background: theme.colors.blueGray[900],
876
+ border: theme.colors.blueGray[700],
877
+ titleColor: theme.colors.blueGray[100],
878
+ subtitleColor: theme.colors.blueGray[400],
879
+ iconColor: theme.colors.blueGray[400],
880
+ activeHeaderBg: palettes.blueGray[800],
881
+ }}
882
+ >…</Collapse>
883
+
884
+ <Collapse
885
+ title="Warm amber theme"
886
+ variant="bordered"
887
+ colors={{
888
+ background: palettes.amber[50],
889
+ border: palettes.amber[300],
890
+ titleColor: palettes.amber[900],
891
+ iconColor: palettes.amber[500],
892
+ activeHeaderBg: palettes.amber[100],
893
+ }}
894
+ >…</Collapse>
895
+
896
+ // --- CollapseGroup: multi-open with defaultActiveKey array ---
897
+ <CollapseGroup variant="bordered" defaultActiveKey={['shipping']}>
898
+ <CollapseItem itemKey="shipping" title="Shipping" subtitle="2–5 business days">…</CollapseItem>
899
+ <CollapseItem itemKey="returns" title="Returns" subtitle="30-day policy">…</CollapseItem>
900
+ <CollapseItem itemKey="sizing" title="Size guide">…</CollapseItem>
901
+ </CollapseGroup>
902
+
903
+ // --- CollapseGroup: accordion FAQ with icons ---
904
+ <CollapseGroup accordion variant="card" defaultActiveKey="q1" style={{ gap: 8 }}>
905
+ <CollapseItem itemKey="q1" leading={<Text style={{ fontSize: 18 }}>💳</Text>} title="Accepted payment methods">…</CollapseItem>
906
+ <CollapseItem itemKey="q2" leading={<Text style={{ fontSize: 18 }}>🔒</Text>} title="Is my data secure?">…</CollapseItem>
907
+ <CollapseItem itemKey="q3" leading={<Text style={{ fontSize: 18 }}>📞</Text>} title="How do I contact support?">…</CollapseItem>
908
+ </CollapseGroup>
909
+ ```
910
+
911
+ | Prop | Type | Default | Description |
912
+ |---|---|---|---|
913
+ | `title / subtitle` | `ReactNode` | — | Header content |
914
+ | `leading / trailing` | `ReactNode` | — | Header side slots |
915
+ | `variant` | `cell \| card \| bordered \| ghost` | `cell` | Visual style |
916
+ | `size` | `sm \| md \| lg` | `md` | Padding scale |
917
+ | `collapse / defaultCollapse` | `boolean` | — | Controlled / uncontrolled open state |
918
+ | `onCollapse` | `(open: boolean) => void` | — | Toggle callback |
919
+ | `activeHeader` | `boolean` | `false` | Tint header when open |
920
+ | `disabled` | `boolean` | `false` | Prevent interaction |
921
+ | `lazyRender` | `boolean` | `true` | Mount body on first expand |
922
+ | `destroyOnClose` | `boolean` | `false` | Unmount body when collapsed |
923
+ | `renderHeader` | `(open: boolean) => ReactNode` | — | Replace the entire header |
924
+ | `renderHeaderRight` | `(open, chevron) => ReactNode` | — | Replace only the right side of the header |
925
+ | `colors` | `Partial<CollapseColors>` | — | Token overrides |
926
+
927
+ `CollapseGroup` additional props: `accordion` (single-open), `defaultActiveKey` (`string \| string[]`)
928
+
929
+ ---
930
+
931
+ ### TabBar
932
+
933
+ A feature-rich animated tab bar with badge, icon, and indicator support.
934
+
935
+ ```tsx
936
+ import { TabBar, TabItem, palettes } from 'fluent-styles'
937
+
938
+ // --- Bottom nav with icons + dot badges ---
939
+ type Nav = 'home' | 'explore' | 'activity' | 'profile'
940
+ const NAV_TABS: TabItem<Nav>[] = [
941
+ { value: 'home', label: 'Home', iconRender: (c) => <HomeIcon color={c} /> },
942
+ { value: 'explore', label: 'Explore', iconRender: (c) => <SearchIcon color={c} />, badge: 3 },
943
+ { value: 'activity', label: 'Activity', iconRender: (c) => <BellIcon color={c} />, badge: '' }, // '' = dot badge
944
+ { value: 'profile', label: 'Profile', iconRender: (c) => <UserIcon color={c} /> },
945
+ ]
946
+ <TabBar options={NAV_TABS} value={nav} onChange={setNav} indicator="dot" showBorder />
947
+
948
+ // --- Animated underline indicator ---
949
+ <TabBar options={SIMPLE_TABS} value={seg} onChange={setSeg} indicator="line" showBorder />
950
+
951
+ // --- Sliding pill indicator ---
952
+ <TabBar
953
+ options={SIMPLE_TABS}
954
+ defaultValue="week"
955
+ indicator="pill"
956
+ colors={{ background: palettes.indigo[50], activeText: palettes.indigo[700], indicator: palettes.indigo[200], text: palettes.indigo[400] }}
957
+ />
958
+
959
+ // --- Scrollable tabs (many items) ---
960
+ <TabBar options={MANY_TABS} value={cat} onChange={setCat} tabAlign="scroll" indicator="line" showBorder />
961
+
962
+ // --- Disabled tabs ---
963
+ const TABS_WITH_DISABLED: TabItem<string>[] = [
964
+ { value: 'available', label: 'Available' },
965
+ { value: 'locked', label: 'Locked', disabled: true },
966
+ { value: 'open', label: 'Open' },
967
+ ]
968
+ <TabBar options={TABS_WITH_DISABLED} value={active} onChange={setActive} indicator="line" showBorder />
969
+
970
+ // --- Solid / chip variant ---
971
+ <TabBar
972
+ options={SIMPLE_TABS}
973
+ defaultValue="week"
974
+ variant="solid"
975
+ indicator="pill"
976
+ colors={{
977
+ background: palettes.gray[100],
978
+ activeChipBg: '#ffffff',
979
+ activeChipText: palettes.gray[900],
980
+ indicator: palettes.coolGray[200],
981
+ text: palettes.gray[500],
982
+ }}
983
+ />
984
+
985
+ // --- Numeric values (step wizard) ---
986
+ type Step = 1 | 2 | 3
987
+ const STEPS: TabItem<Step>[] = [
988
+ { value: 1, label: 'Step 1' },
989
+ { value: 2, label: 'Step 2' },
990
+ { value: 3, label: 'Step 3' },
991
+ ]
992
+ <TabBar
993
+ options={STEPS}
994
+ value={step}
995
+ onChange={setStep}
996
+ indicator="line"
997
+ colors={{ activeText: palettes.violet[600], indicator: palettes.violet[600], text: palettes.gray[400] }}
998
+ showBorder
999
+ />
1000
+
1001
+ // --- Custom indicator sizing ---
1002
+ <TabBar options={SIMPLE_TABS} defaultValue="month" indicator="line" indicatorWidth={24} indicatorHeight={3} indicatorRadius={3} showBorder />
1003
+
1004
+ // --- Label scale on active tab ---
1005
+ <TabBar options={SIMPLE_TABS} defaultValue="week" indicator="line" labelBulge={1.15} showBorder />
1006
+
1007
+ // --- Color overrides: green theme ---
1008
+ <TabBar
1009
+ options={SIMPLE_TABS}
1010
+ defaultValue="day"
1011
+ indicator="line"
1012
+ showBorder
1013
+ colors={{ background: palettes.green[50], activeText: palettes.green[700], indicator: palettes.green[500], text: palettes.green[400], border: palettes.green[200] }}
1014
+ />
1015
+
1016
+ // --- Color overrides: dark slate ---
1017
+ <TabBar
1018
+ options={NAV_TABS}
1019
+ defaultValue="home"
1020
+ indicator="dot"
1021
+ showBorder
1022
+ colors={{ background: palettes.blueGray[900], activeText: palettes.indigo[400], indicator: palettes.indigo[400], text: palettes.blueGray[400], border: palettes.blueGray[700], badge: palettes.rose[400] }}
1023
+ />
1024
+
1025
+ // --- Large font / taller bar ---
1026
+ <TabBar options={SIMPLE_TABS} defaultValue="week" indicator="line" fontSize={17} height={52} showBorder />
1027
+ ```
1028
+
1029
+ | Prop | Type | Default | Description |
1030
+ |---|---|---|---|
1031
+ | `options` | `TabItem<T>[]` | — | Tab definitions |
1032
+ | `value / defaultValue` | `T` | — | Controlled / uncontrolled value |
1033
+ | `onChange` | `(val: T) => void` | — | Change callback |
1034
+ | `variant` | `default \| underline \| card \| solid` | `default` | Visual preset |
1035
+ | `indicator` | `false \| line \| pill \| dot` | `false` | Animated indicator style |
1036
+ | `indicatorColor` | `ColorValue` | — | Indicator colour override |
1037
+ | `indicatorWidth` | `number` | auto | Fixed indicator width (0 = full tab width) |
1038
+ | `indicatorHeight` | `number` | `2` | Indicator thickness |
1039
+ | `indicatorRadius` | `number` | auto | Indicator border radius |
1040
+ | `tabAlign` | `center \| scroll` | `center` | Equal-width or scrolling tabs |
1041
+ | `labelBulge` | `number \| boolean` | `1` | Active label scale factor |
1042
+ | `fontSize` | `number` | — | Label font size |
1043
+ | `height` | `number` | — | Bar height override |
1044
+ | `showBorder` | `boolean` | `false` | Persistent bottom border |
1045
+ | `colors` | `Partial<TabBarColors>` | — | Token overrides |
1046
+
1047
+ **TabItem:** `value`, `label`, `badge?` (`number` = count, `''` = dot), `iconRender?`, `disabled?`
1048
+
1049
+ ---
1050
+
1051
+ ### StyledDivider
1052
+
1053
+ A simple horizontal rule.
1054
+
1055
+ ```tsx
1056
+ import { StyledDivider } from 'fluent-styles'
1057
+
1058
+ <StyledDivider />
1059
+ <StyledDivider borderBottomColor="#e4e4e7" marginVertical={8} />
1060
+ ```
1061
+
1062
+ ---
1063
+
1064
+ ### StyledSeperator
1065
+
1066
+ A horizontal row with left and optional right label — ideal for section headers.
1067
+
1068
+ ```tsx
1069
+ import { StyledSeperator } from 'fluent-styles'
1070
+
1071
+ <StyledSeperator leftLabel="Recent" rightLabel="See all" marginVertical={8} />
1072
+ ```
1073
+
1074
+ Props: `leftLabel`, `leftLabelProps`, `rightLabel`, `rightLabelProps`, plus all `StackProps`.
1075
+
1076
+ ---
1077
+
1078
+ ### Stack
1079
+
1080
+ A layout primitive for row and column arrangements.
1081
+
1082
+ ```tsx
1083
+ import { Stack } from 'fluent-styles'
1084
+
1085
+ // Vertical (column)
1086
+ <Stack gap={12}>
1087
+ <StyledText>Item 1</StyledText>
1088
+ <StyledText>Item 2</StyledText>
1089
+ </Stack>
1090
+
1091
+ // Horizontal (row)
1092
+ <Stack horizontal alignItems="center" gap={8}>
1093
+ <Avatar />
1094
+ <StyledText>Jane Doe</StyledText>
1095
+ </Stack>
1096
+ ```
1097
+
1098
+ ---
1099
+
1100
+ ### StyledText
1101
+
1102
+ A variant-aware Text component accepting `TextStyle` props directly.
1103
+
1104
+ ```tsx
1105
+ import { StyledText } from 'fluent-styles'
1106
+
1107
+ <StyledText fontSize={18} fontWeight="700" color="#1c1c1e">Heading</StyledText>
1108
+ <StyledText link>Click here</StyledText>
1109
+ <StyledText textAlign="center" color="#6b7280">Muted caption</StyledText>
1110
+ ```
1111
+
1112
+ ---
1113
+
1114
+ ### StyledPressable
1115
+
1116
+ A styled `Pressable` accepting flat `ViewStyle` props.
1117
+
1118
+ ```tsx
1119
+ import { StyledPressable } from 'fluent-styles'
1120
+
1121
+ <StyledPressable padding={12} borderRadius={8} backgroundColor="#f4f4f5" onPress={handlePress}>
1122
+ <StyledText>Press me</StyledText>
1123
+ </StyledPressable>
1124
+ ```
1125
+
1126
+ ---
1127
+
1128
+ ### StyledPage / StyledScrollView
1129
+
1130
+ Base layout containers.
1131
+
1132
+ ```tsx
1133
+ import { StyledPage, StyledScrollView } from 'fluent-styles'
1134
+
1135
+ <StyledPage flex={1} backgroundColor="#f8f8f8">
1136
+ <StyledScrollView contentContainerStyle={{ padding: 16 }}>
1137
+ <MyContent />
1138
+ </StyledScrollView>
1139
+ </StyledPage>
1140
+ ```
1141
+
1142
+ ---
1143
+
1144
+ ### StyledSafeAreaView
1145
+
1146
+ A styled wrapper around `SafeAreaView`.
1147
+
1148
+ ```tsx
1149
+ import { StyledSafeAreaView } from 'fluent-styles'
1150
+
1151
+ <StyledSafeAreaView flex={1} backgroundColor="#fff">
1152
+ <App />
1153
+ </StyledSafeAreaView>
1154
+ ```
1155
+
1156
+ ---
1157
+
1158
+ ### Spacer
1159
+
1160
+ Inserts fixed or flexible whitespace.
1161
+
1162
+ ```tsx
1163
+ import { Spacer } from 'fluent-styles'
1164
+
1165
+ <Spacer height={16} />
1166
+ <Spacer flex={1} /> {/* fills remaining space */}
1167
+ ```
1168
+
1169
+ ---
1170
+
1171
+ ### StyledShape
1172
+
1173
+ A shaped container for icon chips, avatars, and dot indicators.
1174
+
1175
+ ```tsx
1176
+ import { StyledShape } from 'fluent-styles'
1177
+
1178
+ <StyledShape size={40} borderRadius={20} backgroundColor="#6366f1">
1179
+ <StyledText color="#fff">A</StyledText>
1180
+ </StyledShape>
1181
+ ```
1182
+
1183
+ ---
1184
+
1185
+ ### Loader
1186
+
1187
+ A loading indicator with four animation variants, optional overlay, and label.
1188
+
1189
+ ```tsx
1190
+ import { Loader } from 'fluent-styles'
1191
+
1192
+ <Loader variant="spinner" />
1193
+ <Loader variant="dots" color="#6366f1" label="Saving…" />
1194
+ <Loader variant="pulse" overlay />
1195
+ <Loader variant="circular" label="Loading…" theme="dark" />
1196
+ ```
1197
+
1198
+ | Prop | Type | Default | Description |
1199
+ |---|---|---|---|
1200
+ | `variant` | `spinner \| pulse \| dots \| circular` | `spinner` | Animation style |
1201
+ | `label` | `string` | — | Text below the indicator |
1202
+ | `color` | `string` | — | Indicator tint colour |
1203
+ | `overlay` | `boolean` | `false` | Full-screen dimmed backdrop |
1204
+ | `theme` | `light \| dark \| system` | `system` | Colour scheme |
1205
+ | `colors` | `Partial<LoaderColors>` | — | Fine-grained token overrides |
1206
+
1207
+ ---
1208
+
1209
+ ### StyledCircularProgress
1210
+
1211
+ An animated SVG ring progress indicator with four visual variants, five preset sizes, centre label modes, gradient support, and full colour customisation.
1212
+
1213
+ ```tsx
1214
+ import { StyledCircularProgress } from 'fluent-styles'
1215
+
1216
+ // Basic — shows percentage
1217
+ <StyledCircularProgress value={72} />
1218
+
1219
+ // Fraction display
1220
+ <StyledCircularProgress value={18} total={25} display="fraction" />
1221
+
1222
+ // With label and sublabel
1223
+ <StyledCircularProgress
1224
+ value={72}
1225
+ display="percent"
1226
+ label="Tasks"
1227
+ sublabel="this week"
1228
+ size="lg"
1229
+ />
1230
+
1231
+ // Gradient variant
1232
+ <StyledCircularProgress
1233
+ value={68}
1234
+ variant="gradient"
1235
+ colors={{
1236
+ gradientFrom: '#6366f1',
1237
+ gradientTo: '#22d3ee',
1238
+ }}
1239
+ />
1240
+
1241
+ // Dashboard (half-circle gauge)
1242
+ <StyledCircularProgress value={55} variant="dashboard" size="xl" />
1243
+
1244
+ // Custom diameter and stroke
1245
+ <StyledCircularProgress value={55} diameter={120} strokeWidth={24} display="percent" />
1246
+
1247
+ // Colour overrides
1248
+ <StyledCircularProgress
1249
+ value={82}
1250
+ display="percent"
1251
+ label="Health"
1252
+ size="md"
1253
+ colors={{
1254
+ arc: theme.colors.green[500],
1255
+ track: theme.colors.green[100],
1256
+ label: theme.colors.green[700],
1257
+ sublabel: theme.colors.green[400],
1258
+ }}
1259
+ />
1260
+
1261
+ // Custom centre content (overrides display/label)
1262
+ <StyledCircularProgress value={55} display="none" size="lg">
1263
+ <Stack alignItems="center" gap={2}>
1264
+ <StyledText fontSize={14}>❤️</StyledText>
1265
+ <StyledText fontSize={12} fontWeight={theme.fontWeight.bold} color="#f43f5e">
1266
+ 55 bpm
1267
+ </StyledText>
1268
+ </Stack>
1269
+ </StyledCircularProgress>
1270
+
1271
+ // Controlled value with animation
1272
+ <StyledCircularProgress
1273
+ value={controlled}
1274
+ display="percent"
1275
+ label="Progress"
1276
+ sublabel={`${controlled} / 100`}
1277
+ size="xl"
1278
+ variant="gradient"
1279
+ duration={600}
1280
+ />
1281
+
1282
+ // No animation
1283
+ <StyledCircularProgress value={90} animated={false} display="percent" />
1284
+
1285
+ // On a dark surface
1286
+ <StyledCircularProgress
1287
+ value={72}
1288
+ variant="gradient"
1289
+ display="percent"
1290
+ label="Progress"
1291
+ colors={{
1292
+ gradientFrom: '#818cf8',
1293
+ gradientTo: '#22d3ee',
1294
+ track: 'rgba(255,255,255,0.12)',
1295
+ label: '#f4f4f5',
1296
+ sublabel: 'rgba(255,255,255,0.5)',
1297
+ }}
1298
+ />
1299
+ ```
1300
+
1301
+ #### Props
1302
+
1303
+ | Prop | Type | Default | Description |
1304
+ |---|---|---|---|
1305
+ | `value` | `number` | **required** | Current progress value |
1306
+ | `total` | `number` | `100` | Maximum value |
1307
+ | `display` | `'percent' \| 'fraction' \| 'value' \| 'label' \| 'none'` | `'percent'` | What to render in the centre |
1308
+ | `label` | `string` | — | Primary label inside the ring |
1309
+ | `sublabel` | `string` | — | Secondary line below the primary label |
1310
+ | `variant` | `'default' \| 'ghost' \| 'gradient' \| 'dashboard'` | `'default'` | Visual style |
1311
+ | `size` | `'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | Preset diameter |
1312
+ | `diameter` | `number` | — | Pixel diameter — overrides `size` |
1313
+ | `strokeWidth` | `number` | — | Arc thickness in px — auto-scaled when omitted |
1314
+ | `lineCap` | `'round' \| 'butt' \| 'square'` | `'round'` | Arc end cap style |
1315
+ | `animated` | `boolean` | `true` | Animate from 0 to `value` on mount / value change |
1316
+ | `duration` | `number` | `900` | Animation duration in ms |
1317
+ | `colors` | `Partial<CircularProgressColors>` | — | Fine-grained colour overrides (see below) |
1318
+ | `children` | `ReactNode` | — | Custom centre content — overrides `display`, `label`, `sublabel` |
1319
+
1320
+ #### Size presets
1321
+
1322
+ | Size | Diameter | Stroke |
1323
+ |---|---|---|
1324
+ | `xs` | 48 px | 4 px |
1325
+ | `sm` | 64 px | 5 px |
1326
+ | `md` | 80 px | 6 px |
1327
+ | `lg` | 100 px | 7 px |
1328
+ | `xl` | 128 px | 8 px |
1329
+
1330
+ #### Variants
1331
+
1332
+ | Variant | Description |
1333
+ |---|---|
1334
+ | `default` | Coloured arc on a light grey track |
1335
+ | `ghost` | Arc only — no background track |
1336
+ | `gradient` | Two-stop linear gradient arc (uses `gradientFrom` / `gradientTo`) |
1337
+ | `dashboard` | Half-circle gauge — flat side at the bottom |
1338
+
1339
+ #### `CircularProgressColors`
1340
+
1341
+ | Token | Default | Controls |
1342
+ |---|---|---|
1343
+ | `arc` | `indigo[500]` | Progress arc fill |
1344
+ | `track` | `gray[200]` | Background track ring |
1345
+ | `label` | `gray[800]` | Primary centre text |
1346
+ | `sublabel` | `gray[400]` | Secondary centre text |
1347
+ | `gradientFrom` | `violet[500]` | Gradient start — `gradient` variant only |
1348
+ | `gradientTo` | `cyan[400]` | Gradient end — `gradient` variant only |
1349
+
1350
+ #### Real-world example — onboarding card
1351
+
1352
+ ```tsx
1353
+ <Stack
1354
+ backgroundColor={theme.colors.indigo[600]}
1355
+ borderRadius={16}
1356
+ horizontal
1357
+ gap={20}
1358
+ paddingVertical={32}
1359
+ paddingHorizontal={16}
1360
+ alignItems="center"
1361
+ >
1362
+ <StyledCircularProgress
1363
+ value={3}
1364
+ total={5}
1365
+ display="fraction"
1366
+ label="done"
1367
+ size="lg"
1368
+ colors={{
1369
+ arc: theme.colors.white,
1370
+ track: 'rgba(255,255,255,0.2)',
1371
+ label: theme.colors.white,
1372
+ sublabel: 'rgba(255,255,255,0.65)',
1373
+ }}
1374
+ />
1375
+ <Stack vertical flex={1} gap={4}>
1376
+ <StyledText fontSize={16} fontWeight={theme.fontWeight.bold} color={theme.colors.white}>
1377
+ Getting started
1378
+ </StyledText>
1379
+ <StyledText fontSize={13} color="rgba(255,255,255,0.75)">
1380
+ Complete 2 more steps to unlock all features.
1381
+ </StyledText>
1382
+ </Stack>
1383
+ </Stack>
1384
+ ```
1385
+
1386
+ ---
1387
+
1388
+ ### StyledChip
1389
+
1390
+ A multi-variant chip/tag component with controlled and uncontrolled selection, animated checkmarks, and six visual variants.
1391
+
1392
+ ```tsx
1393
+ import { StyledChip } from 'fluent-styles'
1394
+ ```
1395
+
1396
+ #### Variants
1397
+
1398
+ | Variant | Description |
1399
+ |---|---|
1400
+ | `outlined` | Border + tinted bg when selected (default) |
1401
+ | `filled` | Solid background, changes tone on select |
1402
+ | `smooth` | Soft grey background, no border |
1403
+ | `ingredient` | Dark-bg when selected (recipe/filter chips) |
1404
+ | `likeable` | Pink heart chip — toggles like state |
1405
+ | `icon` | Leading icon with accent styling |
1406
+
1407
+ #### Size presets
1408
+
1409
+ | Size | Padding H | Padding V | Font | Icon | Radius |
1410
+ |---|---|---|---|---|---|
1411
+ | `sm` | 10 | 5 | 11 | 12 | 20 |
1412
+ | `md` | 14 | 8 | 13 | 14 | 24 |
1413
+ | `lg` | 18 | 11 | 15 | 16 | 28 |
1414
+
1415
+ #### Props
1416
+
1417
+ | Prop | Type | Default | Description |
1418
+ |---|---|---|---|
1419
+ | `label` | `string` | — | Chip text |
1420
+ | `variant` | `ChipVariant` | `'outlined'` | Visual style |
1421
+ | `size` | `ChipSize` | `'md'` | Size preset |
1422
+ | `selected` | `boolean` | — | Controlled selection state |
1423
+ | `defaultSelected` | `boolean` | `false` | Uncontrolled initial state |
1424
+ | `onPress` | `(selected: boolean) => void` | — | Fires with new selection value |
1425
+ | `color` | `string` | theme default | Accent colour (border, text, icon) |
1426
+ | `bgColor` | `string` | variant default | Fill background |
1427
+ | `icon` | `React.ReactNode` | — | Leading icon node (used with `'icon'` variant) |
1428
+ | `showCheck` | `boolean` | `true` | Show checkmark when selected |
1429
+ | `disabled` | `boolean` | `false` | Reduces opacity, disables press |
1430
+ | `borderRadius` | `number` | size preset | Override border radius |
1431
+
1432
+ #### Usage
1433
+
1434
+ ```tsx
1435
+ import React, { useState } from 'react'
1436
+ import { StyledChip, Stack } from 'fluent-styles'
1437
+ import Icon from 'react-native-vector-icons/Feather'
1438
+
1439
+ // ── Multi-select toggle helper ────────────────────────────────────────────────
1440
+ // A common pattern: maintain a string[] of selected labels and toggle them.
1441
+ const [selected, setSelected] = useState<string[]>(['Hacktoberfest'])
1442
+
1443
+ const toggle = (label: string) =>
1444
+ setSelected((prev) =>
1445
+ prev.includes(label) ? prev.filter((l) => l !== label) : [...prev, label]
1446
+ )
1447
+
1448
+ // ── 1. Outlined — multi-select filter bar ─────────────────────────────────────
1449
+ <Stack gap={10}>
1450
+ <Stack horizontal gap={8} flexWrap="wrap">
1451
+ {[
1452
+ { label: 'Enhancement', color: '#9e9e9e' },
1453
+ { label: 'Trends', color: '#ff9800' },
1454
+ ].map(({ label, color }) => (
1455
+ <StyledChip
1456
+ key={label}
1457
+ label={label}
1458
+ variant="outlined"
1459
+ color={color}
1460
+ selected={selected.includes(label)}
1461
+ onPress={() => toggle(label)}
1462
+ />
1463
+ ))}
1464
+ </Stack>
1465
+ <Stack horizontal gap={8} flexWrap="wrap">
1466
+ {[
1467
+ { label: 'Rubi Kapustu', color: '#2196f3' },
1468
+ { label: 'Hacktoberfest', color: '#4caf50' },
1469
+ ].map(({ label, color }) => (
1470
+ <StyledChip
1471
+ key={label}
1472
+ label={label}
1473
+ variant="outlined"
1474
+ color={color}
1475
+ selected={selected.includes(label)}
1476
+ onPress={() => toggle(label)}
1477
+ />
1478
+ ))}
1479
+ </Stack>
1480
+ <Stack horizontal gap={8} flexWrap="wrap">
1481
+ {[
1482
+ { label: 'Limited', color: '#e65100' },
1483
+ { label: 'Taken', color: '#e91e63' },
1484
+ ].map(({ label, color }) => (
1485
+ <StyledChip key={label} label={label} variant="outlined" color={color}
1486
+ selected={selected.includes(label)} onPress={() => toggle(label)} />
1487
+ ))}
1488
+ </Stack>
1489
+ </Stack>
1490
+
1491
+ // ── 2. Ingredient — recipe / dietary filter ───────────────────────────────────
1492
+ const [ingredients, setIngredients] = useState(['Cinnamon', 'Nut'])
1493
+
1494
+ {[['Cheese', 'Vanilla', 'Chocolate', 'Egg'],
1495
+ ['Honey', 'Milk', 'Banana', 'Nut'],
1496
+ ['Cinnamon', 'Tomato', 'Yogurt'],
1497
+ ].map((row, ri) => (
1498
+ <Stack key={ri} horizontal gap={8} flexWrap="wrap">
1499
+ {row.map((label) => (
1500
+ <StyledChip
1501
+ key={label}
1502
+ label={label}
1503
+ variant="ingredient"
1504
+ selected={ingredients.includes(label)}
1505
+ onPress={() => toggle(label)}
1506
+ />
1507
+ ))}
1508
+ </Stack>
1509
+ ))}
1510
+
1511
+ // ── 3. Filled — label/status chips ────────────────────────────────────────────
1512
+ <Stack horizontal gap={8} flexWrap="wrap">
1513
+ <StyledChip label="Hacktoberfest" variant="filled" bgColor="#e8f5e9" color="#388e3c" />
1514
+ <StyledChip label="Question" variant="filled" bgColor="#fff3e0" color="#f57c00" />
1515
+ <StyledChip label="Enhancement" variant="filled" bgColor="#f3e5f5" color="#7b1fa2" />
1516
+ {/* Selected filled chip with checkmark */}
1517
+ <StyledChip
1518
+ label="Taken"
1519
+ variant="filled"
1520
+ bgColor="#e91e8c"
1521
+ color="#fff"
1522
+ defaultSelected
1523
+ showCheck
1524
+ />
1525
+ </Stack>
1526
+
1527
+ // ── 4. Icon chips — dynamic icon colour based on selected state ───────────────
1528
+ const [activeIcons, setActiveIcons] = useState<string[]>(['Social Media'])
1529
+
1530
+ <Stack horizontal gap={8} flexWrap="wrap">
1531
+ {/* Solid active: bgColor becomes fill when selected */}
1532
+ <StyledChip
1533
+ label="Social Media"
1534
+ variant="icon"
1535
+ icon={
1536
+ <Icon
1537
+ name="refresh-cw"
1538
+ size={14}
1539
+ color={activeIcons.includes('Social Media') ? '#fff' : '#2e7d32'}
1540
+ />
1541
+ }
1542
+ color="#2e7d32"
1543
+ bgColor="#2e7d32"
1544
+ selected={activeIcons.includes('Social Media')}
1545
+ onPress={() => toggle('Social Media')}
1546
+ />
1547
+ <StyledChip
1548
+ label="Pin"
1549
+ variant="icon"
1550
+ icon={<Icon name="map-pin" size={14} color="#2e7d32" />}
1551
+ color="#2e7d32"
1552
+ bgColor="#e8f5e9"
1553
+ selected={activeIcons.includes('Pin')}
1554
+ onPress={() => toggle('Pin')}
1555
+ />
1556
+ <StyledChip
1557
+ label="Activity"
1558
+ variant="icon"
1559
+ icon={<Icon name="activity" size={14} color="#2e7d32" />}
1560
+ color="#2e7d32"
1561
+ bgColor="#e8f5e9"
1562
+ selected={activeIcons.includes('Activity')}
1563
+ onPress={() => toggle('Activity')}
1564
+ />
1565
+ </Stack>
1566
+
1567
+ // Icon chips — mixed accent colour palette
1568
+ <Stack horizontal gap={8} flexWrap="wrap">
1569
+ <StyledChip label="Annotation" variant="icon"
1570
+ icon={<Icon name="edit-3" size={14} color="#5c6bc0" />} color="#5c6bc0" bgColor="#e8eaf6" />
1571
+ <StyledChip label="Laboratory" variant="icon"
1572
+ icon={<Icon name="zap" size={14} color="#5c6bc0" />} color="#5c6bc0" bgColor="#e8eaf6" />
1573
+ <StyledChip label="History" variant="icon"
1574
+ icon={<Icon name="clock" size={14} color="#5c6bc0" />} color="#5c6bc0" bgColor="#e8eaf6" />
1575
+ {/* Solid active — pre-selected */}
1576
+ <StyledChip
1577
+ label="Globe"
1578
+ variant="icon"
1579
+ icon={<Icon name="globe" size={14} color="#fff" />}
1580
+ color="#fff"
1581
+ bgColor="#3f51b5"
1582
+ selected
1583
+ onPress={() => {}}
1584
+ />
1585
+ </Stack>
1586
+
1587
+ // ── 5. Likeable — topic interest chips ───────────────────────────────────────
1588
+ const [liked, setLiked] = useState(['Big Data', 'New Technology'])
1589
+
1590
+ {[['Cryptocurrency', 'Big Data'],
1591
+ ['Software Development'],
1592
+ ['New Technology', 'Gadgets'],
1593
+ ['Technology Startups'],
1594
+ ].map((row, ri) => (
1595
+ <Stack key={ri} horizontal gap={8} flexWrap="wrap">
1596
+ {row.map((label) => (
1597
+ <StyledChip
1598
+ key={label}
1599
+ label={label}
1600
+ variant="likeable"
1601
+ selected={liked.includes(label)}
1602
+ onPress={() => toggle(label)}
1603
+ />
1604
+ ))}
1605
+ </Stack>
1606
+ ))}
1607
+
1608
+ // ── 6. Size variants side-by-side ────────────────────────────────────────────
1609
+ <Stack gap={10}>
1610
+ <Stack horizontal gap={8} alignItems="center">
1611
+ <StyledChip label="Small" variant="outlined" size="sm" color="#2196f3" />
1612
+ <StyledChip label="Medium" variant="outlined" size="md" color="#2196f3" />
1613
+ <StyledChip label="Large" variant="outlined" size="lg" color="#2196f3" />
1614
+ </Stack>
1615
+ <Stack horizontal gap={8} alignItems="center">
1616
+ <StyledChip label="Small" variant="ingredient" size="sm" defaultSelected />
1617
+ <StyledChip label="Medium" variant="ingredient" size="md" defaultSelected />
1618
+ <StyledChip label="Large" variant="ingredient" size="lg" defaultSelected />
1619
+ </Stack>
1620
+ </Stack>
1621
+
1622
+ // ── 7. Disabled state ────────────────────────────────────────────────────────
1623
+ <Stack horizontal gap={8} flexWrap="wrap">
1624
+ <StyledChip label="Outlined" variant="outlined" color="#2196f3" disabled />
1625
+ <StyledChip label="Filled" variant="filled" bgColor="#e91e63" color="#fff" disabled />
1626
+ <StyledChip label="Ingredient" variant="ingredient" disabled />
1627
+ <StyledChip label="Likeable" variant="likeable" disabled />
1628
+ </Stack>
1629
+ ```
1630
+
1631
+ ---
1632
+
1633
+ ### StyledBar
1634
+
1635
+ An animated SVG bar chart with gradient active bars, optional hatch texture on inactive bars, and a floating tooltip. Backed by `react-native-svg`.
1636
+
1637
+ ```tsx
1638
+ import { StyledBar } from 'fluent-styles'
1639
+ ```
1640
+
1641
+ #### `StyledBarDatum`
1642
+
1643
+ | Field | Type | Description |
1644
+ |---|---|---|
1645
+ | `label` | `string` | X-axis label |
1646
+ | `value` | `number \| null` | Bar height value; `null` renders a grey placeholder bar |
1647
+ | `active` | `boolean` | Marks the active/highlighted bar (renders gradient + tooltip) |
1648
+
1649
+ #### `StyledBarColors`
1650
+
1651
+ | Field | Default | Description |
1652
+ |---|---|---|
1653
+ | `inactiveBar` | `gray[200]` | Inactive bar fill |
1654
+ | `hatchLine` | `rgba(0,0,0,0.07)` | Hatch stripe colour on inactive bars |
1655
+ | `activeTop` | `#d4f53c` | Active bar gradient top |
1656
+ | `activeBottom` | `#a8c820` | Active bar gradient bottom |
1657
+ | `tooltipBg` | `gray[900]` | Tooltip bubble background |
1658
+ | `tooltipText` | `white` | Tooltip text colour |
1659
+ | `activeLabelColor` | `gray[900]` | Label colour for active bar |
1660
+ | `inactiveLabelColor` | `gray[400]` | Label colour for inactive bars |
1661
+
1662
+ #### Props
1663
+
1664
+ | Prop | Type | Default | Description |
1665
+ |---|---|---|---|
1666
+ | `data` | `StyledBarDatum[]` | — | Array of bar data |
1667
+ | `maxValue` | `number` | max of values | Explicit Y-axis ceiling |
1668
+ | `width` | `number` | screen width − padding | SVG canvas width in px |
1669
+ | `containerPaddingHorizontal` | `number` | `80` | Horizontal padding to subtract from screen width |
1670
+ | `height` | `number` | `180` | Plot area height in px |
1671
+ | `barWidthRatio` | `number` | `0.62` | Bar width as fraction of slot width |
1672
+ | `labelHeight` | `number` | `28` | Height reserved below bars for labels |
1673
+ | `showHatch` | `boolean` | `true` | Render hatch texture on inactive bars |
1674
+ | `hatchSpacing` | `number` | `8` | Pixel gap between hatch lines |
1675
+ | `tooltipLabel` | `string` | auto from active value | Override tooltip text |
1676
+ | `unit` | `string` | `''` | Unit suffix appended to auto tooltip (e.g. `'min'`) |
1677
+ | `colors` | `StyledBarColors` | lime theme | Colour overrides |
1678
+ | `animated` | `boolean` | `true` | Animate bars growing from zero on mount |
1679
+ | `animationDuration` | `number` | `600` | Animation duration in ms |
1680
+
1681
+ #### Usage
1682
+
1683
+ ```tsx
1684
+ import { StyledBar, StyledCard, palettes, theme } from 'fluent-styles'
1685
+
1686
+ // ── Padding rule ──────────────────────────────────────────────────────────────
1687
+ // The chart auto-sizes to: screenWidth − containerPaddingHorizontal
1688
+ // When placed inside a card:
1689
+ // screen paddingHorizontal = 20 → both sides = 40
1690
+ // card padding = 20 → both sides = 40
1691
+ // total containerPaddingHorizontal = 80 ← pass this value
1692
+ const CONTAINER_PAD = 80
1693
+
1694
+ // ── 1. Default lime — workout duration ───────────────────────────────────────
1695
+ <StyledCard padding={20} shadow="light">
1696
+ <StyledBar
1697
+ data={[
1698
+ { label: 'Sat', value: 45 },
1699
+ { label: 'Sun', value: 60 },
1700
+ { label: 'Mon', value: 35 },
1701
+ { label: 'Tue', value: 70, active: true },
1702
+ { label: 'Wed', value: 50 },
1703
+ { label: 'Thu', value: 30 },
1704
+ { label: 'Fri', value: 20 },
1705
+ ]}
1706
+ unit="min"
1707
+ maxValue={100}
1708
+ containerPaddingHorizontal={CONTAINER_PAD}
1709
+ />
1710
+ </StyledCard>
1711
+
1712
+ // ── 2. Green theme — weight tracking with null placeholders ──────────────────
1713
+ // null value renders a shorter grey placeholder bar (e.g. a rest/missing day)
1714
+ <StyledBar
1715
+ data={[
1716
+ { label: '13', value: null }, // missing — shows placeholder
1717
+ { label: '14', value: 60.0, active: true },
1718
+ { label: '15', value: 58.2 },
1719
+ { label: '16', value: 59.1 },
1720
+ { label: '17', value: 57.4 },
1721
+ { label: '18', value: 58.0 },
1722
+ { label: '19', value: 56.8 },
1723
+ ]}
1724
+ unit="kg"
1725
+ maxValue={80}
1726
+ containerPaddingHorizontal={CONTAINER_PAD}
1727
+ colors={{
1728
+ activeTop: '#4ade80',
1729
+ activeBottom: '#16a34a',
1730
+ tooltipBg: '#15803d',
1731
+ tooltipText: '#fff',
1732
+ }}
1733
+ />
1734
+
1735
+ // ── 3. Orange — temperature, no hatch texture ─────────────────────────────────
1736
+ <StyledBar
1737
+ data={[
1738
+ { label: '13', value: null },
1739
+ { label: '14', value: 36.9, active: true },
1740
+ { label: '15', value: 37.1 },
1741
+ { label: '16', value: 36.8 },
1742
+ { label: '17', value: 37.0 },
1743
+ { label: '18', value: 37.2 },
1744
+ { label: '19', value: 36.5 },
1745
+ ]}
1746
+ unit="°C"
1747
+ maxValue={38}
1748
+ showHatch={false}
1749
+ containerPaddingHorizontal={CONTAINER_PAD}
1750
+ colors={{
1751
+ inactiveBar: '#fed7aa',
1752
+ activeTop: '#fb923c',
1753
+ activeBottom: '#ea580c',
1754
+ tooltipBg: '#c2410c',
1755
+ tooltipText: '#fff',
1756
+ }}
1757
+ />
1758
+
1759
+ // ── 4. Blue — water intake, large values ──────────────────────────────────────
1760
+ <StyledBar
1761
+ data={[
1762
+ { label: '13', value: null },
1763
+ { label: '14', value: 1750, active: true },
1764
+ { label: '15', value: 2100 },
1765
+ { label: '16', value: 1600 },
1766
+ { label: '17', value: 1900 },
1767
+ { label: '18', value: 800 },
1768
+ { label: '19', value: null },
1769
+ ]}
1770
+ unit="mL"
1771
+ maxValue={2500}
1772
+ containerPaddingHorizontal={CONTAINER_PAD}
1773
+ colors={{
1774
+ inactiveBar: '#bfdbfe',
1775
+ hatchLine: 'rgba(59,130,246,0.15)',
1776
+ activeTop: '#60a5fa',
1777
+ activeBottom: '#2563eb',
1778
+ tooltipBg: '#1e3a8a',
1779
+ tooltipText: '#fff',
1780
+ }}
1781
+ />
1782
+
1783
+ // ── 5. Rose — calories burned, overridden tooltip label ───────────────────────
1784
+ // tooltipLabel lets you display a formatted string instead of the raw value
1785
+ <StyledBar
1786
+ data={caloriesData}
1787
+ unit="kcal"
1788
+ maxValue={2500}
1789
+ tooltipLabel="2,200 kcal"
1790
+ containerPaddingHorizontal={CONTAINER_PAD}
1791
+ colors={{
1792
+ inactiveBar: '#fce7f3',
1793
+ hatchLine: 'rgba(236,72,153,0.12)',
1794
+ activeTop: '#f472b6',
1795
+ activeBottom: '#db2777',
1796
+ tooltipBg: '#831843',
1797
+ tooltipText: '#fff',
1798
+ activeLabelColor: '#be185d', // active x-label gets accent colour too
1799
+ }}
1800
+ />
1801
+
1802
+ // ── 6. Minimal — no animation, narrow bars, indigo ───────────────────────────
1803
+ // Use animated=false for static/print-style charts.
1804
+ // barWidthRatio controls how wide bars are relative to their slot.
1805
+ <StyledBar
1806
+ data={stepsData}
1807
+ unit="k"
1808
+ maxValue={100}
1809
+ animated={false}
1810
+ showHatch={false}
1811
+ barWidthRatio={0.42}
1812
+ containerPaddingHorizontal={CONTAINER_PAD}
1813
+ colors={{
1814
+ inactiveBar: '#e0e7ff',
1815
+ activeTop: '#818cf8',
1816
+ activeBottom: '#4338ca',
1817
+ tooltipBg: '#312e81',
1818
+ tooltipText: '#fff',
1819
+ }}
1820
+ />
1821
+ ```
1822
+
1823
+ ---
1824
+
1825
+ ### StyledTimeline
1826
+
1827
+ A data-driven vertical timeline with animated dots, three density variants, three dot shapes, custom renderers, and full colour overrides.
1828
+
1829
+ ```tsx
1830
+ import { StyledTimeline } from 'fluent-styles'
1831
+ ```
1832
+
1833
+ #### `TimelineItem`
1834
+
1835
+ | Field | Type | Description |
1836
+ |---|---|---|
1837
+ | `id` | `string` | Unique identifier |
1838
+ | `time` | `string` | Primary time label (e.g. `'09:00'`) |
1839
+ | `endTime` | `string` | Optional end time shown smaller below |
1840
+ | `title` | `string` | Bold title in default content renderer |
1841
+ | `subtitle` | `string` | Secondary line (muted) |
1842
+ | `description` | `string` | Tertiary detail line |
1843
+ | `content` | `React.ReactNode` | Custom content — replaces default renderer for this item |
1844
+ | `meta` | `Record<string, unknown>` | Arbitrary metadata for use in `renderItem` |
1845
+
1846
+ #### Variants
1847
+
1848
+ | Variant | Gap between rows |
1849
+ |---|---|
1850
+ | `compact` | 12 px |
1851
+ | `default` | 20 px |
1852
+ | `spacious` | 32 px |
1853
+
1854
+ #### Dot shapes
1855
+
1856
+ | Shape | Appearance |
1857
+ |---|---|
1858
+ | `circle` | Hollow ring (transparent fill, coloured border) |
1859
+ | `ring` | White fill with coloured border |
1860
+ | `filled` | Solid fill (default) |
1861
+
1862
+ #### `StyledTimelineColors`
1863
+
1864
+ | Field | Default | Description |
1865
+ |---|---|---|
1866
+ | `line` | `gray[200]` | Vertical connector line colour |
1867
+ | `dot` | `#8bc34a` | Dot fill / border colour |
1868
+ | `dotBorder` | `white` | Inner ring background (for `ring` shape) |
1869
+ | `timeText` | `gray[900]` | Primary time label colour |
1870
+ | `endTimeText` | `gray[400]` | End-time label colour |
1871
+
1872
+ #### Props
1873
+
1874
+ | Prop | Type | Default | Description |
1875
+ |---|---|---|---|
1876
+ | `items` | `TimelineItem[]` | `[]` | Data-driven item list |
1877
+ | `renderItem` | `(item, index) => ReactNode` | — | Custom row content renderer |
1878
+ | `children` | `ReactNode` | — | Extra rows appended after `items` |
1879
+ | `variant` | `TimelineVariant` | `'default'` | Row density |
1880
+ | `dotShape` | `TimelineDotShape` | `'filled'` | Dot style |
1881
+ | `dotSize` | `number` | `10` | Dot diameter in px |
1882
+ | `timeColumnWidth` | `number` | `56` | Width of left time column in px |
1883
+ | `timeGap` | `number` | `16` | Horizontal gap between dot column and content |
1884
+ | `animated` | `boolean` | `true` | Pop-in animation on each dot |
1885
+ | `colors` | `StyledTimelineColors` | — | Colour overrides |
1886
+ | `onItemPress` | `(item: TimelineItem) => void` | — | Press handler for rows |
1887
+
1888
+ #### Usage
1889
+
1890
+ ```tsx
1891
+ import { StyledTimeline, type TimelineItem } from 'fluent-styles'
1892
+
1893
+ // ── 1. Minimal JSON-driven ────────────────────────────────────────────────────
1894
+ <StyledTimeline
1895
+ items={[
1896
+ { id: '1', time: '09:00', title: 'Morning Run', subtitle: 'Cardio · 5km' },
1897
+ { id: '2', time: '11:30', title: 'Strength Class', subtitle: 'Upper body' },
1898
+ { id: '3', time: '14:00', title: 'Yoga', subtitle: 'Recovery' },
1899
+ ]}
1900
+ />
1901
+
1902
+ // ── 2. With end time ─────────────────────────────────────────────────────────
1903
+ // endTime is shown smaller below the main time label
1904
+ <StyledTimeline
1905
+ items={[
1906
+ { id: '1', time: '11:35', endTime: '13:05', title: 'Cardio', subtitle: '4 of 6 sessions' },
1907
+ { id: '2', time: '14:45', endTime: '15:45', title: 'Muscle', subtitle: '5 of 8 sessions' },
1908
+ { id: '3', time: '17:00', endTime: '18:00', title: 'Weight Training', subtitle: '4 of 9 sessions' },
1909
+ ]}
1910
+ colors={{ dot: '#8bc34a', timeText: '#1a1a1e', endTimeText: '#9ca3af' }}
1911
+ />
1912
+
1913
+ // ── 3. Custom renderItem — fitness planner card ───────────────────────────────
1914
+ // Store arbitrary per-item data in the meta field; cast it inside renderItem.
1915
+ interface WorkoutMeta {
1916
+ [key: string]: unknown
1917
+ iconName: string
1918
+ calories: string
1919
+ bpm: string
1920
+ duration: string
1921
+ }
1922
+
1923
+ const workoutItems: TimelineItem[] = [
1924
+ {
1925
+ id: '1', time: '11:35', endTime: '13:05', title: 'Cardio',
1926
+ meta: { iconName: 'heart', calories: '1200', bpm: '90', duration: '03:00' },
1927
+ },
1928
+ {
1929
+ id: '2', time: '14:45', endTime: '15:45', title: 'Muscle',
1930
+ meta: { iconName: 'zap', calories: '980', bpm: '102', duration: '01:00' },
1931
+ },
1932
+ ]
1933
+
1934
+ const WorkoutCard: React.FC<{ item: TimelineItem }> = ({ item }) => {
1935
+ const m = item.meta as unknown as WorkoutMeta
1936
+ return (
1937
+ <StyledCard padding={16} borderRadius={20} shadow="light" borderLeftWidth={4} borderLeftColor="#8bc34a">
1938
+ <StyledText fontSize={16} fontWeight="800">{item.title}</StyledText>
1939
+ <Stack horizontal gap={20} marginTop={8}>
1940
+ <StyledText fontSize={13} color="#6b7280">{m.calories} kcal</StyledText>
1941
+ <StyledText fontSize={13} color="#6b7280">{m.bpm} bpm</StyledText>
1942
+ <StyledText fontSize={13} color="#6b7280">{m.duration} hr</StyledText>
1943
+ </Stack>
1944
+ </StyledCard>
1945
+ )
1946
+ }
1947
+
1948
+ <StyledTimeline
1949
+ items={workoutItems}
1950
+ renderItem={(item) => <WorkoutCard item={item} />}
1951
+ variant="default"
1952
+ dotShape="filled"
1953
+ dotSize={10}
1954
+ timeColumnWidth={58}
1955
+ timeGap={12}
1956
+ animated
1957
+ colors={{ dot: '#8bc34a', line: '#e5e7eb', timeText: '#1a1a1e', endTimeText: '#9ca3af' }}
1958
+ />
1959
+
1960
+ // ── 4. Mixed: data items + appended children ──────────────────────────────────
1961
+ <StyledTimeline items={scheduleItems}>
1962
+ {/* This node is appended as a final timeline row */}
1963
+ <StyledCard padding={12}>
1964
+ <StyledText>Don't forget to hydrate! 💚</StyledText>
1965
+ </StyledCard>
1966
+ </StyledTimeline>
1967
+
1968
+ // ── 5. Density variants ───────────────────────────────────────────────────────
1969
+ <StyledTimeline items={items} variant="compact" />
1970
+ <StyledTimeline items={items} variant="default" />
1971
+ <StyledTimeline items={items} variant="spacious" />
1972
+
1973
+ // ── 6. Dot shapes ─────────────────────────────────────────────────────────────
1974
+ <StyledTimeline items={items} dotShape="filled" /> // solid dot (default)
1975
+ <StyledTimeline items={items} dotShape="ring" /> // white fill, coloured border
1976
+ <StyledTimeline items={items} dotShape="circle" /> // hollow ring
1977
+
1978
+ // ── 7. Blue theme with ring dots ─────────────────────────────────────────────
1979
+ <StyledTimeline
1980
+ items={items}
1981
+ variant="spacious"
1982
+ dotShape="ring"
1983
+ colors={{ dot: '#2196f3', line: '#bbdefb', dotBorder: '#fff' }}
1984
+ />
1985
+
1986
+ // ── 8. Press handler — navigate on tap ───────────────────────────────────────
1987
+ <StyledTimeline
1988
+ items={items}
1989
+ onItemPress={(item) => navigation.navigate('SessionDetail', { id: item.id })}
1990
+ />
1991
+
1992
+ // ── 9. Conditional rendering (rest day) ──────────────────────────────────────
1993
+ // items is [] for rest days — render an empty state instead
1994
+ {items.length > 0 ? (
1995
+ <StyledTimeline items={items} renderItem={(item) => <WorkoutCard item={item} />} />
1996
+ ) : (
1997
+ <Stack alignItems="center" paddingVertical={48}>
1998
+ <StyledText fontSize={18} fontWeight="800">Rest Day</StyledText>
1999
+ <StyledText fontSize={14} color="#9ca3af">Recovery is part of the plan.</StyledText>
2000
+ </Stack>
2001
+ )}
2002
+ ```
2003
+
2004
+ ---
2005
+
2006
+ ### StyledRadio / StyledRadioGroup
2007
+
2008
+ Production-ready radio button system with three sub-components and three layout variants. Supports controlled and uncontrolled modes, generic value types, animated dot transitions, and full colour overrides.
2009
+
2010
+ ```tsx
2011
+ import { StyledRadio, StyledRadioGroup } from 'fluent-styles'
2012
+ ```
2013
+
2014
+ #### Sub-components
2015
+
2016
+ | Component | Description |
2017
+ |---|---|
2018
+ | `StyledRadio` | Raw animated radio dot — for custom layouts |
2019
+ | `StyledRadioGroup` | Full managed group with `list`, `card`, and `boxed` variants |
2020
+
2021
+ #### Sizes (`RadioSize`)
2022
+
2023
+ | Size | Outer | Inner dot | Border |
2024
+ |---|---|---|---|
2025
+ | `sm` | 16 | 7 | 1.5 |
2026
+ | `md` | 20 | 9 | 2.0 |
2027
+ | `lg` | 24 | 11 | 2.5 |
2028
+
2029
+ #### Variants (`RadioVariant`)
2030
+
2031
+ | Variant | Description |
2032
+ |---|---|
2033
+ | `list` | Full-width bordered rows — each option is a standalone pressable card |
2034
+ | `card` | Horizontal grid (configurable columns) — compact cards for delivery/plan selection |
2035
+ | `boxed` | Single card wrapper with a title + divider-separated rows inside |
2036
+
2037
+ #### `RadioOption<T>`
2038
+
2039
+ | Field | Type | Description |
2040
+ |---|---|---|
2041
+ | `value` | `T` | Unique option value (string or number) |
2042
+ | `label` | `string` | Primary label text |
2043
+ | `subtitle` | `string` | Secondary description line |
2044
+ | `rightContent` | `ReactNode` | Content displayed on the right (price, tag, etc.) |
2045
+ | `leadingContent` | `ReactNode` | Leading content (logo, icon, etc.) |
2046
+ | `badge` | `ReactNode` | Inline badge after the label (e.g. `"SAVE 33%"`) |
2047
+ | `disabled` | `boolean` | Disables this specific option |
2048
+
2049
+ #### `StyledRadioColors`
2050
+
2051
+ | Field | Default | Description |
2052
+ |---|---|---|
2053
+ | `active` | `gray[900]` | Active dot and border colour |
2054
+ | `inactive` | `gray[300]` | Inactive ring colour |
2055
+ | `selectedCardBg` | `active + 5% opacity` | Selected item background |
2056
+ | `selectedCardBorder` | `active` | Selected item border |
2057
+ | `unselectedCardBorder` | `gray[200]` | Unselected item border |
2058
+ | `label` | `gray[900]` | Label text colour |
2059
+ | `subtitle` | `gray[400]` | Subtitle text colour |
2060
+
2061
+ #### `StyledRadioGroupProps<T>`
2062
+
2063
+ | Prop | Type | Default | Description |
2064
+ |---|---|---|---|
2065
+ | `options` | `RadioOption<T>[]` | — | Options to render |
2066
+ | `value` | `T` | — | Controlled selected value |
2067
+ | `defaultValue` | `T` | — | Initial value for uncontrolled mode |
2068
+ | `onChange` | `(value: T) => void` | — | Called when selection changes |
2069
+ | `variant` | `RadioVariant` | `'list'` | Layout variant |
2070
+ | `size` | `RadioSize` | `'md'` | Dot size preset |
2071
+ | `title` | `string` | — | Section title (shown in `boxed` variant) |
2072
+ | `colors` | `StyledRadioColors` | — | Colour overrides |
2073
+ | `columns` | `number` | `3` | Columns for `card` variant |
2074
+ | `gap` | `number` | `10` | Gap between cards in `card` variant |
2075
+
2076
+ #### Usage
2077
+
2078
+ ```tsx
2079
+ import React, { useState } from 'react'
2080
+ import { StyledRadioGroup, StyledRadio, StyledCard, Stack, StyledText, type RadioOption } from 'fluent-styles'
2081
+
2082
+ // ── Shared colour theme ───────────────────────────────────────────────────────
2083
+ const BLUE_COLORS = {
2084
+ active: '#2563eb',
2085
+ selectedCardBg: '#eff6ff',
2086
+ selectedCardBorder: '#2563eb',
2087
+ unselectedCardBorder: '#e5e7eb',
2088
+ }
2089
+
2090
+ // ── 1. Subscription plan — list variant with badge + price block ──────────────
2091
+ // badge and rightContent let you embed arbitrary nodes beside each option.
2092
+ const PriceBlock = ({ main, sub }: { main: string; sub: string }) => (
2093
+ <Stack alignItems="flex-end" gap={2}>
2094
+ <StyledText fontSize={14} fontWeight="600">{main}</StyledText>
2095
+ <StyledText fontSize={12} color="#9ca3af">{sub}</StyledText>
2096
+ </Stack>
2097
+ )
2098
+
2099
+ const SaveBadge = ({ label }: { label: string }) => (
2100
+ <Stack paddingHorizontal={8} paddingVertical={3} borderRadius={6} backgroundColor="#dcfce7">
2101
+ <StyledText fontSize={10} fontWeight="700" color="#16a34a">{label}</StyledText>
2102
+ </Stack>
2103
+ )
2104
+
2105
+ const [plan, setPlan] = useState('yearly')
2106
+
2107
+ <StyledRadioGroup
2108
+ options={[
2109
+ {
2110
+ value: 'yearly',
2111
+ label: 'Yearly',
2112
+ badge: <SaveBadge label="SAVE 33%" />,
2113
+ rightContent: <PriceBlock main="$19.99/month" sub="$240 billed yearly" />,
2114
+ },
2115
+ {
2116
+ value: 'monthly',
2117
+ label: 'Monthly',
2118
+ rightContent: <PriceBlock main="$24/month" sub="$24 billed monthly" />,
2119
+ },
2120
+ ]}
2121
+ value={plan}
2122
+ onChange={setPlan}
2123
+ variant="list"
2124
+ colors={BLUE_COLORS}
2125
+ />
2126
+
2127
+ // ── 2. Billing period — boxed variant inside a card ─────────────────────────
2128
+ // `title` renders a bold heading inside the card above the options.
2129
+ <StyledRadioGroup
2130
+ title="Billing Period"
2131
+ options={[
2132
+ { value: 'monthly', label: 'Monthly', rightContent: <StyledText>$9.99/month</StyledText> },
2133
+ { value: 'yearly', label: 'Yearly', rightContent: <StyledText>$12.99/month</StyledText> },
2134
+ ]}
2135
+ defaultValue="monthly"
2136
+ variant="boxed"
2137
+ />
2138
+
2139
+ // ── 3. Delivery method — card variant (3-column grid, blue accent) ────────────
2140
+ // Each option becomes a compact card; columns controls the grid width.
2141
+ <StyledRadioGroup
2142
+ options={[
2143
+ { value: 'standard', label: 'Standard', subtitle: '4–10 business days',
2144
+ rightContent: <StyledText fontWeight="600">$5.00</StyledText> },
2145
+ { value: 'express', label: 'Express', subtitle: '2–5 business days',
2146
+ rightContent: <StyledText fontWeight="600" color="#2563eb">$16.00</StyledText> },
2147
+ { value: 'superfast', label: 'Super Fast', subtitle: '1 business day',
2148
+ rightContent: <StyledText fontWeight="600">$25.00</StyledText> },
2149
+ ]}
2150
+ defaultValue="express"
2151
+ variant="card"
2152
+ columns={3}
2153
+ gap={10}
2154
+ colors={{ ...BLUE_COLORS, subtitle: '#2563eb' }}
2155
+ />
2156
+
2157
+ // ── 4. Payment method — list variant with leading card logos ──────────────────
2158
+ // leadingContent rows any node before the radio dot (logos, avatars, icons…).
2159
+ const VisaLogo = () => (
2160
+ <Stack width={40} height={24} borderRadius={4} backgroundColor="#1a1f71"
2161
+ alignItems="center" justifyContent="center">
2162
+ <StyledText fontSize={11} fontWeight="900" color="#fff">VISA</StyledText>
2163
+ </Stack>
2164
+ )
2165
+
2166
+ const MastercardLogo = () => (
2167
+ <Stack width={36} height={24} borderRadius={4} backgroundColor="#f4f4f4"
2168
+ alignItems="center" justifyContent="center">
2169
+ <Stack horizontal>
2170
+ <Stack width={14} height={14} borderRadius={7} backgroundColor="#eb001b" />
2171
+ <Stack width={14} height={14} borderRadius={7} backgroundColor="#f79e1b" style={{ marginLeft: -5 }} />
2172
+ </Stack>
2173
+ </Stack>
2174
+ )
2175
+
2176
+ <StyledRadioGroup
2177
+ options={[
2178
+ { value: 'mc8304', leadingContent: <MastercardLogo />, label: '**** 8304',
2179
+ subtitle: 'Last used: Mar 26, 2022' },
2180
+ { value: 'visa0123', leadingContent: <VisaLogo />, label: '**** 0123',
2181
+ subtitle: 'Never used' },
2182
+ ]}
2183
+ defaultValue="visa0123"
2184
+ variant="list"
2185
+ colors={BLUE_COLORS}
2186
+ />
2187
+
2188
+ // ── 5. Size variants — sm / md / lg ─────────────────────────────────────────
2189
+ // Size affects only the radio dot; overall row proportions stay the same.
2190
+ <Stack gap={14}>
2191
+ {(['sm', 'md', 'lg'] as const).map((size) => (
2192
+ <Stack key={size}>
2193
+ <StyledText fontSize={12} color="#9ca3af" marginBottom={8}>{size}</StyledText>
2194
+ <StyledRadioGroup
2195
+ options={[
2196
+ { value: 'a', label: 'Option A', rightContent: <StyledText>$5.00</StyledText> },
2197
+ { value: 'b', label: 'Option B', rightContent: <StyledText>$10.00</StyledText> },
2198
+ ]}
2199
+ defaultValue="a"
2200
+ variant="list"
2201
+ size={size}
2202
+ colors={BLUE_COLORS}
2203
+ />
2204
+ </Stack>
2205
+ ))}
2206
+ </Stack>
2207
+
2208
+ // ── 6. Disabled individual options ───────────────────────────────────────────
2209
+ // Set disabled: true on any RadioOption to grey it out and block interaction.
2210
+ <StyledRadioGroup
2211
+ options={[
2212
+ { value: 'active', label: 'Active option', rightContent: <StyledText>$9.99</StyledText> },
2213
+ { value: 'disabled', label: 'Disabled option', rightContent: <StyledText>$19.99</StyledText>, disabled: true },
2214
+ { value: 'other', label: 'Another option', rightContent: <StyledText>$5.99</StyledText> },
2215
+ ]}
2216
+ defaultValue="active"
2217
+ variant="list"
2218
+ colors={BLUE_COLORS}
2219
+ />
2220
+
2221
+ // ── 7. StyledRadio standalone — custom layout swatches ───────────────────────
2222
+ // Use StyledRadio directly when you need the dot inside your own layout.
2223
+ <StyledCard padding={16} borderRadius={14} shadow="light">
2224
+ <Stack gap={16}>
2225
+ {[
2226
+ { label: 'Selected · dark', selected: true, color: '#111827' },
2227
+ { label: 'Unselected', selected: false, color: '#111827' },
2228
+ { label: 'Selected · blue', selected: true, color: '#2563eb' },
2229
+ { label: 'Selected · green', selected: true, color: '#16a34a' },
2230
+ { label: 'Selected · rose', selected: true, color: '#e11d48' },
2231
+ ].map(({ label, selected, color }) => (
2232
+ <Stack key={label} horizontal alignItems="center" gap={12}>
2233
+ <StyledRadio selected={selected} color={color} size="md" />
2234
+ <StyledText fontSize={14} color="#374151">{label}</StyledText>
2235
+ </Stack>
2236
+ ))}
2237
+ </Stack>
2238
+ </StyledCard>
2239
+ ```
2240
+
2241
+ ---
2242
+
2243
+ ### StyledProgressBar
2244
+
2245
+ Animated progress bar with 5 variants, 5 size presets, 3 shapes, 5 label positions, and full colour overrides. Backed by `react-native-svg` for gradient and striped fills.
2246
+
2247
+ ```tsx
2248
+ import { StyledProgressBar } from 'fluent-styles'
2249
+ ```
2250
+
2251
+ #### Variants
2252
+
2253
+ | Variant | Description |
2254
+ |---|---|
2255
+ | `default` | Flat filled bar |
2256
+ | `striped` | Diagonal animated stripe overlay |
2257
+ | `gradient` | Left-to-right colour gradient (SVG) |
2258
+ | `segmented` | Divided into N equal tick segments |
2259
+ | `buffer` | Primary fill + secondary buffer track (media player style) |
2260
+
2261
+ #### Sizes
2262
+
2263
+ | Size | Height |
2264
+ |---|---|
2265
+ | `xs` | 3 px |
2266
+ | `sm` | 6 px |
2267
+ | `md` | 10 px (default) |
2268
+ | `lg` | 16 px |
2269
+ | `xl` | 24 px |
2270
+
2271
+ #### Shapes
2272
+
2273
+ | Shape | Border radius |
2274
+ |---|---|
2275
+ | `rounded` | `height / 2` (default) |
2276
+ | `square` | `0` |
2277
+ | `pill` | `999` |
2278
+
2279
+ #### Label positions
2280
+
2281
+ | Position | Placement |
2282
+ |---|---|
2283
+ | `none` | Hidden (default) |
2284
+ | `above` | Right-aligned above the bar |
2285
+ | `below` | Right-aligned below the bar |
2286
+ | `right` | Inline to the right of the bar |
2287
+ | `inside` | Centred inside the filled bar (requires `lg` or `xl`) |
2288
+
2289
+ #### `StyledProgressColors`
2290
+
2291
+ | Field | Default | Description |
2292
+ |---|---|---|
2293
+ | `fill` | `blue[500]` | Filled track colour |
2294
+ | `track` | `gray[100]` | Background track colour |
2295
+ | `buffer` | `gray[300]` | Buffer layer colour (`buffer` variant) |
2296
+ | `stripe` | `rgba(255,255,255,0.25)` | Stripe overlay (`striped` variant) |
2297
+ | `gradFrom` | `blue[400]` | Gradient start (`gradient` variant) |
2298
+ | `gradTo` | `indigo[600]` | Gradient end (`gradient` variant) |
2299
+ | `label` | `gray[700]` | External label text colour |
2300
+ | `labelInside` | `white` | Inside label colour |
2301
+
2302
+ #### Props
2303
+
2304
+ | Prop | Type | Default | Description |
2305
+ |---|---|---|---|
2306
+ | `value` | `number` | required | Current progress (0–`total`) |
2307
+ | `total` | `number` | `100` | Maximum value |
2308
+ | `bufferValue` | `number` | = `value` | Buffer position (`buffer` variant) |
2309
+ | `variant` | `ProgressVariant` | `'default'` | Visual style |
2310
+ | `size` | `ProgressSize` | `'md'` | Height preset |
2311
+ | `shape` | `ProgressShape` | `'rounded'` | Bar end shape |
2312
+ | `labelPosition` | `LabelPosition` | `'none'` | Where to show the percentage |
2313
+ | `label` | `string \| false` | auto `%` | Custom label; `false` hides it |
2314
+ | `showSteps` | `boolean` | `false` | Show `value / total` instead of `%` |
2315
+ | `segments` | `number` | `5` | Segment count (`segmented` variant) |
2316
+ | `segmentGap` | `number` | `3` | Gap between segments in px |
2317
+ | `width` | `number` | container width | Explicit pixel width |
2318
+ | `animated` | `boolean` | `true` | Animate fill on mount / value change |
2319
+ | `animationDuration` | `number` | `600` | Animation duration in ms |
2320
+ | `colors` | `StyledProgressColors` | blue theme | Colour overrides |
2321
+ | `onAnimationComplete` | `() => void` | — | Fires when animation finishes |
2322
+
2323
+ #### Usage
2324
+
2325
+ ```tsx
2326
+ import { StyledProgressBar } from 'fluent-styles'
2327
+
2328
+ // ── 1. Variants ───────────────────────────────────────────────────────────────
2329
+ <StyledProgressBar value={65} labelPosition="right" />
2330
+
2331
+ <StyledProgressBar value={45} variant="striped" size="lg" labelPosition="right" />
2332
+
2333
+ <StyledProgressBar value={72} variant="gradient" labelPosition="right"
2334
+ colors={{ gradFrom: '#6366f1', gradTo: '#22d3ee' }} />
2335
+
2336
+ // Segmented — workout sets: 5 of 9 complete
2337
+ <StyledProgressBar
2338
+ value={5}
2339
+ total={9}
2340
+ variant="segmented"
2341
+ segments={9}
2342
+ showSteps
2343
+ labelPosition="right"
2344
+ colors={{ fill: '#8bc34a', track: '#e5e7eb' }}
2345
+ />
2346
+
2347
+ // Buffer — media player (loaded 60%, played 30%)
2348
+ <StyledProgressBar
2349
+ value={30}
2350
+ bufferValue={60}
2351
+ variant="buffer"
2352
+ size="sm"
2353
+ labelPosition="right"
2354
+ colors={{ fill: '#2563eb', buffer: '#bfdbfe', track: '#e5e7eb' }}
2355
+ />
2356
+
2357
+ // ── 2. Sizes side-by-side ─────────────────────────────────────────────────────
2358
+ {(['xs', 'sm', 'md', 'lg', 'xl'] as const).map((s) => (
2359
+ <StyledProgressBar key={s} value={65} size={s} labelPosition="right"
2360
+ colors={{ fill: '#3b82f6' }} />
2361
+ ))}
2362
+
2363
+ // ── 3. Label positions ────────────────────────────────────────────────────────
2364
+ <StyledProgressBar value={60} labelPosition="above" />
2365
+ <StyledProgressBar value={60} labelPosition="below" />
2366
+ <StyledProgressBar value={60} labelPosition="right" />
2367
+ // Inside label requires lg or xl
2368
+ <StyledProgressBar value={60} size="lg" labelPosition="inside"
2369
+ colors={{ fill: '#3b82f6', labelInside: '#fff' }} />
2370
+ <StyledProgressBar value={55} size="xl" variant="striped" labelPosition="inside"
2371
+ colors={{ fill: '#8bc34a', labelInside: '#1a1a1a' }} />
2372
+
2373
+ // ── 4. Shapes ─────────────────────────────────────────────────────────────────
2374
+ <StyledProgressBar value={65} size="lg" shape="rounded" labelPosition="right" />
2375
+ <StyledProgressBar value={65} size="lg" shape="square" labelPosition="right" />
2376
+ <StyledProgressBar value={65} size="lg" shape="pill" labelPosition="right" />
2377
+
2378
+ // ── 5. Colour themes ─────────────────────────────────────────────────────────
2379
+ <StyledProgressBar value={65} size="md" labelPosition="right" colors={{ fill: '#3b82f6', track: '#dbeafe' }} />
2380
+ <StyledProgressBar value={65} size="md" labelPosition="right" colors={{ fill: '#8bc34a', track: '#ecfccb' }} />
2381
+ <StyledProgressBar value={65} size="md" labelPosition="right" colors={{ fill: '#f43f5e', track: '#ffe4e6' }} />
2382
+ <StyledProgressBar value={65} size="md" labelPosition="right" colors={{ fill: '#f59e0b', track: '#fef3c7' }} />
2383
+
2384
+ // ── 6. Gradient themes ────────────────────────────────────────────────────────
2385
+ {[
2386
+ { label: 'Indigo → Cyan', from: '#6366f1', to: '#22d3ee' },
2387
+ { label: 'Rose → Orange', from: '#f43f5e', to: '#fb923c' },
2388
+ { label: 'Lime → Emerald', from: '#a3e635', to: '#10b981' },
2389
+ { label: 'Violet → Pink', from: '#8b5cf6', to: '#ec4899' },
2390
+ ].map(({ from, to }) => (
2391
+ <StyledProgressBar value={70} variant="gradient" size="md" labelPosition="right"
2392
+ colors={{ gradFrom: from, gradTo: to }} />
2393
+ ))}
2394
+
2395
+ // ── 7. Controlled with button strip ──────────────────────────────────────────
2396
+ const [progress, setProgress] = useState(45)
2397
+
2398
+ <StyledProgressBar value={progress} variant="gradient" size="lg" labelPosition="above"
2399
+ animationDuration={400}
2400
+ colors={{ gradFrom: '#6366f1', gradTo: '#22d3ee' }} />
2401
+
2402
+ <Stack horizontal gap={10} justifyContent="center">
2403
+ {[0, 25, 50, 75, 100].map((v) => (
2404
+ <StyledPressable key={v} onPress={() => setProgress(v)}
2405
+ paddingHorizontal={14} paddingVertical={8} borderRadius={20}
2406
+ backgroundColor={progress === v ? '#6366f1' : '#f3f4f6'}>
2407
+ <StyledText fontSize={13} fontWeight="600"
2408
+ color={progress === v ? '#fff' : '#374151'}>{v}%</StyledText>
2409
+ </StyledPressable>
2410
+ ))}
2411
+ </Stack>
2412
+
2413
+ // ── 8. Real-world: workout card ───────────────────────────────────────────────
2414
+ {[
2415
+ { title: 'Cardio', progress: 65, label: '4 Of 6', color: '#dc2626', bg: '#fff0f0' },
2416
+ { title: 'Muscle', progress: 62, label: '5 Of 8', color: '#9333ea', bg: '#fdf4ff' },
2417
+ { title: 'Weight', progress: 44, label: '4 Of 9', color: '#ea580c', bg: '#fff7ed' },
2418
+ ].map(({ title, progress, label, color, bg }) => (
2419
+ <Stack key={title} marginBottom={16}>
2420
+ <Stack horizontal alignItems="center" gap={10} marginBottom={8}>
2421
+ <Stack width={32} height={32} borderRadius={16} backgroundColor={bg}
2422
+ alignItems="center" justifyContent="center">
2423
+ <Icon name="activity" size={14} color={color} />
2424
+ </Stack>
2425
+ <StyledText fontSize={14} fontWeight="700">{title}</StyledText>
2426
+ </Stack>
2427
+ <StyledProgressBar
2428
+ value={progress}
2429
+ size="sm"
2430
+ labelPosition="right"
2431
+ label={label}
2432
+ colors={{ fill: color, track: '#f3f4f6' }}
2433
+ />
2434
+ </Stack>
2435
+ ))}
2436
+
2437
+ // ── 9. Real-world: file upload status ─────────────────────────────────────────
2438
+ {[
2439
+ { name: 'design-assets.zip', size: '24.5 MB', value: 100, done: true },
2440
+ { name: 'report-final.pdf', size: '3.2 MB', value: 67, done: false },
2441
+ { name: 'video-export.mp4', size: '128 MB', value: 23, done: false },
2442
+ ].map(({ name, size, value, done }) => (
2443
+ <Stack key={name} marginBottom={14}>
2444
+ <Stack horizontal alignItems="center" justifyContent="space-between" marginBottom={6}>
2445
+ <StyledText fontSize={13} fontWeight="600">{name}</StyledText>
2446
+ <StyledText fontSize={11} color="#9ca3af">{size}</StyledText>
2447
+ </Stack>
2448
+ <StyledProgressBar
2449
+ value={value}
2450
+ size="xs"
2451
+ shape="pill"
2452
+ colors={{ fill: done ? '#10b981' : '#3b82f6', track: '#f3f4f6' }}
2453
+ />
2454
+ </Stack>
2455
+ ))}
2456
+
2457
+ // ── 10. Real-world: skills profile ────────────────────────────────────────────
2458
+ {[
2459
+ { skill: 'React Native', pct: 92 },
2460
+ { skill: 'TypeScript', pct: 85 },
2461
+ { skill: 'UI Design', pct: 74 },
2462
+ ].map(({ skill, pct }) => (
2463
+ <Stack key={skill} horizontal alignItems="center" gap={12} marginBottom={12}>
2464
+ <StyledText fontSize={13} fontWeight="600" width={100}>{skill}</StyledText>
2465
+ <Stack flex={1}>
2466
+ <StyledProgressBar value={pct} size="md" variant="gradient" labelPosition="right"
2467
+ colors={{ gradFrom: '#6366f1', gradTo: '#8b5cf6' }} />
2468
+ </Stack>
2469
+ </Stack>
2470
+ ))}
2471
+ ```
2472
+
2473
+ ---
2474
+
2475
+ ### StyledSlider
2476
+
2477
+ Gesture-driven slider with PanResponder, animated thumb scale, tooltip, tick marks, and 5 variants. Range mode manages two independent thumbs. Backed by `react-native-svg` for gradient fills.
2478
+
2479
+ ```tsx
2480
+ import { StyledSlider } from 'fluent-styles'
2481
+ ```
2482
+
2483
+ #### Variants
2484
+
2485
+ | Variant | Description |
2486
+ |---|---|
2487
+ | `default` | Single thumb, fill left of thumb |
2488
+ | `range` | Two thumbs, fill between them |
2489
+ | `stepped` | Snaps to discrete tick marks |
2490
+ | `gradient` | Gradient-filled track |
2491
+ | `buffer` | Primary thumb + secondary buffer fill (media player style) |
2492
+
2493
+ #### Sizes
2494
+
2495
+ | Size | Track height | Thumb diameter |
2496
+ |---|---|---|
2497
+ | `sm` | 4 px | 18 px |
2498
+ | `md` | 6 px (default) | 24 px |
2499
+ | `lg` | 10 px | 32 px |
2500
+
2501
+ #### `StyledSliderColors`
2502
+
2503
+ | Field | Default | Description |
2504
+ |---|---|---|
2505
+ | `fill` | `#3b82f6` | Filled track colour |
2506
+ | `track` | `gray[200]` | Background track |
2507
+ | `buffer` | `gray[300]` | Buffer fill (`buffer` variant) |
2508
+ | `thumb` | `white` | Thumb fill |
2509
+ | `thumbBorder` | = `fill` | Thumb border colour |
2510
+ | `gradFrom` | `#60a5fa` | Gradient start (`gradient` variant) |
2511
+ | `gradTo` | `#4f46e5` | Gradient end (`gradient` variant) |
2512
+ | `tooltipBg` | `#111827` | Tooltip background |
2513
+ | `tooltipText` | `white` | Tooltip text |
2514
+ | `rangeLabel` | `gray[400]` | Min/max label colour |
2515
+ | `tick` | `gray[300]` | Inactive tick colour |
2516
+ | `tickActive` | = `fill` | Filled tick colour |
2517
+
2518
+ #### Props
2519
+
2520
+ | Prop | Type | Default | Description |
2521
+ |---|---|---|---|
2522
+ | `value` | `number` | required | Current thumb value (or low thumb for `range`) |
2523
+ | `valueHigh` | `number` | — | High thumb value (`range` variant) |
2524
+ | `bufferValue` | `number` | — | Buffer position (`buffer` variant) |
2525
+ | `min` | `number` | `0` | Minimum value |
2526
+ | `max` | `number` | `100` | Maximum value |
2527
+ | `step` | `number` | `1` | Step increment |
2528
+ | `variant` | `SliderVariant` | `'default'` | Visual style |
2529
+ | `size` | `SliderSize` | `'md'` | Track/thumb size preset |
2530
+ | `showTooltip` | `boolean` | `true` | Show tooltip while dragging |
2531
+ | `alwaysShowTooltip` | `boolean` | `false` | Keep tooltip permanently visible |
2532
+ | `showMinMax` | `boolean` | `false` | Display min/max labels at track ends |
2533
+ | `steps` | `number` | `5` | Number of ticks (`stepped` variant) |
2534
+ | `formatLabel` | `(v: number) => string` | `String(v)` | Custom tooltip/tick label formatter |
2535
+ | `width` | `number` | container width | Explicit pixel width |
2536
+ | `disabled` | `boolean` | `false` | Disables interaction, reduces opacity |
2537
+ | `colors` | `StyledSliderColors` | blue theme | Colour overrides |
2538
+ | `onValueChange` | `(value: number) => void` | — | Fires continuously while dragging |
2539
+ | `onSlidingComplete` | `(value: number) => void` | — | Fires once on drag release |
2540
+ | `onRangeChange` | `(low, high: number) => void` | — | Range drag callback |
2541
+ | `onRangeComplete` | `(low, high: number) => void` | — | Range drag-release callback |
2542
+
2543
+ #### Usage
2544
+
2545
+ ```tsx
2546
+ import React, { useState } from 'react'
2547
+ import { StyledSlider, Stack, StyledText } from 'fluent-styles'
2548
+ import Icon from 'react-native-vector-icons/Feather'
2549
+
2550
+ // ── 1. Default — basic volume control ────────────────────────────────────────
2551
+ const [vol, setVol] = useState(65)
2552
+
2553
+ <StyledSlider value={vol} onValueChange={setVol} showMinMax />
2554
+
2555
+ // ── 2. Range — price filter ───────────────────────────────────────────────────
2556
+ // valueHigh is required for the range variant.
2557
+ const [priceLow, setPriceLow] = useState(20)
2558
+ const [priceHigh, setPriceHigh] = useState(75)
2559
+
2560
+ <StyledSlider
2561
+ variant="range"
2562
+ value={priceLow}
2563
+ valueHigh={priceHigh}
2564
+ min={0}
2565
+ max={200}
2566
+ step={5}
2567
+ onRangeChange={(lo, hi) => { setPriceLow(lo); setPriceHigh(hi) }}
2568
+ showMinMax
2569
+ formatLabel={(v) => `$${v}`}
2570
+ colors={{ fill: '#6366f1', thumbBorder: '#6366f1', tooltipBg: '#6366f1' }}
2571
+ />
2572
+
2573
+ // ── 3. Stepped — star rating (snaps to 5 ticks) ───────────────────────────────
2574
+ // steps controls both the number of ticks and the snap resolution.
2575
+ const [rating, setRating] = useState(4)
2576
+
2577
+ <StyledSlider
2578
+ variant="stepped"
2579
+ value={rating}
2580
+ min={1} max={5} steps={5}
2581
+ onValueChange={setRating}
2582
+ alwaysShowTooltip
2583
+ size="lg"
2584
+ formatLabel={(v) => ['','★','★★','★★★','★★★★','★★★★★'][Math.round(v)] ?? ''}
2585
+ colors={{
2586
+ fill: '#f59e0b',
2587
+ track: '#fef3c7',
2588
+ thumbBorder: '#f59e0b',
2589
+ tooltipBg: '#f59e0b',
2590
+ tickActive: '#f59e0b',
2591
+ }}
2592
+ />
2593
+
2594
+ // ── 4. Gradient — temperature control ────────────────────────────────────────
2595
+ const [temp, setTemp] = useState(22)
2596
+
2597
+ <StyledSlider
2598
+ variant="gradient"
2599
+ value={temp}
2600
+ min={10} max={35}
2601
+ onValueChange={setTemp}
2602
+ formatLabel={(v) => `${v}°`}
2603
+ alwaysShowTooltip
2604
+ showMinMax
2605
+ size="lg"
2606
+ colors={{
2607
+ gradFrom: '#60a5fa',
2608
+ gradTo: '#ef4444',
2609
+ tooltipBg: temp < 22 ? '#60a5fa' : '#ef4444',
2610
+ }}
2611
+ />
2612
+
2613
+ // ── 5. Buffer — media player seek bar ────────────────────────────────────────
2614
+ const formatTime = (s: number) =>
2615
+ `${Math.floor(s / 60)}:${String(Math.floor(s % 60)).padStart(2, '0')}`
2616
+
2617
+ const [played, setPlayed] = useState(95)
2618
+ const DURATION = 243
2619
+
2620
+ <StyledSlider
2621
+ variant="buffer"
2622
+ value={played}
2623
+ bufferValue={Math.min(played + 60, DURATION)}
2624
+ min={0}
2625
+ max={DURATION}
2626
+ size="sm"
2627
+ onValueChange={setPlayed}
2628
+ formatLabel={formatTime}
2629
+ colors={{ fill: '#2563eb', buffer: '#bfdbfe' }}
2630
+ />
2631
+
2632
+ // ── 6. Sizes ──────────────────────────────────────────────────────────────────
2633
+ <StyledSlider value={40} size="sm" onValueChange={() => {}} />
2634
+ <StyledSlider value={60} size="md" onValueChange={() => {}} />
2635
+ <StyledSlider value={80} size="lg" onValueChange={() => {}} />
2636
+
2637
+ // ── 7. Colour themes ──────────────────────────────────────────────────────────
2638
+ {[
2639
+ { fill: '#8bc34a', track: '#ecfccb', label: 'Lime' },
2640
+ { fill: '#f43f5e', track: '#ffe4e6', label: 'Rose' },
2641
+ { fill: '#f59e0b', track: '#fef3c7', label: 'Amber' },
2642
+ { fill: '#8b5cf6', track: '#ede9fe', label: 'Purple' },
2643
+ { fill: '#14b8a6', track: '#ccfbf1', label: 'Teal' },
2644
+ ].map(({ fill, track }) => (
2645
+ <StyledSlider
2646
+ value={65}
2647
+ onValueChange={() => {}}
2648
+ colors={{ fill, track, thumbBorder: fill, tooltipBg: fill }}
2649
+ formatLabel={(v) => `${v}%`}
2650
+ />
2651
+ ))}
2652
+
2653
+ // ── 8. Real-world: Audio / brightness controls with icons ─────────────────────
2654
+ <Stack horizontal alignItems="center" gap={12}>
2655
+ <Icon name="volume-x" size={18} color="#9ca3af" />
2656
+ <Stack flex={1}>
2657
+ <StyledSlider value={vol} onValueChange={setVol} showTooltip={false}
2658
+ colors={{ fill: '#1a1a1a', track: '#e5e7eb', thumbBorder: '#1a1a1a' }} />
2659
+ </Stack>
2660
+ <Icon name="volume-2" size={18} color="#9ca3af" />
2661
+ <StyledText fontSize={13} fontWeight="600" width={32}>{vol}%</StyledText>
2662
+ </Stack>
2663
+
2664
+ <Stack horizontal alignItems="center" gap={12}>
2665
+ <Icon name="sun" size={18} color="#9ca3af" />
2666
+ <Stack flex={1}>
2667
+ <StyledSlider value={bright} onValueChange={setBright} showTooltip={false}
2668
+ colors={{ fill: '#f59e0b', track: '#fef3c7', thumbBorder: '#f59e0b' }} />
2669
+ </Stack>
2670
+ <Icon name="sun" size={18} color="#f59e0b" />
2671
+ <StyledText fontSize={13} fontWeight="600" width={32}>{bright}%</StyledText>
2672
+ </Stack>
2673
+
2674
+ // ── 9. Disabled state ─────────────────────────────────────────────────────────
2675
+ <StyledSlider value={55} disabled showMinMax />
2676
+ ```
2677
+
2678
+ ---
2679
+
2680
+ ## Hooks
2681
+
2682
+ All hooks require a `PortalManager` ancestor.
2683
+
2684
+ ### useToast
2685
+
2686
+ ```tsx
2687
+ import { useToast } from 'fluent-styles'
2688
+
2689
+ const toast = useToast()
2690
+
2691
+ // --- Shortcut methods ---
2692
+ toast.success('Profile saved')
2693
+ toast.error('Upload failed', 'The selected file is larger than 5 MB.')
2694
+ toast.warning('Unsaved changes', 'You have pending edits on this screen.')
2695
+ toast.info('New update available', 'Restart the app to use the latest version.')
2696
+
2697
+ // --- Full control with show() ---
2698
+ const id = toast.show({
2699
+ message: 'Settings updated',
2700
+ description: 'Your preferences were saved successfully.',
2701
+ variant: 'success', // 'success' | 'error' | 'warning' | 'info'
2702
+ duration: 2500,
2703
+ theme: 'light', // 'light' | 'dark' | 'system'
2704
+ })
2705
+
2706
+ // Dark-themed toast
2707
+ toast.show({
2708
+ message: 'Background sync started',
2709
+ description: 'We will notify you when sync is complete.',
2710
+ variant: 'info',
2711
+ duration: 4000,
2712
+ theme: 'dark',
2713
+ })
2714
+
2715
+ // --- Persistent toast (duration: 0 — never auto-dismisses) ---
2716
+ const persistId = toast.show({
2717
+ message: 'Uploading file…',
2718
+ description: 'Please keep the app open until upload finishes.',
2719
+ variant: 'info',
2720
+ duration: 0,
2721
+ theme: 'dark',
2722
+ })
2723
+ toast.dismiss(persistId) // dismiss manually later
2724
+
2725
+ // --- Short / long durations ---
2726
+ toast.show({ message: 'Quick message', variant: 'info', duration: 1200, theme: 'light' })
2727
+ toast.show({ message: 'Read this carefully', variant: 'warning', duration: 6000, theme: 'light' })
2728
+
2729
+ // --- Color token overrides ---
2730
+ toast.show({
2731
+ message: 'Custom success',
2732
+ variant: 'success',
2733
+ theme: 'light',
2734
+ colors: {
2735
+ successBg: '#ecfdf5',
2736
+ successBorder: '#10b981',
2737
+ successLabel: '#065f46',
2738
+ description: '#047857',
2739
+ closeIcon: '#065f46',
2740
+ },
2741
+ })
2742
+
2743
+ toast.show({
2744
+ message: 'Custom error',
2745
+ variant: 'error',
2746
+ theme: 'dark',
2747
+ colors: {
2748
+ errorBg: '#3b0a0a',
2749
+ errorBorder: '#ef4444',
2750
+ errorLabel: '#fecaca',
2751
+ description: '#fca5a5',
2752
+ closeIcon: '#fecaca',
2753
+ },
2754
+ })
2755
+
2756
+ // --- Dismiss ---
2757
+ toast.dismiss(id) // single
2758
+ toast.dismissAll() // all active
2759
+ ```
2760
+
2761
+ | Method | Signature | Description |
2762
+ |---|---|---|
2763
+ | `show` | `(options) => number` | Show a toast, returns portal id |
2764
+ | `success` | `(message, description?) => number` | Green success toast |
2765
+ | `error` | `(message, description?) => number` | Red error toast |
2766
+ | `warning` | `(message, description?) => number` | Amber warning toast |
2767
+ | `info` | `(message, description?) => number` | Blue info toast |
2768
+ | `dismiss` | `(id: number) => void` | Dismiss specific toast |
2769
+ | `dismissAll` | `() => void` | Dismiss all active toasts |
2770
+
2771
+ **`show` options:** `message`, `description?`, `variant`, `duration` (`0` = persistent), `theme`, `colors`
2772
+
2773
+ ---
2774
+
2775
+ ### useNotification
2776
+
2777
+ ```tsx
2778
+ import { useNotification } from 'fluent-styles'
2779
+
2780
+ const notification = useNotification()
2781
+
2782
+ // --- Basic notification ---
2783
+ const id = notification.show({
2784
+ title: 'New message from Alex',
2785
+ body: 'Hey, are you free this afternoon?',
2786
+ source: 'Messages',
2787
+ initials: 'AK',
2788
+ timestamp: 'now',
2789
+ theme: 'dark',
2790
+ })
2791
+
2792
+ // --- With avatar image ---
2793
+ notification.show({
2794
+ title: 'Sarah Johnson',
2795
+ body: 'Sent you 3 new design files.',
2796
+ source: 'Drive',
2797
+ avatar: { uri: 'https://example.com/avatar.jpg' },
2798
+ timestamp: '2m',
2799
+ theme: 'light',
2800
+ })
2801
+
2802
+ // --- With action button ---
2803
+ notification.show({
2804
+ title: 'Deployment finished',
2805
+ body: 'Production build completed successfully.',
2806
+ source: 'CI/CD',
2807
+ initials: 'CI',
2808
+ timestamp: 'now',
2809
+ actionLabel: 'Open',
2810
+ onAction: () => navigate('Dashboard'),
2811
+ theme: 'dark',
2812
+ })
2813
+
2814
+ // --- Custom duration ---
2815
+ notification.show({ title: 'Quick', body: 'Disappears fast', initials: 'Q', duration: 1500, theme: 'light' })
2816
+ notification.show({ title: 'Long', body: 'Stays a while', initials: 'L', duration: 8000, theme: 'dark' })
2817
+
2818
+ // --- Color token overrides ---
2819
+ notification.show({
2820
+ title: 'Custom brand notification',
2821
+ body: 'Using token overrides on top of the active theme.',
2822
+ source: 'Brand',
2823
+ initials: 'BR',
2824
+ timestamp: 'now',
2825
+ theme: 'light',
2826
+ actionLabel: 'View',
2827
+ onAction: () => navigate('Brand'),
2828
+ colors: {
2829
+ background: '#eff6ff',
2830
+ border: '#2563eb',
2831
+ title: '#1e3a8a',
2832
+ body: '#1d4ed8',
2833
+ source: '#2563eb',
2834
+ timestamp: '#3b82f6',
2835
+ avatarBg: '#dbeafe',
2836
+ avatarBorder: '#60a5fa',
2837
+ avatarInitials: '#1d4ed8',
2838
+ actionBg: '#dbeafe',
2839
+ actionLabel: '#1d4ed8',
2840
+ closeIcon: '#1d4ed8',
2841
+ },
2842
+ })
2843
+
2844
+ // --- Real-world examples ---
2845
+ notification.show({
2846
+ title: 'New comment on your PR',
2847
+ body: 'Chris left feedback on the latest changes.',
2848
+ source: 'Git',
2849
+ initials: 'CK',
2850
+ timestamp: '1m',
2851
+ actionLabel: 'Review',
2852
+ onAction: () => navigate('PRReview'),
2853
+ theme: 'dark',
2854
+ })
2855
+
2856
+ notification.show({
2857
+ title: 'Meeting starts in 10 minutes',
2858
+ body: 'Frontend sync with the product team.',
2859
+ source: 'Calendar',
2860
+ initials: 'CA',
2861
+ timestamp: 'soon',
2862
+ actionLabel: 'Join',
2863
+ onAction: joinMeeting,
2864
+ theme: 'light',
2865
+ })
2866
+
2867
+ notification.dismiss(id)
2868
+ ```
2869
+
2870
+ **Show options:** `title`, `body`, `avatar`, `initials`, `source`, `timestamp`, `actionLabel`, `onAction`, `duration` (`0` = persistent), `theme`, `colors`
2871
+
2872
+ ---
2873
+
2874
+ ### useDialogue
2875
+
2876
+ ```tsx
2877
+ import { useDialogue } from 'fluent-styles'
2878
+
2879
+ const dialogue = useDialogue()
2880
+
2881
+ // --- Alert (Promise<void>) ---
2882
+ await dialogue.alert(
2883
+ 'Session expired',
2884
+ 'Please log in again to continue.',
2885
+ '🔒',
2886
+ 'light', // optional theme
2887
+ )
2888
+
2889
+ // --- Confirm (Promise<boolean>) ---
2890
+ const confirmed = await dialogue.confirm({
2891
+ title: 'Save changes?',
2892
+ message: 'Your edits will be saved to this project.',
2893
+ icon: '💾',
2894
+ confirmLabel: 'Save',
2895
+ cancelLabel: 'Cancel',
2896
+ theme: 'light',
2897
+ })
2898
+ if (confirmed) save()
2899
+
2900
+ // --- Destructive confirm ---
2901
+ const ok = await dialogue.confirm({
2902
+ title: 'Delete project?',
2903
+ message: 'This action cannot be undone.',
2904
+ icon: '⚠️',
2905
+ confirmLabel: 'Delete',
2906
+ cancelLabel: 'Keep it',
2907
+ destructive: true,
2908
+ })
2909
+ if (ok) deleteProject()
2910
+
2911
+ // --- Custom multi-action dialogue ---
2912
+ dialogue.show({
2913
+ title: 'Unsaved changes',
2914
+ message: 'You have unsaved edits. What would you like to do?',
2915
+ icon: '📝',
2916
+ theme: 'light',
2917
+ actions: [
2918
+ { label: 'Discard', variant: 'destructive', onPress: () => discard() },
2919
+ { label: 'Save draft', variant: 'secondary', onPress: () => saveDraft() },
2920
+ { label: 'Keep editing', variant: 'primary', onPress: () => keepEditing() },
2921
+ ],
2922
+ })
2923
+
2924
+ // --- Async chained flow (confirm then alert) ---
2925
+ const publish = async () => {
2926
+ const confirmed = await dialogue.confirm({
2927
+ title: 'Publish update?',
2928
+ message: 'This will make the latest version visible to users.',
2929
+ icon: '🚀',
2930
+ confirmLabel: 'Publish',
2931
+ cancelLabel: 'Not now',
2932
+ theme: 'light',
2933
+ })
2934
+ if (!confirmed) return
2935
+
2936
+ await performPublish()
2937
+
2938
+ await dialogue.alert('Published', 'Your update is now live.', '✅')
2939
+ }
2940
+
2941
+ // --- Programmatic dismiss by id ---
2942
+ const id = dialogue.show({
2943
+ title: 'Temporary dialogue',
2944
+ message: 'This will close automatically in 2 seconds.',
2945
+ icon: '⏳',
2946
+ theme: 'light',
2947
+ actions: [{ label: 'OK', variant: 'primary', onPress: () => {} }],
2948
+ })
2949
+ setTimeout(() => dialogue.dismiss(id), 2000)
2950
+
2951
+ // --- Real-world: log out + rate app ---
2952
+ const handleLogout = async () => {
2953
+ const ok = await dialogue.confirm({ title: 'Log out?', message: 'You will need to sign in again.', icon: '👋', confirmLabel: 'Log out', destructive: true })
2954
+ if (ok) logout()
2955
+ }
2956
+
2957
+ const handleRateApp = () => {
2958
+ dialogue.show({
2959
+ title: 'Enjoying the app?',
2960
+ icon: '⭐',
2961
+ actions: [
2962
+ { label: '😠 1', variant: 'secondary', onPress: () => submitRating(1) },
2963
+ { label: '😐 3', variant: 'secondary', onPress: () => submitRating(3) },
2964
+ { label: '😁 5', variant: 'primary', onPress: () => submitRating(5) },
2965
+ ],
2966
+ })
2967
+ }
2968
+ ```
2969
+
2970
+ **Action variants:** `primary` | `secondary` | `destructive`
2971
+
2972
+ ---
2973
+
2974
+ ### useActionSheet
2975
+
2976
+ ```tsx
2977
+ import { useActionSheet } from 'fluent-styles'
2978
+
2979
+ const actionSheet = useActionSheet()
2980
+
2981
+ // Items list
2982
+ actionSheet.show({
2983
+ title: 'Post options',
2984
+ items: [
2985
+ { icon: '✏️', label: 'Edit', onPress: onEdit },
2986
+ { icon: '🔗', label: 'Copy link', onPress: onCopy },
2987
+ { icon: '🚩', label: 'Report', variant: 'destructive', onPress: onReport },
2988
+ { icon: '🔒', label: 'Premium', variant: 'disabled' },
2989
+ ],
2990
+ })
2991
+
2992
+ // Custom content sheet
2993
+ actionSheet.present(<MyDatePicker onChange={setDate} />, { title: 'Pick a date' })
2994
+
2995
+ // Mixed: content + items
2996
+ actionSheet.show({
2997
+ title: 'Choose a colour',
2998
+ children: <ColorSwatchRow onSelect={setColor} />,
2999
+ items: [{ label: 'Reset to default', onPress: resetColor }],
3000
+ })
3001
+ ```
3002
+
3003
+ **ActionSheetItem variants:** `default` | `destructive` | `disabled`
3004
+
3005
+ ---
3006
+
3007
+ ### useLoader
3008
+
3009
+ ```tsx
3010
+ import { useLoader } from 'fluent-styles'
3011
+
3012
+ const loader = useLoader()
3013
+
3014
+ // --- Manual show / hide ---
3015
+ const id = loader.show({ label: 'Saving…', variant: 'spinner' })
3016
+ await saveData()
3017
+ loader.hide(id)
3018
+
3019
+ // --- Variants ---
3020
+ loader.show({ variant: 'spinner' })
3021
+ loader.show({ variant: 'dots', label: 'Processing…' })
3022
+ loader.show({ variant: 'pulse', overlay: true })
3023
+ loader.show({ variant: 'circular', label: 'Loading…', theme: 'dark' })
3024
+
3025
+ // --- Color overrides ---
3026
+ loader.show({
3027
+ label: 'Preparing analytics…',
3028
+ variant: 'circular',
3029
+ theme: 'dark',
3030
+ colors: { indicator: '#60a5fa', label: '#dbeafe' },
3031
+ })
3032
+
3033
+ // --- Automatic wrap (always hides, even on error) ---
3034
+ const report = await loader.wrap(
3035
+ () => api.fetchReport(),
3036
+ { label: 'Loading report…', variant: 'dots' },
3037
+ )
3038
+
3039
+ // --- Wrap example with status feedback ---
3040
+ const runFakeTask = async (options, successMsg) => {
3041
+ const result = await loader.wrap(
3042
+ () => new Promise(resolve => setTimeout(resolve, 2000)),
3043
+ options,
3044
+ )
3045
+ toast.success(successMsg)
3046
+ }
3047
+ await runFakeTask({ label: 'Saving profile…', variant: 'spinner' }, 'Profile saved')
3048
+ await runFakeTask({ label: 'Uploading data…', variant: 'circular' }, 'Upload complete')
3049
+ ```
3050
+
3051
+ ---
3052
+
3053
+ ## Imperative Services
3054
+
3055
+ These services are callable from **anywhere** — Redux middleware, Axios interceptors, navigation helpers — because they use the global `portal` singleton. No `PortalManager` is required.
3056
+
3057
+ ### toastService
3058
+
3059
+ ```ts
3060
+ import { toastService } from 'fluent-styles'
3061
+
3062
+ toastService.success('Saved!')
3063
+ toastService.error('Network error', 'Check your connection.')
3064
+ toastService.warning('Session expiring')
3065
+ toastService.info('New version available')
3066
+
3067
+ const id = toastService.show({ message: 'Custom', variant: 'info', duration: 2000 })
3068
+ toastService.dismiss(id)
3069
+ ```
3070
+
3071
+ ### notificationService
3072
+
3073
+ ```ts
3074
+ import { notificationService } from 'fluent-styles'
3075
+
3076
+ const id = notificationService.show({
3077
+ title: 'Payment received',
3078
+ body: '$49.99 from John Smith',
3079
+ initials: 'JS',
3080
+ })
3081
+ notificationService.dismiss(id)
3082
+ ```
3083
+
3084
+ ### dialogueService
3085
+
3086
+ ```ts
3087
+ import { dialogueService } from 'fluent-styles'
3088
+
3089
+ const ok = await dialogueService.confirm({ title: 'Sign out?', destructive: true })
3090
+ await dialogueService.alert('Welcome back!', 'You were away for 3 days.')
3091
+
3092
+ dialogueService.show({ title: 'Custom', actions: [{ label: 'Got it', onPress: () => {} }] })
3093
+ ```
3094
+
3095
+ ### actionSheetService
3096
+
3097
+ ```ts
3098
+ import { actionSheetService } from 'fluent-styles'
3099
+
3100
+ actionSheetService.show({
3101
+ title: 'Share',
3102
+ items: [
3103
+ { icon: '📋', label: 'Copy link', onPress: copyLink },
3104
+ { icon: '✉️', label: 'Email', onPress: shareEmail },
3105
+ ],
3106
+ })
3107
+
3108
+ actionSheetService.present(<MyPicker />, { title: 'Choose' })
3109
+ ```
3110
+
3111
+ ### loaderService
3112
+
3113
+ ```ts
3114
+ import { loaderService } from 'fluent-styles'
3115
+
3116
+ const id = loaderService.show({ label: 'Uploading…', variant: 'circular' })
3117
+ await uploadFile()
3118
+ loaderService.hide(id)
3119
+
3120
+ // Wrapped — always hides, even on error
3121
+ const result = await loaderService.wrap(() => api.submit(form), { label: 'Submitting…' })
3122
+ ```
3123
+
3124
+ ---
3125
+
3126
+ ## Theme & Tokens
3127
+
3128
+ The design token system is fully exported for use in your own components.
3129
+
3130
+ ```ts
3131
+ import { theme, palettes, lightColors, darkColors, fontStyles } from 'fluent-styles'
3132
+
3133
+ // Colour scales (50–900)
3134
+ theme.colors.indigo[500] // '#6366f1'
3135
+ theme.colors.rose[600] // '#e11d48'
3136
+ theme.colors.gray[100] // '#f4f4f5'
3137
+
3138
+ // Base values
3139
+ palettes.white // '#FFFFFF'
3140
+ palettes.black // '#000000'
3141
+
3142
+ // Typography scale
3143
+ theme.fontSize.small
3144
+ theme.fontSize.normal
3145
+ theme.fontSize.medium
3146
+ theme.fontSize.large
3147
+
3148
+ theme.fontWeight.normal
3149
+ theme.fontWeight.semiBold
3150
+ theme.fontWeight.bold
3151
+
3152
+ // Prebuilt font style objects
3153
+ fontStyles.body
3154
+ fontStyles.heading
3155
+ ```
3156
+
3157
+ ### Per-component colour token overrides
3158
+
3159
+ Every complex component accepts a `colors` prop typed as `Partial<ComponentColors>`. Exported default token maps:
3160
+
3161
+ | Export | Used by |
3162
+ |---|---|
3163
+ | `TAB_BAR_COLORS_LIGHT` / `TAB_BAR_COLORS_DARK` | `TabBar` |
3164
+ | `POPUP_COLORS_LIGHT` / `POPUP_COLORS_DARK` | `Popup` |
3165
+ | `DRAWER_COLORS_LIGHT` / `DRAWER_COLORS_DARK` | `Drawer` |
3166
+ | `COLLAPSE_LIGHT` / `COLLAPSE_DARK` | `Collapse` |
3167
+ | `LOADER_LIGHT` / `LOADER_DARK` | `Loader` |
3168
+
3169
+ ### `theme` prop
3170
+
3171
+ Overlay and feedback components accept a `theme` prop:
3172
+
3173
+ ```tsx
3174
+ <Popup theme="dark" visible={…}>…</Popup>
3175
+ <Loader theme="system" /> {/* follows device dark mode */}
3176
+ ```
3177
+
3178
+ Values: `'light'` | `'dark'` | `'system'`
3179
+
3180
+ ---
3181
+
3182
+ ## Contributing
3183
+
3184
+ Issues and pull requests are welcome. Please open an issue first to discuss any significant changes.
3185
+
3186
+ - Repository: [github.com/aaghorighor/fluent-styles](https://github.com/aaghorighor/fluent-styles)
3187
+ - Bug reports: [github.com/aaghorighor/fluent-styles/issues](https://github.com/aaghorighor/fluent-styles/issues)
3188
+
3189
+ ---
3190
+
3191
+ ## License
3192
+
3193
+ [Apache 2.0](LICENSE)