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,70 @@
1
+ import * as React from 'react';
2
+
3
+ export type CameraPermissionState = 'unknown' | 'granted' | 'denied' | 'prompt';
4
+
5
+ export type UseFaceCameraPermissionArgs = {
6
+ /** When false, the hook stays idle and returns 'unknown'. */
7
+ enabled: boolean;
8
+ };
9
+
10
+ export type UseFaceCameraPermissionResult = {
11
+ permissionState: CameraPermissionState;
12
+ };
13
+
14
+ /**
15
+ * useFaceCameraPermission
16
+ *
17
+ * Reads camera permission state using `navigator.permissions` when available.
18
+ * - Some browsers (notably Safari) don't support `navigator.permissions` for camera.
19
+ * - When unsupported (or errors), returns 'unknown'.
20
+ */
21
+ export function useFaceCameraPermission(
22
+ args: UseFaceCameraPermissionArgs
23
+ ): UseFaceCameraPermissionResult {
24
+ const { enabled } = args;
25
+ const [permissionState, setPermissionState] =
26
+ React.useState<CameraPermissionState>('unknown');
27
+
28
+ React.useEffect(() => {
29
+ if (!enabled) {
30
+ setPermissionState('unknown');
31
+ return;
32
+ }
33
+
34
+ let cancelled = false;
35
+
36
+ async function checkPermission() {
37
+ try {
38
+ const perms: any = (navigator as any)?.permissions;
39
+ if (!perms?.query) {
40
+ if (!cancelled) setPermissionState('unknown');
41
+ return;
42
+ }
43
+
44
+ const status = await perms.query({ name: 'camera' as any });
45
+ if (cancelled) return;
46
+
47
+ setPermissionState((status?.state as CameraPermissionState) ?? 'unknown');
48
+
49
+ if (status && typeof status.onchange !== 'undefined') {
50
+ status.onchange = () => {
51
+ if (cancelled) return;
52
+ setPermissionState((status?.state as CameraPermissionState) ?? 'unknown');
53
+ };
54
+ }
55
+ } catch {
56
+ if (!cancelled) setPermissionState('unknown');
57
+ }
58
+ }
59
+
60
+ checkPermission();
61
+
62
+ return () => {
63
+ cancelled = true;
64
+ };
65
+ }, [enabled]);
66
+
67
+ return { permissionState };
68
+ }
69
+
70
+ export default useFaceCameraPermission;
@@ -0,0 +1,106 @@
1
+
2
+
3
+ import * as React from 'react';
4
+
5
+ // We keep a module-level singleton so multiple FaceRecognition instances
6
+ // share one heavy MediaPipe model + wasm runtime.
7
+ let faceLandmarkerPromise: Promise<any | null> | null = null;
8
+ let faceLandmarkerSingleton: any | null = null;
9
+
10
+ // Note: The wasm + model URLs are pinned to specific versions for stability.
11
+ // They can be self-hosted later if desired.
12
+ async function getFaceLandmarker(): Promise<any | null> {
13
+ if (faceLandmarkerSingleton) return faceLandmarkerSingleton;
14
+ if (faceLandmarkerPromise) return faceLandmarkerPromise;
15
+
16
+ faceLandmarkerPromise = (async () => {
17
+ try {
18
+ const vision = await import('@mediapipe/tasks-vision');
19
+ const { FaceLandmarker, FilesetResolver } = vision as any;
20
+
21
+ const wasmBasePath = 'https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.14/wasm';
22
+ const filesetResolver = await FilesetResolver.forVisionTasks(wasmBasePath);
23
+
24
+ const modelPath =
25
+ 'https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task';
26
+
27
+ const faceLandmarker = await FaceLandmarker.createFromOptions(filesetResolver, {
28
+ baseOptions: {
29
+ modelAssetPath: modelPath,
30
+ },
31
+ runningMode: 'VIDEO',
32
+ numFaces: 1,
33
+ });
34
+
35
+ faceLandmarkerSingleton = faceLandmarker;
36
+ return faceLandmarker;
37
+ } catch {
38
+ return null;
39
+ }
40
+ })();
41
+
42
+ return faceLandmarkerPromise;
43
+ }
44
+
45
+ export type UseFaceLandmarkerOptions = {
46
+ /** Whether the consumer wants the landmarker available. */
47
+ enabled: boolean;
48
+ };
49
+
50
+ export type UseFaceLandmarkerResult = {
51
+ faceLandmarker: any | null;
52
+ faceLandmarkerLoading: boolean;
53
+ faceLandmarkerError: boolean;
54
+ };
55
+
56
+ /**
57
+ * useFaceLandmarker
58
+ *
59
+ * Loads MediaPipe's FaceLandmarker lazily and exposes loading/error state.
60
+ * Uses a module-level singleton so we only pay model+wasm cost once.
61
+ */
62
+ export function useFaceLandmarker(options: UseFaceLandmarkerOptions): UseFaceLandmarkerResult {
63
+ const { enabled } = options;
64
+
65
+ const [faceLandmarker, setFaceLandmarker] = React.useState<any | null>(null);
66
+ const [faceLandmarkerError, setFaceLandmarkerError] = React.useState<boolean>(false);
67
+ const [faceLandmarkerLoading, setFaceLandmarkerLoading] = React.useState<boolean>(false);
68
+
69
+ React.useEffect(() => {
70
+ if (!enabled) {
71
+ // We intentionally do not clear the module singleton; we only detach local state.
72
+ setFaceLandmarker(null);
73
+ setFaceLandmarkerLoading(false);
74
+ setFaceLandmarkerError(false);
75
+ return;
76
+ }
77
+
78
+ let cancelled = false;
79
+ setFaceLandmarkerLoading(true);
80
+ setFaceLandmarkerError(false);
81
+
82
+ getFaceLandmarker().then((fl) => {
83
+ if (cancelled) return;
84
+ if (fl) {
85
+ setFaceLandmarker(fl);
86
+ setFaceLandmarkerLoading(false);
87
+ } else {
88
+ setFaceLandmarker(null);
89
+ setFaceLandmarkerLoading(false);
90
+ setFaceLandmarkerError(true);
91
+ }
92
+ });
93
+
94
+ return () => {
95
+ cancelled = true;
96
+ };
97
+ }, [enabled]);
98
+
99
+ return {
100
+ faceLandmarker,
101
+ faceLandmarkerLoading,
102
+ faceLandmarkerError,
103
+ };
104
+ }
105
+
106
+ export default useFaceLandmarker;
@@ -0,0 +1,489 @@
1
+ import * as React from 'react';
2
+
3
+ export type FacePoint = { x: number; y: number };
4
+
5
+ export type UseFaceOverlayArgs = {
6
+ /** Whether the overlay loop should run. Typically: open && showLandmarks */
7
+ enabled: boolean;
8
+ /** Ref to the overlay canvas */
9
+ canvasRef: React.RefObject<HTMLCanvasElement | null>;
10
+ /** Getter for the underlying video element (from react-webcam) */
11
+ getVideoEl: () => HTMLVideoElement | undefined;
12
+
13
+ /** MediaPipe FaceLandmarker instance (or null). */
14
+ faceLandmarker: any | null;
15
+ /** Whether landmarker is currently loading. */
16
+ faceLandmarkerLoading?: boolean;
17
+ /** Whether landmarker failed to load. */
18
+ faceLandmarkerError?: boolean;
19
+
20
+ /** UI variant affects fit mode. inline => cover, modal => contain */
21
+ variant?: 'modal' | 'inline';
22
+ /** Mirror preview + overlay mapping. Default true */
23
+ mirrorPreview?: boolean;
24
+
25
+ /** Draw connection strokes between mesh points. Default: true when real mesh is present */
26
+ showMeshConnections?: boolean;
27
+ /** Draw density for mesh points. 1 = full 468 points, 2 = every other, etc. Default 1 */
28
+ meshStep?: number;
29
+
30
+ /** Detection throttle in ms. Lower = more responsive. Default 80. */
31
+ detectThrottleMs?: number;
32
+ /** How many consecutive misses before declaring no-face. Default 6 (lenient defaults bump this). */
33
+ noFaceMissesToClear?: number;
34
+ /** Grace window (ms) to keep last points after last seen face. Default 450 (lenient defaults bump this). */
35
+ noFaceGraceMs?: number;
36
+ /** Minimum time (ms) to hold a detected face before clearing. Helps avoid badge flicker. */
37
+ minFaceHoldMs?: number;
38
+
39
+ /** Optional: called whenever face presence changes */
40
+ onHasFaceChange?: (hasFace: boolean) => void;
41
+ /** Optional: called with latest landmark points (normalized 0..1, video space). null when none */
42
+ onPoints?: (points: FacePoint[] | null) => void;
43
+ /** Optional: called with latest blendshapes categories (if available). null when none */
44
+ onBlendshapes?: (
45
+ blendshapes: Array<{ categoryName: string; score: number }> | null
46
+ ) => void;
47
+ /** Optional: called with an anchor point suitable for HUD placement (normalized) */
48
+ onHudAnchor?: (anchor: FacePoint | null) => void;
49
+ };
50
+
51
+ export type UseFaceOverlayResult = {
52
+ hasFace: boolean;
53
+ /** Latest real points from MediaPipe if available; otherwise null */
54
+ lastPoints: FacePoint[] | null;
55
+ /** Latest blendshapes if available */
56
+ lastBlendshapes: Array<{ categoryName: string; score: number }> | null;
57
+ /** Latest HUD anchor (normalized) */
58
+ hudAnchor: FacePoint | null;
59
+ };
60
+
61
+ // Lightweight subset of MediaPipe FaceMesh connections (contours)
62
+ const MESH_CONNECTIONS: Array<[number, number]> = [
63
+ // face oval
64
+ [10, 338],
65
+ [338, 297],
66
+ [297, 332],
67
+ [332, 284],
68
+ [284, 251],
69
+ [251, 389],
70
+ [389, 356],
71
+ [356, 454],
72
+ [454, 323],
73
+ [323, 361],
74
+ [361, 288],
75
+ [288, 397],
76
+ [397, 365],
77
+ [365, 379],
78
+ [379, 378],
79
+ [378, 400],
80
+ [400, 377],
81
+ [377, 152],
82
+ [152, 148],
83
+ [148, 176],
84
+ [176, 149],
85
+ [149, 150],
86
+ [150, 136],
87
+ [136, 172],
88
+ [172, 58],
89
+ [58, 132],
90
+ [132, 93],
91
+ [93, 234],
92
+ [234, 127],
93
+ [127, 162],
94
+ [162, 21],
95
+ [21, 54],
96
+ [54, 103],
97
+ [103, 67],
98
+ [67, 109],
99
+ [109, 10],
100
+ // lips outer (approx)
101
+ [61, 146],
102
+ [146, 91],
103
+ [91, 181],
104
+ [181, 84],
105
+ [84, 17],
106
+ [17, 314],
107
+ [314, 405],
108
+ [405, 321],
109
+ [321, 375],
110
+ [375, 291],
111
+ [291, 61],
112
+ // nose ridge-ish
113
+ [1, 2],
114
+ [2, 98],
115
+ [1, 5],
116
+ [5, 4],
117
+ ];
118
+
119
+ function detectPlaceholderLandmarksFromVideo(video: HTMLVideoElement): { points: FacePoint[] } | null {
120
+ if (!video.videoWidth || !video.videoHeight) return null;
121
+ // Simple normalized points roughly for eyes, nose, mouth
122
+ const points: FacePoint[] = [
123
+ { x: 0.35, y: 0.4 },
124
+ { x: 0.65, y: 0.4 },
125
+ { x: 0.5, y: 0.5 },
126
+ { x: 0.4, y: 0.6 },
127
+ { x: 0.6, y: 0.6 },
128
+ { x: 0.3, y: 0.5 },
129
+ { x: 0.7, y: 0.5 },
130
+ { x: 0.5, y: 0.3 },
131
+ { x: 0.45, y: 0.45 },
132
+ { x: 0.55, y: 0.45 },
133
+ { x: 0.5, y: 0.7 },
134
+ ];
135
+ return { points };
136
+ }
137
+
138
+ /**
139
+ * useFaceOverlay
140
+ *
141
+ * Owns the requestAnimationFrame loop that:
142
+ * - keeps canvas resolution in sync
143
+ * - runs MediaPipe detectForVideo (throttled)
144
+ * - draws mesh points + optional contour connections
145
+ * - publishes latest points/blendshapes/hud anchor
146
+ */
147
+ export function useFaceOverlay(args: UseFaceOverlayArgs): UseFaceOverlayResult {
148
+ const {
149
+ enabled,
150
+ canvasRef,
151
+ getVideoEl,
152
+ faceLandmarker,
153
+ faceLandmarkerLoading = false,
154
+ faceLandmarkerError = false,
155
+ variant = 'modal',
156
+ mirrorPreview = true,
157
+ showMeshConnections,
158
+ meshStep = 1,
159
+ detectThrottleMs = 80,
160
+ // Smoother defaults: keep face “locked” longer to avoid flicker on brief misses.
161
+ noFaceMissesToClear = 24,
162
+ noFaceGraceMs = 1500,
163
+ minFaceHoldMs = 1200,
164
+ onHasFaceChange,
165
+ onPoints,
166
+ onBlendshapes,
167
+ onHudAnchor,
168
+ } = args;
169
+
170
+ const rafRef = React.useRef<number | null>(null);
171
+ const lastDetectTimeRef = React.useRef<number>(0);
172
+ const lastFaceSeenAtRef = React.useRef<number>(0);
173
+ const missCountRef = React.useRef<number>(0);
174
+ const lastLogAtRef = React.useRef<number>(0);
175
+ const lastFaceMarkedAtRef = React.useRef<number>(0);
176
+
177
+ const lastRealPointsRef = React.useRef<FacePoint[] | null>(null);
178
+ const lastBlendshapesRef = React.useRef<Array<{ categoryName: string; score: number }> | null>(
179
+ null
180
+ );
181
+ const lastHudAnchorRef = React.useRef<FacePoint | null>(null);
182
+
183
+ const [hasFace, setHasFace] = React.useState<boolean>(false);
184
+
185
+ // Keep callbacks stable without re-wiring the RAF loop every render.
186
+ const callbacksRef = React.useRef({ onHasFaceChange, onPoints, onBlendshapes, onHudAnchor });
187
+ React.useEffect(() => {
188
+ callbacksRef.current = { onHasFaceChange, onPoints, onBlendshapes, onHudAnchor };
189
+ }, [onHasFaceChange, onPoints, onBlendshapes, onHudAnchor]);
190
+
191
+ const setHasFaceSafe = React.useCallback(
192
+ (next: boolean, force?: boolean) => {
193
+ setHasFace((prev) => {
194
+ // Min-hold: if we already have a face, don't drop it immediately unless forced.
195
+ if (!next && prev && !force) {
196
+ const now = performance.now();
197
+ const heldFor = now - lastFaceMarkedAtRef.current;
198
+ if (heldFor < Number(minFaceHoldMs ?? 0)) {
199
+ return prev;
200
+ }
201
+ }
202
+
203
+ if (prev !== next) callbacksRef.current.onHasFaceChange?.(next);
204
+ if (next) lastFaceMarkedAtRef.current = performance.now();
205
+ return next;
206
+ });
207
+ },
208
+ [minFaceHoldMs]
209
+ );
210
+
211
+ React.useEffect(() => {
212
+ if (!enabled) {
213
+ if (rafRef.current !== null) {
214
+ cancelAnimationFrame(rafRef.current);
215
+ rafRef.current = null;
216
+ }
217
+ setHasFaceSafe(false, true);
218
+ lastFaceSeenAtRef.current = 0;
219
+ missCountRef.current = 0;
220
+ lastLogAtRef.current = 0;
221
+ lastRealPointsRef.current = null;
222
+ lastBlendshapesRef.current = null;
223
+ lastHudAnchorRef.current = null;
224
+ callbacksRef.current.onPoints?.(null);
225
+ callbacksRef.current.onBlendshapes?.(null);
226
+ callbacksRef.current.onHudAnchor?.(null);
227
+ return;
228
+ }
229
+
230
+ const canvasEl = canvasRef.current;
231
+ if (!canvasEl) return;
232
+
233
+ let cancelled = false;
234
+
235
+ async function draw() {
236
+ if (cancelled) return;
237
+
238
+ const canvasNow = canvasRef.current;
239
+ if (!canvasNow) return;
240
+
241
+ const videoNow = getVideoEl();
242
+
243
+ // Sync canvas backing store size with CSS size for sharpness
244
+ const rect = canvasNow.getBoundingClientRect();
245
+ if (rect.width && rect.height && (canvasNow.width !== rect.width || canvasNow.height !== rect.height)) {
246
+ canvasNow.width = rect.width;
247
+ canvasNow.height = rect.height;
248
+ }
249
+
250
+ const ctx = canvasNow.getContext('2d');
251
+ if (!ctx) {
252
+ rafRef.current = requestAnimationFrame(draw);
253
+ return;
254
+ }
255
+
256
+ ctx.clearRect(0, 0, canvasNow.width, canvasNow.height);
257
+
258
+ const vw = videoNow?.videoWidth ?? 0;
259
+ const vh = videoNow?.videoHeight ?? 0;
260
+ const readyState = videoNow?.readyState ?? 0;
261
+ const videoIsReady = !!videoNow && vw > 0 && vh > 0 && readyState >= 2;
262
+
263
+ if (!videoIsReady) {
264
+ rafRef.current = requestAnimationFrame(draw);
265
+ return;
266
+ }
267
+
268
+ if (!videoNow || faceLandmarkerLoading) {
269
+ rafRef.current = requestAnimationFrame(draw);
270
+ return;
271
+ }
272
+
273
+ // --- Compute video-to-canvas mapping (cover/contain) ---
274
+ const cw = canvasNow.width;
275
+ const ch = canvasNow.height;
276
+ const fitMode = variant === 'inline' ? 'cover' : 'contain';
277
+ const scale = fitMode === 'cover' ? Math.max(cw / vw, ch / vh) : Math.min(cw / vw, ch / vh);
278
+ const drawW = vw * scale;
279
+ const drawH = vh * scale;
280
+ const offsetX = (cw - drawW) / 2;
281
+ const offsetY = (ch - drawH) / 2;
282
+
283
+ const isMirrored = mirrorPreview;
284
+
285
+ // --- Detection (throttled) ---
286
+ const now = performance.now();
287
+ const elapsed = now - lastDetectTimeRef.current;
288
+ const throttleMs = Math.max(16, Number(detectThrottleMs ?? 80));
289
+
290
+ if (!faceLandmarkerError && faceLandmarker && elapsed > throttleMs) {
291
+ lastDetectTimeRef.current = now;
292
+ try {
293
+ const mpResult = faceLandmarker.detectForVideo(videoNow, now);
294
+ const has = !!(mpResult && mpResult.faceLandmarks && mpResult.faceLandmarks.length > 0);
295
+
296
+ if (has) {
297
+ missCountRef.current = 0;
298
+ lastFaceSeenAtRef.current = now;
299
+ lastFaceMarkedAtRef.current = now;
300
+
301
+ const rawPoints = mpResult.faceLandmarks[0];
302
+ const points: FacePoint[] = rawPoints.map((p: any) => ({ x: p.x, y: p.y }));
303
+ lastRealPointsRef.current = points;
304
+
305
+ const forehead = points[10] || points[9] || points[8] || { x: 0.5, y: 0.12 };
306
+ lastHudAnchorRef.current = { x: forehead.x, y: forehead.y };
307
+
308
+ const bs = (mpResult as any)?.faceBlendshapes?.[0]?.categories;
309
+ if (Array.isArray(bs) && bs.length) {
310
+ lastBlendshapesRef.current = bs.map((c: any) => ({
311
+ categoryName: String(c.categoryName ?? ''),
312
+ score: Number(c.score ?? 0),
313
+ }));
314
+ } else {
315
+ lastBlendshapesRef.current = null;
316
+ }
317
+
318
+ setHasFaceSafe(true);
319
+ callbacksRef.current.onPoints?.(points);
320
+ callbacksRef.current.onBlendshapes?.(lastBlendshapesRef.current);
321
+ callbacksRef.current.onHudAnchor?.(lastHudAnchorRef.current);
322
+ } else {
323
+ // Hysteresis: don't drop face immediately on a single miss.
324
+ missCountRef.current += 1;
325
+
326
+ const lastSeen = lastFaceSeenAtRef.current || 0;
327
+ const withinGrace = lastSeen > 0 && (now - lastSeen) < Number(noFaceGraceMs ?? 450);
328
+ const missesNeeded = Math.max(1, Number(noFaceMissesToClear ?? 6));
329
+
330
+ if (!withinGrace && missCountRef.current >= missesNeeded) {
331
+ setHasFaceSafe(false);
332
+ lastRealPointsRef.current = null;
333
+ lastBlendshapesRef.current = null;
334
+ lastHudAnchorRef.current = null;
335
+ callbacksRef.current.onPoints?.(null);
336
+ callbacksRef.current.onBlendshapes?.(null);
337
+ callbacksRef.current.onHudAnchor?.(null);
338
+ }
339
+ }
340
+ } catch (err) {
341
+ // If detect fails intermittently, keep last points for a grace window.
342
+ missCountRef.current += 1;
343
+ const lastSeen = lastFaceSeenAtRef.current || 0;
344
+ const withinGrace = lastSeen > 0 && (now - lastSeen) < Number(noFaceGraceMs ?? 450);
345
+ const missesNeeded = Math.max(1, Number(noFaceMissesToClear ?? 6));
346
+
347
+ // Lightweight debug log (at most 1/sec)
348
+ if (now - lastLogAtRef.current > 1000) {
349
+ lastLogAtRef.current = now;
350
+ // eslint-disable-next-line no-console
351
+ console.warn('[useFaceOverlay] detectForVideo failed:', (err as any)?.message || err);
352
+ }
353
+
354
+ if (!withinGrace && missCountRef.current >= missesNeeded) {
355
+ setHasFaceSafe(false);
356
+ lastRealPointsRef.current = null;
357
+ lastBlendshapesRef.current = null;
358
+ lastHudAnchorRef.current = null;
359
+ callbacksRef.current.onPoints?.(null);
360
+ callbacksRef.current.onBlendshapes?.(null);
361
+ callbacksRef.current.onHudAnchor?.(null);
362
+ }
363
+ }
364
+ }
365
+
366
+ // --- Choose points to draw ---
367
+ let pointsToDraw: FacePoint[] | null = null;
368
+ if (faceLandmarkerError || !faceLandmarker) {
369
+ pointsToDraw = detectPlaceholderLandmarksFromVideo(videoNow)?.points ?? null;
370
+ } else {
371
+ pointsToDraw = lastRealPointsRef.current;
372
+ }
373
+
374
+ if (pointsToDraw) {
375
+ ctx.save();
376
+
377
+ // Read theme-like CSS vars if present
378
+ const styles = getComputedStyle(canvasNow);
379
+ const primary =
380
+ styles.getPropertyValue('--gui-primary')?.trim() ||
381
+ styles.getPropertyValue('--color-primary')?.trim() ||
382
+ 'rgba(116, 202, 255, 1)';
383
+ const secondary = styles.getPropertyValue('--gui-secondary')?.trim() || primary;
384
+
385
+ const grad = ctx.createLinearGradient(0, 0, canvasNow.width, 0);
386
+ grad.addColorStop(0, primary);
387
+ grad.addColorStop(1, secondary);
388
+
389
+ ctx.globalAlpha = 0.95;
390
+ ctx.strokeStyle = grad;
391
+ ctx.fillStyle = 'transparent';
392
+ ctx.lineWidth = 1.75;
393
+ ctx.shadowBlur = 10;
394
+ ctx.shadowColor = primary;
395
+
396
+ const mapPoint = (pt: FacePoint) => {
397
+ let vx = pt.x * vw;
398
+ const vy = pt.y * vh;
399
+ if (isMirrored) vx = (1 - pt.x) * vw;
400
+ return {
401
+ px: offsetX + vx * scale,
402
+ py: offsetY + vy * scale,
403
+ };
404
+ };
405
+
406
+ const hasRealMesh = pointsToDraw.length > 200;
407
+ const connectionsEnabled = showMeshConnections !== undefined ? showMeshConnections : hasRealMesh;
408
+
409
+ if (hasRealMesh && connectionsEnabled) {
410
+ ctx.save();
411
+ ctx.globalAlpha = 0.35;
412
+ ctx.shadowBlur = 0;
413
+ ctx.lineWidth = 1.25;
414
+
415
+ ctx.beginPath();
416
+ for (const [a, b] of MESH_CONNECTIONS) {
417
+ const pa = pointsToDraw[a];
418
+ const pb = pointsToDraw[b];
419
+ if (!pa || !pb) continue;
420
+ const A = mapPoint(pa);
421
+ const B = mapPoint(pb);
422
+ ctx.moveTo(A.px, A.py);
423
+ ctx.lineTo(B.px, B.py);
424
+ }
425
+ ctx.stroke();
426
+ ctx.restore();
427
+ }
428
+
429
+ const step = hasRealMesh ? Math.max(1, meshStep || 1) : 1;
430
+ const r = hasRealMesh ? 2.25 : 4;
431
+
432
+ for (let i = 0; i < pointsToDraw.length; i += step) {
433
+ const { px, py } = mapPoint(pointsToDraw[i]);
434
+ ctx.beginPath();
435
+ ctx.arc(px, py, r, 0, 2 * Math.PI);
436
+ ctx.stroke();
437
+ }
438
+
439
+ ctx.restore();
440
+ }
441
+
442
+ rafRef.current = requestAnimationFrame(draw);
443
+ }
444
+
445
+ rafRef.current = requestAnimationFrame(draw);
446
+
447
+ return () => {
448
+ cancelled = true;
449
+ if (rafRef.current !== null) {
450
+ cancelAnimationFrame(rafRef.current);
451
+ rafRef.current = null;
452
+ }
453
+ setHasFaceSafe(false);
454
+ lastFaceSeenAtRef.current = 0;
455
+ missCountRef.current = 0;
456
+ lastLogAtRef.current = 0;
457
+ lastRealPointsRef.current = null;
458
+ lastBlendshapesRef.current = null;
459
+ lastHudAnchorRef.current = null;
460
+ callbacksRef.current.onPoints?.(null);
461
+ callbacksRef.current.onBlendshapes?.(null);
462
+ callbacksRef.current.onHudAnchor?.(null);
463
+ };
464
+ }, [
465
+ enabled,
466
+ canvasRef,
467
+ getVideoEl,
468
+ faceLandmarker,
469
+ faceLandmarkerLoading,
470
+ faceLandmarkerError,
471
+ variant,
472
+ mirrorPreview,
473
+ showMeshConnections,
474
+ meshStep,
475
+ detectThrottleMs,
476
+ noFaceMissesToClear,
477
+ noFaceGraceMs,
478
+ setHasFaceSafe,
479
+ ]);
480
+
481
+ return {
482
+ hasFace,
483
+ lastPoints: lastRealPointsRef.current,
484
+ lastBlendshapes: lastBlendshapesRef.current,
485
+ hudAnchor: lastHudAnchorRef.current,
486
+ };
487
+ }
488
+
489
+ export default useFaceOverlay;
@@ -0,0 +1,32 @@
1
+ import * as React from 'react';
2
+ import type {
3
+ FaceTemplate,
4
+ Blendshape,
5
+ Point2D,
6
+ UseFaceTemplateBurstOptions,
7
+ } from './useFaceTemplateBurst';
8
+ import { useFaceTemplateBurst } from './useFaceTemplateBurst';
9
+
10
+ // Re-export types (optional, but handy for external imports)
11
+ export type { FaceTemplate, Blendshape, Point2D };
12
+
13
+ // Backwards-friendly alias: keep old hook name, same options.
14
+ export type UseFaceTemplateOptions = UseFaceTemplateBurstOptions;
15
+
16
+ export type UseFaceTemplateResult = {
17
+ stableTemplate: FaceTemplate | null;
18
+ reset: () => void;
19
+ };
20
+
21
+ /**
22
+ * useFaceTemplate
23
+ *
24
+ * Backwards-friendly wrapper. Internally uses a burst sampler that emits
25
+ * a stable template every N samples.
26
+ */
27
+ export function useFaceTemplate(options: UseFaceTemplateOptions): UseFaceTemplateResult {
28
+ const { stableTemplate, reset } = useFaceTemplateBurst(options);
29
+ return { stableTemplate, reset };
30
+ }
31
+
32
+ export default useFaceTemplate;