♻️ refactor(wip): refactor with @lobehub/ui

This commit is contained in:
canisminor1990 2023-06-18 23:19:11 +08:00
parent e9e51e66b2
commit e116458d10
8 changed files with 872 additions and 499 deletions

View File

@ -1 +1 @@
module.exports = require('@lobehub/lint/dist/semantic-release'); module.exports = require('@lobehub/lint').semanticRelease;

File diff suppressed because one or more lines are too long

View File

@ -51,6 +51,7 @@
"@ant-design/icons": "^5", "@ant-design/icons": "^5",
"@commitlint/cli": "^17", "@commitlint/cli": "^17",
"@lobehub/lint": "latest", "@lobehub/lint": "latest",
"@lobehub/ui": "latest",
"@types/lodash-es": "^4", "@types/lodash-es": "^4",
"@types/node": "^20", "@types/node": "^20",
"@types/react": "^18", "@types/react": "^18",
@ -62,7 +63,7 @@
"@umijs/lint": "^4", "@umijs/lint": "^4",
"ahooks": "^3", "ahooks": "^3",
"antd": "^5", "antd": "^5",
"antd-style": "^3", "antd-style": "latest",
"babel-plugin-styled-components": "^2", "babel-plugin-styled-components": "^2",
"browserslist": "^4", "browserslist": "^4",
"commitlint": "^17", "commitlint": "^17",
@ -83,14 +84,13 @@
"react-dnd": "^16", "react-dnd": "^16",
"react-dnd-html5-backend": "^16", "react-dnd-html5-backend": "^16",
"react-dom": "^18", "react-dom": "^18",
"react-font-loader": "^2",
"react-layout-kit": "^1", "react-layout-kit": "^1",
"react-rnd": "^10", "react-rnd": "^10",
"react-tag-input": "^6", "react-tag-input": "^6",
"remark": "^14", "remark": "^14",
"remark-cli": "^11", "remark-cli": "^11",
"semantic-release": "^21", "semantic-release": "^21",
"styled-components": "^5", "styled-components": "latest",
"stylelint": "^15", "stylelint": "^15",
"typescript": "^5", "typescript": "^5",
"umi": "^4", "umi": "^4",

View File

@ -1,12 +1,12 @@
import { ZoomInOutlined } from '@ant-design/icons'; import {ZoomInOutlined} from '@ant-design/icons';
import { Slider } from 'antd'; import {DraggablePanel} from '@lobehub/ui';
import { useResponsive } from 'antd-style'; import {Slider} from 'antd';
import { type CSSProperties, type ReactNode, memo, useEffect, useState } from 'react'; import {useResponsive} from 'antd-style';
import styled, { createGlobalStyle } from 'styled-components'; import {type CSSProperties, type ReactNode, memo, useEffect, useState} from 'react';
import { shallow } from 'zustand/shallow'; import styled, {createGlobalStyle} from 'styled-components';
import {shallow} from 'zustand/shallow';
import { DraggablePanel } from '@/components'; import {useAppStore} from '@/store';
import { useAppStore } from '@/store';
const GlobalStyle = createGlobalStyle` const GlobalStyle = createGlobalStyle`
button#txt2img_extra_networks, button#txt2img_extra_networks,
@ -40,11 +40,11 @@ const SidebarView = styled.div<{ size: number }>`
.extra-network-cards, .extra-network-cards,
.extra-network-thumbs { .extra-network-thumbs {
display: grid; display: grid;
grid-template-columns: repeat(auto-fill, minmax(${({ size }) => size}px, 1fr)); grid-template-columns: repeat(auto-fill, minmax(${({size}) => size}px, 1fr));
> .card { > .card {
width: var(--fill-available) !important; width: var(--fill-available) !important;
height: ${({ size }) => size * 1.5}px !important; height: ${({size}) => size * 1.5}px !important;
} }
} }
`; `;
@ -71,44 +71,44 @@ interface SidebarProps {
style?: CSSProperties; style?: CSSProperties;
} }
const Sidebar = memo<SidebarProps>(({ children, style }) => { const Sidebar = memo<SidebarProps>(({children, style}) => {
const { mobile } = useResponsive(); const {mobile} = useResponsive();
const [setting] = useAppStore((st) => [st.setting], shallow); const [setting] = useAppStore((st) => [st.setting], shallow);
const [mode] = useState<'fixed' | 'float'>(setting.extraNetworkFixedMode); const [mode] = useState<'fixed' | 'float'>(setting.extraNetworkFixedMode);
const [expand, setExpand] = useState<boolean>(setting.extraNetworkSidebarExpand); const [expand, setExpand] = useState<boolean>(setting.extraNetworkSidebarExpand);
const [size, setSize] = useState<number>(setting?.extraNetworkCardSize || 86); const [size, setSize] = useState<number>(setting?.extraNetworkCardSize || 86);
useEffect(() => { useEffect(() => {
if (mobile) setExpand(false); if (mobile) setExpand(false);
}, []); }, []);
return ( return (
<> <>
<GlobalStyle /> <GlobalStyle />
<DraggablePanel <DraggablePanel
defaultSize={{ width: setting.extraNetworkSidebarWidth }} defaultSize={{width: setting.extraNetworkSidebarWidth}}
expand={expand} expand={expand}
minWidth={setting.extraNetworkSidebarWidth} minWidth={setting.extraNetworkSidebarWidth}
mode={mode} mode={mode}
onExpandChange={setExpand} onExpandChange={setExpand}
pin={mode === 'fixed'} pin={mode === 'fixed'}
placement="right" placement="right"
style={{ style={{
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
...style, ...style,
}} }}
> >
<View> <View>
<SidebarView size={size}>{children}</SidebarView> <SidebarView size={size}>{children}</SidebarView>
<Footer> <Footer>
<ZoomInOutlined /> <ZoomInOutlined />
<ZoomSlider defaultValue={size} max={256} min={64} onChange={setSize} step={8} /> <ZoomSlider defaultValue={size} max={256} min={64} onChange={setSize} step={8} />
</Footer> </Footer>
</View> </View>
</DraggablePanel> </DraggablePanel>
</> </>
); );
}); });
export default Sidebar; export default Sidebar;

View File

@ -1,77 +1,33 @@
import type {MenuProps} from 'antd'; import {TabsNav, type TabsNavProps} from '@lobehub/ui';
import {Menu} from 'antd';
import {memo, useEffect, useState} from 'react'; import {memo, useEffect, useState} from 'react';
import styled from 'styled-components';
/****************************************************** const getNavButtons: HTMLButtonElement[] | any = () =>
*********************** Style ************************* gradioApp().querySelectorAll('#tabs > .tab-nav:first-child button') || [];
******************************************************/
const NavBar = styled(Menu)` const onChange: TabsNavProps['onChange'] = (activeKey) => {
overflow: hidden; const buttons = getNavButtons();
flex: 1; buttons[Number(activeKey)]?.click();
line-height: 1;
border: none;
.ant-menu-overflow-item {
padding: 8px 12px;
color: var(--color-text-secondary);
border-radius: 4px !important;
&::after {
display: none !important;
}
&:hover {
color: var(--color-text);
background: var(--color-fill-tertiary);
}
&.ant-menu-item-selected {
font-weight: 600;
color: var(--color-text);
}
}
`;
/******************************************************
************************* Dom *************************
******************************************************/
const onClick: MenuProps['onClick'] = (e: any) => {
const buttons: HTMLButtonElement[] | any = gradioApp().querySelectorAll(
'#tabs > .tab-nav:first-child button',
);
buttons[Number(e.key)]?.click();
}; };
const Nav = memo(() => { const Nav = memo(() => {
const [items, setItems] = useState<MenuProps['items']>([]); const [items, setItems] = useState<TabsNavProps['items']>([]);
useEffect(() => { useEffect(() => {
onUiLoaded(() => { onUiLoaded(() => {
const buttons = gradioApp().querySelectorAll('#tabs > .tab-nav:first-child button'); const buttons = getNavButtons();
const list: MenuProps['items'] | any = []; const list: TabsNavProps['items'] | any = [];
buttons.forEach((button: HTMLButtonElement | any, index) => { buttons.forEach((button: HTMLButtonElement | any, index: number) => {
button.id = `kitchen-nav-${index}`; button.id = `kitchen-nav-${index}`;
list.push({ list.push({
key: String(index), key: String(index),
label: button.textContent, label: button.textContent,
}); });
}); });
setItems(list); setItems(list.filter(Boolean));
}); });
}, []); }, []);
return ( return <TabsNav items={items} onChange={onChange} />;
<NavBar
defaultActiveFirst
defaultSelectedKeys={['0']}
items={items}
mode="horizontal"
onClick={onClick}
/>
);
}); });
export default Nav; export default Nav;

View File

@ -1,12 +1,10 @@
import {BoldOutlined, GithubOutlined} from '@ant-design/icons'; import {BoldOutlined, GithubOutlined} from '@ant-design/icons';
import {Header as H} from '@lobehub/ui';
import {Button, Modal, Space} from 'antd'; import {Button, Modal, Space} from 'antd';
import {useResponsive} from 'antd-style';
import qs from 'query-string'; import qs from 'query-string';
import {type ReactNode, memo, useCallback, useEffect, useState} from 'react'; import {type ReactNode, memo, useCallback, useState} from 'react';
import styled from 'styled-components';
import {shallow} from 'zustand/shallow'; import {shallow} from 'zustand/shallow';
import {DraggablePanel} from '@/components';
import {useAppStore} from '@/store'; import {useAppStore} from '@/store';
import Giscus from './Giscus'; import Giscus from './Giscus';
@ -15,39 +13,14 @@ import Nav from './Nav';
import Setting from './Setting'; import Setting from './Setting';
import {civitaiLogo, themeIcon} from './style'; import {civitaiLogo, themeIcon} from './style';
/******************************************************
*********************** Style *************************
******************************************************/
const HeaderView = styled.div`
display: flex;
flex-wrap: nowrap;
gap: 12px;
align-items: center;
justify-content: space-between;
height: var(--fill-available);
padding: 16px 24px;
`;
/******************************************************
************************* Dom *************************
******************************************************/
interface HeaderProps { interface HeaderProps {
children: ReactNode; children: ReactNode;
} }
const Header = memo<HeaderProps>(({children}) => { const Header = memo<HeaderProps>(({children}) => {
const [themeMode] = useAppStore((st) => [st.themeMode], shallow); const [themeMode] = useAppStore((st) => [st.themeMode], shallow);
const {mobile} = useResponsive();
const [expand, setExpand] = useState<boolean>(true);
const [isModalOpen, setIsModalOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false);
useEffect(() => {
if (mobile) setExpand(false);
}, []);
const handleSetTheme = useCallback(() => { const handleSetTheme = useCallback(() => {
const theme = themeMode === 'light' ? 'dark' : 'light'; const theme = themeMode === 'light' ? 'dark' : 'light';
const gradioURL = qs.parseUrl(window.location.href); const gradioURL = qs.parseUrl(window.location.href);
@ -61,25 +34,8 @@ const Header = memo<HeaderProps>(({children}) => {
return ( return (
<> <>
<DraggablePanel <H
defaultSize={{height: 'auto'}} actions={
expand={expand}
minHeight={64}
onExpandChange={setExpand}
placement="top"
>
<HeaderView id="header" style={{flexDirection: mobile ? 'column' : 'row'}}>
<a
href="https://github.com/canisminor1990/sd-webui-kitchen-theme"
rel="noreferrer"
target="_blank"
>
<Logo themeMode={themeMode} />
</a>
<Nav />
{children}
<Space.Compact> <Space.Compact>
<a href="https://civitai.com/" rel="noreferrer" target="_blank"> <a href="https://civitai.com/" rel="noreferrer" target="_blank">
<Button icon={civitaiLogo} title="Civitai" /> <Button icon={civitaiLogo} title="Civitai" />
@ -95,8 +51,23 @@ const Header = memo<HeaderProps>(({children}) => {
<Setting /> <Setting />
<Button icon={themeIcon[themeMode]} onClick={handleSetTheme} title="Switch Theme" /> <Button icon={themeIcon[themeMode]} onClick={handleSetTheme} title="Switch Theme" />
</Space.Compact> </Space.Compact>
</HeaderView> }
</DraggablePanel> logo={
<a
href="https://github.com/canisminor1990/sd-webui-kitchen-theme"
rel="noreferrer"
target="_blank"
>
<Logo themeMode={themeMode} />
</a>
}
nav={
<>
<Nav />
{children}
</>
}
/>
<Modal <Modal
footer={false} footer={false}
onCancel={handleCancel} onCancel={handleCancel}

View File

@ -1,10 +1,10 @@
import { useResponsive } from 'antd-style'; import {DraggablePanel} from '@lobehub/ui';
import { type CSSProperties, type ReactNode, memo, useEffect, useState } from 'react'; import {useResponsive} from 'antd-style';
import {type CSSProperties, type ReactNode, memo, useEffect, useState} from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import { shallow } from 'zustand/shallow'; import {shallow} from 'zustand/shallow';
import { DraggablePanel } from '@/components'; import {useAppStore} from '@/store';
import { useAppStore } from '@/store';
import PromptGroup from './PromptGroup'; import PromptGroup from './PromptGroup';
@ -29,37 +29,37 @@ interface SidebarProps {
style?: CSSProperties; style?: CSSProperties;
} }
const Sidebar = memo<SidebarProps>(({ children, loading, style }) => { const Sidebar = memo<SidebarProps>(({children, loading, style}) => {
const [setting] = useAppStore((st) => [st.setting], shallow); const [setting] = useAppStore((st) => [st.setting], shallow);
const [mode] = useState<'fixed' | 'float'>(setting.sidebarFixedMode); const [mode] = useState<'fixed' | 'float'>(setting.sidebarFixedMode);
const { mobile } = useResponsive(); const {mobile} = useResponsive();
const [expand, setExpand] = useState<boolean>(setting.sidebarExpand); const [expand, setExpand] = useState<boolean>(setting.sidebarExpand);
useEffect(() => { useEffect(() => {
if (mobile) setExpand(false); if (mobile) setExpand(false);
}, []); }, []);
return ( return (
<DraggablePanel <DraggablePanel
defaultSize={{ width: setting.sidebarWidth }} defaultSize={{width: setting.sidebarWidth}}
expand={expand} expand={expand}
minWidth={setting.sidebarWidth} minWidth={setting.sidebarWidth}
mode={mode} mode={mode}
onExpandChange={setExpand} onExpandChange={setExpand}
pin={mode === 'fixed'} pin={mode === 'fixed'}
placement="left" placement="left"
style={{ style={{
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
...style, ...style,
}} }}
> >
<SidebarView> <SidebarView>
{!loading && <PromptGroup />} {!loading && <PromptGroup />}
{children} {children}
</SidebarView> </SidebarView>
</DraggablePanel> </DraggablePanel>
); );
}); });
export default Sidebar; export default Sidebar;

View File

@ -1,10 +1,7 @@
import {ThemeProvider, setupStyled} from 'antd-style'; import {ThemeProvider} from '@lobehub/ui';
import qs from 'query-string'; import qs from 'query-string';
import {memo, useEffect, useState} from 'react'; import {memo, useEffect, useState} from 'react';
import {createRoot} from 'react-dom/client'; import {createRoot} from 'react-dom/client';
// @ts-ignore
import ReactFontLoader from 'react-font-loader';
import {ThemeContext} from 'styled-components';
import {shallow} from 'zustand/shallow'; import {shallow} from 'zustand/shallow';
import {useIsDarkMode} from '@/components/theme/useIsDarkMode'; import {useIsDarkMode} from '@/components/theme/useIsDarkMode';
@ -15,11 +12,8 @@ import {useAppStore} from '@/store';
import '@/theme/style.less'; import '@/theme/style.less';
import App from './App'; import App from './App';
import GlobalStyle from './GlobalStyle';
import {baseToken} from './style';
const Root = memo(() => { const Root = memo(() => {
setupStyled({ThemeContext});
const [onSetThemeMode, onInit] = useAppStore((st) => [st.onSetThemeMode, st.onInit], shallow); const [onSetThemeMode, onInit] = useAppStore((st) => [st.onSetThemeMode, st.onInit], shallow);
const isDarkMode = useIsDarkMode(); const isDarkMode = useIsDarkMode();
const [appearance, setAppearance] = useState<'light' | 'dark'>('light'); const [appearance, setAppearance] = useState<'light' | 'dark'>('light');
@ -47,10 +41,7 @@ const Root = memo(() => {
window.location.reload(); window.location.reload();
}, [isDarkMode]); }, [isDarkMode]);
return ( return (
<ThemeProvider appearance={appearance} theme={{token: baseToken}}> <ThemeProvider themeMode={appearance}>
<GlobalStyle />
<ReactFontLoader url="https://raw.githubusercontent.com/IKKI2000/harmonyos-fonts/main/css/harmonyos_sans.css" />
<ReactFontLoader url="https://raw.githubusercontent.com/IKKI2000/harmonyos-fonts/main/css/harmonyos_sans_sc.css" />
<App /> <App />
</ThemeProvider> </ThemeProvider>
); );