@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,120 @@
1
+ import * as DropdownMenuPrimitive from "@rn-primitives/dropdown-menu";
2
+ import { cn } from "../utils/cn";
3
+ import React from "react";
4
+ import { Platform, View, type ViewStyle } from "react-native";
5
+
6
+ const DropdownMenu = DropdownMenuPrimitive.Root;
7
+ const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
8
+
9
+ const DropdownMenuContent = React.forwardRef<
10
+ React.ElementRef<typeof DropdownMenuPrimitive.Content>,
11
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
12
+ >(({ className, sideOffset = 4, ...props }, ref) => {
13
+ const content = (
14
+ <DropdownMenuPrimitive.Content
15
+ ref={ref}
16
+ sideOffset={sideOffset}
17
+ className={cn(
18
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border border-border bg-popover p-1",
19
+ className
20
+ )}
21
+ style={
22
+ Platform.OS === "web"
23
+ ? ({ boxShadow: "0px 4px 12px rgba(0, 0, 0, 0.15)" } as ViewStyle &
24
+ Record<string, unknown>)
25
+ : undefined
26
+ }
27
+ {...props}
28
+ />
29
+ );
30
+
31
+ if (Platform.OS === "web") {
32
+ // On web, Portal expects exactly one child — skip the Overlay (Radix
33
+ // handles dismiss-on-click-outside internally).
34
+ return <DropdownMenuPrimitive.Portal>{content}</DropdownMenuPrimitive.Portal>;
35
+ }
36
+
37
+ return (
38
+ <DropdownMenuPrimitive.Portal>
39
+ <DropdownMenuPrimitive.Overlay className="animate-in fade-in-0" />
40
+ {content}
41
+ </DropdownMenuPrimitive.Portal>
42
+ );
43
+ });
44
+ DropdownMenuContent.displayName = "DropdownMenuContent";
45
+
46
+ const DropdownMenuItem = React.forwardRef<
47
+ React.ElementRef<typeof DropdownMenuPrimitive.Item>,
48
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item>
49
+ >(({ className, ...props }, ref) => (
50
+ <DropdownMenuPrimitive.Item
51
+ ref={ref}
52
+ className={cn(
53
+ "relative flex flex-row items-center rounded-sm px-2 py-1.5 web:cursor-pointer web:outline-none active:bg-accent",
54
+ "web:hover:bg-accent web:focus:bg-accent",
55
+ props.disabled && "opacity-50 web:pointer-events-none",
56
+ className
57
+ )}
58
+ {...props}
59
+ />
60
+ ));
61
+ DropdownMenuItem.displayName = "DropdownMenuItem";
62
+
63
+ const DropdownMenuCheckboxItem = React.forwardRef<
64
+ React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
65
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
66
+ >(({ className, children, checked, ...props }, ref) => (
67
+ <DropdownMenuPrimitive.CheckboxItem
68
+ ref={ref}
69
+ className={cn(
70
+ "relative flex flex-row items-center rounded-sm py-1.5 pl-8 pr-2 web:cursor-pointer web:outline-none active:bg-accent",
71
+ "web:hover:bg-accent web:focus:bg-accent",
72
+ props.disabled && "opacity-50 web:pointer-events-none",
73
+ className
74
+ )}
75
+ checked={checked}
76
+ {...props}
77
+ >
78
+ <View className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
79
+ <DropdownMenuPrimitive.ItemIndicator>
80
+ {/* Checkmark indicator */}
81
+ </DropdownMenuPrimitive.ItemIndicator>
82
+ </View>
83
+ {children as React.ReactNode}
84
+ </DropdownMenuPrimitive.CheckboxItem>
85
+ ));
86
+ DropdownMenuCheckboxItem.displayName = "DropdownMenuCheckboxItem";
87
+
88
+ const DropdownMenuLabel = React.forwardRef<
89
+ React.ElementRef<typeof DropdownMenuPrimitive.Label>,
90
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label>
91
+ >(({ className, ...props }, ref) => (
92
+ <DropdownMenuPrimitive.Label
93
+ ref={ref}
94
+ className={cn("px-2 py-1.5 text-sm font-semibold text-foreground", className)}
95
+ {...props}
96
+ />
97
+ ));
98
+ DropdownMenuLabel.displayName = "DropdownMenuLabel";
99
+
100
+ const DropdownMenuSeparator = React.forwardRef<
101
+ React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
102
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
103
+ >(({ className, ...props }, ref) => (
104
+ <DropdownMenuPrimitive.Separator
105
+ ref={ref}
106
+ className={cn("-mx-1 my-1 h-px bg-border", className)}
107
+ {...props}
108
+ />
109
+ ));
110
+ DropdownMenuSeparator.displayName = "DropdownMenuSeparator";
111
+
112
+ export {
113
+ DropdownMenu,
114
+ DropdownMenuTrigger,
115
+ DropdownMenuContent,
116
+ DropdownMenuItem,
117
+ DropdownMenuCheckboxItem,
118
+ DropdownMenuLabel,
119
+ DropdownMenuSeparator,
120
+ };
@@ -0,0 +1,114 @@
1
+ import React, { useEffect, useRef } from "react";
2
+ import { Animated, Easing, Platform, StyleSheet, View } from "react-native";
3
+ import { useColorScheme } from "nativewind";
4
+ import Svg, { Path } from "react-native-svg";
5
+ import { ENTROPY_MARK_ASPECT, ENTROPY_MARK_PATH, ENTROPY_MARK_VIEWBOX } from "./entropy-mark";
6
+ import { usePalette } from "../utils/palette";
7
+ import { DISABLE_BRANDING } from "../flags";
8
+
9
+ // Web has no native animated module; requesting the native driver there just
10
+ // warns and falls back to JS. Gate it so the console stays clean.
11
+ const USE_NATIVE_DRIVER = Platform.OS !== "web";
12
+
13
+ export interface EntropyBootSplashProps {
14
+ /** Called once the intro + hold + fade-out finishes. */
15
+ onFinish?: () => void;
16
+ /** Mark height in px. */
17
+ size?: number;
18
+ /** "chroma" (default) shows the faint cyan/red fringe; "mono" is plain. */
19
+ variant?: "mono" | "chroma";
20
+ /** Override background; defaults to themed near-black / white. */
21
+ background?: string;
22
+ /** ms to hold fully-drifted before fading out. Default 550. */
23
+ holdMs?: number;
24
+ }
25
+
26
+ /**
27
+ * Company boot splash — the website's logo motion as a launch animation: the
28
+ * mark fades in flat, the three echoes drift apart + breathe (driven by
29
+ * EntropyMarkAnimated's `active` state — the same motion source as the
30
+ * website hover), hold, then the whole thing fades out and calls `onFinish`.
31
+ * Subtle corporate recognition at launch; each product keeps its own
32
+ * icon/splash for the OS-level launch screen — this is an in-app overlay.
33
+ */
34
+ export function EntropyBootSplash({
35
+ onFinish,
36
+ size = 96,
37
+ // `variant` is retained on the props interface for API compatibility but the
38
+ // current flat-mark splash renders the same regardless, so it isn't read.
39
+ background,
40
+ holdMs = 550,
41
+ }: EntropyBootSplashProps) {
42
+ const { colorScheme } = useColorScheme();
43
+ const isDark = colorScheme === "dark";
44
+ const { palette } = usePalette();
45
+ // Match the app's themed background exactly (bg-background) so there's no
46
+ // color seam when the splash dismisses into the screen behind it.
47
+ const bg = background ?? palette.background;
48
+
49
+ const fade = useRef(new Animated.Value(0)).current;
50
+
51
+ useEffect(() => {
52
+ // Self-host branding opt-out: skip the splash entirely, let the app proceed.
53
+ if (DISABLE_BRANDING) {
54
+ onFinish?.();
55
+ return;
56
+ }
57
+ const anim = Animated.sequence([
58
+ Animated.timing(fade, {
59
+ toValue: 1,
60
+ duration: 320,
61
+ easing: Easing.out(Easing.quad),
62
+ useNativeDriver: USE_NATIVE_DRIVER,
63
+ }),
64
+ // mark's own open-ease (~450ms) + breathing run during the hold
65
+ Animated.delay(900 + holdMs),
66
+ Animated.timing(fade, {
67
+ toValue: 0,
68
+ duration: 420,
69
+ easing: Easing.in(Easing.quad),
70
+ useNativeDriver: USE_NATIVE_DRIVER,
71
+ }),
72
+ ]);
73
+ anim.start(({ finished }) => {
74
+ if (finished) {
75
+ onFinish?.();
76
+ }
77
+ });
78
+ return () => anim.stop();
79
+ // run once on mount
80
+ // eslint-disable-next-line react-hooks/exhaustive-deps
81
+ }, []);
82
+
83
+ if (DISABLE_BRANDING) {
84
+ return null;
85
+ }
86
+
87
+ return (
88
+ <View
89
+ style={[
90
+ StyleSheet.absoluteFill,
91
+ {
92
+ backgroundColor: bg,
93
+ alignItems: "center",
94
+ justifyContent: "center",
95
+ pointerEvents: "none",
96
+ },
97
+ ]}
98
+ >
99
+ {/* Static flat source mark — the topmost layer only, monochromatic to the
100
+ theme (black in light, white in dark). No echoes, no motion. */}
101
+ <Animated.View style={{ opacity: fade }}>
102
+ <Svg
103
+ width={Math.round(size * ENTROPY_MARK_ASPECT)}
104
+ height={size}
105
+ viewBox={ENTROPY_MARK_VIEWBOX}
106
+ >
107
+ <Path d={ENTROPY_MARK_PATH} fillRule="evenodd" fill={isDark ? "#ffffff" : "#000000"} />
108
+ </Svg>
109
+ </Animated.View>
110
+ </View>
111
+ );
112
+ }
113
+
114
+ export default EntropyBootSplash;
@@ -0,0 +1,260 @@
1
+ import React, { useEffect } from "react";
2
+ import { View, type GestureResponderEvent } from "react-native";
3
+ import Svg, { Path } from "react-native-svg";
4
+ import Animated, {
5
+ Easing,
6
+ ReduceMotion,
7
+ useAnimatedStyle,
8
+ useSharedValue,
9
+ withDelay,
10
+ withRepeat,
11
+ withSequence,
12
+ withTiming,
13
+ type SharedValue,
14
+ } from "react-native-reanimated";
15
+ import { useColorScheme } from "nativewind";
16
+ import {
17
+ ENTROPY_MARK_ASPECT,
18
+ ENTROPY_MARK_PATH,
19
+ ENTROPY_MARK_STEP,
20
+ ENTROPY_MARK_VIEWBOX,
21
+ } from "./entropy-mark-geometry";
22
+
23
+ // React Native port of the website's animated company mark
24
+ // (website/src/components/logo.tsx). Same motion model, hover → touch:
25
+ //
26
+ // • At rest the mark is FLAT — sharp source `>_` only, echoes collapsed
27
+ // underneath it (invisible).
28
+ // • While pressed, `open` eases 0→1: the three grey time-echoes fade in and
29
+ // drift apart, each breathing on its own period/phase so they never move
30
+ // in lockstep (the endless, unevenly-spaced cascade).
31
+ // • Parallax: while pressed, the echoes lean toward the finger (deeper
32
+ // echoes shift more = depth), gated by `open` so it fades with collapse.
33
+ // • On release, `open` eases 1→0 and the echoes resolve cleanly back into
34
+ // the source — no snap.
35
+ // • The sharp source NEVER moves (anchored), and each echo lives on its own
36
+ // Animated.View layer so the source is never re-rasterized mid-animation
37
+ // (the compositor lesson from the web version).
38
+ //
39
+ // Honors the system reduce-motion setting via ReduceMotion.System.
40
+
41
+ // echo keyed by depth (3 = furthest/dimmest .. 1 = nearest the source)
42
+ const PALETTE = {
43
+ light: {
44
+ src: "#000000",
45
+ echo: { 3: "#f5f5f5", 2: "#e2e2e2", 1: "#cbcbcb" },
46
+ cyan: "#0096aa",
47
+ red: "#c82837",
48
+ },
49
+ dark: {
50
+ src: "#ffffff",
51
+ echo: { 3: "#373737", 2: "#5f5f5f", 1: "#8c8c8c" },
52
+ cyan: "#268ca0",
53
+ red: "#a53440",
54
+ },
55
+ } as const;
56
+
57
+ // Matches the web component: breathing reach per echo depth, parallax px per
58
+ // depth-step, breathing period 2.6+i*0.7s with staggered phase.
59
+ const AMP: Record<1 | 2 | 3, number> = { 3: 1.55, 2: 1.4, 1: 1.6 };
60
+ const PX = 9;
61
+ const PY = 7;
62
+
63
+ export interface EntropyMarkAnimatedProps {
64
+ /** Rendered height in px. Width follows the ~1.63:1 aspect. */
65
+ size?: number;
66
+ /** "mono" = grey echoes only; "chroma" = adds the faint cyan/red fringe. */
67
+ variant?: "mono" | "chroma";
68
+ /** Override the theme; defaults to the active color scheme. */
69
+ scheme?: "light" | "dark";
70
+ /** Force the drifted-apart state (e.g. boot splash drives this). */
71
+ active?: boolean;
72
+ /** Drift apart while touched (default true). */
73
+ animateOnPress?: boolean;
74
+ }
75
+
76
+ function Echo({
77
+ depth,
78
+ fill,
79
+ open,
80
+ px,
81
+ py,
82
+ width,
83
+ height,
84
+ }: {
85
+ depth: 1 | 2 | 3;
86
+ fill: string;
87
+ open: SharedValue<number>;
88
+ px: SharedValue<number>;
89
+ py: SharedValue<number>;
90
+ width: number;
91
+ height: number;
92
+ }) {
93
+ // Breathing oscillator 0..1, own period + phase per depth → desynced.
94
+ const breath = useSharedValue(0);
95
+ useEffect(() => {
96
+ const half = ((2.6 + depth * 0.7) * 1000) / 2;
97
+ const ease = Easing.inOut(Easing.sin);
98
+ breath.value = withDelay(
99
+ depth * 400,
100
+ withRepeat(
101
+ withSequence(
102
+ withTiming(1, { duration: half, easing: ease, reduceMotion: ReduceMotion.System }),
103
+ withTiming(0, { duration: half, easing: ease, reduceMotion: ReduceMotion.System })
104
+ ),
105
+ -1,
106
+ false,
107
+ undefined,
108
+ ReduceMotion.System
109
+ )
110
+ );
111
+ // eslint-disable-next-line react-hooks/exhaustive-deps
112
+ }, [depth]);
113
+
114
+ const style = useAnimatedStyle(() => {
115
+ // Offset = base drift * breathing multiplier (1..AMP) + parallax lean,
116
+ // all scaled by `open` so rest = exactly collapsed under the source.
117
+ const m = 1 + (AMP[depth] - 1) * breath.value;
118
+ const tx = depth * ENTROPY_MARK_STEP.x * open.value * m + depth * PX * px.value * open.value;
119
+ const ty = depth * ENTROPY_MARK_STEP.y * open.value * m + depth * PY * py.value * open.value;
120
+ return {
121
+ opacity: open.value,
122
+ transform: [{ translateX: tx }, { translateY: ty }],
123
+ };
124
+ });
125
+
126
+ return (
127
+ <Animated.View style={[{ position: "absolute", width, height, pointerEvents: "none" }, style]}>
128
+ <Svg width={width} height={height} viewBox={ENTROPY_MARK_VIEWBOX}>
129
+ <Path d={ENTROPY_MARK_PATH} fillRule="evenodd" fill={fill} />
130
+ </Svg>
131
+ </Animated.View>
132
+ );
133
+ }
134
+
135
+ /**
136
+ * Touch-interactive company `>_` mark — flat at rest, echo-cascade + parallax
137
+ * while pressed, clean collapse on release. The RN twin of the website logo.
138
+ */
139
+ export function EntropyMarkAnimated({
140
+ size = 28,
141
+ variant = "mono",
142
+ scheme,
143
+ active = false,
144
+ animateOnPress = true,
145
+ }: EntropyMarkAnimatedProps) {
146
+ const { colorScheme } = useColorScheme();
147
+ const p = PALETTE[scheme ?? (colorScheme === "dark" ? "dark" : "light")];
148
+ const width = Math.round(size * ENTROPY_MARK_ASPECT);
149
+
150
+ const open = useSharedValue(active ? 1 : 0);
151
+ const px = useSharedValue(0);
152
+ const py = useSharedValue(0);
153
+
154
+ useEffect(() => {
155
+ open.value = withTiming(active ? 1 : 0, {
156
+ duration: 450,
157
+ easing: Easing.out(Easing.cubic),
158
+ reduceMotion: ReduceMotion.System,
159
+ });
160
+ // eslint-disable-next-line react-hooks/exhaustive-deps
161
+ }, [active]);
162
+
163
+ const track = (e: GestureResponderEvent) => {
164
+ // Normalize finger position over the mark to -1..1 (parallax input).
165
+ const nx = Math.max(-1, Math.min(1, (e.nativeEvent.locationX / width - 0.5) * 2));
166
+ const ny = Math.max(-1, Math.min(1, (e.nativeEvent.locationY / size - 0.5) * 2));
167
+ px.value = withTiming(nx, { duration: 80, reduceMotion: ReduceMotion.System });
168
+ py.value = withTiming(ny, { duration: 80, reduceMotion: ReduceMotion.System });
169
+ };
170
+
171
+ const press = (down: boolean) => (e: GestureResponderEvent) => {
172
+ if (!animateOnPress) {
173
+ return;
174
+ }
175
+ if (down) {
176
+ track(e);
177
+ open.value = withTiming(1, {
178
+ duration: 450,
179
+ easing: Easing.out(Easing.cubic),
180
+ reduceMotion: ReduceMotion.System,
181
+ });
182
+ } else {
183
+ // Release: echoes resolve back into the source, parallax recenters.
184
+ open.value = withTiming(active ? 1 : 0, {
185
+ duration: 500,
186
+ easing: Easing.inOut(Easing.cubic),
187
+ reduceMotion: ReduceMotion.System,
188
+ });
189
+ px.value = withTiming(0, { duration: 500, reduceMotion: ReduceMotion.System });
190
+ py.value = withTiming(0, { duration: 500, reduceMotion: ReduceMotion.System });
191
+ }
192
+ };
193
+
194
+ const chromaStyle = useAnimatedStyle(() => ({ opacity: open.value }));
195
+
196
+ return (
197
+ <View
198
+ style={{ width, height: size }}
199
+ onStartShouldSetResponder={() => animateOnPress}
200
+ onResponderGrant={press(true)}
201
+ onResponderMove={track}
202
+ onResponderRelease={press(false)}
203
+ onResponderTerminate={press(false)}
204
+ >
205
+ {/* echoes: far (dim) → near, each on its own compositor layer */}
206
+ {([3, 2, 1] as const).map((i) => (
207
+ <Echo
208
+ key={i}
209
+ depth={i}
210
+ fill={p.echo[i]}
211
+ open={open}
212
+ px={px}
213
+ py={py}
214
+ width={width}
215
+ height={size}
216
+ />
217
+ ))}
218
+
219
+ {/* chroma fringe — rides `open` (sharp offset; RN SVG has no cheap blur) */}
220
+ {variant === "chroma" ? (
221
+ <Animated.View
222
+ style={[
223
+ { position: "absolute", width, height: size, pointerEvents: "none" },
224
+ chromaStyle,
225
+ ]}
226
+ >
227
+ <Svg width={width} height={size} viewBox={ENTROPY_MARK_VIEWBOX}>
228
+ <Path
229
+ d={ENTROPY_MARK_PATH}
230
+ fillRule="evenodd"
231
+ fill={p.cyan}
232
+ opacity={0.5}
233
+ transform="translate(10 8)"
234
+ />
235
+ <Path
236
+ d={ENTROPY_MARK_PATH}
237
+ fillRule="evenodd"
238
+ fill={p.red}
239
+ opacity={0.45}
240
+ transform="translate(-10 -8)"
241
+ />
242
+ </Svg>
243
+ </Animated.View>
244
+ ) : null}
245
+
246
+ {/* sharp source — always visible, never moves (anchored). Absolutely
247
+ positioned + last in the tree so it paints ON TOP of the absolutely-
248
+ positioned echo/chroma layers on web too: CSS paints positioned
249
+ siblings above static ones regardless of DOM order, so a static
250
+ source would otherwise be buried under the echoes on web. */}
251
+ <View style={{ position: "absolute", width, height: size, pointerEvents: "none" }}>
252
+ <Svg width={width} height={size} viewBox={ENTROPY_MARK_VIEWBOX}>
253
+ <Path d={ENTROPY_MARK_PATH} fillRule="evenodd" fill={p.src} />
254
+ </Svg>
255
+ </View>
256
+ </View>
257
+ );
258
+ }
259
+
260
+ export default EntropyMarkAnimated;
@@ -0,0 +1,11 @@
1
+ // Geometry of the Entropy Softworks company mark (`>_`), shared by the static
2
+ // `EntropyMark` and the animated `EntropyMarkAnimated`. Lives in its own module
3
+ // so both can import it without the two components importing each other (which
4
+ // formed a require cycle). Kept in sync with the website
5
+ // (website/src/components/logo.tsx).
6
+
7
+ export const ENTROPY_MARK_VIEWBOX = "300 562 1311 805";
8
+ export const ENTROPY_MARK_ASPECT = 1311 / 805;
9
+ export const ENTROPY_MARK_PATH =
10
+ "M 869,1057.5 L 672,1057.5 L 673,1055.5 L 752.5,1015 L 606.5,941 L 632.5,894 L 633.5,892 L 632,890.5 L 449.5,798 L 449.5,648 L 703,776.5 L 704.5,779 L 679.5,822 L 678,827.5 L 867,923.5 L 869.5,926 L 869,1057.5 Z M 804,1201.5 L 524,1201.5 L 523.5,1194 L 743,1081.5 L 989.5,1082 L 989.5,1106 L 988,1107.5 L 804,1201.5 Z M 1597,1331.5 L 1524,1331.5 L 1354.5,1162 L 1597,1161.5 L 1597,1331.5 Z M 1479,1353.5 L 1011,1353.5 L 1009.5,1352 L 1009.5,1184 L 1310,1183.5 L 1479,1353.5 Z M 404,1344.5 L 404,1225.5 L 635.5,1226 L 404,1344.5 Z";
11
+ export const ENTROPY_MARK_STEP = { x: -30, y: -24 };
@@ -0,0 +1,132 @@
1
+ import React, { useEffect } from "react";
2
+ import { View } from "react-native";
3
+ import Svg, { Path } from "react-native-svg";
4
+ import Animated, {
5
+ Easing,
6
+ useAnimatedStyle,
7
+ useSharedValue,
8
+ withRepeat,
9
+ withTiming,
10
+ type SharedValue,
11
+ } from "react-native-reanimated";
12
+ import { useColorScheme } from "nativewind";
13
+ import {
14
+ ENTROPY_MARK_ASPECT,
15
+ ENTROPY_MARK_PATH,
16
+ ENTROPY_MARK_STEP,
17
+ ENTROPY_MARK_VIEWBOX,
18
+ } from "./entropy-mark";
19
+
20
+ // Boot/loading variant of the company mark: instead of all echoes drifting +
21
+ // breathing at once (the website hover), exactly ONE layer is visible at a
22
+ // time. A single pulse travels through the depth layers in sequence — furthest
23
+ // echo → … → sharp source — then loops forever. Each layer sits at its own
24
+ // echo offset (drifted up-left by depth × STEP), so the pulse reads as the mark
25
+ // converging from the deep echoes into the source.
26
+
27
+ interface MarkColors {
28
+ src: string;
29
+ echo: Record<1 | 2 | 3, string>;
30
+ }
31
+ const COLORS: Record<"light" | "dark", MarkColors> = {
32
+ light: { src: "#000000", echo: { 3: "#cbcbcb", 2: "#a3a3a3", 1: "#525252" } },
33
+ dark: { src: "#ffffff", echo: { 3: "#373737", 2: "#5f5f5f", 1: "#8c8c8c" } },
34
+ };
35
+
36
+ // Order the pulse travels: sharp source first → out through the echoes.
37
+ const DEPTHS = [0, 1, 2, 3] as const; // 0 = source
38
+ const COUNT = DEPTHS.length;
39
+
40
+ export interface EntropyMarkSequentialProps {
41
+ /** Rendered height in px. Width follows the ~1.63:1 aspect. */
42
+ size?: number;
43
+ /** Override the theme; defaults to the active color scheme. */
44
+ scheme?: "light" | "dark";
45
+ /** Full-cycle duration in ms (time to sweep through all layers once). */
46
+ durationMs?: number;
47
+ }
48
+
49
+ function Layer({
50
+ prog,
51
+ index,
52
+ width,
53
+ size,
54
+ color,
55
+ offsetX,
56
+ offsetY,
57
+ }: {
58
+ prog: SharedValue<number>;
59
+ index: number;
60
+ width: number;
61
+ size: number;
62
+ color: string;
63
+ offsetX: number;
64
+ offsetY: number;
65
+ }) {
66
+ const style = useAnimatedStyle(() => {
67
+ // Triangular pulse centered on this layer's slot; near-zero at the
68
+ // neighbours' centers so only one layer is lit at a time. Wraps so the
69
+ // loop has no seam.
70
+ const center = (index + 0.5) / COUNT;
71
+ let d = Math.abs(prog.value - center);
72
+ d = Math.min(d, 1 - d);
73
+ const opacity = Math.max(0, Math.min(1, 1 - d * COUNT * 1.15));
74
+ return { opacity };
75
+ });
76
+ return (
77
+ <Animated.View
78
+ style={[
79
+ {
80
+ position: "absolute",
81
+ width,
82
+ height: size,
83
+ pointerEvents: "none",
84
+ transform: [{ translateX: offsetX }, { translateY: offsetY }],
85
+ },
86
+ style,
87
+ ]}
88
+ >
89
+ <Svg width={width} height={size} viewBox={ENTROPY_MARK_VIEWBOX}>
90
+ <Path d={ENTROPY_MARK_PATH} fillRule="evenodd" fill={color} />
91
+ </Svg>
92
+ </Animated.View>
93
+ );
94
+ }
95
+
96
+ export function EntropyMarkSequential({
97
+ size = 96,
98
+ scheme,
99
+ durationMs = 1000,
100
+ }: EntropyMarkSequentialProps) {
101
+ const { colorScheme } = useColorScheme();
102
+ const c = COLORS[scheme ?? (colorScheme === "dark" ? "dark" : "light")];
103
+ const width = Math.round(size * ENTROPY_MARK_ASPECT);
104
+
105
+ const prog = useSharedValue(0);
106
+ useEffect(() => {
107
+ prog.value = withRepeat(
108
+ withTiming(1, { duration: durationMs, easing: Easing.linear }),
109
+ -1,
110
+ false
111
+ );
112
+ }, [prog, durationMs]);
113
+
114
+ return (
115
+ <View style={{ width, height: size }}>
116
+ {DEPTHS.map((depth, index) => (
117
+ <Layer
118
+ key={depth}
119
+ prog={prog}
120
+ index={index}
121
+ width={width}
122
+ size={size}
123
+ color={depth === 0 ? c.src : c.echo[depth]}
124
+ offsetX={depth * ENTROPY_MARK_STEP.x}
125
+ offsetY={depth * ENTROPY_MARK_STEP.y}
126
+ />
127
+ ))}
128
+ </View>
129
+ );
130
+ }
131
+
132
+ export default EntropyMarkSequential;