mirror of
https://github.com/lobehub/sd-webui-lobe-theme.git
synced 2026-01-09 06:23:44 +08:00
🔨 chore: add react layout
This commit is contained in:
parent
8e84bbd187
commit
f8e98b9f80
23686
javascript/index.js
23686
javascript/index.js
File diff suppressed because one or more lines are too long
@ -42,10 +42,13 @@
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@ant-design/icons": "^5.0.1",
|
||||
"@commitlint/cli": "^17",
|
||||
"@types/node": "^18",
|
||||
"@types/react": "^18",
|
||||
"@types/react-dom": "^18",
|
||||
"@types/react-rnd": "^8.0.0",
|
||||
"@types/styled-components": "^5.1.26",
|
||||
"@umijs/lint": "^4.0.64",
|
||||
"antd": "^5.4.2",
|
||||
"antd-style": "^3.0.0",
|
||||
@ -58,12 +61,16 @@
|
||||
"husky": "^8.0.3",
|
||||
"lint-staged": "^13.2.1",
|
||||
"object-to-css-variables": "^0.2.1",
|
||||
"polished": "^4.2.2",
|
||||
"prettier": "^2",
|
||||
"prettier-plugin-organize-imports": "^3",
|
||||
"prettier-plugin-packagejson": "^2",
|
||||
"query-string": "^8.1.0",
|
||||
"re-resizable": "^6.9.9",
|
||||
"react": "^18",
|
||||
"react-dom": "^18",
|
||||
"react-layout-kit": "^1.6.1",
|
||||
"react-rnd": "^10.4.1",
|
||||
"semantic-release": "^21",
|
||||
"semantic-release-config-gitmoji": "^1",
|
||||
"styled-components": "^5.3.9",
|
||||
@ -71,6 +78,7 @@
|
||||
"stylelint-less": "^1.0.6",
|
||||
"typescript": "^5.0.0",
|
||||
"umi": "^4.0.64",
|
||||
"use-merge-value": "^1.2.0",
|
||||
"webpack-shell-plugin-next": "^2.3.1"
|
||||
}
|
||||
}
|
||||
|
||||
171
src/components/DraggablePanel/DraggablePanel.tsx
Normal file
171
src/components/DraggablePanel/DraggablePanel.tsx
Normal file
@ -0,0 +1,171 @@
|
||||
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
|
||||
}
|
||||
|
||||
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,
|
||||
}) => {
|
||||
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}
|
||||
>
|
||||
{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>
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
248
src/components/DraggablePanel/FixMode.tsx
Normal file
248
src/components/DraggablePanel/FixMode.tsx
Normal file
@ -0,0 +1,248 @@
|
||||
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
|
||||
}
|
||||
|
||||
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,
|
||||
}) => {
|
||||
const prefixCls = 'draggable-panel'
|
||||
|
||||
const isVertical = placement === 'top' || placement === 'bottom'
|
||||
|
||||
const { styles, cx } = useStyle(prefixCls)
|
||||
|
||||
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>
|
||||
)
|
||||
}
|
||||
)
|
||||
174
src/components/DraggablePanel/FloatMode.tsx
Normal file
174
src/components/DraggablePanel/FloatMode.tsx
Normal file
@ -0,0 +1,174 @@
|
||||
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(prefixCls)
|
||||
|
||||
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>
|
||||
)
|
||||
}
|
||||
)
|
||||
3
src/components/DraggablePanel/index.ts
Normal file
3
src/components/DraggablePanel/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export type { Position } from 'react-rnd'
|
||||
export { Draggable as DraggablePanel } from './DraggablePanel'
|
||||
export type { DraggablePanelProps } from './DraggablePanel'
|
||||
174
src/components/DraggablePanel/style.ts
Normal file
174
src/components/DraggablePanel/style.ts
Normal file
@ -0,0 +1,174 @@
|
||||
import { createStyles, css, cx } from 'antd-style'
|
||||
|
||||
export const useStyle = createStyles(({ token }, prefix: string) => {
|
||||
const commonHandle = css`
|
||||
position: relative;
|
||||
&::before {
|
||||
position: absolute;
|
||||
z-index: 50;
|
||||
transition: all 0.3s ease-in-out;
|
||||
content: '';
|
||||
}
|
||||
&:hover,
|
||||
&:active {
|
||||
&::before {
|
||||
background: ${token.colorPrimary};
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const commonToggle = css`
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
z-index: 1001;
|
||||
transition: opacity 0.1s;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
background: ${token.colorBgElevated};
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
color: ${token.colorTextTertiary};
|
||||
border-color: ${token.colorBorder};
|
||||
&:hover {
|
||||
color: ${token.colorTextSecondary};
|
||||
background: ${token.colorFillQuaternary};
|
||||
}
|
||||
`
|
||||
|
||||
const offset = 17
|
||||
const toggleLength = 40
|
||||
const toggleShort = 16
|
||||
|
||||
return {
|
||||
container: cx(
|
||||
prefix,
|
||||
css`
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
border: 0 solid ${token.colorSplit};
|
||||
&:hover {
|
||||
.${prefix}-toggle {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
`
|
||||
),
|
||||
toggleLeft: cx(
|
||||
`${prefix}-toggle`,
|
||||
`${prefix}-toggle-left`,
|
||||
commonToggle,
|
||||
css`
|
||||
width: ${toggleShort}px;
|
||||
height: ${toggleLength}px;
|
||||
left: -${offset}px;
|
||||
top: 50%;
|
||||
margin-top: -20px;
|
||||
border-radius: 4px 0 0 4px;
|
||||
border-right-width: 0;
|
||||
`
|
||||
),
|
||||
toggleRight: cx(
|
||||
`${prefix}-toggle`,
|
||||
`${prefix}-toggle-right`,
|
||||
commonToggle,
|
||||
css`
|
||||
width: ${toggleShort}px;
|
||||
height: ${toggleLength}px;
|
||||
right: -${offset}px;
|
||||
top: 50%;
|
||||
margin-top: -20px;
|
||||
border-radius: 0 4px 4px 0;
|
||||
border-left-width: 0;
|
||||
`
|
||||
),
|
||||
toggleTop: cx(
|
||||
`${prefix}-toggle`,
|
||||
`${prefix}-toggle-top`,
|
||||
commonToggle,
|
||||
css`
|
||||
height: ${toggleShort}px;
|
||||
width: ${toggleLength}px;
|
||||
top: -${offset}px;
|
||||
left: 50%;
|
||||
margin-left: -20px;
|
||||
border-radius: 4px 4px 0 0;
|
||||
border-bottom-width: 0;
|
||||
`
|
||||
),
|
||||
toggleBottom: cx(
|
||||
`${prefix}-toggle`,
|
||||
`${prefix}-toggle-bottom`,
|
||||
commonToggle,
|
||||
css`
|
||||
height: 16px;
|
||||
width: ${toggleLength}px;
|
||||
bottom: -${offset}px;
|
||||
left: 50%;
|
||||
margin-left: -20px;
|
||||
border-radius: 0 0 4px 4px;
|
||||
border-top-width: 0;
|
||||
`
|
||||
),
|
||||
fixed: cx(
|
||||
`${prefix}-fixed`,
|
||||
css`
|
||||
background: ${token.colorBgContainer};
|
||||
overflow: hidden;
|
||||
`
|
||||
),
|
||||
float: cx(
|
||||
`${prefix}-float`,
|
||||
css`
|
||||
overflow: hidden;
|
||||
border-radius: 8px;
|
||||
background: ${token.colorBgElevated};
|
||||
box-shadow: ${token.boxShadowSecondary};
|
||||
z-index: 2000;
|
||||
`
|
||||
),
|
||||
leftHandle: cx(
|
||||
css`
|
||||
${commonHandle};
|
||||
&::before {
|
||||
left: 50%;
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
}
|
||||
`,
|
||||
`${prefix}-left-handle`
|
||||
),
|
||||
rightHandle: cx(
|
||||
css`
|
||||
${commonHandle};
|
||||
&::before {
|
||||
right: 50%;
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
}
|
||||
`,
|
||||
`${prefix}-right-handle`
|
||||
),
|
||||
topHandle: cx(
|
||||
`${prefix}-top-handle`,
|
||||
css`
|
||||
${commonHandle};
|
||||
&::before {
|
||||
top: 50%;
|
||||
height: 2px;
|
||||
width: 100%;
|
||||
}
|
||||
`
|
||||
),
|
||||
bottomHandle: cx(
|
||||
`${prefix}-bottom-handle`,
|
||||
css`
|
||||
${commonHandle};
|
||||
&::before {
|
||||
bottom: 50%;
|
||||
height: 2px;
|
||||
width: 100%;
|
||||
}
|
||||
`
|
||||
),
|
||||
}
|
||||
})
|
||||
1
src/components/index.tsx
Normal file
1
src/components/index.tsx
Normal file
@ -0,0 +1 @@
|
||||
export * from './DraggablePanel'
|
||||
@ -4,14 +4,16 @@ import React, { useEffect, useState } from 'react'
|
||||
import Layout from './Layout'
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [appearance, setAppearance] = useState<string>('auto')
|
||||
const [appearance, setAppearance] = useState<string>('dark')
|
||||
useEffect(() => {
|
||||
setAppearance(String(qs.parseUrl(window.location.href).query.__theme) || 'auto')
|
||||
const themeMode = String(qs.parseUrl(window.location.href).query.__theme) || 'dark'
|
||||
setAppearance(themeMode)
|
||||
document.body.classList.add(themeMode)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<ThemeProvider appearance={appearance}>
|
||||
<Layout />
|
||||
<Layout themeMode={appearance} />
|
||||
</ThemeProvider>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,16 +1,58 @@
|
||||
import { Layout } from 'antd'
|
||||
import React from 'react'
|
||||
import { DraggablePanel } from '@/components/DraggablePanel'
|
||||
import React, { useEffect, useRef } from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
const { Header } = Layout
|
||||
const View = styled.div`
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: row !important;
|
||||
`
|
||||
|
||||
const LayoutView: React.FC = () => {
|
||||
// const header = gradioApp().getElementById('quicksettings')
|
||||
const header = document.getElementById('quicksettings')
|
||||
const MainView = styled.div`
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
`
|
||||
|
||||
const Header = styled.div`
|
||||
height: 72px;
|
||||
`
|
||||
|
||||
const Content = styled.div``
|
||||
|
||||
interface LayoutViewProps {
|
||||
themeMode: string
|
||||
}
|
||||
|
||||
const LayoutView: React.FC<LayoutViewProps> = ({ themeMode }) => {
|
||||
const sidebarRef: any = useRef<HTMLElement>()
|
||||
const mainRef: any = useRef<HTMLElement>()
|
||||
const headerRef: any = useRef<HTMLElement>()
|
||||
useEffect(() => {
|
||||
onUiLoaded(() => {
|
||||
const sidebar = gradioApp().querySelector('#quicksettings')
|
||||
const header = gradioApp().querySelector('#tabs > .tab-nav:first-child')
|
||||
const main = gradioApp().querySelector('.app')
|
||||
if (sidebar) sidebarRef.current?.appendChild(sidebar)
|
||||
if (header) headerRef.current?.appendChild(header)
|
||||
if (main) mainRef.current?.appendChild(main)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<Header>{header}</Header>
|
||||
</Layout>
|
||||
<View>
|
||||
<MainView>
|
||||
<Header className="gradio-container-3-23-0">
|
||||
<div id="header" ref={headerRef} />
|
||||
</Header>
|
||||
<Content>
|
||||
<div ref={mainRef} />
|
||||
</Content>
|
||||
</MainView>
|
||||
<DraggablePanel placement="right">
|
||||
<div ref={sidebarRef} />
|
||||
</DraggablePanel>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -1,21 +1,20 @@
|
||||
import favicon from '@/script/favicon'
|
||||
import formatPrompt from '@/script/format-prompt'
|
||||
import promptBracketChecker from '@/script/prompt-bracket-checker'
|
||||
import '@/theme/style.less'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import favicon from '../../script/favicon'
|
||||
import formatPrompt from '../../script/format-prompt'
|
||||
import promptBracketChecker from '../../script/prompt-bracket-checker'
|
||||
import '../../theme/style.less'
|
||||
import App from './App'
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const root = document.createElement('div')
|
||||
root.setAttribute('id', 'root')
|
||||
document.body.append(root)
|
||||
gradioApp().append(root)
|
||||
const client = createRoot(root)
|
||||
client.render(<App />)
|
||||
})
|
||||
|
||||
onUiLoaded(() => {
|
||||
favicon()
|
||||
window.init = true
|
||||
})
|
||||
|
||||
onUiUpdate(() => {
|
||||
@ -23,4 +22,4 @@ onUiUpdate(() => {
|
||||
promptBracketChecker()
|
||||
})
|
||||
|
||||
export default () => null
|
||||
export default () => <App />
|
||||
|
||||
@ -1,16 +1,4 @@
|
||||
#quicksettings {
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
flex-wrap: nowrap;
|
||||
top: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> * {
|
||||
@media screen and (max-width: 640px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
white-space: nowrap;
|
||||
@ -19,17 +7,17 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
display: block;
|
||||
background: var(--logo) no-repeat;
|
||||
width: 129px;
|
||||
height: 26px;
|
||||
z-index: 1000;
|
||||
margin-right: 36px;
|
||||
margin-left: 16px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
//&::before {
|
||||
// content: '';
|
||||
// display: block;
|
||||
// background: var(--logo) no-repeat;
|
||||
// width: 129px;
|
||||
// height: 26px;
|
||||
// z-index: 1000;
|
||||
// margin-right: 36px;
|
||||
// margin-left: 16px;
|
||||
// margin-top: 12px;
|
||||
//}
|
||||
|
||||
.dropdown-arrow {
|
||||
min-width: 16px;
|
||||
@ -39,9 +27,6 @@
|
||||
> div,
|
||||
> fieldset {
|
||||
min-width: 240px !important;
|
||||
@media screen and (max-width: 640px) {
|
||||
max-width: 160px;
|
||||
}
|
||||
}
|
||||
|
||||
button.svelte-1ipelgc {
|
||||
@ -57,45 +42,46 @@
|
||||
margin-top: 118px;
|
||||
}
|
||||
|
||||
> .tab-nav:first-child {
|
||||
position: fixed;
|
||||
top: 90px;
|
||||
z-index: 999;
|
||||
flex-wrap: nowrap;
|
||||
overflow-y: auto;
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
|
||||
#header {
|
||||
//position: fixed;
|
||||
//top: 90px;
|
||||
//z-index: 999;
|
||||
//flex-wrap: nowrap;
|
||||
//width: 100%;
|
||||
//border: none;
|
||||
//&::before {
|
||||
// content: '';
|
||||
// display: block;
|
||||
// position: fixed;
|
||||
// width: 100vw;
|
||||
// height: 121px;
|
||||
// top: 0;
|
||||
// left: 0;
|
||||
// border-block-end: 1px solid var(--color-border-secondary);
|
||||
// background: var(--color-header);
|
||||
// backdrop-filter: blur(24px);
|
||||
// z-index: -1;
|
||||
//}
|
||||
|
||||
button {
|
||||
border: none;
|
||||
&::before {
|
||||
content: '';
|
||||
display: block;
|
||||
position: fixed;
|
||||
width: 100vw;
|
||||
height: 121px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
border-block-end: 1px solid var(--color-border-secondary);
|
||||
background: var(--color-header);
|
||||
backdrop-filter: blur(24px);
|
||||
z-index: -1;
|
||||
border-bottom: 3px solid transparent !important;
|
||||
flex: none;
|
||||
transition: all 0.2s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
border: none;
|
||||
border-bottom: 3px solid var(--color-primary) !important;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
> button {
|
||||
&.selected {
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-bottom: 3px solid transparent !important;
|
||||
flex: none;
|
||||
transition: all 0.2s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
border: none;
|
||||
border-bottom: 3px solid var(--color-primary) !important;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-bottom: 3px solid var(--color-primary) !important;
|
||||
}
|
||||
border-bottom: 3px solid var(--color-primary) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
@import 'components/container';
|
||||
@import 'components/scrollbar';
|
||||
@import 'components/options';
|
||||
//@import 'components/header';
|
||||
@import 'components/header';
|
||||
@import 'components/modal';
|
||||
@import 'components/sliders';
|
||||
@import 'components/button';
|
||||
@ -35,8 +35,11 @@ body {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-size-adjust: 100%;
|
||||
background-image: var(--color-body-background);
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
|
||||
code {
|
||||
font-family: var(--font-family-code);
|
||||
}
|
||||
@ -67,13 +70,18 @@ h5 {
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
.dark, .light {
|
||||
div {
|
||||
color: var(--color-text);
|
||||
}
|
||||
}
|
||||
|
||||
/* Theme Fix */
|
||||
.gradio-container {
|
||||
font-size: var(--font-size);
|
||||
color: var(--color-text);
|
||||
margin: 0;
|
||||
background-image: var(--color-body-background);
|
||||
background-repeat: no-repeat;
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
#txtimg_hr_finalres {
|
||||
|
||||
@ -15,7 +15,10 @@
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx"
|
||||
"jsx": "react-jsx",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["javascript"]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user