🐛 fix: extranetwork model load and some ui bugs [#58,#81,#77]

main
canisminor1990 2023-05-17 23:42:10 +08:00
parent 58a2dea924
commit 090fad8050
24 changed files with 677 additions and 1037 deletions

View File

@ -23,4 +23,14 @@ jobs:
body: |
Since the issue was labeled with `🤔 Need Reproduce`, but no response in 3 days. This issue will be closed. If you have any questions, you can comment and reply.
由于该 issue 被标记为需要更多信息,却 3 天未收到回应。现关闭 issue若有任何问题可评论回复。
由于该 issue 被标记为需要更多信息,却 3 天未收到回应。现关闭 issue若有任何问题可评论回复。
- name: need reproduce
uses: actions-cool/issues-helper@v3
with:
actions: 'close-issues'
labels: '🙅🏻‍♀️ WON'T DO'
inactive-day: 3
body: |
Since the issue was labeled with `🙅🏻‍♀️ WON'T DO`, and no response in 3 days. This issue will be closed. If you have any questions, you can comment and reply.
由于该 issue 被标记为暂不处理,却 3 天未收到回应。现关闭 issue若有任何问题可评论回复。

File diff suppressed because one or more lines are too long

View File

@ -99,5 +99,8 @@
"use-merge-value": "^1",
"webpack-shell-plugin-next": "^2",
"zustand": "^4"
},
"dependencies": {
"lucide-react": "^0.217.0"
}
}

View File

@ -1,174 +0,0 @@
import type { NumberSize, Size } from 're-resizable'
import type { CSSProperties, FC, ReactNode } from 'react'
import { memo } from 'react'
import type { Props as RndProps } from 'react-rnd'
import { FixMode, placementType } from './FixMode'
import { FloatMode } from './FloatMode'
export interface DraggablePanelProps {
/**
*
* 使
*/
mode?: 'fixed' | 'float'
/**
*
* @default right
*/
placement?: placementType
/**
*
*/
minWidth?: number
/**
*
*/
minHeight?: number
/**
*
*/
resize?: RndProps['enableResizing']
/**
*
*
*/
size?: Partial<Size>
onSizeChange?: (delta: NumberSize, size?: Size) => void
/**
*
* @param delta
* @param size
*/
onSizeDragging?: (delta: NumberSize, size?: Size) => void
/**
*
* @default true
*/
expandable?: boolean
/**
*
*/
isExpand?: boolean
/**
*
* @param expand
*/
onExpandChange?: (expand: boolean) => void
/**
*
*
*/
position?: RndProps['position']
/**
*
* width 320px height 100%
* width 320px height 400px
*/
defaultSize?: Partial<Size>
/**
*
* @default [100,100]
*/
defaultPosition?: RndProps['position']
/**
*
*/
onPositionChange?: (position: RndProps['position']) => void
/**
*
*/
style?: CSSProperties
/**
*
*/
className?: string
/**
*
*/
children: ReactNode
/**
*
*/
prefixCls?: string
maxHeight?: boolean
}
export const Draggable: FC<DraggablePanelProps> = memo(
({
children,
className,
mode,
placement = 'right',
resize,
style,
position,
onPositionChange,
size,
defaultSize,
defaultPosition,
minWidth,
minHeight,
onSizeChange,
onSizeDragging,
expandable = true,
isExpand,
onExpandChange,
maxHeight,
}) => {
const prefixCls = 'draggable-panel'
switch (mode) {
case 'fixed':
default:
return (
<FixMode
prefixCls={prefixCls}
// 尺寸
size={size}
defaultSize={defaultSize}
onSizeDragging={onSizeDragging}
onSizeChange={onSizeChange}
minHeight={minHeight}
minWidth={minWidth}
// 缩放
resize={resize}
onExpandChange={onExpandChange}
expandable={expandable}
isExpand={isExpand}
className={className}
placement={placement}
style={style}
maxHeight={maxHeight}
>
{children}
</FixMode>
)
case 'float':
return (
<FloatMode
prefixCls={prefixCls}
// 坐标
defaultPosition={defaultPosition}
position={position}
onPositionChange={onPositionChange}
// 尺寸
minHeight={minHeight}
minWidth={minWidth}
defaultSize={defaultSize}
size={size}
onSizeDragging={onSizeDragging}
onSizeChange={onSizeChange}
// 缩放
resize={resize}
canResizing={resize !== false}
className={className}
style={style}
>
{children}
</FloatMode>
)
}
}
)

View File

@ -1,250 +0,0 @@
import { DownOutlined, LeftOutlined, RightOutlined, UpOutlined } from '@ant-design/icons'
import type { Enable, NumberSize, Size } from 're-resizable'
import { HandleClassName, Resizable } from 're-resizable'
import type { CSSProperties, FC, ReactNode } from 'react'
import { memo, useMemo } from 'react'
import { Center } from 'react-layout-kit'
import type { Props as RndProps } from 'react-rnd'
import useControlledState from 'use-merge-value'
import { useStyle } from './style'
export type placementType = 'right' | 'left' | 'top' | 'bottom'
export interface FixModePanelProps {
/**
*
* 使
*/
mode?: 'fixed' | 'float'
/**
*
* @default right
*/
placement: placementType
/**
*
*/
minWidth?: number
/**
*
*/
minHeight?: number
/**
*
*/
resize?: RndProps['enableResizing']
/**
*
*
*/
size?: Partial<Size>
onSizeChange?: (delta: NumberSize, size?: Size) => void
/**
*
* @param delta
* @param size
*/
onSizeDragging?: (delta: NumberSize, size?: Size) => void
/**
*
* @default true
*/
expandable?: boolean
/**
*
*/
isExpand?: boolean
/**
*
* @param expand
*/
onExpandChange?: (expand: boolean) => void
/**
*
*
*/
position?: RndProps['position']
/**
*
* width 320px height 100%
* width 320px height 400px
*/
defaultSize?: Partial<Size>
/**
*
* @default [100,100]
*/
defaultPosition?: RndProps['position']
/**
*
*/
onPositionChange?: (position: RndProps['position']) => void
/**
*
*/
style?: CSSProperties
className?: string
/**
*
*/
children: ReactNode
/**
*
*/
prefixCls?: string
maxHeight?: boolean
}
const DEFAULT_HEIGHT = 150
const DEFAULT_WIDTH = 400
const revesePlacement = (placement: placementType) => {
switch (placement) {
case 'bottom':
return 'top'
case 'top':
return 'bottom'
case 'right':
return 'left'
case 'left':
return 'right'
}
}
export const FixMode: FC<FixModePanelProps> = memo<FixModePanelProps>(
({
children,
placement = 'right',
resize,
style,
size,
defaultSize: customizeDefaultSize,
minWidth,
minHeight,
onSizeChange,
onSizeDragging,
expandable = true,
isExpand: expand,
onExpandChange,
className,
maxHeight,
}) => {
const prefixCls = 'draggable-panel'
const isVertical = placement === 'top' || placement === 'bottom'
const { styles, cx } = useStyle({ prefix: prefixCls, maxHeight })
const [isExpand, setIsExpand] = useControlledState(true, {
value: expand,
onChange: onExpandChange,
})
// 只有配置了 resize 和 isExpand 属性后才可拖拽
const canResizing = resize !== false && isExpand
const resizeHandleClassNames: HandleClassName = useMemo(() => {
if (!canResizing) return {}
return {
[revesePlacement(placement)]: styles[`${revesePlacement(placement)}Handle`],
}
}, [canResizing, placement])
const resizing = {
top: false,
bottom: false,
right: false,
left: false,
topRight: false,
bottomRight: false,
bottomLeft: false,
topLeft: false,
[revesePlacement(placement)]: true,
...(resize as Enable),
}
const defaultSize: Size = useMemo(() => {
if (isVertical)
return {
width: '100%',
height: DEFAULT_HEIGHT,
...customizeDefaultSize,
}
return {
width: DEFAULT_WIDTH,
height: '100%',
...customizeDefaultSize,
}
}, [isVertical])
const sizeProps = isExpand
? {
minWidth: typeof minWidth === 'number' ? Math.max(minWidth, 0) : 280,
minHeight: typeof minHeight === 'number' ? Math.max(minHeight, 0) : undefined,
defaultSize,
size: size as Size,
style,
}
: {
minWidth: 0,
minHeight: 0,
size: { width: 0, height: 0 },
}
const { Arrow, className: arrowPlacement } = useMemo(() => {
switch (placement) {
case 'top':
return { className: 'Bottom', Arrow: DownOutlined }
case 'bottom':
return { className: 'Top', Arrow: UpOutlined }
case 'right':
return { className: 'Left', Arrow: LeftOutlined }
case 'left':
return { className: 'Right', Arrow: RightOutlined }
}
}, [styles, placement])
return (
<div className={cx(styles.container, className)} style={{ [`border${arrowPlacement}Width`]: 1 }}>
{expandable && (
<Center
// @ts-ignore
className={cx(styles[`toggle${arrowPlacement}`])}
onClick={() => {
setIsExpand(!isExpand)
}}
style={{ opacity: isExpand ? undefined : 1 }}
>
<Arrow rotate={isExpand ? 180 : 0} />
</Center>
)}
{
<Resizable
{...sizeProps}
className={styles.fixed}
enable={canResizing ? (resizing as Enable) : undefined}
handleClasses={resizeHandleClassNames}
onResizeStop={(e, direction, ref, delta) => {
onSizeChange?.(delta, {
width: ref.style.width,
height: ref.style.height,
})
}}
onResize={(_, direction, ref, delta) => {
onSizeDragging?.(delta, {
width: ref.style.width,
height: ref.style.height,
})
}}
>
{children}
</Resizable>
}
</div>
)
}
)

View File

@ -1,174 +0,0 @@
import type { Enable, NumberSize, Size } from 're-resizable'
import { HandleClassName } from 're-resizable'
import type { CSSProperties, FC, ReactNode } from 'react'
import { memo, useMemo } from 'react'
import type { Position, Props as RndProps } from 'react-rnd'
import { Rnd } from 'react-rnd'
import { useStyle } from './style'
export interface FloatProps {
/**
*
* 使
*/
mode?: 'fixed' | 'float'
/**
*
* @default horizontal
*/
direction?: 'vertical' | 'horizontal'
/**
*
*/
minWidth?: number
/**
*
*/
minHeight?: number
/**
*
*/
resize?: RndProps['enableResizing']
/**
*
*
*/
size?: Partial<Size>
onSizeChange?: (delta: NumberSize, size?: Size) => void
/**
*
* @param delta
* @param size
*/
onSizeDragging?: (delta: NumberSize, size?: Size) => void
canResizing?: boolean
/**
*
*
*/
position?: RndProps['position']
/**
*
* width 320px height 100%
* width 320px height 400px
*/
defaultSize?: Partial<Size>
/**
*
* @default [100,100]
*/
defaultPosition?: RndProps['position']
/**
*
*/
onPositionChange?: (position: RndProps['position']) => void
/**
*
*/
style?: CSSProperties
/**
*
*/
className?: string
/**
*
*/
children: ReactNode
/**
*
*/
prefixCls?: string
}
const DEFAULT_HEIGHT = 300
const DEFAULT_WIDTH = 400
export const FloatMode: FC<FloatProps> = memo(
({
children,
direction,
resize,
style,
position,
onPositionChange,
size,
defaultSize: customizeDefaultSize,
defaultPosition: customizeDefaultPosition,
minWidth = 280,
minHeight = 200,
prefixCls,
canResizing,
}) => {
const { styles } = useStyle({ prefix: prefixCls, maxHeight: false })
const resizeHandleClassNames: HandleClassName = useMemo(() => {
if (!canResizing) return {}
return {
right: styles.rightHandle,
left: styles.leftHandle,
top: styles.topHandle,
bottom: styles.bottomHandle,
}
}, [canResizing, direction])
const resizing = useMemo(() => {
if (canResizing) return resize
return {
top: true,
bottom: true,
right: true,
left: true,
topRight: true,
bottomRight: true,
bottomLeft: true,
topLeft: true,
...(resize as Enable),
}
}, [canResizing, resize])
const defaultSize: Size = {
width: DEFAULT_WIDTH,
height: DEFAULT_HEIGHT,
...customizeDefaultSize,
}
const defaultPosition: Position = {
x: 100,
y: 100,
...customizeDefaultPosition,
}
const sizeProps = {
minWidth: Math.max(minWidth, 0),
minHeight: Math.max(minHeight, 0),
defaultSize,
size: size as Size,
style,
}
return (
<Rnd
position={position}
resizeHandleClasses={resizeHandleClassNames}
default={{
...defaultPosition,
...defaultSize,
}}
onDragStop={(e, data) => {
onPositionChange?.({ x: data.x, y: data.y })
}}
bound={'parent'}
enableResizing={resizing}
{...sizeProps}
className={styles.float}
>
{children}
</Rnd>
)
}
)

View File

@ -1,3 +0,0 @@
export type { Position } from 'react-rnd'
export { Draggable as DraggablePanel } from './DraggablePanel'
export type { DraggablePanelProps } from './DraggablePanel'

View File

@ -0,0 +1,216 @@
import type { DivProps } from '@/types'
import { useHover } from 'ahooks'
import { ChevronDown, ChevronLeft, ChevronRight, ChevronUp } from 'lucide-react'
import type { Enable, NumberSize, Size } from 're-resizable'
import { HandleClassName, Resizable } from 're-resizable'
import React, { useEffect, useMemo, useRef, useState } from 'react'
import { Center } from 'react-layout-kit'
import type { Props as RndProps } from 'react-rnd'
import useControlledState from 'use-merge-value'
import { useStyle } from './style'
import { revesePlacement } from './utils'
const DEFAULT_HEIGHT = 180
const DEFAULT_WIDTH = 280
export type placementType = 'right' | 'left' | 'top' | 'bottom'
export interface DraggablePanelProps extends DivProps {
pin?: boolean
mode?: 'fixed' | 'float'
placement: placementType
minWidth?: number
minHeight?: number
resize?: RndProps['enableResizing']
size?: Partial<Size>
onSizeChange?: (delta: NumberSize, size?: Size) => void
onSizeDragging?: (delta: NumberSize, size?: Size) => void
expandable?: boolean
expand?: boolean
defaultExpand?: boolean
onExpandChange?: (expand: boolean) => void
defaultSize?: Partial<Size>
destroyOnClose?: boolean
showHandlerWhenUnexpand?: boolean
hanlderStyle?: React.CSSProperties
}
const DraggablePanel: React.FC<DraggablePanelProps> = ({
pin = 'true',
mode = 'fixed',
children,
placement = 'right',
resize,
style,
size,
defaultSize: customizeDefaultSize,
minWidth,
minHeight,
onSizeChange,
onSizeDragging,
expandable = true,
expand,
defaultExpand = true,
onExpandChange,
className,
showHandlerWhenUnexpand,
destroyOnClose,
hanlderStyle,
}) => {
const ref = useRef(null)
const isHovering = useHover(ref)
const isVertical = placement === 'top' || placement === 'bottom'
const { styles, cx } = useStyle('draggable-panel')
const [isExpand, setIsExpand] = useControlledState(defaultExpand, {
value: expand,
onChange: onExpandChange,
})
useEffect(() => {
if (pin) return
if (isHovering && !isExpand) {
setIsExpand(true)
} else if (!isHovering && isExpand) {
setIsExpand(false)
}
}, [pin, isHovering, isExpand])
const [showExpand, setShowExpand] = useState(true)
const canResizing = resize !== false && isExpand
const resizeHandleClassNames: HandleClassName = useMemo(() => {
if (!canResizing) return {}
return {
[revesePlacement(placement)]: styles[`${revesePlacement(placement)}Handle`],
}
}, [canResizing, placement])
const resizing = {
top: false,
bottom: false,
right: false,
left: false,
topRight: false,
bottomRight: false,
bottomLeft: false,
topLeft: false,
[revesePlacement(placement)]: true,
...(resize as Enable),
}
const defaultSize: Size = useMemo(() => {
if (isVertical)
return {
width: '100%',
height: DEFAULT_HEIGHT,
...customizeDefaultSize,
}
return {
width: DEFAULT_WIDTH,
height: '100%',
...customizeDefaultSize,
}
}, [isVertical])
const sizeProps = isExpand
? {
minWidth: typeof minWidth === 'number' ? Math.max(minWidth, 0) : 280,
minHeight: typeof minHeight === 'number' ? Math.max(minHeight, 0) : undefined,
defaultSize,
size: size as Size,
}
: isVertical
? {
minHeight: 0,
size: { height: 0 },
}
: {
minWidth: 0,
size: { width: 0 },
}
const { Arrow, className: arrowPlacement } = useMemo(() => {
switch (placement) {
case 'top':
return { className: 'Bottom', Arrow: ChevronDown }
case 'bottom':
return { className: 'Top', Arrow: ChevronUp }
case 'right':
return { className: 'Left', Arrow: ChevronLeft }
case 'left':
return { className: 'Right', Arrow: ChevronRight }
}
}, [styles, placement])
const handler = (
// @ts-ignore
<Center
// @ts-ignore
className={cx(styles[`toggle${arrowPlacement}`])}
style={{ opacity: isExpand ? (!pin ? 0 : undefined) : showHandlerWhenUnexpand ? 1 : 0 }}
>
<Center
style={hanlderStyle}
onClick={() => {
setIsExpand(!isExpand)
}}
>
<div className={styles.handlerIcon} style={{ transform: `rotate(${isExpand ? 180 : 0}deg)` }}>
<Arrow size={16} strokeWidth={1.5} />
</div>
</Center>
</Center>
)
const inner = (
// @ts-ignore
<Resizable
{...sizeProps}
style={style}
className={styles.panel}
enable={canResizing ? (resizing as Enable) : undefined}
handleClasses={resizeHandleClassNames}
onResizeStop={(e, direction, ref, delta) => {
setShowExpand(true)
onSizeChange?.(delta, {
width: ref.style.width,
height: ref.style.height,
})
}}
onResizeStart={() => {
setShowExpand(false)
}}
onResize={(_, direction, ref, delta) => {
onSizeDragging?.(delta, {
width: ref.style.width,
height: ref.style.height,
})
}}
>
{children}
</Resizable>
)
return (
<div
ref={ref}
className={cx(
styles.container,
// @ts-ignore
styles[mode === 'fixed' ? 'fixed' : `${placement}Float`],
className
)}
style={{ [`border${arrowPlacement}Width`]: 1 }}
>
{expandable && showExpand && handler}
{destroyOnClose ? isExpand && inner : inner}
</div>
)
}
export default React.memo(DraggablePanel)

View File

@ -1,16 +1,19 @@
import { createStyles, css, cx } from 'antd-style'
import { rgba } from 'polished'
export const useStyle = createStyles(({ token }, props: { prefix?: string; maxHeight?: boolean }) => {
const { prefix, maxHeight } = props
const offset = 16
const toggleLength = 40
const toggleShort = 16
export const useStyle = createStyles(({ token }, prefix: string) => {
const commonHandle = css`
position: relative;
&::before {
content: '';
position: absolute;
z-index: 50;
transition: all 0.3s ease-in-out;
transition: all 0.2s ${token.motionEaseOut};
}
&:hover,
&:active {
&::before {
@ -20,38 +23,58 @@ export const useStyle = createStyles(({ token }, props: { prefix?: string; maxHe
`
const commonToggle = css`
cursor: pointer;
position: absolute;
z-index: 1001;
color: ${token.colorTextTertiary};
opacity: 0;
background: ${token.colorBgElevated};
border-color: ${token.colorBorder};
border-style: solid;
border-width: 1px;
border-radius: 4px;
transition: all 0.2s ${token.motionEaseOut};
transition: opacity 0.1s;
&:hover {
color: ${token.colorTextSecondary};
background: ${token.colorFillQuaternary};
opacity: 1 !important;
}
&:active {
opacity: 1 !important;
}
> div {
cursor: pointer;
position: absolute;
color: ${token.colorTextTertiary};
background: ${token.colorFillTertiary};
border-color: ${token.colorBorderSecondary};
border-style: solid;
border-width: 1px;
border-radius: 4px;
transition: all 0.2s ${token.motionEaseOut};
&:hover {
color: ${token.colorTextSecondary};
background: ${token.colorFillSecondary};
}
&:active {
color: ${token.colorText};
background: ${token.colorFill};
}
}
`
const offset = 17
const toggleLength = 40
const toggleShort = 16
const float = css`
position: absolute;
z-index: 2000;
`
return {
container: cx(
prefix,
css`
position: relative;
flex-shrink: 0;
border: 0 solid ${token.colorSplit};
border: 0 solid ${token.colorBorderSecondary};
&:hover {
.${prefix}-toggle {
opacity: 1;
@ -59,20 +82,62 @@ export const useStyle = createStyles(({ token }, props: { prefix?: string; maxHe
}
`
),
fixed: css`
position: relative;
`,
leftFloat: cx(
float,
css`
top: 0;
bottom: 0;
left: 0;
height: 100%;
`
),
rightFloat: cx(
float,
css`
top: 0;
right: 0;
bottom: 0;
height: 100%;
`
),
topFloat: cx(
float,
css`
top: 0;
right: 0;
left: 0;
width: 100%;
`
),
bottomFloat: cx(
float,
css`
right: 0;
bottom: 0;
left: 0;
width: 100%;
`
),
toggleLeft: cx(
`${prefix}-toggle`,
`${prefix}-toggle-left`,
commonToggle,
css`
top: 50%;
left: -${offset}px;
width: ${toggleShort}px;
height: ${toggleLength}px;
margin-top: -20px;
height: 100%;
> div {
top: 50%;
border-right-width: 0;
border-radius: 4px 0 0 4px;
width: ${toggleShort}px;
height: ${toggleLength}px;
margin-top: -20px;
border-radius: 4px 0 0 4px;
}
`
),
toggleRight: cx(
@ -80,15 +145,18 @@ export const useStyle = createStyles(({ token }, props: { prefix?: string; maxHe
`${prefix}-toggle-right`,
commonToggle,
css`
top: 50%;
right: -${offset}px;
width: ${toggleShort}px;
height: ${toggleLength}px;
margin-top: -20px;
height: 100%;
> div {
top: 50%;
border-left-width: 0;
border-radius: 0 4px 4px 0;
width: ${toggleShort}px;
height: ${toggleLength}px;
margin-top: -20px;
border-radius: 0 4px 4px 0;
}
`
),
toggleTop: cx(
@ -97,14 +165,18 @@ export const useStyle = createStyles(({ token }, props: { prefix?: string; maxHe
commonToggle,
css`
top: -${offset}px;
left: 50%;
width: ${toggleLength}px;
width: 100%;
height: ${toggleShort}px;
margin-left: -20px;
border-bottom-width: 0;
border-radius: 4px 4px 0 0;
> div {
left: 50%;
width: ${toggleLength}px;
height: ${toggleShort}px;
margin-left: -20px;
border-radius: 4px 4px 0 0;
}
`
),
toggleBottom: cx(
@ -113,44 +185,38 @@ export const useStyle = createStyles(({ token }, props: { prefix?: string; maxHe
commonToggle,
css`
bottom: -${offset}px;
left: 50%;
width: 100%;
height: ${toggleShort}px;
width: ${toggleLength}px;
height: 16px;
margin-left: -20px;
> div {
left: 50%;
border-top-width: 0;
border-radius: 0 0 4px 4px;
width: ${toggleLength}px;
height: 16px;
margin-left: -20px;
border-radius: 0 0 4px 4px;
}
`
),
fixed: cx(
panel: cx(
`${prefix}-fixed`,
css`
position: relative;
overflow: hidden;
background: ${rgba(token.colorBgContainer, 0.75)};
backdrop-filter: blur(40px);
${maxHeight ? 'height: 100% !important;' : ''}
`
),
float: cx(
`${prefix}-float`,
css`
position: relative;
z-index: 2000;
overflow: hidden;
background: ${rgba(token.colorBgElevated, 0.75)};
backdrop-filter: blur(40px);
border-radius: 8px;
box-shadow: ${token.boxShadowSecondary};
background: ${token.colorBgContainer};
transition: all 0.2s ${token.motionEaseOut};
`
),
handlerIcon: css`
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ${token.motionEaseOut};
`,
leftHandle: cx(
css`
${commonHandle};
&::before {
left: 50%;
width: 2px;
@ -174,6 +240,7 @@ export const useStyle = createStyles(({ token }, props: { prefix?: string; maxHe
`${prefix}-top-handle`,
css`
${commonHandle};
&::before {
top: 50%;
width: 100%;
@ -185,6 +252,7 @@ export const useStyle = createStyles(({ token }, props: { prefix?: string; maxHe
`${prefix}-bottom-handle`,
css`
${commonHandle};
&::before {
bottom: 50%;
width: 100%;

View File

@ -0,0 +1,14 @@
import { placementType } from './index'
export const revesePlacement = (placement: placementType) => {
switch (placement) {
case 'bottom':
return 'top'
case 'top':
return 'bottom'
case 'right':
return 'left'
case 'left':
return 'right'
}
}

View File

@ -69,6 +69,7 @@ interface SidebarProps {
const Sidebar: React.FC<SidebarProps> = ({ children, style }) => {
const { mobile } = useResponsive()
const [setting] = useAppStore((st) => [st.setting], shallow)
const [mode] = useState<'fixed' | 'float'>(setting.extraNetworkFixedMode)
const [expand, setExpand] = useState<boolean>(setting.extraNetworkSidebarExpand)
const [size, setSize] = useState<number>(setting?.extraNetworkCardSize || 86)
@ -80,7 +81,8 @@ const Sidebar: React.FC<SidebarProps> = ({ children, style }) => {
<>
<GlobalStyle />
<DraggablePanel
maxHeight
mode={mode}
pin={mode === 'fixed'}
style={{
display: 'flex',
flexDirection: 'column',
@ -89,7 +91,7 @@ const Sidebar: React.FC<SidebarProps> = ({ children, style }) => {
placement="right"
defaultSize={{ width: setting.extraNetworkSidebarWidth }}
minWidth={setting.extraNetworkSidebarWidth}
isExpand={expand}
expand={expand}
onExpandChange={setExpand}
>
<View>

View File

@ -1,6 +1,6 @@
import { WebuiSetting, defaultSetting, useAppStore } from '@/store'
import { SettingOutlined } from '@ant-design/icons'
import { Button, Divider, Form, InputNumber, Popover, Space, Switch } from 'antd'
import { Button, Divider, Form, InputNumber, Popover, Space, Switch, Segmented } from 'antd'
import React, { useCallback } from 'react'
import styled from 'styled-components'
import { shallow } from 'zustand/shallow'
@ -59,6 +59,9 @@ const Setting: React.FC = () => {
<FormItem label="Default expand" name="sidebarExpand" valuePropName="checked">
<Switch />
</FormItem>
<FormItem label="Fixed mode" name="sidebarFixedMode">
<Segmented options={['fixed', 'float']} />
</FormItem>
<FormItem label="Default width" name="sidebarWidth">
<InputNumber />
</FormItem>
@ -67,6 +70,9 @@ const Setting: React.FC = () => {
<FormItem label="Enable" name="enableExtraNetworkSidebar" valuePropName="checked">
<Switch />
</FormItem>
<FormItem label="Fixed mode" name="extraNetworkFixedMode" valuePropName="checked">
<Segmented options={['fixed', 'float']} />
</FormItem>
<FormItem label="Default expand" name="extraNetworkSidebarExpand" valuePropName="checked">
<Switch />
</FormItem>

View File

@ -96,7 +96,7 @@ const Header: React.FC<HeaderProps> = ({ children }) => {
return (
<>
<DraggablePanel placement="top" defaultSize={{ height: 'auto' }} isExpand={expand} onExpandChange={setExpand}>
<DraggablePanel placement="top" defaultSize={{ height: 'auto' }} expand={expand} onExpandChange={setExpand}>
<HeaderView id="header" style={{ flexDirection: mobile ? 'column' : 'row' }}>
<a href="https://github.com/canisminor1990/sd-webui-kitchen-theme" target="_blank" rel="noreferrer">
<Logo themeMode={themeMode} />

View File

@ -23,6 +23,7 @@ interface SidebarProps {
const Sidebar: React.FC<SidebarProps> = ({ children, loading, style }) => {
const [setting] = useAppStore((st) => [st.setting], shallow)
const [mode] = useState<'fixed' | 'float'>(setting.sidebarFixedMode)
const { mobile } = useResponsive()
const [expand, setExpand] = useState<boolean>(setting.sidebarExpand)
@ -32,7 +33,8 @@ const Sidebar: React.FC<SidebarProps> = ({ children, loading, style }) => {
return (
<DraggablePanel
maxHeight
mode={mode}
pin={mode === 'fixed'}
style={{
display: 'flex',
flexDirection: 'column',
@ -41,7 +43,7 @@ const Sidebar: React.FC<SidebarProps> = ({ children, loading, style }) => {
placement="left"
defaultSize={{ width: setting.sidebarWidth }}
minWidth={setting.sidebarWidth}
isExpand={expand}
expand={expand}
onExpandChange={setExpand}
>
<SidebarView>

View File

@ -1,5 +1,5 @@
export { default as Content } from './Content'
export * from './DraggablePanel'
export { default as DraggablePanel } from './DraggablePanel'
export { default as ExtraNetworkSidebar } from './ExtraNetworkSidebar'
export { default as Header } from './Header'
export { default as Sidebar } from './Sidebar'

View File

@ -7,6 +7,7 @@ import { useResponsive } from 'antd-style'
import React, { useEffect, useRef, useState } from 'react'
import styled from 'styled-components'
import { shallow } from 'zustand/shallow'
import civitaiHelperFix from '@/script/civitaiHelperFix'
const View = styled.div`
position: relative;
@ -45,6 +46,7 @@ const App: React.FC = () => {
)
const { mobile } = useResponsive()
const [loading, setLoading] = useState(true)
const [extraLoading, setExtraLoading] = useState(true)
const sidebarRef: any = useRef<HTMLElement>()
const mainRef: any = useRef<HTMLElement>()
const headerRef: any = useRef<HTMLElement>()
@ -69,7 +71,7 @@ const App: React.FC = () => {
if (sidebar) sidebarRef.current?.appendChild(sidebar)
// ExtraNetworkSidebar
if (setting?.enableExtraNetworkSidebar) {
if (setting.enableExtraNetworkSidebar) {
const txt2imgExtraNetworks = gradioApp().querySelector('div#txt2img_extra_networks')
const img2imgExtraNetworks = gradioApp().querySelector('div#img2img_extra_networks')
if (txt2imgExtraNetworks && img2imgExtraNetworks) {
@ -79,7 +81,7 @@ const App: React.FC = () => {
}
// Other
if (setting?.svgIcon) replaceIcon()
if (setting.svgIcon) replaceIcon()
setLoading(false)
})
@ -88,6 +90,35 @@ const App: React.FC = () => {
})
}, [])
useEffect(() => {
if (!loading && setting.enableExtraNetworkSidebar) {
if (document.querySelector('#txt2img_lora_cards')) {
setExtraLoading(false)
return
}
setTimeout(() => {
const t2iBtn: any = document.querySelector('#txt2img_extra_refresh')
const i2iBtn: any = document.querySelector('#img2img_extra_refresh')
t2iBtn.click()
i2iBtn.click()
setExtraLoading(false)
try {
const civitaiBtn = document.querySelectorAll('button[title="Refresh Civitai Helper\'s additional buttons"]')
if (civitaiBtn) {
civitaiBtn.forEach((btn: any) => (btn.onclick = civitaiHelperFix))
}
const fixInterval = setInterval(() => {
const checkDom = document.querySelector('#txt2img_lora_cards')
if (checkDom) {
civitaiHelperFix()
clearInterval(fixInterval)
}
}, 1000)
} catch {}
}, 2000)
}
}, [loading])
return (
<MainView>
<Header>
@ -96,7 +127,7 @@ const App: React.FC = () => {
<Spin size="small" />
</LoadingBox>
)}
<div ref={headerRef} className="header" />
<div style={loading ? { display: 'none' } : {}} ref={headerRef} className="header" />
</Header>
<View>
<Sidebar>
@ -105,7 +136,7 @@ const App: React.FC = () => {
<Spin size="small" />
</LoadingBox>
)}
<div id="sidebar" ref={sidebarRef} />
<div style={loading ? { display: 'none' } : {}} id="sidebar" ref={sidebarRef} />
</Sidebar>
<Content loading={loading}>
{loading && (
@ -113,25 +144,27 @@ const App: React.FC = () => {
<Spin tip="Loading" size="large" />
</LoadingBox>
)}
<div id="content" ref={mainRef} />
<div style={loading ? { display: 'none' } : {}} id="content" ref={mainRef} />
</Content>
{setting?.enableExtraNetworkSidebar && (
<ExtraNetworkSidebar>
{loading && (
{extraLoading && (
<LoadingBox>
<Spin size="small" />
</LoadingBox>
)}
<div
id="txt2img-extra-netwrok-sidebar"
style={currentTab !== 'tab_img2img' ? {} : { display: 'none' }}
ref={txt2imgExtraNetworkSidebarRef}
/>
<div
id="img2img-extra-netwrok-sidebar"
style={currentTab === 'tab_img2img' ? {} : { display: 'none' }}
ref={img2imgExtraNetworkSidebarRef}
/>
<div style={extraLoading ? { display: 'none' } : {}}>
<div
id="txt2img-extra-netwrok-sidebar"
style={currentTab !== 'tab_img2img' ? {} : { display: 'none' }}
ref={txt2imgExtraNetworkSidebarRef}
/>
<div
id="img2img-extra-netwrok-sidebar"
style={currentTab === 'tab_img2img' ? {} : { display: 'none' }}
ref={img2imgExtraNetworkSidebarRef}
/>
</div>
</ExtraNetworkSidebar>
)}
</View>

View File

@ -1,5 +1,4 @@
import { useIsDarkMode } from '@/components/theme/useIsDarkMode'
import civitaiHelperFix from '@/script/civitaiHelperFix'
import formatPrompt from '@/script/formatPrompt'
import promptBracketChecker from '@/script/promptBracketChecker'
import setupHead from '@/script/setupHead'
@ -68,7 +67,6 @@ document.addEventListener(
onUiLoaded(() => {
formatPrompt()
promptBracketChecker()
civitaiHelperFix()
})
export default () => null

View File

@ -5,13 +5,27 @@ const SETTING_KEY = 'SD-KITCHEN-SETTING'
export interface WebuiSetting {
sidebarExpand: boolean
sidebarFixedMode: 'fixed' | 'float'
sidebarWidth: number
enableExtraNetworkSidebar: boolean
extraNetworkSidebarExpand: boolean
extraNetworkFixedMode: 'fixed' | 'float'
extraNetworkSidebarWidth: number
extraNetworkCardSize: number
svgIcon: boolean
}
export const defaultSetting: WebuiSetting = {
sidebarExpand: true,
sidebarFixedMode: 'fixed',
sidebarWidth: 280,
enableExtraNetworkSidebar: true,
extraNetworkSidebarExpand: true,
extraNetworkFixedMode: 'fixed',
extraNetworkSidebarWidth: 340,
extraNetworkCardSize: 86,
svgIcon: false,
}
export interface AppState {
themeMode: 'light' | 'dark'
setting: WebuiSetting
@ -22,16 +36,6 @@ export interface AppState {
onSetSetting: (setting: WebuiSetting) => void
onInit: () => void
}
export const defaultSetting: WebuiSetting = {
sidebarExpand: true,
sidebarWidth: 280,
enableExtraNetworkSidebar: true,
extraNetworkSidebarExpand: true,
extraNetworkSidebarWidth: 340,
extraNetworkCardSize: 86,
svgIcon: false,
}
export const useAppStore = create<AppState>()(
devtools((set, get) => ({
themeMode: 'light',

View File

@ -69,3 +69,7 @@
#deepbooru {
display: block !important;
}
[id$='2img_dimensions_row'] {
min-width: 36px !important;
}

View File

@ -77,3 +77,9 @@
div.svelte-1oo81b7 > *:not(.absolute) {
border-radius: var(--border-radius) !important;
}
.head {
> label {
overflow: hidden;
}
}

View File

@ -112,12 +112,25 @@
}
.metadata-button {
top: 24px;
right: 4px;
font-size: 24px !important;
top: 50% !important;
transform: translateY(-50%);
display: flex !important;
align-items: center;
justify-content: center;
padding: 0 !important;
font-size: 20px !important;
text-shadow: none !important;
opacity: 0;
background: rgba(0, 0, 0, 0.7);
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
&:hover {
color: #fff !important;
opacity: 1;
}
}

View File

@ -30,12 +30,15 @@
input[type='number'],
textarea {
box-sizing: border-box;
width: -webkit-fill-available;
width: -moz-available;
height: 28px !important;
padding: 4px !important;
}
textarea {
width: -webkit-fill-available;
width: -moz-available;
}
span {
overflow: hidden;
width: 100%;

3
src/types/index.ts Normal file
View File

@ -0,0 +1,3 @@
import React from 'react'
export type DivProps = React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>

File diff suppressed because one or more lines are too long