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,214 @@
|
|
|
1
|
+
// src/gui/atoms/ListItemButton/ListItemButton.resolver.tsx
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import ListItemButton from './ListItemButton';
|
|
4
|
+
import Link from '@/gui/components/atoms/Link/Link';
|
|
5
|
+
import Icon from '@/gui/Theme/Icon/Icon';
|
|
6
|
+
// Use our own thin wrappers for consistency & display names
|
|
7
|
+
import ListItemIcon from '@/gui/components/atoms/ListItemIcon/ListItemIcon';
|
|
8
|
+
import ListItemText from '@/gui/components/atoms/ListItemText/ListItemText';
|
|
9
|
+
import type { RegistryEntry, ResolveCtx } from '@/registry/types';
|
|
10
|
+
import type { SxProps, Theme } from '@mui/material/styles';
|
|
11
|
+
import Box from '../Box/Box';
|
|
12
|
+
import { ensureNodeId } from '@/gui/utils/nodeID';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Declarative spec for ListItemButton
|
|
16
|
+
*
|
|
17
|
+
* Goals
|
|
18
|
+
* - Be faithful to MUI's API: forward native props like `selected`, `disabled`, `dense`, `alignItems`, etc.
|
|
19
|
+
* - Preserve polymorphism via MUI's `component` prop (and alias `as`).
|
|
20
|
+
* - Add **declarative sugar** (optional):
|
|
21
|
+
* - `startIcon` / `endIcon`: string token (e.g., "lucide:mail", "mui:settings") or ReactNode
|
|
22
|
+
* - `label` / `secondary`: mapped to `<ListItemText primary/secondary />`
|
|
23
|
+
* - Add **granular styling** for slots:
|
|
24
|
+
* - `sx` → root ListItemButton
|
|
25
|
+
* - `iconSx` → ListItemIcon (leading)
|
|
26
|
+
* - `textSx` → ListItemText
|
|
27
|
+
* - `endIconSx` → trailing icon container
|
|
28
|
+
*
|
|
29
|
+
* Notes
|
|
30
|
+
* - If `children` are provided, they take precedence and render as-is (no sugar applied).
|
|
31
|
+
* - Tokens are normalized (lowercased & trimmed) to avoid missing icons due to casing.
|
|
32
|
+
* - Routing:
|
|
33
|
+
* - If `to` is provided (and no explicit `component`), the resolver will default to This.GUI `Link`.
|
|
34
|
+
* - If `external` is true (and no explicit `component`), it will default to an anchor `'a'` and add safe `target`/`rel`.
|
|
35
|
+
*/
|
|
36
|
+
export type ListItemButtonSpec = {
|
|
37
|
+
type: 'ListItemButton';
|
|
38
|
+
props?: {
|
|
39
|
+
children?: React.ReactNode;
|
|
40
|
+
|
|
41
|
+
// Polymorphism / routing
|
|
42
|
+
component?: any; // 'div' | 'a' | Link | custom
|
|
43
|
+
as?: any; // alias for component
|
|
44
|
+
to?: string; // router target (when component={Link})
|
|
45
|
+
href?: string; // anchor target (when component='a')
|
|
46
|
+
external?: boolean; // force external anchor
|
|
47
|
+
target?: React.HTMLAttributeAnchorTarget;
|
|
48
|
+
rel?: string;
|
|
49
|
+
|
|
50
|
+
// Sugar (optional)
|
|
51
|
+
startIcon?: React.ReactNode | string;
|
|
52
|
+
endIcon?: React.ReactNode | string;
|
|
53
|
+
iconColor?: string; // applies to startIcon/endIcon when tokens
|
|
54
|
+
endIconColor?: string; // override for trailing icon
|
|
55
|
+
size?: number; // icon size (default 20)
|
|
56
|
+
label?: React.ReactNode | string;
|
|
57
|
+
secondary?: React.ReactNode | string;
|
|
58
|
+
|
|
59
|
+
// MUI props (subset; others passthrough)
|
|
60
|
+
selected?: boolean;
|
|
61
|
+
disabled?: boolean;
|
|
62
|
+
dense?: boolean;
|
|
63
|
+
alignItems?: 'flex-start' | 'center';
|
|
64
|
+
divider?: boolean;
|
|
65
|
+
|
|
66
|
+
// Granular styling
|
|
67
|
+
sx?: SxProps<Theme>; // root
|
|
68
|
+
iconSx?: SxProps<Theme>; // leading ListItemIcon
|
|
69
|
+
textSx?: SxProps<Theme>; // ListItemText
|
|
70
|
+
endIconSx?: SxProps<Theme>; // trailing icon container
|
|
71
|
+
|
|
72
|
+
// Slot props passthrough (their own sx can be merged)
|
|
73
|
+
ListItemIconProps?: { sx?: SxProps<Theme>; [k: string]: any };
|
|
74
|
+
ListItemTextProps?: { sx?: SxProps<Theme>; [k: string]: any };
|
|
75
|
+
|
|
76
|
+
// Editor / telemetry
|
|
77
|
+
'data-gui-id'?: string;
|
|
78
|
+
|
|
79
|
+
// Misc DOM
|
|
80
|
+
id?: string;
|
|
81
|
+
className?: string;
|
|
82
|
+
'data-testid'?: string;
|
|
83
|
+
|
|
84
|
+
// Arbitrary passthrough
|
|
85
|
+
[key: string]: any;
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const normalizeToken = (s: string) => s.trim().toLowerCase();
|
|
90
|
+
|
|
91
|
+
function renderIcon(node: React.ReactNode | string | undefined, color?: string, size = 20) {
|
|
92
|
+
if (!node) return null;
|
|
93
|
+
return typeof node === 'string'
|
|
94
|
+
? (
|
|
95
|
+
<Icon
|
|
96
|
+
name={normalizeToken(node)}
|
|
97
|
+
iconColor={color}
|
|
98
|
+
fontSize={size}
|
|
99
|
+
/>
|
|
100
|
+
)
|
|
101
|
+
: node;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const ListItemButtonResolver: RegistryEntry = {
|
|
105
|
+
type: 'ListItemButton',
|
|
106
|
+
resolve(spec: ListItemButtonSpec, _ctx?: ResolveCtx) {
|
|
107
|
+
const p = spec.props ?? {};
|
|
108
|
+
|
|
109
|
+
// Generate/ensure a stable gui id (does not override an explicit one)
|
|
110
|
+
const dataGuiId = ensureNodeId('list-item-button', (p as any)['data-gui-id']);
|
|
111
|
+
|
|
112
|
+
// Decide polymorphic target (only pass when defined)
|
|
113
|
+
const decidedComponent = p.component ?? p.as ?? (p.to ? Link : p.external ? 'a' : undefined);
|
|
114
|
+
const componentProp = decidedComponent ? { component: decidedComponent } : undefined;
|
|
115
|
+
|
|
116
|
+
// Routing/anchor props
|
|
117
|
+
const routingProps =
|
|
118
|
+
decidedComponent === 'a' || p.external
|
|
119
|
+
? {
|
|
120
|
+
href: p.href,
|
|
121
|
+
target: p.target ?? (p.external ? '_blank' : undefined),
|
|
122
|
+
rel: p.rel ?? (p.external ? 'noopener noreferrer' : undefined),
|
|
123
|
+
}
|
|
124
|
+
: decidedComponent === Link || (p.to && !p.component)
|
|
125
|
+
? { to: p.to }
|
|
126
|
+
: {};
|
|
127
|
+
|
|
128
|
+
// Destructure and clean resolver-only fields
|
|
129
|
+
const {
|
|
130
|
+
children,
|
|
131
|
+
startIcon,
|
|
132
|
+
endIcon,
|
|
133
|
+
iconColor,
|
|
134
|
+
endIconColor,
|
|
135
|
+
size = 20,
|
|
136
|
+
ListItemIconProps,
|
|
137
|
+
ListItemTextProps,
|
|
138
|
+
iconSx,
|
|
139
|
+
textSx,
|
|
140
|
+
endIconSx,
|
|
141
|
+
|
|
142
|
+
// strip resolver-only aliasing keys so they don't leak to DOM
|
|
143
|
+
as: _as,
|
|
144
|
+
external: _external,
|
|
145
|
+
to: _to,
|
|
146
|
+
href: _href,
|
|
147
|
+
target: _target,
|
|
148
|
+
rel: _rel,
|
|
149
|
+
|
|
150
|
+
// keep rest: native MUI props (selected, dense, disabled, divider, alignItems, sx, etc.)
|
|
151
|
+
...rest
|
|
152
|
+
} = p as any;
|
|
153
|
+
|
|
154
|
+
// If explicit children, render as-is (no sugar)
|
|
155
|
+
if (children != null) {
|
|
156
|
+
return (
|
|
157
|
+
<ListItemButton
|
|
158
|
+
{...componentProp}
|
|
159
|
+
sx={p.sx}
|
|
160
|
+
id={p.id}
|
|
161
|
+
className={p.className}
|
|
162
|
+
data-testid={p['data-testid']}
|
|
163
|
+
data-gui-id={dataGuiId}
|
|
164
|
+
{...routingProps}
|
|
165
|
+
{...rest}
|
|
166
|
+
>
|
|
167
|
+
{children}
|
|
168
|
+
</ListItemButton>
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Build sugar content
|
|
173
|
+
const leadingIcon = renderIcon(startIcon, iconColor, size);
|
|
174
|
+
const trailingIcon = renderIcon(endIcon, endIconColor ?? iconColor, size);
|
|
175
|
+
const hasText = p.label != null || p.secondary != null;
|
|
176
|
+
|
|
177
|
+
// Merge sx for slot props safely (array merge preserves both)
|
|
178
|
+
const mergedIconSx =
|
|
179
|
+
iconSx != null && ListItemIconProps?.sx != null ? [iconSx, ListItemIconProps.sx] : iconSx ?? ListItemIconProps?.sx;
|
|
180
|
+
const mergedTextSx =
|
|
181
|
+
textSx != null && ListItemTextProps?.sx != null ? [textSx, ListItemTextProps.sx] : textSx ?? ListItemTextProps?.sx;
|
|
182
|
+
|
|
183
|
+
const finalIconProps = leadingIcon
|
|
184
|
+
? (ListItemIconProps ? { ...ListItemIconProps, sx: mergedIconSx } : (mergedIconSx != null ? { sx: mergedIconSx } : undefined))
|
|
185
|
+
: undefined;
|
|
186
|
+
|
|
187
|
+
const finalTextProps = hasText
|
|
188
|
+
? (ListItemTextProps ? { ...ListItemTextProps, sx: mergedTextSx } : (mergedTextSx != null ? { sx: mergedTextSx } : undefined))
|
|
189
|
+
: undefined;
|
|
190
|
+
|
|
191
|
+
return (
|
|
192
|
+
<ListItemButton
|
|
193
|
+
{...componentProp}
|
|
194
|
+
sx={p.sx}
|
|
195
|
+
id={p.id}
|
|
196
|
+
className={p.className}
|
|
197
|
+
data-testid={p['data-testid']}
|
|
198
|
+
data-gui-id={dataGuiId}
|
|
199
|
+
{...routingProps}
|
|
200
|
+
{...rest}
|
|
201
|
+
>
|
|
202
|
+
{leadingIcon ? <ListItemIcon {...finalIconProps}>{leadingIcon}</ListItemIcon> : null}
|
|
203
|
+
{hasText ? <ListItemText primary={p.label} secondary={p.secondary} {...finalTextProps} /> : null}
|
|
204
|
+
{trailingIcon ? (
|
|
205
|
+
<Box sx={[{ marginLeft: 'auto', display: 'inline-flex', alignItems: 'center' }, endIconSx as any]}>
|
|
206
|
+
{trailingIcon}
|
|
207
|
+
</Box>
|
|
208
|
+
) : null}
|
|
209
|
+
</ListItemButton>
|
|
210
|
+
);
|
|
211
|
+
},
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
export default ListItemButtonResolver;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import ListItemButton from './ListItemButton';
|
|
4
|
+
import ListItemIcon from '@/gui/components/atoms/ListItemIcon/ListItemIcon';
|
|
5
|
+
import ListItemText from '@/gui/components/atoms/ListItemText/ListItemText';
|
|
6
|
+
import Icon from '@/gui/Theme/Icon/Icon';
|
|
7
|
+
import List from '@mui/material/List';
|
|
8
|
+
import ListItem from '@mui/material/ListItem';
|
|
9
|
+
|
|
10
|
+
const meta: Meta<typeof ListItemButton> = {
|
|
11
|
+
title: 'Atoms/Organization/ListItemButton',
|
|
12
|
+
component: ListItemButton,
|
|
13
|
+
tags: ['autodocs'],
|
|
14
|
+
decorators: [
|
|
15
|
+
(Story) => (
|
|
16
|
+
<div style={{ padding: 16, minHeight: 260, maxWidth: 560 }}>
|
|
17
|
+
<Story />
|
|
18
|
+
</div>
|
|
19
|
+
),
|
|
20
|
+
],
|
|
21
|
+
parameters: {
|
|
22
|
+
docs: {
|
|
23
|
+
description: {
|
|
24
|
+
component: `
|
|
25
|
+
The **ListItemButton** atom is a thin wrapper around MUI's \`MuiListItemButton\`, staying faithful to its API and polymorphism.
|
|
26
|
+
|
|
27
|
+
In **declarative** mode, the resolver adds sugar:
|
|
28
|
+
- \`startIcon\` / \`endIcon\`: token (e.g., \`"lucide:mail"\`, \`"mui:settings"\`) or ReactNode — rendered via the icon registry
|
|
29
|
+
- \`label\` / \`secondary\` → mapped to \`<ListItemText primary/secondary />\`
|
|
30
|
+
- Granular styling:
|
|
31
|
+
- \`sx\` (root), \`iconSx\` (leading \`ListItemIcon\`), \`textSx\` (text), \`endIconSx\` (trailing icon container)
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
## React usage
|
|
35
|
+
~~~jsx
|
|
36
|
+
<List>
|
|
37
|
+
<ListItem disablePadding>
|
|
38
|
+
<ListItemButton selected>
|
|
39
|
+
<ListItemIcon>
|
|
40
|
+
<Icon name="lucide:mail" />
|
|
41
|
+
</ListItemIcon>
|
|
42
|
+
<ListItemText primary="Inbox" secondary="Messages" />
|
|
43
|
+
</ListItemButton>
|
|
44
|
+
</ListItem>
|
|
45
|
+
</List>
|
|
46
|
+
~~~
|
|
47
|
+
|
|
48
|
+
## Declarative JSON / Resolver
|
|
49
|
+
~~~json
|
|
50
|
+
{
|
|
51
|
+
"type": "ListItemButton",
|
|
52
|
+
"props": {
|
|
53
|
+
"startIcon": "lucide:mail",
|
|
54
|
+
"label": "Inbox",
|
|
55
|
+
"secondary": "Messages",
|
|
56
|
+
"sx": { "py": 1 },
|
|
57
|
+
"iconSx": { "minWidth": 36 },
|
|
58
|
+
"textSx": { "my": 0 }
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
~~~
|
|
62
|
+
`,
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
controls: {
|
|
66
|
+
exclude: ['component', 'children'],
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
argTypes: {
|
|
70
|
+
selected: { control: 'boolean' },
|
|
71
|
+
disabled: { control: 'boolean' },
|
|
72
|
+
dense: { control: 'boolean' },
|
|
73
|
+
divider: { control: 'boolean' },
|
|
74
|
+
alignItems: { control: { type: 'radio' }, options: ['center', 'flex-start'] },
|
|
75
|
+
sx: { control: 'object' },
|
|
76
|
+
},
|
|
77
|
+
args: {
|
|
78
|
+
selected: false,
|
|
79
|
+
disabled: false,
|
|
80
|
+
dense: false,
|
|
81
|
+
divider: false,
|
|
82
|
+
alignItems: 'center',
|
|
83
|
+
sx: {},
|
|
84
|
+
children: undefined,
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export default meta;
|
|
89
|
+
type Story = StoryObj<typeof ListItemButton>;
|
|
90
|
+
|
|
91
|
+
const DemoList: React.FC<{ children?: React.ReactNode }> = ({ children }) => (
|
|
92
|
+
<List dense sx={{ bgcolor: 'background.paper', borderRadius: 1, overflow: 'hidden', border: '1px solid', borderColor: 'divider' }}>
|
|
93
|
+
<ListItem disablePadding>{children}</ListItem>
|
|
94
|
+
</List>
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
// ======================= Stories =======================
|
|
98
|
+
export const Playground: Story = {
|
|
99
|
+
render: (args) => (
|
|
100
|
+
<DemoList>
|
|
101
|
+
<ListItemButton {...args}>
|
|
102
|
+
<ListItemIcon>
|
|
103
|
+
<Icon name="mail" />
|
|
104
|
+
</ListItemIcon>
|
|
105
|
+
<ListItemText primary="Inbox" secondary="Messages" />
|
|
106
|
+
</ListItemButton>
|
|
107
|
+
</DemoList>
|
|
108
|
+
),
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export const WithTrailingIcon: Story = {
|
|
112
|
+
render: () => (
|
|
113
|
+
<DemoList>
|
|
114
|
+
<ListItemButton>
|
|
115
|
+
<ListItemIcon>
|
|
116
|
+
<Icon name="settings" />
|
|
117
|
+
</ListItemIcon>
|
|
118
|
+
<ListItemText primary="Settings" secondary="Preferences" />
|
|
119
|
+
<span style={{ marginLeft: 'auto', display: 'inline-flex' }}>
|
|
120
|
+
<Icon name="chevron_right" />
|
|
121
|
+
</span>
|
|
122
|
+
</ListItemButton>
|
|
123
|
+
</DemoList>
|
|
124
|
+
),
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export const AsAnchorLink: Story = {
|
|
128
|
+
render: () => (
|
|
129
|
+
<DemoList>
|
|
130
|
+
<ListItemButton component="a" href="https://neurons.me">
|
|
131
|
+
<ListItemIcon>
|
|
132
|
+
<Icon name="link" />
|
|
133
|
+
</ListItemIcon>
|
|
134
|
+
<ListItemText primary="neurons.me" secondary="External link" />
|
|
135
|
+
</ListItemButton>
|
|
136
|
+
</DemoList>
|
|
137
|
+
),
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export const WithSx: Story = {
|
|
141
|
+
render: () => (
|
|
142
|
+
<DemoList>
|
|
143
|
+
<ListItemButton sx={{ py: 1.25 }}>
|
|
144
|
+
<ListItemIcon sx={{ minWidth: 40 }}>
|
|
145
|
+
<Icon name="person" />
|
|
146
|
+
</ListItemIcon>
|
|
147
|
+
<ListItemText
|
|
148
|
+
primary="Profile"
|
|
149
|
+
secondary="Account"
|
|
150
|
+
slotProps={{ secondary: { sx: { color: 'text.secondary' } } }}
|
|
151
|
+
/>
|
|
152
|
+
</ListItemButton>
|
|
153
|
+
</DemoList>
|
|
154
|
+
),
|
|
155
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This component is a thin wrapper around MUI’s ListItemButton.
|
|
3
|
+
* It preserves MUI’s props and typing, staying faithful to MUI.
|
|
4
|
+
*
|
|
5
|
+
* Why wrap it?
|
|
6
|
+
* - Consistency with This.GUI’s atom pattern (each atom has its own file).
|
|
7
|
+
* - Supports declarative/resolver usage while keeping all MUI props intact.
|
|
8
|
+
* - Allows granular style control via `sx`.
|
|
9
|
+
*/
|
|
10
|
+
import * as React from 'react';
|
|
11
|
+
import MuiListItemButton from '@mui/material/ListItemButton';
|
|
12
|
+
const ListItemButton = MuiListItemButton;
|
|
13
|
+
export type ListItemButtonProps = React.ComponentProps<typeof ListItemButton>;
|
|
14
|
+
(ListItemButton as any).displayName = 'Gui.ListItemButton';
|
|
15
|
+
export default ListItemButton;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// src/gui/atoms/ListItemIcon/ListItemIcon.resolver.tsx
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import ListItemIcon from './ListItemIcon';
|
|
4
|
+
import Icon from '@/gui/Theme/Icon/Icon';
|
|
5
|
+
import type { RegistryEntry, ResolveCtx } from '@/registry/types';
|
|
6
|
+
import type { SxProps, Theme } from '@mui/material/styles';
|
|
7
|
+
import { ensureNodeId } from '@/gui/utils/nodeID';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Declarative spec for ListItemIcon
|
|
11
|
+
*
|
|
12
|
+
* Fidelity
|
|
13
|
+
* - Forwards MUI props faithfully to `<ListItemIcon />`.
|
|
14
|
+
* - `children` has priority over any sugar props.
|
|
15
|
+
*
|
|
16
|
+
* Sugar
|
|
17
|
+
* - `icon`: string token (e.g., "lucide:mail", "mui:settings") or a ReactNode.
|
|
18
|
+
* - `iconProps`: forwarded to `<Icon />` when `icon` is a string.
|
|
19
|
+
* - `iconColor`: convenience alias mapped to Icon's color/htmlColor semantics.
|
|
20
|
+
* - `size`: sets Icon size (default 20).
|
|
21
|
+
*
|
|
22
|
+
* Editor/Inspector
|
|
23
|
+
* - Always emits a stable `data-gui-id` (auto via `ensureNodeId`) unless provided.
|
|
24
|
+
*/
|
|
25
|
+
export type ListItemIconSpec = {
|
|
26
|
+
type: 'ListItemIcon';
|
|
27
|
+
props?: {
|
|
28
|
+
// content
|
|
29
|
+
children?: React.ReactNode;
|
|
30
|
+
|
|
31
|
+
// sugar for registry-driven icons
|
|
32
|
+
icon?: React.ReactNode | string;
|
|
33
|
+
iconProps?: Record<string, any>;
|
|
34
|
+
iconColor?: string;
|
|
35
|
+
size?: number;
|
|
36
|
+
|
|
37
|
+
// styling
|
|
38
|
+
sx?: SxProps<Theme>;
|
|
39
|
+
className?: string;
|
|
40
|
+
id?: string;
|
|
41
|
+
'data-testid'?: string;
|
|
42
|
+
|
|
43
|
+
// inspector id (auto if omitted)
|
|
44
|
+
'data-gui-id'?: string;
|
|
45
|
+
|
|
46
|
+
// passthrough
|
|
47
|
+
[key: string]: any;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const normalizeToken = (s: string) => String(s).trim().toLowerCase();
|
|
52
|
+
|
|
53
|
+
const ListItemIconResolver: RegistryEntry = {
|
|
54
|
+
type: 'ListItemIcon',
|
|
55
|
+
resolve(spec: ListItemIconSpec, _ctx?: ResolveCtx) {
|
|
56
|
+
const p = spec.props ?? {};
|
|
57
|
+
|
|
58
|
+
// Build content with precedence: children > icon sugar
|
|
59
|
+
const { children, icon, iconColor, iconProps, size = 20 } = p;
|
|
60
|
+
let content: React.ReactNode = children;
|
|
61
|
+
if (content == null && icon) {
|
|
62
|
+
content =
|
|
63
|
+
typeof icon === 'string'
|
|
64
|
+
? <Icon name={normalizeToken(icon)} iconColor={iconColor} fontSize={size} {...iconProps} />
|
|
65
|
+
: icon;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Prepare safe props for ListItemIcon (avoid leaking resolver-only keys)
|
|
69
|
+
const {
|
|
70
|
+
// sugar / resolver-only
|
|
71
|
+
icon: _icon,
|
|
72
|
+
iconProps: _iconProps,
|
|
73
|
+
iconColor: _iconColor,
|
|
74
|
+
size: _size,
|
|
75
|
+
'data-gui-id': providedNodeId,
|
|
76
|
+
// keep common
|
|
77
|
+
sx,
|
|
78
|
+
className,
|
|
79
|
+
id,
|
|
80
|
+
'data-testid': dataTestId,
|
|
81
|
+
// everything else passes through
|
|
82
|
+
...rest
|
|
83
|
+
} = p;
|
|
84
|
+
|
|
85
|
+
const dataGuiId = ensureNodeId('list-item-icon', providedNodeId);
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<ListItemIcon
|
|
89
|
+
sx={sx}
|
|
90
|
+
className={className}
|
|
91
|
+
id={id}
|
|
92
|
+
data-testid={dataTestId}
|
|
93
|
+
data-gui-id={dataGuiId}
|
|
94
|
+
{...rest}
|
|
95
|
+
>
|
|
96
|
+
{content}
|
|
97
|
+
</ListItemIcon>
|
|
98
|
+
);
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export default ListItemIconResolver;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import List from '@mui/material/List';
|
|
4
|
+
import ListItem from '@mui/material/ListItem';
|
|
5
|
+
import ListItemText from '@/gui/components/atoms/ListItemText/ListItemText';
|
|
6
|
+
import ListItemIcon from './ListItemIcon';
|
|
7
|
+
import Icon from '@/gui/Theme/Icon/Icon';
|
|
8
|
+
import GuiProvider from '@/gui/Theme/GuiProvider';
|
|
9
|
+
|
|
10
|
+
const meta: Meta<typeof ListItemIcon> = {
|
|
11
|
+
title: 'Atoms/Organization/ListItemIcon',
|
|
12
|
+
component: ListItemIcon,
|
|
13
|
+
tags: ['autodocs'],
|
|
14
|
+
decorators: [
|
|
15
|
+
(Story) => (
|
|
16
|
+
<GuiProvider>
|
|
17
|
+
<div style={{ padding: 16, minHeight: 260, maxWidth: 520 }}>
|
|
18
|
+
<Story />
|
|
19
|
+
</div>
|
|
20
|
+
</GuiProvider>
|
|
21
|
+
),
|
|
22
|
+
],
|
|
23
|
+
parameters: {
|
|
24
|
+
docs: {
|
|
25
|
+
description: {
|
|
26
|
+
component: `
|
|
27
|
+
The **ListItemIcon** atom is a thin wrapper around MUI's \`MuiListItemIcon\` and remains faithful to its API.
|
|
28
|
+
|
|
29
|
+
In **declarative** mode, the resolver adds sugar to render icons by **token** via the registry:
|
|
30
|
+
- \`icon\`: string token (e.g., \`"lucide:mail"\`, \`"mui:settings"\`) or React node
|
|
31
|
+
- \`iconProps\`: forwarded to the registry \`<Icon />\` when \`icon\` is a token
|
|
32
|
+
- \`iconColor\`: convenience color for the registry icon
|
|
33
|
+
- \`size\`: icon size (default 20)
|
|
34
|
+
|
|
35
|
+
Tokens are **normalized** (lowercased & trimmed) to avoid missing icons due to casing.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
## React usage
|
|
39
|
+
~~~jsx
|
|
40
|
+
<List>
|
|
41
|
+
<ListItem>
|
|
42
|
+
<ListItemIcon sx={{ minWidth: 36 }}>
|
|
43
|
+
<Icon name="lucide:mail" size={20} />
|
|
44
|
+
</ListItemIcon>
|
|
45
|
+
<ListItemText primary="Inbox" />
|
|
46
|
+
</ListItem>
|
|
47
|
+
</List>
|
|
48
|
+
~~~
|
|
49
|
+
|
|
50
|
+
## Declarative JSON / Resolver
|
|
51
|
+
~~~json
|
|
52
|
+
{
|
|
53
|
+
"type": "ListItemIcon",
|
|
54
|
+
"props": {
|
|
55
|
+
"icon": "lucide:mail",
|
|
56
|
+
"sx": { "minWidth": 36 },
|
|
57
|
+
"iconProps": { "strokeWidth": 1.5 }
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
~~~
|
|
61
|
+
`,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
controls: {
|
|
65
|
+
exclude: ['children'],
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
argTypes: {
|
|
69
|
+
sx: { control: 'object', table: { category: 'Style' } },
|
|
70
|
+
className: { control: 'text' },
|
|
71
|
+
},
|
|
72
|
+
args: {
|
|
73
|
+
sx: {},
|
|
74
|
+
children: undefined,
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export default meta;
|
|
79
|
+
type Story = StoryObj<typeof ListItemIcon>;
|
|
80
|
+
|
|
81
|
+
const DemoList: React.FC<{ children?: React.ReactNode }> = ({ children }) => (
|
|
82
|
+
<List dense>
|
|
83
|
+
<ListItem>{children}</ListItem>
|
|
84
|
+
</List>
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
// ======================= Stories =======================
|
|
88
|
+
export const Playground: Story = {
|
|
89
|
+
render: (args) => (
|
|
90
|
+
<DemoList>
|
|
91
|
+
<ListItemIcon {...args}>
|
|
92
|
+
<Icon name="lucide:mail" />
|
|
93
|
+
</ListItemIcon>
|
|
94
|
+
<ListItemText primary="Item with icon slot" />
|
|
95
|
+
</DemoList>
|
|
96
|
+
),
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export const WithTokenViaResolverExample: Story = {
|
|
100
|
+
name: 'Declarative token (doc example)',
|
|
101
|
+
render: () => (
|
|
102
|
+
<DemoList>
|
|
103
|
+
{/* Emula el resultado del resolver al usar icon="lucide:mail" */}
|
|
104
|
+
<ListItemIcon sx={{ minWidth: 36 }}>
|
|
105
|
+
<Icon name="mail" fontSize={20} />
|
|
106
|
+
</ListItemIcon>
|
|
107
|
+
<ListItemText primary="Inbox (token)" />
|
|
108
|
+
</DemoList>
|
|
109
|
+
),
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export const WithReactChild: Story = {
|
|
113
|
+
render: () => (
|
|
114
|
+
<DemoList>
|
|
115
|
+
<ListItemIcon sx={{ minWidth: 40 }}>
|
|
116
|
+
<Icon name="mui:settings" />
|
|
117
|
+
</ListItemIcon>
|
|
118
|
+
<ListItemText primary="Settings (React child)" />
|
|
119
|
+
</DemoList>
|
|
120
|
+
),
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export const WithSx: Story = {
|
|
124
|
+
render: () => (
|
|
125
|
+
<DemoList>
|
|
126
|
+
<ListItemIcon sx={{ minWidth: 48 }}>
|
|
127
|
+
<Icon name="lucide:user" />
|
|
128
|
+
</ListItemIcon>
|
|
129
|
+
<ListItemText primary="Custom minWidth via sx" />
|
|
130
|
+
</DemoList>
|
|
131
|
+
),
|
|
132
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This.GUI — ListItemIcon
|
|
3
|
+
* Thin wrapper that preserves MUI typing.
|
|
4
|
+
* Use our resolver for declarative sugar (icon tokens) and granular styling patterns.
|
|
5
|
+
*/
|
|
6
|
+
import * as React from 'react';
|
|
7
|
+
import MuiListItemIcon from '@mui/material/ListItemIcon';
|
|
8
|
+
const ListItemIcon = MuiListItemIcon;
|
|
9
|
+
export type ListItemIconProps = React.ComponentProps<typeof ListItemIcon>;
|
|
10
|
+
(ListItemIcon as any).displayName = 'Gui.ListItemIcon';
|
|
11
|
+
export default ListItemIcon;
|