Merge pull request #49 from Sanster/0427_optimize

optimize
This commit is contained in:
Qing 2022-05-23 21:36:45 +08:00 committed by GitHub
commit 623c5bb485
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 697 additions and 373 deletions

View File

@ -8,11 +8,11 @@ https://user-images.githubusercontent.com/3998421/153323093-b664bb68-2928-480b-b
- [x] Support multiple model architectures
1. [LaMa](https://github.com/saic-mdal/lama)
1. [LDM](https://github.com/CompVis/latent-diffusion)
- [x] Support CPU & GPU
- [x] High resolution support
- [x] Run as a desktop APP
- [x] Multi stroke support. Press and hold the `cmd/ctrl` key to enable multi stroke mode.
- [x] Zoom & Pan
- [ ] Keep image EXIF data
## Install

View File

@ -1,17 +1,17 @@
{
"files": {
"main.css": "/static/css/main.4201b632.chunk.css",
"main.js": "/static/js/main.18cd2cfc.chunk.js",
"main.css": "/static/css/main.d1028b29.chunk.css",
"main.js": "/static/js/main.b169e669.chunk.js",
"runtime-main.js": "/static/js/runtime-main.5e86ac81.js",
"static/js/2.2d367d07.chunk.js": "/static/js/2.2d367d07.chunk.js",
"static/js/2.1b1d3019.chunk.js": "/static/js/2.1b1d3019.chunk.js",
"index.html": "/index.html",
"static/js/2.2d367d07.chunk.js.LICENSE.txt": "/static/js/2.2d367d07.chunk.js.LICENSE.txt",
"static/js/2.1b1d3019.chunk.js.LICENSE.txt": "/static/js/2.1b1d3019.chunk.js.LICENSE.txt",
"static/media/_index.scss": "/static/media/WorkSans-SemiBold.1e98db4e.ttf"
},
"entrypoints": [
"static/js/runtime-main.5e86ac81.js",
"static/js/2.2d367d07.chunk.js",
"static/css/main.4201b632.chunk.css",
"static/js/main.18cd2cfc.chunk.js"
"static/js/2.1b1d3019.chunk.js",
"static/css/main.d1028b29.chunk.css",
"static/js/main.b169e669.chunk.js"
]
}

View File

@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0"/><meta name="theme-color" content="#ffffff"/><title>lama-cleaner - Image inpainting powered by LaMa</title><link href="/static/css/main.4201b632.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>"localhost"===location.hostname&&(self.FIREBASE_APPCHECK_DEBUG_TOKEN=!0)</script><script>!function(e){function r(r){for(var n,l,a=r[0],f=r[1],i=r[2],p=0,s=[];p<a.length;p++)l=a[p],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in f)Object.prototype.hasOwnProperty.call(f,n)&&(e[n]=f[n]);for(c&&c(r);s.length;)s.shift()();return u.push.apply(u,i||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,a=1;a<t.length;a++){var f=t[a];0!==o[f]&&(n=!1)}n&&(u.splice(r--,1),e=l(l.s=t[0]))}return e}var n={},o={1:0},u=[];function l(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,l),t.l=!0,t.exports}l.m=e,l.c=n,l.d=function(e,r,t){l.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,r){if(1&r&&(e=l(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(l.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)l.d(t,n,function(r){return e[r]}.bind(null,n));return t},l.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(r,"a",r),r},l.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},l.p="/";var a=this["webpackJsonplama-cleaner"]=this["webpackJsonplama-cleaner"]||[],f=a.push.bind(a);a.push=r,a=a.slice();for(var i=0;i<a.length;i++)r(a[i]);var c=f;t()}([])</script><script src="/static/js/2.2d367d07.chunk.js"></script><script src="/static/js/main.18cd2cfc.chunk.js"></script></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0"/><meta name="theme-color" content="#ffffff"/><title>lama-cleaner - Image inpainting powered by LaMa</title><link href="/static/css/main.d1028b29.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,l,a=r[0],f=r[1],i=r[2],p=0,s=[];p<a.length;p++)l=a[p],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in f)Object.prototype.hasOwnProperty.call(f,n)&&(e[n]=f[n]);for(c&&c(r);s.length;)s.shift()();return u.push.apply(u,i||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,a=1;a<t.length;a++){var f=t[a];0!==o[f]&&(n=!1)}n&&(u.splice(r--,1),e=l(l.s=t[0]))}return e}var n={},o={1:0},u=[];function l(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,l),t.l=!0,t.exports}l.m=e,l.c=n,l.d=function(e,r,t){l.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,r){if(1&r&&(e=l(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(l.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)l.d(t,n,function(r){return e[r]}.bind(null,n));return t},l.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(r,"a",r),r},l.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},l.p="/";var a=this["webpackJsonplama-cleaner"]=this["webpackJsonplama-cleaner"]||[],f=a.push.bind(a);a.push=r,a=a.slice();for(var i=0;i<a.length;i++)r(a[i]);var c=f;t()}([])</script><script src="/static/js/2.1b1d3019.chunk.js"></script><script src="/static/js/main.b169e669.chunk.js"></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5,6 +5,8 @@
"proxy": "http://localhost:8080",
"dependencies": {
"@heroicons/react": "^1.0.4",
"@radix-ui/react-dialog": "0.1.8-rc.25",
"@radix-ui/react-select": "0.1.2-rc.27",
"@radix-ui/react-switch": "^0.1.5",
"@radix-ui/react-toast": "^0.1.1",
"@testing-library/jest-dom": "^5.14.1",

View File

@ -22,10 +22,5 @@
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script>
if (location.hostname === 'localhost') {
self.FIREBASE_APPCHECK_DEBUG_TOKEN = true
}
</script>
</body>
</html>

View File

@ -29,8 +29,12 @@ function App() {
setTheme(newTheme)
})
useEffect(() => {
document.body.setAttribute('data-theme', theme)
}, [theme])
return (
<div className="lama-cleaner" data-theme={theme}>
<div className="lama-cleaner">
<Header />
{file ? <Workspace file={file} /> : <LandingPage />}
</div>

View File

@ -52,7 +52,6 @@
}
.editor-toolkit-panel {
// width: 100%;
position: fixed;
bottom: 0.5rem;
border-radius: 3rem;
@ -110,80 +109,3 @@
border: 1px solid var(--yellow-accent);
pointer-events: none;
}
.editor-size-selector-options {
position: fixed;
display: grid;
}
.editor-size-selector {
grid-area: toolkit-size-selector;
display: grid;
grid-template-columns: repeat(2, max-content);
align-items: center;
}
.editor-size-selector-main {
@include accented-display(var(white));
user-select: none;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
outline: none;
gap: 8px;
width: 128px;
border: 1px solid var(--editor-size-border-color);
color: var(--options-text-color);
svg {
width: 1rem;
height: 1rem;
margin-top: 0.25rem;
}
}
.editor-size-options {
@include accented-display(var(--btn-primary-bg));
width: 128px;
padding: 0;
display: grid;
justify-self: center;
position: fixed;
bottom: 4rem;
cursor: pointer;
color: var(--options-text-color);
background-color: var(--page-bg);
border: 1px solid var(--editor-size-border-color);
border-radius: 0.6rem;
@include mobile {
bottom: 11.5rem;
}
.editor-size-option {
display: flex;
align-items: center;
height: 40px;
user-select: none;
padding: 0.2rem 0.8rem;
&:first-of-type {
border-top-right-radius: 0.5rem;
border-top-left-radius: 0.5rem;
}
&:last-of-type {
border-bottom-left-radius: 0.5rem;
border-bottom-right-radius: 0.5rem;
}
&:hover {
background-color: var(--yellow-accent);
color: var(--btn-text-hover-color);
}
}
}

View File

@ -21,7 +21,13 @@ import inpaint from '../../adapters/inpainting'
import Button from '../shared/Button'
import Slider from './Slider'
import SizeSelector from './SizeSelector'
import { downloadImage, loadImage, useImage } from '../../utils'
import {
downloadImage,
isMidClick,
isRightClick,
loadImage,
useImage,
} from '../../utils'
import { settingState } from '../../store/Atoms'
const TOOLBAR_SIZE = 200
@ -78,6 +84,7 @@ export default function Editor(props: EditorProps) {
const [curLineGroup, setCurLineGroup] = useState<LineGroup>([])
const [{ x, y }, setCoords] = useState({ x: -1, y: -1 })
const [showBrush, setShowBrush] = useState(false)
const [showRefBrush, setShowRefBrush] = useState(false)
const [isPanning, setIsPanning] = useState<boolean>(false)
const [showOriginal, setShowOriginal] = useState(false)
const [isInpaintingLoading, setIsInpaintingLoading] = useState(false)
@ -86,6 +93,8 @@ export default function Editor(props: EditorProps) {
const [minScale, setMinScale] = useState<number>(1.0)
const [sizeLimit, setSizeLimit] = useState<number>(1080)
const windowSize = useWindowSize()
const windowCenterX = windowSize.width / 2
const windowCenterY = windowSize.height / 2
const viewportRef = useRef<ReactZoomPanPinchRef | undefined | null>()
// Indicates that the image has been loaded and is centered on first load
const [initialCentered, setInitialCentered] = useState(false)
@ -259,6 +268,7 @@ export default function Editor(props: EditorProps) {
isOriginalLoaded,
windowSize,
initialCentered,
drawOnCurrentRender,
])
// Zoom reset
@ -338,7 +348,11 @@ export default function Editor(props: EditorProps) {
drawOnCurrentRender(lineGroup)
}
const onPointerUp = () => {
const onPointerUp = (ev: SyntheticEvent) => {
if (isMidClick(ev)) {
setIsPanning(false)
}
if (isPanning) {
return
}
@ -382,6 +396,16 @@ export default function Editor(props: EditorProps) {
if (isInpaintingLoading) {
return
}
if (isRightClick(ev)) {
return
}
if (isMidClick(ev)) {
setIsPanning(true)
return
}
setIsDraging(true)
let lineGroup: LineGroup = []
@ -531,6 +555,13 @@ export default function Editor(props: EditorProps) {
})
})
// Manual Inpainting Hotkey
useKeyPressEvent('R', () => {
if (settings.runInpaintingManually && hadDrawSomething()) {
runInpainting()
}
})
// Toggle clean/zoom tool on spacebar.
useKeyPressEvent(
' ',
@ -556,17 +587,28 @@ export default function Editor(props: EditorProps) {
return s!
}
const getBrushStyle = () => {
const getBrushStyle = (_x: number, _y: number) => {
const curScale = getCurScale()
return {
width: `${brushSize * curScale}px`,
height: `${brushSize * curScale}px`,
left: `${x}px`,
top: `${y}px`,
left: `${_x}px`,
top: `${_y}px`,
transform: 'translate(-50%, -50%)',
}
}
const handleSliderChange = (value: number) => {
setBrushSize(value)
if (!showRefBrush) {
setShowRefBrush(true)
window.setTimeout(() => {
setShowRefBrush(false)
}, 10000)
}
}
return (
<div
className="editor-container"
@ -615,7 +657,10 @@ export default function Editor(props: EditorProps) {
onContextMenu={e => {
e.preventDefault()
}}
onMouseOver={() => toggleShowBrush(true)}
onMouseOver={() => {
toggleShowBrush(true)
setShowRefBrush(false)
}}
onFocus={() => toggleShowBrush(true)}
onMouseLeave={() => toggleShowBrush(false)}
onMouseDown={onMouseDown}
@ -660,7 +705,14 @@ export default function Editor(props: EditorProps) {
</TransformWrapper>
{showBrush && !isInpaintingLoading && !isPanning && (
<div className="brush-shape" style={getBrushStyle()} />
<div className="brush-shape" style={getBrushStyle(x, y)} />
)}
{showRefBrush && (
<div
className="brush-shape"
style={getBrushStyle(windowCenterX, windowCenterY)}
/>
)}
<div className="editor-toolkit-panel">
@ -674,15 +726,20 @@ export default function Editor(props: EditorProps) {
min={10}
max={150}
value={brushSize}
onChange={setBrushSize}
onChange={handleSliderChange}
onClick={() => setShowRefBrush(false)}
/>
<div className="editor-toolkit-btns">
<Button
toolTip="Reset Zoom & Pan"
tooltipPosition="top"
icon={<ArrowsExpandIcon />}
disabled={scale === minScale && panned === false}
onClick={resetZoom}
/>
<Button
toolTip="Undo"
tooltipPosition="top"
icon={
<svg
width="19"
@ -701,6 +758,8 @@ export default function Editor(props: EditorProps) {
disabled={disableUndo()}
/>
<Button
toolTip="Show Original"
tooltipPosition="top"
icon={<EyeIcon />}
className={showOriginal ? 'eyeicon-active' : ''}
onDown={ev => {
@ -721,6 +780,8 @@ export default function Editor(props: EditorProps) {
disabled={renders.length === 0}
/>
<Button
toolTip="Save Image"
tooltipPosition="top"
icon={<DownloadIcon />}
disabled={!renders.length}
onClick={download}
@ -728,6 +789,8 @@ export default function Editor(props: EditorProps) {
{settings.runInpaintingManually && (
<Button
toolTip="Run Inpainting"
tooltipPosition="top"
icon={
<svg
width="24"

View File

@ -1,6 +1,5 @@
import React, { useCallback, useRef, useState } from 'react'
import { useClickAway } from 'react-use'
import { ChevronUpIcon } from '@heroicons/react/outline'
import React, { useCallback, useState } from 'react'
import Selector from '../shared/Selector'
const sizes = ['720', '1080', '2000', 'Original']
@ -12,24 +11,9 @@ type SizeSelectorProps = {
export default function SizeSelector(props: SizeSelectorProps) {
const { originalHeight, originalWidth, onChange } = props
const [showOptions, setShowOptions] = useState<boolean>(false)
const sizeSelectorRef = useRef(null)
const [activeSize, setActiveSize] = useState<string>('Original')
const longSide: number = Math.max(originalWidth, originalHeight)
const getValidSizes = useCallback(() => {
const validSizes: string[] = []
for (let i = 0; i < sizes.length; i += 1) {
if (sizes[i] === 'Original') {
validSizes.push(sizes[i])
}
if (parseInt(sizes[i], 10) < longSide) {
validSizes.push(sizes[i])
}
}
return validSizes
}, [longSide])
const getSizeShowName = useCallback(
(size: string) => {
if (size === 'Original') {
@ -46,57 +30,38 @@ export default function SizeSelector(props: SizeSelectorProps) {
[originalWidth, originalHeight, longSide]
)
const showOptionsHandler = () => {
setShowOptions(currentShowOptionsState => !currentShowOptionsState)
const getValidSizes = useCallback(() => {
const validSizes: string[] = []
for (let i = 0; i < sizes.length; i += 1) {
if (sizes[i] === 'Original') {
validSizes.push(getSizeShowName(sizes[i]))
}
if (parseInt(sizes[i], 10) < longSide) {
validSizes.push(getSizeShowName(sizes[i]))
}
}
return validSizes
}, [longSide, getSizeShowName])
useClickAway(sizeSelectorRef, () => {
setShowOptions(false)
})
const sizeChangeHandler = (e: any) => {
const currentRes = e.target.textContent.split('x')
const sizeChangeHandler = (value: string) => {
const currentRes = value.split('x')
if (originalWidth > originalHeight) {
setActiveSize(currentRes[0])
onChange(currentRes[0])
onChange(parseInt(currentRes[0], 10))
} else {
setActiveSize(currentRes[1])
onChange(currentRes[1])
onChange(parseInt(currentRes[1], 10))
}
setShowOptions(!showOptions)
}
return (
<div className="editor-size-selector" ref={sizeSelectorRef}>
<div
className="editor-size-selector-main"
role="button"
tabIndex={0}
onClick={showOptionsHandler}
aria-hidden="true"
>
<p>{getSizeShowName(activeSize.toString())}</p>
<div className="editor-size-selector-icon">
<ChevronUpIcon />
</div>
</div>
{showOptions && (
<div className="editor-size-options">
{getValidSizes().map(size => (
<div
className="editor-size-option"
role="button"
tabIndex={0}
key={size}
onClick={sizeChangeHandler}
aria-hidden="true"
>
{getSizeShowName(size)}
</div>
))}
</div>
)}
</div>
<Selector
width={100}
autoFocusAfterClose={false}
value={getSizeShowName(activeSize.toString())}
options={getValidSizes()}
onChange={sizeChangeHandler}
chevronDirection="up"
/>
)
}

View File

@ -6,10 +6,11 @@ type SliderProps = {
min?: number
max?: number
onChange: (value: number) => void
onClick: () => void
}
export default function Slider(props: SliderProps) {
const { value, onChange, label, min, max } = props
const { value, onChange, onClick, label, min, max } = props
const step = ((max || 100) - (min || 0)) / 100
@ -27,6 +28,7 @@ export default function Slider(props: SliderProps) {
ev.stopPropagation()
onChange(parseInt(ev.currentTarget.value, 10))
}}
onClick={onClick}
/>
</div>
)

View File

@ -26,15 +26,15 @@ const Header = () => {
{resolution === 'desktop' ? 'Start New' : undefined}
</Button>
</div>
<div className="header-icons-wrapper">
<div
className="header-icons"
style={{ visibility: file ? 'visible' : 'hidden' }}
>
<SettingIcon />
<Shortcuts />
</div>
<ThemeChanger />
{file && (
<div className="header-icons">
<Shortcuts />
<SettingIcon />
</div>
)}
</div>
</header>
)

View File

@ -119,6 +119,7 @@ function HDSettingBlock() {
title="High Resolution Strategy"
input={
<Selector
width={80}
value={setting.hdStrategy as string}
options={Object.values(HDStrategy)}
onChange={val => onStrategyChange(val as HDStrategy)}

View File

@ -15,7 +15,7 @@ const ManualRunInpaintingSettingBlock: React.FC = () => {
return (
<SettingBlock
title="Run inpainting manually"
title="Manual Inpainting Mode"
input={
<Switch
checked={setting.runInpaintingManually}

View File

@ -90,6 +90,7 @@ function ModelSettingBlock() {
title="Inpainting Model"
input={
<Selector
width={80}
value={setting.model as string}
options={Object.values(AIModel)}
onChange={val => onModelChange(val as AIModel)}

View File

@ -14,6 +14,8 @@ const SettingIcon = () => {
<div>
<Button
onClick={onClick}
toolTip="Settings"
tooltipPosition="bottom"
style={{ border: 0 }}
icon={
<svg

View File

@ -34,11 +34,10 @@
.shortcut-key {
justify-self: end;
font-family: 'WorkSans-Bold';
border: 1px solid var(--modal-hotkey-border-color);
padding: 0.4rem 1rem;
padding: 0.4rem 0.4rem;
width: max-content;
border-radius: 0.4rem;
border-radius: 0.2rem;
@include mobile {
padding: 0.2rem 0.4rem;
@ -48,7 +47,6 @@
.shortcut-description {
justify-self: start;
text-align: left;
width: 18rem;
@include mobile {
text-align: left;

View File

@ -22,6 +22,8 @@ const Shortcuts = () => {
<div className="shortcuts">
<Button
onClick={shortcutStateHandler}
toolTip="Hotkeys"
tooltipPosition="bottom"
disabled={shortcutVisibility}
style={{ border: 0 }}
icon={

View File

@ -4,21 +4,37 @@ import { shortcutsState } from '../../store/Atoms'
import Modal from '../shared/Modal'
interface Shortcut {
children: ReactNode
content: string
keys: string[]
}
function ShortCut(props: Shortcut) {
const { children, content } = props
const { content, keys } = props
return (
<div className="shortcut-option">
<div className="shortcut-description">{content}</div>
<div className="shortcut-key">{children}</div>
<div style={{ display: 'flex', justifySelf: 'end', gap: '8px' }}>
{keys.map((k, index) => (
<div className="shortcut-key" key={k}>
{k}
</div>
))}
</div>
</div>
)
}
const isMac = (function () {
return /macintosh|mac os x/i.test(navigator.userAgent)
})()
const isWindows = (function () {
return /windows|win32/i.test(navigator.userAgent)
})()
const CmdOrCtrl = isMac ? 'Cmd' : 'Ctrl'
export default function ShortcutsModal() {
const [shortcutsShow, setShortcutState] = useRecoilState(shortcutsState)
@ -34,36 +50,20 @@ export default function ShortcutsModal() {
show={shortcutsShow}
>
<div className="shortcut-options">
<ShortCut content="Enable multi-stroke mask drawing">
<p>Hold Cmd/Ctrl</p>
</ShortCut>
<ShortCut content="Undo inpainting">
<p>Cmd/Ctrl + Z</p>
</ShortCut>
<ShortCut content="Pan">
<p>Space & Drag</p>
</ShortCut>
<ShortCut content="View original image">
<p>Hold Tab</p>
</ShortCut>
<ShortCut content="Reset zoom/pan">
<p>Esc</p>
</ShortCut>
<ShortCut content="Cancel mask drawing">
<p>Esc</p>
</ShortCut>
<ShortCut content="Decrease Brush Size">
<p>[</p>
</ShortCut>
<ShortCut content="Increase Brush Size">
<p>]</p>
</ShortCut>
<ShortCut content="Toggle Dark Mode">
<p>Shift + D</p>
</ShortCut>
<ShortCut content="Toggle Hotkeys Panel">
<p>H</p>
</ShortCut>
<ShortCut
content="Enable Multi-Stroke Mask Drawing"
keys={[`Hold ${CmdOrCtrl}`]}
/>
<ShortCut content="Undo Inpainting" keys={[CmdOrCtrl, 'Z']} />
<ShortCut content="Pan" keys={['Space & Drag']} />
<ShortCut content="View Original Image" keys={['Hold Tag']} />
<ShortCut content="Reset Zoom/Pan" keys={['Esc']} />
<ShortCut content="Cancel Mask Drawing" keys={['Esc']} />
<ShortCut content="Run Inpainting Manually" keys={['Shift', 'R']} />
<ShortCut content="Decrease Brush Size" keys={['[']} />
<ShortCut content="Increase Brush Size" keys={[']']} />
<ShortCut content="Toggle Dark Mode" keys={['Shift', 'D']} />
<ShortCut content="Toggle Hotkeys Panel" keys={['H']} />
</div>
</Modal>
)

View File

@ -4,7 +4,7 @@ import Editor from './Editor/Editor'
import ShortcutsModal from './Shortcuts/ShortcutsModal'
import SettingModal from './Settings/SettingsModal'
import Toast from './shared/Toast'
import { Settings, settingState, toastState } from '../store/Atoms'
import { settingState, toastState } from '../store/Atoms'
import {
currentModel,
modelDownloaded,
@ -79,7 +79,7 @@ const Workspace = ({ file }: WorkspaceProps) => {
return { ...old, model: model as AIModel }
})
})
}, [])
}, [setSettingState])
return (
<>

View File

@ -1,8 +1,9 @@
@use '../../styles/Mixins/' as *;
.btn-primary {
display: grid;
grid-auto-flow: column;
column-gap: 1rem;
border: 1px solid var(--btn-border-color);
color: var(--btn-text-color);
font-family: 'WorkSans', sans-serif;
width: max-content;

View File

@ -5,6 +5,8 @@ interface ButtonProps {
children?: ReactNode
className?: string
icon?: ReactNode
toolTip?: string
tooltipPosition?: string
onKeyDown?: () => void
onClick?: () => void
onDown?: (ev: PointerEvent) => void
@ -18,6 +20,8 @@ const Button: React.FC<ButtonProps> = props => {
className,
disabled,
icon,
toolTip,
tooltipPosition,
onKeyDown,
onClick,
onDown,
@ -33,6 +37,7 @@ const Button: React.FC<ButtonProps> = props => {
return (
<div
role="button"
data-tooltip={toolTip}
style={style}
onKeyDown={onKeyDown}
onClick={blurOnClick}
@ -47,6 +52,8 @@ const Button: React.FC<ButtonProps> = props => {
'btn-primary',
children ? 'btn-primary-content' : '',
disabled === true ? 'btn-primary-disabled' : '',
toolTip ? 'info-tooltip' : '',
tooltipPosition ? `info-tooltip-${tooltipPosition}` : '',
className,
].join(' ')}
>

View File

@ -1,17 +1,33 @@
.modal-mask {
z-index: 9999;
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
position: fixed;
z-index: 9998;
inset: 0;
background-color: var(--model-mask-bg);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
@media (prefers-reduced-motion: no-preference) {
animation: opacityReveal 150ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
}
@keyframes contentShow {
0% {
opacity: 0;
transform: translate(-50%, -48%) scale(0.96);
}
100% {
opacity: 1;
transform: translate(-50%, -50%) scale(1);
}
}
.modal {
background-color: var(--page-bg);
z-index: 9999;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: grid;
grid-auto-rows: max-content;
row-gap: 2rem;
@ -19,6 +35,10 @@
padding: 2rem;
border-radius: 0.95rem;
&:focus {
outline: none;
}
.modal-header {
display: grid;
grid-template-columns: repeat(2, auto);
@ -28,4 +48,8 @@
justify-self: end;
}
}
@media (prefers-reduced-motion: no-preference) {
animation: contentShow 150ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
}

View File

@ -1,6 +1,6 @@
import { XIcon } from '@heroicons/react/outline'
import React, { ReactNode, useRef } from 'react'
import { useClickAway, useKey, useKeyPress, useKeyPressEvent } from 'react-use'
import React, { ReactNode } from 'react'
import * as DialogPrimitive from '@radix-ui/react-dialog'
import Button from './Button'
export interface ModalProps {
@ -11,34 +11,35 @@ export interface ModalProps {
className?: string
}
export default function Modal(props: ModalProps) {
const Modal = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Root>,
ModalProps
>((props, forwardedRef) => {
const { show, children, onClose, className, title } = props
const ref = useRef(null)
useClickAway(ref, () => {
if (show) {
const onOpenChange = (open: boolean) => {
if (!open) {
onClose?.()
}
})
useKeyPressEvent('Escape', e => {
if (show) {
onClose?.()
}
})
return (
<div
className="modal-mask"
style={{ visibility: show === true ? 'visible' : 'hidden' }}
<DialogPrimitive.Root open={show} onOpenChange={onOpenChange}>
<DialogPrimitive.Portal>
<DialogPrimitive.Overlay className="modal-mask" />
<DialogPrimitive.Content
ref={forwardedRef}
className={`modal ${className}`}
>
<div ref={ref} className={`modal ${className}`}>
<div className="modal-header">
<h2>{title}</h2>
<DialogPrimitive.Title>{title}</DialogPrimitive.Title>
<Button icon={<XIcon />} onClick={onClose} />
</div>
{children}
</div>
</div>
</DialogPrimitive.Content>
</DialogPrimitive.Portal>
</DialogPrimitive.Root>
)
}
})
export default Modal

View File

@ -2,8 +2,7 @@
all: unset;
flex: 1 0 auto;
border-radius: 0.5rem;
padding: 0.2rem 0.8rem;
line-height: 1;
padding: 0.4rem 0.8rem;
outline: 1px solid var(--border-color);
&:focus-visible {

View File

@ -1,26 +1,14 @@
@use '../../styles/Mixins' as *;
.selector {
position: relative;
display: flex;
flex-direction: column;
.select-trigger {
all: unset;
display: inline-flex;
align-items: center;
justify-content: space-between;
}
.selector-main {
@include accented-display(var(white));
width: 100%;
user-select: none;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
outline: none;
border-radius: 0.5rem;
height: 38px;
gap: 8px;
padding: 0.2rem 0.8rem;
padding: 0 0.8rem;
border: 1px solid var(--border-color);
background-color: var(--page-bg);
color: var(--options-text-color);
svg {
@ -28,47 +16,52 @@
height: 1rem;
margin-top: 0.25rem;
}
}
.selector-options {
@include accented-display(var(--btn-primary-bg));
width: 100%;
padding: 0;
display: grid;
justify-self: center;
position: absolute;
cursor: pointer;
top: 3rem;
color: var(--options-text-color);
background-color: var(--page-bg);
border: 1px solid var(--border-color);
border-radius: 0.6rem;
@include mobile {
bottom: 11.5rem;
}
.selector-option {
display: flex;
align-items: center;
user-select: none;
padding: 0.5rem 0.8rem;
&:first-of-type {
border-top-right-radius: 0.5rem;
border-top-left-radius: 0.5rem;
}
&:last-of-type {
border-bottom-left-radius: 0.5rem;
border-bottom-right-radius: 0.5rem;
}
&:hover {
background-color: var(--yellow-accent);
border-color: var(--yellow-accent);
}
// &:focus-visible {
// border-color: var(--yellow-accent);
// }
}
.select-content {
overflow: hidden;
background-color: var(--page-bg);
border-radius: 0.5rem;
}
.select-viewport {
border: 1px solid var(--border-color);
border-radius: 0.5rem;
padding: 5px;
}
.select-item {
all: unset;
background-color: var(--page-bg);
color: var(--options-text-color);
display: flex;
align-items: center;
border-radius: 0.5rem;
padding: 6px 6px 6px 25px;
position: relative;
user-select: none;
&:focus {
color: var(--btn-text-hover-color);
background-color: var(--yellow-accent);
}
}
.select-item-indicator {
position: absolute;
left: 0;
width: 25px;
padding-right: 4px;
display: inline-flex;
align-items: center;
justify-content: center;
}

View File

@ -1,86 +1,84 @@
import React, { MutableRefObject, useCallback, useRef, useState } from 'react'
import { useClickAway, useKeyPressEvent } from 'react-use'
import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/react/outline'
import React, { useRef } from 'react'
import {
CheckIcon,
ChevronDownIcon,
ChevronUpIcon,
} from '@heroicons/react/outline'
import * as Select from '@radix-ui/react-select'
type SelectorChevronDirection = 'up' | 'down'
type SelectorProps = {
minWidth?: number
chevronDirection?: SelectorChevronDirection
interface Props {
width?: number
value: string
options: string[]
chevronDirection?: SelectorChevronDirection
autoFocusAfterClose?: boolean
onChange: (value: string) => void
}
const selectorDefaultProps = {
minWidth: 128,
chevronDirection: 'down',
const Selector = (props: Props) => {
const {
width,
value,
chevronDirection,
options,
autoFocusAfterClose,
onChange,
} = props
const contentRef = useRef<HTMLButtonElement>(null)
const onOpenChange = (open: boolean) => {
if (!open) {
if (!autoFocusAfterClose) {
// 如果使用 Select.Content 的 onCloseAutoFocus 来取消 focus防止空格继续打开这个 select
// 会导致其它快捷键失效,原因未知
window.setTimeout(() => {
contentRef?.current?.blur()
}, 100)
}
function Selector(props: SelectorProps) {
const { minWidth, chevronDirection, value, options, onChange } = props
const [showOptions, setShowOptions] = useState<boolean>(false)
const selectorRef = useRef<HTMLDivElement | null>(null)
const showOptionsHandler = () => {
// console.log(selectorRef.current?.focus)
// selectorRef?.current?.focus()
setShowOptions(currentShowOptionsState => !currentShowOptionsState)
}
useClickAway(selectorRef, () => {
setShowOptions(false)
})
// TODO: how to prevent Modal close?
// useKeyPressEvent('Escape', (e: KeyboardEvent) => {
// if (showOptions === true) {
// console.log(`selector ${e}`)
// e.preventDefault()
// e.stopPropagation()
// setShowOptions(false)
// }
// })
const onOptionClick = (e: any, newIndex: number) => {
const currentRes = e.target.textContent.split('x')
onChange(currentRes[0])
setShowOptions(false)
}
return (
<div className="selector" ref={selectorRef} style={{ minWidth }}>
<div
className="selector-main"
role="button"
onClick={showOptionsHandler}
aria-hidden="true"
<Select.Root
value={value}
onValueChange={onChange}
onOpenChange={onOpenChange}
>
<p>{value}</p>
<div className="selector-icon">
<Select.Trigger
className="select-trigger"
style={{ width }}
ref={contentRef}
>
<Select.Value />
<Select.Icon>
{chevronDirection === 'up' ? <ChevronUpIcon /> : <ChevronDownIcon />}
</div>
</div>
</Select.Icon>
</Select.Trigger>
{showOptions && (
<div className="selector-options">
{options.map((val, _index) => (
<div
className="selector-option"
role="button"
tabIndex={0}
key={val}
onClick={e => onOptionClick(e, _index)}
aria-hidden="true"
>
{val}
</div>
<Select.Content className="select-content">
<Select.Viewport className="select-viewport">
{options.map(val => (
<Select.Item value={val} className="select-item" key={val}>
<Select.ItemText>{val}</Select.ItemText>
<Select.ItemIndicator className="select-item-indicator">
<CheckIcon />
</Select.ItemIndicator>
</Select.Item>
))}
</div>
)}
</div>
</Select.Viewport>
</Select.Content>
</Select.Root>
)
}
const selectorDefaultProps = {
chevronDirection: 'down',
autoFocusAfterClose: true,
}
Selector.defaultProps = selectorDefaultProps
export default Selector

View File

@ -0,0 +1,33 @@
$tooltip-translate: 100%;
$tooltip-margin: 1.5rem;
.info-tooltip {
&:hover:before {
content: attr(data-tooltip);
position: absolute;
background-color: var(--tooltip-bg);
color: var(--tooltip-text-color);
padding: 0.5rem;
border-radius: 0.3rem;
z-index: 2;
opacity: 0;
animation-name: opacityReveal;
animation-duration: 0.2s;
animation-fill-mode: forwards;
animation-delay: 1s;
}
}
.info-tooltip-top {
&:hover:before {
transform: translateY(calc($tooltip-translate * -1));
margin-bottom: $tooltip-margin;
}
}
.info-tooltip-bottom {
&:hover:before {
transform: translateY($tooltip-translate);
margin-top: $tooltip-margin;
}
}

View File

@ -9,12 +9,15 @@
--link-color: rgb(0, 0, 0);
--border-color: rgb(100, 100, 120);
--border-color-light: rgba(100, 100, 120, 0.5);
--tooltip-bg: rgb(230, 230, 234);
--tooltip-text-color: rgb(0, 0,0);
--error-color: rgb(239, 68, 68);
--success-color: rgb(16, 185, 129);
// Editor
--editor-toolkit-bg: rgba(255, 255, 255, 0.5);
--editor-options-bg: rgb(230, 230, 234);
--options-text-color: var(--page-text-color);
--editor-size-border-color: var(--border-color);
--editor-toolkit-panel-border: 0;

View File

@ -9,9 +9,12 @@
--link-color: var(--yellow-accent);
--border-color: rgb(100, 100, 120);
--border-color-light: rgba(102, 102, 102);
--tooltip-bg: rgb(33, 33, 33);
--tooltip-text-color: rgb(210, 210, 210);
// Editor
--editor-toolkit-bg: rgba(0, 0, 0, 0.5);
--editor-options-bg: rgb(33, 33, 33);
--options-text-color: var(--page-text-color);
--editor-size-border-color: var(--yellow-accent);
--editor-toolkit-panel-border: 1px solid rgb(100, 100, 120, 0.4);

View File

@ -21,6 +21,7 @@
@use '../components/shared/Switch';
@use '../components/shared/NumberInput';
@use '../components/shared/Toast';
@use '../components/shared/Tooltip';
// Main CSS
*,

View File

@ -1,4 +1,4 @@
import { useEffect, useState } from 'react'
import { SyntheticEvent, useEffect, useState } from 'react'
export function dataURItoBlob(dataURI: string) {
const mime = dataURI.split(',')[0].split(':')[1].split(';')[0]
@ -182,3 +182,13 @@ export function keepGUIAlive() {
})
}
}
export function isRightClick(ev: SyntheticEvent) {
const mouseEvent = ev.nativeEvent as MouseEvent
return mouseEvent.button === 2
}
export function isMidClick(ev: SyntheticEvent) {
const mouseEvent = ev.nativeEvent as MouseEvent
return mouseEvent.button === 1
}

View File

@ -1544,6 +1544,13 @@
schema-utils "^2.6.5"
source-map "^0.7.3"
"@radix-ui/number@0.1.0":
version "0.1.0"
resolved "https://registry.npmmirror.com/@radix-ui/number/-/number-0.1.0.tgz#73ad13d5cc5f75fa5e147d72e5d5d5e50d688256"
integrity sha512-rpf6QiOWLHAkM4FEMYu9i+5Jr8cKT893+R4mPpcdsy4LD7omr9JfdOqj/h/xPA5+EcVrpMMlU6rrRYpUB5UI8g==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/primitive@0.1.0":
version "0.1.0"
resolved "https://registry.npmmirror.com/@radix-ui/primitive/-/primitive-0.1.0.tgz#6206b97d379994f0d1929809db035733b337e543"
@ -1551,6 +1558,17 @@
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-collection@0.1.5-rc.18":
version "0.1.5-rc.18"
resolved "https://registry.npmmirror.com/@radix-ui/react-collection/-/react-collection-0.1.5-rc.18.tgz#4dc03a8f464643748c0dad781b472f149d671d5c"
integrity sha512-ZTxuynXn3FgNVQ2+1/G+QLBoNH7F826OIUHAHc/tkuMsSjTKv1QVUxkE1t+UuyApYS4aqvFcrgyQlbcdqp4MpA==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-compose-refs" "0.1.1-rc.18"
"@radix-ui/react-context" "0.1.2-rc.18"
"@radix-ui/react-primitive" "0.1.5-rc.18"
"@radix-ui/react-slot" "0.1.3-rc.18"
"@radix-ui/react-compose-refs@0.1.0":
version "0.1.0"
resolved "https://registry.npmmirror.com/@radix-ui/react-compose-refs/-/react-compose-refs-0.1.0.tgz#cff6e780a0f73778b976acff2c2a5b6551caab95"
@ -1558,6 +1576,13 @@
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-compose-refs@0.1.1-rc.18":
version "0.1.1-rc.18"
resolved "https://registry.npmmirror.com/@radix-ui/react-compose-refs/-/react-compose-refs-0.1.1-rc.18.tgz#5d6d8e74aa98f41f8e740f22067aa4c30718af68"
integrity sha512-K0txrUszW1rI0af8tUBGHTxcfLzMH/criPZirLFBsZ1nJTg1GItJvQdoEAZeP51ooPXRtn0VWdD1va0eHtAGVA==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-context@0.1.1":
version "0.1.1"
resolved "https://registry.npmmirror.com/@radix-ui/react-context/-/react-context-0.1.1.tgz#06996829ea124d9a1bc1dbe3e51f33588fab0875"
@ -1565,6 +1590,41 @@
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-context@0.1.2-rc.18":
version "0.1.2-rc.18"
resolved "https://registry.npmmirror.com/@radix-ui/react-context/-/react-context-0.1.2-rc.18.tgz#b5746bd609d6d7372ae6f5c778c7d5a6c7eb6834"
integrity sha512-ZQD/FTtNb1Y+O9kML5RLWYzpdbwrhwQHJcVh/BSeaxJvAqQtWqfMlKPSKjvQgkPMljWK7o6hqUptdicVdNpIRQ==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-dialog@0.1.8-rc.25":
version "0.1.8-rc.25"
resolved "https://registry.npmmirror.com/@radix-ui/react-dialog/-/react-dialog-0.1.8-rc.25.tgz#dea6af32268b34070346ed5d6d609ff699a1de43"
integrity sha512-THdTgtqCWmOs06zQOod8lNgH+eoBFlqJKwLOC6TVIgj76lNahEotPOz8K5Dio/IyJ7U2NAVZtGgV6ZQkdjtKFQ==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/primitive" "0.1.0"
"@radix-ui/react-compose-refs" "0.1.1-rc.18"
"@radix-ui/react-context" "0.1.2-rc.18"
"@radix-ui/react-dismissable-layer" "0.1.6-rc.18"
"@radix-ui/react-focus-guards" "0.1.1-rc.18"
"@radix-ui/react-focus-scope" "0.1.5-rc.18"
"@radix-ui/react-id" "0.1.6-rc.18"
"@radix-ui/react-portal" "0.1.5-rc.18"
"@radix-ui/react-presence" "0.1.3-rc.18"
"@radix-ui/react-primitive" "0.1.5-rc.18"
"@radix-ui/react-slot" "0.1.3-rc.18"
"@radix-ui/react-use-controllable-state" "0.1.1-rc.18"
aria-hidden "^1.1.1"
react-remove-scroll "^2.4.0"
"@radix-ui/react-direction@0.1.0-rc.21":
version "0.1.0-rc.21"
resolved "https://registry.npmmirror.com/@radix-ui/react-direction/-/react-direction-0.1.0-rc.21.tgz#01954caa203ebd87e9a770b727c34956b9829eca"
integrity sha512-c2mlHIXhgkLT7RiXdaqHhLC0b3XtWKimG5FUFGxUSr3+IKADg7CioTAVwOqz2Pa+AKO8tYJG/2aE583mmE9OMg==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-dismissable-layer@0.1.5":
version "0.1.5"
resolved "https://registry.npmmirror.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-0.1.5.tgz#9379032351e79028d472733a5cc8ba4a0ea43314"
@ -1578,6 +1638,36 @@
"@radix-ui/react-use-callback-ref" "0.1.0"
"@radix-ui/react-use-escape-keydown" "0.1.0"
"@radix-ui/react-dismissable-layer@0.1.6-rc.18":
version "0.1.6-rc.18"
resolved "https://registry.npmmirror.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-0.1.6-rc.18.tgz#0827b3f6148048c934a5f26feccb5f6a360817b2"
integrity sha512-7ZrO3UbvlLfmVFgqhbT3E1Nss7iz4SpUba8/wCbgcoEmb2gXHukFpZhvXunkublFcNxs6kb58jHZtdPL98vMHQ==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/primitive" "0.1.0"
"@radix-ui/react-compose-refs" "0.1.1-rc.18"
"@radix-ui/react-primitive" "0.1.5-rc.18"
"@radix-ui/react-use-body-pointer-events" "0.1.2-rc.18"
"@radix-ui/react-use-callback-ref" "0.1.1-rc.18"
"@radix-ui/react-use-escape-keydown" "0.1.1-rc.18"
"@radix-ui/react-focus-guards@0.1.1-rc.18":
version "0.1.1-rc.18"
resolved "https://registry.npmmirror.com/@radix-ui/react-focus-guards/-/react-focus-guards-0.1.1-rc.18.tgz#f0e2ebd3cbfd363a71682e3234b274ab7d7df4ce"
integrity sha512-eJq8XBF/vh5uPMqB8kWpaRfXjwDAPK3hXi7a8NrxhDDL4DLrIT5VnKzdNptmIu59SAwWBdb7maS71J4/oS9tWA==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-focus-scope@0.1.5-rc.18":
version "0.1.5-rc.18"
resolved "https://registry.npmmirror.com/@radix-ui/react-focus-scope/-/react-focus-scope-0.1.5-rc.18.tgz#e26a0317130687fd3668af8ec68e19e04dc7668f"
integrity sha512-uiiOQqbcsV68zPrbUO0V86DJ7SNhZ6HQSBYkQI5NRVOOP4NAx2KJoj8838M4JHxwBq2EvmGvhH1xCOEF8YGuwA==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-compose-refs" "0.1.1-rc.18"
"@radix-ui/react-primitive" "0.1.5-rc.18"
"@radix-ui/react-use-callback-ref" "0.1.1-rc.18"
"@radix-ui/react-id@0.1.5":
version "0.1.5"
resolved "https://registry.npmmirror.com/@radix-ui/react-id/-/react-id-0.1.5.tgz#010d311bedd5a2884c1e9bb6aaaa4e6cc1d1d3b8"
@ -1586,6 +1676,14 @@
"@babel/runtime" "^7.13.10"
"@radix-ui/react-use-layout-effect" "0.1.0"
"@radix-ui/react-id@0.1.6-rc.18":
version "0.1.6-rc.18"
resolved "https://registry.npmmirror.com/@radix-ui/react-id/-/react-id-0.1.6-rc.18.tgz#8a73ddeabf8195babe9153e3ab68b6a61eb0dc07"
integrity sha512-NWSNlEdCSq9uNWsoWkmIHdjNNl5Sir8R17k5GPWez5uC0p72ymxNQRrIEm6Lp+kdaBFHwiNLUcMECMpF4gvDuw==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-use-layout-effect" "0.1.1-rc.18"
"@radix-ui/react-label@0.1.5":
version "0.1.5"
resolved "https://registry.npmmirror.com/@radix-ui/react-label/-/react-label-0.1.5.tgz#12cd965bfc983e0148121d4c99fb8e27a917c45c"
@ -1597,6 +1695,17 @@
"@radix-ui/react-id" "0.1.5"
"@radix-ui/react-primitive" "0.1.4"
"@radix-ui/react-label@0.1.6-rc.18":
version "0.1.6-rc.18"
resolved "https://registry.npmmirror.com/@radix-ui/react-label/-/react-label-0.1.6-rc.18.tgz#91a01c97553d92f6b3683702dd939b5ff13bd5d8"
integrity sha512-T+pnKxUTCy4E0TcasaN9mbI80jI3SCmUlcLIofHjT8gMfNKB6ctbZVnRZ+8NhkXdkcPtrTbL+xtX3YAlukn3Xg==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-compose-refs" "0.1.1-rc.18"
"@radix-ui/react-context" "0.1.2-rc.18"
"@radix-ui/react-id" "0.1.6-rc.18"
"@radix-ui/react-primitive" "0.1.5-rc.18"
"@radix-ui/react-portal@0.1.4":
version "0.1.4"
resolved "https://registry.npmmirror.com/@radix-ui/react-portal/-/react-portal-0.1.4.tgz#17bdce3d7f1a9a0b35cb5e935ab8bc562441a7d2"
@ -1606,6 +1715,15 @@
"@radix-ui/react-primitive" "0.1.4"
"@radix-ui/react-use-layout-effect" "0.1.0"
"@radix-ui/react-portal@0.1.5-rc.18":
version "0.1.5-rc.18"
resolved "https://registry.npmmirror.com/@radix-ui/react-portal/-/react-portal-0.1.5-rc.18.tgz#8ff156abc2d4a4cc43f7fb95605edf677dc4983f"
integrity sha512-DlmS8wDoI3hFrLLALD44l0O8UI10S3e220RcIADxwhhfSg4mwKOznKMdeZLUW/Hmqcmhqwez7Y3u4ktClT82QQ==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-primitive" "0.1.5-rc.18"
"@radix-ui/react-use-layout-effect" "0.1.1-rc.18"
"@radix-ui/react-presence@0.1.2":
version "0.1.2"
resolved "https://registry.npmmirror.com/@radix-ui/react-presence/-/react-presence-0.1.2.tgz#9f11cce3df73cf65bc348e8b76d891f0d54c1fe3"
@ -1615,6 +1733,15 @@
"@radix-ui/react-compose-refs" "0.1.0"
"@radix-ui/react-use-layout-effect" "0.1.0"
"@radix-ui/react-presence@0.1.3-rc.18":
version "0.1.3-rc.18"
resolved "https://registry.npmmirror.com/@radix-ui/react-presence/-/react-presence-0.1.3-rc.18.tgz#53994cf898d29f41246e4eb81c4627a5fe46da61"
integrity sha512-hr1/71w5alELTUnap4FtTCSkT83HROwRr3+J+5NAU3niEeebdUJTpCBGg+hV7h/SV67vmIivZdI2VmPuWyx69A==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-compose-refs" "0.1.1-rc.18"
"@radix-ui/react-use-layout-effect" "0.1.1-rc.18"
"@radix-ui/react-primitive@0.1.4":
version "0.1.4"
resolved "https://registry.npmmirror.com/@radix-ui/react-primitive/-/react-primitive-0.1.4.tgz#6c233cf08b0cb87fecd107e9efecb3f21861edc1"
@ -1623,6 +1750,40 @@
"@babel/runtime" "^7.13.10"
"@radix-ui/react-slot" "0.1.2"
"@radix-ui/react-primitive@0.1.5-rc.18":
version "0.1.5-rc.18"
resolved "https://registry.npmmirror.com/@radix-ui/react-primitive/-/react-primitive-0.1.5-rc.18.tgz#a6ac3ddb1a96b448de2241e7af8d83335aa31b18"
integrity sha512-JJ+u0LSb3C7i2Pqlq0L37aysfbYvyXc2ZFvlzQLpSLnac2pJEkftih2ODGDZHyWW3OdJne/eL442xi+CeKoJpw==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-slot" "0.1.3-rc.18"
"@radix-ui/react-select@0.1.2-rc.27":
version "0.1.2-rc.27"
resolved "https://registry.npmmirror.com/@radix-ui/react-select/-/react-select-0.1.2-rc.27.tgz#91948d482b3db8cf83172838dfae0f4bedec9566"
integrity sha512-bU7edMZ57HSjD/QjFNUXqR1BNbKJiNa/Ue/i4pNSZzu1uoz93s7T1fNZcfUtz1TyJSCfSqw7M9qnteVgM67frg==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/number" "0.1.0"
"@radix-ui/primitive" "0.1.0"
"@radix-ui/react-collection" "0.1.5-rc.18"
"@radix-ui/react-compose-refs" "0.1.1-rc.18"
"@radix-ui/react-context" "0.1.2-rc.18"
"@radix-ui/react-direction" "0.1.0-rc.21"
"@radix-ui/react-dismissable-layer" "0.1.6-rc.18"
"@radix-ui/react-focus-scope" "0.1.5-rc.18"
"@radix-ui/react-id" "0.1.6-rc.18"
"@radix-ui/react-label" "0.1.6-rc.18"
"@radix-ui/react-portal" "0.1.5-rc.18"
"@radix-ui/react-primitive" "0.1.5-rc.18"
"@radix-ui/react-use-callback-ref" "0.1.1-rc.18"
"@radix-ui/react-use-controllable-state" "0.1.1-rc.18"
"@radix-ui/react-use-layout-effect" "0.1.1-rc.18"
"@radix-ui/react-use-previous" "0.1.2-rc.18"
"@radix-ui/react-visually-hidden" "0.1.5-rc.18"
aria-hidden "^1.1.1"
react-remove-scroll "^2.4.0"
"@radix-ui/react-slot@0.1.2":
version "0.1.2"
resolved "https://registry.npmmirror.com/@radix-ui/react-slot/-/react-slot-0.1.2.tgz#e6f7ad9caa8ce81cc8d532c854c56f9b8b6307c8"
@ -1631,6 +1792,14 @@
"@babel/runtime" "^7.13.10"
"@radix-ui/react-compose-refs" "0.1.0"
"@radix-ui/react-slot@0.1.3-rc.18":
version "0.1.3-rc.18"
resolved "https://registry.npmmirror.com/@radix-ui/react-slot/-/react-slot-0.1.3-rc.18.tgz#370869c60e6d988f2bde0909771e4ad84c99e11f"
integrity sha512-7dOYAMzx0zhQFOPpSCgBSManKOvC+ezy67makxmBCMpfa8uV1B0A6sfWze6p0fBLnEt+bDVvR4ZGBEK1EnoQAA==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-compose-refs" "0.1.1-rc.18"
"@radix-ui/react-switch@^0.1.5":
version "0.1.5"
resolved "https://registry.npmmirror.com/@radix-ui/react-switch/-/react-switch-0.1.5.tgz#071ffa19a17a47fdc5c5e6f371bd5901c9fef2f4"
@ -1672,6 +1841,14 @@
"@babel/runtime" "^7.13.10"
"@radix-ui/react-use-layout-effect" "0.1.0"
"@radix-ui/react-use-body-pointer-events@0.1.2-rc.18":
version "0.1.2-rc.18"
resolved "https://registry.npmmirror.com/@radix-ui/react-use-body-pointer-events/-/react-use-body-pointer-events-0.1.2-rc.18.tgz#bfea07e70d07fc3fa5f17c97848a435bee3a0a1b"
integrity sha512-QvuzIsLrZJZDcbQEQMRoKyKX2ULfdPJO3BG/+NSvFDxJNht6VTV4OR7B+jNtV78EwtBvZ+o/14hUeSJR+InbAw==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-use-layout-effect" "0.1.1-rc.18"
"@radix-ui/react-use-callback-ref@0.1.0":
version "0.1.0"
resolved "https://registry.npmmirror.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-0.1.0.tgz#934b6e123330f5b3a6b116460e6662cbc663493f"
@ -1679,6 +1856,13 @@
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-use-callback-ref@0.1.1-rc.18":
version "0.1.1-rc.18"
resolved "https://registry.npmmirror.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-0.1.1-rc.18.tgz#86cd931b69cbf333ff3ca888ba74edf119184ede"
integrity sha512-Jw0jcOL66xhfOTIAaPvcDfynN5KNE+Y2lokXnDS9n/erGeOAFANLem3hV5elqxel6xOAhTj55dubxzV08nJ1vg==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-use-controllable-state@0.1.0":
version "0.1.0"
resolved "https://registry.npmmirror.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-0.1.0.tgz#4fced164acfc69a4e34fb9d193afdab973a55de1"
@ -1687,6 +1871,14 @@
"@babel/runtime" "^7.13.10"
"@radix-ui/react-use-callback-ref" "0.1.0"
"@radix-ui/react-use-controllable-state@0.1.1-rc.18":
version "0.1.1-rc.18"
resolved "https://registry.npmmirror.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-0.1.1-rc.18.tgz#6a404591ff8f021ca2e8ca3a3ff6a79d5c2a8bd5"
integrity sha512-enVVaxWLlfd4hsqG9ezIGUd1H0nYdwsVOTVeswmwP0MCt4mX4hQUiXwdp2uwLfc19HpHFnHCN8pohmVIEx8tqg==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-use-callback-ref" "0.1.1-rc.18"
"@radix-ui/react-use-escape-keydown@0.1.0":
version "0.1.0"
resolved "https://registry.npmmirror.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-0.1.0.tgz#dc80cb3753e9d1bd992adbad9a149fb6ea941874"
@ -1695,6 +1887,14 @@
"@babel/runtime" "^7.13.10"
"@radix-ui/react-use-callback-ref" "0.1.0"
"@radix-ui/react-use-escape-keydown@0.1.1-rc.18":
version "0.1.1-rc.18"
resolved "https://registry.npmmirror.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-0.1.1-rc.18.tgz#82bea76e7191d00023b4e1505d8acfb136726c05"
integrity sha512-z+syfHS88smrl7YpNTFNrUpT8FgFX0ejNnEu8STXyofuHr+K6uQHv/jjn/ZFRtHKXTPgkqL1MIxR3WSvlMlFAw==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-use-callback-ref" "0.1.1-rc.18"
"@radix-ui/react-use-layout-effect@0.1.0":
version "0.1.0"
resolved "https://registry.npmmirror.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-0.1.0.tgz#ebf71bd6d2825de8f1fbb984abf2293823f0f223"
@ -1702,6 +1902,13 @@
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-use-layout-effect@0.1.1-rc.18":
version "0.1.1-rc.18"
resolved "https://registry.npmmirror.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-0.1.1-rc.18.tgz#2b2010253fdb50a95a73c951daf7f74462a67d65"
integrity sha512-DR7qRSlsQnVYuEroMUyUGfEBUhxYBM+gLVJ0+c8rTKIShpJ2W2mDgTLynJQiD3bBa3o0J0/KkRbZg2FzbdDURQ==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-use-previous@0.1.1":
version "0.1.1"
resolved "https://registry.npmmirror.com/@radix-ui/react-use-previous/-/react-use-previous-0.1.1.tgz#0226017f72267200f6e832a7103760e96a6db5d0"
@ -1709,6 +1916,13 @@
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-use-previous@0.1.2-rc.18":
version "0.1.2-rc.18"
resolved "https://registry.npmmirror.com/@radix-ui/react-use-previous/-/react-use-previous-0.1.2-rc.18.tgz#7a94a4a8914849de595b3a5c5f9d6e0b7e12e45d"
integrity sha512-RbdV/yXkVtgMZwcvgtH7VbhJWO2ZUnnHZWZ3CzVoroEqvSunlBSYMZngPbnFLiO3ZKTSD9jFsi+FS6MJAj3iRw==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-use-size@0.1.1":
version "0.1.1"
resolved "https://registry.npmmirror.com/@radix-ui/react-use-size/-/react-use-size-0.1.1.tgz#f6b75272a5d41c3089ca78c8a2e48e5f204ef90f"
@ -1724,6 +1938,14 @@
"@babel/runtime" "^7.13.10"
"@radix-ui/react-primitive" "0.1.4"
"@radix-ui/react-visually-hidden@0.1.5-rc.18":
version "0.1.5-rc.18"
resolved "https://registry.npmmirror.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-0.1.5-rc.18.tgz#d0a3fffa611258b57114c533718076353f6afb65"
integrity sha512-0e0JNOKdmh6hl41mzL5dGSVNfb8MMD1HzWluO6iTEYUyJrs6eBkwKpeGiZNp7sxmvGSbI/yFNEwMWbMFKq51Kw==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-primitive" "0.1.5-rc.18"
"@rollup/plugin-node-resolve@^7.1.1":
version "7.1.3"
resolved "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz"
@ -2696,6 +2918,13 @@ argparse@^1.0.7:
dependencies:
sprintf-js "~1.0.2"
aria-hidden@^1.1.1:
version "1.1.3"
resolved "https://registry.npmmirror.com/aria-hidden/-/aria-hidden-1.1.3.tgz#bb48de18dc84787a3c6eee113709c473c64ec254"
integrity sha512-RhVWFtKH5BiGMycI72q2RAFMLQi8JP9bLuQXgR5a8Znp7P5KOIADSJeyfI8PCVxLEp067B2HbP5JIiI/PXIZeA==
dependencies:
tslib "^1.0.0"
aria-query@^4.2.2:
version "4.2.2"
resolved "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz"
@ -4435,6 +4664,11 @@ detect-newline@^3.0.0:
resolved "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz"
integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==
detect-node-es@^1.1.0:
version "1.1.0"
resolved "https://registry.npmmirror.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493"
integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==
detect-node@^2.0.4:
version "2.1.0"
resolved "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz"
@ -5628,6 +5862,11 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1:
has "^1.0.3"
has-symbols "^1.0.1"
get-nonce@^1.0.0:
version "1.0.1"
resolved "https://registry.npmmirror.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3"
integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==
get-own-enumerable-property-symbols@^3.0.0:
version "3.0.2"
resolved "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz"
@ -6236,6 +6475,13 @@ internal-slot@^1.0.3:
has "^1.0.3"
side-channel "^1.0.4"
invariant@^2.2.4:
version "2.2.4"
resolved "https://registry.npmmirror.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
dependencies:
loose-envify "^1.0.0"
ip-regex@^2.1.0:
version "2.1.0"
resolved "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz"
@ -7472,7 +7718,7 @@ loglevel@^1.6.8:
resolved "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz"
integrity sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==
loose-envify@^1.1.0, loose-envify@^1.4.0:
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
@ -9606,6 +9852,25 @@ react-refresh@^0.8.3:
resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz"
integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==
react-remove-scroll-bar@^2.3.0:
version "2.3.0"
resolved "https://registry.npmmirror.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.0.tgz#4f1c8442e4a8bbf98f0cd7ba30fdaf7bf5bcffe5"
integrity sha512-v2vf8kgrRph5FQeLVZjSOmM0g3ZiBxwMk98VXhsiJDSPeRDUaXJrzYDk2Hhoe6qLggrhWtAXJZVxUwXmRXa93g==
dependencies:
react-style-singleton "^2.2.0"
tslib "^2.0.0"
react-remove-scroll@^2.4.0:
version "2.5.1"
resolved "https://registry.npmmirror.com/react-remove-scroll/-/react-remove-scroll-2.5.1.tgz#28c318c2e076040e5d6172bf28aab2916ad89b46"
integrity sha512-Lzam+uvyTLlSCqxGeEe5fLadZQkAYYWurr7P+9kgJfgBcBhs04T181D3yqmUzML63W0FLW/oqSd6dnaE0IIisQ==
dependencies:
react-remove-scroll-bar "^2.3.0"
react-style-singleton "^2.2.0"
tslib "^2.0.0"
use-callback-ref "^1.3.0"
use-sidecar "^1.1.2"
react-scripts@4.0.3:
version "4.0.3"
resolved "https://registry.npmjs.org/react-scripts/-/react-scripts-4.0.3.tgz"
@ -9672,6 +9937,15 @@ react-scripts@4.0.3:
optionalDependencies:
fsevents "^2.1.3"
react-style-singleton@^2.2.0:
version "2.2.0"
resolved "https://registry.npmmirror.com/react-style-singleton/-/react-style-singleton-2.2.0.tgz#70f45f5fef97fdb9a52eed98d1839fa6b9032b22"
integrity sha512-nK7mN92DMYZEu3cQcAhfwE48NpzO5RpxjG4okbSqRRbfal9Pk+fG2RdQXTMp+f6all1hB9LIJSt+j7dCYrU11g==
dependencies:
get-nonce "^1.0.0"
invariant "^2.2.4"
tslib "^2.0.0"
react-universal-interface@^0.6.2:
version "0.6.2"
resolved "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz"
@ -11237,11 +11511,16 @@ tsconfig-paths@^3.11.0:
minimist "^1.2.0"
strip-bom "^3.0.0"
tslib@^1.8.1:
tslib@^1.0.0, tslib@^1.8.1:
version "1.14.1"
resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
tslib@^2.0.0:
version "2.4.0"
resolved "https://registry.npmmirror.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
tslib@^2.0.3, tslib@^2.1.0:
version "2.3.1"
resolved "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz"
@ -11482,6 +11761,21 @@ url@^0.11.0:
punycode "1.3.2"
querystring "0.2.0"
use-callback-ref@^1.3.0:
version "1.3.0"
resolved "https://registry.npmmirror.com/use-callback-ref/-/use-callback-ref-1.3.0.tgz#772199899b9c9a50526fedc4993fc7fa1f7e32d5"
integrity sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w==
dependencies:
tslib "^2.0.0"
use-sidecar@^1.1.2:
version "1.1.2"
resolved "https://registry.npmmirror.com/use-sidecar/-/use-sidecar-1.1.2.tgz#2f43126ba2d7d7e117aa5855e5d8f0276dfe73c2"
integrity sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==
dependencies:
detect-node-es "^1.1.0"
tslib "^2.0.0"
use@^3.1.0:
version "3.1.1"
resolved "https://registry.npmjs.org/use/-/use-3.1.1.tgz"

View File

@ -21,7 +21,7 @@ def load_requirements():
# https://setuptools.readthedocs.io/en/latest/setuptools.html#including-data-files
setuptools.setup(
name="lama-cleaner",
version="0.10.0",
version="0.11.0",
author="PanicByte",
author_email="cwq1913@gmail.com",
description="Image inpainting tool powered by SOTA AI Model",