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,263 @@
|
|
|
1
|
+
// src/gui/atoms/Box/Box.stories.tsx
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import { Box, Link, Typography, Button } from '@/gui/components/atoms';
|
|
4
|
+
// ======================= Meta =======================
|
|
5
|
+
const meta: Meta<typeof Box> = {
|
|
6
|
+
title: 'Atoms/Containers/Box',
|
|
7
|
+
component: Box,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
decorators: [
|
|
10
|
+
(Story) => (
|
|
11
|
+
<div style={{ padding: 16, minHeight: 240 }}>
|
|
12
|
+
<Story />
|
|
13
|
+
</div>
|
|
14
|
+
),
|
|
15
|
+
],
|
|
16
|
+
parameters: {
|
|
17
|
+
docs: {
|
|
18
|
+
description: {
|
|
19
|
+
component: `
|
|
20
|
+
**Box** is a thin wrapper around MUI's \`Box\` that preserves **polymorphism** and integrates with **This.GUI** theming.
|
|
21
|
+
Use it as your default layout primitive: spacing, flex/grid, backgrounds, borders, etc.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
## Features
|
|
25
|
+
- **Polymorphic**: \`component\` (or \`as\`) can be an element tag (e.g. \`'section'\`, \`'img'\`, \`'a'\`) or a component (e.g. This.GUI \`Link\`).
|
|
26
|
+
- **Routing-friendly**: when using \`component={Link}\` you can pass \`to\`; anchors use \`href\`.
|
|
27
|
+
- **System props** & **sx**: use MUI system (p, m, display, gap, flex, grid, etc.) and the \`sx\` prop for deep styling.
|
|
28
|
+
- **Image mode**: if \`component="img"\`, you can pass \`src\`, \`alt\`, \`width\`, \`height\`, \`loading\`, \`decoding\`, \`referrerPolicy\`, \`sizes\`, \`srcSet\`.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
## Key Props
|
|
32
|
+
- \`component?: ElementType | string\` / \`as?: ElementType | string\`
|
|
33
|
+
- \`to?: string\` (when \`component={Link}\`)
|
|
34
|
+
- \`href?: string\` (when \`component="a"\`)
|
|
35
|
+
- \`sx?: SxProps\` + all MUI system props (e.g. \`p\`, \`m\`, \`display\`, \`gap\`)
|
|
36
|
+
- **Image-only extras** (when \`component="img"\`): \`src\`, \`alt\`, \`width\`, \`height\`, \`loading\`, \`decoding\`, \`referrerPolicy\`, \`sizes\`, \`srcSet\`.
|
|
37
|
+
|
|
38
|
+
> We don't expose \`component\`, \`to\`, \`href\` as Storybook controls—see the dedicated stories below.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
## Basic usage
|
|
42
|
+
~~~jsx
|
|
43
|
+
import { Box } from '@/gui/atoms';
|
|
44
|
+
|
|
45
|
+
<Box p={2} sx={{ border: '1px solid', borderColor: 'divider', borderRadius: 1 }}>
|
|
46
|
+
Content
|
|
47
|
+
</Box>
|
|
48
|
+
~~~
|
|
49
|
+
|
|
50
|
+
## Polymorphic (as a section)
|
|
51
|
+
~~~jsx
|
|
52
|
+
<Box component="section" p={2}>Section content</Box>
|
|
53
|
+
~~~
|
|
54
|
+
|
|
55
|
+
## Router link target
|
|
56
|
+
~~~jsx
|
|
57
|
+
import { Box, Link } from '@/gui/atoms';
|
|
58
|
+
|
|
59
|
+
<Box component={Link} to="/docs" p={1} sx={{ display: 'inline-block' }}>
|
|
60
|
+
Go to docs
|
|
61
|
+
</Box>
|
|
62
|
+
~~~
|
|
63
|
+
|
|
64
|
+
## Image mode
|
|
65
|
+
~~~jsx
|
|
66
|
+
<Box component="img" src="/logo.png" alt="Logo" sx={{ width: 120, height: 'auto' }} />
|
|
67
|
+
~~~
|
|
68
|
+
|
|
69
|
+
## Declarative JSON / Config usage
|
|
70
|
+
~~~json
|
|
71
|
+
{
|
|
72
|
+
"type": "Box",
|
|
73
|
+
"props": {
|
|
74
|
+
"component": "section",
|
|
75
|
+
"p": 2,
|
|
76
|
+
"sx": { "border": "1px solid", "borderColor": "divider", "borderRadius": 8 },
|
|
77
|
+
"children": "Section content"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
~~~
|
|
81
|
+
`,
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
controls: {
|
|
85
|
+
exclude: ['component', 'as', 'to', 'href', 'sx'],
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
argTypes: {
|
|
89
|
+
// System props examples (you can add more if useful)
|
|
90
|
+
p: { control: { type: 'number' }, description: 'Padding (system prop)' },
|
|
91
|
+
m: { control: { type: 'number' }, description: 'Margin (system prop)' },
|
|
92
|
+
display: {
|
|
93
|
+
control: { type: 'select' },
|
|
94
|
+
options: ['block', 'inline-block', 'flex', 'grid', 'inline-flex', 'inline', 'none'],
|
|
95
|
+
},
|
|
96
|
+
gap: { control: { type: 'number' } },
|
|
97
|
+
},
|
|
98
|
+
args: {
|
|
99
|
+
p: 2,
|
|
100
|
+
display: 'block',
|
|
101
|
+
children: 'Box content',
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
export default meta;
|
|
105
|
+
|
|
106
|
+
type Story = StoryObj<typeof Box>;
|
|
107
|
+
|
|
108
|
+
// ======================= Stories =======================
|
|
109
|
+
export const Playground: Story = {};
|
|
110
|
+
|
|
111
|
+
export const LayoutBasics: Story = {
|
|
112
|
+
name: 'Layout basics (spacing, border, radius)',
|
|
113
|
+
render: (args) => (
|
|
114
|
+
<Box
|
|
115
|
+
{...args}
|
|
116
|
+
sx={{
|
|
117
|
+
border: '1px solid',
|
|
118
|
+
borderColor: 'divider',
|
|
119
|
+
borderRadius: 2,
|
|
120
|
+
bgcolor: 'background.paper',
|
|
121
|
+
}}
|
|
122
|
+
/>
|
|
123
|
+
),
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export const FlexRow: Story = {
|
|
127
|
+
args: {},
|
|
128
|
+
render: () => (
|
|
129
|
+
<Box display="flex" gap={2}>
|
|
130
|
+
<Box p={1} sx={{ border: '1px dashed', borderColor: 'divider' }}>A</Box>
|
|
131
|
+
<Box p={1} sx={{ border: '1px dashed', borderColor: 'divider' }}>B</Box>
|
|
132
|
+
<Box p={1} sx={{ border: '1px dashed', borderColor: 'divider' }}>C</Box>
|
|
133
|
+
</Box>
|
|
134
|
+
),
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
export const GridLayout: Story = {
|
|
138
|
+
render: () => (
|
|
139
|
+
<Box display="grid" sx={{ gridTemplateColumns: 'repeat(3, 1fr)', gap: 2 }}>
|
|
140
|
+
{Array.from({ length: 6 }).map((_, i) => (
|
|
141
|
+
<Box key={i} p={2} sx={{ border: '1px solid', borderColor: 'divider', borderRadius: 1 }}>
|
|
142
|
+
Cell {i + 1}
|
|
143
|
+
</Box>
|
|
144
|
+
))}
|
|
145
|
+
</Box>
|
|
146
|
+
),
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
export const AsSection: Story = {
|
|
150
|
+
name: 'Polymorphic: section',
|
|
151
|
+
render: () => (
|
|
152
|
+
<Box component="section" p={2} sx={{ borderLeft: '4px solid', borderColor: 'primary.main' }}>
|
|
153
|
+
<Typography variant="h6">Section title</Typography>
|
|
154
|
+
<Typography variant="body2" sx={{ opacity: 0.8 }}>
|
|
155
|
+
Section content goes here.
|
|
156
|
+
</Typography>
|
|
157
|
+
</Box>
|
|
158
|
+
),
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
export const AsAnchor: Story = {
|
|
162
|
+
name: 'Polymorphic: anchor (href)',
|
|
163
|
+
render: () => (
|
|
164
|
+
<Box
|
|
165
|
+
component="a"
|
|
166
|
+
href="https://neurons.me"
|
|
167
|
+
target="_blank"
|
|
168
|
+
rel="noreferrer"
|
|
169
|
+
p={1}
|
|
170
|
+
sx={{
|
|
171
|
+
display: 'inline-block',
|
|
172
|
+
border: '1px solid',
|
|
173
|
+
borderColor: 'divider',
|
|
174
|
+
borderRadius: 1,
|
|
175
|
+
'&:hover': { textDecoration: 'none', bgcolor: 'action.hover' },
|
|
176
|
+
}}
|
|
177
|
+
>
|
|
178
|
+
Visit neurons.me
|
|
179
|
+
</Box>
|
|
180
|
+
),
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
export const AsRouterLink: Story = {
|
|
184
|
+
name: 'Polymorphic: Link (to)',
|
|
185
|
+
render: () => (
|
|
186
|
+
<Box
|
|
187
|
+
component={Link}
|
|
188
|
+
to="/docs"
|
|
189
|
+
p={1}
|
|
190
|
+
sx={{
|
|
191
|
+
display: 'inline-block',
|
|
192
|
+
border: '1px solid',
|
|
193
|
+
borderColor: 'divider',
|
|
194
|
+
borderRadius: 1,
|
|
195
|
+
'&:hover': { textDecoration: 'none', bgcolor: 'action.hover' },
|
|
196
|
+
}}
|
|
197
|
+
>
|
|
198
|
+
Go to docs
|
|
199
|
+
</Box>
|
|
200
|
+
),
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
export const ImageMode: Story = {
|
|
204
|
+
name: 'Image mode (component="img")',
|
|
205
|
+
render: () => (
|
|
206
|
+
<Box
|
|
207
|
+
component="img"
|
|
208
|
+
src="https://placekitten.com/320/160"
|
|
209
|
+
alt="Kitten"
|
|
210
|
+
sx={{ width: 320, height: 'auto', borderRadius: 1, border: '1px solid', borderColor: 'divider' }}
|
|
211
|
+
loading="lazy"
|
|
212
|
+
decoding="async"
|
|
213
|
+
/>
|
|
214
|
+
),
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
export const NestedComposition: Story = {
|
|
218
|
+
render: () => (
|
|
219
|
+
<Box p={2} sx={{ border: '1px solid', borderColor: 'divider', borderRadius: 1 }}>
|
|
220
|
+
<Typography variant="subtitle1" sx={{ mb: 1 }}>Nested composition</Typography>
|
|
221
|
+
<Box display="flex" gap={1}>
|
|
222
|
+
<Button variant="contained" color="primary">Action</Button>
|
|
223
|
+
<Box component={Link} to="/docs" sx={{ alignSelf: 'center' }}>
|
|
224
|
+
Learn more
|
|
225
|
+
</Box>
|
|
226
|
+
</Box>
|
|
227
|
+
</Box>
|
|
228
|
+
),
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
export const SXDeepStyling: Story = {
|
|
232
|
+
name: 'Deep styling with sx',
|
|
233
|
+
render: () => (
|
|
234
|
+
<Box
|
|
235
|
+
p={2}
|
|
236
|
+
sx={{
|
|
237
|
+
borderRadius: 2,
|
|
238
|
+
bgcolor: 'background.paper',
|
|
239
|
+
border: '1px solid',
|
|
240
|
+
borderColor: 'divider',
|
|
241
|
+
'& .demo-title': {
|
|
242
|
+
fontWeight: 700,
|
|
243
|
+
color: 'text.primary',
|
|
244
|
+
mb: 1,
|
|
245
|
+
},
|
|
246
|
+
'& .demo-card': {
|
|
247
|
+
p: 1.5,
|
|
248
|
+
border: '1px solid',
|
|
249
|
+
borderColor: 'divider',
|
|
250
|
+
borderRadius: 1,
|
|
251
|
+
'&:hover': { bgcolor: 'action.hover' },
|
|
252
|
+
},
|
|
253
|
+
}}
|
|
254
|
+
>
|
|
255
|
+
<Typography className="demo-title">Cards</Typography>
|
|
256
|
+
<Box display="grid" sx={{ gridTemplateColumns: 'repeat(3, 1fr)', gap: 1.5 }}>
|
|
257
|
+
<Box className="demo-card">One</Box>
|
|
258
|
+
<Box className="demo-card">Two</Box>
|
|
259
|
+
<Box className="demo-card">Three</Box>
|
|
260
|
+
</Box>
|
|
261
|
+
</Box>
|
|
262
|
+
),
|
|
263
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// src/gui/atoms/Box/Box.tsx
|
|
2
|
+
/*
|
|
3
|
+
* This.GUI — Box (polymorphic)
|
|
4
|
+
* Wrapper that keeps MUI's own typing, including the `component` prop.
|
|
5
|
+
* Ejemplos válidos:
|
|
6
|
+
* <Box component="img" src="..." alt="..." />
|
|
7
|
+
* <Box component="a" href="..." />
|
|
8
|
+
*/
|
|
9
|
+
import MuiBox from '@mui/material/Box';
|
|
10
|
+
import * as React from 'react';
|
|
11
|
+
// Re-export using MUI's own component type
|
|
12
|
+
const Box = MuiBox;
|
|
13
|
+
export type BoxProps = React.ComponentProps<typeof Box>;
|
|
14
|
+
(Box as any).displayName = 'Gui.Box';
|
|
15
|
+
export default Box;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// src/gui/primitives/Button/Button.resolver.tsx
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import Button from './Button';
|
|
4
|
+
import Icon from '@/gui/Theme/Icon/Icon';
|
|
5
|
+
import Link from '../Link/Link';
|
|
6
|
+
import type { RegistryEntry } from '@/registry/types';
|
|
7
|
+
import type { SxProps, Theme } from '@mui/material/styles';
|
|
8
|
+
import { ensureNodeId } from '@/gui/utils/nodeID';
|
|
9
|
+
/**
|
|
10
|
+
* Declarative spec for Button.
|
|
11
|
+
* This is the JSON-friendly shape your renderer/LLM can emit.
|
|
12
|
+
*/
|
|
13
|
+
type ButtonSpec = {
|
|
14
|
+
type: 'Button';
|
|
15
|
+
props?: {
|
|
16
|
+
// Content
|
|
17
|
+
label?: string; // convenience for children text
|
|
18
|
+
children?: React.ReactNode; // optional explicit children
|
|
19
|
+
// Visual
|
|
20
|
+
variant?: 'text' | 'outlined' | 'contained';
|
|
21
|
+
color?: 'inherit' | 'primary' | 'secondary' | 'success' | 'info' | 'warning' | 'error';
|
|
22
|
+
size?: 'small' | 'medium' | 'large';
|
|
23
|
+
startIcon?: React.ReactNode | string;
|
|
24
|
+
endIcon?: React.ReactNode | string;
|
|
25
|
+
sx?: SxProps<Theme>;
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
fullWidth?: boolean;
|
|
28
|
+
// Routing / polymorphism
|
|
29
|
+
external?: boolean | 'true' | 1; // if true → anchor + target/rel
|
|
30
|
+
href?: string; // for anchors
|
|
31
|
+
to?: string; // for routers
|
|
32
|
+
target?: React.HTMLAttributeAnchorTarget;
|
|
33
|
+
rel?: string;
|
|
34
|
+
component?: React.ElementType | string; // override polymorphic target (e.g., your Link)
|
|
35
|
+
as?: React.ElementType | string;
|
|
36
|
+
type?: 'button' | 'submit' | 'reset';
|
|
37
|
+
// You can extend with data-* attributes, id, className, etc.
|
|
38
|
+
id?: string;
|
|
39
|
+
className?: string;
|
|
40
|
+
'data-testid'?: string;
|
|
41
|
+
[key: string]: any;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* ButtonResolver
|
|
47
|
+
* - Maps JSON-friendly spec → real <Button /> props.
|
|
48
|
+
* - Keeps MUI polymorphism intact. If `to` is provided and no `component`,
|
|
49
|
+
* it defaults to your primitives Link; if `external` is true, it uses an anchor safely.
|
|
50
|
+
*/
|
|
51
|
+
const ButtonResolver: RegistryEntry = {
|
|
52
|
+
type: 'Button',
|
|
53
|
+
resolve(spec: ButtonSpec) {
|
|
54
|
+
const p = spec.props ?? {};
|
|
55
|
+
// Decide component priority
|
|
56
|
+
const isExternal = p.external === true || p.external === 'true' || p.external === 1;
|
|
57
|
+
let component: React.ElementType | string | undefined =
|
|
58
|
+
p.component ?? p.as ?? (p.to ? Link : (p.href || isExternal) ? 'a' : undefined);
|
|
59
|
+
|
|
60
|
+
const routingProps: Record<string, any> = {};
|
|
61
|
+
if (component === Link && p.to) {
|
|
62
|
+
routingProps.to = p.to;
|
|
63
|
+
} else if (component === 'a') {
|
|
64
|
+
routingProps.href = p.href;
|
|
65
|
+
if (isExternal) {
|
|
66
|
+
routingProps.target = p.target ?? '_blank';
|
|
67
|
+
routingProps.rel = p.rel ?? 'noopener noreferrer';
|
|
68
|
+
} else {
|
|
69
|
+
if (p.target) routingProps.target = p.target;
|
|
70
|
+
if (p.rel) routingProps.rel = p.rel;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Children precedence: explicit children > label > fallback
|
|
75
|
+
const children = p.children ?? p.label ?? 'Button';
|
|
76
|
+
return (
|
|
77
|
+
<Button
|
|
78
|
+
{...(component ? { component } : {})}
|
|
79
|
+
variant={p.variant ?? 'text'}
|
|
80
|
+
color={p.color ?? 'inherit'}
|
|
81
|
+
size={p.size ?? 'medium'}
|
|
82
|
+
startIcon={
|
|
83
|
+
typeof p.startIcon === 'string' ? <Icon name={p.startIcon} /> : p.startIcon
|
|
84
|
+
}
|
|
85
|
+
endIcon={
|
|
86
|
+
typeof p.endIcon === 'string' ? <Icon name={p.endIcon} /> : p.endIcon
|
|
87
|
+
}
|
|
88
|
+
disabled={p.disabled}
|
|
89
|
+
fullWidth={p.fullWidth}
|
|
90
|
+
type={p.type}
|
|
91
|
+
sx={p.sx}
|
|
92
|
+
id={ensureNodeId('button', p.id)}
|
|
93
|
+
className={p.className}
|
|
94
|
+
data-testid={p['data-testid']}
|
|
95
|
+
{...routingProps}
|
|
96
|
+
>
|
|
97
|
+
{children}
|
|
98
|
+
</Button>
|
|
99
|
+
);
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export default ButtonResolver;
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { Button, Link } from '@/gui/components/atoms';
|
|
3
|
+
import Icon from '@/gui/Theme/Icon/Icon';
|
|
4
|
+
|
|
5
|
+
// ======================= Meta =======================
|
|
6
|
+
const meta: Meta<typeof Button> = {
|
|
7
|
+
title: 'Atoms/Forms & Inputs/Button',
|
|
8
|
+
component: Button,
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
decorators: [
|
|
11
|
+
(Story) => (
|
|
12
|
+
<div style={{ padding: 16, minHeight: 240 }}>
|
|
13
|
+
<Story />
|
|
14
|
+
</div>
|
|
15
|
+
),
|
|
16
|
+
],
|
|
17
|
+
parameters: {
|
|
18
|
+
docs: {
|
|
19
|
+
description: {
|
|
20
|
+
component: `
|
|
21
|
+
The **Button** primitive is a thin wrapper around MUI's \`MuiButton\` that preserves **polymorphism** and adds **declarative icons** (string tokens like
|
|
22
|
+
\`mui:Send\` or \`lucide:bolt\`). It integrates with **This.GUI** theming and respects your token-built palette.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
## Features
|
|
26
|
+
- Variants: \`contained\`, \`outlined\`, \`text\`.
|
|
27
|
+
- Colors: \`primary\`, \`secondary\`, \`success\`, \`info\`, \`warning\`, \`error\`, \`inherit\`.
|
|
28
|
+
- Sizes: \`small\`, \`medium\`, \`large\`.
|
|
29
|
+
- **Icons** via tokens (\`startIcon\` / \`endIcon\`) or React nodes.
|
|
30
|
+
- **Polymorphic**: \`component\` can be \`'a'\` or a Link (e.g. the This.GUI wrapper \`Link\`) for routing.
|
|
31
|
+
- Respects your theme from \`GuiProvider\` (no need to wrap with \`ThemeProvider\`).
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
## Key Props
|
|
35
|
+
- \`startIcon?: string | ReactNode\` — accepts a name from the **icon registry** (\`mui:*\` / \`lucide:*\`) or a React element.
|
|
36
|
+
- \`endIcon?: string | ReactNode\`.
|
|
37
|
+
- \`component?: ElementType | string\` — for polymorphism (\`'a'\`, RouterLink, etc.).
|
|
38
|
+
- \`href?: string\` — when \`component='a'\`.
|
|
39
|
+
- \`to?: string\` — when \`component={Link}\`.
|
|
40
|
+
|
|
41
|
+
> Note: \`to\` and \`href\` are not exposed as Storybook controls because they only apply in specific modes; they are shown in dedicated stories.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
## Basic usage
|
|
45
|
+
~~~jsx
|
|
46
|
+
import { Button } from '@/gui/primitives';
|
|
47
|
+
|
|
48
|
+
<Button variant="contained" color="primary">Save</Button>
|
|
49
|
+
<Button variant="outlined" color="secondary">Cancel</Button>
|
|
50
|
+
<Button variant="text">Learn more</Button>
|
|
51
|
+
~~~
|
|
52
|
+
|
|
53
|
+
## With declarative icons
|
|
54
|
+
~~~jsx
|
|
55
|
+
<Button variant="contained" color="secondary" startIcon="mui:Send" endIcon="lucide:bolt">
|
|
56
|
+
Send
|
|
57
|
+
</Button>
|
|
58
|
+
~~~
|
|
59
|
+
|
|
60
|
+
## As native anchor link
|
|
61
|
+
~~~jsx
|
|
62
|
+
<Button component="a" href="https://neurons.me" /* target="_blank" rel="noreferrer" */>
|
|
63
|
+
Visit neurons.me
|
|
64
|
+
</Button>
|
|
65
|
+
~~~
|
|
66
|
+
|
|
67
|
+
## With RouterLink (This.GUI Link)
|
|
68
|
+
~~~jsx
|
|
69
|
+
import { Button, Link } from '@/gui/primitives';
|
|
70
|
+
|
|
71
|
+
<Button component={Link} to="/docs">Go to docs</Button>
|
|
72
|
+
~~~
|
|
73
|
+
## Declarative JSON / Config usage
|
|
74
|
+
~~~json
|
|
75
|
+
{
|
|
76
|
+
"type": "Button",
|
|
77
|
+
"props": {
|
|
78
|
+
"variant": "text",
|
|
79
|
+
"color": "primary",
|
|
80
|
+
"component": "a",
|
|
81
|
+
"href": "https://neurons.me",
|
|
82
|
+
"target": "_blank",
|
|
83
|
+
"rel": "noreferrer",
|
|
84
|
+
"children": "Visit neurons.me"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
~~~
|
|
88
|
+
|
|
89
|
+
Another example with a RouterLink:
|
|
90
|
+
~~~json
|
|
91
|
+
{
|
|
92
|
+
"type": "Button",
|
|
93
|
+
"props": {
|
|
94
|
+
"variant": "contained",
|
|
95
|
+
"color": "secondary",
|
|
96
|
+
"component": "Link",
|
|
97
|
+
"to": "/docs",
|
|
98
|
+
"startIcon": "mui:Send",
|
|
99
|
+
"children": "Go to docs"
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
~~~
|
|
103
|
+
`,
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
argTypes: {
|
|
108
|
+
variant: {
|
|
109
|
+
control: { type: 'radio' },
|
|
110
|
+
options: ['contained', 'outlined', 'text'],
|
|
111
|
+
},
|
|
112
|
+
color: {
|
|
113
|
+
control: { type: 'select' },
|
|
114
|
+
options: ['primary', 'secondary', 'success', 'info', 'warning', 'error', 'inherit'],
|
|
115
|
+
},
|
|
116
|
+
size: {
|
|
117
|
+
control: { type: 'radio' },
|
|
118
|
+
options: ['small', 'medium', 'large'],
|
|
119
|
+
},
|
|
120
|
+
startIcon: { control: 'text', description: 'Icon token or a React element.' },
|
|
121
|
+
endIcon: { control: 'text', description: 'Icon token or a React element.' },
|
|
122
|
+
onClick: { action: 'clicked' },
|
|
123
|
+
},
|
|
124
|
+
args: {
|
|
125
|
+
variant: 'contained',
|
|
126
|
+
color: 'primary',
|
|
127
|
+
size: 'medium',
|
|
128
|
+
children: 'Click me',
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
export default meta;
|
|
132
|
+
|
|
133
|
+
type Story = StoryObj<typeof Button>;
|
|
134
|
+
|
|
135
|
+
// ======================= Stories =======================
|
|
136
|
+
export const Playground: Story = {};
|
|
137
|
+
|
|
138
|
+
export const Variants: Story = {
|
|
139
|
+
args: { color: 'primary' },
|
|
140
|
+
render: (args) => (
|
|
141
|
+
<div style={{ display: 'flex', gap: 12, flexWrap: 'wrap' }}>
|
|
142
|
+
<Button {...args} variant="contained">Contained</Button>
|
|
143
|
+
<Button {...args} variant="outlined">Outlined</Button>
|
|
144
|
+
<Button {...args} variant="text">Text</Button>
|
|
145
|
+
</div>
|
|
146
|
+
),
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
export const Colors: Story = {
|
|
150
|
+
args: { variant: 'contained' },
|
|
151
|
+
render: (args) => {
|
|
152
|
+
const colors: Array<'primary' | 'secondary' | 'success' | 'info' | 'warning' | 'error'> =
|
|
153
|
+
['primary', 'secondary', 'success', 'info', 'warning', 'error'];
|
|
154
|
+
return (
|
|
155
|
+
<div style={{ display: 'flex', gap: 12, flexWrap: 'wrap' }}>
|
|
156
|
+
{colors.map((c) => (
|
|
157
|
+
<Button key={c} {...args} color={c}>
|
|
158
|
+
{c[0].toUpperCase() + c.slice(1)}
|
|
159
|
+
</Button>
|
|
160
|
+
))}
|
|
161
|
+
</div>
|
|
162
|
+
);
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
export const Sizes: Story = {
|
|
167
|
+
args: { color: 'primary', variant: 'contained' },
|
|
168
|
+
render: (args) => (
|
|
169
|
+
<div style={{ display: 'flex', gap: 12, alignItems: 'center', flexWrap: 'wrap' }}>
|
|
170
|
+
<Button {...args} size="small">Small</Button>
|
|
171
|
+
<Button {...args} size="medium">Medium</Button>
|
|
172
|
+
<Button {...args} size="large">Large</Button>
|
|
173
|
+
</div>
|
|
174
|
+
),
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
export const WithIcons: Story = {
|
|
178
|
+
args: {
|
|
179
|
+
variant: 'contained',
|
|
180
|
+
color: 'secondary',
|
|
181
|
+
startIcon: <Icon name="Power" />,
|
|
182
|
+
endIcon: <Icon name="bolt" />,
|
|
183
|
+
children: 'Send',
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
export const PolymorphicAnchor: Story = {
|
|
188
|
+
args: {
|
|
189
|
+
variant: 'text',
|
|
190
|
+
color: 'primary',
|
|
191
|
+
children: 'Go to neurons.me',
|
|
192
|
+
},
|
|
193
|
+
render: (args) => (
|
|
194
|
+
<Button component="a" href="https://neurons.me">
|
|
195
|
+
{args.children}
|
|
196
|
+
</Button>
|
|
197
|
+
),
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
export const PolymorphicRouterLink: Story = {
|
|
201
|
+
args: {
|
|
202
|
+
variant: 'text',
|
|
203
|
+
color: 'primary',
|
|
204
|
+
children: 'Go to /docs',
|
|
205
|
+
},
|
|
206
|
+
render: (args) => (
|
|
207
|
+
<Button component={Link} to="/docs">
|
|
208
|
+
{args.children}
|
|
209
|
+
</Button>
|
|
210
|
+
),
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
export const Disabled: Story = {
|
|
214
|
+
args: { variant: 'contained', color: 'primary', disabled: true, children: 'Disabled' },
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
export const FullWidth: Story = {
|
|
218
|
+
args: { variant: 'contained', color: 'primary', fullWidth: true, children: 'Full Width' },
|
|
219
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
import MuiButton from '@mui/material/Button';
|
|
4
|
+
import type { OverridableComponent } from '@mui/material/OverridableComponent';
|
|
5
|
+
import type { ButtonTypeMap } from '@mui/material/Button';
|
|
6
|
+
import type { ButtonProps as MuiButtonProps } from '@mui/material/Button';
|
|
7
|
+
import Icon from '@/gui/Theme/Icon/Icon';
|
|
8
|
+
/**
|
|
9
|
+
* Button (This.GUI primitive)
|
|
10
|
+
* ----------------------------------------
|
|
11
|
+
* - Polymorphic: preserves MUI's `component` API and typing via OverridableComponent.
|
|
12
|
+
* - Enhances MUI by allowing `startIcon` / `endIcon` to be a declarative string
|
|
13
|
+
* (e.g., "mui:Settings" / "lucide:camera") or a ReactNode.
|
|
14
|
+
*/
|
|
15
|
+
// Polymorphic props type that matches MUI Button while letting us tweak icon props
|
|
16
|
+
export type Iconish = ReactNode | string | undefined;
|
|
17
|
+
export type ButtonProps = Omit<MuiButtonProps, 'startIcon' | 'endIcon'> & {
|
|
18
|
+
startIcon?: Iconish;
|
|
19
|
+
endIcon?: Iconish;
|
|
20
|
+
};
|
|
21
|
+
function resolveIcon(node: Iconish): ReactNode | null {
|
|
22
|
+
if (!node) return null;
|
|
23
|
+
return typeof node === 'string' ? <Icon name={node} fontSize={18} /> : node;
|
|
24
|
+
}
|
|
25
|
+
const ButtonImpl = React.forwardRef<any, ButtonProps>(function Button(
|
|
26
|
+
{ startIcon, endIcon, ...rest },
|
|
27
|
+
ref
|
|
28
|
+
) {
|
|
29
|
+
return (
|
|
30
|
+
<MuiButton
|
|
31
|
+
ref={ref}
|
|
32
|
+
startIcon={resolveIcon(startIcon)}
|
|
33
|
+
endIcon={resolveIcon(endIcon)}
|
|
34
|
+
{...rest}
|
|
35
|
+
/>
|
|
36
|
+
);
|
|
37
|
+
}) as unknown as OverridableComponent<ButtonTypeMap<{}, 'button'>>;
|
|
38
|
+
(ButtonImpl as any).displayName = 'Button';
|
|
39
|
+
export default ButtonImpl;
|
|
40
|
+
export type GuiButtonProps = React.ComponentProps<typeof ButtonImpl>;
|