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,350 @@
|
|
|
1
|
+
import TopBar from './TopBar';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'Layout/TopBar',
|
|
6
|
+
component: TopBar,
|
|
7
|
+
tags: ['autodocs'],
|
|
8
|
+
decorators: [
|
|
9
|
+
(Story) => (
|
|
10
|
+
<Story />
|
|
11
|
+
),
|
|
12
|
+
],
|
|
13
|
+
parameters: {
|
|
14
|
+
docs: {
|
|
15
|
+
description: {
|
|
16
|
+
component:
|
|
17
|
+
`The **TopBar** component provides a responsive, application top bar for navigation, branding and other actions.
|
|
18
|
+
---
|
|
19
|
+
## Features
|
|
20
|
+
- **Branding:** Display a logo and title.
|
|
21
|
+
- **Navigation Links:** With optional icons and dropdown menus (nested children).
|
|
22
|
+
- **Custom actions:** Theme toggle, etc.
|
|
23
|
+
- **Responsive:** Adapts to mobile layouts.
|
|
24
|
+
- **Inset-aware:** Reads global left/right/nav insets from the theme to align with permanent drawers.
|
|
25
|
+
- **Icon support:** Via the This.GUI icon registry (declarative strings).
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
### Position Modes
|
|
30
|
+
- \`position="static"\`: The TopBar scrolls with the content, part of the normal document flow.
|
|
31
|
+
- \`position="fixed"\`: The TopBar stays pinned to the top of the viewport, remaining visible during scrolling.
|
|
32
|
+
- Ergonomically, \`static\` feels fluid and natural for reading layouts, while \`fixed\` provides stability and quick access to main navigation.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
### Props
|
|
37
|
+
Each element can specify:
|
|
38
|
+
- \`type\` (string): Element type, e.g. 'link' or 'menu'.
|
|
39
|
+
- \`props\` (object): Properties for the element.
|
|
40
|
+
- For \`link\`: \`label\` (string), \`href\` (string), \`icon\` (string), \`iconColor\` (string).
|
|
41
|
+
- For \`menu\`: \`label\` (string), \`icon\` (string), \`iconColor\` (string), \`children\` (array of elements).
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
**Example:**
|
|
45
|
+
~~~jsx
|
|
46
|
+
<TopBar
|
|
47
|
+
logo="https://neurons.me/neurons.me.png"
|
|
48
|
+
elementsCenter={[
|
|
49
|
+
{ type: 'link', props: { label: 'Home', href: '/', icon: 'home', iconColor: 'primary' } },
|
|
50
|
+
{ type: 'link', props: { label: 'Docs', href: '/docs', icon: 'insights', iconColor: 'secondary' } },
|
|
51
|
+
{
|
|
52
|
+
type: 'menu',
|
|
53
|
+
props: {
|
|
54
|
+
label: 'More',
|
|
55
|
+
icon: 'info',
|
|
56
|
+
iconColor: '#00aa96',
|
|
57
|
+
items: [
|
|
58
|
+
{ label: 'About', href: '/about', icon: 'message', iconColor: 'info' },
|
|
59
|
+
{ label: 'Contact', href: '/contact', icon: 'mail', iconColor: '#4caf50' },
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
]}
|
|
64
|
+
showThemeToggle
|
|
65
|
+
position="fixed"
|
|
66
|
+
/>
|
|
67
|
+
~~~
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
#### Dropdown Menus
|
|
72
|
+
- To create a dropdown, provide a \`children\` array with elements of type \`link\` inside a \`menu\` element.
|
|
73
|
+
|
|
74
|
+
~~~jsx
|
|
75
|
+
<TopBar
|
|
76
|
+
elementsCenter={[
|
|
77
|
+
{
|
|
78
|
+
type: 'menu',
|
|
79
|
+
props: {
|
|
80
|
+
label: 'More',
|
|
81
|
+
icon: 'info',
|
|
82
|
+
items: [
|
|
83
|
+
{ label: 'About', href: '/about' },
|
|
84
|
+
{ label: 'Contact', href: '/contact' },
|
|
85
|
+
],
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
]}
|
|
89
|
+
/>
|
|
90
|
+
~~~
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
#### Icon Usage
|
|
95
|
+
- **Material Symbols:** Use icon names directly (e.g. \`bar_chart\`, \`mail\`, \`insights\`). See [Material Symbols Catalog](https://fonts.google.com/icons?icon.set=Material+Symbols).
|
|
96
|
+
- Icon rendering is handled by the \`<Icon />\` component, which supports font variation settings like \`weight\`, \`fill\`, \`grade\`, \`opticalSize\`, and standard props like \`iconColor\` and \`fontSize\`.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
### React Component Mode (Advanced)
|
|
100
|
+
You may also use TopBar as a React component and pass elements as arrays of objects with \`type\` and \`props\`:
|
|
101
|
+
|
|
102
|
+
~~~jsx
|
|
103
|
+
import TopBar from './TopBar';
|
|
104
|
+
|
|
105
|
+
<TopBar
|
|
106
|
+
elementsCenter={[
|
|
107
|
+
{ type: 'link', props: { label: 'Home', href: '/', icon: 'bar_chart', iconColor: 'primary' } },
|
|
108
|
+
{ type: 'link', props: { label: 'Docs', href: '/docs', icon: 'insights', iconColor: '#f50057' } },
|
|
109
|
+
{
|
|
110
|
+
type: 'menu',
|
|
111
|
+
props: {
|
|
112
|
+
label: 'More',
|
|
113
|
+
icon: 'info',
|
|
114
|
+
items: [
|
|
115
|
+
{ label: 'About', href: '/about', icon: 'mail', iconColor: '#4caf50' },
|
|
116
|
+
],
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
]}
|
|
120
|
+
position="static"
|
|
121
|
+
/>
|
|
122
|
+
~~~
|
|
123
|
+
- **Note:** The \`props.icon\` property accepts icon names as strings. Color and style are controlled via \`iconColor\` and other props handled by the \`<Icon />\` component.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Notes
|
|
128
|
+
- TopBar uses \`react-router-dom\` internally. Stories wrap it in a \`MemoryRouter\` for demo purposes.
|
|
129
|
+
- Dropdown menus are created by providing a \`children\` array for any menu element.
|
|
130
|
+
- Icon colors can be set with theme color keys (\`primary\`, \`secondary\`, \`info\`, etc.) or any valid CSS color string.
|
|
131
|
+
- \`elementsCenter\` and \`elementsRight\` accept objects with \`type\` and \`props\`, supporting nested menus.
|
|
132
|
+
- Toggles like showThemeToggle and homeTo/position.
|
|
133
|
+
Inset handling:
|
|
134
|
+
- Measure Toolbar with toolbarRef, call theme.updateInsets({ nav: h }), and clean up in return → this updates theme.layout.insets.nav in GuiProvider and also the CSS vars (--gui-nav-height).
|
|
135
|
+
Theme integration:
|
|
136
|
+
- Use useTheme()/useMediaQuery(). In GuiProvider, inject updateInsets and layout.insets into the memoized MUI theme, so TopBar sees them correctly.
|
|
137
|
+
|
|
138
|
+
`,
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
argTypes: {
|
|
143
|
+
title: {
|
|
144
|
+
description: 'Title text displayed next to the logo.',
|
|
145
|
+
control: 'text',
|
|
146
|
+
},
|
|
147
|
+
logo: {
|
|
148
|
+
description: 'Logo image URL shown in the top-left.',
|
|
149
|
+
control: 'text',
|
|
150
|
+
},
|
|
151
|
+
elementsCenter: {
|
|
152
|
+
description: 'Array of navigation elements for center alignment, e.g. [{ type: "link", props: { label: string, href?: string, icon?: string, iconColor?: string } }, { type: "menu", props: { label: string, icon?: string, iconColor?: string, children: elements[] } }]. Supports nested dropdown menus.',
|
|
153
|
+
control: 'object',
|
|
154
|
+
},
|
|
155
|
+
elementsRight: {
|
|
156
|
+
description: 'Array of navigation elements for right alignment, similar structure as elementsCenter.',
|
|
157
|
+
control: 'object',
|
|
158
|
+
},
|
|
159
|
+
homeTo: {
|
|
160
|
+
description: 'Router path for clicking on logo/title.',
|
|
161
|
+
control: 'text',
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
} satisfies Meta<typeof TopBar>;
|
|
165
|
+
export default meta;
|
|
166
|
+
export type Story = StoryObj<typeof TopBar>;
|
|
167
|
+
|
|
168
|
+
export const Default: Story = {
|
|
169
|
+
args: {
|
|
170
|
+
title: 'neurons.me',
|
|
171
|
+
logo: 'https://neurons.me/neurons.me.png',
|
|
172
|
+
elementsCenter: [
|
|
173
|
+
{ type: 'link', props: { label: 'Home', href: '/', icon: 'home' } },
|
|
174
|
+
{ type: 'link', props: { label: 'Docs', href: '/docs', icon: 'insights' } },
|
|
175
|
+
{
|
|
176
|
+
type: 'menu',
|
|
177
|
+
props: {
|
|
178
|
+
label: 'More',
|
|
179
|
+
icon: 'info',
|
|
180
|
+
items: [
|
|
181
|
+
{ label: 'About', href: '/about', icon: 'message' },
|
|
182
|
+
{ label: 'Contact', href: '/contact', icon: 'mail' },
|
|
183
|
+
],
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
],
|
|
187
|
+
homeTo: '/',
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
export const FixedTopBar = () => (
|
|
193
|
+
<>
|
|
194
|
+
<TopBar
|
|
195
|
+
title="neurons.me"
|
|
196
|
+
logo="https://neurons.me/neurons.me.png"
|
|
197
|
+
elementsCenter={[
|
|
198
|
+
{ type: 'link', props: { label: 'Home', href: '/', icon: 'home' } },
|
|
199
|
+
{ type: 'link', props: { label: 'Docs', href: '/docs', icon: 'insights' } },
|
|
200
|
+
{
|
|
201
|
+
type: 'menu',
|
|
202
|
+
props: {
|
|
203
|
+
label: 'More',
|
|
204
|
+
icon: 'info',
|
|
205
|
+
items: [
|
|
206
|
+
{ label: 'About', href: '/about', icon: 'message' },
|
|
207
|
+
{ label: 'Contact', href: '/contact', icon: 'mail' },
|
|
208
|
+
],
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
]}
|
|
212
|
+
homeTo="/"
|
|
213
|
+
position="fixed"
|
|
214
|
+
/>
|
|
215
|
+
<div style={{ marginTop: 80, padding: 20, height: '200vh'}}>
|
|
216
|
+
{Array(100).fill('Lorem ipsum dolor sit amet, consectetur adipiscing elit. ').join('')}
|
|
217
|
+
</div>
|
|
218
|
+
</>
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
FixedTopBar.storyName = 'Fixed TopBar';
|
|
222
|
+
FixedTopBar.parameters = {
|
|
223
|
+
docs: {
|
|
224
|
+
description: {
|
|
225
|
+
story: 'Demonstrates the TopBar with `position="fixed"`. Scroll down to see the TopBar stay fixed at the top.',
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
export const StaticTopBar = () => (
|
|
231
|
+
<>
|
|
232
|
+
<TopBar
|
|
233
|
+
title="neurons.me"
|
|
234
|
+
logo="https://neurons.me/neurons.me.png"
|
|
235
|
+
elementsCenter={[
|
|
236
|
+
{ type: 'link', props: { label: 'Home', href: '/', icon: 'home' } },
|
|
237
|
+
{ type: 'link', props: { label: 'Docs', href: '/docs', icon: 'insights' } },
|
|
238
|
+
{
|
|
239
|
+
type: 'menu',
|
|
240
|
+
props: {
|
|
241
|
+
label: 'More',
|
|
242
|
+
icon: 'info',
|
|
243
|
+
items: [
|
|
244
|
+
{ label: 'About', href: '/about', icon: 'message' },
|
|
245
|
+
{ label: 'Contact', href: '/contact', icon: 'mail' },
|
|
246
|
+
],
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
]}
|
|
250
|
+
homeTo="/"
|
|
251
|
+
position="static"
|
|
252
|
+
/>
|
|
253
|
+
<div style={{ padding: 20, height: '200vh'}}>
|
|
254
|
+
{Array(100).fill('Lorem ipsum dolor sit amet, consectetur adipiscing elit. ').join('')}
|
|
255
|
+
</div>
|
|
256
|
+
</>
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
StaticTopBar.storyName = 'Static TopBar';
|
|
260
|
+
StaticTopBar.parameters = {
|
|
261
|
+
docs: {
|
|
262
|
+
description: {
|
|
263
|
+
story: 'Demonstrates the TopBar with `position="static"`. Scroll down to see the TopBar scroll with the page.',
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
export const CenterElements: Story = {
|
|
269
|
+
args: {
|
|
270
|
+
title: 'neurons.me',
|
|
271
|
+
logo: 'https://neurons.me/neurons.me.png',
|
|
272
|
+
elementsCenter: [
|
|
273
|
+
{ type: 'link', props: { label: 'Home', href: '/', icon: 'home', iconColor: 'primary' } },
|
|
274
|
+
{ type: 'link', props: { label: 'Blog', href: '/blog', icon: 'article', iconColor: 'secondary' } },
|
|
275
|
+
{
|
|
276
|
+
type: 'menu',
|
|
277
|
+
props: {
|
|
278
|
+
label: 'Services',
|
|
279
|
+
icon: 'build',
|
|
280
|
+
iconColor: '#00796b',
|
|
281
|
+
items: [
|
|
282
|
+
{ label: 'Consulting', href: '/consulting', icon: 'support_agent', iconColor: 'info' },
|
|
283
|
+
{ label: 'Development', href: '/development', icon: 'code', iconColor: '#4caf50' },
|
|
284
|
+
],
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
],
|
|
288
|
+
homeTo: '/',
|
|
289
|
+
},
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
export const RightElements: Story = {
|
|
293
|
+
args: {
|
|
294
|
+
title: 'neurons.me',
|
|
295
|
+
logo: 'https://neurons.me/neurons.me.png',
|
|
296
|
+
elementsRight: [
|
|
297
|
+
{ type: 'link', props: { label: 'Login', href: '/login', icon: 'login', iconColor: 'primary' } },
|
|
298
|
+
{ type: 'link', props: { label: 'Register', href: '/register', icon: 'person_add', iconColor: 'secondary' } },
|
|
299
|
+
{
|
|
300
|
+
type: 'menu',
|
|
301
|
+
props: {
|
|
302
|
+
label: 'Profile',
|
|
303
|
+
icon: 'account_circle',
|
|
304
|
+
iconColor: '#3f51b5',
|
|
305
|
+
items: [
|
|
306
|
+
{ label: 'Settings', href: '/settings', icon: 'settings', iconColor: 'info' },
|
|
307
|
+
{ label: 'Logout', href: '/logout', icon: 'logout', iconColor: '#f44336' },
|
|
308
|
+
],
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
],
|
|
312
|
+
homeTo: '/',
|
|
313
|
+
},
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
export const CenterAndRightElements: Story = {
|
|
317
|
+
args: {
|
|
318
|
+
title: 'neurons.me',
|
|
319
|
+
logo: 'https://neurons.me/neurons.me.png',
|
|
320
|
+
elementsCenter: [
|
|
321
|
+
{ type: 'link', props: { label: 'Dashboard', href: '/dashboard', icon: 'dashboard', iconColor: 'primary' } },
|
|
322
|
+
{ type: 'link', props: { label: 'Reports', href: '/reports', icon: 'bar_chart', iconColor: 'secondary' } },
|
|
323
|
+
],
|
|
324
|
+
elementsRight: [
|
|
325
|
+
{
|
|
326
|
+
type: 'menu',
|
|
327
|
+
props: {
|
|
328
|
+
label: 'User',
|
|
329
|
+
icon: 'account_circle',
|
|
330
|
+
iconColor: '#3f51b5',
|
|
331
|
+
items: [
|
|
332
|
+
{ label: 'Profile', href: '/profile', icon: 'person', iconColor: 'info' },
|
|
333
|
+
{ label: 'Logout', href: '/logout', icon: 'logout', iconColor: '#f44336' },
|
|
334
|
+
],
|
|
335
|
+
},
|
|
336
|
+
},
|
|
337
|
+
],
|
|
338
|
+
homeTo: '/',
|
|
339
|
+
},
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
export const NoElements: Story = {
|
|
343
|
+
args: {
|
|
344
|
+
title: 'neurons.me',
|
|
345
|
+
logo: 'https://neurons.me/neurons.me.png',
|
|
346
|
+
elementsCenter: [],
|
|
347
|
+
elementsRight: [],
|
|
348
|
+
homeTo: '/',
|
|
349
|
+
},
|
|
350
|
+
};
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
import type { SxProps, Theme } from '@mui/material/styles';
|
|
3
|
+
import type { TopBarProps, TopBarElement } from './TopBar.types';
|
|
4
|
+
import type { TopBarMenuItemProps } from './components/TopBarMenu/TopBarMenu.types';
|
|
5
|
+
import TopBarLink from './components/TopBarLink/TopBarLink';
|
|
6
|
+
import TopBarMenu from './components/TopBarMenu/TopBarMenu';
|
|
7
|
+
import TopBarAction from './components/TopBarAction/TopBarAction';
|
|
8
|
+
import { AppBar, Toolbar, Typography, Box, Avatar } from '@mui/material';
|
|
9
|
+
import { Link as RouterLink } from 'react-router-dom';
|
|
10
|
+
import { useGuiTheme, useGuiMediaQuery, useInsets, useUpdateInsets } from '@/gui/hooks';
|
|
11
|
+
const sxN = (...parts: Array<SxProps<Theme> | undefined>): SxProps<Theme> => (parts.filter(Boolean) as unknown) as SxProps<Theme>;
|
|
12
|
+
const buildCollapsedItems = (elements: TopBarElement[]): TopBarMenuItemProps[] => {
|
|
13
|
+
const items: TopBarMenuItemProps[] = [];
|
|
14
|
+
elements.forEach((el) => {
|
|
15
|
+
if (el.type === 'link') {
|
|
16
|
+
const { label, href, icon, iconColor, external } = el.props as any;
|
|
17
|
+
if (label && href) {
|
|
18
|
+
items.push({ label, href, icon, iconColor, external });
|
|
19
|
+
}
|
|
20
|
+
} else if (el.type === 'menu') {
|
|
21
|
+
const { items: sub } = el.props as any;
|
|
22
|
+
if (Array.isArray(sub)) {
|
|
23
|
+
// Flatten one level: include submenu items directly
|
|
24
|
+
sub.forEach((si: TopBarMenuItemProps) => items.push(si));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// 'action' elements are not included in collapsed menu by default
|
|
28
|
+
});
|
|
29
|
+
return items;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* ## TopBar Layout Overview
|
|
33
|
+
*
|
|
34
|
+
* The TopBar is divided into three main sections:
|
|
35
|
+
* - **Brand (Left)** → Displays the logo and title, linking to `homeTo`.
|
|
36
|
+
* - **Center Elements** → Typically used for navigation links or menus, centered horizontally.
|
|
37
|
+
* - **Right Elements** → Used for actions, user menus, or secondary navigation.
|
|
38
|
+
*
|
|
39
|
+
* ---
|
|
40
|
+
*
|
|
41
|
+
* ## Responsiveness Behavior
|
|
42
|
+
*
|
|
43
|
+
* The TopBar adapts dynamically to screen width using MUI breakpoints:
|
|
44
|
+
*
|
|
45
|
+
* | Viewport | Breakpoint Range | Behavior |
|
|
46
|
+
* |-----------------|----------------------|-------------------------------------------|
|
|
47
|
+
* | **Desktop** | ≥ 900px (`md` and up) | Shows icons **and** labels (full view). |
|
|
48
|
+
* | **Tablet** | 600–899px (`sm`–`md`) | Shows **icons only** (labels hidden). |
|
|
49
|
+
* | **Mobile** | < 600px (`sm` down) | Collapses into two grouped menus. |
|
|
50
|
+
*
|
|
51
|
+
* - The **center section** and **right section** each collapse into a single `TopBarMenu` trigger in mobile view.
|
|
52
|
+
* - The **collapsed menus** show their corresponding grouped elements as dropdown items.
|
|
53
|
+
*
|
|
54
|
+
* ---
|
|
55
|
+
*
|
|
56
|
+
* ## Collapsed Icons
|
|
57
|
+
*
|
|
58
|
+
* The props `collapsedIconCenter` and `collapsedIconRight` define the icons used when the TopBar collapses into mobile view:
|
|
59
|
+
*
|
|
60
|
+
* ```tsx
|
|
61
|
+
* <TopBar
|
|
62
|
+
* collapsedIconCenter="settings" // default
|
|
63
|
+
* collapsedIconRight="more_horiz" // default
|
|
64
|
+
* />
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* These determine which icons appear for the two grouped mobile dropdown triggers.
|
|
68
|
+
* The values should correspond to names supported by the `Icon` component (e.g., Material Symbols).
|
|
69
|
+
*
|
|
70
|
+
* ---
|
|
71
|
+
*
|
|
72
|
+
* ## Notes
|
|
73
|
+
*
|
|
74
|
+
* - The TopBar ensures real visual centering of `elementsCenter` using absolute positioning.
|
|
75
|
+
* - Padding and insets automatically adjust based on AppBar position (`fixed`, `static`, or `sticky`).
|
|
76
|
+
* - `TopBarLink` and `TopBarMenu` each accept `showLabel` for tablet responsiveness (icons-only view).
|
|
77
|
+
*/
|
|
78
|
+
export default function TopBar(props: TopBarProps) {
|
|
79
|
+
const {
|
|
80
|
+
title = '',
|
|
81
|
+
logo = '',
|
|
82
|
+
elementsCenter = [],
|
|
83
|
+
elementsRight = [],
|
|
84
|
+
homeTo,
|
|
85
|
+
position = 'fixed',
|
|
86
|
+
sx,
|
|
87
|
+
appBarSx,
|
|
88
|
+
toolbarSx,
|
|
89
|
+
brandSx,
|
|
90
|
+
logoSx,
|
|
91
|
+
titleSx,
|
|
92
|
+
linksSx,
|
|
93
|
+
id,
|
|
94
|
+
className,
|
|
95
|
+
collapsedIconCenter = 'settings',
|
|
96
|
+
collapsedIconRight = 'more_horiz',
|
|
97
|
+
} = props;
|
|
98
|
+
const theme = useGuiTheme();
|
|
99
|
+
// Adjusted breakpoints for later collapse:
|
|
100
|
+
const isMobile = useGuiMediaQuery(theme.breakpoints.down('sm')); // <600px
|
|
101
|
+
const isDesktop = useGuiMediaQuery(theme.breakpoints.up('md')); // ≥900px
|
|
102
|
+
const toolbarRef = useRef<HTMLDivElement | null>(null);
|
|
103
|
+
const appBarRef = useRef<HTMLDivElement | null>(null);
|
|
104
|
+
const insets = useInsets();
|
|
105
|
+
const updateInsets = useUpdateInsets();
|
|
106
|
+
const insetLeft = Math.max(0, Number(insets?.left ?? 0));
|
|
107
|
+
const insetRight = Math.max(0, Number(insets?.right ?? 0));
|
|
108
|
+
const horizontalInset = insetLeft + insetRight;
|
|
109
|
+
const showBrandLabel = !isMobile;
|
|
110
|
+
const brandInitial = String(title ?? '').trim().charAt(0)?.toUpperCase() || '';
|
|
111
|
+
const hasBrandLink = homeTo !== null;
|
|
112
|
+
const resolvedHomeTo = hasBrandLink ? (homeTo ?? '/') : undefined;
|
|
113
|
+
const brandVisual = logo ? (
|
|
114
|
+
<Box component="img" src={logo} alt={title ? `${title} logo` : 'Brand logo'} sx={sxN({ height: 28 }, logoSx)} />
|
|
115
|
+
) : (
|
|
116
|
+
<Avatar sx={sxN({ width: 28, height: 28, fontSize: '0.875rem' }, logoSx)}>{brandInitial || '?'}</Avatar>
|
|
117
|
+
);
|
|
118
|
+
// Sync nav inset with real rendered height (idempotent via provider)
|
|
119
|
+
useEffect(() => {
|
|
120
|
+
if (typeof updateInsets !== 'function') return;
|
|
121
|
+
const measure = () => {
|
|
122
|
+
const target = appBarRef.current ?? toolbarRef.current;
|
|
123
|
+
const h = target?.offsetHeight ?? 48;
|
|
124
|
+
updateInsets({ nav: h });
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
// initial measure
|
|
128
|
+
measure();
|
|
129
|
+
// observe toolbar size changes (density, breakpoints, etc.)
|
|
130
|
+
let ro: ResizeObserver | undefined;
|
|
131
|
+
if (typeof ResizeObserver !== 'undefined') {
|
|
132
|
+
const target = appBarRef.current ?? toolbarRef.current;
|
|
133
|
+
if (target) {
|
|
134
|
+
ro = new ResizeObserver(() => measure());
|
|
135
|
+
ro.observe(target);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return () => {
|
|
140
|
+
if (ro) ro.disconnect();
|
|
141
|
+
updateInsets({ top: 0, nav: 0 });
|
|
142
|
+
};
|
|
143
|
+
}, [isMobile, updateInsets]);
|
|
144
|
+
// Sync insets.left with global CSS variable for layout
|
|
145
|
+
useEffect(() => {
|
|
146
|
+
if (insets && typeof insets.left === 'number') {
|
|
147
|
+
document.documentElement.style.setProperty('--gui-inset-left', `${insets.left}px`);
|
|
148
|
+
}
|
|
149
|
+
}, [insets.left]);
|
|
150
|
+
// Determine if the TopBar is fixed or sticky for styling
|
|
151
|
+
const isFixed = position === 'fixed' || position === 'sticky';
|
|
152
|
+
// Indentation handled by Toolbar padding-left via --gui-inset-left CSS variable
|
|
153
|
+
const baseAppBarSx = {
|
|
154
|
+
minHeight: 48,
|
|
155
|
+
backgroundColor: theme.palette.background.nav,
|
|
156
|
+
borderBottom: '1px solid',
|
|
157
|
+
borderColor: theme.palette.divider,
|
|
158
|
+
// Keep AppBar *below* the Drawer so the Drawer edge sits flush over it.
|
|
159
|
+
zIndex: (theme as any)?.zIndex?.appBar ?? 1100,
|
|
160
|
+
...(isFixed && {
|
|
161
|
+
top: 0,
|
|
162
|
+
left: `${insetLeft}px`,
|
|
163
|
+
right: `${insetRight}px`,
|
|
164
|
+
width: `calc(100% - ${horizontalInset}px)`,
|
|
165
|
+
transition: 'left 0.3s ease, right 0.3s ease, width 0.3s ease',
|
|
166
|
+
}),
|
|
167
|
+
boxSizing: 'border-box',
|
|
168
|
+
} as const;
|
|
169
|
+
const flowAppBarSx = !isFixed
|
|
170
|
+
? ({
|
|
171
|
+
ml: `${insetLeft}px`,
|
|
172
|
+
mr: `${insetRight}px`,
|
|
173
|
+
width: `calc(100% - ${horizontalInset}px)`,
|
|
174
|
+
transition: 'margin-left 0.3s ease, margin-right 0.3s ease, width 0.3s ease',
|
|
175
|
+
} as SxProps<Theme>)
|
|
176
|
+
: undefined;
|
|
177
|
+
return (
|
|
178
|
+
<AppBar
|
|
179
|
+
id={id}
|
|
180
|
+
className={className}
|
|
181
|
+
position={position}
|
|
182
|
+
elevation={0}
|
|
183
|
+
ref={appBarRef}
|
|
184
|
+
sx={sxN(
|
|
185
|
+
baseAppBarSx as SxProps<Theme>,
|
|
186
|
+
{ '--has-topbar': 1 } as any,
|
|
187
|
+
flowAppBarSx,
|
|
188
|
+
sx,
|
|
189
|
+
appBarSx
|
|
190
|
+
)}
|
|
191
|
+
>
|
|
192
|
+
<Toolbar
|
|
193
|
+
ref={toolbarRef}
|
|
194
|
+
variant="dense"
|
|
195
|
+
disableGutters
|
|
196
|
+
sx={sxN(
|
|
197
|
+
isFixed
|
|
198
|
+
? {
|
|
199
|
+
minHeight: 48,
|
|
200
|
+
pl: 1.5,
|
|
201
|
+
pr: 1.5,
|
|
202
|
+
py: 0,
|
|
203
|
+
display: 'flex',
|
|
204
|
+
alignItems: 'center',
|
|
205
|
+
gap: 1.25,
|
|
206
|
+
position: 'relative',
|
|
207
|
+
}
|
|
208
|
+
: {
|
|
209
|
+
minHeight: 48,
|
|
210
|
+
pl: 1.5,
|
|
211
|
+
pr: 1.5,
|
|
212
|
+
py: 0.5,
|
|
213
|
+
display: 'flex',
|
|
214
|
+
alignItems: 'center',
|
|
215
|
+
gap: 1.25,
|
|
216
|
+
position: 'relative',
|
|
217
|
+
},
|
|
218
|
+
toolbarSx
|
|
219
|
+
)}
|
|
220
|
+
>
|
|
221
|
+
<Box
|
|
222
|
+
sx={sxN(
|
|
223
|
+
{
|
|
224
|
+
display: 'flex',
|
|
225
|
+
alignItems: 'center',
|
|
226
|
+
flexShrink: 0,
|
|
227
|
+
textDecoration: 'none',
|
|
228
|
+
ml: 0,
|
|
229
|
+
pl: 1.5,
|
|
230
|
+
gap: showBrandLabel ? 1.25 : 0.75,
|
|
231
|
+
'&:hover': { textDecoration: 'none' },
|
|
232
|
+
cursor: hasBrandLink ? 'pointer' : 'default',
|
|
233
|
+
},
|
|
234
|
+
brandSx
|
|
235
|
+
)}
|
|
236
|
+
component={
|
|
237
|
+
hasBrandLink
|
|
238
|
+
? typeof resolvedHomeTo === 'string' && /^(https?:)?\/\//.test(resolvedHomeTo)
|
|
239
|
+
? 'a'
|
|
240
|
+
: (RouterLink as any)
|
|
241
|
+
: 'div'
|
|
242
|
+
}
|
|
243
|
+
{...(hasBrandLink && resolvedHomeTo
|
|
244
|
+
? typeof resolvedHomeTo === 'string' && /^(https?:)?\/\//.test(resolvedHomeTo)
|
|
245
|
+
? { href: resolvedHomeTo }
|
|
246
|
+
: { to: resolvedHomeTo }
|
|
247
|
+
: {})}
|
|
248
|
+
>
|
|
249
|
+
{brandVisual}
|
|
250
|
+
{showBrandLabel && title && (
|
|
251
|
+
<Typography variant="h6" noWrap component="div" sx={sxN({ color: theme.palette.text.secondary, fontWeight: 500 }, titleSx)}>
|
|
252
|
+
{title}
|
|
253
|
+
</Typography>
|
|
254
|
+
)}
|
|
255
|
+
</Box>
|
|
256
|
+
{/* Center Elements */}
|
|
257
|
+
{!isMobile && (
|
|
258
|
+
<Box sx={{ position: 'absolute', left: '50%', transform: 'translateX(-50%)', pointerEvents: 'none', color: theme.palette.text.secondary }}>
|
|
259
|
+
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1.25, pointerEvents: 'auto' }}>
|
|
260
|
+
{elementsCenter.map((item, idx) => {
|
|
261
|
+
if (item.type === 'link') return <TopBarLink showLabel={isDesktop} key={item.props.label ?? idx} {...item.props} />;
|
|
262
|
+
if (item.type === 'menu') return <TopBarMenu showLabel={isDesktop} key={item.props.label ?? idx} {...item.props} />;
|
|
263
|
+
if (item.type === 'action') return <TopBarAction key={idx} {...item.props} />;
|
|
264
|
+
return null;
|
|
265
|
+
})}
|
|
266
|
+
</Box>
|
|
267
|
+
</Box>
|
|
268
|
+
)}
|
|
269
|
+
{/* Right Elements */}
|
|
270
|
+
<Box sx={sxN({ display: 'flex', alignItems: 'center', flexShrink: 0, marginLeft: 'auto', gap: 1.25, pr: 1.5, color: theme.palette.text.secondary, transition: 'color 0.2s ease', '&:hover': { color: theme.palette.text.primary } }, linksSx)}>
|
|
271
|
+
{isMobile ? (
|
|
272
|
+
<>
|
|
273
|
+
{elementsCenter.length > 0 && (
|
|
274
|
+
<TopBarMenu label="" icon={collapsedIconCenter} items={buildCollapsedItems(elementsCenter)} showLabel={false} />
|
|
275
|
+
)}
|
|
276
|
+
{elementsRight.length > 0 && (
|
|
277
|
+
<TopBarMenu label="" icon={collapsedIconRight} items={buildCollapsedItems(elementsRight)} showLabel={false} />
|
|
278
|
+
)}
|
|
279
|
+
</>
|
|
280
|
+
) : (
|
|
281
|
+
elementsRight?.map((item, idx) => {
|
|
282
|
+
if (item.type === 'link') return <TopBarLink showLabel={isDesktop} key={item.props.label ?? idx} {...item.props} />;
|
|
283
|
+
if (item.type === 'menu') return <TopBarMenu showLabel={isDesktop} key={item.props.label ?? idx} {...item.props} />;
|
|
284
|
+
if (item.type === 'action') return <TopBarAction key={idx} {...item.props} />;
|
|
285
|
+
return null;
|
|
286
|
+
})
|
|
287
|
+
)}
|
|
288
|
+
</Box>
|
|
289
|
+
</Toolbar>
|
|
290
|
+
</AppBar>
|
|
291
|
+
);
|
|
292
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { SxProps, Theme } from '@mui/material/styles';
|
|
2
|
+
import type { AppBarProps } from '@mui/material/AppBar';
|
|
3
|
+
import type { TopBarLinkProps } from './components/TopBarLink/TopBarLink.types';
|
|
4
|
+
import type { TopBarMenuProps } from './components/TopBarMenu/TopBarMenu.types';
|
|
5
|
+
import type { TopBarActionProps } from './components/TopBarAction/TopBarAction.types';
|
|
6
|
+
|
|
7
|
+
export interface TopBarProps extends AppBarProps {
|
|
8
|
+
title?: string;
|
|
9
|
+
logo?: string;
|
|
10
|
+
elementsCenter?: TopBarElement[];
|
|
11
|
+
elementsRight?: TopBarElement[];
|
|
12
|
+
/** Icon name used when center elements are collapsed (mobile). Default: "settings". */
|
|
13
|
+
collapsedIconCenter?: string;
|
|
14
|
+
/** Icon name used when right elements are collapsed (mobile). Default: "more_horiz". */
|
|
15
|
+
collapsedIconRight?: string;
|
|
16
|
+
homeTo?: string | null;
|
|
17
|
+
sx?: SxProps<Theme>;
|
|
18
|
+
appBarSx?: SxProps<Theme>;
|
|
19
|
+
toolbarSx?: SxProps<Theme>;
|
|
20
|
+
brandSx?: SxProps<Theme>;
|
|
21
|
+
logoSx?: SxProps<Theme>;
|
|
22
|
+
titleSx?: SxProps<Theme>;
|
|
23
|
+
linksSx?: SxProps<Theme>;
|
|
24
|
+
linkSx?: SxProps<Theme>;
|
|
25
|
+
menuSx?: SxProps<Theme>;
|
|
26
|
+
menuItemSx?: SxProps<Theme>;
|
|
27
|
+
id?: string;
|
|
28
|
+
className?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export type TopBarElement =
|
|
32
|
+
| { type: 'link'; props: TopBarLinkProps }
|
|
33
|
+
| { type: 'menu'; props: TopBarMenuProps }
|
|
34
|
+
| { type: 'action'; props: TopBarActionProps };
|
|
35
|
+
|
|
36
|
+
export type TopBarResolverSpec = {
|
|
37
|
+
type: 'TopBar';
|
|
38
|
+
props?: TopBarProps;
|
|
39
|
+
};
|