this.gui 1.3.22 → 1.3.26
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/dist/this-gui.es.js +0 -1
- package/dist/this-gui.umd.js +65 -65
- package/index.ts +3 -2
- package/init/index.html +4 -5
- package/init/package-lock.json +2 -2
- package/init/package.json +1 -1
- package/init/src/App.tsx +24 -0
- package/init/src/index.css +16 -0
- package/init/src/main.tsx +14 -0
- package/init/src/router/DerivableRouter.tsx +36 -0
- package/package.json +1 -1
- package/src/GUI.tsx +15 -0
- package/src/components/generics/Cards/Gridme.jsx +52 -0
- package/src/components/generics/Cards/LilBox.jsx +65 -0
- package/src/components/generics/Cards/ModuleCard.jsx +106 -0
- package/src/components/generics/Chats/FullChatBot.jsx +223 -0
- package/src/components/generics/Code/CodeBlock.jsx +33 -0
- package/src/components/generics/Feedback/Callout.jsx +92 -0
- package/src/components/generics/Layout/GridX.jsx +29 -0
- package/src/components/generics/Layout/Hero2.jsx +132 -0
- package/src/components/generics/Layout/PageContainer.jsx +29 -0
- package/src/components/generics/Layout/PageDivider.jsx +20 -0
- package/src/components/generics/Layout/Section.jsx +43 -0
- package/src/components/generics/Layout/SectionHeader.jsx +21 -0
- package/src/components/generics/Media/Img.jsx +58 -0
- package/src/components/generics/Media/VideoEmbed.jsx +51 -0
- package/src/components/generics/Organization/TableOfContents.jsx +51 -0
- package/src/components/generics/Organization/Tabs.jsx +45 -0
- package/src/components/generics/Text/TextList.jsx +41 -0
- package/src/components/generics/Text/TextParagraph.jsx +28 -0
- package/src/components/generics/Text/TextQuote.jsx +23 -0
- package/src/components/generics/Text/TextTitle.jsx +44 -0
- package/src/gui/Layouts/ResponsiveUI/Content/Content.resolver.tsx +0 -0
- package/src/gui/Layouts/ResponsiveUI/Content/Content.stories.tsx +88 -0
- package/src/gui/Layouts/ResponsiveUI/Content/Content.tsx +53 -0
- package/src/gui/Layouts/ResponsiveUI/Content/Content.types.tsx +40 -0
- package/src/gui/Layouts/ResponsiveUI/Footer/Footer.resolver.tsx +45 -0
- package/src/gui/Layouts/ResponsiveUI/Footer/Footer.stories.tsx +209 -0
- package/src/gui/Layouts/ResponsiveUI/Footer/Footer.tsx +337 -0
- package/src/gui/Layouts/ResponsiveUI/Footer/Footer.types.ts +40 -0
- package/src/gui/Layouts/ResponsiveUI/Layout/Layout.resolver.tsx +37 -0
- package/src/gui/Layouts/ResponsiveUI/Layout/Layout.stories.tsx +290 -0
- package/src/gui/Layouts/ResponsiveUI/Layout/Layout.tsx +112 -0
- package/src/gui/Layouts/ResponsiveUI/Layout/Layout.types.ts +56 -0
- package/src/gui/Layouts/ResponsiveUI/Layout/useLayoutBreakpoints.ts +9 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/LeftSidebar/LeftSidebar.resolver.tsx +87 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/LeftSidebar/LeftSidebar.stories.tsx +199 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/LeftSidebar/LeftSidebar.tsx +311 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/LeftSidebar/LeftSidebar.types.ts +41 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/LeftSidebar/SidebarToggleButton.tsx +53 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/LeftSidebar/components/LeftSidebarAction/LeftSidebarAction.resolver.tsx +19 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/LeftSidebar/components/LeftSidebarAction/LeftSidebarAction.tsx +107 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/LeftSidebar/components/LeftSidebarLink/LeftSidebarLink.resolver.tsx +0 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/LeftSidebar/components/LeftSidebarLink/LeftSidebarLink.tsx +122 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/LeftSidebar/components/LeftSidebarLink/LeftSidebarLink.types.ts +13 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/LeftSidebar/components/LeftSidebarMenu/LeftSidebarMenu.tsx +142 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/LeftSidebar/components/LeftSidebarToggleButton/LeftSidebarToggleButton.tsx +23 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/RightSidebar/RightSidebar.resolver.tsx +35 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/RightSidebar/RightSidebar.stories.tsx +240 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/RightSidebar/RightSidebar.tsx +319 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/RightSidebar/RightSidebar.types.ts +17 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/RightSidebar/components/RightSidebarAction/RightSidebarAction.tsx +102 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/RightSidebar/components/RightSidebarLink/RightSidebarLink.tsx +132 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/RightSidebar/components/RightSidebarMenu/RightSidebarMenu.tsx +140 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/RightSidebar/components/RightSidebarToggleButton/RightSidebarToggleButton.tsx +22 -0
- package/src/gui/Layouts/ResponsiveUI/StickyOptions/StickyOptionsTop.stories.tsx +469 -0
- package/src/gui/Layouts/ResponsiveUI/StickyOptions/StickyOptionsTop.tsx +489 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/TopBar.resolver.tsx +86 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/TopBar.stories.tsx +350 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/TopBar.tsx +281 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/TopBar.types.ts +39 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/components/TopBarAction/TopBarAction.stories.tsx +83 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/components/TopBarAction/TopBarAction.tsx +18 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/components/TopBarAction/TopBarAction.types.ts +4 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/components/TopBarLink/TopBarLink.stories.tsx +189 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/components/TopBarLink/TopBarLink.tsx +30 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/components/TopBarLink/TopBarLink.types.ts +9 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/components/TopBarMenu/TopBarMenu.resolver.tsx +14 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/components/TopBarMenu/TopBarMenu.stories.tsx +56 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/components/TopBarMenu/TopBarMenu.tsx +123 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/components/TopBarMenu/TopBarMenu.types.ts +44 -0
- package/src/gui/Theme/GuiProvider.tsx +125 -0
- package/src/gui/Theme/Icon/Icon.resolver.tsx +29 -0
- package/src/gui/Theme/Icon/Icon.tsx +43 -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 +273 -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/apis/codegen.api.ts +38 -0
- package/src/gui/components/atoms/AppBar/AppBar.resolver.tsx +41 -0
- package/src/gui/components/atoms/AppBar/AppBar.stories.tsx +225 -0
- package/src/gui/components/atoms/AppBar/AppBar.tsx +8 -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/TextField/TextField.stories.tsx +28 -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.tsx +138 -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/HeroSection/HeroSection.stories.tsx +141 -0
- package/src/gui/components/molecules/HeroSection/HeroSection.tsx +152 -0
- package/src/gui/components/molecules/HeroSection/HeroSection.types.tsx +18 -0
- package/src/gui/components/molecules/ModalBox/ModalBox.resolver.tsx +38 -0
- package/src/gui/components/molecules/ModalBox/ModalBox.stories.tsx +82 -0
- package/src/gui/components/molecules/ModalBox/ModalBox.tsx +106 -0
- package/src/gui/components/molecules/ModalBox/ModalBox.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/organism/ChatGPTInterface/ChatGPTInterface.stories.tsx +17 -0
- package/src/gui/components/organism/ChatGPTInterface/ChatGPTInterface.tsx +71 -0
- package/src/gui/components/organism/RootDomain/RootDomain.stories.tsx +31 -0
- package/src/gui/components/organism/RootDomain/RootDomain.tsx +100 -0
- package/src/gui/components/organism/RootDomain/staticServices.ts +66 -0
- package/src/gui/components/window/Nodes/node.ts +0 -0
- package/src/gui/components/window/code/block/node.tsx +0 -0
- package/src/gui/components/window/code/hugging.face.api.ts +11 -0
- package/src/gui/components/window/connectors/index.ts +19 -0
- package/src/gui/components/window/window.stories.tsx +20 -0
- package/src/gui/components/window/window.tsx +633 -0
- package/src/gui/contexts/InsetsContext.tsx +38 -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/me/Logic.tsx +31 -0
- package/src/gui/me/Me.stories.tsx +8 -0
- package/src/gui/me/Me.tsx +197 -0
- package/src/gui/me/fundamentals/verbs/verbs.tsx +94 -0
- package/src/gui/me/modificators/Adjectives.ts +0 -0
- package/src/gui/me/modificators/Adverbs.ts +0 -0
- package/src/gui/me/modificators/Complements.ts +27 -0
- package/src/gui/me/utils/Context.tsx +14 -0
- package/src/gui/me/utils/hooks/useMe.js +37 -0
- package/src/gui/utils/nodeID.ts +11 -0
- package/src/registry/GuiRegistry.ts +19 -0
- package/src/registry/factory.ts +12 -0
- package/src/registry/index.ts +3 -0
- package/src/registry/types.ts +6 -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/types/gui.d.ts +67 -0
- package/src/types/theme.d.ts +191 -0
- package/src/types/viewport.ts +132 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import ThemeModeToggle from './ThemeModeToggle';
|
|
2
|
+
import { ThemeModeToggleResolverSpec } from './ThemeModeToggle.types';
|
|
3
|
+
/**
|
|
4
|
+
* Resolver for ThemeModeToggle
|
|
5
|
+
* ----------------------------
|
|
6
|
+
* Allows you to render the ThemeModeToggle from a plain JSON/config object.
|
|
7
|
+
*
|
|
8
|
+
* Minimal accepted shape:
|
|
9
|
+
* {
|
|
10
|
+
* "type": "ThemeModeToggle",
|
|
11
|
+
* "props": {
|
|
12
|
+
* "variant": "minimal" | "switchMinimal" | "switchWithLabel",
|
|
13
|
+
* "show": "icons" | "label" | "both",
|
|
14
|
+
* "id": "optional-id",
|
|
15
|
+
* "className": "optional-class",
|
|
16
|
+
* "data-testid": "test-id",
|
|
17
|
+
* // Optional granular styling
|
|
18
|
+
* "sx": { root styles },
|
|
19
|
+
* "iconSx": { icons styles },
|
|
20
|
+
* "switchSx": { switch styles (variant='switch') },
|
|
21
|
+
* "labelSx": { label Typography styles }
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
export function resolveThemeModeToggle(p: ThemeModeToggleResolverSpec = {}) {
|
|
27
|
+
const {
|
|
28
|
+
variant = 'minimal',
|
|
29
|
+
show = 'icons',
|
|
30
|
+
id,
|
|
31
|
+
className,
|
|
32
|
+
['data-testid']: dataTestId,
|
|
33
|
+
sx,
|
|
34
|
+
iconSx,
|
|
35
|
+
switchSx,
|
|
36
|
+
labelSx,
|
|
37
|
+
switchSize,
|
|
38
|
+
iconSize,
|
|
39
|
+
} = p;
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<ThemeModeToggle
|
|
43
|
+
variant={variant}
|
|
44
|
+
show={show}
|
|
45
|
+
id={id}
|
|
46
|
+
className={className}
|
|
47
|
+
data-testid={dataTestId}
|
|
48
|
+
sx={sx}
|
|
49
|
+
iconSx={iconSx}
|
|
50
|
+
switchSx={switchSx}
|
|
51
|
+
labelSx={labelSx}
|
|
52
|
+
switchSize={switchSize}
|
|
53
|
+
iconSize={iconSize}
|
|
54
|
+
/>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export default resolveThemeModeToggle;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import ThemeModeToggle from './ThemeModeToggle';
|
|
3
|
+
|
|
4
|
+
// ======================= Meta =======================
|
|
5
|
+
const meta: Meta<typeof ThemeModeToggle> = {
|
|
6
|
+
title: 'Theme/ThemeModeToggle',
|
|
7
|
+
component: ThemeModeToggle,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
decorators: [
|
|
10
|
+
(Story) => (
|
|
11
|
+
<div style={{ padding: 24, minHeight: 160, display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
|
|
12
|
+
<Story />
|
|
13
|
+
</div>
|
|
14
|
+
),
|
|
15
|
+
],
|
|
16
|
+
parameters: {
|
|
17
|
+
docs: {
|
|
18
|
+
description: {
|
|
19
|
+
component: `
|
|
20
|
+
The **ThemeModeToggle** is a theme control molecule that allows users to toggle between **light**, **dark**, and optionally **system** themes in a UI.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
## What it does
|
|
24
|
+
ThemeModeToggle provides a way to change the global color mode of the app via UI toggles. It connects with \`useThemeMode\` from This.GUI, so any updates reflect instantly in your theme context.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
## Visual Variants
|
|
28
|
+
This component supports multiple visual representations depending on how much context or control you want to show the user:
|
|
29
|
+
|
|
30
|
+
- **minimal**: Just a clickable icon (uses IconButton).
|
|
31
|
+
- **switchMinimal**: Shows a switch with sun/moon icons.
|
|
32
|
+
- **switchWithLabel**: Shows the switch, icons, and a label that updates dynamically between "Light" and "Dark".
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
## Props
|
|
36
|
+
- \`variant?: 'minimal' | 'switchMinimal' | 'switchWithLabel'\`
|
|
37
|
+
- Determines the UI structure.
|
|
38
|
+
- \`show?: 'icons' | 'label' | 'both'\`
|
|
39
|
+
- For \`variant="minimal"\` only. Controls whether to show icon, label or both.
|
|
40
|
+
- \`switchSize?: 'small' | 'medium'\` — size of the MUI Switch.
|
|
41
|
+
- \`iconSize?: 'small' | 'medium' | 'large'\` — size of the icons.
|
|
42
|
+
- \`sx\`, \`iconSx\`, \`switchSx\`, \`labelSx\` — MUI system styling overrides.
|
|
43
|
+
- \`id\`, \`className\`, \`data-testid\` — standard element props.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
## Internal Logic
|
|
47
|
+
- Uses \`useThemeContext()\` to read current mode (\`light\` or \`dark\`) and the \`toggleMode()\` handler.
|
|
48
|
+
- Dynamically determines whether current mode is \`light\` or not to drive the state of the UI (like whether switch is \`checked\` or not).
|
|
49
|
+
- Automatically updates \`labelText\` based on the mode.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
## Usage Examples
|
|
53
|
+
|
|
54
|
+
### Basic usage in React:
|
|
55
|
+
~~~tsx
|
|
56
|
+
<ThemeModeToggle variant="minimal" />
|
|
57
|
+
<ThemeModeToggle variant="switchMinimal" />
|
|
58
|
+
<ThemeModeToggle variant="switchWithLabel" />
|
|
59
|
+
~~~
|
|
60
|
+
|
|
61
|
+
### Declarative JSON usage:
|
|
62
|
+
~~~json
|
|
63
|
+
{
|
|
64
|
+
"type": "ThemeModeToggle",
|
|
65
|
+
"props": {
|
|
66
|
+
"variant": "switchWithLabel",
|
|
67
|
+
"iconSize": "medium",
|
|
68
|
+
"switchSize": "small",
|
|
69
|
+
"sx": { "ml": 2 }
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
~~~
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
## Design Notes
|
|
76
|
+
This component is designed to be:
|
|
77
|
+
- **Declarative-first**: usable directly from This.GUI config structures.
|
|
78
|
+
- **Minimal footprint**: all styling is optional and overrideable.
|
|
79
|
+
- **Context-integrated**: updates global theme state through context, not local component state.
|
|
80
|
+
|
|
81
|
+
Ideal for UIs where users are expected to switch theme modes or where accessible, theme-aware interfaces are critical.
|
|
82
|
+
`,
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
argTypes: {
|
|
87
|
+
variant: {
|
|
88
|
+
control: { type: 'radio' },
|
|
89
|
+
options: ['minimal', 'switch'],
|
|
90
|
+
},
|
|
91
|
+
sx: {
|
|
92
|
+
control: 'object',
|
|
93
|
+
description: 'MUI system style overrides.',
|
|
94
|
+
},
|
|
95
|
+
show: {
|
|
96
|
+
control: { type: 'radio' },
|
|
97
|
+
options: ['icons', 'label', 'both'],
|
|
98
|
+
description: 'Controls whether to show icons, label, or both.',
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
args: {
|
|
102
|
+
variant: 'minimal',
|
|
103
|
+
sx: {},
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export default meta;
|
|
108
|
+
type Story = StoryObj<typeof ThemeModeToggle>;
|
|
109
|
+
|
|
110
|
+
// ======================= Stories =======================
|
|
111
|
+
|
|
112
|
+
export const Playground: Story = {
|
|
113
|
+
render: (args) => <ThemeModeToggle {...args} />,
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export const Variants: Story = {
|
|
117
|
+
render: () => (
|
|
118
|
+
<div style={{ display: 'flex', gap: 24, flexDirection: 'column' }}>
|
|
119
|
+
<div>
|
|
120
|
+
<h4>minimal (icon only)</h4>
|
|
121
|
+
<ThemeModeToggle variant="minimal" />
|
|
122
|
+
</div>
|
|
123
|
+
<div>
|
|
124
|
+
<h4>switchMinimal (switch with icons)</h4>
|
|
125
|
+
<ThemeModeToggle variant="switchMinimal" show="icons" />
|
|
126
|
+
</div>
|
|
127
|
+
<div>
|
|
128
|
+
<h4>switchWithLabel (switch with icons + label)</h4>
|
|
129
|
+
<ThemeModeToggle variant="switchWithLabel" show="both" />
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
132
|
+
),
|
|
133
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { IconButton, Switch } from '@/gui/components/atoms';
|
|
3
|
+
import Icon from '@/gui/Theme/Icon/Icon';
|
|
4
|
+
import { useThemeContext } from '@/gui/Theme';
|
|
5
|
+
import { Typography, Box } from '@/gui/components/atoms';
|
|
6
|
+
import type { ThemeModeToggleProps } from './ThemeModeToggle.types';
|
|
7
|
+
|
|
8
|
+
const ThemeModeToggle: React.FC<ThemeModeToggleProps> = ({
|
|
9
|
+
variant = 'minimal',
|
|
10
|
+
show = 'icons',
|
|
11
|
+
switchSize = 'medium',
|
|
12
|
+
iconSize = 'medium',
|
|
13
|
+
sx,
|
|
14
|
+
iconSx,
|
|
15
|
+
switchSx,
|
|
16
|
+
labelSx,
|
|
17
|
+
id,
|
|
18
|
+
className,
|
|
19
|
+
['data-testid']: dataTestId,
|
|
20
|
+
}) => {
|
|
21
|
+
const { mode, toggleMode } = useThemeContext();
|
|
22
|
+
const isLight = mode === 'light';
|
|
23
|
+
const labelText = isLight ? 'Light' : 'Dark';
|
|
24
|
+
const iconFontSize = {
|
|
25
|
+
small: '1rem',
|
|
26
|
+
medium: '1.5rem',
|
|
27
|
+
large: '2rem',
|
|
28
|
+
}[iconSize];
|
|
29
|
+
|
|
30
|
+
const handleToggle = () => {
|
|
31
|
+
toggleMode();
|
|
32
|
+
};
|
|
33
|
+
if (variant === 'switchMinimal' || variant === 'switchWithLabel') {
|
|
34
|
+
return (
|
|
35
|
+
<Box
|
|
36
|
+
id={id}
|
|
37
|
+
display="flex"
|
|
38
|
+
alignItems="center"
|
|
39
|
+
sx={sx ? ([{ cursor: 'pointer' }, sx] as any) : ({ cursor: 'pointer' } as any)}
|
|
40
|
+
className={className}
|
|
41
|
+
data-testid={dataTestId}
|
|
42
|
+
>
|
|
43
|
+
{/* Always show icons for both switch variants */}
|
|
44
|
+
<Icon
|
|
45
|
+
name="light_mode"
|
|
46
|
+
iconColor={isLight ? 'primary' : 'disabled'}
|
|
47
|
+
fontSize={iconFontSize}
|
|
48
|
+
/>
|
|
49
|
+
<Switch
|
|
50
|
+
checked={!isLight}
|
|
51
|
+
onChange={handleToggle}
|
|
52
|
+
color="primary"
|
|
53
|
+
size={switchSize}
|
|
54
|
+
inputProps={{ 'aria-label': 'toggle theme mode' }}
|
|
55
|
+
sx={switchSx}
|
|
56
|
+
/>
|
|
57
|
+
<Icon
|
|
58
|
+
name="dark_mode"
|
|
59
|
+
iconColor={!isLight ? 'primary' : 'disabled'}
|
|
60
|
+
fontSize={iconFontSize}
|
|
61
|
+
/>
|
|
62
|
+
{variant === 'switchWithLabel' && (
|
|
63
|
+
<Typography
|
|
64
|
+
sx={
|
|
65
|
+
labelSx
|
|
66
|
+
? ([{ ml: 1 }, labelSx] as any)
|
|
67
|
+
: ({ ml: 1 } as any)
|
|
68
|
+
}
|
|
69
|
+
>
|
|
70
|
+
{labelText}
|
|
71
|
+
</Typography>
|
|
72
|
+
)}
|
|
73
|
+
</Box>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// variant === 'minimal'
|
|
78
|
+
return (
|
|
79
|
+
<IconButton id={id} onClick={handleToggle} color="inherit" aria-label="toggle theme mode" size={iconSize} className={className} data-testid={dataTestId} sx={sx}>
|
|
80
|
+
{show !== 'label' &&
|
|
81
|
+
(isLight ? (
|
|
82
|
+
<Icon name="light_mode" iconColor="primary" fontSize={iconFontSize} />
|
|
83
|
+
) : (
|
|
84
|
+
<Icon name="dark_mode" iconColor="primary" fontSize={iconFontSize} />
|
|
85
|
+
))}
|
|
86
|
+
{(show === 'label' || show === 'both') && (
|
|
87
|
+
<Typography
|
|
88
|
+
sx={
|
|
89
|
+
labelSx
|
|
90
|
+
? ([{ ml: show === 'both' ? 1 : 0 }, labelSx] as any)
|
|
91
|
+
: ({ ml: show === 'both' ? 1 : 0 } as any)
|
|
92
|
+
}
|
|
93
|
+
>
|
|
94
|
+
{labelText}
|
|
95
|
+
</Typography>
|
|
96
|
+
)}
|
|
97
|
+
</IconButton>
|
|
98
|
+
);
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export default ThemeModeToggle;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { SxProps, Theme } from '@mui/material/styles';
|
|
2
|
+
export type ThemeModeToggleProps = {
|
|
3
|
+
variant?: 'minimal' | 'switchMinimal' | 'switchWithLabel';
|
|
4
|
+
show?: 'icons' | 'label' | 'both';
|
|
5
|
+
id?: string;
|
|
6
|
+
className?: string;
|
|
7
|
+
['data-testid']?: string;
|
|
8
|
+
sx?: SxProps<Theme>;
|
|
9
|
+
iconSx?: SxProps<Theme>;
|
|
10
|
+
switchSx?: SxProps<Theme>;
|
|
11
|
+
labelSx?: SxProps<Theme>;
|
|
12
|
+
switchSize?: 'small' | 'medium';
|
|
13
|
+
iconSize?: 'small' | 'medium' | 'large';
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type ThemeModeToggleResolverSpec = {
|
|
17
|
+
type?: 'ThemeModeToggle';
|
|
18
|
+
variant?: 'minimal' | 'switchMinimal' | 'switchWithLabel';
|
|
19
|
+
show?: 'icons' | 'label' | 'both';
|
|
20
|
+
id?: string;
|
|
21
|
+
className?: string;
|
|
22
|
+
['data-testid']?: string;
|
|
23
|
+
sx?: SxProps<Theme>;
|
|
24
|
+
iconSx?: SxProps<Theme>;
|
|
25
|
+
switchSx?: SxProps<Theme>;
|
|
26
|
+
labelSx?: SxProps<Theme>;
|
|
27
|
+
switchSize?: 'small' | 'medium';
|
|
28
|
+
iconSize?: 'small' | 'medium' | 'large';
|
|
29
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import ThemesCatalog from './ThemesCatalog';
|
|
2
|
+
import type { ThemesCatalogResolverSpec } from './ThemesCatalog.types';
|
|
3
|
+
|
|
4
|
+
const resolver = {
|
|
5
|
+
type: 'ThemesCatalog',
|
|
6
|
+
resolve: (props?: ThemesCatalogResolverSpec) => {
|
|
7
|
+
const { variant, sx } = props || {};
|
|
8
|
+
return {
|
|
9
|
+
component: () => <ThemesCatalog variant={variant} sx={sx} />,
|
|
10
|
+
props,
|
|
11
|
+
};
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default resolver;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import ThemesCatalog from './ThemesCatalog';
|
|
3
|
+
|
|
4
|
+
// ======================= Meta =======================
|
|
5
|
+
const meta: Meta<typeof ThemesCatalog> = {
|
|
6
|
+
title: 'Theme/ThemesCatalog',
|
|
7
|
+
component: ThemesCatalog,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
decorators: [
|
|
10
|
+
(Story) => (
|
|
11
|
+
<div style={{ padding: 16, minHeight: 320 }}>
|
|
12
|
+
<Story />
|
|
13
|
+
</div>
|
|
14
|
+
),
|
|
15
|
+
],
|
|
16
|
+
parameters: {
|
|
17
|
+
docs: {
|
|
18
|
+
description: {
|
|
19
|
+
component: `
|
|
20
|
+
The **ThemesCatalog** component renders a visual interface to explore and select available GUI themes for your application.
|
|
21
|
+
|
|
22
|
+
It fetches all theme configurations from the \`getGuiThemes()\` utility and displays them using a visually rich card interface. You can toggle between **grid** and **list** layouts and switch between light/dark previews per theme. When a theme is selected, it is applied globally via the context provided by \`useThemeContext()\`.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
## Features
|
|
26
|
+
- Visual layout for theme browsing.
|
|
27
|
+
- Switch between **grid** and **list** variants.
|
|
28
|
+
- Light/dark mode preview toggle.
|
|
29
|
+
- Swatches preview for key palette values: \`primary\`, \`secondary\`, and \`background\`.
|
|
30
|
+
- Selectable themes that apply across your GUI via context.
|
|
31
|
+
- JSON-compatible configuration for declarative UI building.
|
|
32
|
+
- Fully themed with **This.GUI** primitives.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
## Props
|
|
36
|
+
- \`variant?: 'grid' | 'list'\` — controls layout format. Defaults to \`grid\`.
|
|
37
|
+
- \`sx?: SxProps\` — accepts style overrides via MUI’s \`sx\` prop.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
## Basic Usage
|
|
41
|
+
~~~jsx
|
|
42
|
+
<ThemesCatalog variant="grid" />
|
|
43
|
+
<ThemesCatalog variant="list" />
|
|
44
|
+
~~~
|
|
45
|
+
|
|
46
|
+
## Declarative JSON Configuration
|
|
47
|
+
~~~json
|
|
48
|
+
{
|
|
49
|
+
"type": "ThemesCatalog",
|
|
50
|
+
"props": {
|
|
51
|
+
"variant": "list"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
~~~
|
|
55
|
+
|
|
56
|
+
This component is ideal for apps that allow users to select their visual theme from a set of predefined theme options. It pairs well with This.GUI’s theme management context and is useful in both developer-facing configuration tools and end-user customization interfaces.
|
|
57
|
+
`,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
argTypes: {
|
|
62
|
+
variant: {
|
|
63
|
+
control: { type: 'radio' },
|
|
64
|
+
options: ['grid', 'list'],
|
|
65
|
+
description: 'Choose layout variant',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
args: {
|
|
69
|
+
variant: 'grid',
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default meta;
|
|
74
|
+
type Story = StoryObj<typeof ThemesCatalog>;
|
|
75
|
+
|
|
76
|
+
// ======================= Stories =======================
|
|
77
|
+
export const Playground: Story = {
|
|
78
|
+
args: {
|
|
79
|
+
variant: 'grid',
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export const ListVariant: Story = {
|
|
84
|
+
name: 'List layout',
|
|
85
|
+
args: {
|
|
86
|
+
variant: 'list',
|
|
87
|
+
},
|
|
88
|
+
};
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
// ThemesCatalog.tsx
|
|
2
|
+
import type { SxProps, Theme } from '@mui/material/styles';
|
|
3
|
+
import type { ThemesCatalogProps } from './ThemesCatalog.types';
|
|
4
|
+
import { getGuiThemes } from '@/gui/Theme/utils/catalog';
|
|
5
|
+
import type { ThemeManifest } from '@/types/theme';
|
|
6
|
+
import Grid from '@/gui/components/atoms/Grid/Grid';
|
|
7
|
+
import Card from '@/gui/components/atoms/Card/Card';
|
|
8
|
+
import CardHeader from '@/gui/components/atoms/CardHeader/CardHeader';
|
|
9
|
+
import CardContent from '@/gui/components/atoms/CardContent/CardContent';
|
|
10
|
+
import CardActions from '@/gui/components/atoms/CardActions/CardActions';
|
|
11
|
+
import Typography from '@/gui/components/atoms/Typography/Typography';
|
|
12
|
+
import Box from '@/gui/components/atoms/Box/Box';
|
|
13
|
+
import Avatar from '@/gui/components/atoms/Avatar/Avatar';
|
|
14
|
+
import Checkbox from '@mui/material/Checkbox';
|
|
15
|
+
import Tooltip from '@mui/material/Tooltip';
|
|
16
|
+
import MuiSwitch from '@mui/material/Switch';
|
|
17
|
+
import Icon from '@/gui/Theme/Icon/Icon';
|
|
18
|
+
import { useThemeContext } from '@/gui/contexts/ThemeContext';
|
|
19
|
+
function getPreviewSwatches(item: ThemeManifest) {
|
|
20
|
+
const swatches = [];
|
|
21
|
+
const lightMode = item.mode?.light;
|
|
22
|
+
if (typeof lightMode === 'object' && lightMode?.palette) {
|
|
23
|
+
if (lightMode.palette.primary?.main) {
|
|
24
|
+
swatches.push({ label: 'Primary', value: lightMode.palette.primary.main });
|
|
25
|
+
}
|
|
26
|
+
if (lightMode.palette.secondary?.main) {
|
|
27
|
+
swatches.push({ label: 'Secondary', value: lightMode.palette.secondary.main });
|
|
28
|
+
}
|
|
29
|
+
if (lightMode.palette.background?.default) {
|
|
30
|
+
swatches.push({ label: 'Background', value: lightMode.palette.background.default });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return swatches;
|
|
34
|
+
}
|
|
35
|
+
export default function ThemesCatalog({ sx, variant = 'grid' }: ThemesCatalogProps = {}) {
|
|
36
|
+
const themes = getGuiThemes();
|
|
37
|
+
const { setMode, mode: activeMode, themeId, setThemeId } = useThemeContext();
|
|
38
|
+
if (!themes || themes.length === 0) {
|
|
39
|
+
return <Typography>No themes available.</Typography>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Shared card rendering logic as a helper
|
|
43
|
+
const ThemeCard = ({ theme }: { theme: ThemeManifest }) => {
|
|
44
|
+
const light = Boolean(theme.mode?.light);
|
|
45
|
+
const dark = Boolean(theme.mode?.dark);
|
|
46
|
+
const isDarkSelected = activeMode === 'dark';
|
|
47
|
+
return (
|
|
48
|
+
<Box sx={{ position: 'relative' }}>
|
|
49
|
+
<Card
|
|
50
|
+
sx={{
|
|
51
|
+
p: 1,
|
|
52
|
+
display: 'flex',
|
|
53
|
+
flexDirection: 'column',
|
|
54
|
+
justifyContent: 'space-between',
|
|
55
|
+
backgroundColor: 'background.default',
|
|
56
|
+
border: (theme.mode.light as any).palette?.primary?.main
|
|
57
|
+
? `1px solid ${(theme.mode.light as any).palette.primary.main}`
|
|
58
|
+
: '1px solid rgba(0,0,0,0.04)',
|
|
59
|
+
borderRadius: 1.5,
|
|
60
|
+
boxShadow: 'none',
|
|
61
|
+
height: '100%',
|
|
62
|
+
gap: 0.25,
|
|
63
|
+
}}
|
|
64
|
+
>
|
|
65
|
+
<CardHeader
|
|
66
|
+
sx={{ mb: 0, '& .MuiCardHeader-content': { overflow: 'hidden' } }}
|
|
67
|
+
avatar={
|
|
68
|
+
theme.badgeUrl ? (
|
|
69
|
+
<Avatar src={theme.badgeUrl} alt={theme.themeName} />
|
|
70
|
+
) : (
|
|
71
|
+
<Avatar>{theme.themeName?.[0] ?? 'T'}</Avatar>
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
title={theme.themeName}
|
|
75
|
+
subheader={theme.author}
|
|
76
|
+
/>
|
|
77
|
+
<Box sx={{ display: 'flex', gap: 0.75, flexWrap: 'wrap', mt: 1 }}>
|
|
78
|
+
{getPreviewSwatches(theme).map((sw, i) => (
|
|
79
|
+
<Tooltip key={`${theme.themeId}-swatch-${i}`} title={sw.label}>
|
|
80
|
+
<Box
|
|
81
|
+
sx={{
|
|
82
|
+
width: 14,
|
|
83
|
+
height: 14,
|
|
84
|
+
borderRadius: 1,
|
|
85
|
+
...(String(sw.value).includes('gradient')
|
|
86
|
+
? { background: sw.value }
|
|
87
|
+
: { bgcolor: sw.value }),
|
|
88
|
+
border: '1px solid rgba(0,0,0,0.2)',
|
|
89
|
+
}}
|
|
90
|
+
/>
|
|
91
|
+
</Tooltip>
|
|
92
|
+
))}
|
|
93
|
+
</Box>
|
|
94
|
+
<Box sx={{ position: 'absolute', top: 8, right: 8 }}>
|
|
95
|
+
<Checkbox
|
|
96
|
+
size="small"
|
|
97
|
+
color="primary"
|
|
98
|
+
checked={theme.themeId === themeId}
|
|
99
|
+
onChange={() => {
|
|
100
|
+
if (typeof setThemeId === 'function') {
|
|
101
|
+
setThemeId(theme.themeId ?? '');
|
|
102
|
+
}
|
|
103
|
+
if (typeof setMode === 'function') {
|
|
104
|
+
const fallbackMode: 'light' | 'dark' = theme.defaultMode === 'dark' ? 'dark' : 'light';
|
|
105
|
+
setMode(fallbackMode);
|
|
106
|
+
}
|
|
107
|
+
}}
|
|
108
|
+
sx={{
|
|
109
|
+
p: 0.5,
|
|
110
|
+
backgroundColor: 'background.paper',
|
|
111
|
+
borderRadius: 1,
|
|
112
|
+
}}
|
|
113
|
+
/>
|
|
114
|
+
</Box>
|
|
115
|
+
<CardContent sx={{ p: 0.75, pt: 0.25 }}>
|
|
116
|
+
<Typography variant="body2" color="text.secondary">
|
|
117
|
+
{theme.description}
|
|
118
|
+
</Typography>
|
|
119
|
+
{theme.themeId === themeId && (
|
|
120
|
+
<Box sx={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center', mt: 0.5, mb: 0.25 }}>
|
|
121
|
+
<Icon name="light_mode" style={{ opacity: light ? 1 : 0.4 }} />
|
|
122
|
+
<MuiSwitch
|
|
123
|
+
size="small"
|
|
124
|
+
checked={isDarkSelected}
|
|
125
|
+
disabled={!light || !dark}
|
|
126
|
+
onChange={(e) => {
|
|
127
|
+
const checked = e.target.checked;
|
|
128
|
+
const nextMode = checked ? 'dark' : 'light';
|
|
129
|
+
if (typeof setMode === 'function') {
|
|
130
|
+
try { setMode(nextMode); } catch {}
|
|
131
|
+
}
|
|
132
|
+
}}
|
|
133
|
+
inputProps={{ 'aria-label': 'Toggle light/dark mode' }}
|
|
134
|
+
/>
|
|
135
|
+
<Icon name="dark_mode" style={{ opacity: dark ? 1 : 0.4 }} />
|
|
136
|
+
</Box>
|
|
137
|
+
)}
|
|
138
|
+
</CardContent>
|
|
139
|
+
<CardActions>
|
|
140
|
+
</CardActions>
|
|
141
|
+
</Card>
|
|
142
|
+
</Box>
|
|
143
|
+
);
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
if (variant === 'list') {
|
|
147
|
+
return (
|
|
148
|
+
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2, ...sx }}>
|
|
149
|
+
{themes.map((theme: ThemeManifest) => (
|
|
150
|
+
<Box key={theme.themeId}>
|
|
151
|
+
<ThemeCard theme={theme} />
|
|
152
|
+
</Box>
|
|
153
|
+
))}
|
|
154
|
+
</Box>
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return (
|
|
159
|
+
<Grid container spacing={2} sx={sx}>
|
|
160
|
+
{themes.map((theme: ThemeManifest) => (
|
|
161
|
+
<Grid item key={theme.themeId} xs={12} sm={6} md={4} lg={3}>
|
|
162
|
+
<ThemeCard theme={theme} />
|
|
163
|
+
</Grid>
|
|
164
|
+
))}
|
|
165
|
+
</Grid>
|
|
166
|
+
);
|
|
167
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { SxProps, Theme } from '@mui/system';
|
|
2
|
+
export type ThemesCatalogVariant = 'grid' | 'list';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Props passed directly to the ThemesCatalog React component.
|
|
6
|
+
*/
|
|
7
|
+
export interface ThemesCatalogProps {
|
|
8
|
+
/**
|
|
9
|
+
* Whether to display the themes as a grid or list.
|
|
10
|
+
*/
|
|
11
|
+
variant?: ThemesCatalogVariant;
|
|
12
|
+
/**
|
|
13
|
+
* Custom styles for the component container.
|
|
14
|
+
*/
|
|
15
|
+
sx?: SxProps<Theme>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* JSON/declarative spec for ThemesCatalog used in resolvers.
|
|
20
|
+
* This is the shape accepted by the resolver when rendering via config.
|
|
21
|
+
*/
|
|
22
|
+
export interface ThemesCatalogResolverSpec {
|
|
23
|
+
type?: 'ThemesCatalog';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Whether to render the themes in a grid or list layout.
|
|
27
|
+
*/
|
|
28
|
+
variant?: ThemesCatalogVariant;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Styles applied to the root element.
|
|
32
|
+
*/
|
|
33
|
+
sx?: SxProps<Theme>;
|
|
34
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import ChatGPTInterface from "./ChatGPTInterface";
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof ChatGPTInterface> = {
|
|
5
|
+
title: "Organisms/ChatGPTInterface",
|
|
6
|
+
component: ChatGPTInterface,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: "fullscreen",
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export default meta;
|
|
13
|
+
type Story = StoryObj<typeof ChatGPTInterface>;
|
|
14
|
+
|
|
15
|
+
export const Default: Story = {
|
|
16
|
+
render: () => <ChatGPTInterface />,
|
|
17
|
+
};
|