@oxyhq/bloom 0.1.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 (456) hide show
  1. package/README.md +295 -0
  2. package/lib/commonjs/avatar/Avatar.js +215 -0
  3. package/lib/commonjs/avatar/Avatar.js.map +1 -0
  4. package/lib/commonjs/avatar/index.js +13 -0
  5. package/lib/commonjs/avatar/index.js.map +1 -0
  6. package/lib/commonjs/avatar/types.js +6 -0
  7. package/lib/commonjs/avatar/types.js.map +1 -0
  8. package/lib/commonjs/button/Button.js +169 -0
  9. package/lib/commonjs/button/Button.js.map +1 -0
  10. package/lib/commonjs/button/index.js +43 -0
  11. package/lib/commonjs/button/index.js.map +1 -0
  12. package/lib/commonjs/button/types.js +6 -0
  13. package/lib/commonjs/button/types.js.map +1 -0
  14. package/lib/commonjs/collapsible/Collapsible.js +58 -0
  15. package/lib/commonjs/collapsible/Collapsible.js.map +1 -0
  16. package/lib/commonjs/collapsible/index.js +13 -0
  17. package/lib/commonjs/collapsible/index.js.map +1 -0
  18. package/lib/commonjs/collapsible/types.js +6 -0
  19. package/lib/commonjs/collapsible/types.js.map +1 -0
  20. package/lib/commonjs/dialog/Dialog.js +186 -0
  21. package/lib/commonjs/dialog/Dialog.js.map +1 -0
  22. package/lib/commonjs/dialog/Dialog.web.js +244 -0
  23. package/lib/commonjs/dialog/Dialog.web.js.map +1 -0
  24. package/lib/commonjs/dialog/context.js +35 -0
  25. package/lib/commonjs/dialog/context.js.map +1 -0
  26. package/lib/commonjs/dialog/index.js +56 -0
  27. package/lib/commonjs/dialog/index.js.map +1 -0
  28. package/lib/commonjs/dialog/types.js +6 -0
  29. package/lib/commonjs/dialog/types.js.map +1 -0
  30. package/lib/commonjs/divider/Divider.js +39 -0
  31. package/lib/commonjs/divider/Divider.js.map +1 -0
  32. package/lib/commonjs/divider/index.js +13 -0
  33. package/lib/commonjs/divider/index.js.map +1 -0
  34. package/lib/commonjs/divider/types.js +6 -0
  35. package/lib/commonjs/divider/types.js.map +1 -0
  36. package/lib/commonjs/error-boundary/ErrorBoundary.js +116 -0
  37. package/lib/commonjs/error-boundary/ErrorBoundary.js.map +1 -0
  38. package/lib/commonjs/error-boundary/index.js +13 -0
  39. package/lib/commonjs/error-boundary/index.js.map +1 -0
  40. package/lib/commonjs/error-boundary/types.js +6 -0
  41. package/lib/commonjs/error-boundary/types.js.map +1 -0
  42. package/lib/commonjs/grouped-buttons/GroupedButtons.js +86 -0
  43. package/lib/commonjs/grouped-buttons/GroupedButtons.js.map +1 -0
  44. package/lib/commonjs/grouped-buttons/index.js +19 -0
  45. package/lib/commonjs/grouped-buttons/index.js.map +1 -0
  46. package/lib/commonjs/grouped-buttons/types.js +6 -0
  47. package/lib/commonjs/grouped-buttons/types.js.map +1 -0
  48. package/lib/commonjs/index.js +136 -0
  49. package/lib/commonjs/index.js.map +1 -0
  50. package/lib/commonjs/loading/Loading.js +274 -0
  51. package/lib/commonjs/loading/Loading.js.map +1 -0
  52. package/lib/commonjs/loading/index.js +13 -0
  53. package/lib/commonjs/loading/index.js.map +1 -0
  54. package/lib/commonjs/loading/types.js +6 -0
  55. package/lib/commonjs/loading/types.js.map +1 -0
  56. package/lib/commonjs/package.json +1 -0
  57. package/lib/commonjs/portal/index.js +90 -0
  58. package/lib/commonjs/portal/index.js.map +1 -0
  59. package/lib/commonjs/prompt/Prompt.js +267 -0
  60. package/lib/commonjs/prompt/Prompt.js.map +1 -0
  61. package/lib/commonjs/prompt/index.js +61 -0
  62. package/lib/commonjs/prompt/index.js.map +1 -0
  63. package/lib/commonjs/prompt-input/Actions.js +45 -0
  64. package/lib/commonjs/prompt-input/Actions.js.map +1 -0
  65. package/lib/commonjs/prompt-input/Attachments.js +277 -0
  66. package/lib/commonjs/prompt-input/Attachments.js.map +1 -0
  67. package/lib/commonjs/prompt-input/PromptInput.js +226 -0
  68. package/lib/commonjs/prompt-input/PromptInput.js.map +1 -0
  69. package/lib/commonjs/prompt-input/SubmitButton.js +81 -0
  70. package/lib/commonjs/prompt-input/SubmitButton.js.map +1 -0
  71. package/lib/commonjs/prompt-input/Textarea.js +101 -0
  72. package/lib/commonjs/prompt-input/Textarea.js.map +1 -0
  73. package/lib/commonjs/prompt-input/Textarea.web.js +148 -0
  74. package/lib/commonjs/prompt-input/Textarea.web.js.map +1 -0
  75. package/lib/commonjs/prompt-input/context.js +35 -0
  76. package/lib/commonjs/prompt-input/context.js.map +1 -0
  77. package/lib/commonjs/prompt-input/index.js +54 -0
  78. package/lib/commonjs/prompt-input/index.js.map +1 -0
  79. package/lib/commonjs/prompt-input/types.js +6 -0
  80. package/lib/commonjs/prompt-input/types.js.map +1 -0
  81. package/lib/commonjs/radio-indicator/RadioIndicator.js +48 -0
  82. package/lib/commonjs/radio-indicator/RadioIndicator.js.map +1 -0
  83. package/lib/commonjs/radio-indicator/index.js +13 -0
  84. package/lib/commonjs/radio-indicator/index.js.map +1 -0
  85. package/lib/commonjs/radio-indicator/types.js +6 -0
  86. package/lib/commonjs/radio-indicator/types.js.map +1 -0
  87. package/lib/commonjs/theme/BloomThemeProvider.js +122 -0
  88. package/lib/commonjs/theme/BloomThemeProvider.js.map +1 -0
  89. package/lib/commonjs/theme/adaptive-colors.js +96 -0
  90. package/lib/commonjs/theme/adaptive-colors.js.map +1 -0
  91. package/lib/commonjs/theme/apply-dark-class.js +13 -0
  92. package/lib/commonjs/theme/apply-dark-class.js.map +1 -0
  93. package/lib/commonjs/theme/color-presets.js +486 -0
  94. package/lib/commonjs/theme/color-presets.js.map +1 -0
  95. package/lib/commonjs/theme/index.js +57 -0
  96. package/lib/commonjs/theme/index.js.map +1 -0
  97. package/lib/commonjs/theme/set-color-scheme-safe.js +23 -0
  98. package/lib/commonjs/theme/set-color-scheme-safe.js.map +1 -0
  99. package/lib/commonjs/theme/types.js +2 -0
  100. package/lib/commonjs/theme/types.js.map +1 -0
  101. package/lib/commonjs/theme/use-theme.js +29 -0
  102. package/lib/commonjs/theme/use-theme.js.map +1 -0
  103. package/lib/module/avatar/Avatar.js +210 -0
  104. package/lib/module/avatar/Avatar.js.map +1 -0
  105. package/lib/module/avatar/index.js +4 -0
  106. package/lib/module/avatar/index.js.map +1 -0
  107. package/lib/module/avatar/types.js +4 -0
  108. package/lib/module/avatar/types.js.map +1 -0
  109. package/lib/module/button/Button.js +164 -0
  110. package/lib/module/button/Button.js.map +1 -0
  111. package/lib/module/button/index.js +4 -0
  112. package/lib/module/button/index.js.map +1 -0
  113. package/lib/module/button/types.js +4 -0
  114. package/lib/module/button/types.js.map +1 -0
  115. package/lib/module/collapsible/Collapsible.js +53 -0
  116. package/lib/module/collapsible/Collapsible.js.map +1 -0
  117. package/lib/module/collapsible/index.js +4 -0
  118. package/lib/module/collapsible/index.js.map +1 -0
  119. package/lib/module/collapsible/types.js +4 -0
  120. package/lib/module/collapsible/types.js.map +1 -0
  121. package/lib/module/dialog/Dialog.js +165 -0
  122. package/lib/module/dialog/Dialog.js.map +1 -0
  123. package/lib/module/dialog/Dialog.web.js +222 -0
  124. package/lib/module/dialog/Dialog.web.js.map +1 -0
  125. package/lib/module/dialog/context.js +29 -0
  126. package/lib/module/dialog/context.js.map +1 -0
  127. package/lib/module/dialog/index.js +5 -0
  128. package/lib/module/dialog/index.js.map +1 -0
  129. package/lib/module/dialog/types.js +4 -0
  130. package/lib/module/dialog/types.js.map +1 -0
  131. package/lib/module/divider/Divider.js +34 -0
  132. package/lib/module/divider/Divider.js.map +1 -0
  133. package/lib/module/divider/index.js +4 -0
  134. package/lib/module/divider/index.js.map +1 -0
  135. package/lib/module/divider/types.js +4 -0
  136. package/lib/module/divider/types.js.map +1 -0
  137. package/lib/module/error-boundary/ErrorBoundary.js +110 -0
  138. package/lib/module/error-boundary/ErrorBoundary.js.map +1 -0
  139. package/lib/module/error-boundary/index.js +4 -0
  140. package/lib/module/error-boundary/index.js.map +1 -0
  141. package/lib/module/error-boundary/types.js +4 -0
  142. package/lib/module/error-boundary/types.js.map +1 -0
  143. package/lib/module/grouped-buttons/GroupedButtons.js +80 -0
  144. package/lib/module/grouped-buttons/GroupedButtons.js.map +1 -0
  145. package/lib/module/grouped-buttons/index.js +4 -0
  146. package/lib/module/grouped-buttons/index.js.map +1 -0
  147. package/lib/module/grouped-buttons/types.js +4 -0
  148. package/lib/module/grouped-buttons/types.js.map +1 -0
  149. package/lib/module/index.js +16 -0
  150. package/lib/module/index.js.map +1 -0
  151. package/lib/module/loading/Loading.js +269 -0
  152. package/lib/module/loading/Loading.js.map +1 -0
  153. package/lib/module/loading/index.js +4 -0
  154. package/lib/module/loading/index.js.map +1 -0
  155. package/lib/module/loading/types.js +4 -0
  156. package/lib/module/loading/types.js.map +1 -0
  157. package/lib/module/package.json +1 -0
  158. package/lib/module/portal/index.js +85 -0
  159. package/lib/module/portal/index.js.map +1 -0
  160. package/lib/module/prompt/Prompt.js +250 -0
  161. package/lib/module/prompt/Prompt.js.map +1 -0
  162. package/lib/module/prompt/index.js +4 -0
  163. package/lib/module/prompt/index.js.map +1 -0
  164. package/lib/module/prompt-input/Actions.js +40 -0
  165. package/lib/module/prompt-input/Actions.js.map +1 -0
  166. package/lib/module/prompt-input/Attachments.js +272 -0
  167. package/lib/module/prompt-input/Attachments.js.map +1 -0
  168. package/lib/module/prompt-input/PromptInput.js +221 -0
  169. package/lib/module/prompt-input/PromptInput.js.map +1 -0
  170. package/lib/module/prompt-input/SubmitButton.js +76 -0
  171. package/lib/module/prompt-input/SubmitButton.js.map +1 -0
  172. package/lib/module/prompt-input/Textarea.js +96 -0
  173. package/lib/module/prompt-input/Textarea.js.map +1 -0
  174. package/lib/module/prompt-input/Textarea.web.js +143 -0
  175. package/lib/module/prompt-input/Textarea.web.js.map +1 -0
  176. package/lib/module/prompt-input/context.js +28 -0
  177. package/lib/module/prompt-input/context.js.map +1 -0
  178. package/lib/module/prompt-input/index.js +9 -0
  179. package/lib/module/prompt-input/index.js.map +1 -0
  180. package/lib/module/prompt-input/types.js +4 -0
  181. package/lib/module/prompt-input/types.js.map +1 -0
  182. package/lib/module/radio-indicator/RadioIndicator.js +43 -0
  183. package/lib/module/radio-indicator/RadioIndicator.js.map +1 -0
  184. package/lib/module/radio-indicator/index.js +4 -0
  185. package/lib/module/radio-indicator/index.js.map +1 -0
  186. package/lib/module/radio-indicator/types.js +4 -0
  187. package/lib/module/radio-indicator/types.js.map +1 -0
  188. package/lib/module/theme/BloomThemeProvider.js +116 -0
  189. package/lib/module/theme/BloomThemeProvider.js.map +1 -0
  190. package/lib/module/theme/adaptive-colors.js +92 -0
  191. package/lib/module/theme/adaptive-colors.js.map +1 -0
  192. package/lib/module/theme/apply-dark-class.js +9 -0
  193. package/lib/module/theme/apply-dark-class.js.map +1 -0
  194. package/lib/module/theme/color-presets.js +481 -0
  195. package/lib/module/theme/color-presets.js.map +1 -0
  196. package/lib/module/theme/index.js +6 -0
  197. package/lib/module/theme/index.js.map +1 -0
  198. package/lib/module/theme/set-color-scheme-safe.js +19 -0
  199. package/lib/module/theme/set-color-scheme-safe.js.map +1 -0
  200. package/lib/module/theme/types.js +2 -0
  201. package/lib/module/theme/types.js.map +1 -0
  202. package/lib/module/theme/use-theme.js +23 -0
  203. package/lib/module/theme/use-theme.js.map +1 -0
  204. package/lib/typescript/commonjs/avatar/Avatar.d.ts +4 -0
  205. package/lib/typescript/commonjs/avatar/Avatar.d.ts.map +1 -0
  206. package/lib/typescript/commonjs/avatar/index.d.ts +3 -0
  207. package/lib/typescript/commonjs/avatar/index.d.ts.map +1 -0
  208. package/lib/typescript/commonjs/avatar/types.d.ts +31 -0
  209. package/lib/typescript/commonjs/avatar/types.d.ts.map +1 -0
  210. package/lib/typescript/commonjs/button/Button.d.ts +10 -0
  211. package/lib/typescript/commonjs/button/Button.d.ts.map +1 -0
  212. package/lib/typescript/commonjs/button/index.d.ts +3 -0
  213. package/lib/typescript/commonjs/button/index.d.ts.map +1 -0
  214. package/lib/typescript/commonjs/button/types.d.ts +25 -0
  215. package/lib/typescript/commonjs/button/types.d.ts.map +1 -0
  216. package/lib/typescript/commonjs/collapsible/Collapsible.d.ts +4 -0
  217. package/lib/typescript/commonjs/collapsible/Collapsible.d.ts.map +1 -0
  218. package/lib/typescript/commonjs/collapsible/index.d.ts +3 -0
  219. package/lib/typescript/commonjs/collapsible/index.d.ts.map +1 -0
  220. package/lib/typescript/commonjs/collapsible/types.d.ts +18 -0
  221. package/lib/typescript/commonjs/collapsible/types.d.ts.map +1 -0
  222. package/lib/typescript/commonjs/dialog/Dialog.d.ts +11 -0
  223. package/lib/typescript/commonjs/dialog/Dialog.d.ts.map +1 -0
  224. package/lib/typescript/commonjs/dialog/Dialog.web.d.ts +23 -0
  225. package/lib/typescript/commonjs/dialog/Dialog.web.d.ts.map +1 -0
  226. package/lib/typescript/commonjs/dialog/context.d.ts +5 -0
  227. package/lib/typescript/commonjs/dialog/context.d.ts.map +1 -0
  228. package/lib/typescript/commonjs/dialog/index.d.ts +4 -0
  229. package/lib/typescript/commonjs/dialog/index.d.ts.map +1 -0
  230. package/lib/typescript/commonjs/dialog/types.d.ts +30 -0
  231. package/lib/typescript/commonjs/dialog/types.d.ts.map +1 -0
  232. package/lib/typescript/commonjs/divider/Divider.d.ts +4 -0
  233. package/lib/typescript/commonjs/divider/Divider.d.ts.map +1 -0
  234. package/lib/typescript/commonjs/divider/index.d.ts +3 -0
  235. package/lib/typescript/commonjs/divider/index.d.ts.map +1 -0
  236. package/lib/typescript/commonjs/divider/types.d.ts +15 -0
  237. package/lib/typescript/commonjs/divider/types.d.ts.map +1 -0
  238. package/lib/typescript/commonjs/error-boundary/ErrorBoundary.d.ts +16 -0
  239. package/lib/typescript/commonjs/error-boundary/ErrorBoundary.d.ts.map +1 -0
  240. package/lib/typescript/commonjs/error-boundary/index.d.ts +3 -0
  241. package/lib/typescript/commonjs/error-boundary/index.d.ts.map +1 -0
  242. package/lib/typescript/commonjs/error-boundary/types.d.ts +16 -0
  243. package/lib/typescript/commonjs/error-boundary/types.d.ts.map +1 -0
  244. package/lib/typescript/commonjs/grouped-buttons/GroupedButtons.d.ts +8 -0
  245. package/lib/typescript/commonjs/grouped-buttons/GroupedButtons.d.ts.map +1 -0
  246. package/lib/typescript/commonjs/grouped-buttons/index.d.ts +3 -0
  247. package/lib/typescript/commonjs/grouped-buttons/index.d.ts.map +1 -0
  248. package/lib/typescript/commonjs/grouped-buttons/types.d.ts +15 -0
  249. package/lib/typescript/commonjs/grouped-buttons/types.d.ts.map +1 -0
  250. package/lib/typescript/commonjs/index.d.ts +15 -0
  251. package/lib/typescript/commonjs/index.d.ts.map +1 -0
  252. package/lib/typescript/commonjs/loading/Loading.d.ts +4 -0
  253. package/lib/typescript/commonjs/loading/Loading.d.ts.map +1 -0
  254. package/lib/typescript/commonjs/loading/index.d.ts +3 -0
  255. package/lib/typescript/commonjs/loading/index.d.ts.map +1 -0
  256. package/lib/typescript/commonjs/loading/types.d.ts +60 -0
  257. package/lib/typescript/commonjs/loading/types.d.ts.map +1 -0
  258. package/lib/typescript/commonjs/package.json +1 -0
  259. package/lib/typescript/commonjs/portal/index.d.ts +5 -0
  260. package/lib/typescript/commonjs/portal/index.d.ts.map +1 -0
  261. package/lib/typescript/commonjs/prompt/Prompt.d.ts +42 -0
  262. package/lib/typescript/commonjs/prompt/Prompt.d.ts.map +1 -0
  263. package/lib/typescript/commonjs/prompt/index.d.ts +3 -0
  264. package/lib/typescript/commonjs/prompt/index.d.ts.map +1 -0
  265. package/lib/typescript/commonjs/prompt-input/Actions.d.ts +3 -0
  266. package/lib/typescript/commonjs/prompt-input/Actions.d.ts.map +1 -0
  267. package/lib/typescript/commonjs/prompt-input/Attachments.d.ts +3 -0
  268. package/lib/typescript/commonjs/prompt-input/Attachments.d.ts.map +1 -0
  269. package/lib/typescript/commonjs/prompt-input/PromptInput.d.ts +3 -0
  270. package/lib/typescript/commonjs/prompt-input/PromptInput.d.ts.map +1 -0
  271. package/lib/typescript/commonjs/prompt-input/SubmitButton.d.ts +3 -0
  272. package/lib/typescript/commonjs/prompt-input/SubmitButton.d.ts.map +1 -0
  273. package/lib/typescript/commonjs/prompt-input/Textarea.d.ts +3 -0
  274. package/lib/typescript/commonjs/prompt-input/Textarea.d.ts.map +1 -0
  275. package/lib/typescript/commonjs/prompt-input/Textarea.web.d.ts +3 -0
  276. package/lib/typescript/commonjs/prompt-input/Textarea.web.d.ts.map +1 -0
  277. package/lib/typescript/commonjs/prompt-input/context.d.ts +34 -0
  278. package/lib/typescript/commonjs/prompt-input/context.d.ts.map +1 -0
  279. package/lib/typescript/commonjs/prompt-input/index.d.ts +8 -0
  280. package/lib/typescript/commonjs/prompt-input/index.d.ts.map +1 -0
  281. package/lib/typescript/commonjs/prompt-input/types.d.ts +88 -0
  282. package/lib/typescript/commonjs/prompt-input/types.d.ts.map +1 -0
  283. package/lib/typescript/commonjs/radio-indicator/RadioIndicator.d.ts +4 -0
  284. package/lib/typescript/commonjs/radio-indicator/RadioIndicator.d.ts.map +1 -0
  285. package/lib/typescript/commonjs/radio-indicator/index.d.ts +3 -0
  286. package/lib/typescript/commonjs/radio-indicator/index.d.ts.map +1 -0
  287. package/lib/typescript/commonjs/radio-indicator/types.d.ts +15 -0
  288. package/lib/typescript/commonjs/radio-indicator/types.d.ts.map +1 -0
  289. package/lib/typescript/commonjs/theme/BloomThemeProvider.d.ts +20 -0
  290. package/lib/typescript/commonjs/theme/BloomThemeProvider.d.ts.map +1 -0
  291. package/lib/typescript/commonjs/theme/adaptive-colors.d.ts +3 -0
  292. package/lib/typescript/commonjs/theme/adaptive-colors.d.ts.map +1 -0
  293. package/lib/typescript/commonjs/theme/apply-dark-class.d.ts +2 -0
  294. package/lib/typescript/commonjs/theme/apply-dark-class.d.ts.map +1 -0
  295. package/lib/typescript/commonjs/theme/color-presets.d.ts +12 -0
  296. package/lib/typescript/commonjs/theme/color-presets.d.ts.map +1 -0
  297. package/lib/typescript/commonjs/theme/index.d.ts +7 -0
  298. package/lib/typescript/commonjs/theme/index.d.ts.map +1 -0
  299. package/lib/typescript/commonjs/theme/set-color-scheme-safe.d.ts +9 -0
  300. package/lib/typescript/commonjs/theme/set-color-scheme-safe.d.ts.map +1 -0
  301. package/lib/typescript/commonjs/theme/types.d.ts +39 -0
  302. package/lib/typescript/commonjs/theme/types.d.ts.map +1 -0
  303. package/lib/typescript/commonjs/theme/use-theme.d.ts +5 -0
  304. package/lib/typescript/commonjs/theme/use-theme.d.ts.map +1 -0
  305. package/lib/typescript/module/avatar/Avatar.d.ts +4 -0
  306. package/lib/typescript/module/avatar/Avatar.d.ts.map +1 -0
  307. package/lib/typescript/module/avatar/index.d.ts +3 -0
  308. package/lib/typescript/module/avatar/index.d.ts.map +1 -0
  309. package/lib/typescript/module/avatar/types.d.ts +31 -0
  310. package/lib/typescript/module/avatar/types.d.ts.map +1 -0
  311. package/lib/typescript/module/button/Button.d.ts +10 -0
  312. package/lib/typescript/module/button/Button.d.ts.map +1 -0
  313. package/lib/typescript/module/button/index.d.ts +3 -0
  314. package/lib/typescript/module/button/index.d.ts.map +1 -0
  315. package/lib/typescript/module/button/types.d.ts +25 -0
  316. package/lib/typescript/module/button/types.d.ts.map +1 -0
  317. package/lib/typescript/module/collapsible/Collapsible.d.ts +4 -0
  318. package/lib/typescript/module/collapsible/Collapsible.d.ts.map +1 -0
  319. package/lib/typescript/module/collapsible/index.d.ts +3 -0
  320. package/lib/typescript/module/collapsible/index.d.ts.map +1 -0
  321. package/lib/typescript/module/collapsible/types.d.ts +18 -0
  322. package/lib/typescript/module/collapsible/types.d.ts.map +1 -0
  323. package/lib/typescript/module/dialog/Dialog.d.ts +11 -0
  324. package/lib/typescript/module/dialog/Dialog.d.ts.map +1 -0
  325. package/lib/typescript/module/dialog/Dialog.web.d.ts +23 -0
  326. package/lib/typescript/module/dialog/Dialog.web.d.ts.map +1 -0
  327. package/lib/typescript/module/dialog/context.d.ts +5 -0
  328. package/lib/typescript/module/dialog/context.d.ts.map +1 -0
  329. package/lib/typescript/module/dialog/index.d.ts +4 -0
  330. package/lib/typescript/module/dialog/index.d.ts.map +1 -0
  331. package/lib/typescript/module/dialog/types.d.ts +30 -0
  332. package/lib/typescript/module/dialog/types.d.ts.map +1 -0
  333. package/lib/typescript/module/divider/Divider.d.ts +4 -0
  334. package/lib/typescript/module/divider/Divider.d.ts.map +1 -0
  335. package/lib/typescript/module/divider/index.d.ts +3 -0
  336. package/lib/typescript/module/divider/index.d.ts.map +1 -0
  337. package/lib/typescript/module/divider/types.d.ts +15 -0
  338. package/lib/typescript/module/divider/types.d.ts.map +1 -0
  339. package/lib/typescript/module/error-boundary/ErrorBoundary.d.ts +16 -0
  340. package/lib/typescript/module/error-boundary/ErrorBoundary.d.ts.map +1 -0
  341. package/lib/typescript/module/error-boundary/index.d.ts +3 -0
  342. package/lib/typescript/module/error-boundary/index.d.ts.map +1 -0
  343. package/lib/typescript/module/error-boundary/types.d.ts +16 -0
  344. package/lib/typescript/module/error-boundary/types.d.ts.map +1 -0
  345. package/lib/typescript/module/grouped-buttons/GroupedButtons.d.ts +8 -0
  346. package/lib/typescript/module/grouped-buttons/GroupedButtons.d.ts.map +1 -0
  347. package/lib/typescript/module/grouped-buttons/index.d.ts +3 -0
  348. package/lib/typescript/module/grouped-buttons/index.d.ts.map +1 -0
  349. package/lib/typescript/module/grouped-buttons/types.d.ts +15 -0
  350. package/lib/typescript/module/grouped-buttons/types.d.ts.map +1 -0
  351. package/lib/typescript/module/index.d.ts +15 -0
  352. package/lib/typescript/module/index.d.ts.map +1 -0
  353. package/lib/typescript/module/loading/Loading.d.ts +4 -0
  354. package/lib/typescript/module/loading/Loading.d.ts.map +1 -0
  355. package/lib/typescript/module/loading/index.d.ts +3 -0
  356. package/lib/typescript/module/loading/index.d.ts.map +1 -0
  357. package/lib/typescript/module/loading/types.d.ts +60 -0
  358. package/lib/typescript/module/loading/types.d.ts.map +1 -0
  359. package/lib/typescript/module/package.json +1 -0
  360. package/lib/typescript/module/portal/index.d.ts +5 -0
  361. package/lib/typescript/module/portal/index.d.ts.map +1 -0
  362. package/lib/typescript/module/prompt/Prompt.d.ts +42 -0
  363. package/lib/typescript/module/prompt/Prompt.d.ts.map +1 -0
  364. package/lib/typescript/module/prompt/index.d.ts +3 -0
  365. package/lib/typescript/module/prompt/index.d.ts.map +1 -0
  366. package/lib/typescript/module/prompt-input/Actions.d.ts +3 -0
  367. package/lib/typescript/module/prompt-input/Actions.d.ts.map +1 -0
  368. package/lib/typescript/module/prompt-input/Attachments.d.ts +3 -0
  369. package/lib/typescript/module/prompt-input/Attachments.d.ts.map +1 -0
  370. package/lib/typescript/module/prompt-input/PromptInput.d.ts +3 -0
  371. package/lib/typescript/module/prompt-input/PromptInput.d.ts.map +1 -0
  372. package/lib/typescript/module/prompt-input/SubmitButton.d.ts +3 -0
  373. package/lib/typescript/module/prompt-input/SubmitButton.d.ts.map +1 -0
  374. package/lib/typescript/module/prompt-input/Textarea.d.ts +3 -0
  375. package/lib/typescript/module/prompt-input/Textarea.d.ts.map +1 -0
  376. package/lib/typescript/module/prompt-input/Textarea.web.d.ts +3 -0
  377. package/lib/typescript/module/prompt-input/Textarea.web.d.ts.map +1 -0
  378. package/lib/typescript/module/prompt-input/context.d.ts +34 -0
  379. package/lib/typescript/module/prompt-input/context.d.ts.map +1 -0
  380. package/lib/typescript/module/prompt-input/index.d.ts +8 -0
  381. package/lib/typescript/module/prompt-input/index.d.ts.map +1 -0
  382. package/lib/typescript/module/prompt-input/types.d.ts +88 -0
  383. package/lib/typescript/module/prompt-input/types.d.ts.map +1 -0
  384. package/lib/typescript/module/radio-indicator/RadioIndicator.d.ts +4 -0
  385. package/lib/typescript/module/radio-indicator/RadioIndicator.d.ts.map +1 -0
  386. package/lib/typescript/module/radio-indicator/index.d.ts +3 -0
  387. package/lib/typescript/module/radio-indicator/index.d.ts.map +1 -0
  388. package/lib/typescript/module/radio-indicator/types.d.ts +15 -0
  389. package/lib/typescript/module/radio-indicator/types.d.ts.map +1 -0
  390. package/lib/typescript/module/theme/BloomThemeProvider.d.ts +20 -0
  391. package/lib/typescript/module/theme/BloomThemeProvider.d.ts.map +1 -0
  392. package/lib/typescript/module/theme/adaptive-colors.d.ts +3 -0
  393. package/lib/typescript/module/theme/adaptive-colors.d.ts.map +1 -0
  394. package/lib/typescript/module/theme/apply-dark-class.d.ts +2 -0
  395. package/lib/typescript/module/theme/apply-dark-class.d.ts.map +1 -0
  396. package/lib/typescript/module/theme/color-presets.d.ts +12 -0
  397. package/lib/typescript/module/theme/color-presets.d.ts.map +1 -0
  398. package/lib/typescript/module/theme/index.d.ts +7 -0
  399. package/lib/typescript/module/theme/index.d.ts.map +1 -0
  400. package/lib/typescript/module/theme/set-color-scheme-safe.d.ts +9 -0
  401. package/lib/typescript/module/theme/set-color-scheme-safe.d.ts.map +1 -0
  402. package/lib/typescript/module/theme/types.d.ts +39 -0
  403. package/lib/typescript/module/theme/types.d.ts.map +1 -0
  404. package/lib/typescript/module/theme/use-theme.d.ts +5 -0
  405. package/lib/typescript/module/theme/use-theme.d.ts.map +1 -0
  406. package/package.json +260 -0
  407. package/src/avatar/Avatar.tsx +217 -0
  408. package/src/avatar/index.ts +2 -0
  409. package/src/avatar/types.ts +32 -0
  410. package/src/button/Button.tsx +172 -0
  411. package/src/button/index.ts +10 -0
  412. package/src/button/types.ts +25 -0
  413. package/src/collapsible/Collapsible.tsx +62 -0
  414. package/src/collapsible/index.ts +2 -0
  415. package/src/collapsible/types.ts +18 -0
  416. package/src/dialog/Dialog.tsx +160 -0
  417. package/src/dialog/Dialog.web.tsx +238 -0
  418. package/src/dialog/context.ts +34 -0
  419. package/src/dialog/index.ts +3 -0
  420. package/src/dialog/types.ts +34 -0
  421. package/src/divider/Divider.tsx +42 -0
  422. package/src/divider/index.ts +2 -0
  423. package/src/divider/types.ts +15 -0
  424. package/src/error-boundary/ErrorBoundary.tsx +112 -0
  425. package/src/error-boundary/index.ts +2 -0
  426. package/src/error-boundary/types.ts +16 -0
  427. package/src/grouped-buttons/GroupedButtons.tsx +94 -0
  428. package/src/grouped-buttons/index.ts +2 -0
  429. package/src/grouped-buttons/types.ts +16 -0
  430. package/src/index.ts +14 -0
  431. package/src/loading/Loading.tsx +258 -0
  432. package/src/loading/index.ts +10 -0
  433. package/src/loading/types.ts +69 -0
  434. package/src/portal/index.tsx +100 -0
  435. package/src/prompt/Prompt.tsx +248 -0
  436. package/src/prompt/index.ts +13 -0
  437. package/src/prompt-input/Actions.tsx +45 -0
  438. package/src/prompt-input/Attachments.tsx +264 -0
  439. package/src/prompt-input/PromptInput.tsx +263 -0
  440. package/src/prompt-input/SubmitButton.tsx +74 -0
  441. package/src/prompt-input/Textarea.tsx +102 -0
  442. package/src/prompt-input/Textarea.web.tsx +154 -0
  443. package/src/prompt-input/context.ts +59 -0
  444. package/src/prompt-input/index.ts +18 -0
  445. package/src/prompt-input/types.ts +92 -0
  446. package/src/radio-indicator/RadioIndicator.tsx +52 -0
  447. package/src/radio-indicator/index.ts +2 -0
  448. package/src/radio-indicator/types.ts +15 -0
  449. package/src/theme/BloomThemeProvider.tsx +160 -0
  450. package/src/theme/adaptive-colors.ts +90 -0
  451. package/src/theme/apply-dark-class.ts +7 -0
  452. package/src/theme/color-presets.ts +499 -0
  453. package/src/theme/index.ts +6 -0
  454. package/src/theme/set-color-scheme-safe.ts +19 -0
  455. package/src/theme/types.ts +48 -0
  456. package/src/theme/use-theme.ts +24 -0
@@ -0,0 +1,154 @@
1
+ import React, { useCallback, useEffect, useImperativeHandle, useRef } from 'react';
2
+ import {
3
+ TextInput,
4
+ View,
5
+ type NativeSyntheticEvent,
6
+ type TextInputContentSizeChangeEventData,
7
+ type TextInputKeyPressEventData,
8
+ } from 'react-native';
9
+
10
+ import { useTheme } from '../theme/use-theme';
11
+ import { usePromptInput } from './context';
12
+ import type { PromptInputTextareaProps } from './types';
13
+
14
+ export function PromptInputTextarea({
15
+ placeholder,
16
+ style,
17
+ inputStyle,
18
+ textInputProps,
19
+ testID,
20
+ }: PromptInputTextareaProps) {
21
+ const {
22
+ value,
23
+ setValue,
24
+ onSubmit,
25
+ disabled,
26
+ textareaRef,
27
+ setCurrentHeight,
28
+ isFullscreen,
29
+ maxHeight,
30
+ onImagePaste,
31
+ handleCompletionKey,
32
+ } = usePromptInput();
33
+ const theme = useTheme();
34
+ const inputRef = useRef<TextInput>(null);
35
+ const wrapperRef = useRef<View>(null);
36
+
37
+ useImperativeHandle(textareaRef, () => inputRef.current as TextInput);
38
+
39
+ // Web-only: paste event listener for images
40
+ useEffect(() => {
41
+ if (!onImagePaste) return;
42
+
43
+ const handlePaste = (e: ClipboardEvent) => {
44
+ const activeElement = document.activeElement;
45
+ const wrapper = wrapperRef.current as unknown as HTMLElement | null;
46
+
47
+ if (!wrapper || !wrapper.contains(activeElement)) return;
48
+
49
+ const items = e.clipboardData?.items;
50
+ if (!items) return;
51
+
52
+ const imageFiles: File[] = [];
53
+ for (let i = 0; i < items.length; i++) {
54
+ const item = items[i]!;
55
+ if (item.type.indexOf('image') !== -1) {
56
+ const file = item.getAsFile();
57
+ if (file) imageFiles.push(file);
58
+ }
59
+ }
60
+
61
+ if (imageFiles.length > 0) {
62
+ e.preventDefault();
63
+ onImagePaste(imageFiles);
64
+ }
65
+ };
66
+
67
+ document.addEventListener('paste', handlePaste);
68
+ return () => document.removeEventListener('paste', handlePaste);
69
+ }, [onImagePaste]);
70
+
71
+ const handleKeyPress = useCallback(
72
+ (e: NativeSyntheticEvent<TextInputKeyPressEventData>) => {
73
+ textInputProps?.onKeyPress?.(e);
74
+ const key = e.nativeEvent.key;
75
+
76
+ // Autocomplete key navigation
77
+ if (handleCompletionKey && ['ArrowUp', 'ArrowDown', 'Enter', 'Escape'].includes(key)) {
78
+ if (handleCompletionKey(key)) {
79
+ e.preventDefault();
80
+ return;
81
+ }
82
+ }
83
+
84
+ // Enter-to-submit (without Shift) when not in fullscreen
85
+ if (key === 'Enter' && !isFullscreen) {
86
+ const nativeEvent = e.nativeEvent as TextInputKeyPressEventData & { shiftKey?: boolean };
87
+ if (!nativeEvent.shiftKey) {
88
+ e.preventDefault();
89
+ onSubmit?.();
90
+ }
91
+ }
92
+ },
93
+ [handleCompletionKey, isFullscreen, onSubmit, textInputProps],
94
+ );
95
+
96
+ const handleContentSizeChange = useCallback(
97
+ (e: NativeSyntheticEvent<TextInputContentSizeChangeEventData>) => {
98
+ textInputProps?.onContentSizeChange?.(e);
99
+ },
100
+ [textInputProps],
101
+ );
102
+
103
+ const fieldSizingStyle = !isFullscreen
104
+ ? { fieldSizing: 'content', minHeight: 44, maxHeight, overflow: 'auto' }
105
+ : undefined;
106
+
107
+ const textInput = (
108
+ <View
109
+ ref={wrapperRef}
110
+ style={[{ width: '100%' }, isFullscreen && { flex: 1 }]}
111
+ onLayout={(e) => setCurrentHeight(e.nativeEvent.layout.height)}
112
+ >
113
+ <TextInput
114
+ ref={inputRef}
115
+ accessibilityLabel="Message input"
116
+ value={value}
117
+ onChangeText={setValue}
118
+ onSubmitEditing={onSubmit}
119
+ onKeyPress={handleKeyPress}
120
+ onContentSizeChange={handleContentSizeChange}
121
+ multiline
122
+ editable={!disabled}
123
+ scrollEnabled={isFullscreen}
124
+ placeholder={placeholder}
125
+ placeholderTextColor={theme.colors.textTertiary}
126
+ style={[
127
+ {
128
+ width: '100%',
129
+ fontSize: 16,
130
+ color: theme.colors.text,
131
+ paddingHorizontal: 14,
132
+ backgroundColor: 'transparent',
133
+ borderWidth: 0,
134
+ },
135
+ // Web-only: remove focus outline
136
+ { outlineStyle: 'none' } as Record<string, string>,
137
+ isFullscreen
138
+ ? { flex: 1, paddingTop: 16, paddingBottom: 100 }
139
+ : { paddingVertical: 12 },
140
+ fieldSizingStyle as Record<string, unknown>,
141
+ inputStyle,
142
+ ]}
143
+ testID={testID}
144
+ {...textInputProps}
145
+ />
146
+ </View>
147
+ );
148
+
149
+ if (isFullscreen) {
150
+ return <View style={[{ flex: 1 }, style]}>{textInput}</View>;
151
+ }
152
+
153
+ return <View style={style}>{textInput}</View>;
154
+ }
@@ -0,0 +1,59 @@
1
+ import React, { createContext, useContext } from 'react';
2
+ import type { TextInput as RNTextInput } from 'react-native';
3
+
4
+ export interface Attachment {
5
+ id: string;
6
+ uri: string;
7
+ type: 'image' | 'document';
8
+ name: string;
9
+ size: number;
10
+ mimeType: string;
11
+ isLoading?: boolean;
12
+ }
13
+
14
+ export type PromptInputContextType = {
15
+ isLoading: boolean;
16
+ value: string;
17
+ setValue: (value: string) => void;
18
+ maxHeight: number;
19
+ onSubmit?: () => void;
20
+ disabled?: boolean;
21
+ textareaRef: React.RefObject<RNTextInput | null>;
22
+ currentHeight: number;
23
+ setCurrentHeight: (height: number) => void;
24
+ isFullscreen: boolean;
25
+ onImagePaste?: (files: File[]) => void;
26
+ attachments: Attachment[];
27
+ addAttachment: (attachment: Attachment) => void;
28
+ removeAttachment: (id: string) => void;
29
+ updateAttachment: (id: string, updates: Partial<Attachment>) => void;
30
+ handleCompletionKey: ((key: string) => boolean) | null;
31
+ setHandleCompletionKey: (fn: ((key: string) => boolean) | null) => void;
32
+ };
33
+
34
+ export const PromptInputContext = createContext<PromptInputContextType>({
35
+ isLoading: false,
36
+ value: '',
37
+ setValue: () => {},
38
+ maxHeight: 240,
39
+ onSubmit: undefined,
40
+ disabled: false,
41
+ textareaRef: React.createRef<RNTextInput>(),
42
+ currentHeight: 44,
43
+ setCurrentHeight: () => {},
44
+ isFullscreen: false,
45
+ attachments: [],
46
+ addAttachment: () => {},
47
+ removeAttachment: () => {},
48
+ updateAttachment: () => {},
49
+ handleCompletionKey: null,
50
+ setHandleCompletionKey: () => {},
51
+ });
52
+
53
+ export function usePromptInput(): PromptInputContextType {
54
+ return useContext(PromptInputContext);
55
+ }
56
+
57
+ export function useIsFullscreen(): boolean {
58
+ return useContext(PromptInputContext).isFullscreen;
59
+ }
@@ -0,0 +1,18 @@
1
+ export { PromptInput } from './PromptInput';
2
+ export { PromptInputTextarea } from './Textarea';
3
+ export { PromptInputActions } from './Actions';
4
+ export { PromptInputAttachments } from './Attachments';
5
+ export { PromptInputSubmitButton } from './SubmitButton';
6
+ export {
7
+ usePromptInput,
8
+ useIsFullscreen,
9
+ type Attachment,
10
+ type PromptInputContextType,
11
+ } from './context';
12
+ export type {
13
+ PromptInputProps,
14
+ PromptInputTextareaProps,
15
+ PromptInputSubmitButtonProps,
16
+ PromptInputActionsProps,
17
+ PromptInputAttachmentsProps,
18
+ } from './types';
@@ -0,0 +1,92 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { StyleProp, ViewStyle, TextStyle, TextInputProps } from 'react-native';
3
+ import type { Attachment } from './context';
4
+
5
+ export interface PromptInputProps {
6
+ /** Whether the AI is currently generating a response */
7
+ isLoading?: boolean;
8
+ /** Controlled text value */
9
+ value?: string;
10
+ /** Callback when text value changes */
11
+ onValueChange?: (value: string) => void;
12
+ /** Max height for the textarea before scrolling (defaults to 240) */
13
+ maxHeight?: number;
14
+ /** Called when user submits the prompt */
15
+ onSubmit?: () => void;
16
+ /** Compound mode children (overrides simple mode) */
17
+ children?: ReactNode;
18
+ /** Container style */
19
+ style?: StyleProp<ViewStyle>;
20
+ /** Whether the input is disabled */
21
+ disabled?: boolean;
22
+ /** Web-only: callback when images are pasted */
23
+ onImagePaste?: (files: File[]) => void;
24
+ /** Simple mode: placeholder text */
25
+ placeholder?: string;
26
+ /** Custom left-side actions in the actions bar */
27
+ actionsLeft?: ReactNode;
28
+ /** Called when user presses stop during loading */
29
+ onStop?: () => void;
30
+ /** Rendered when input is empty and not loading (e.g., mic button) */
31
+ emptyAction?: ReactNode;
32
+ /** Controlled attachments */
33
+ attachments?: Attachment[];
34
+ /** Callback to add an attachment */
35
+ onAddAttachment?: (attachment: Attachment) => void;
36
+ /** Callback to remove an attachment */
37
+ onRemoveAttachment?: (id: string) => void;
38
+ /** Callback to update an attachment */
39
+ onUpdateAttachment?: (id: string, updates: Partial<Attachment>) => void;
40
+ /** Skip the inner KeyboardAvoidingView (use when outer keyboard handling exists) */
41
+ disableKeyboardAvoidance?: boolean;
42
+ /** Icon shown on the expand button (defaults to text "⤢") */
43
+ expandIcon?: ReactNode;
44
+ /** Icon shown on the collapse button in fullscreen (defaults to text "⤡") */
45
+ collapseIcon?: ReactNode;
46
+ testID?: string;
47
+ }
48
+
49
+ export interface PromptInputTextareaProps {
50
+ /** Placeholder text */
51
+ placeholder?: string;
52
+ /** Container style */
53
+ style?: StyleProp<ViewStyle>;
54
+ /** Text input style */
55
+ inputStyle?: StyleProp<TextStyle>;
56
+ /** Additional TextInput props */
57
+ textInputProps?: Omit<TextInputProps, 'value' | 'onChangeText' | 'multiline' | 'editable'>;
58
+ testID?: string;
59
+ }
60
+
61
+ export interface PromptInputSubmitButtonProps {
62
+ /** Whether the AI is currently generating */
63
+ isLoading?: boolean;
64
+ /** Called when user presses stop */
65
+ onStop?: () => void;
66
+ /** Rendered when input is empty and not loading */
67
+ emptyAction?: ReactNode;
68
+ /** Custom submit icon (defaults to "↑" text) */
69
+ submitIcon?: ReactNode;
70
+ /** Custom stop icon (defaults to "■" text) */
71
+ stopIcon?: ReactNode;
72
+ /** Container style */
73
+ style?: StyleProp<ViewStyle>;
74
+ testID?: string;
75
+ }
76
+
77
+ export interface PromptInputActionsProps {
78
+ children: ReactNode;
79
+ /** Container style */
80
+ style?: StyleProp<ViewStyle>;
81
+ testID?: string;
82
+ }
83
+
84
+ export interface PromptInputAttachmentsProps {
85
+ /** Custom remove button icon (defaults to "×" text) */
86
+ removeIcon?: ReactNode;
87
+ /** Custom render function for document type icons */
88
+ renderDocumentIcon?: (mimeType: string, name: string) => ReactNode;
89
+ /** Container style */
90
+ style?: StyleProp<ViewStyle>;
91
+ testID?: string;
92
+ }
@@ -0,0 +1,52 @@
1
+ import React, { memo } from 'react';
2
+ import { View } from 'react-native';
3
+
4
+ import { useTheme } from '../theme/use-theme';
5
+ import type { RadioIndicatorProps } from './types';
6
+
7
+ const RadioIndicatorComponent: React.FC<RadioIndicatorProps> = ({
8
+ selected,
9
+ size = 20,
10
+ selectedColor,
11
+ borderColor,
12
+ style,
13
+ testID,
14
+ }) => {
15
+ const theme = useTheme();
16
+ const resolvedSelectedColor = selectedColor ?? theme.colors.primary;
17
+ const resolvedBorderColor = borderColor ?? theme.colors.border;
18
+ const dotSize = size * 0.5;
19
+
20
+ return (
21
+ <View
22
+ testID={testID}
23
+ style={[
24
+ {
25
+ width: size,
26
+ height: size,
27
+ borderRadius: size / 2,
28
+ borderWidth: selected ? 0 : 2,
29
+ borderColor: selected ? undefined : resolvedBorderColor,
30
+ backgroundColor: selected ? resolvedSelectedColor : 'transparent',
31
+ alignItems: 'center',
32
+ justifyContent: 'center',
33
+ },
34
+ style,
35
+ ]}
36
+ >
37
+ {selected && (
38
+ <View
39
+ style={{
40
+ width: dotSize,
41
+ height: dotSize,
42
+ borderRadius: dotSize / 2,
43
+ backgroundColor: '#FFFFFF',
44
+ }}
45
+ />
46
+ )}
47
+ </View>
48
+ );
49
+ };
50
+
51
+ export const RadioIndicator = memo(RadioIndicatorComponent);
52
+ RadioIndicator.displayName = 'RadioIndicator';
@@ -0,0 +1,2 @@
1
+ export { RadioIndicator } from './RadioIndicator';
2
+ export type { RadioIndicatorProps } from './types';
@@ -0,0 +1,15 @@
1
+ import type { StyleProp, ViewStyle } from 'react-native';
2
+
3
+ export interface RadioIndicatorProps {
4
+ /** Whether the radio is selected */
5
+ selected: boolean;
6
+ /** Outer circle size in pixels (defaults to 20) */
7
+ size?: number;
8
+ /** Color when selected (defaults to theme.colors.primary) */
9
+ selectedColor?: string;
10
+ /** Border color when unselected (defaults to theme.colors.border) */
11
+ borderColor?: string;
12
+ /** Custom style */
13
+ style?: StyleProp<ViewStyle>;
14
+ testID?: string;
15
+ }
@@ -0,0 +1,160 @@
1
+ import React, { createContext, useCallback, useEffect, useMemo } from 'react';
2
+ import { useColorScheme as useRNColorScheme, Platform } from 'react-native';
3
+ import { APP_COLOR_PRESETS, type AppColorName } from './color-presets';
4
+ import { getAdaptiveColors } from './adaptive-colors';
5
+ import { applyDarkClass } from './apply-dark-class';
6
+ import { setColorSchemeSafe } from './set-color-scheme-safe';
7
+ import type { Theme, ThemeColors, ThemeMode } from './types';
8
+
9
+ function hslVarToCSS(value: string): string {
10
+ const parts = value.split('/').map((s) => s.trim());
11
+ if (parts.length === 2) {
12
+ const alpha = parseFloat(parts[1]!) / 100;
13
+ return `hsla(${parts[0]!.replace(/ /g, ', ')}, ${alpha})`;
14
+ }
15
+ return `hsl(${value.replace(/ /g, ', ')})`;
16
+ }
17
+
18
+ function extractHue(hslVar: string): number {
19
+ return parseInt(hslVar.split(' ')[0]!, 10);
20
+ }
21
+
22
+ function hsl(h: number, s: number, l: number): string {
23
+ return `hsl(${h}, ${s}%, ${l}%)`;
24
+ }
25
+
26
+ export interface BloomThemeContextValue {
27
+ theme: Theme;
28
+ mode: ThemeMode;
29
+ colorPreset: AppColorName;
30
+ setMode: (mode: ThemeMode) => void;
31
+ setColorPreset: (preset: AppColorName) => void;
32
+ }
33
+
34
+ export const BloomThemeContext = createContext<BloomThemeContextValue | null>(null);
35
+
36
+ export interface BloomThemeProviderProps {
37
+ mode?: ThemeMode;
38
+ colorPreset?: AppColorName;
39
+ onModeChange?: (mode: ThemeMode) => void;
40
+ onColorPresetChange?: (preset: AppColorName) => void;
41
+ children: React.ReactNode;
42
+ }
43
+
44
+ export function BloomThemeProvider({
45
+ mode: controlledMode,
46
+ colorPreset: controlledPreset,
47
+ onModeChange,
48
+ onColorPresetChange,
49
+ children,
50
+ }: BloomThemeProviderProps) {
51
+ const rnScheme = useRNColorScheme();
52
+
53
+ const mode = controlledMode ?? 'system';
54
+ const appColor = controlledPreset ?? 'teal';
55
+
56
+ const isAdaptive = mode === 'adaptive';
57
+ const effectiveMode = isAdaptive ? 'system' : mode;
58
+ const resolved: 'light' | 'dark' =
59
+ effectiveMode === 'system'
60
+ ? (rnScheme === 'dark' ? 'dark' : 'light')
61
+ : effectiveMode;
62
+
63
+ useEffect(() => {
64
+ applyDarkClass(resolved);
65
+ }, [resolved]);
66
+
67
+ const setMode = useCallback(
68
+ (newMode: ThemeMode) => {
69
+ setColorSchemeSafe(newMode);
70
+ onModeChange?.(newMode);
71
+ },
72
+ [onModeChange],
73
+ );
74
+
75
+ const setColorPreset = useCallback(
76
+ (preset: AppColorName) => {
77
+ onColorPresetChange?.(preset);
78
+ },
79
+ [onColorPresetChange],
80
+ );
81
+
82
+ const contextValue = useMemo<BloomThemeContextValue>(() => {
83
+ const isDark = resolved === 'dark';
84
+
85
+ let themeColors: ThemeColors;
86
+
87
+ if (isAdaptive && Platform.OS !== 'web') {
88
+ const adaptive = getAdaptiveColors();
89
+ if (adaptive) {
90
+ themeColors = adaptive;
91
+ }
92
+ }
93
+
94
+ if (!themeColors!) {
95
+ const preset = APP_COLOR_PRESETS[appColor];
96
+ const vars = resolved === 'light' ? preset.light : preset.dark;
97
+ const primaryHue = extractHue(vars['--primary']!);
98
+ const destructiveHue = extractHue(vars['--destructive']!);
99
+
100
+ const surface = hslVarToCSS(vars['--surface']!);
101
+ const background = hslVarToCSS(vars['--background']!);
102
+ const mutedForeground = hslVarToCSS(vars['--muted-foreground']!);
103
+
104
+ themeColors = {
105
+ background,
106
+ backgroundSecondary: surface,
107
+ backgroundTertiary: hslVarToCSS(vars['--muted']!),
108
+
109
+ text: hslVarToCSS(vars['--foreground']!),
110
+ textSecondary: mutedForeground,
111
+ textTertiary: mutedForeground,
112
+
113
+ border: hslVarToCSS(vars['--border']!),
114
+ borderLight: hslVarToCSS(vars['--input']!),
115
+
116
+ primary: preset.hex,
117
+ primaryLight: surface,
118
+ primaryDark: background,
119
+
120
+ secondary: preset.hex,
121
+
122
+ tint: preset.hex,
123
+ icon: mutedForeground,
124
+ iconActive: preset.hex,
125
+
126
+ success: '#10B981',
127
+ error: '#EF4444',
128
+ warning: '#F59E0B',
129
+ info: '#3B82F6',
130
+
131
+ primarySubtle: isDark ? hsl(primaryHue, 50, 10) : hsl(primaryHue, 70, 93),
132
+ primarySubtleForeground: isDark ? hsl(primaryHue, 70, 65) : hsl(primaryHue, 90, 25),
133
+ negative: hsl(destructiveHue, 84, 45),
134
+ negativeForeground: '#FFFFFF',
135
+ negativeSubtle: isDark ? hsl(destructiveHue, 50, 10) : hsl(destructiveHue, 90, 95),
136
+ negativeSubtleForeground: isDark ? hsl(destructiveHue, 70, 65) : hsl(destructiveHue, 80, 40),
137
+ contrast50: isDark ? hsl(primaryHue, 15, 12) : hsl(primaryHue, 10, 93),
138
+
139
+ card: surface,
140
+ shadow: isDark ? 'rgba(0, 0, 0, 0.3)' : 'rgba(0, 0, 0, 0.1)',
141
+ overlay: 'rgba(0, 0, 0, 0.5)',
142
+ };
143
+ }
144
+
145
+ const theme: Theme = {
146
+ mode: resolved,
147
+ colors: themeColors,
148
+ isDark,
149
+ isLight: !isDark,
150
+ };
151
+
152
+ return { theme, mode, colorPreset: appColor, setMode, setColorPreset };
153
+ }, [resolved, appColor, isAdaptive, mode, setMode, setColorPreset]);
154
+
155
+ return (
156
+ <BloomThemeContext.Provider value={contextValue}>
157
+ {children}
158
+ </BloomThemeContext.Provider>
159
+ );
160
+ }
@@ -0,0 +1,90 @@
1
+ import { Platform } from 'react-native';
2
+ import type { ThemeColors } from './types';
3
+
4
+ const c = (v: unknown): string => v as string;
5
+
6
+ function getAndroidColors(): ThemeColors | null {
7
+ try {
8
+ const { Color } = require('expo-router');
9
+ const d = Color.android.dynamic;
10
+ return {
11
+ background: c(d.surface),
12
+ backgroundSecondary: c(d.surfaceContainerLow),
13
+ backgroundTertiary: c(d.surfaceContainer),
14
+ text: c(d.onSurface),
15
+ textSecondary: c(d.onSurfaceVariant),
16
+ textTertiary: c(d.outline),
17
+ border: c(d.outlineVariant),
18
+ borderLight: c(d.outline),
19
+ primary: c(d.primary),
20
+ primaryLight: c(d.primaryContainer),
21
+ primaryDark: c(d.onPrimaryContainer),
22
+ secondary: c(d.secondary),
23
+ tint: c(d.primary),
24
+ icon: c(d.onSurfaceVariant),
25
+ iconActive: c(d.primary),
26
+ success: '#10B981',
27
+ error: '#EF4444',
28
+ warning: '#F59E0B',
29
+ info: '#3B82F6',
30
+ primarySubtle: c(d.primaryContainer),
31
+ primarySubtleForeground: c(d.onPrimaryContainer),
32
+ negative: '#B91C1C',
33
+ negativeForeground: '#FFFFFF',
34
+ negativeSubtle: c(d.errorContainer),
35
+ negativeSubtleForeground: c(d.onErrorContainer),
36
+ contrast50: c(d.surfaceContainerLow),
37
+ card: c(d.surfaceContainerLow),
38
+ shadow: 'rgba(0, 0, 0, 0.2)',
39
+ overlay: 'rgba(0, 0, 0, 0.5)',
40
+ };
41
+ } catch {
42
+ return null;
43
+ }
44
+ }
45
+
46
+ function getIOSColors(): ThemeColors | null {
47
+ try {
48
+ const { Color } = require('expo-router');
49
+ const i = Color.ios;
50
+ return {
51
+ background: c(i.systemBackground),
52
+ backgroundSecondary: c(i.secondarySystemBackground),
53
+ backgroundTertiary: c(i.tertiarySystemBackground),
54
+ text: c(i.label),
55
+ textSecondary: c(i.secondaryLabel),
56
+ textTertiary: c(i.tertiaryLabel),
57
+ border: c(i.separator),
58
+ borderLight: c(i.opaqueSeparator),
59
+ primary: c(i.systemBlue),
60
+ primaryLight: c(i.systemGray6),
61
+ primaryDark: c(i.systemBlue),
62
+ secondary: c(i.systemPurple),
63
+ tint: c(i.systemBlue),
64
+ icon: c(i.secondaryLabel),
65
+ iconActive: c(i.systemBlue),
66
+ success: c(i.systemGreen),
67
+ error: c(i.systemRed),
68
+ warning: c(i.systemOrange),
69
+ info: c(i.systemBlue),
70
+ primarySubtle: c(i.systemGray6),
71
+ primarySubtleForeground: c(i.systemBlue),
72
+ negative: c(i.systemRed),
73
+ negativeForeground: '#FFFFFF',
74
+ negativeSubtle: c(i.systemGray6),
75
+ negativeSubtleForeground: c(i.systemRed),
76
+ contrast50: c(i.systemGray6),
77
+ card: c(i.secondarySystemBackground),
78
+ shadow: 'rgba(0, 0, 0, 0.15)',
79
+ overlay: 'rgba(0, 0, 0, 0.5)',
80
+ };
81
+ } catch {
82
+ return null;
83
+ }
84
+ }
85
+
86
+ export function getAdaptiveColors(): ThemeColors | null {
87
+ if (Platform.OS === 'android') return getAndroidColors();
88
+ if (Platform.OS === 'ios') return getIOSColors();
89
+ return null;
90
+ }
@@ -0,0 +1,7 @@
1
+ import { Platform } from 'react-native';
2
+
3
+ export function applyDarkClass(resolved: 'light' | 'dark') {
4
+ if (Platform.OS === 'web' && typeof document !== 'undefined') {
5
+ document.documentElement.classList.toggle('dark', resolved === 'dark');
6
+ }
7
+ }