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.
- package/package.json +3 -2
- package/src/GUI.tsx +46 -0
- package/src/QRouter/QRegistry.tsx +53 -0
- package/src/QRouter/QRouter.stories.tsx +31 -0
- package/src/QRouter/QRouter.tsx +57 -0
- package/src/gui/Theme/GuiProvider.tsx +111 -0
- package/src/gui/Theme/Icon/Icon.resolver.tsx +29 -0
- package/src/gui/Theme/Icon/Icon.tsx +43 -0
- package/src/gui/Theme/Layout/Content/Content.resolver.tsx +0 -0
- package/src/gui/Theme/Layout/Content/Content.stories.tsx +88 -0
- package/src/gui/Theme/Layout/Content/Content.tsx +53 -0
- package/src/gui/Theme/Layout/Content/Content.types.tsx +40 -0
- package/src/gui/Theme/Layout/Footer/Footer.resolver.tsx +45 -0
- package/src/gui/Theme/Layout/Footer/Footer.stories.tsx +205 -0
- package/src/gui/Theme/Layout/Footer/Footer.tsx +337 -0
- package/src/gui/Theme/Layout/Footer/Footer.types.ts +40 -0
- package/src/gui/Theme/Layout/Layout/Layout.resolver.tsx +37 -0
- package/src/gui/Theme/Layout/Layout/Layout.stories.tsx +289 -0
- package/src/gui/Theme/Layout/Layout/Layout.tsx +117 -0
- package/src/gui/Theme/Layout/Layout/Layout.types.ts +57 -0
- package/src/gui/Theme/Layout/Layout/useLayoutBreakpoints.ts +9 -0
- package/src/gui/Theme/Layout/Namespace/Namespace.stories.tsx +105 -0
- package/src/gui/Theme/Layout/Namespace/Namespace.tsx +26 -0
- package/src/gui/Theme/Layout/Sidebars/LeftSidebar/LeftSidebar.resolver.tsx +87 -0
- package/src/gui/Theme/Layout/Sidebars/LeftSidebar/LeftSidebar.stories.tsx +199 -0
- package/src/gui/Theme/Layout/Sidebars/LeftSidebar/LeftSidebar.tsx +311 -0
- package/src/gui/Theme/Layout/Sidebars/LeftSidebar/LeftSidebar.types.ts +41 -0
- package/src/gui/Theme/Layout/Sidebars/LeftSidebar/SidebarToggleButton.tsx +53 -0
- package/src/gui/Theme/Layout/Sidebars/LeftSidebar/components/LeftSidebarAction/LeftSidebarAction.resolver.tsx +19 -0
- package/src/gui/Theme/Layout/Sidebars/LeftSidebar/components/LeftSidebarAction/LeftSidebarAction.tsx +107 -0
- package/src/gui/Theme/Layout/Sidebars/LeftSidebar/components/LeftSidebarLink/LeftSidebarLink.resolver.tsx +0 -0
- package/src/gui/Theme/Layout/Sidebars/LeftSidebar/components/LeftSidebarLink/LeftSidebarLink.tsx +134 -0
- package/src/gui/Theme/Layout/Sidebars/LeftSidebar/components/LeftSidebarLink/LeftSidebarLink.types.ts +15 -0
- package/src/gui/Theme/Layout/Sidebars/LeftSidebar/components/LeftSidebarMenu/LeftSidebarMenu.tsx +142 -0
- package/src/gui/Theme/Layout/Sidebars/LeftSidebar/components/LeftSidebarToggleButton/LeftSidebarToggleButton.tsx +23 -0
- package/src/gui/Theme/Layout/Sidebars/RightSidebar/RightSidebar.resolver.tsx +35 -0
- package/src/gui/Theme/Layout/Sidebars/RightSidebar/RightSidebar.stories.tsx +239 -0
- package/src/gui/Theme/Layout/Sidebars/RightSidebar/RightSidebar.tsx +319 -0
- package/src/gui/Theme/Layout/Sidebars/RightSidebar/RightSidebar.types.ts +17 -0
- package/src/gui/Theme/Layout/Sidebars/RightSidebar/components/RightSidebarAction/RightSidebarAction.tsx +102 -0
- package/src/gui/Theme/Layout/Sidebars/RightSidebar/components/RightSidebarLink/RightSidebarLink.tsx +132 -0
- package/src/gui/Theme/Layout/Sidebars/RightSidebar/components/RightSidebarMenu/RightSidebarMenu.tsx +140 -0
- package/src/gui/Theme/Layout/Sidebars/RightSidebar/components/RightSidebarToggleButton/RightSidebarToggleButton.tsx +22 -0
- package/src/gui/Theme/Layout/StickyOptions/StickyOptionsTop.stories.tsx +469 -0
- package/src/gui/Theme/Layout/StickyOptions/StickyOptionsTop.tsx +489 -0
- package/src/gui/Theme/Layout/TopBar/TopBar.resolver.tsx +86 -0
- package/src/gui/Theme/Layout/TopBar/TopBar.stories.tsx +350 -0
- package/src/gui/Theme/Layout/TopBar/TopBar.tsx +292 -0
- package/src/gui/Theme/Layout/TopBar/TopBar.types.ts +39 -0
- package/src/gui/Theme/Layout/TopBar/components/TopBarAction/TopBarAction.stories.tsx +83 -0
- package/src/gui/Theme/Layout/TopBar/components/TopBarAction/TopBarAction.tsx +18 -0
- package/src/gui/Theme/Layout/TopBar/components/TopBarAction/TopBarAction.types.ts +4 -0
- package/src/gui/Theme/Layout/TopBar/components/TopBarLink/TopBarLink.stories.tsx +189 -0
- package/src/gui/Theme/Layout/TopBar/components/TopBarLink/TopBarLink.tsx +30 -0
- package/src/gui/Theme/Layout/TopBar/components/TopBarLink/TopBarLink.types.ts +9 -0
- package/src/gui/Theme/Layout/TopBar/components/TopBarMenu/TopBarMenu.resolver.tsx +14 -0
- package/src/gui/Theme/Layout/TopBar/components/TopBarMenu/TopBarMenu.stories.tsx +56 -0
- package/src/gui/Theme/Layout/TopBar/components/TopBarMenu/TopBarMenu.tsx +123 -0
- package/src/gui/Theme/Layout/TopBar/components/TopBarMenu/TopBarMenu.types.ts +44 -0
- package/src/gui/Theme/catalog/CherryByte/CherryByte.png +0 -0
- package/src/gui/Theme/catalog/CherryByte/dark.tokens.ts +47 -0
- package/src/gui/Theme/catalog/CherryByte/light.tokens.ts +47 -0
- package/src/gui/Theme/catalog/CherryByte/manifest.ts +24 -0
- package/src/gui/Theme/catalog/GhostShell/dark.tokens.ts +43 -0
- package/src/gui/Theme/catalog/GhostShell/ghost.png +0 -0
- package/src/gui/Theme/catalog/GhostShell/light.tokens.ts +39 -0
- package/src/gui/Theme/catalog/GhostShell/manifest.ts +24 -0
- package/src/gui/Theme/catalog/LunaHex/LunaHex.png +0 -0
- package/src/gui/Theme/catalog/LunaHex/dark.tokens.ts +34 -0
- package/src/gui/Theme/catalog/LunaHex/light.tokens.ts +74 -0
- package/src/gui/Theme/catalog/LunaHex/manifest.ts +24 -0
- package/src/gui/Theme/catalog/MUI/MUI.png +0 -0
- package/src/gui/Theme/catalog/MUI/dark.tokens.ts +58 -0
- package/src/gui/Theme/catalog/MUI/light.tokens.ts +74 -0
- package/src/gui/Theme/catalog/MUI/manifest.ts +24 -0
- package/src/gui/Theme/catalog/PrinceOfDarkness/dark.tokens.ts +48 -0
- package/src/gui/Theme/catalog/PrinceOfDarkness/light.tokens.ts +47 -0
- package/src/gui/Theme/catalog/PrinceOfDarkness/manifest.ts +24 -0
- package/src/gui/Theme/catalog/PrinceOfDarkness/prince.png +0 -0
- package/src/gui/Theme/catalog/PrinceOfDarkness/princeOfDarkness.png +0 -0
- package/src/gui/Theme/catalog/Seafoam/dark.tokens.ts +49 -0
- package/src/gui/Theme/catalog/Seafoam/light.tokens.ts +47 -0
- package/src/gui/Theme/catalog/Seafoam/manifest.ts +24 -0
- package/src/gui/Theme/catalog/Seafoam/seaFoam.png +0 -0
- package/src/gui/Theme/catalog/neurons/dark.tokens.ts +58 -0
- package/src/gui/Theme/catalog/neurons/light.tokens.ts +74 -0
- package/src/gui/Theme/catalog/neurons/manifest.ts +24 -0
- package/src/gui/Theme/catalog/neurons/neurons.me.png +0 -0
- package/src/gui/Theme/fromTokens.ts +272 -0
- package/src/gui/Theme/gui.css +31 -0
- package/src/gui/Theme/index.ts +17 -0
- package/src/gui/Theme/styles/buildShadows.ts +83 -0
- package/src/gui/Theme/styles/theme.tokens.ts +108 -0
- package/src/gui/Theme/utils/catalog.ts +61 -0
- package/src/gui/Theme/utils/persistence.ts +66 -0
- package/src/gui/Theme/utils/themeUtils.ts +34 -0
- package/src/gui/components/atoms/AppBar/AppBar.resolver.tsx +46 -0
- package/src/gui/components/atoms/AppBar/AppBar.stories.tsx +251 -0
- package/src/gui/components/atoms/AppBar/AppBar.tsx +107 -0
- package/src/gui/components/atoms/AppBar/AppBar.types.ts +28 -0
- package/src/gui/components/atoms/Avatar/Avatar.resolver.tsx +61 -0
- package/src/gui/components/atoms/Avatar/Avatar.stories.tsx +36 -0
- package/src/gui/components/atoms/Avatar/Avatar.tsx +14 -0
- package/src/gui/components/atoms/Box/Box.resolver.tsx +171 -0
- package/src/gui/components/atoms/Box/Box.stories.tsx +263 -0
- package/src/gui/components/atoms/Box/Box.tsx +15 -0
- package/src/gui/components/atoms/Button/Button.resolver.tsx +103 -0
- package/src/gui/components/atoms/Button/Button.stories.tsx +219 -0
- package/src/gui/components/atoms/Button/Button.tsx +40 -0
- package/src/gui/components/atoms/Card/Card.resolver.tsx +63 -0
- package/src/gui/components/atoms/Card/Card.stories.tsx +54 -0
- package/src/gui/components/atoms/Card/Card.tsx +13 -0
- package/src/gui/components/atoms/CardActions/CardActions.resolver.tsx +59 -0
- package/src/gui/components/atoms/CardActions/CardActions.stories.tsx +32 -0
- package/src/gui/components/atoms/CardActions/CardActions.tsx +14 -0
- package/src/gui/components/atoms/CardContent/CardContent.resolver.tsx +60 -0
- package/src/gui/components/atoms/CardContent/CardContent.stories.tsx +34 -0
- package/src/gui/components/atoms/CardContent/CardContent.tsx +13 -0
- package/src/gui/components/atoms/CardHeader/CardHeader.resolver.tsx +68 -0
- package/src/gui/components/atoms/CardHeader/CardHeader.stories.tsx +40 -0
- package/src/gui/components/atoms/CardHeader/CardHeader.tsx +12 -0
- package/src/gui/components/atoms/Collapse/Collapse.resolver.tsx +85 -0
- package/src/gui/components/atoms/Collapse/Collapse.stories.tsx +130 -0
- package/src/gui/components/atoms/Collapse/Collapse.tsx +17 -0
- package/src/gui/components/atoms/Divider/Divider.resolver.tsx +95 -0
- package/src/gui/components/atoms/Divider/Divider.stories.tsx +108 -0
- package/src/gui/components/atoms/Divider/Divider.tsx +14 -0
- package/src/gui/components/atoms/Drawer/Drawer.resolver.tsx +116 -0
- package/src/gui/components/atoms/Drawer/Drawer.stories.tsx +223 -0
- package/src/gui/components/atoms/Drawer/Drawer.tsx +25 -0
- package/src/gui/components/atoms/Grid/Grid.resolver.tsx +33 -0
- package/src/gui/components/atoms/Grid/Grid.stories.tsx +136 -0
- package/src/gui/components/atoms/Grid/Grid.tsx +15 -0
- package/src/gui/components/atoms/Grid/Grid.types.ts +9 -0
- package/src/gui/components/atoms/IconButton/IconButton.resolver.tsx +137 -0
- package/src/gui/components/atoms/IconButton/IconButton.stories.tsx +134 -0
- package/src/gui/components/atoms/IconButton/IconButton.tsx +22 -0
- package/src/gui/components/atoms/Link/Link.resolver.tsx +74 -0
- package/src/gui/components/atoms/Link/Link.stories.tsx +157 -0
- package/src/gui/components/atoms/Link/Link.tsx +36 -0
- package/src/gui/components/atoms/List/List.resolver.tsx +94 -0
- package/src/gui/components/atoms/List/List.stories.tsx +137 -0
- package/src/gui/components/atoms/List/List.tsx +20 -0
- package/src/gui/components/atoms/ListItem/ListItem.resolver.tsx +88 -0
- package/src/gui/components/atoms/ListItem/ListItem.stories.tsx +151 -0
- package/src/gui/components/atoms/ListItem/ListItem.tsx +19 -0
- package/src/gui/components/atoms/ListItemButton/ListItemButton.resolver.tsx +214 -0
- package/src/gui/components/atoms/ListItemButton/ListItemButton.stories.tsx +155 -0
- package/src/gui/components/atoms/ListItemButton/ListItemButton.tsx +15 -0
- package/src/gui/components/atoms/ListItemIcon/ListItemIcon.resolver.tsx +102 -0
- package/src/gui/components/atoms/ListItemIcon/ListItemIcon.stories.tsx +132 -0
- package/src/gui/components/atoms/ListItemIcon/ListItemIcon.tsx +11 -0
- package/src/gui/components/atoms/ListItemText/ListItemText.resolver.tsx +112 -0
- package/src/gui/components/atoms/ListItemText/ListItemText.stories.tsx +156 -0
- package/src/gui/components/atoms/ListItemText/ListItemText.tsx +15 -0
- package/src/gui/components/atoms/Menu/Menu.resolver.tsx +112 -0
- package/src/gui/components/atoms/Menu/Menu.stories.tsx +162 -0
- package/src/gui/components/atoms/Menu/Menu.tsx +17 -0
- package/src/gui/components/atoms/MenuItem/MenuItem.resolver.tsx +183 -0
- package/src/gui/components/atoms/MenuItem/MenuItem.stories.tsx +134 -0
- package/src/gui/components/atoms/MenuItem/MenuItem.tsx +14 -0
- package/src/gui/components/atoms/Paper/Paper.resolver.tsx +98 -0
- package/src/gui/components/atoms/Paper/Paper.stories.tsx +184 -0
- package/src/gui/components/atoms/Paper/Paper.tsx +15 -0
- package/src/gui/components/atoms/Section/Section.resolver.tsx +10 -0
- package/src/gui/components/atoms/Section/Section.stories.tsx +189 -0
- package/src/gui/components/atoms/Section/Section.tsx +76 -0
- package/src/gui/components/atoms/Section/Section.types.tsx +24 -0
- package/src/gui/components/atoms/Stack/Stack.resolver.tsx +94 -0
- package/src/gui/components/atoms/Stack/Stack.stories.tsx +160 -0
- package/src/gui/components/atoms/Stack/Stack.tsx +15 -0
- package/src/gui/components/atoms/Surface/Surface.resolver.tsx +37 -0
- package/src/gui/components/atoms/Surface/Surface.tsx +49 -0
- package/src/gui/components/atoms/Surface/Surface.types.ts +20 -0
- package/src/gui/components/atoms/Switch/Switch.resolver.tsx +53 -0
- package/src/gui/components/atoms/Switch/Switch.stories.tsx +236 -0
- package/src/gui/components/atoms/Switch/Switch.tsx +22 -0
- package/src/gui/components/atoms/Table/Body/TableBody.tsx +7 -0
- package/src/gui/components/atoms/Table/Cell/TableCell.tsx +18 -0
- package/src/gui/components/atoms/Table/Head/TableHead.tsx +9 -0
- package/src/gui/components/atoms/Table/Row/TableRow.tsx +20 -0
- package/src/gui/components/atoms/Table/Table.resolver.tsx +77 -0
- package/src/gui/components/atoms/Table/Table.stories.tsx +173 -0
- package/src/gui/components/atoms/Table/Table.tsx +20 -0
- package/src/gui/components/atoms/TextField/TextField.stories.tsx +25 -0
- package/src/gui/components/atoms/TextField/TextField.tsx +15 -0
- package/src/gui/components/atoms/Toolbar/Toolbar.resolver.tsx +60 -0
- package/src/gui/components/atoms/Toolbar/Toolbar.stories.tsx +155 -0
- package/src/gui/components/atoms/Toolbar/Toolbar.tsx +16 -0
- package/src/gui/components/atoms/Tooltip/Tooltip.resolver.tsx +142 -0
- package/src/gui/components/atoms/Tooltip/Tooltip.stories.tsx +117 -0
- package/src/gui/components/atoms/Tooltip/Tooltip.tsx +70 -0
- package/src/gui/components/atoms/Typography/Typography.resolver.tsx +158 -0
- package/src/gui/components/atoms/Typography/Typography.stories.tsx +222 -0
- package/src/gui/components/atoms/Typography/Typography.tsx +27 -0
- package/src/gui/components/atoms/Window/Nodes/node.ts +0 -0
- package/src/gui/components/atoms/Window/code/block/node.tsx +0 -0
- package/src/gui/components/atoms/Window/code/hugging.face.api.ts +11 -0
- package/src/gui/components/atoms/Window/connectors/index.ts +19 -0
- package/src/gui/components/atoms/Window/window.stories.tsx +20 -0
- package/src/gui/components/atoms/Window/window.tsx +636 -0
- package/src/gui/components/atoms/atoms.tsx +151 -0
- package/src/gui/components/atoms/index.ts +2 -0
- package/src/gui/components/generics/Cards/Gridme.jsx +52 -0
- package/src/gui/components/generics/Cards/LilBox.jsx +65 -0
- package/src/gui/components/generics/Cards/ModuleCard.jsx +106 -0
- package/src/gui/components/generics/Chats/FullChatBot.jsx +223 -0
- package/src/gui/components/generics/Code/CodeBlock.jsx +33 -0
- package/src/gui/components/generics/EmojiCursor/EmojiCursor.stories.tsx +153 -0
- package/src/gui/components/generics/EmojiCursor/EmojiCursor.tsx +23 -0
- package/src/gui/components/generics/Feedback/Callout.jsx +92 -0
- package/src/gui/components/generics/Layout/GridX.jsx +29 -0
- package/src/gui/components/generics/Layout/Hero2.jsx +132 -0
- package/src/gui/components/generics/Layout/PageContainer.jsx +29 -0
- package/src/gui/components/generics/Layout/PageDivider.jsx +20 -0
- package/src/gui/components/generics/Layout/Section.jsx +43 -0
- package/src/gui/components/generics/Layout/SectionHeader.jsx +21 -0
- package/src/gui/components/generics/Media/Img.jsx +58 -0
- package/src/gui/components/generics/Media/VideoEmbed.jsx +51 -0
- package/src/gui/components/generics/Organization/TableOfContents.jsx +51 -0
- package/src/gui/components/generics/Organization/Tabs.jsx +45 -0
- package/src/gui/components/generics/Text/TextList.jsx +41 -0
- package/src/gui/components/generics/Text/TextParagraph.jsx +28 -0
- package/src/gui/components/generics/Text/TextQuote.jsx +23 -0
- package/src/gui/components/generics/Text/TextTitle.jsx +44 -0
- package/src/gui/components/molecules/Dialog/Dialog.stories.tsx +18 -0
- package/src/gui/components/molecules/Dialog/Dialog.tsx +5 -0
- package/src/gui/components/molecules/Hero/Hero.stories.tsx +140 -0
- package/src/gui/components/molecules/Hero/Hero.tsx +152 -0
- package/src/gui/components/molecules/Hero/Hero.types.tsx +18 -0
- package/src/gui/components/molecules/Modal/Modal.resolver.tsx +38 -0
- package/src/gui/components/molecules/Modal/Modal.stories.tsx +82 -0
- package/src/gui/components/molecules/Modal/Modal.tsx +110 -0
- package/src/gui/components/molecules/Modal/Modal.types.ts +29 -0
- package/src/gui/components/molecules/Page/Page.stories.tsx +135 -0
- package/src/gui/components/molecules/Page/Page.tsx +94 -0
- package/src/gui/components/molecules/Theme/ThemeModeToggle/ThemeModeToggle.resolver.tsx +58 -0
- package/src/gui/components/molecules/Theme/ThemeModeToggle/ThemeModeToggle.stories.tsx +133 -0
- package/src/gui/components/molecules/Theme/ThemeModeToggle/ThemeModeToggle.tsx +101 -0
- package/src/gui/components/molecules/Theme/ThemeModeToggle/ThemeModeToggle.types.ts +29 -0
- package/src/gui/components/molecules/Theme/ThemesCatalog/ThemesCatalog.resolver.tsx +15 -0
- package/src/gui/components/molecules/Theme/ThemesCatalog/ThemesCatalog.stories.tsx +88 -0
- package/src/gui/components/molecules/Theme/ThemesCatalog/ThemesCatalog.tsx +167 -0
- package/src/gui/components/molecules/Theme/ThemesCatalog/ThemesCatalog.types.ts +34 -0
- package/src/gui/components/molecules/molecules.ts +49 -0
- package/src/gui/components/organisms/Blockchain/Blocks/BlocksTable.tsx +119 -0
- package/src/gui/components/organisms/Blockchain/Usernames/Identities.stories.tsx +20 -0
- package/src/gui/components/organisms/Blockchain/Usernames/QR.tsx +566 -0
- package/src/gui/components/organisms/Blockchain/Usernames/Usernames.tsx +448 -0
- package/src/gui/components/organisms/Blockchain/Usernames/identities.tsx +710 -0
- package/src/gui/components/organisms/Blockchain/blockchain.stories.tsx +17 -0
- package/src/gui/components/organisms/Blockchain/blockchain.tsx +368 -0
- package/src/gui/components/organisms/Blockchain/scripts/connection.ts +82 -0
- package/src/gui/components/organisms/Blockchain/scripts/match_face.ts +143 -0
- package/src/gui/components/organisms/HighLighter/HighLighter.stories.tsx +168 -0
- package/src/gui/components/organisms/HighLighter/HighLighter.tsx +420 -0
- package/src/gui/components/organisms/HighLighter/HighLightsDrawer.tsx +197 -0
- package/src/gui/components/organisms/IdentityNoise/FaceRecognition/FaceRecognition.stories.tsx +312 -0
- package/src/gui/components/organisms/IdentityNoise/FaceRecognition/FaceRecognition.tsx +765 -0
- package/src/gui/components/organisms/IdentityNoise/FaceRecognition/modules/useFaceCameraPermission.ts +70 -0
- package/src/gui/components/organisms/IdentityNoise/FaceRecognition/modules/useFaceLandmarker.ts +106 -0
- package/src/gui/components/organisms/IdentityNoise/FaceRecognition/modules/useFaceOverlay.ts +489 -0
- package/src/gui/components/organisms/IdentityNoise/FaceRecognition/modules/useFaceTemplate.ts +32 -0
- package/src/gui/components/organisms/IdentityNoise/FaceRecognition/modules/useFaceTemplateBurst.ts +178 -0
- package/src/gui/components/organisms/IdentityNoise/FaceRecognition/modules/verifyTemplate.ts +136 -0
- package/src/gui/components/organisms/IdentityNoise/IdentityNoise.tsx +403 -0
- package/src/gui/components/organisms/IdentityNoise/IndentityNoise.stories.tsx +15 -0
- package/src/gui/components/organisms/IdentityNoise/Noise/Noise.stories.tsx +206 -0
- package/src/gui/components/organisms/IdentityNoise/Noise/Noise.tsx +394 -0
- package/src/gui/components/organisms/IdentityNoise/Triad/QR.tsx +566 -0
- package/src/gui/components/organisms/IdentityNoise/Triad/Tiad.stories.tsx +6 -0
- package/src/gui/components/organisms/IdentityNoise/Triad/Triad.tsx +917 -0
- package/src/gui/components/organisms/IdentityNoise/Triad/handleCleak.ts +0 -0
- package/src/gui/components/organisms/IdentityNoise/Triad/identity.ts +31 -0
- package/src/gui/components/organisms/IdentityNoise/Triad/me/fundamentals/vectors/vectors.tsx +252 -0
- package/src/gui/components/organisms/IdentityNoise/Triad/me/me.stories.tsx +314 -0
- package/src/gui/components/organisms/IdentityNoise/Triad/me/me.tsx +0 -0
- package/src/gui/components/organisms/organisms.ts +15 -0
- package/src/gui/contexts/InsetsContext.tsx +40 -0
- package/src/gui/contexts/LeftSidebarContext.tsx +20 -0
- package/src/gui/contexts/RightSidebarContext.tsx +25 -0
- package/src/gui/contexts/ThemeContext.ts +34 -0
- package/src/gui/contexts/index.ts +4 -0
- package/src/gui/hooks/index.ts +11 -0
- package/src/gui/hooks/resolveColorToken.ts +39 -0
- package/src/gui/hooks/useCodeGen.ts +12 -0
- package/src/gui/hooks/useGuiMediaQuery.ts +18 -0
- package/src/gui/hooks/useGuiTheme.ts +18 -0
- package/src/gui/hooks/useInsets.ts +26 -0
- package/src/gui/hooks/useIsMobile.ts +13 -0
- package/src/gui/hooks/useIsTouchDevice.ts +25 -0
- package/src/gui/hooks/useLeftSidebar.ts +10 -0
- package/src/gui/hooks/useRightSidebar.ts +12 -0
- package/src/gui/hooks/useViewportKey.ts +19 -0
- package/src/gui/hooks/useViewportProp.ts +17 -0
- package/src/gui/registry/GuiRegistry.ts +19 -0
- package/src/gui/registry/factory.ts +12 -0
- package/src/gui/registry/index.ts +3 -0
- package/src/gui/registry/types.ts +6 -0
- package/src/gui/utils/nodeID.ts +11 -0
- package/src/registry/GuiRegistry.ts +19 -0
- package/src/stories/01.Home.mdx +22 -0
- package/src/stories/02.Understanding.This.GUI.mdx +149 -0
- package/src/stories/Theme/Palette.stories.tsx +86 -0
- package/src/stories/Theme/ThemeViewer.stories.tsx +91 -0
- package/src/stories/Theme/Typography.stories.jsx +211 -0
- package/src/stories/assets/this.GUI.png +0 -0
- package/src/types/gui.d.ts +67 -0
- package/src/types/theme.d.ts +191 -0
- package/src/types/viewport.ts +132 -0
|
@@ -0,0 +1,566 @@
|
|
|
1
|
+
import React, { useId, useMemo } from "react";
|
|
2
|
+
import qrcodegen from "qrcode-generator";
|
|
3
|
+
export type QREmbedMode = "none" | "negative-space" | "positive-overlay";
|
|
4
|
+
export type QRProps = {
|
|
5
|
+
/** The string to encode in the QR (e.g. identityRoot / cleak) */
|
|
6
|
+
value: string;
|
|
7
|
+
/** Overall rendered size in px */
|
|
8
|
+
size?: number;
|
|
9
|
+
/** Background color (can use CSS variables, e.g. var(--qr-bg)) */
|
|
10
|
+
bg?: string;
|
|
11
|
+
/** Foreground color (can use CSS variables, e.g. var(--qr-fg)) */
|
|
12
|
+
fg?: string;
|
|
13
|
+
/** Rounded corner radius (px) for modules (0 = square) */
|
|
14
|
+
moduleRadius?: number;
|
|
15
|
+
/** Quiet zone in modules */
|
|
16
|
+
quietZone?: number;
|
|
17
|
+
/** Error correction level */
|
|
18
|
+
ecc?: "L" | "M" | "Q" | "H";
|
|
19
|
+
/** Optional ASCII art label to show above the QR (not inside the QR) */
|
|
20
|
+
asciiHeader?: string;
|
|
21
|
+
/** Optional small caption to show under the QR */
|
|
22
|
+
caption?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Embed ASCII “logo” by carving out negative space in the center.
|
|
25
|
+
* - `none`: standard QR
|
|
26
|
+
* - `negative-space`: remove modules in the center region (safe with ECC=H)
|
|
27
|
+
* - `positive-overlay`: clear the center region, then draw modules from the ASCII art on top
|
|
28
|
+
*/
|
|
29
|
+
embedMode?: QREmbedMode;
|
|
30
|
+
/**
|
|
31
|
+
* Size of the embedded region as a fraction of QR modules. Typical safe range: 0.18–0.28.
|
|
32
|
+
* Used only when embedMode !== 'none'.
|
|
33
|
+
*/
|
|
34
|
+
embedScale?: number;
|
|
35
|
+
/**
|
|
36
|
+
* The ASCII art to embed (center carve or overlay). Keep it compact.
|
|
37
|
+
* NOTE: for scan safety, we carve empty space in negative-space mode,
|
|
38
|
+
* and draw modules in positive-overlay mode.
|
|
39
|
+
*/
|
|
40
|
+
embedAscii?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Optional bitmap to embed instead of ASCII parsing.
|
|
43
|
+
* Provide rows of "0"/"1" (all rows same length). "1" = draw module.
|
|
44
|
+
*/
|
|
45
|
+
embedBitmap?: string[];
|
|
46
|
+
/** Additional className */
|
|
47
|
+
className?: string;
|
|
48
|
+
/** Inline style */
|
|
49
|
+
style?: React.CSSProperties;
|
|
50
|
+
/** Debug: render the parsed/trimmed ASCII bitmap above the QR */
|
|
51
|
+
showEmbeddedAsciiPreview?: boolean;
|
|
52
|
+
};
|
|
53
|
+
function parseStringBitmap(rows: string[]): boolean[][] {
|
|
54
|
+
const cleaned = (rows ?? []).map((r) => (r ?? "").trimEnd());
|
|
55
|
+
while (cleaned.length && cleaned[0].trim().length === 0) cleaned.shift();
|
|
56
|
+
while (cleaned.length && cleaned[cleaned.length - 1].trim().length === 0) cleaned.pop();
|
|
57
|
+
if (!cleaned.length) return [];
|
|
58
|
+
|
|
59
|
+
const w = Math.max(0, ...cleaned.map((r) => r.length));
|
|
60
|
+
return cleaned.map((r) => {
|
|
61
|
+
const line = r.padEnd(w, "0");
|
|
62
|
+
return [...line].map((ch) => ch === "1");
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
type ModuleMatrix = boolean[][];
|
|
67
|
+
|
|
68
|
+
function buildQRMatrix(value: string, ecc: "L" | "M" | "Q" | "H"): ModuleMatrix {
|
|
69
|
+
// qrcode-generator expects typeNumber 0 for auto
|
|
70
|
+
const qr = (qrcodegen as any)(0, ecc);
|
|
71
|
+
qr.addData(value);
|
|
72
|
+
qr.make();
|
|
73
|
+
const count: number = qr.getModuleCount();
|
|
74
|
+
const m: boolean[][] = [];
|
|
75
|
+
for (let y = 0; y < count; y++) {
|
|
76
|
+
const row: boolean[] = [];
|
|
77
|
+
for (let x = 0; x < count; x++) {
|
|
78
|
+
row.push(qr.isDark(y, x));
|
|
79
|
+
}
|
|
80
|
+
m.push(row);
|
|
81
|
+
}
|
|
82
|
+
return m;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function isInFinderOrTiming(m: ModuleMatrix, x: number, y: number): boolean {
|
|
86
|
+
const n = m.length;
|
|
87
|
+
|
|
88
|
+
// Finder patterns are 7x7 in three corners (+ separators around them)
|
|
89
|
+
const inTopLeft = x <= 8 && y <= 8;
|
|
90
|
+
const inTopRight = x >= n - 9 && y <= 8;
|
|
91
|
+
const inBottomLeft = x <= 8 && y >= n - 9;
|
|
92
|
+
if (inTopLeft || inTopRight || inBottomLeft) return true;
|
|
93
|
+
|
|
94
|
+
// Timing patterns are along row 6 and col 6 (0-indexed)
|
|
95
|
+
if (x === 6 || y === 6) return true;
|
|
96
|
+
|
|
97
|
+
// Format information areas near finders
|
|
98
|
+
if (y === 8 && (x <= 8 || x >= n - 8)) return true;
|
|
99
|
+
if (x === 8 && (y <= 8 || y >= n - 8)) return true;
|
|
100
|
+
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function parseAsciiToBitmap(ascii: string): boolean[][] {
|
|
105
|
+
const lines = ascii
|
|
106
|
+
.replace(/\r/g, "")
|
|
107
|
+
.split("\n")
|
|
108
|
+
.map((l) => l.replace(/\t/g, " "))
|
|
109
|
+
// keep empty lines inside art, but trim purely-leading/trailing blank lines
|
|
110
|
+
;
|
|
111
|
+
|
|
112
|
+
// Trim leading/trailing fully-blank lines
|
|
113
|
+
while (lines.length && lines[0].trimEnd().length === 0) lines.shift();
|
|
114
|
+
while (lines.length && lines[lines.length - 1].trimEnd().length === 0) lines.pop();
|
|
115
|
+
|
|
116
|
+
if (!lines.length) return [];
|
|
117
|
+
|
|
118
|
+
const onChars = new Set([
|
|
119
|
+
"█",
|
|
120
|
+
"▄",
|
|
121
|
+
"▀",
|
|
122
|
+
"▌",
|
|
123
|
+
"▐",
|
|
124
|
+
"▖",
|
|
125
|
+
"▗",
|
|
126
|
+
"▘",
|
|
127
|
+
"▝",
|
|
128
|
+
"▚",
|
|
129
|
+
"▛",
|
|
130
|
+
"▜",
|
|
131
|
+
"▙",
|
|
132
|
+
"▟",
|
|
133
|
+
"■",
|
|
134
|
+
"▓",
|
|
135
|
+
"▒",
|
|
136
|
+
"░",
|
|
137
|
+
"#",
|
|
138
|
+
"@",
|
|
139
|
+
"*",
|
|
140
|
+
"+",
|
|
141
|
+
]);
|
|
142
|
+
|
|
143
|
+
const maxW = Math.max(0, ...lines.map((l) => l.length));
|
|
144
|
+
return lines.map((line) => {
|
|
145
|
+
const padded = line.padEnd(maxW, " ");
|
|
146
|
+
return [...padded].map((ch) => onChars.has(ch));
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function bitmapToDebugAscii(bitmap: boolean[][]): string {
|
|
151
|
+
if (!bitmap.length) return "";
|
|
152
|
+
return bitmap
|
|
153
|
+
.map((row) => row.map((on) => (on ? "█" : " ")).join(""))
|
|
154
|
+
.join("\n");
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function getCenteredEmbedRegion(
|
|
158
|
+
matrixSize: number,
|
|
159
|
+
ascii: string | undefined,
|
|
160
|
+
embedBitmap: string[] | undefined,
|
|
161
|
+
embedScale: number
|
|
162
|
+
): {
|
|
163
|
+
startX: number;
|
|
164
|
+
startY: number;
|
|
165
|
+
regionW: number;
|
|
166
|
+
regionH: number;
|
|
167
|
+
scaled: boolean[][];
|
|
168
|
+
} | null {
|
|
169
|
+
const bmp = embedBitmap?.length
|
|
170
|
+
? parseStringBitmap(embedBitmap)
|
|
171
|
+
: ascii
|
|
172
|
+
? parseAsciiToBitmap(ascii)
|
|
173
|
+
: [];
|
|
174
|
+
if (bmp.length === 0) return null;
|
|
175
|
+
const bmpH = bmp.length;
|
|
176
|
+
const bmpW = bmp[0]?.length ?? 0;
|
|
177
|
+
if (!bmpW) return null;
|
|
178
|
+
|
|
179
|
+
// Trim to ink bounding box
|
|
180
|
+
let minX = bmpW,
|
|
181
|
+
minY = bmpH,
|
|
182
|
+
maxX = -1,
|
|
183
|
+
maxY = -1;
|
|
184
|
+
for (let y = 0; y < bmpH; y++) {
|
|
185
|
+
for (let x = 0; x < bmpW; x++) {
|
|
186
|
+
if (!bmp[y]?.[x]) continue;
|
|
187
|
+
if (x < minX) minX = x;
|
|
188
|
+
if (y < minY) minY = y;
|
|
189
|
+
if (x > maxX) maxX = x;
|
|
190
|
+
if (y > maxY) maxY = y;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (maxX < 0 || maxY < 0) return null;
|
|
194
|
+
|
|
195
|
+
const trimmed = bmp
|
|
196
|
+
.slice(minY, maxY + 1)
|
|
197
|
+
.map((row) => row.slice(minX, maxX + 1));
|
|
198
|
+
|
|
199
|
+
const tH = trimmed.length;
|
|
200
|
+
const tW = trimmed[0]?.length ?? 0;
|
|
201
|
+
if (!tW) return null;
|
|
202
|
+
|
|
203
|
+
const region = Math.max(1, Math.floor(matrixSize * embedScale));
|
|
204
|
+
|
|
205
|
+
// Make the embed region rectangular to better fit the ASCII art.
|
|
206
|
+
// If the art is wider than tall, give it extra width (up to ~25% more).
|
|
207
|
+
const aspect = tW / tH;
|
|
208
|
+
const maxBoost = 1.6;
|
|
209
|
+
|
|
210
|
+
let regionW = region;
|
|
211
|
+
let regionH = region;
|
|
212
|
+
|
|
213
|
+
if (aspect > 1) {
|
|
214
|
+
regionW = Math.min(matrixSize, Math.max(1, Math.round(region * Math.min(maxBoost, aspect))));
|
|
215
|
+
regionH = Math.max(1, Math.round(region / Math.min(maxBoost, aspect)));
|
|
216
|
+
} else if (aspect < 1) {
|
|
217
|
+
regionH = Math.min(matrixSize, Math.max(1, Math.round(region * Math.min(maxBoost, 1 / aspect))));
|
|
218
|
+
regionW = Math.max(1, Math.round(region / Math.min(maxBoost, 1 / aspect)));
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const startX = Math.floor((matrixSize - regionW) / 2);
|
|
222
|
+
const startY = Math.floor((matrixSize - regionH) / 2);
|
|
223
|
+
|
|
224
|
+
// Scale into region while preserving aspect ratio (letterbox inside region)
|
|
225
|
+
const sx = regionW / tW;
|
|
226
|
+
const sy = regionH / tH;
|
|
227
|
+
const s = Math.min(sx, sy);
|
|
228
|
+
|
|
229
|
+
// REMOVED vScale vertical fudge for bitmap
|
|
230
|
+
const drawW = Math.max(1, Math.floor(tW * s));
|
|
231
|
+
const drawH = Math.max(1, Math.floor(tH * s));
|
|
232
|
+
|
|
233
|
+
// Center the drawn area inside the region
|
|
234
|
+
const offX = Math.floor((regionW - drawW) / 2);
|
|
235
|
+
const offY = Math.floor((regionH - drawH) / 2);
|
|
236
|
+
|
|
237
|
+
const scaled: boolean[][] = Array.from({ length: regionH }, () =>
|
|
238
|
+
Array.from({ length: regionW }, () => false)
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
const invS = 1 / s;
|
|
242
|
+
for (let ry = 0; ry < drawH; ry++) {
|
|
243
|
+
for (let rx = 0; rx < drawW; rx++) {
|
|
244
|
+
const bx = Math.min(tW - 1, Math.floor(rx * invS));
|
|
245
|
+
const by = Math.min(tH - 1, Math.floor(ry * invS));
|
|
246
|
+
const x = offX + rx;
|
|
247
|
+
const y = offY + ry;
|
|
248
|
+
if (x < 0 || y < 0 || x >= regionW || y >= regionH) continue;
|
|
249
|
+
scaled[y][x] = trimmed[by]?.[bx] ?? false;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return { startX, startY, regionW, regionH, scaled };
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function clearCenteredRegion(
|
|
256
|
+
matrix: ModuleMatrix,
|
|
257
|
+
ascii: string | undefined,
|
|
258
|
+
embedBitmap: string[] | undefined,
|
|
259
|
+
embedScale: number,
|
|
260
|
+
padX: number = 1,
|
|
261
|
+
padY: number = 1
|
|
262
|
+
): ModuleMatrix {
|
|
263
|
+
const n = matrix.length;
|
|
264
|
+
const region = getCenteredEmbedRegion(n, ascii, embedBitmap, embedScale);
|
|
265
|
+
if (!region) return matrix;
|
|
266
|
+
|
|
267
|
+
const { startX, startY, regionW, regionH } = region;
|
|
268
|
+
const out: ModuleMatrix = matrix.map((row) => row.slice());
|
|
269
|
+
|
|
270
|
+
// Anisotropic padding around the embed region
|
|
271
|
+
const x0 = Math.max(0, startX - padX);
|
|
272
|
+
const y0 = Math.max(0, startY - padY);
|
|
273
|
+
const x1 = Math.min(n - 1, startX + regionW - 1 + padX);
|
|
274
|
+
const y1 = Math.min(n - 1, startY + regionH - 1 + padY);
|
|
275
|
+
|
|
276
|
+
// Rounded-rect clearing for a nicer merge with the QR noise
|
|
277
|
+
const w = x1 - x0 + 1;
|
|
278
|
+
const h = y1 - y0 + 1;
|
|
279
|
+
const radius = Math.max(2, Math.floor(Math.min(w, h) * 0.18)); // corner roundness
|
|
280
|
+
const fade = 2; // thickness of the transition band
|
|
281
|
+
// Lower-left corner shaping: soften the cut and close the gap more in that corner
|
|
282
|
+
const llCornerSpan = Math.max(3, Math.floor(Math.min(w, h) * 0.55));
|
|
283
|
+
|
|
284
|
+
const distToRoundedRect = (x: number, y: number) => {
|
|
285
|
+
const cx = x0 + w / 2;
|
|
286
|
+
const cy = y0 + h / 2;
|
|
287
|
+
const qx = Math.abs(x - cx) - (w / 2 - radius);
|
|
288
|
+
const qy = Math.abs(y - cy) - (h / 2 - radius);
|
|
289
|
+
const ax = Math.max(qx, 0);
|
|
290
|
+
const ay = Math.max(qy, 0);
|
|
291
|
+
const outside = Math.hypot(ax, ay);
|
|
292
|
+
const inside = Math.min(Math.max(qx, qy), 0);
|
|
293
|
+
return outside + inside - radius; // <= 0 inside
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
for (let y = y0 - fade; y <= y1 + fade; y++) {
|
|
297
|
+
for (let x = x0 - fade; x <= x1 + fade; x++) {
|
|
298
|
+
if (x < 0 || y < 0 || x >= n || y >= n) continue;
|
|
299
|
+
if (isInFinderOrTiming(out, x, y)) continue;
|
|
300
|
+
|
|
301
|
+
const d = distToRoundedRect(x, y);
|
|
302
|
+
if (d <= 0) {
|
|
303
|
+
// Fully clear inside, but keep a tiny amount of noise near the lower-left corner
|
|
304
|
+
const llDist0 = Math.hypot(x - x0, y - y1);
|
|
305
|
+
const llW0 = Math.max(0, Math.min(1, 1 - llDist0 / llCornerSpan));
|
|
306
|
+
const seed0 = ((x * 73856093) ^ (y * 19349663)) >>> 0;
|
|
307
|
+
const rnd0 = (seed0 % 1024) / 1024;
|
|
308
|
+
// Keep up to ~22% of modules near that corner (so it doesn't look like a sharp bite)
|
|
309
|
+
if (!(llW0 > 0 && rnd0 < llW0 * 0.22)) out[y][x] = false;
|
|
310
|
+
} else if (d <= fade) {
|
|
311
|
+
// Transition band: probabilistic clearing for a softer edge (stable, no flicker)
|
|
312
|
+
const t = 1 - d / fade; // 1 near edge, 0 far
|
|
313
|
+
|
|
314
|
+
// Make the RIGHT side less empty: reduce clearing probability as we approach x1
|
|
315
|
+
const edgeSpan = Math.max(1, Math.floor(w * 0.34)); // rightmost 35% of the cleared box
|
|
316
|
+
const rightness = Math.max(0, Math.min(1, (x - (x1 - edgeSpan)) / edgeSpan)); // 0..1
|
|
317
|
+
const edgeFactor = 1 - 0.55 * rightness; // 1.0 (left) -> 0.45 (right)
|
|
318
|
+
|
|
319
|
+
// Stable hash noise for a less grid-like mix
|
|
320
|
+
const seed = ((x * 73856093) ^ (y * 19349663)) >>> 0;
|
|
321
|
+
const rnd = (seed % 1024) / 1024; // 0..1
|
|
322
|
+
|
|
323
|
+
// Lower-left corner weight (1 near LL corner, 0 away)
|
|
324
|
+
const llDist = Math.hypot(x - x0, y - y1);
|
|
325
|
+
const llW = Math.max(0, Math.min(1, 1 - llDist / llCornerSpan));
|
|
326
|
+
|
|
327
|
+
// In LL corner: clear less aggressively (fills more) and effectively widen fade
|
|
328
|
+
const llT = Math.min(1, t + llW * 0.35);
|
|
329
|
+
const strength = 0.55 - llW * 0.18;
|
|
330
|
+
|
|
331
|
+
if (rnd < llT * strength * edgeFactor) out[y][x] = false;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return out;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function carveCenterForAscii(
|
|
340
|
+
matrix: ModuleMatrix,
|
|
341
|
+
ascii: string | undefined,
|
|
342
|
+
embedBitmap: string[] | undefined,
|
|
343
|
+
embedScale: number
|
|
344
|
+
): ModuleMatrix {
|
|
345
|
+
const n = matrix.length;
|
|
346
|
+
const region = getCenteredEmbedRegion(n, ascii, embedBitmap, embedScale);
|
|
347
|
+
if (!region) return matrix;
|
|
348
|
+
|
|
349
|
+
// First, clear the entire center rectangle so QR noise doesn't bleed into the logo.
|
|
350
|
+
// Padding gives the logo some breathing room and improves readability.
|
|
351
|
+
const cleared = clearCenteredRegion(matrix, ascii, embedBitmap, embedScale, 1, 1);
|
|
352
|
+
const { startX, startY, regionW, regionH, scaled } = region;
|
|
353
|
+
const out: ModuleMatrix = cleared.map((row) => row.slice());
|
|
354
|
+
// Then, carve the logo shape inside that cleared area (negative-space effect).
|
|
355
|
+
for (let ry = 0; ry < regionH; ry++) {
|
|
356
|
+
for (let rx = 0; rx < regionW; rx++) {
|
|
357
|
+
const on = scaled[ry]?.[rx] ?? false;
|
|
358
|
+
const x = startX + rx;
|
|
359
|
+
const y = startY + ry;
|
|
360
|
+
if (x < 0 || y < 0 || x >= n || y >= n) continue;
|
|
361
|
+
if (isInFinderOrTiming(out, x, y)) continue;
|
|
362
|
+
if (on) out[y][x] = false;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
return out;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function buildAsciiOverlayPath(
|
|
370
|
+
matrix: ModuleMatrix,
|
|
371
|
+
ascii: string | undefined,
|
|
372
|
+
embedBitmap: string[] | undefined,
|
|
373
|
+
embedScale: number,
|
|
374
|
+
quietZone: number,
|
|
375
|
+
cell: number,
|
|
376
|
+
moduleRadius: number
|
|
377
|
+
): string {
|
|
378
|
+
const n = matrix.length;
|
|
379
|
+
const region = getCenteredEmbedRegion(n, ascii, embedBitmap, embedScale);
|
|
380
|
+
if (!region) return "";
|
|
381
|
+
// NOTE: The QR matrix itself is carved elsewhere; this is just the overlay.
|
|
382
|
+
// We keep the overlay constrained to the region, and the region is cleared with padding for readability.
|
|
383
|
+
const { startX, startY, regionW, regionH, scaled } = region;
|
|
384
|
+
|
|
385
|
+
const r = Math.max(0, moduleRadius);
|
|
386
|
+
const parts: string[] = [];
|
|
387
|
+
|
|
388
|
+
for (let ry = 0; ry < regionH; ry++) {
|
|
389
|
+
for (let rx = 0; rx < regionW; rx++) {
|
|
390
|
+
const on = scaled[ry]?.[rx] ?? false;
|
|
391
|
+
if (!on) continue;
|
|
392
|
+
const x = startX + rx;
|
|
393
|
+
const y = startY + ry;
|
|
394
|
+
if (x < 0 || y < 0 || x >= n || y >= n) continue;
|
|
395
|
+
if (isInFinderOrTiming(matrix, x, y)) continue;
|
|
396
|
+
|
|
397
|
+
const px = (x + quietZone) * cell;
|
|
398
|
+
const py = (y + quietZone) * cell;
|
|
399
|
+
parts.push(roundedRectPath(px, py, cell, cell, r));
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
return parts.join(" ");
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
function roundedRectPath(x: number, y: number, w: number, h: number, r: number): string {
|
|
407
|
+
const rr = Math.max(0, Math.min(r, Math.min(w, h) / 2));
|
|
408
|
+
if (rr <= 0) return `M${x} ${y}h${w}v${h}h-${w}Z`;
|
|
409
|
+
return [
|
|
410
|
+
`M${x + rr} ${y}`,
|
|
411
|
+
`h${w - rr * 2}`,
|
|
412
|
+
`a${rr} ${rr} 0 0 1 ${rr} ${rr}`,
|
|
413
|
+
`v${h - rr * 2}`,
|
|
414
|
+
`a${rr} ${rr} 0 0 1 -${rr} ${rr}`,
|
|
415
|
+
`h-${w - rr * 2}`,
|
|
416
|
+
`a${rr} ${rr} 0 0 1 -${rr} -${rr}`,
|
|
417
|
+
`v-${h - rr * 2}`,
|
|
418
|
+
`a${rr} ${rr} 0 0 1 ${rr} -${rr}`,
|
|
419
|
+
`Z`,
|
|
420
|
+
].join(" ");
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
export default function QR({
|
|
424
|
+
value,
|
|
425
|
+
size = 160,
|
|
426
|
+
bg = "var(--qr-bg, transparent)",
|
|
427
|
+
fg = "var(--qr-fg, currentColor)",
|
|
428
|
+
moduleRadius = 0,
|
|
429
|
+
quietZone = 4,
|
|
430
|
+
ecc = "H",
|
|
431
|
+
asciiHeader,
|
|
432
|
+
caption,
|
|
433
|
+
embedMode = "none",
|
|
434
|
+
embedScale = 0.22,
|
|
435
|
+
embedAscii,
|
|
436
|
+
embedBitmap,
|
|
437
|
+
className,
|
|
438
|
+
style,
|
|
439
|
+
showEmbeddedAsciiPreview = false,
|
|
440
|
+
}: QRProps) {
|
|
441
|
+
const clipId = useId();
|
|
442
|
+
|
|
443
|
+
const matrix = useMemo(() => {
|
|
444
|
+
const base = buildQRMatrix(value, ecc);
|
|
445
|
+
if (embedMode === "negative-space" || embedMode === "positive-overlay") {
|
|
446
|
+
if (embedBitmap?.length || embedAscii) {
|
|
447
|
+
return carveCenterForAscii(base, embedAscii, embedBitmap, embedScale);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
return base;
|
|
451
|
+
}, [value, ecc, embedMode, embedAscii, embedBitmap, embedScale]);
|
|
452
|
+
|
|
453
|
+
const n = matrix.length;
|
|
454
|
+
const totalModules = n + quietZone * 2;
|
|
455
|
+
const cell = size / totalModules;
|
|
456
|
+
const r = Math.max(0, moduleRadius);
|
|
457
|
+
|
|
458
|
+
// Build a single path for performance
|
|
459
|
+
const pathD = useMemo(() => {
|
|
460
|
+
const parts: string[] = [];
|
|
461
|
+
for (let y = 0; y < n; y++) {
|
|
462
|
+
for (let x = 0; x < n; x++) {
|
|
463
|
+
if (!matrix[y][x]) continue;
|
|
464
|
+
const px = (x + quietZone) * cell;
|
|
465
|
+
const py = (y + quietZone) * cell;
|
|
466
|
+
parts.push(roundedRectPath(px, py, cell, cell, r));
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
return parts.join(" ");
|
|
470
|
+
}, [matrix, n, quietZone, cell, r]);
|
|
471
|
+
|
|
472
|
+
const overlayD = useMemo(() => {
|
|
473
|
+
if (!embedAscii && !(embedBitmap?.length)) return "";
|
|
474
|
+
if (embedMode !== "positive-overlay" && embedMode !== "negative-space") return "";
|
|
475
|
+
const base = buildQRMatrix(value, ecc);
|
|
476
|
+
return buildAsciiOverlayPath(base, embedAscii, embedBitmap, embedScale, quietZone, cell, r);
|
|
477
|
+
}, [embedMode, embedAscii, embedBitmap, embedScale, value, ecc, quietZone, cell, r]);
|
|
478
|
+
|
|
479
|
+
return (
|
|
480
|
+
<div
|
|
481
|
+
className={className}
|
|
482
|
+
style={{
|
|
483
|
+
display: "inline-flex",
|
|
484
|
+
flexDirection: "column",
|
|
485
|
+
gap: 8,
|
|
486
|
+
...(style ?? {}),
|
|
487
|
+
// Allow theme to drive QR colors via CSS variables
|
|
488
|
+
["--qr-bg" as any]: bg,
|
|
489
|
+
["--qr-fg" as any]: fg,
|
|
490
|
+
}}
|
|
491
|
+
>
|
|
492
|
+
{asciiHeader ? (
|
|
493
|
+
<pre
|
|
494
|
+
style={{
|
|
495
|
+
margin: 0,
|
|
496
|
+
padding: 0,
|
|
497
|
+
lineHeight: 1,
|
|
498
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace",
|
|
499
|
+
fontSize: 12,
|
|
500
|
+
opacity: 0.9,
|
|
501
|
+
userSelect: "none",
|
|
502
|
+
}}
|
|
503
|
+
>
|
|
504
|
+
{asciiHeader}
|
|
505
|
+
</pre>
|
|
506
|
+
) : null}
|
|
507
|
+
|
|
508
|
+
{showEmbeddedAsciiPreview && (embedAscii || (embedBitmap?.length)) ? (() => {
|
|
509
|
+
const reg = getCenteredEmbedRegion(matrix.length, embedAscii, embedBitmap, embedScale);
|
|
510
|
+
if (!reg) return null;
|
|
511
|
+
// show the trimmed ascii or bitmap (pre-scale)
|
|
512
|
+
const trimmedBmp = embedBitmap?.length ? parseStringBitmap(embedBitmap) : parseAsciiToBitmap(embedAscii ?? "");
|
|
513
|
+
const trimmedDebug = bitmapToDebugAscii(trimmedBmp);
|
|
514
|
+
return (
|
|
515
|
+
<div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
|
|
516
|
+
<div style={{ fontSize: 11, opacity: 0.8, fontFamily: "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace" }}>
|
|
517
|
+
embed region: {reg.regionW}×{reg.regionH} modules @ {Math.round(embedScale * 100)}%
|
|
518
|
+
</div>
|
|
519
|
+
<pre style={{ margin: 0, padding: 8, borderRadius: 8, background: "rgba(0,0,0,0.06)", lineHeight: 1, fontSize: 10, userSelect: "text", overflow: "auto", maxWidth: size }}>
|
|
520
|
+
{trimmedDebug || "(empty bitmap)"}
|
|
521
|
+
</pre>
|
|
522
|
+
</div>
|
|
523
|
+
);
|
|
524
|
+
})() : null}
|
|
525
|
+
|
|
526
|
+
<svg
|
|
527
|
+
width={size}
|
|
528
|
+
height={size}
|
|
529
|
+
viewBox={`0 0 ${size} ${size}`}
|
|
530
|
+
role="img"
|
|
531
|
+
aria-label="QR code"
|
|
532
|
+
shapeRendering="crispEdges"
|
|
533
|
+
>
|
|
534
|
+
{/* background */}
|
|
535
|
+
{bg !== "transparent" ? <rect x={0} y={0} width={size} height={size} fill={`var(--qr-bg, ${bg})`} /> : null}
|
|
536
|
+
|
|
537
|
+
{/* clip to rounded outer rect if bg is transparent */}
|
|
538
|
+
<defs>
|
|
539
|
+
<clipPath id={clipId}>
|
|
540
|
+
<rect x={0} y={0} width={size} height={size} rx={12} ry={12} />
|
|
541
|
+
</clipPath>
|
|
542
|
+
</defs>
|
|
543
|
+
|
|
544
|
+
<g clipPath={`url(#${clipId})`}>
|
|
545
|
+
<path d={pathD} fill={`var(--qr-fg, ${fg})`} />
|
|
546
|
+
{overlayD ? <path d={overlayD} fill={`var(--qr-fg, ${fg})`} /> : null}
|
|
547
|
+
</g>
|
|
548
|
+
</svg>
|
|
549
|
+
|
|
550
|
+
{caption ? (
|
|
551
|
+
<div
|
|
552
|
+
style={{
|
|
553
|
+
fontSize: 11,
|
|
554
|
+
lineHeight: "14px",
|
|
555
|
+
opacity: 0.8,
|
|
556
|
+
maxWidth: size,
|
|
557
|
+
wordBreak: "break-all",
|
|
558
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace",
|
|
559
|
+
}}
|
|
560
|
+
>
|
|
561
|
+
{caption}
|
|
562
|
+
</div>
|
|
563
|
+
) : null}
|
|
564
|
+
</div>
|
|
565
|
+
);
|
|
566
|
+
}
|