this.gui 1.3.41 → 1.3.42

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 (310) hide show
  1. package/package.json +3 -2
  2. package/src/GUI.tsx +46 -0
  3. package/src/QRouter/QRegistry.tsx +53 -0
  4. package/src/QRouter/QRouter.stories.tsx +31 -0
  5. package/src/QRouter/QRouter.tsx +57 -0
  6. package/src/gui/Theme/GuiProvider.tsx +111 -0
  7. package/src/gui/Theme/Icon/Icon.resolver.tsx +29 -0
  8. package/src/gui/Theme/Icon/Icon.tsx +43 -0
  9. package/src/gui/Theme/Layout/Content/Content.resolver.tsx +0 -0
  10. package/src/gui/Theme/Layout/Content/Content.stories.tsx +88 -0
  11. package/src/gui/Theme/Layout/Content/Content.tsx +53 -0
  12. package/src/gui/Theme/Layout/Content/Content.types.tsx +40 -0
  13. package/src/gui/Theme/Layout/Footer/Footer.resolver.tsx +45 -0
  14. package/src/gui/Theme/Layout/Footer/Footer.stories.tsx +205 -0
  15. package/src/gui/Theme/Layout/Footer/Footer.tsx +337 -0
  16. package/src/gui/Theme/Layout/Footer/Footer.types.ts +40 -0
  17. package/src/gui/Theme/Layout/Layout/Layout.resolver.tsx +37 -0
  18. package/src/gui/Theme/Layout/Layout/Layout.stories.tsx +289 -0
  19. package/src/gui/Theme/Layout/Layout/Layout.tsx +117 -0
  20. package/src/gui/Theme/Layout/Layout/Layout.types.ts +57 -0
  21. package/src/gui/Theme/Layout/Layout/useLayoutBreakpoints.ts +9 -0
  22. package/src/gui/Theme/Layout/Namespace/Namespace.stories.tsx +105 -0
  23. package/src/gui/Theme/Layout/Namespace/Namespace.tsx +26 -0
  24. package/src/gui/Theme/Layout/Sidebars/LeftSidebar/LeftSidebar.resolver.tsx +87 -0
  25. package/src/gui/Theme/Layout/Sidebars/LeftSidebar/LeftSidebar.stories.tsx +199 -0
  26. package/src/gui/Theme/Layout/Sidebars/LeftSidebar/LeftSidebar.tsx +311 -0
  27. package/src/gui/Theme/Layout/Sidebars/LeftSidebar/LeftSidebar.types.ts +41 -0
  28. package/src/gui/Theme/Layout/Sidebars/LeftSidebar/SidebarToggleButton.tsx +53 -0
  29. package/src/gui/Theme/Layout/Sidebars/LeftSidebar/components/LeftSidebarAction/LeftSidebarAction.resolver.tsx +19 -0
  30. package/src/gui/Theme/Layout/Sidebars/LeftSidebar/components/LeftSidebarAction/LeftSidebarAction.tsx +107 -0
  31. package/src/gui/Theme/Layout/Sidebars/LeftSidebar/components/LeftSidebarLink/LeftSidebarLink.resolver.tsx +0 -0
  32. package/src/gui/Theme/Layout/Sidebars/LeftSidebar/components/LeftSidebarLink/LeftSidebarLink.tsx +134 -0
  33. package/src/gui/Theme/Layout/Sidebars/LeftSidebar/components/LeftSidebarLink/LeftSidebarLink.types.ts +15 -0
  34. package/src/gui/Theme/Layout/Sidebars/LeftSidebar/components/LeftSidebarMenu/LeftSidebarMenu.tsx +142 -0
  35. package/src/gui/Theme/Layout/Sidebars/LeftSidebar/components/LeftSidebarToggleButton/LeftSidebarToggleButton.tsx +23 -0
  36. package/src/gui/Theme/Layout/Sidebars/RightSidebar/RightSidebar.resolver.tsx +35 -0
  37. package/src/gui/Theme/Layout/Sidebars/RightSidebar/RightSidebar.stories.tsx +239 -0
  38. package/src/gui/Theme/Layout/Sidebars/RightSidebar/RightSidebar.tsx +319 -0
  39. package/src/gui/Theme/Layout/Sidebars/RightSidebar/RightSidebar.types.ts +17 -0
  40. package/src/gui/Theme/Layout/Sidebars/RightSidebar/components/RightSidebarAction/RightSidebarAction.tsx +102 -0
  41. package/src/gui/Theme/Layout/Sidebars/RightSidebar/components/RightSidebarLink/RightSidebarLink.tsx +132 -0
  42. package/src/gui/Theme/Layout/Sidebars/RightSidebar/components/RightSidebarMenu/RightSidebarMenu.tsx +140 -0
  43. package/src/gui/Theme/Layout/Sidebars/RightSidebar/components/RightSidebarToggleButton/RightSidebarToggleButton.tsx +22 -0
  44. package/src/gui/Theme/Layout/StickyOptions/StickyOptionsTop.stories.tsx +469 -0
  45. package/src/gui/Theme/Layout/StickyOptions/StickyOptionsTop.tsx +489 -0
  46. package/src/gui/Theme/Layout/TopBar/TopBar.resolver.tsx +86 -0
  47. package/src/gui/Theme/Layout/TopBar/TopBar.stories.tsx +350 -0
  48. package/src/gui/Theme/Layout/TopBar/TopBar.tsx +292 -0
  49. package/src/gui/Theme/Layout/TopBar/TopBar.types.ts +39 -0
  50. package/src/gui/Theme/Layout/TopBar/components/TopBarAction/TopBarAction.stories.tsx +83 -0
  51. package/src/gui/Theme/Layout/TopBar/components/TopBarAction/TopBarAction.tsx +18 -0
  52. package/src/gui/Theme/Layout/TopBar/components/TopBarAction/TopBarAction.types.ts +4 -0
  53. package/src/gui/Theme/Layout/TopBar/components/TopBarLink/TopBarLink.stories.tsx +189 -0
  54. package/src/gui/Theme/Layout/TopBar/components/TopBarLink/TopBarLink.tsx +30 -0
  55. package/src/gui/Theme/Layout/TopBar/components/TopBarLink/TopBarLink.types.ts +9 -0
  56. package/src/gui/Theme/Layout/TopBar/components/TopBarMenu/TopBarMenu.resolver.tsx +14 -0
  57. package/src/gui/Theme/Layout/TopBar/components/TopBarMenu/TopBarMenu.stories.tsx +56 -0
  58. package/src/gui/Theme/Layout/TopBar/components/TopBarMenu/TopBarMenu.tsx +123 -0
  59. package/src/gui/Theme/Layout/TopBar/components/TopBarMenu/TopBarMenu.types.ts +44 -0
  60. package/src/gui/Theme/catalog/CherryByte/CherryByte.png +0 -0
  61. package/src/gui/Theme/catalog/CherryByte/dark.tokens.ts +47 -0
  62. package/src/gui/Theme/catalog/CherryByte/light.tokens.ts +47 -0
  63. package/src/gui/Theme/catalog/CherryByte/manifest.ts +24 -0
  64. package/src/gui/Theme/catalog/GhostShell/dark.tokens.ts +43 -0
  65. package/src/gui/Theme/catalog/GhostShell/ghost.png +0 -0
  66. package/src/gui/Theme/catalog/GhostShell/light.tokens.ts +39 -0
  67. package/src/gui/Theme/catalog/GhostShell/manifest.ts +24 -0
  68. package/src/gui/Theme/catalog/LunaHex/LunaHex.png +0 -0
  69. package/src/gui/Theme/catalog/LunaHex/dark.tokens.ts +34 -0
  70. package/src/gui/Theme/catalog/LunaHex/light.tokens.ts +74 -0
  71. package/src/gui/Theme/catalog/LunaHex/manifest.ts +24 -0
  72. package/src/gui/Theme/catalog/MUI/MUI.png +0 -0
  73. package/src/gui/Theme/catalog/MUI/dark.tokens.ts +58 -0
  74. package/src/gui/Theme/catalog/MUI/light.tokens.ts +74 -0
  75. package/src/gui/Theme/catalog/MUI/manifest.ts +24 -0
  76. package/src/gui/Theme/catalog/PrinceOfDarkness/dark.tokens.ts +48 -0
  77. package/src/gui/Theme/catalog/PrinceOfDarkness/light.tokens.ts +47 -0
  78. package/src/gui/Theme/catalog/PrinceOfDarkness/manifest.ts +24 -0
  79. package/src/gui/Theme/catalog/PrinceOfDarkness/prince.png +0 -0
  80. package/src/gui/Theme/catalog/PrinceOfDarkness/princeOfDarkness.png +0 -0
  81. package/src/gui/Theme/catalog/Seafoam/dark.tokens.ts +49 -0
  82. package/src/gui/Theme/catalog/Seafoam/light.tokens.ts +47 -0
  83. package/src/gui/Theme/catalog/Seafoam/manifest.ts +24 -0
  84. package/src/gui/Theme/catalog/Seafoam/seaFoam.png +0 -0
  85. package/src/gui/Theme/catalog/neurons/dark.tokens.ts +58 -0
  86. package/src/gui/Theme/catalog/neurons/light.tokens.ts +74 -0
  87. package/src/gui/Theme/catalog/neurons/manifest.ts +24 -0
  88. package/src/gui/Theme/catalog/neurons/neurons.me.png +0 -0
  89. package/src/gui/Theme/fromTokens.ts +272 -0
  90. package/src/gui/Theme/gui.css +31 -0
  91. package/src/gui/Theme/index.ts +17 -0
  92. package/src/gui/Theme/styles/buildShadows.ts +83 -0
  93. package/src/gui/Theme/styles/theme.tokens.ts +108 -0
  94. package/src/gui/Theme/utils/catalog.ts +61 -0
  95. package/src/gui/Theme/utils/persistence.ts +66 -0
  96. package/src/gui/Theme/utils/themeUtils.ts +34 -0
  97. package/src/gui/components/atoms/AppBar/AppBar.resolver.tsx +46 -0
  98. package/src/gui/components/atoms/AppBar/AppBar.stories.tsx +251 -0
  99. package/src/gui/components/atoms/AppBar/AppBar.tsx +107 -0
  100. package/src/gui/components/atoms/AppBar/AppBar.types.ts +28 -0
  101. package/src/gui/components/atoms/Avatar/Avatar.resolver.tsx +61 -0
  102. package/src/gui/components/atoms/Avatar/Avatar.stories.tsx +36 -0
  103. package/src/gui/components/atoms/Avatar/Avatar.tsx +14 -0
  104. package/src/gui/components/atoms/Box/Box.resolver.tsx +171 -0
  105. package/src/gui/components/atoms/Box/Box.stories.tsx +263 -0
  106. package/src/gui/components/atoms/Box/Box.tsx +15 -0
  107. package/src/gui/components/atoms/Button/Button.resolver.tsx +103 -0
  108. package/src/gui/components/atoms/Button/Button.stories.tsx +219 -0
  109. package/src/gui/components/atoms/Button/Button.tsx +40 -0
  110. package/src/gui/components/atoms/Card/Card.resolver.tsx +63 -0
  111. package/src/gui/components/atoms/Card/Card.stories.tsx +54 -0
  112. package/src/gui/components/atoms/Card/Card.tsx +13 -0
  113. package/src/gui/components/atoms/CardActions/CardActions.resolver.tsx +59 -0
  114. package/src/gui/components/atoms/CardActions/CardActions.stories.tsx +32 -0
  115. package/src/gui/components/atoms/CardActions/CardActions.tsx +14 -0
  116. package/src/gui/components/atoms/CardContent/CardContent.resolver.tsx +60 -0
  117. package/src/gui/components/atoms/CardContent/CardContent.stories.tsx +34 -0
  118. package/src/gui/components/atoms/CardContent/CardContent.tsx +13 -0
  119. package/src/gui/components/atoms/CardHeader/CardHeader.resolver.tsx +68 -0
  120. package/src/gui/components/atoms/CardHeader/CardHeader.stories.tsx +40 -0
  121. package/src/gui/components/atoms/CardHeader/CardHeader.tsx +12 -0
  122. package/src/gui/components/atoms/Collapse/Collapse.resolver.tsx +85 -0
  123. package/src/gui/components/atoms/Collapse/Collapse.stories.tsx +130 -0
  124. package/src/gui/components/atoms/Collapse/Collapse.tsx +17 -0
  125. package/src/gui/components/atoms/Divider/Divider.resolver.tsx +95 -0
  126. package/src/gui/components/atoms/Divider/Divider.stories.tsx +108 -0
  127. package/src/gui/components/atoms/Divider/Divider.tsx +14 -0
  128. package/src/gui/components/atoms/Drawer/Drawer.resolver.tsx +116 -0
  129. package/src/gui/components/atoms/Drawer/Drawer.stories.tsx +223 -0
  130. package/src/gui/components/atoms/Drawer/Drawer.tsx +25 -0
  131. package/src/gui/components/atoms/Grid/Grid.resolver.tsx +33 -0
  132. package/src/gui/components/atoms/Grid/Grid.stories.tsx +136 -0
  133. package/src/gui/components/atoms/Grid/Grid.tsx +15 -0
  134. package/src/gui/components/atoms/Grid/Grid.types.ts +9 -0
  135. package/src/gui/components/atoms/IconButton/IconButton.resolver.tsx +137 -0
  136. package/src/gui/components/atoms/IconButton/IconButton.stories.tsx +134 -0
  137. package/src/gui/components/atoms/IconButton/IconButton.tsx +22 -0
  138. package/src/gui/components/atoms/Link/Link.resolver.tsx +74 -0
  139. package/src/gui/components/atoms/Link/Link.stories.tsx +157 -0
  140. package/src/gui/components/atoms/Link/Link.tsx +36 -0
  141. package/src/gui/components/atoms/List/List.resolver.tsx +94 -0
  142. package/src/gui/components/atoms/List/List.stories.tsx +137 -0
  143. package/src/gui/components/atoms/List/List.tsx +20 -0
  144. package/src/gui/components/atoms/ListItem/ListItem.resolver.tsx +88 -0
  145. package/src/gui/components/atoms/ListItem/ListItem.stories.tsx +151 -0
  146. package/src/gui/components/atoms/ListItem/ListItem.tsx +19 -0
  147. package/src/gui/components/atoms/ListItemButton/ListItemButton.resolver.tsx +214 -0
  148. package/src/gui/components/atoms/ListItemButton/ListItemButton.stories.tsx +155 -0
  149. package/src/gui/components/atoms/ListItemButton/ListItemButton.tsx +15 -0
  150. package/src/gui/components/atoms/ListItemIcon/ListItemIcon.resolver.tsx +102 -0
  151. package/src/gui/components/atoms/ListItemIcon/ListItemIcon.stories.tsx +132 -0
  152. package/src/gui/components/atoms/ListItemIcon/ListItemIcon.tsx +11 -0
  153. package/src/gui/components/atoms/ListItemText/ListItemText.resolver.tsx +112 -0
  154. package/src/gui/components/atoms/ListItemText/ListItemText.stories.tsx +156 -0
  155. package/src/gui/components/atoms/ListItemText/ListItemText.tsx +15 -0
  156. package/src/gui/components/atoms/Menu/Menu.resolver.tsx +112 -0
  157. package/src/gui/components/atoms/Menu/Menu.stories.tsx +162 -0
  158. package/src/gui/components/atoms/Menu/Menu.tsx +17 -0
  159. package/src/gui/components/atoms/MenuItem/MenuItem.resolver.tsx +183 -0
  160. package/src/gui/components/atoms/MenuItem/MenuItem.stories.tsx +134 -0
  161. package/src/gui/components/atoms/MenuItem/MenuItem.tsx +14 -0
  162. package/src/gui/components/atoms/Paper/Paper.resolver.tsx +98 -0
  163. package/src/gui/components/atoms/Paper/Paper.stories.tsx +184 -0
  164. package/src/gui/components/atoms/Paper/Paper.tsx +15 -0
  165. package/src/gui/components/atoms/Section/Section.resolver.tsx +10 -0
  166. package/src/gui/components/atoms/Section/Section.stories.tsx +189 -0
  167. package/src/gui/components/atoms/Section/Section.tsx +76 -0
  168. package/src/gui/components/atoms/Section/Section.types.tsx +24 -0
  169. package/src/gui/components/atoms/Stack/Stack.resolver.tsx +94 -0
  170. package/src/gui/components/atoms/Stack/Stack.stories.tsx +160 -0
  171. package/src/gui/components/atoms/Stack/Stack.tsx +15 -0
  172. package/src/gui/components/atoms/Surface/Surface.resolver.tsx +37 -0
  173. package/src/gui/components/atoms/Surface/Surface.tsx +49 -0
  174. package/src/gui/components/atoms/Surface/Surface.types.ts +20 -0
  175. package/src/gui/components/atoms/Switch/Switch.resolver.tsx +53 -0
  176. package/src/gui/components/atoms/Switch/Switch.stories.tsx +236 -0
  177. package/src/gui/components/atoms/Switch/Switch.tsx +22 -0
  178. package/src/gui/components/atoms/Table/Body/TableBody.tsx +7 -0
  179. package/src/gui/components/atoms/Table/Cell/TableCell.tsx +18 -0
  180. package/src/gui/components/atoms/Table/Head/TableHead.tsx +9 -0
  181. package/src/gui/components/atoms/Table/Row/TableRow.tsx +20 -0
  182. package/src/gui/components/atoms/Table/Table.resolver.tsx +77 -0
  183. package/src/gui/components/atoms/Table/Table.stories.tsx +173 -0
  184. package/src/gui/components/atoms/Table/Table.tsx +20 -0
  185. package/src/gui/components/atoms/TextField/TextField.stories.tsx +25 -0
  186. package/src/gui/components/atoms/TextField/TextField.tsx +15 -0
  187. package/src/gui/components/atoms/Toolbar/Toolbar.resolver.tsx +60 -0
  188. package/src/gui/components/atoms/Toolbar/Toolbar.stories.tsx +155 -0
  189. package/src/gui/components/atoms/Toolbar/Toolbar.tsx +16 -0
  190. package/src/gui/components/atoms/Tooltip/Tooltip.resolver.tsx +142 -0
  191. package/src/gui/components/atoms/Tooltip/Tooltip.stories.tsx +117 -0
  192. package/src/gui/components/atoms/Tooltip/Tooltip.tsx +70 -0
  193. package/src/gui/components/atoms/Typography/Typography.resolver.tsx +158 -0
  194. package/src/gui/components/atoms/Typography/Typography.stories.tsx +222 -0
  195. package/src/gui/components/atoms/Typography/Typography.tsx +27 -0
  196. package/src/gui/components/atoms/Window/Nodes/node.ts +0 -0
  197. package/src/gui/components/atoms/Window/code/block/node.tsx +0 -0
  198. package/src/gui/components/atoms/Window/code/hugging.face.api.ts +11 -0
  199. package/src/gui/components/atoms/Window/connectors/index.ts +19 -0
  200. package/src/gui/components/atoms/Window/window.stories.tsx +20 -0
  201. package/src/gui/components/atoms/Window/window.tsx +636 -0
  202. package/src/gui/components/atoms/atoms.tsx +151 -0
  203. package/src/gui/components/atoms/index.ts +2 -0
  204. package/src/gui/components/generics/Cards/Gridme.jsx +52 -0
  205. package/src/gui/components/generics/Cards/LilBox.jsx +65 -0
  206. package/src/gui/components/generics/Cards/ModuleCard.jsx +106 -0
  207. package/src/gui/components/generics/Chats/FullChatBot.jsx +223 -0
  208. package/src/gui/components/generics/Code/CodeBlock.jsx +33 -0
  209. package/src/gui/components/generics/EmojiCursor/EmojiCursor.stories.tsx +153 -0
  210. package/src/gui/components/generics/EmojiCursor/EmojiCursor.tsx +23 -0
  211. package/src/gui/components/generics/Feedback/Callout.jsx +92 -0
  212. package/src/gui/components/generics/Layout/GridX.jsx +29 -0
  213. package/src/gui/components/generics/Layout/Hero2.jsx +132 -0
  214. package/src/gui/components/generics/Layout/PageContainer.jsx +29 -0
  215. package/src/gui/components/generics/Layout/PageDivider.jsx +20 -0
  216. package/src/gui/components/generics/Layout/Section.jsx +43 -0
  217. package/src/gui/components/generics/Layout/SectionHeader.jsx +21 -0
  218. package/src/gui/components/generics/Media/Img.jsx +58 -0
  219. package/src/gui/components/generics/Media/VideoEmbed.jsx +51 -0
  220. package/src/gui/components/generics/Organization/TableOfContents.jsx +51 -0
  221. package/src/gui/components/generics/Organization/Tabs.jsx +45 -0
  222. package/src/gui/components/generics/Text/TextList.jsx +41 -0
  223. package/src/gui/components/generics/Text/TextParagraph.jsx +28 -0
  224. package/src/gui/components/generics/Text/TextQuote.jsx +23 -0
  225. package/src/gui/components/generics/Text/TextTitle.jsx +44 -0
  226. package/src/gui/components/molecules/Dialog/Dialog.stories.tsx +18 -0
  227. package/src/gui/components/molecules/Dialog/Dialog.tsx +5 -0
  228. package/src/gui/components/molecules/Hero/Hero.stories.tsx +140 -0
  229. package/src/gui/components/molecules/Hero/Hero.tsx +152 -0
  230. package/src/gui/components/molecules/Hero/Hero.types.tsx +18 -0
  231. package/src/gui/components/molecules/Modal/Modal.resolver.tsx +38 -0
  232. package/src/gui/components/molecules/Modal/Modal.stories.tsx +82 -0
  233. package/src/gui/components/molecules/Modal/Modal.tsx +110 -0
  234. package/src/gui/components/molecules/Modal/Modal.types.ts +29 -0
  235. package/src/gui/components/molecules/Page/Page.stories.tsx +135 -0
  236. package/src/gui/components/molecules/Page/Page.tsx +94 -0
  237. package/src/gui/components/molecules/Theme/ThemeModeToggle/ThemeModeToggle.resolver.tsx +58 -0
  238. package/src/gui/components/molecules/Theme/ThemeModeToggle/ThemeModeToggle.stories.tsx +133 -0
  239. package/src/gui/components/molecules/Theme/ThemeModeToggle/ThemeModeToggle.tsx +101 -0
  240. package/src/gui/components/molecules/Theme/ThemeModeToggle/ThemeModeToggle.types.ts +29 -0
  241. package/src/gui/components/molecules/Theme/ThemesCatalog/ThemesCatalog.resolver.tsx +15 -0
  242. package/src/gui/components/molecules/Theme/ThemesCatalog/ThemesCatalog.stories.tsx +88 -0
  243. package/src/gui/components/molecules/Theme/ThemesCatalog/ThemesCatalog.tsx +167 -0
  244. package/src/gui/components/molecules/Theme/ThemesCatalog/ThemesCatalog.types.ts +34 -0
  245. package/src/gui/components/molecules/molecules.ts +49 -0
  246. package/src/gui/components/organisms/Blockchain/Blocks/BlocksTable.tsx +119 -0
  247. package/src/gui/components/organisms/Blockchain/Usernames/Identities.stories.tsx +20 -0
  248. package/src/gui/components/organisms/Blockchain/Usernames/QR.tsx +566 -0
  249. package/src/gui/components/organisms/Blockchain/Usernames/Usernames.tsx +448 -0
  250. package/src/gui/components/organisms/Blockchain/Usernames/identities.tsx +710 -0
  251. package/src/gui/components/organisms/Blockchain/blockchain.stories.tsx +17 -0
  252. package/src/gui/components/organisms/Blockchain/blockchain.tsx +368 -0
  253. package/src/gui/components/organisms/Blockchain/scripts/connection.ts +82 -0
  254. package/src/gui/components/organisms/Blockchain/scripts/match_face.ts +143 -0
  255. package/src/gui/components/organisms/HighLighter/HighLighter.stories.tsx +168 -0
  256. package/src/gui/components/organisms/HighLighter/HighLighter.tsx +420 -0
  257. package/src/gui/components/organisms/HighLighter/HighLightsDrawer.tsx +197 -0
  258. package/src/gui/components/organisms/IdentityNoise/FaceRecognition/FaceRecognition.stories.tsx +312 -0
  259. package/src/gui/components/organisms/IdentityNoise/FaceRecognition/FaceRecognition.tsx +765 -0
  260. package/src/gui/components/organisms/IdentityNoise/FaceRecognition/modules/useFaceCameraPermission.ts +70 -0
  261. package/src/gui/components/organisms/IdentityNoise/FaceRecognition/modules/useFaceLandmarker.ts +106 -0
  262. package/src/gui/components/organisms/IdentityNoise/FaceRecognition/modules/useFaceOverlay.ts +489 -0
  263. package/src/gui/components/organisms/IdentityNoise/FaceRecognition/modules/useFaceTemplate.ts +32 -0
  264. package/src/gui/components/organisms/IdentityNoise/FaceRecognition/modules/useFaceTemplateBurst.ts +178 -0
  265. package/src/gui/components/organisms/IdentityNoise/FaceRecognition/modules/verifyTemplate.ts +136 -0
  266. package/src/gui/components/organisms/IdentityNoise/IdentityNoise.tsx +403 -0
  267. package/src/gui/components/organisms/IdentityNoise/IndentityNoise.stories.tsx +15 -0
  268. package/src/gui/components/organisms/IdentityNoise/Noise/Noise.stories.tsx +206 -0
  269. package/src/gui/components/organisms/IdentityNoise/Noise/Noise.tsx +394 -0
  270. package/src/gui/components/organisms/IdentityNoise/Triad/QR.tsx +566 -0
  271. package/src/gui/components/organisms/IdentityNoise/Triad/Tiad.stories.tsx +6 -0
  272. package/src/gui/components/organisms/IdentityNoise/Triad/Triad.tsx +917 -0
  273. package/src/gui/components/organisms/IdentityNoise/Triad/handleCleak.ts +0 -0
  274. package/src/gui/components/organisms/IdentityNoise/Triad/identity.ts +31 -0
  275. package/src/gui/components/organisms/IdentityNoise/Triad/me/fundamentals/vectors/vectors.tsx +252 -0
  276. package/src/gui/components/organisms/IdentityNoise/Triad/me/me.stories.tsx +314 -0
  277. package/src/gui/components/organisms/IdentityNoise/Triad/me/me.tsx +0 -0
  278. package/src/gui/components/organisms/organisms.ts +15 -0
  279. package/src/gui/contexts/InsetsContext.tsx +40 -0
  280. package/src/gui/contexts/LeftSidebarContext.tsx +20 -0
  281. package/src/gui/contexts/RightSidebarContext.tsx +25 -0
  282. package/src/gui/contexts/ThemeContext.ts +34 -0
  283. package/src/gui/contexts/index.ts +4 -0
  284. package/src/gui/hooks/index.ts +11 -0
  285. package/src/gui/hooks/resolveColorToken.ts +39 -0
  286. package/src/gui/hooks/useCodeGen.ts +12 -0
  287. package/src/gui/hooks/useGuiMediaQuery.ts +18 -0
  288. package/src/gui/hooks/useGuiTheme.ts +18 -0
  289. package/src/gui/hooks/useInsets.ts +26 -0
  290. package/src/gui/hooks/useIsMobile.ts +13 -0
  291. package/src/gui/hooks/useIsTouchDevice.ts +25 -0
  292. package/src/gui/hooks/useLeftSidebar.ts +10 -0
  293. package/src/gui/hooks/useRightSidebar.ts +12 -0
  294. package/src/gui/hooks/useViewportKey.ts +19 -0
  295. package/src/gui/hooks/useViewportProp.ts +17 -0
  296. package/src/gui/registry/GuiRegistry.ts +19 -0
  297. package/src/gui/registry/factory.ts +12 -0
  298. package/src/gui/registry/index.ts +3 -0
  299. package/src/gui/registry/types.ts +6 -0
  300. package/src/gui/utils/nodeID.ts +11 -0
  301. package/src/registry/GuiRegistry.ts +19 -0
  302. package/src/stories/01.Home.mdx +22 -0
  303. package/src/stories/02.Understanding.This.GUI.mdx +149 -0
  304. package/src/stories/Theme/Palette.stories.tsx +86 -0
  305. package/src/stories/Theme/ThemeViewer.stories.tsx +91 -0
  306. package/src/stories/Theme/Typography.stories.jsx +211 -0
  307. package/src/stories/assets/this.GUI.png +0 -0
  308. package/src/types/gui.d.ts +67 -0
  309. package/src/types/theme.d.ts +191 -0
  310. package/src/types/viewport.ts +132 -0
@@ -0,0 +1,17 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import Blockchain from "./blockchain";
3
+
4
+ const meta: Meta<typeof Blockchain> = {
5
+ title: "Organisms/Blockchain",
6
+ component: Blockchain,
7
+ };
8
+
9
+ export default meta;
10
+ type Story = StoryObj<typeof Blockchain>;
11
+ export const Default: Story = {
12
+ render: () => <Blockchain />,
13
+ };
14
+
15
+ export const Empty: Story = {
16
+ render: () => <Blockchain />,
17
+ };
@@ -0,0 +1,368 @@
1
+ // this.GUI — Blockchain Container (Clean Version)
2
+ // This component ONLY manages:
3
+ // ✔ Endpoint URL
4
+ // ✔ Connection state
5
+ // ✔ Tabs (Users / Blocks)
6
+ // ✔ Passing endpoint prop downward
7
+ // No fetching, no table markup.
8
+ //@/gui/components/organisms/IdentityNoise/Triad/Blockchain/blockchain.tsx
9
+ import React, { useEffect, useRef, useState } from 'react';
10
+ import { Box, Button, IconButton, Tooltip, Typography } from '@/gui/components/atoms';
11
+ import Icon from '@/gui/Theme/Icon/Icon';
12
+ import { useGuiTheme, useGuiMediaQuery } from '@/gui/hooks';
13
+ import UsersTable from './Usernames/Usernames';
14
+ import { BlocksTable } from './Blocks/BlocksTable';
15
+ export default function Blockchain() {
16
+ const [endpoint, setEndpoint] = useState('http://localhost:8161');
17
+ const [connected, setConnected] = useState(false);
18
+ const [activeTab, setActiveTab] = useState<'users' | 'blocks' | 'details'>('users');
19
+ const [showEndpointInput, setShowEndpointInput] = useState(false);
20
+ const theme = useGuiTheme();
21
+ const isMobile = useGuiMediaQuery(theme.breakpoints.down('sm'));
22
+ const debounceRef = useRef<number | null>(null);
23
+ function normalizeEndpoint(raw: string) {
24
+ const v = (raw ?? '').trim();
25
+ if (!v) return null;
26
+ // If user types a token like "Blockchain", don't treat as an endpoint.
27
+ if (!v.includes('.') && !v.includes(':') && !v.startsWith('/')) return null;
28
+
29
+ // Add protocol if missing.
30
+ const withProto = /^https?:\/\//i.test(v) ? v : `http://${v}`;
31
+ // Strip trailing slash for consistent concatenation.
32
+ return withProto.replace(/\/+$/, '');
33
+ }
34
+ const safeEndpoint = normalizeEndpoint(endpoint) ?? '';
35
+
36
+ async function handleConnect() {
37
+ const base = safeEndpoint;
38
+ if (!base) {
39
+ setConnected(false);
40
+ return;
41
+ }
42
+ try {
43
+ const res = await fetch(`${base}/`, { method: 'GET' });
44
+ if (!res.ok) throw new Error('Failed');
45
+ setConnected(true);
46
+ } catch {
47
+ setConnected(false);
48
+ }
49
+ }
50
+
51
+ function scheduleConnect(nextEndpoint: string) {
52
+ if (debounceRef.current) window.clearTimeout(debounceRef.current);
53
+ const nextBase = normalizeEndpoint(nextEndpoint) ?? '';
54
+ if (!nextBase) {
55
+ if (debounceRef.current) window.clearTimeout(debounceRef.current);
56
+ setConnected(false);
57
+ return;
58
+ }
59
+
60
+ debounceRef.current = window.setTimeout(() => {
61
+ // noop: the [safeEndpoint] effect will connect using the latest endpoint value
62
+ }, 450);
63
+ }
64
+
65
+ function onEndpointKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
66
+ if (e.key === 'Enter') {
67
+ if (debounceRef.current) window.clearTimeout(debounceRef.current);
68
+ handleConnect();
69
+ }
70
+ }
71
+
72
+ useEffect(() => {
73
+ return () => {
74
+ if (debounceRef.current) window.clearTimeout(debounceRef.current);
75
+ };
76
+ }, []);
77
+
78
+ useEffect(() => {
79
+ // Auto-connect when we have a valid endpoint (on mount and whenever it changes)
80
+ if (!safeEndpoint) return;
81
+ handleConnect();
82
+ // eslint-disable-next-line react-hooks/exhaustive-deps
83
+ }, [safeEndpoint]);
84
+
85
+ return (
86
+ <Box
87
+ sx={{
88
+ border: '1px solid',
89
+ borderColor: 'divider',
90
+ borderRadius: 2,
91
+ padding: '1.5rem',
92
+ maxWidth: '900px',
93
+ margin: '0 auto',
94
+ background: 'background.paper',
95
+ position: 'relative',
96
+ }}
97
+ >
98
+ <Box
99
+ sx={{
100
+ position: 'absolute',
101
+ top: 10,
102
+ right: 10,
103
+ display: 'flex',
104
+ alignItems: 'center',
105
+ gap: 0.5,
106
+ }}
107
+ >
108
+ <Tooltip
109
+ title={showEndpointInput ? 'Hide blockchain URL' : 'Show blockchain URL'}
110
+ placement="bottom"
111
+ arrow
112
+ >
113
+ <Box component="span" sx={{ display: 'inline-flex' }}>
114
+ <IconButton
115
+ aria-label={showEndpointInput ? 'Hide blockchain input' : 'Show blockchain input'}
116
+ onClick={() => setShowEndpointInput((v) => !v)}
117
+ size="small"
118
+ sx={{
119
+ border: '1px solid',
120
+ borderColor: 'divider',
121
+ bgcolor: 'background.paper',
122
+ color:
123
+ !safeEndpoint
124
+ ? 'divider'
125
+ : connected
126
+ ? 'success.main'
127
+ : 'error.main',
128
+ '&:hover': {
129
+ bgcolor: 'background.nav',
130
+ color:
131
+ !safeEndpoint
132
+ ? 'text.secondary'
133
+ : connected
134
+ ? 'success.main'
135
+ : 'error.main',
136
+ },
137
+ }}
138
+ >
139
+ <Icon name="dns" fontSize={18} />
140
+ </IconButton>
141
+ </Box>
142
+ </Tooltip>
143
+
144
+ <Tooltip title="What is a blockchain URL?" placement="bottom" arrow>
145
+ <Box component="span" sx={{ display: 'inline-flex' }}>
146
+ <IconButton
147
+ aria-label="Blockchain URL info"
148
+ size="small"
149
+ onClick={() => setActiveTab('details')}
150
+ sx={{
151
+ border: '1px solid',
152
+ borderColor: 'divider',
153
+ bgcolor: 'background.paper',
154
+ color: 'text.secondary',
155
+ '&:hover': { bgcolor: 'background.nav', color: 'text.primary' },
156
+ }}
157
+ >
158
+ <Icon name="info" />
159
+ </IconButton>
160
+ </Box>
161
+ </Tooltip>
162
+ </Box>
163
+ {/* Connection Input */}
164
+ {showEndpointInput && (
165
+ <Box
166
+ sx={{
167
+ marginTop: '1rem',
168
+ display: 'flex',
169
+ gap: 0.75,
170
+ alignItems: 'center',
171
+ flexDirection: isMobile ? 'column' : 'row',
172
+ }}
173
+ >
174
+ <Box
175
+ sx={{
176
+ flex: '0 0 auto',
177
+ width: isMobile ? '100%' : '25%',
178
+ minWidth: 240,
179
+ }}
180
+ >
181
+ <Box
182
+ component="fieldset"
183
+ sx={{
184
+ m: 0,
185
+ p: 0,
186
+ border: '1px solid',
187
+ borderColor: connected ? 'success.main' : 'divider',
188
+ borderRadius: 2,
189
+ minHeight: 36,
190
+ bgcolor: 'background.default',
191
+ transition: 'border-color 120ms ease, box-shadow 120ms ease',
192
+ '&:focus-within': {
193
+ borderColor: connected ? 'success.main' : 'primary.main',
194
+ boxShadow: (theme: any) =>
195
+ connected
196
+ ? `0 0 0 3px ${theme?.palette?.success?.main}22`
197
+ : `0 0 0 3px ${theme?.palette?.primary?.main}22`,
198
+ },
199
+ }}
200
+ >
201
+ <Box
202
+ component="legend"
203
+ sx={{
204
+ px: 0.75,
205
+ mx: 1,
206
+ fontSize: '0.75rem',
207
+ color: connected ? 'success.main' : 'text.secondary',
208
+ lineHeight: 1,
209
+ cursor: 'help',
210
+ }}
211
+ onClick={() => setActiveTab('details')}
212
+ title="What is a blockchain URL?"
213
+ >
214
+ Blockchain
215
+ </Box>
216
+
217
+ <Box
218
+ component="input"
219
+ type="text"
220
+ name="blockchain"
221
+ aria-label="Blockchain endpoint"
222
+ placeholder="http://localhost:8161"
223
+ title="Example: http://localhost:8161"
224
+ value={endpoint}
225
+ onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
226
+ const next = e.target.value;
227
+ setEndpoint(next);
228
+ scheduleConnect(next);
229
+ }}
230
+ onKeyDown={onEndpointKeyDown}
231
+ sx={{
232
+ width: '100%',
233
+ px: 1.25,
234
+ py: 0.75,
235
+ border: 0,
236
+ outline: 'none',
237
+ bgcolor: 'transparent',
238
+ color: 'text.primary',
239
+ fontSize: '0.85rem',
240
+ boxSizing: 'border-box',
241
+ }}
242
+ />
243
+ </Box>
244
+ </Box>
245
+ <Box
246
+ sx={{
247
+ display: 'flex',
248
+ alignItems: 'center',
249
+ justifyContent: 'flex-end',
250
+ width: isMobile ? '100%' : 'auto',
251
+ }}
252
+ >
253
+ <IconButton
254
+ aria-label={connected ? 'Connected' : 'Connect'}
255
+ onClick={() => handleConnect()}
256
+ size="small"
257
+ disabled={!safeEndpoint}
258
+ sx={{
259
+ border: '1px solid',
260
+ borderColor: 'divider',
261
+ bgcolor: 'background.paper',
262
+ color: connected ? 'success.main' : 'text.secondary',
263
+ '&:hover': {
264
+ bgcolor: 'background.nav',
265
+ color: connected ? 'success.main' : 'text.primary',
266
+ },
267
+ }}
268
+ >
269
+ <Icon name={connected ? 'check' : 'sync'} />
270
+ </IconButton>
271
+ </Box>
272
+ </Box>
273
+ )}
274
+ {/* Tabs */}
275
+ <Box
276
+ sx={{
277
+ display: 'flex',
278
+ gap: '1rem',
279
+ marginTop: '1.5rem',
280
+ marginBottom: '1rem',
281
+ borderBottom: '1px solid rgba(255,255,255,0.1)',
282
+ paddingBottom: '0.5rem',
283
+ }}
284
+ >
285
+ <Button
286
+ variant={activeTab === 'users' ? 'outlined' : 'text'}
287
+ size="small"
288
+ sx={{ minHeight: 32, px: 1.25, fontSize: '0.8rem' }}
289
+ onClick={() => setActiveTab('users')}
290
+ >
291
+ Users
292
+ </Button>
293
+ <Button
294
+ variant={activeTab === 'blocks' ? 'outlined' : 'text'}
295
+ size="small"
296
+ sx={{ minHeight: 32, px: 1.25, fontSize: '0.8rem' }}
297
+ onClick={() => setActiveTab('blocks')}
298
+ >
299
+ Blocks
300
+ </Button>
301
+ <Button
302
+ variant={activeTab === 'details' ? 'outlined' : 'text'}
303
+ size="small"
304
+ sx={{ minHeight: 32, px: 1.25, fontSize: '0.8rem' }}
305
+ onClick={() => setActiveTab('details')}
306
+ >
307
+ Details
308
+ </Button>
309
+ </Box>
310
+ {/* Render Only Child Components */}
311
+ {activeTab === 'users' && safeEndpoint && <UsersTable endpoint={safeEndpoint} />}
312
+ {activeTab === 'blocks' && safeEndpoint && <BlocksTable endpoint={safeEndpoint} />}
313
+
314
+ {activeTab === 'details' && (
315
+ <Box
316
+ sx={{
317
+ border: '1px solid',
318
+ borderColor: 'divider',
319
+ borderRadius: 2,
320
+ p: 2,
321
+ bgcolor: 'background.default',
322
+ }}
323
+ >
324
+ <Typography variant="h6" sx={{ mb: 1 }}>
325
+ Blockchain URL
326
+ </Typography>
327
+
328
+ <Typography variant="body2" sx={{ color: 'text.secondary', mb: 1.5 }}>
329
+ This view connects to a blockchain node running at a specific <strong>host</strong> and <strong>port</strong>.
330
+ </Typography>
331
+
332
+ <Typography variant="body2" sx={{ mb: 1.25 }}>
333
+ <strong>What is a blockchain URL?</strong>
334
+ <br />
335
+ It’s the address of a server (node) that exposes blockchain data over HTTP. Example:
336
+ <br />
337
+ <Typography component="span" sx={{ fontFamily: 'monospace' }}>
338
+ http://localhost:8161
339
+ </Typography>
340
+ </Typography>
341
+
342
+ <Typography variant="body2" sx={{ mb: 1.25 }}>
343
+ <strong>What does this screen do?</strong>
344
+ <br />
345
+ When you enter a URL, this page tries to reach that node and then displays:
346
+ </Typography>
347
+
348
+ <Box component="ul" sx={{ m: 0, pl: 2.5, color: 'text.secondary' }}>
349
+ <li>
350
+ <Typography variant="body2" sx={{ color: 'text.secondary' }}>
351
+ <strong>Users</strong> — identities or usernames registered on that chain (if supported).
352
+ </Typography>
353
+ </li>
354
+ <li>
355
+ <Typography variant="body2" sx={{ color: 'text.secondary' }}>
356
+ <strong>Blocks</strong> — the latest blocks and their data from that chain (if supported).
357
+ </Typography>
358
+ </li>
359
+ </Box>
360
+
361
+ <Typography variant="body2" sx={{ color: 'text.secondary', mt: 1.5 }}>
362
+ Tip: <strong>localhost</strong> means the blockchain node is running on your own machine. A remote host means it’s running somewhere else.
363
+ </Typography>
364
+ </Box>
365
+ )}
366
+ </Box>
367
+ );
368
+ }
@@ -0,0 +1,82 @@
1
+ import React from "react";
2
+ export type ConnectionStatus = 'idle' | 'connecting' | 'online' | 'offline' | 'declined';
3
+ export type UsernameStatus = 'idle' | 'checking' | 'exists' | 'available' | 'error';
4
+ export function normalizeBlockchain(raw: string): string {
5
+ return raw.trim()
6
+ .replace(/^https?:\/\//i, '')
7
+ .replace(/\/$/, '');
8
+ }
9
+ export function useBlockchainConnection(params: {
10
+ blockchain: string;
11
+ username: string;
12
+ me: any;
13
+ debouncePingMs?: number;
14
+ debounceUserMs?: number;
15
+ }): {
16
+ blockchainHost: string;
17
+ blockchainBaseUrl: string;
18
+ connectionStatus: ConnectionStatus;
19
+ usernameStatus: UsernameStatus;
20
+ } {
21
+ const {
22
+ blockchain,
23
+ username,
24
+ debouncePingMs = 400,
25
+ debounceUserMs = 350,
26
+ } = params;
27
+ const blockchainHost = normalizeBlockchain(blockchain);
28
+ const blockchainBaseUrl = `http://${blockchainHost}`;
29
+ const [connectionStatus, setConnectionStatus] = React.useState<ConnectionStatus>('idle');
30
+ const [usernameStatus, setUsernameStatus] = React.useState<UsernameStatus>('idle');
31
+ React.useEffect(() => {
32
+ if (!blockchainHost) {
33
+ setConnectionStatus('idle');
34
+ return;
35
+ }
36
+ setConnectionStatus('connecting');
37
+ const handle = setTimeout(() => {
38
+ fetch(`${blockchainBaseUrl}/`)
39
+ .then(res => {
40
+ if (res.ok) setConnectionStatus('online');
41
+ else setConnectionStatus('offline');
42
+ })
43
+ .catch(err => {
44
+ const msg = err.message.toLowerCase();
45
+ if (msg.includes('cors') || msg.includes('failed to fetch')) setConnectionStatus('declined');
46
+ else setConnectionStatus('offline');
47
+ });
48
+ }, debouncePingMs);
49
+ return () => clearTimeout(handle);
50
+ }, [blockchainHost, blockchainBaseUrl, debouncePingMs]);
51
+ React.useEffect(() => {
52
+ if (connectionStatus !== 'online' || !username) {
53
+ setUsernameStatus('idle');
54
+ return;
55
+ }
56
+ setUsernameStatus('checking');
57
+ // Try me['@'](username) to ignore validation errors while typing
58
+ try {
59
+ params.me['@'](username);
60
+ } catch {
61
+ // ignore
62
+ }
63
+
64
+ const handle = setTimeout(() => {
65
+ fetch(`${blockchainBaseUrl}/users/${username}`)
66
+ .then(res => {
67
+ if (res.status === 200) setUsernameStatus('exists');
68
+ else if (res.status === 404) setUsernameStatus('available');
69
+ else setUsernameStatus('error');
70
+ })
71
+ .catch(() => setUsernameStatus('error'));
72
+ }, debounceUserMs);
73
+
74
+ return () => clearTimeout(handle);
75
+ }, [connectionStatus, username, blockchainBaseUrl, debounceUserMs, params.me]);
76
+ return {
77
+ blockchainHost,
78
+ blockchainBaseUrl,
79
+ connectionStatus,
80
+ usernameStatus,
81
+ };
82
+ }
@@ -0,0 +1,143 @@
1
+ import React from "react";
2
+
3
+ export type MatchFaceStatus = "idle" | "checking" | "match" | "no_match" | "not_enrolled" | "error";
4
+
5
+ // Keep this intentionally simple and transport-only.
6
+ // The server decides how to interpret the payload (template, blendshapes, etc.).
7
+ export type MatchFaceResult = {
8
+ ok: boolean;
9
+ match?: {
10
+ username: string;
11
+ identityHash?: string;
12
+ score?: number;
13
+ };
14
+ error?: string;
15
+ };
16
+
17
+ export function normalizeBlockchain(raw: string): string {
18
+ return String(raw || "")
19
+ .trim()
20
+ .replace(/^https?:\/\//i, "")
21
+ .replace(/\/$/, "");
22
+ }
23
+
24
+ export function useFaceMatch(params: {
25
+ blockchain: string;
26
+ /** Optional: only used for debugging / scoping on the server if you want it */
27
+ username?: string;
28
+ /** Any serializable payload from FaceRecognition (face template, blendshapes, etc.) */
29
+ payload: any | null;
30
+ /** Set true to run automatically when payload changes */
31
+ auto?: boolean;
32
+ debounceMs?: number;
33
+ }): {
34
+ status: MatchFaceStatus;
35
+ result: MatchFaceResult | null;
36
+ match: () => Promise<void>;
37
+ reset: () => void;
38
+ } {
39
+ const {
40
+ blockchain,
41
+ username,
42
+ payload,
43
+ auto = false,
44
+ debounceMs = 250,
45
+ } = params;
46
+
47
+ const blockchainHost = React.useMemo(() => normalizeBlockchain(blockchain), [blockchain]);
48
+ const blockchainBaseUrl = React.useMemo(
49
+ () => (blockchainHost ? `http://${blockchainHost}` : ""),
50
+ [blockchainHost]
51
+ );
52
+
53
+ const [status, setStatus] = React.useState<MatchFaceStatus>("idle");
54
+ const [result, setResult] = React.useState<MatchFaceResult | null>(null);
55
+
56
+ const reset = React.useCallback(() => {
57
+ setStatus("idle");
58
+ setResult(null);
59
+ }, []);
60
+
61
+ const match = React.useCallback(async () => {
62
+ if (!blockchainBaseUrl) {
63
+ setStatus("error");
64
+ setResult({ ok: false, error: "BLOCKCHAIN_REQUIRED" });
65
+ return;
66
+ }
67
+ if (!payload) {
68
+ setStatus("error");
69
+ setResult({ ok: false, error: "FACE_PAYLOAD_REQUIRED" });
70
+ return;
71
+ }
72
+
73
+ setStatus("checking");
74
+ setResult(null);
75
+
76
+ try {
77
+ // Hardcoded route (same as /users/:username pattern).
78
+ // You can later swap this to your unified ME operator surface.
79
+ const resp = await fetch(`${blockchainBaseUrl}/faces/match`, {
80
+ method: "POST",
81
+ headers: { "Content-Type": "application/json" },
82
+ body: JSON.stringify({ username: username || "", template: payload }),
83
+ });
84
+
85
+ const json = (await resp.json().catch(() => null)) as MatchFaceResult | null;
86
+
87
+ if (!resp.ok) {
88
+ // If the ledger returns 404, we want to reflect it in the UI as a concrete state
89
+ // so the face widget can show a "404"/"not enrolled" label.
90
+ if (resp.status === 404) {
91
+ setStatus("not_enrolled");
92
+ setResult(json || { ok: false, error: "HTTP_404" });
93
+ return;
94
+ }
95
+
96
+ setStatus("error");
97
+ setResult(json || { ok: false, error: `HTTP_${resp.status}` });
98
+ return;
99
+ }
100
+
101
+ // Support both response shapes:
102
+ // A) { ok, match: { username, ... } }
103
+ // B) { ok, match: boolean, score?, best? }
104
+ const hasObjectMatch = Boolean((json as any)?.ok && (json as any)?.match && typeof (json as any).match === 'object');
105
+ const hasBooleanMatch = Boolean((json as any)?.ok && typeof (json as any)?.match === 'boolean');
106
+
107
+ if (hasObjectMatch) {
108
+ setStatus("match");
109
+ setResult(json);
110
+ return;
111
+ }
112
+
113
+ if (hasBooleanMatch) {
114
+ const m = Boolean((json as any).match);
115
+ setStatus(m ? "match" : "no_match");
116
+ setResult(json);
117
+ return;
118
+ }
119
+
120
+ // Fallback
121
+ setStatus("no_match");
122
+ setResult(json || { ok: true });
123
+ } catch (e: any) {
124
+ setStatus("error");
125
+ setResult({ ok: false, error: e?.message || "MATCH_FAILED" });
126
+ }
127
+ }, [blockchainBaseUrl, payload, username]);
128
+
129
+ // Optional auto-run
130
+ React.useEffect(() => {
131
+ if (!auto) return;
132
+ if (!payload) return;
133
+ if (!blockchainBaseUrl) return;
134
+
135
+ const h = window.setTimeout(() => {
136
+ match();
137
+ }, debounceMs);
138
+
139
+ return () => window.clearTimeout(h);
140
+ }, [auto, payload, blockchainBaseUrl, debounceMs, match]);
141
+
142
+ return { status, result, match, reset };
143
+ }