@entropy-softworks/ui 2026.7.31

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 (590) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/LICENSE +21 -0
  3. package/README.md +115 -0
  4. package/lib/components/auth/LockOverlay.d.ts +22 -0
  5. package/lib/components/auth/LockOverlay.d.ts.map +1 -0
  6. package/lib/components/auth/LockOverlay.jsx +82 -0
  7. package/lib/components/auth/LockOverlay.jsx.map +1 -0
  8. package/lib/components/auth/PasswordStrengthMeter.d.ts +12 -0
  9. package/lib/components/auth/PasswordStrengthMeter.d.ts.map +1 -0
  10. package/lib/components/auth/PasswordStrengthMeter.jsx +81 -0
  11. package/lib/components/auth/PasswordStrengthMeter.jsx.map +1 -0
  12. package/lib/components/auth/ProtectedRoute.d.ts +24 -0
  13. package/lib/components/auth/ProtectedRoute.d.ts.map +1 -0
  14. package/lib/components/auth/ProtectedRoute.jsx +56 -0
  15. package/lib/components/auth/ProtectedRoute.jsx.map +1 -0
  16. package/lib/components/auth/PwnedPasswordWarning.d.ts +13 -0
  17. package/lib/components/auth/PwnedPasswordWarning.d.ts.map +1 -0
  18. package/lib/components/auth/PwnedPasswordWarning.jsx +29 -0
  19. package/lib/components/auth/PwnedPasswordWarning.jsx.map +1 -0
  20. package/lib/components/auth/index.d.ts +5 -0
  21. package/lib/components/auth/index.d.ts.map +1 -0
  22. package/lib/components/auth/index.js +5 -0
  23. package/lib/components/auth/index.js.map +1 -0
  24. package/lib/components/bottom-nav.d.ts +25 -0
  25. package/lib/components/bottom-nav.d.ts.map +1 -0
  26. package/lib/components/bottom-nav.jsx +51 -0
  27. package/lib/components/bottom-nav.jsx.map +1 -0
  28. package/lib/components/button.d.ts +16 -0
  29. package/lib/components/button.d.ts.map +1 -0
  30. package/lib/components/button.jsx +73 -0
  31. package/lib/components/button.jsx.map +1 -0
  32. package/lib/components/card.d.ts +22 -0
  33. package/lib/components/card.d.ts.map +1 -0
  34. package/lib/components/card.jsx +36 -0
  35. package/lib/components/card.jsx.map +1 -0
  36. package/lib/components/checkbox.d.ts +12 -0
  37. package/lib/components/checkbox.d.ts.map +1 -0
  38. package/lib/components/checkbox.jsx +16 -0
  39. package/lib/components/checkbox.jsx.map +1 -0
  40. package/lib/components/connection-settings.d.ts +41 -0
  41. package/lib/components/connection-settings.d.ts.map +1 -0
  42. package/lib/components/connection-settings.jsx +354 -0
  43. package/lib/components/connection-settings.jsx.map +1 -0
  44. package/lib/components/context-menu.d.ts +52 -0
  45. package/lib/components/context-menu.d.ts.map +1 -0
  46. package/lib/components/context-menu.jsx +24 -0
  47. package/lib/components/context-menu.jsx.map +1 -0
  48. package/lib/components/data-table.d.ts +59 -0
  49. package/lib/components/data-table.d.ts.map +1 -0
  50. package/lib/components/data-table.jsx +101 -0
  51. package/lib/components/data-table.jsx.map +1 -0
  52. package/lib/components/dialog.d.ts +58 -0
  53. package/lib/components/dialog.d.ts.map +1 -0
  54. package/lib/components/dialog.jsx +197 -0
  55. package/lib/components/dialog.jsx.map +1 -0
  56. package/lib/components/dropdown-menu.d.ts +55 -0
  57. package/lib/components/dropdown-menu.d.ts.map +1 -0
  58. package/lib/components/dropdown-menu.jsx +38 -0
  59. package/lib/components/dropdown-menu.jsx.map +1 -0
  60. package/lib/components/entropy-boot-splash.d.ts +24 -0
  61. package/lib/components/entropy-boot-splash.d.ts.map +1 -0
  62. package/lib/components/entropy-boot-splash.jsx +83 -0
  63. package/lib/components/entropy-boot-splash.jsx.map +1 -0
  64. package/lib/components/entropy-mark-animated.d.ts +20 -0
  65. package/lib/components/entropy-mark-animated.d.ts.map +1 -0
  66. package/lib/components/entropy-mark-animated.jsx +148 -0
  67. package/lib/components/entropy-mark-animated.jsx.map +1 -0
  68. package/lib/components/entropy-mark-geometry.d.ts +8 -0
  69. package/lib/components/entropy-mark-geometry.d.ts.map +1 -0
  70. package/lib/components/entropy-mark-geometry.js +10 -0
  71. package/lib/components/entropy-mark-geometry.js.map +1 -0
  72. package/lib/components/entropy-mark-sequential.d.ts +12 -0
  73. package/lib/components/entropy-mark-sequential.d.ts.map +1 -0
  74. package/lib/components/entropy-mark-sequential.jsx +53 -0
  75. package/lib/components/entropy-mark-sequential.jsx.map +1 -0
  76. package/lib/components/entropy-mark.d.ts +29 -0
  77. package/lib/components/entropy-mark.d.ts.map +1 -0
  78. package/lib/components/entropy-mark.jsx +66 -0
  79. package/lib/components/entropy-mark.jsx.map +1 -0
  80. package/lib/components/error-boundary.d.ts +31 -0
  81. package/lib/components/error-boundary.d.ts.map +1 -0
  82. package/lib/components/error-boundary.jsx +40 -0
  83. package/lib/components/error-boundary.jsx.map +1 -0
  84. package/lib/components/index.d.ts +41 -0
  85. package/lib/components/index.d.ts.map +1 -0
  86. package/lib/components/index.js +43 -0
  87. package/lib/components/index.js.map +1 -0
  88. package/lib/components/input.d.ts +26 -0
  89. package/lib/components/input.d.ts.map +1 -0
  90. package/lib/components/input.jsx +95 -0
  91. package/lib/components/input.jsx.map +1 -0
  92. package/lib/components/item-icon.d.ts +32 -0
  93. package/lib/components/item-icon.d.ts.map +1 -0
  94. package/lib/components/item-icon.jsx +54 -0
  95. package/lib/components/item-icon.jsx.map +1 -0
  96. package/lib/components/label.d.ts +13 -0
  97. package/lib/components/label.d.ts.map +1 -0
  98. package/lib/components/label.jsx +9 -0
  99. package/lib/components/label.jsx.map +1 -0
  100. package/lib/components/legal-dialog.d.ts +18 -0
  101. package/lib/components/legal-dialog.d.ts.map +1 -0
  102. package/lib/components/legal-dialog.jsx +31 -0
  103. package/lib/components/legal-dialog.jsx.map +1 -0
  104. package/lib/components/license-gate.d.ts +17 -0
  105. package/lib/components/license-gate.d.ts.map +1 -0
  106. package/lib/components/license-gate.jsx +21 -0
  107. package/lib/components/license-gate.jsx.map +1 -0
  108. package/lib/components/logo.d.ts +15 -0
  109. package/lib/components/logo.d.ts.map +1 -0
  110. package/lib/components/logo.jsx +20 -0
  111. package/lib/components/logo.jsx.map +1 -0
  112. package/lib/components/onboarding-wizard.d.ts +89 -0
  113. package/lib/components/onboarding-wizard.d.ts.map +1 -0
  114. package/lib/components/onboarding-wizard.jsx +185 -0
  115. package/lib/components/onboarding-wizard.jsx.map +1 -0
  116. package/lib/components/pagination.d.ts +43 -0
  117. package/lib/components/pagination.d.ts.map +1 -0
  118. package/lib/components/pagination.jsx +72 -0
  119. package/lib/components/pagination.jsx.map +1 -0
  120. package/lib/components/password-generator.d.ts +15 -0
  121. package/lib/components/password-generator.d.ts.map +1 -0
  122. package/lib/components/password-generator.jsx +273 -0
  123. package/lib/components/password-generator.jsx.map +1 -0
  124. package/lib/components/pin-pad.d.ts +20 -0
  125. package/lib/components/pin-pad.d.ts.map +1 -0
  126. package/lib/components/pin-pad.jsx +93 -0
  127. package/lib/components/pin-pad.jsx.map +1 -0
  128. package/lib/components/popover.d.ts +27 -0
  129. package/lib/components/popover.d.ts.map +1 -0
  130. package/lib/components/popover.jsx +18 -0
  131. package/lib/components/popover.jsx.map +1 -0
  132. package/lib/components/profile/ProfileDialog.d.ts +25 -0
  133. package/lib/components/profile/ProfileDialog.d.ts.map +1 -0
  134. package/lib/components/profile/ProfileDialog.jsx +71 -0
  135. package/lib/components/profile/ProfileDialog.jsx.map +1 -0
  136. package/lib/components/profile/ProfileTab.d.ts +12 -0
  137. package/lib/components/profile/ProfileTab.d.ts.map +1 -0
  138. package/lib/components/profile/ProfileTab.jsx +112 -0
  139. package/lib/components/profile/ProfileTab.jsx.map +1 -0
  140. package/lib/components/profile/SecurityTab.d.ts +32 -0
  141. package/lib/components/profile/SecurityTab.d.ts.map +1 -0
  142. package/lib/components/profile/SecurityTab.jsx +145 -0
  143. package/lib/components/profile/SecurityTab.jsx.map +1 -0
  144. package/lib/components/profile/index.d.ts +4 -0
  145. package/lib/components/profile/index.d.ts.map +1 -0
  146. package/lib/components/profile/index.js +4 -0
  147. package/lib/components/profile/index.js.map +1 -0
  148. package/lib/components/segmented-toggle.d.ts +28 -0
  149. package/lib/components/segmented-toggle.d.ts.map +1 -0
  150. package/lib/components/segmented-toggle.jsx +64 -0
  151. package/lib/components/segmented-toggle.jsx.map +1 -0
  152. package/lib/components/separator.d.ts +13 -0
  153. package/lib/components/separator.d.ts.map +1 -0
  154. package/lib/components/separator.jsx +16 -0
  155. package/lib/components/separator.jsx.map +1 -0
  156. package/lib/components/server-settings.d.ts +27 -0
  157. package/lib/components/server-settings.d.ts.map +1 -0
  158. package/lib/components/server-settings.jsx +307 -0
  159. package/lib/components/server-settings.jsx.map +1 -0
  160. package/lib/components/settings/AccountSection.d.ts +26 -0
  161. package/lib/components/settings/AccountSection.d.ts.map +1 -0
  162. package/lib/components/settings/AccountSection.jsx +32 -0
  163. package/lib/components/settings/AccountSection.jsx.map +1 -0
  164. package/lib/components/settings/DangerZoneSection.d.ts +13 -0
  165. package/lib/components/settings/DangerZoneSection.d.ts.map +1 -0
  166. package/lib/components/settings/DangerZoneSection.jsx +16 -0
  167. package/lib/components/settings/DangerZoneSection.jsx.map +1 -0
  168. package/lib/components/settings/GeneralSection.d.ts +11 -0
  169. package/lib/components/settings/GeneralSection.d.ts.map +1 -0
  170. package/lib/components/settings/GeneralSection.jsx +12 -0
  171. package/lib/components/settings/GeneralSection.jsx.map +1 -0
  172. package/lib/components/settings/SupportSection.d.ts +11 -0
  173. package/lib/components/settings/SupportSection.d.ts.map +1 -0
  174. package/lib/components/settings/SupportSection.jsx +22 -0
  175. package/lib/components/settings/SupportSection.jsx.map +1 -0
  176. package/lib/components/settings/index.d.ts +5 -0
  177. package/lib/components/settings/index.d.ts.map +1 -0
  178. package/lib/components/settings/index.js +5 -0
  179. package/lib/components/settings/index.js.map +1 -0
  180. package/lib/components/settings-row.d.ts +28 -0
  181. package/lib/components/settings-row.d.ts.map +1 -0
  182. package/lib/components/settings-row.jsx +68 -0
  183. package/lib/components/settings-row.jsx.map +1 -0
  184. package/lib/components/skeleton.d.ts +8 -0
  185. package/lib/components/skeleton.d.ts.map +1 -0
  186. package/lib/components/skeleton.jsx +24 -0
  187. package/lib/components/skeleton.jsx.map +1 -0
  188. package/lib/components/social-connections.d.ts +15 -0
  189. package/lib/components/social-connections.d.ts.map +1 -0
  190. package/lib/components/social-connections.jsx +31 -0
  191. package/lib/components/social-connections.jsx.map +1 -0
  192. package/lib/components/stat-card.d.ts +29 -0
  193. package/lib/components/stat-card.d.ts.map +1 -0
  194. package/lib/components/stat-card.jsx +36 -0
  195. package/lib/components/stat-card.jsx.map +1 -0
  196. package/lib/components/tag-chip.d.ts +18 -0
  197. package/lib/components/tag-chip.d.ts.map +1 -0
  198. package/lib/components/tag-chip.jsx +54 -0
  199. package/lib/components/tag-chip.jsx.map +1 -0
  200. package/lib/components/tag-multi-select.d.ts +27 -0
  201. package/lib/components/tag-multi-select.d.ts.map +1 -0
  202. package/lib/components/tag-multi-select.jsx +65 -0
  203. package/lib/components/tag-multi-select.jsx.map +1 -0
  204. package/lib/components/text.d.ts +22 -0
  205. package/lib/components/text.d.ts.map +1 -0
  206. package/lib/components/text.jsx +43 -0
  207. package/lib/components/text.jsx.map +1 -0
  208. package/lib/components/toast/ToastPortal.d.ts +11 -0
  209. package/lib/components/toast/ToastPortal.d.ts.map +1 -0
  210. package/lib/components/toast/ToastPortal.jsx +15 -0
  211. package/lib/components/toast/ToastPortal.jsx.map +1 -0
  212. package/lib/components/toast/ToastPortal.web.d.ts +14 -0
  213. package/lib/components/toast/ToastPortal.web.d.ts.map +1 -0
  214. package/lib/components/toast/ToastPortal.web.jsx +39 -0
  215. package/lib/components/toast/ToastPortal.web.jsx.map +1 -0
  216. package/lib/components/toast/index.d.ts +3 -0
  217. package/lib/components/toast/index.d.ts.map +1 -0
  218. package/lib/components/toast/index.js +3 -0
  219. package/lib/components/toast/index.js.map +1 -0
  220. package/lib/components/toast/toast-config.d.ts +14 -0
  221. package/lib/components/toast/toast-config.d.ts.map +1 -0
  222. package/lib/components/toast/toast-config.jsx +24 -0
  223. package/lib/components/toast/toast-config.jsx.map +1 -0
  224. package/lib/components/tooltip.d.ts +30 -0
  225. package/lib/components/tooltip.d.ts.map +1 -0
  226. package/lib/components/tooltip.jsx +14 -0
  227. package/lib/components/tooltip.jsx.map +1 -0
  228. package/lib/components/totp-display.d.ts +23 -0
  229. package/lib/components/totp-display.d.ts.map +1 -0
  230. package/lib/components/totp-display.jsx +132 -0
  231. package/lib/components/totp-display.jsx.map +1 -0
  232. package/lib/components/user-avatar.d.ts +18 -0
  233. package/lib/components/user-avatar.d.ts.map +1 -0
  234. package/lib/components/user-avatar.jsx +25 -0
  235. package/lib/components/user-avatar.jsx.map +1 -0
  236. package/lib/context/AppConfigContext.d.ts +56 -0
  237. package/lib/context/AppConfigContext.d.ts.map +1 -0
  238. package/lib/context/AppConfigContext.jsx +14 -0
  239. package/lib/context/AppConfigContext.jsx.map +1 -0
  240. package/lib/context/NavigationContext.d.ts +42 -0
  241. package/lib/context/NavigationContext.d.ts.map +1 -0
  242. package/lib/context/NavigationContext.jsx +53 -0
  243. package/lib/context/NavigationContext.jsx.map +1 -0
  244. package/lib/context/NotificationContext.d.ts +32 -0
  245. package/lib/context/NotificationContext.d.ts.map +1 -0
  246. package/lib/context/NotificationContext.jsx +49 -0
  247. package/lib/context/NotificationContext.jsx.map +1 -0
  248. package/lib/context/ThemeContext.d.ts +12 -0
  249. package/lib/context/ThemeContext.d.ts.map +1 -0
  250. package/lib/context/ThemeContext.jsx +66 -0
  251. package/lib/context/ThemeContext.jsx.map +1 -0
  252. package/lib/context/index.d.ts +5 -0
  253. package/lib/context/index.d.ts.map +1 -0
  254. package/lib/context/index.js +5 -0
  255. package/lib/context/index.js.map +1 -0
  256. package/lib/flags.d.ts +9 -0
  257. package/lib/flags.d.ts.map +1 -0
  258. package/lib/flags.js +37 -0
  259. package/lib/flags.js.map +1 -0
  260. package/lib/forms/form-error.d.ts +12 -0
  261. package/lib/forms/form-error.d.ts.map +1 -0
  262. package/lib/forms/form-error.jsx +14 -0
  263. package/lib/forms/form-error.jsx.map +1 -0
  264. package/lib/forms/index.d.ts +3 -0
  265. package/lib/forms/index.d.ts.map +1 -0
  266. package/lib/forms/index.js +3 -0
  267. package/lib/forms/index.js.map +1 -0
  268. package/lib/forms/shake-field.d.ts +18 -0
  269. package/lib/forms/shake-field.d.ts.map +1 -0
  270. package/lib/forms/shake-field.jsx +30 -0
  271. package/lib/forms/shake-field.jsx.map +1 -0
  272. package/lib/hooks/index.d.ts +6 -0
  273. package/lib/hooks/index.d.ts.map +1 -0
  274. package/lib/hooks/index.js +6 -0
  275. package/lib/hooks/index.js.map +1 -0
  276. package/lib/hooks/useAuth.d.ts +109 -0
  277. package/lib/hooks/useAuth.d.ts.map +1 -0
  278. package/lib/hooks/useAuth.jsx +404 -0
  279. package/lib/hooks/useAuth.jsx.map +1 -0
  280. package/lib/hooks/useAutoLock.d.ts +22 -0
  281. package/lib/hooks/useAutoLock.d.ts.map +1 -0
  282. package/lib/hooks/useAutoLock.js +85 -0
  283. package/lib/hooks/useAutoLock.js.map +1 -0
  284. package/lib/hooks/useDebouncedValue.d.ts +19 -0
  285. package/lib/hooks/useDebouncedValue.d.ts.map +1 -0
  286. package/lib/hooks/useDebouncedValue.js +29 -0
  287. package/lib/hooks/useDebouncedValue.js.map +1 -0
  288. package/lib/hooks/useShakeAnimation.d.ts +17 -0
  289. package/lib/hooks/useShakeAnimation.d.ts.map +1 -0
  290. package/lib/hooks/useShakeAnimation.js +22 -0
  291. package/lib/hooks/useShakeAnimation.js.map +1 -0
  292. package/lib/hooks/useUploadBlobUrl.d.ts +13 -0
  293. package/lib/hooks/useUploadBlobUrl.d.ts.map +1 -0
  294. package/lib/hooks/useUploadBlobUrl.js +60 -0
  295. package/lib/hooks/useUploadBlobUrl.js.map +1 -0
  296. package/lib/index.d.ts +10 -0
  297. package/lib/index.d.ts.map +1 -0
  298. package/lib/index.js +47 -0
  299. package/lib/index.js.map +1 -0
  300. package/lib/screens/auth/AccountPickerScreen.d.ts +24 -0
  301. package/lib/screens/auth/AccountPickerScreen.d.ts.map +1 -0
  302. package/lib/screens/auth/AccountPickerScreen.jsx +47 -0
  303. package/lib/screens/auth/AccountPickerScreen.jsx.map +1 -0
  304. package/lib/screens/auth/AuthScreen.d.ts +59 -0
  305. package/lib/screens/auth/AuthScreen.d.ts.map +1 -0
  306. package/lib/screens/auth/AuthScreen.jsx +594 -0
  307. package/lib/screens/auth/AuthScreen.jsx.map +1 -0
  308. package/lib/screens/auth/ConsentScreen.d.ts +27 -0
  309. package/lib/screens/auth/ConsentScreen.d.ts.map +1 -0
  310. package/lib/screens/auth/ConsentScreen.jsx +55 -0
  311. package/lib/screens/auth/ConsentScreen.jsx.map +1 -0
  312. package/lib/screens/auth/ErrorScreen.d.ts +20 -0
  313. package/lib/screens/auth/ErrorScreen.d.ts.map +1 -0
  314. package/lib/screens/auth/ErrorScreen.jsx +43 -0
  315. package/lib/screens/auth/ErrorScreen.jsx.map +1 -0
  316. package/lib/screens/auth/ExpiredLinkScreen.d.ts +19 -0
  317. package/lib/screens/auth/ExpiredLinkScreen.d.ts.map +1 -0
  318. package/lib/screens/auth/ExpiredLinkScreen.jsx +38 -0
  319. package/lib/screens/auth/ExpiredLinkScreen.jsx.map +1 -0
  320. package/lib/screens/auth/ForgotPasswordScreen.d.ts +4 -0
  321. package/lib/screens/auth/ForgotPasswordScreen.d.ts.map +1 -0
  322. package/lib/screens/auth/ForgotPasswordScreen.jsx +123 -0
  323. package/lib/screens/auth/ForgotPasswordScreen.jsx.map +1 -0
  324. package/lib/screens/auth/ImportDataScreen.d.ts +17 -0
  325. package/lib/screens/auth/ImportDataScreen.d.ts.map +1 -0
  326. package/lib/screens/auth/ImportDataScreen.jsx +73 -0
  327. package/lib/screens/auth/ImportDataScreen.jsx.map +1 -0
  328. package/lib/screens/auth/LoginScreen.d.ts +38 -0
  329. package/lib/screens/auth/LoginScreen.d.ts.map +1 -0
  330. package/lib/screens/auth/LoginScreen.jsx +326 -0
  331. package/lib/screens/auth/LoginScreen.jsx.map +1 -0
  332. package/lib/screens/auth/MfaChallengeScreen.d.ts +4 -0
  333. package/lib/screens/auth/MfaChallengeScreen.d.ts.map +1 -0
  334. package/lib/screens/auth/MfaChallengeScreen.jsx +139 -0
  335. package/lib/screens/auth/MfaChallengeScreen.jsx.map +1 -0
  336. package/lib/screens/auth/MfaEnrollScreen.d.ts +12 -0
  337. package/lib/screens/auth/MfaEnrollScreen.d.ts.map +1 -0
  338. package/lib/screens/auth/MfaEnrollScreen.jsx +267 -0
  339. package/lib/screens/auth/MfaEnrollScreen.jsx.map +1 -0
  340. package/lib/screens/auth/PasskeyEnrollScreen.d.ts +18 -0
  341. package/lib/screens/auth/PasskeyEnrollScreen.d.ts.map +1 -0
  342. package/lib/screens/auth/PasskeyEnrollScreen.jsx +51 -0
  343. package/lib/screens/auth/PasskeyEnrollScreen.jsx.map +1 -0
  344. package/lib/screens/auth/PrivacyPolicyScreen.d.ts +19 -0
  345. package/lib/screens/auth/PrivacyPolicyScreen.d.ts.map +1 -0
  346. package/lib/screens/auth/PrivacyPolicyScreen.jsx +143 -0
  347. package/lib/screens/auth/PrivacyPolicyScreen.jsx.map +1 -0
  348. package/lib/screens/auth/RegisterScreen.d.ts +14 -0
  349. package/lib/screens/auth/RegisterScreen.d.ts.map +1 -0
  350. package/lib/screens/auth/RegisterScreen.jsx +296 -0
  351. package/lib/screens/auth/RegisterScreen.jsx.map +1 -0
  352. package/lib/screens/auth/ResetPasswordScreen.d.ts +12 -0
  353. package/lib/screens/auth/ResetPasswordScreen.d.ts.map +1 -0
  354. package/lib/screens/auth/ResetPasswordScreen.jsx +276 -0
  355. package/lib/screens/auth/ResetPasswordScreen.jsx.map +1 -0
  356. package/lib/screens/auth/ServerConfigScreen.d.ts +18 -0
  357. package/lib/screens/auth/ServerConfigScreen.d.ts.map +1 -0
  358. package/lib/screens/auth/ServerConfigScreen.jsx +259 -0
  359. package/lib/screens/auth/ServerConfigScreen.jsx.map +1 -0
  360. package/lib/screens/auth/TermsOfServiceScreen.d.ts +30 -0
  361. package/lib/screens/auth/TermsOfServiceScreen.d.ts.map +1 -0
  362. package/lib/screens/auth/TermsOfServiceScreen.jsx +130 -0
  363. package/lib/screens/auth/TermsOfServiceScreen.jsx.map +1 -0
  364. package/lib/screens/auth/VerifyEmailScreen.d.ts +4 -0
  365. package/lib/screens/auth/VerifyEmailScreen.d.ts.map +1 -0
  366. package/lib/screens/auth/VerifyEmailScreen.jsx +249 -0
  367. package/lib/screens/auth/VerifyEmailScreen.jsx.map +1 -0
  368. package/lib/screens/auth/WelcomeScreen.d.ts +17 -0
  369. package/lib/screens/auth/WelcomeScreen.d.ts.map +1 -0
  370. package/lib/screens/auth/WelcomeScreen.jsx +58 -0
  371. package/lib/screens/auth/WelcomeScreen.jsx.map +1 -0
  372. package/lib/screens/auth/index.d.ts +19 -0
  373. package/lib/screens/auth/index.d.ts.map +1 -0
  374. package/lib/screens/auth/index.js +19 -0
  375. package/lib/screens/auth/index.js.map +1 -0
  376. package/lib/screens/index.d.ts +2 -0
  377. package/lib/screens/index.d.ts.map +1 -0
  378. package/lib/screens/index.js +2 -0
  379. package/lib/screens/index.js.map +1 -0
  380. package/lib/services/api-config.d.ts +87 -0
  381. package/lib/services/api-config.d.ts.map +1 -0
  382. package/lib/services/api-config.js +202 -0
  383. package/lib/services/api-config.js.map +1 -0
  384. package/lib/services/auth.service.d.ts +140 -0
  385. package/lib/services/auth.service.d.ts.map +1 -0
  386. package/lib/services/auth.service.js +376 -0
  387. package/lib/services/auth.service.js.map +1 -0
  388. package/lib/services/favicon.d.ts +46 -0
  389. package/lib/services/favicon.d.ts.map +1 -0
  390. package/lib/services/favicon.js +84 -0
  391. package/lib/services/favicon.js.map +1 -0
  392. package/lib/services/hibp-cache.d.ts +23 -0
  393. package/lib/services/hibp-cache.d.ts.map +1 -0
  394. package/lib/services/hibp-cache.js +56 -0
  395. package/lib/services/hibp-cache.js.map +1 -0
  396. package/lib/services/hibp.d.ts +28 -0
  397. package/lib/services/hibp.d.ts.map +1 -0
  398. package/lib/services/hibp.js +92 -0
  399. package/lib/services/hibp.js.map +1 -0
  400. package/lib/services/index.d.ts +8 -0
  401. package/lib/services/index.d.ts.map +1 -0
  402. package/lib/services/index.js +7 -0
  403. package/lib/services/index.js.map +1 -0
  404. package/lib/services/passkey.d.ts +10 -0
  405. package/lib/services/passkey.d.ts.map +1 -0
  406. package/lib/services/passkey.js +192 -0
  407. package/lib/services/passkey.js.map +1 -0
  408. package/lib/utils/api-fetch.d.ts +11 -0
  409. package/lib/utils/api-fetch.d.ts.map +1 -0
  410. package/lib/utils/api-fetch.js +52 -0
  411. package/lib/utils/api-fetch.js.map +1 -0
  412. package/lib/utils/clipboard.d.ts +31 -0
  413. package/lib/utils/clipboard.d.ts.map +1 -0
  414. package/lib/utils/clipboard.js +66 -0
  415. package/lib/utils/clipboard.js.map +1 -0
  416. package/lib/utils/cn.d.ts +9 -0
  417. package/lib/utils/cn.d.ts.map +1 -0
  418. package/lib/utils/cn.js +12 -0
  419. package/lib/utils/cn.js.map +1 -0
  420. package/lib/utils/debounce.d.ts +13 -0
  421. package/lib/utils/debounce.d.ts.map +1 -0
  422. package/lib/utils/debounce.js +28 -0
  423. package/lib/utils/debounce.js.map +1 -0
  424. package/lib/utils/error.d.ts +9 -0
  425. package/lib/utils/error.d.ts.map +1 -0
  426. package/lib/utils/error.js +11 -0
  427. package/lib/utils/error.js.map +1 -0
  428. package/lib/utils/fetch.d.ts +17 -0
  429. package/lib/utils/fetch.d.ts.map +1 -0
  430. package/lib/utils/fetch.js +29 -0
  431. package/lib/utils/fetch.js.map +1 -0
  432. package/lib/utils/http-error.d.ts +41 -0
  433. package/lib/utils/http-error.d.ts.map +1 -0
  434. package/lib/utils/http-error.js +63 -0
  435. package/lib/utils/http-error.js.map +1 -0
  436. package/lib/utils/index.d.ts +11 -0
  437. package/lib/utils/index.d.ts.map +1 -0
  438. package/lib/utils/index.js +11 -0
  439. package/lib/utils/index.js.map +1 -0
  440. package/lib/utils/palette.d.ts +46 -0
  441. package/lib/utils/palette.d.ts.map +1 -0
  442. package/lib/utils/palette.js +75 -0
  443. package/lib/utils/palette.js.map +1 -0
  444. package/lib/utils/password.d.ts +20 -0
  445. package/lib/utils/password.d.ts.map +1 -0
  446. package/lib/utils/password.js +51 -0
  447. package/lib/utils/password.js.map +1 -0
  448. package/lib/utils/settings-storage.d.ts +3 -0
  449. package/lib/utils/settings-storage.d.ts.map +1 -0
  450. package/lib/utils/settings-storage.js +62 -0
  451. package/lib/utils/settings-storage.js.map +1 -0
  452. package/lib/utils/validation.d.ts +29 -0
  453. package/lib/utils/validation.d.ts.map +1 -0
  454. package/lib/utils/validation.js +58 -0
  455. package/lib/utils/validation.js.map +1 -0
  456. package/package.json +204 -0
  457. package/src/components/__tests__/data-table.test.ts +94 -0
  458. package/src/components/__tests__/pagination.test.ts +73 -0
  459. package/src/components/__tests__/stat-card.test.ts +21 -0
  460. package/src/components/auth/LockOverlay.tsx +122 -0
  461. package/src/components/auth/PasswordStrengthMeter.tsx +96 -0
  462. package/src/components/auth/ProtectedRoute.tsx +91 -0
  463. package/src/components/auth/PwnedPasswordWarning.tsx +54 -0
  464. package/src/components/auth/index.ts +10 -0
  465. package/src/components/bottom-nav.tsx +99 -0
  466. package/src/components/button.tsx +144 -0
  467. package/src/components/card.tsx +82 -0
  468. package/src/components/checkbox.tsx +48 -0
  469. package/src/components/connection-settings.tsx +583 -0
  470. package/src/components/context-menu.tsx +95 -0
  471. package/src/components/data-table.tsx +223 -0
  472. package/src/components/dialog.tsx +376 -0
  473. package/src/components/dropdown-menu.tsx +120 -0
  474. package/src/components/entropy-boot-splash.tsx +114 -0
  475. package/src/components/entropy-mark-animated.tsx +260 -0
  476. package/src/components/entropy-mark-geometry.ts +11 -0
  477. package/src/components/entropy-mark-sequential.tsx +132 -0
  478. package/src/components/entropy-mark.tsx +135 -0
  479. package/src/components/error-boundary.tsx +70 -0
  480. package/src/components/index.ts +156 -0
  481. package/src/components/input.tsx +246 -0
  482. package/src/components/item-icon.tsx +111 -0
  483. package/src/components/label.tsx +25 -0
  484. package/src/components/legal-dialog.tsx +47 -0
  485. package/src/components/license-gate.tsx +28 -0
  486. package/src/components/logo.tsx +34 -0
  487. package/src/components/onboarding-wizard.tsx +353 -0
  488. package/src/components/pagination.tsx +154 -0
  489. package/src/components/password-generator.tsx +393 -0
  490. package/src/components/pin-pad.tsx +156 -0
  491. package/src/components/popover.tsx +38 -0
  492. package/src/components/profile/ProfileDialog.tsx +129 -0
  493. package/src/components/profile/ProfileTab.tsx +151 -0
  494. package/src/components/profile/SecurityTab.tsx +229 -0
  495. package/src/components/profile/index.ts +3 -0
  496. package/src/components/segmented-toggle.tsx +119 -0
  497. package/src/components/separator.tsx +41 -0
  498. package/src/components/server-settings.tsx +442 -0
  499. package/src/components/settings/AccountSection.tsx +76 -0
  500. package/src/components/settings/DangerZoneSection.tsx +37 -0
  501. package/src/components/settings/GeneralSection.tsx +39 -0
  502. package/src/components/settings/SupportSection.tsx +53 -0
  503. package/src/components/settings/index.ts +4 -0
  504. package/src/components/settings-row.tsx +126 -0
  505. package/src/components/skeleton.tsx +48 -0
  506. package/src/components/social-connections.tsx +55 -0
  507. package/src/components/stat-card.tsx +64 -0
  508. package/src/components/tag-chip.tsx +78 -0
  509. package/src/components/tag-multi-select.tsx +136 -0
  510. package/src/components/text.tsx +77 -0
  511. package/src/components/toast/ToastPortal.tsx +16 -0
  512. package/src/components/toast/ToastPortal.web.tsx +47 -0
  513. package/src/components/toast/index.ts +2 -0
  514. package/src/components/toast/toast-config.tsx +31 -0
  515. package/src/components/tooltip.tsx +30 -0
  516. package/src/components/totp-display.tsx +207 -0
  517. package/src/components/user-avatar.tsx +46 -0
  518. package/src/context/AppConfigContext.tsx +76 -0
  519. package/src/context/NavigationContext.tsx +75 -0
  520. package/src/context/NotificationContext.tsx +69 -0
  521. package/src/context/ThemeContext.tsx +83 -0
  522. package/src/context/__tests__/NavigationContext.test.tsx +53 -0
  523. package/src/context/index.ts +24 -0
  524. package/src/flags.ts +44 -0
  525. package/src/forms/form-error.tsx +20 -0
  526. package/src/forms/index.ts +2 -0
  527. package/src/forms/shake-field.tsx +52 -0
  528. package/src/hooks/__tests__/useUploadBlobUrl.test.tsx +77 -0
  529. package/src/hooks/index.ts +18 -0
  530. package/src/hooks/useAuth.tsx +567 -0
  531. package/src/hooks/useAutoLock.ts +110 -0
  532. package/src/hooks/useDebouncedValue.ts +32 -0
  533. package/src/hooks/useShakeAnimation.ts +42 -0
  534. package/src/hooks/useUploadBlobUrl.ts +75 -0
  535. package/src/index.ts +48 -0
  536. package/src/screens/auth/AccountPickerScreen.tsx +103 -0
  537. package/src/screens/auth/AuthScreen.tsx +941 -0
  538. package/src/screens/auth/ConsentScreen.tsx +118 -0
  539. package/src/screens/auth/ErrorScreen.tsx +96 -0
  540. package/src/screens/auth/ExpiredLinkScreen.tsx +87 -0
  541. package/src/screens/auth/ForgotPasswordScreen.tsx +182 -0
  542. package/src/screens/auth/ImportDataScreen.tsx +112 -0
  543. package/src/screens/auth/LoginScreen.tsx +484 -0
  544. package/src/screens/auth/MfaChallengeScreen.tsx +216 -0
  545. package/src/screens/auth/MfaEnrollScreen.tsx +388 -0
  546. package/src/screens/auth/PasskeyEnrollScreen.tsx +96 -0
  547. package/src/screens/auth/PrivacyPolicyScreen.tsx +249 -0
  548. package/src/screens/auth/RegisterScreen.tsx +430 -0
  549. package/src/screens/auth/ResetPasswordScreen.tsx +377 -0
  550. package/src/screens/auth/ServerConfigScreen.tsx +388 -0
  551. package/src/screens/auth/TermsOfServiceScreen.tsx +236 -0
  552. package/src/screens/auth/VerifyEmailScreen.tsx +310 -0
  553. package/src/screens/auth/WelcomeScreen.tsx +78 -0
  554. package/src/screens/auth/index.ts +36 -0
  555. package/src/screens/index.ts +1 -0
  556. package/src/services/__tests__/api-config.test.ts +67 -0
  557. package/src/services/__tests__/favicon.test.ts +88 -0
  558. package/src/services/__tests__/hibp-cache.test.ts +37 -0
  559. package/src/services/__tests__/hibp.test.ts +39 -0
  560. package/src/services/api-config.ts +260 -0
  561. package/src/services/auth.service.ts +498 -0
  562. package/src/services/favicon.ts +102 -0
  563. package/src/services/hibp-cache.ts +71 -0
  564. package/src/services/hibp.ts +120 -0
  565. package/src/services/index.ts +52 -0
  566. package/src/services/passkey.ts +213 -0
  567. package/src/types/external.d.ts +24 -0
  568. package/src/utils/__tests__/clipboard.test.ts +59 -0
  569. package/src/utils/__tests__/cn.test.ts +24 -0
  570. package/src/utils/__tests__/debounce.test.ts +42 -0
  571. package/src/utils/__tests__/error.test.ts +18 -0
  572. package/src/utils/__tests__/http-error.test.ts +33 -0
  573. package/src/utils/__tests__/palette.test.ts +22 -0
  574. package/src/utils/__tests__/password.test.ts +55 -0
  575. package/src/utils/__tests__/settings-storage.test.ts +15 -0
  576. package/src/utils/__tests__/validation.test.ts +52 -0
  577. package/src/utils/api-fetch.ts +61 -0
  578. package/src/utils/clipboard.ts +69 -0
  579. package/src/utils/cn.ts +12 -0
  580. package/src/utils/debounce.ts +33 -0
  581. package/src/utils/error.ts +10 -0
  582. package/src/utils/fetch.ts +33 -0
  583. package/src/utils/http-error.ts +81 -0
  584. package/src/utils/index.ts +23 -0
  585. package/src/utils/palette.ts +105 -0
  586. package/src/utils/password.ts +64 -0
  587. package/src/utils/settings-storage.ts +68 -0
  588. package/src/utils/validation.ts +71 -0
  589. package/styles/globals.css +262 -0
  590. package/tailwind-preset.js +163 -0
@@ -0,0 +1,388 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import {
3
+ ActivityIndicator,
4
+ Alert,
5
+ Pressable,
6
+ ScrollView,
7
+ Text,
8
+ TextInput,
9
+ View,
10
+ } from "react-native";
11
+ import { SafeAreaView } from "react-native-safe-area-context";
12
+ import { useNavigation } from "../../context/NavigationContext";
13
+ import { StatusBar } from "expo-status-bar";
14
+ import { Ionicons } from "@expo/vector-icons";
15
+ import { useColorScheme } from "nativewind";
16
+ import * as Haptics from "expo-haptics";
17
+ import AuthService from "../../services/auth.service";
18
+ import { getDefaultBaseUrl } from "../../services/api-config";
19
+ import { useAppConfig } from "../../context/AppConfigContext";
20
+ import { getErrorMessage } from "../../utils/error";
21
+
22
+ export interface ServerConfigScreenProps {
23
+ /**
24
+ * Path appended to the configured URL when running the connection
25
+ * test. Defaults to `/api/health`. Server is expected to return JSON
26
+ * with `{ status: "healthy", version: "..." }`.
27
+ */
28
+ healthCheckPath?: string;
29
+ /** Optional help bullets rendered at the bottom. */
30
+ helpBullets?: string[];
31
+ /** Default number of retry attempts when testing. Default 3. */
32
+ defaultMaxRetries?: number;
33
+ /** Default request timeout in seconds. Default 30. */
34
+ defaultTimeoutSeconds?: number;
35
+ }
36
+
37
+ export function ServerConfigScreen({
38
+ healthCheckPath = "/api/health",
39
+ helpBullets,
40
+ defaultMaxRetries = 3,
41
+ defaultTimeoutSeconds = 30,
42
+ }: ServerConfigScreenProps = {}) {
43
+ const router = useNavigation();
44
+ const { appName } = useAppConfig();
45
+ const defaultUrl = getDefaultBaseUrl();
46
+
47
+ const [serverUrl, setServerUrl] = useState("");
48
+ const [isTestingConnection, setIsTestingConnection] = useState(false);
49
+ const [connectionStatus, setConnectionStatus] = useState<
50
+ "idle" | "testing" | "success" | "error"
51
+ >("idle");
52
+ const [testAttempt, setTestAttempt] = useState(0);
53
+ const [isLoading, setIsLoading] = useState(true);
54
+
55
+ const { colorScheme } = useColorScheme();
56
+ const isDark = colorScheme === "dark";
57
+
58
+ useEffect(() => {
59
+ try {
60
+ setServerUrl(AuthService.getBaseUrl());
61
+ } catch {
62
+ setServerUrl(defaultUrl);
63
+ } finally {
64
+ setIsLoading(false);
65
+ }
66
+ }, [defaultUrl]);
67
+
68
+ const testConnectionWithRetry = async (
69
+ url: string,
70
+ attemptNumber: number = 1
71
+ ): Promise<boolean> => {
72
+ const timeoutMs = defaultTimeoutSeconds * 1000;
73
+
74
+ try {
75
+ setTestAttempt(attemptNumber);
76
+ const formattedUrl = url.endsWith("/") ? url.slice(0, -1) : url;
77
+ const healthUrl = `${formattedUrl}${healthCheckPath}`;
78
+
79
+ const controller = new AbortController();
80
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
81
+
82
+ const response = await fetch(healthUrl, {
83
+ method: "GET",
84
+ signal: controller.signal,
85
+ headers: { Accept: "application/json" },
86
+ });
87
+
88
+ clearTimeout(timeoutId);
89
+
90
+ if (response.ok) {
91
+ const data = await response.json();
92
+ if (data.status === "healthy" && data.version) {
93
+ return true;
94
+ }
95
+ }
96
+
97
+ if (attemptNumber < defaultMaxRetries) {
98
+ await new Promise((resolve) => setTimeout(resolve, attemptNumber * 1000));
99
+ return await testConnectionWithRetry(url, attemptNumber + 1);
100
+ }
101
+
102
+ return false;
103
+ } catch {
104
+ if (attemptNumber < defaultMaxRetries) {
105
+ await new Promise((resolve) => setTimeout(resolve, attemptNumber * 1000));
106
+ return await testConnectionWithRetry(url, attemptNumber + 1);
107
+ }
108
+
109
+ return false;
110
+ }
111
+ };
112
+
113
+ const testConnection = async () => {
114
+ if (!serverUrl) {
115
+ Alert.alert("Error", "Please enter a server URL");
116
+ return;
117
+ }
118
+
119
+ setIsTestingConnection(true);
120
+ setConnectionStatus("testing");
121
+ setTestAttempt(0);
122
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
123
+
124
+ try {
125
+ const success = await testConnectionWithRetry(serverUrl);
126
+ setIsTestingConnection(false);
127
+
128
+ if (success) {
129
+ setConnectionStatus("success");
130
+ Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
131
+ Alert.alert(
132
+ "Success",
133
+ "Connection successful! Server is reachable and responding correctly.",
134
+ [{ text: "OK" }]
135
+ );
136
+ } else {
137
+ setConnectionStatus("error");
138
+ Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error);
139
+ Alert.alert(
140
+ "Connection Failed",
141
+ `Unable to reach the server after ${defaultMaxRetries} attempts. Please check the URL and try again.`,
142
+ [{ text: "OK" }]
143
+ );
144
+ }
145
+ } catch {
146
+ setIsTestingConnection(false);
147
+ setConnectionStatus("error");
148
+ Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error);
149
+ Alert.alert(
150
+ "Connection Error",
151
+ "An unexpected error occurred while testing the connection.",
152
+ [{ text: "OK" }]
153
+ );
154
+ }
155
+ };
156
+
157
+ const handleSave = async () => {
158
+ if (!serverUrl) {
159
+ Alert.alert("Error", "Please enter a server URL");
160
+ return;
161
+ }
162
+
163
+ const sanitizedUrl = serverUrl.trim();
164
+
165
+ try {
166
+ const url = new URL(sanitizedUrl);
167
+ if (url.protocol === "http:" && !["localhost", "127.0.0.1"].includes(url.hostname)) {
168
+ Alert.alert(
169
+ "HTTPS Required",
170
+ "Non-localhost connections require HTTPS. Please use an https:// URL.",
171
+ [{ text: "OK" }]
172
+ );
173
+ return;
174
+ }
175
+ } catch {
176
+ // setBaseUrl validates and surfaces the error
177
+ }
178
+
179
+ try {
180
+ await AuthService.setBaseUrl(sanitizedUrl);
181
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
182
+ Alert.alert("Configuration Saved", "Server settings have been saved.", [
183
+ { text: "OK", onPress: () => router.back() },
184
+ ]);
185
+ } catch (e) {
186
+ Alert.alert("Save Failed", `Unable to save the configuration: ${getErrorMessage(e)}`, [
187
+ { text: "OK" },
188
+ ]);
189
+ }
190
+ };
191
+
192
+ const handleUseDefault = () => {
193
+ setServerUrl(defaultUrl);
194
+ setConnectionStatus("idle");
195
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
196
+ };
197
+
198
+ const handleClearConfiguration = () => {
199
+ Alert.alert(
200
+ "Clear Configuration",
201
+ "This will reset all server settings to defaults. Are you sure?",
202
+ [
203
+ { text: "Cancel", style: "cancel" },
204
+ {
205
+ text: "Clear",
206
+ style: "destructive",
207
+ onPress: async () => {
208
+ try {
209
+ await AuthService.resetBaseUrl();
210
+ setServerUrl(defaultUrl);
211
+ setConnectionStatus("idle");
212
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
213
+ Alert.alert("Success", "Configuration has been reset to defaults.");
214
+ } catch {
215
+ Alert.alert("Error", "Failed to clear configuration.");
216
+ }
217
+ },
218
+ },
219
+ ]
220
+ );
221
+ };
222
+
223
+ if (isLoading) {
224
+ return (
225
+ <SafeAreaView className="flex-1 bg-background">
226
+ <View className="flex-1 items-center justify-center">
227
+ <ActivityIndicator size="large" color={isDark ? "white" : "black"} />
228
+ </View>
229
+ </SafeAreaView>
230
+ );
231
+ }
232
+
233
+ const bullets = helpBullets ?? [
234
+ `Default server is hosted at ${defaultUrl}`,
235
+ "Ensure your server is running and the /api/health endpoint is accessible",
236
+ "Use HTTPS for secure connections",
237
+ ];
238
+
239
+ return (
240
+ <SafeAreaView className="flex-1 bg-background">
241
+ <StatusBar style="auto" />
242
+ <ScrollView className="flex-1">
243
+ <View className="px-6 py-6">
244
+ <View className="mb-8 flex-row items-center justify-between">
245
+ <Pressable
246
+ onPress={() => router.back()}
247
+ accessibilityRole="button"
248
+ accessibilityLabel="Go back"
249
+ className="active:scale-98 h-10 w-10 items-center justify-center rounded-lg bg-secondary"
250
+ >
251
+ <Ionicons name="close" size={24} color={isDark ? "white" : "black"} />
252
+ </Pressable>
253
+ <Text className="text-lg font-semibold text-foreground">Server Configuration</Text>
254
+ <View className="h-10 w-10" />
255
+ </View>
256
+
257
+ <View className="mb-6 rounded-lg bg-secondary p-4">
258
+ <View className="flex-row items-start">
259
+ <Ionicons
260
+ name="information-circle"
261
+ size={24}
262
+ color={isDark ? "#3b82f6" : "#2563eb"}
263
+ />
264
+ <View className="ml-3 flex-1">
265
+ <Text className="mb-1 text-sm font-semibold text-foreground">
266
+ Self-Hosted Server
267
+ </Text>
268
+ <Text className="text-xs text-muted-foreground">
269
+ Configure your own {appName} server for complete control over your data. Default
270
+ server: {defaultUrl}
271
+ </Text>
272
+ </View>
273
+ </View>
274
+ </View>
275
+
276
+ <View className="mb-6">
277
+ <Text className="mb-2 text-sm font-medium text-foreground">Server URL</Text>
278
+ <View className="flex-row items-center rounded-lg border border-border bg-background px-3 py-3">
279
+ <Ionicons
280
+ name="globe-outline"
281
+ size={20}
282
+ color={isDark ? "rgba(255, 255, 255, 0.5)" : "rgba(0, 0, 0, 0.5)"}
283
+ />
284
+ <TextInput
285
+ value={serverUrl}
286
+ onChangeText={(text) => {
287
+ setServerUrl(text);
288
+ setConnectionStatus("idle");
289
+ }}
290
+ placeholder={defaultUrl}
291
+ placeholderTextColor={isDark ? "rgba(255, 255, 255, 0.5)" : "rgba(0, 0, 0, 0.5)"}
292
+ autoCapitalize="none"
293
+ autoCorrect={false}
294
+ keyboardType="url"
295
+ accessibilityLabel="Server URL"
296
+ className="ml-2 flex-1 text-base text-foreground"
297
+ />
298
+ {connectionStatus === "success" && (
299
+ <Ionicons name="checkmark-circle" size={20} color="#22c55e" />
300
+ )}
301
+ {connectionStatus === "error" && (
302
+ <Ionicons name="close-circle" size={20} color="#ef4444" />
303
+ )}
304
+ </View>
305
+ </View>
306
+
307
+ <Pressable
308
+ onPress={testConnection}
309
+ disabled={isTestingConnection}
310
+ accessibilityRole="button"
311
+ accessibilityLabel="Test connection"
312
+ className="active:scale-98 mb-3 w-full rounded-lg border border-border bg-background px-6 py-4"
313
+ >
314
+ {isTestingConnection ? (
315
+ <View className="flex-row items-center justify-center">
316
+ <ActivityIndicator size="small" color={isDark ? "white" : "black"} />
317
+ <Text className="ml-2 text-base font-semibold text-foreground">
318
+ Testing Connection
319
+ {testAttempt > 0 ? ` (Attempt ${testAttempt}/${defaultMaxRetries})` : "..."}
320
+ </Text>
321
+ </View>
322
+ ) : (
323
+ <View className="flex-row items-center justify-center">
324
+ <Ionicons name="wifi-outline" size={20} color={isDark ? "white" : "black"} />
325
+ <Text className="ml-2 text-base font-semibold text-foreground">
326
+ Test Connection
327
+ </Text>
328
+ </View>
329
+ )}
330
+ </Pressable>
331
+
332
+ <Pressable
333
+ onPress={handleUseDefault}
334
+ accessibilityRole="button"
335
+ accessibilityLabel="Use default server"
336
+ className="active:scale-98 mb-3 w-full rounded-lg border border-border bg-background px-6 py-4"
337
+ >
338
+ <View className="flex-row items-center justify-center">
339
+ <Ionicons name="cloud-outline" size={20} color={isDark ? "white" : "black"} />
340
+ <Text className="ml-2 text-base font-semibold text-foreground">
341
+ Use Default Server
342
+ </Text>
343
+ </View>
344
+ </Pressable>
345
+
346
+ <Pressable
347
+ onPress={handleClearConfiguration}
348
+ accessibilityRole="button"
349
+ accessibilityLabel="Clear all settings"
350
+ className="active:scale-98 mb-3 w-full rounded-lg border border-destructive bg-background px-6 py-3"
351
+ >
352
+ <View className="flex-row items-center justify-center">
353
+ <Ionicons name="trash-outline" size={20} color="#ef4444" />
354
+ <Text className="ml-2 text-base font-medium text-destructive">
355
+ Clear All Settings
356
+ </Text>
357
+ </View>
358
+ </Pressable>
359
+
360
+ <Pressable
361
+ onPress={handleSave}
362
+ accessibilityRole="button"
363
+ accessibilityLabel="Save configuration"
364
+ className="active:scale-98 mb-6 w-full rounded-lg bg-primary px-6 py-4"
365
+ >
366
+ <Text className="text-center text-base font-semibold text-primary-foreground">
367
+ Save Configuration
368
+ </Text>
369
+ </Pressable>
370
+
371
+ <View className="rounded-lg bg-card p-4">
372
+ <Text className="mb-3 text-sm font-semibold text-foreground">Need Help?</Text>
373
+ <View className="space-y-2">
374
+ {bullets.map((bullet, idx) => (
375
+ <View key={idx} className="flex-row items-start">
376
+ <Text className="mr-2 text-sm text-muted-foreground">•</Text>
377
+ <Text className="flex-1 text-sm text-muted-foreground">{bullet}</Text>
378
+ </View>
379
+ ))}
380
+ </View>
381
+ </View>
382
+ </View>
383
+ </ScrollView>
384
+ </SafeAreaView>
385
+ );
386
+ }
387
+
388
+ export default ServerConfigScreen;
@@ -0,0 +1,236 @@
1
+ import React from "react";
2
+ import { Linking, ScrollView, Text, View } from "react-native";
3
+ import { SafeAreaView } from "react-native-safe-area-context";
4
+ import { useNavigation } from "../../context/NavigationContext";
5
+ import { StatusBar } from "expo-status-bar";
6
+ import { Ionicons } from "@expo/vector-icons";
7
+ import { useColorScheme } from "nativewind";
8
+ import { IconButton } from "../../components/button";
9
+ import { EntropyByline } from "../../components/entropy-mark";
10
+ import { useAppConfig } from "../../context/AppConfigContext";
11
+
12
+ export interface LegalSection {
13
+ title: string;
14
+ content: string;
15
+ }
16
+
17
+ export interface TermsOfServiceScreenProps {
18
+ /**
19
+ * Per-app section list. When omitted, the screen falls back to
20
+ * `AppConfig.termsText` (rendered as a single section) or a generic
21
+ * placeholder.
22
+ */
23
+ sections?: LegalSection[];
24
+ /**
25
+ * Optional version/build label rendered in the header (vault uses
26
+ * `v1.2.3 (4567)` here). Apps that don't ship build metadata can
27
+ * omit this.
28
+ */
29
+ buildLabel?: string;
30
+ /** Effective-date label override. Defaults to today's date. */
31
+ effectiveDate?: string;
32
+ /** Support email surfaced in the contact section. */
33
+ supportEmail?: string;
34
+ /** Footer organisation name. Defaults to `appName`. */
35
+ organisationName?: string;
36
+ /** Footer license blurb. Defaults to "Open Source • MIT License". */
37
+ licenseLabel?: string;
38
+ }
39
+
40
+ export function TermsOfServiceScreen({
41
+ sections,
42
+ buildLabel,
43
+ effectiveDate,
44
+ supportEmail = "support@entropysoftworks.com",
45
+ organisationName,
46
+ licenseLabel = "Open Source • MIT License",
47
+ }: TermsOfServiceScreenProps) {
48
+ const { colorScheme } = useColorScheme();
49
+ const isDark = colorScheme === "dark";
50
+ const router = useNavigation();
51
+ const { appName, termsText } = useAppConfig();
52
+
53
+ const resolvedSections: LegalSection[] =
54
+ sections ??
55
+ (termsText
56
+ ? [{ title: "Terms", content: termsText }]
57
+ : [{ title: "Terms of Service", content: `Terms of service for ${appName}.` }]);
58
+
59
+ const today =
60
+ effectiveDate ??
61
+ new Date().toLocaleDateString("en-US", {
62
+ year: "numeric",
63
+ month: "long",
64
+ day: "numeric",
65
+ });
66
+
67
+ const org = organisationName ?? appName;
68
+
69
+ return (
70
+ <SafeAreaView className="flex-1" style={{ backgroundColor: isDark ? "#000000" : "#FFFFFF" }}>
71
+ <StatusBar style={isDark ? "light" : "dark"} />
72
+
73
+ <View className="flex-1" style={{ backgroundColor: isDark ? "#000000" : "#FFFFFF" }}>
74
+ <View className="px-6 pt-4 pb-6">
75
+ <View className="flex-row items-center justify-between mb-6">
76
+ <IconButton variant="ghost" size="sm" onPress={() => router.back()}>
77
+ <Ionicons name="arrow-back" size={20} color={isDark ? "#FFFFFF" : "#000000"} />
78
+ </IconButton>
79
+
80
+ {buildLabel ? (
81
+ <Text className="text-xs" style={{ color: isDark ? "#999999" : "#666666" }}>
82
+ {buildLabel}
83
+ </Text>
84
+ ) : null}
85
+ </View>
86
+
87
+ <Text
88
+ className="font-sans-bold mb-3"
89
+ style={{ fontSize: 36, color: isDark ? "#FFFFFF" : "#000000" }}
90
+ >
91
+ Terms of Service
92
+ </Text>
93
+
94
+ <Text className="font-mono text-sm" style={{ color: isDark ? "#999999" : "#666666" }}>
95
+ Effective Date: {today}
96
+ </Text>
97
+ </View>
98
+
99
+ <ScrollView
100
+ className="flex-1 px-6"
101
+ showsVerticalScrollIndicator={false}
102
+ contentContainerStyle={{ paddingBottom: 40 }}
103
+ >
104
+ <View
105
+ className="rounded-lg mb-4 p-4"
106
+ style={{
107
+ backgroundColor: isDark ? "#1A1A1A" : "#F9F9F9",
108
+ borderWidth: 1,
109
+ borderColor: isDark ? "#333333" : "#E5E5E5",
110
+ }}
111
+ >
112
+ <Text
113
+ className="font-mono text-base"
114
+ style={{ color: isDark ? "#E5E5E5" : "#333333", lineHeight: 24 }}
115
+ >
116
+ These Terms of Service (&quot;Terms&quot;) govern your use of {appName} and related
117
+ services. By using {appName}, you agree to be bound by these Terms.
118
+ </Text>
119
+ </View>
120
+
121
+ <View className="gap-4">
122
+ {resolvedSections.map((section, index) => (
123
+ <View
124
+ key={index}
125
+ className="rounded-lg p-4"
126
+ style={{
127
+ backgroundColor: isDark ? "#0A0A0A" : "#FFFFFF",
128
+ borderWidth: 1,
129
+ borderColor: isDark ? "#333333" : "#E5E5E5",
130
+ }}
131
+ >
132
+ <Text
133
+ className="font-sans-medium text-lg mb-2"
134
+ style={{ color: isDark ? "#FFFFFF" : "#000000" }}
135
+ >
136
+ {section.title}
137
+ </Text>
138
+ <Text
139
+ className="font-mono text-sm"
140
+ style={{ color: isDark ? "#999999" : "#666666", lineHeight: 22 }}
141
+ >
142
+ {section.content}
143
+ </Text>
144
+ </View>
145
+ ))}
146
+
147
+ <View
148
+ className="rounded-lg p-4"
149
+ style={{
150
+ backgroundColor: isDark ? "#0A0A0A" : "#FFFFFF",
151
+ borderWidth: 1,
152
+ borderColor: isDark ? "#333333" : "#E5E5E5",
153
+ }}
154
+ >
155
+ <Text
156
+ className="font-sans-medium text-lg mb-2"
157
+ style={{ color: isDark ? "#FFFFFF" : "#000000" }}
158
+ >
159
+ Contact
160
+ </Text>
161
+ <Text
162
+ className="font-mono text-sm"
163
+ style={{ color: isDark ? "#999999" : "#666666", lineHeight: 22 }}
164
+ >
165
+ For questions about these Terms of Service, please contact us by email at{" "}
166
+ <Text
167
+ className="font-mono text-sm underline"
168
+ style={{ color: isDark ? "#6BA3E5" : "#4A90E2" }}
169
+ onPress={() => Linking.openURL(`mailto:${supportEmail}`)}
170
+ >
171
+ {supportEmail}
172
+ </Text>
173
+ </Text>
174
+ </View>
175
+ </View>
176
+
177
+ <View
178
+ className="rounded-lg mt-6 p-4"
179
+ style={{
180
+ backgroundColor: isDark ? "#1A2332" : "#F0F8FF",
181
+ borderWidth: 1,
182
+ borderColor: isDark ? "#2A3F5F" : "#D0E0FF",
183
+ }}
184
+ >
185
+ <View className="flex-row items-start">
186
+ <Ionicons
187
+ name="information-circle"
188
+ size={20}
189
+ color="#4A90E2"
190
+ style={{ marginTop: 2, marginRight: 8 }}
191
+ />
192
+ <View className="flex-1">
193
+ <Text
194
+ className="font-sans-medium text-sm mb-2"
195
+ style={{ color: isDark ? "#FFFFFF" : "#000000" }}
196
+ >
197
+ Important Notice
198
+ </Text>
199
+ <Text
200
+ className="font-mono text-xs"
201
+ style={{ color: isDark ? "#999999" : "#666666", lineHeight: 20 }}
202
+ >
203
+ By creating an account or using {appName}, you acknowledge that you have read,
204
+ understood, and agree to be bound by these Terms of Service. If you do not agree,
205
+ please discontinue use of the application.
206
+ </Text>
207
+ </View>
208
+ </View>
209
+ </View>
210
+
211
+ <View className="mt-8 items-center">
212
+ <Text
213
+ className="font-mono text-xs text-center"
214
+ style={{ color: isDark ? "#666666" : "#999999" }}
215
+ >
216
+ © {new Date().getFullYear()} {org}. All rights reserved.
217
+ </Text>
218
+ {licenseLabel ? (
219
+ <Text
220
+ className="font-mono text-xs text-center mt-2"
221
+ style={{ color: isDark ? "#666666" : "#999999" }}
222
+ >
223
+ {licenseLabel}
224
+ </Text>
225
+ ) : null}
226
+ <View style={{ marginTop: 20 }}>
227
+ <EntropyByline size={16} />
228
+ </View>
229
+ </View>
230
+ </ScrollView>
231
+ </View>
232
+ </SafeAreaView>
233
+ );
234
+ }
235
+
236
+ export default TermsOfServiceScreen;