diff --git a/lama_cleaner/app/.eslintrc.json b/lama_cleaner/app/.eslintrc.json
index 14846f0..d19d2dc 100644
--- a/lama_cleaner/app/.eslintrc.json
+++ b/lama_cleaner/app/.eslintrc.json
@@ -17,6 +17,7 @@
"project": "./tsconfig.json"
},
"rules": {
+ "react/jsx-props-no-spreading": 0,
"import/no-unresolved": 0,
"react/jsx-no-bind": "off",
"react/jsx-filename-extension": [
diff --git a/lama_cleaner/app/package.json b/lama_cleaner/app/package.json
index ca3a067..13095a8 100644
--- a/lama_cleaner/app/package.json
+++ b/lama_cleaner/app/package.json
@@ -5,6 +5,7 @@
"proxy": "http://localhost:8080",
"dependencies": {
"@heroicons/react": "^1.0.4",
+ "@radix-ui/react-switch": "^0.1.5",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^12.1.2",
"@testing-library/user-event": "^13.5.0",
diff --git a/lama_cleaner/app/src/components/Header/Header.scss b/lama_cleaner/app/src/components/Header/Header.scss
index 35c7933..6c80dbb 100644
--- a/lama_cleaner/app/src/components/Header/Header.scss
+++ b/lama_cleaner/app/src/components/Header/Header.scss
@@ -23,3 +23,11 @@ header {
gap: 12px;
justify-self: end;
}
+
+.header-icons {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 6px;
+ justify-self: end;
+}
\ No newline at end of file
diff --git a/lama_cleaner/app/src/components/Header/Header.tsx b/lama_cleaner/app/src/components/Header/Header.tsx
index ad17726..c0fb1cc 100644
--- a/lama_cleaner/app/src/components/Header/Header.tsx
+++ b/lama_cleaner/app/src/components/Header/Header.tsx
@@ -6,6 +6,7 @@ import Button from '../shared/Button'
import Shortcuts from '../Shortcuts/Shortcuts'
import useResolution from '../../hooks/useResolution'
import { ThemeChanger } from './ThemeChanger'
+import SettingIcon from '../Setting/SettingIcon'
const Header = () => {
const [file, setFile] = useRecoilState(fileState)
@@ -26,7 +27,11 @@ const Header = () => {
-
+
+
diff --git a/lama_cleaner/app/src/components/Setting/HDSettingBlock.tsx b/lama_cleaner/app/src/components/Setting/HDSettingBlock.tsx
new file mode 100644
index 0000000..44a1437
--- /dev/null
+++ b/lama_cleaner/app/src/components/Setting/HDSettingBlock.tsx
@@ -0,0 +1,137 @@
+import React, { ReactNode } from 'react'
+import { useRecoilState } from 'recoil'
+import { settingState } from '../../store/Atoms'
+import NumberInput from '../shared/NumberInput'
+import Selector from '../shared/Selector'
+import SettingBlock from './SettingBlock'
+
+export enum HDStrategy {
+ ORIGINAL = 'Original',
+ REISIZE = 'Resize',
+ CROP = 'Crop',
+}
+
+interface PixelSizeInputProps {
+ title: string
+ value: string
+ onValue: (val: string) => void
+}
+
+function PixelSizeInputSetting(props: PixelSizeInputProps) {
+ const { title, value, onValue } = props
+
+ return (
+
+
+ pixel
+
+ }
+ />
+ )
+}
+
+function HDSettingBlock() {
+ const [setting, setSettingState] = useRecoilState(settingState)
+
+ const onStrategyChange = (value: HDStrategy) => {
+ setSettingState(old => {
+ return { ...old, hdStrategy: value }
+ })
+ }
+
+ const onResizeLimitChange = (value: string) => {
+ setSettingState(old => {
+ return { ...old, hdStrategyResizeLimit: value }
+ })
+ }
+
+ const onCropTriggerSizeChange = (value: string) => {
+ setSettingState(old => {
+ return { ...old, hdStrategyCropTrigerSize: value }
+ })
+ }
+
+ const renderOriginalOptionDesc = () => {
+ return (
+
+ Use the original resolution of the picture, suitable for picture size
+ below 2K, of course you can try it on higher resolution pictures
+
+ )
+ }
+
+ const renderResizeOptionDesc = () => {
+ return (
+
+
+ Resize the longer side of the image to a specific size(keep ratio),
+ then do inpainting on the entire resized image.
+
+
+
+ )
+ }
+
+ const renderCropOptionDesc = () => {
+ return (
+
+
+ Crop masking area from the original image to do inpainting, and paste
+ the result back. Mainly for performance and memory reasons on high
+ resolution image.
+
+
+
+ )
+ }
+
+ const renderHDStrategyOptionDesc = (): ReactNode => {
+ switch (setting.hdStrategy) {
+ case HDStrategy.ORIGINAL:
+ return renderOriginalOptionDesc()
+ case HDStrategy.CROP:
+ return renderCropOptionDesc()
+ case HDStrategy.REISIZE:
+ return renderResizeOptionDesc()
+ default:
+ return renderOriginalOptionDesc()
+ }
+ }
+
+ return (
+
onStrategyChange(val as HDStrategy)}
+ />
+ }
+ optionDesc={renderHDStrategyOptionDesc()}
+ />
+ )
+}
+
+export default HDSettingBlock
diff --git a/lama_cleaner/app/src/components/Setting/SavePathSettingBlock.tsx b/lama_cleaner/app/src/components/Setting/SavePathSettingBlock.tsx
new file mode 100644
index 0000000..fcd5fe7
--- /dev/null
+++ b/lama_cleaner/app/src/components/Setting/SavePathSettingBlock.tsx
@@ -0,0 +1,19 @@
+import React, { ReactNode } from 'react'
+import { useRecoilState } from 'recoil'
+import { Switch, SwitchThumb } from '../shared/Switch'
+import SettingBlock from './SettingBlock'
+
+function SavePathSettingBlock() {
+ return (
+
+
+
+ }
+ />
+ )
+}
+
+export default SavePathSettingBlock
diff --git a/lama_cleaner/app/src/components/Setting/Setting.scss b/lama_cleaner/app/src/components/Setting/Setting.scss
new file mode 100644
index 0000000..81c57f9
--- /dev/null
+++ b/lama_cleaner/app/src/components/Setting/Setting.scss
@@ -0,0 +1,19 @@
+@use '../../styles/Mixins/' as *;
+@import './SettingBlock.scss';
+
+.modal-setting {
+ grid-area: main-content;
+ background-color: var(--modal-bg);
+ color: var(--modal-text-color);
+ box-shadow: 0px 0px 20px rgb(0, 0, 40, 0.2);
+ min-height: 450px;
+ width: 700px;
+
+ @include mobile {
+ display: grid;
+ width: 100%;
+ height: auto;
+ margin-top: -11rem;
+ animation: slideDown 0.2s ease-out;
+ }
+}
diff --git a/lama_cleaner/app/src/components/Setting/SettingBlock.scss b/lama_cleaner/app/src/components/Setting/SettingBlock.scss
new file mode 100644
index 0000000..f790e85
--- /dev/null
+++ b/lama_cleaner/app/src/components/Setting/SettingBlock.scss
@@ -0,0 +1,31 @@
+.setting-block {
+ display: flex;
+ flex-direction: column;
+ margin-top: 12px;
+
+ .option-desc {
+ margin-top: 12px;
+ border: 1px solid var(--border-color);
+ border-radius: 0.3rem;
+ padding: 2rem;
+ }
+}
+
+.setting-block-content {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ gap: 12rem;
+}
+
+.setting-block-content-title {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+}
+
+.setting-block-desc {
+ font-size: 1rem;
+ margin-top: 8px;
+ color: var(--text-color-gray);
+}
diff --git a/lama_cleaner/app/src/components/Setting/SettingBlock.tsx b/lama_cleaner/app/src/components/Setting/SettingBlock.tsx
new file mode 100644
index 0000000..30bb7a1
--- /dev/null
+++ b/lama_cleaner/app/src/components/Setting/SettingBlock.tsx
@@ -0,0 +1,27 @@
+import React, { ReactNode } from 'react'
+
+interface SettingBlockProps {
+ title: string
+ desc?: string
+ input: ReactNode
+ optionDesc?: ReactNode
+ className?: string
+}
+
+function SettingBlock(props: SettingBlockProps) {
+ const { title, desc, input, optionDesc, className } = props
+ return (
+
+
+
+ {title}
+ {desc && {desc} }
+
+ {input}
+
+ {optionDesc &&
{optionDesc}
}
+
+ )
+}
+
+export default SettingBlock
diff --git a/lama_cleaner/app/src/components/Setting/SettingIcon.tsx b/lama_cleaner/app/src/components/Setting/SettingIcon.tsx
new file mode 100644
index 0000000..ca11c55
--- /dev/null
+++ b/lama_cleaner/app/src/components/Setting/SettingIcon.tsx
@@ -0,0 +1,46 @@
+import React from 'react'
+import { useRecoilState } from 'recoil'
+import { settingState } from '../../store/Atoms'
+import Button from '../shared/Button'
+
+const SettingIcon = () => {
+ const [setting, setSettingState] = useRecoilState(settingState)
+
+ const onClick = () => {
+ setSettingState({ ...setting, show: !setting.show })
+ }
+
+ return (
+
+ )
+}
+
+export default SettingIcon
diff --git a/lama_cleaner/app/src/components/Setting/SettingModal.tsx b/lama_cleaner/app/src/components/Setting/SettingModal.tsx
new file mode 100644
index 0000000..98410ad
--- /dev/null
+++ b/lama_cleaner/app/src/components/Setting/SettingModal.tsx
@@ -0,0 +1,29 @@
+import React from 'react'
+
+import { useRecoilState } from 'recoil'
+import { settingState } from '../../store/Atoms'
+import Modal from '../shared/Modal'
+import HDSettingBlock from './HDSettingBlock'
+import SavePathSettingBlock from './SavePathSettingBlock'
+
+export default function SettingModal() {
+ const [setting, setSettingState] = useRecoilState(settingState)
+
+ const onClose = () => {
+ setSettingState(old => {
+ return { ...old, show: false }
+ })
+ }
+
+ return (
+
+
+
+
+ )
+}
diff --git a/lama_cleaner/app/src/components/Shortcuts/ShortcutsModal.tsx b/lama_cleaner/app/src/components/Shortcuts/ShortcutsModal.tsx
index a341d4a..0d2ca94 100644
--- a/lama_cleaner/app/src/components/Shortcuts/ShortcutsModal.tsx
+++ b/lama_cleaner/app/src/components/Shortcuts/ShortcutsModal.tsx
@@ -1,5 +1,5 @@
import React, { ReactNode } from 'react'
-import { useSetRecoilState } from 'recoil'
+import { useRecoilState } from 'recoil'
import { shortcutsState } from '../../store/Atoms'
import Modal from '../shared/Modal'
@@ -19,13 +19,8 @@ function ShortCut(props: Shortcut) {
)
}
-interface ShortcutsModalProps {
- show: boolean
-}
-
-export default function ShortcutsModal(props: ShortcutsModalProps) {
- const { show } = props
- const setShortcutState = useSetRecoilState(shortcutsState)
+export default function ShortcutsModal() {
+ const [shortcutsShow, setShortcutState] = useRecoilState(shortcutsState)
const shortcutStateHandler = () => {
setShortcutState(false)
@@ -36,7 +31,7 @@ export default function ShortcutsModal(props: ShortcutsModalProps) {
onClose={shortcutStateHandler}
title="Hotkeys"
className="modal-shortcuts"
- show={show}
+ show={shortcutsShow}
>
diff --git a/lama_cleaner/app/src/components/Workspace.tsx b/lama_cleaner/app/src/components/Workspace.tsx
index 739cf19..f084296 100644
--- a/lama_cleaner/app/src/components/Workspace.tsx
+++ b/lama_cleaner/app/src/components/Workspace.tsx
@@ -3,17 +3,18 @@ import { useRecoilValue } from 'recoil'
import Editor from './Editor/Editor'
import { shortcutsState } from '../store/Atoms'
import ShortcutsModal from './Shortcuts/ShortcutsModal'
+import SettingModal from './Setting/SettingModal'
interface WorkspaceProps {
file: File
}
const Workspace = ({ file }: WorkspaceProps) => {
- const shortcutVisbility = useRecoilValue(shortcutsState)
return (
<>
-
+
+
>
)
}
diff --git a/lama_cleaner/app/src/components/shared/Modal.tsx b/lama_cleaner/app/src/components/shared/Modal.tsx
index dcc8863..e7db92e 100644
--- a/lama_cleaner/app/src/components/shared/Modal.tsx
+++ b/lama_cleaner/app/src/components/shared/Modal.tsx
@@ -1,6 +1,6 @@
import { XIcon } from '@heroicons/react/outline'
import React, { ReactNode, useRef } from 'react'
-import { useClickAway, useKey } from 'react-use'
+import { useClickAway, useKey, useKeyPress, useKeyPressEvent } from 'react-use'
import Button from './Button'
export interface ModalProps {
@@ -19,8 +19,8 @@ export default function Modal(props: ModalProps) {
onClose?.()
})
- useKey('Escape', onClose, {
- event: 'keydown',
+ useKeyPressEvent('Escape', e => {
+ onClose?.()
})
return (
@@ -30,7 +30,7 @@ export default function Modal(props: ModalProps) {
>
-
{title}
+ {title}
} onClick={onClose} />
{children}
diff --git a/lama_cleaner/app/src/components/shared/NumberInput.scss b/lama_cleaner/app/src/components/shared/NumberInput.scss
new file mode 100644
index 0000000..ac261d2
--- /dev/null
+++ b/lama_cleaner/app/src/components/shared/NumberInput.scss
@@ -0,0 +1,12 @@
+.number-input {
+ all: unset;
+ flex: 1 0 auto;
+ border-radius: 0.5rem;
+ padding: 0.2rem 0.8rem;
+ line-height: 1;
+ outline: 1px solid var(--border-color);
+
+ &:focus-visible {
+ outline: 1px solid var(--yellow-accent);
+ }
+}
diff --git a/lama_cleaner/app/src/components/shared/NumberInput.tsx b/lama_cleaner/app/src/components/shared/NumberInput.tsx
new file mode 100644
index 0000000..5f93bca
--- /dev/null
+++ b/lama_cleaner/app/src/components/shared/NumberInput.tsx
@@ -0,0 +1,31 @@
+import React, { FormEvent, InputHTMLAttributes } from 'react'
+
+interface NumberInputProps extends InputHTMLAttributes
{
+ value: string
+ onValue?: (val: string) => void
+}
+
+const NumberInput = React.forwardRef(
+ (props: NumberInputProps, forwardedRef) => {
+ const { value, onValue, ...itemProps } = props
+
+ const handleOnInput = (evt: FormEvent) => {
+ const target = evt.target as HTMLInputElement
+ const val = target.value.replace(/\D/g, '')
+ onValue?.(val)
+ }
+
+ return (
+
+ )
+ }
+)
+
+export default NumberInput
diff --git a/lama_cleaner/app/src/components/shared/Selector.scss b/lama_cleaner/app/src/components/shared/Selector.scss
new file mode 100644
index 0000000..22f2170
--- /dev/null
+++ b/lama_cleaner/app/src/components/shared/Selector.scss
@@ -0,0 +1,74 @@
+@use '../../styles/Mixins' as *;
+
+.selector {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ 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;
+ gap: 8px;
+ padding: 0.2rem 0.8rem;
+
+ border: 1px solid var(--border-color);
+ color: var(--options-text-color);
+
+ svg {
+ width: 1rem;
+ 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);
+ color: var(--btn-text-hover-color);
+ }
+ }
+}
diff --git a/lama_cleaner/app/src/components/shared/Selector.tsx b/lama_cleaner/app/src/components/shared/Selector.tsx
new file mode 100644
index 0000000..d256606
--- /dev/null
+++ b/lama_cleaner/app/src/components/shared/Selector.tsx
@@ -0,0 +1,87 @@
+import React, { MutableRefObject, useCallback, useRef, useState } from 'react'
+import { useClickAway, useKeyPressEvent } from 'react-use'
+import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/react/outline'
+
+type SelectorChevronDirection = 'up' | 'down'
+
+type SelectorProps = {
+ minWidth?: number
+ chevronDirection?: SelectorChevronDirection
+ options: string[]
+ onChange: (value: string) => void
+}
+
+const selectorDefaultProps = {
+ minWidth: 128,
+ chevronDirection: 'down',
+}
+
+function Selector(props: SelectorProps) {
+ const { minWidth, chevronDirection, options, onChange } = props
+ const [showOptions, setShowOptions] = useState(false)
+ const [index, setIndex] = useState(0)
+ const selectorRef = useRef(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)
+ setIndex(newIndex)
+ }
+
+ return (
+
+
+
{options[index]}
+
+ {chevronDirection === 'up' ? : }
+
+
+
+ {showOptions && (
+
+ {options.map((val, _index) => (
+
onOptionClick(e, _index)}
+ aria-hidden="true"
+ >
+ {val}
+
+ ))}
+
+ )}
+
+ )
+}
+
+Selector.defaultProps = selectorDefaultProps
+export default Selector
diff --git a/lama_cleaner/app/src/components/shared/Switch.scss b/lama_cleaner/app/src/components/shared/Switch.scss
new file mode 100644
index 0000000..03a5610
--- /dev/null
+++ b/lama_cleaner/app/src/components/shared/Switch.scss
@@ -0,0 +1,36 @@
+.switch-root {
+ all: 'unset';
+ width: 42px;
+ height: 25px;
+ background-color: var(--switch-root-background-color);
+ border-radius: 9999px;
+ border: none;
+ position: relative;
+ transition: background-color 100ms;
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+
+ &:focus-visible {
+ outline: none;
+ }
+}
+
+.switch-root[data-state='checked'] {
+ background-color: var(--yellow-accent);
+}
+
+.switch-thumb {
+ display: block;
+ width: 17px;
+ height: 17px;
+ background-color: var(--switch-thumb-color);
+ border-radius: 9999px;
+ transition: transform 100ms;
+ transform: translateX(4px);
+ will-change: transform;
+}
+
+.switch-thumb[data-state='checked'] {
+ transform: translateX(21px);
+ background-color: var(--switch-thumb-checked-color);
+ outline: 1px solid rgb(100, 100, 120, 0.5);
+}
diff --git a/lama_cleaner/app/src/components/shared/Switch.tsx b/lama_cleaner/app/src/components/shared/Switch.tsx
new file mode 100644
index 0000000..fea7e49
--- /dev/null
+++ b/lama_cleaner/app/src/components/shared/Switch.tsx
@@ -0,0 +1,34 @@
+import React from 'react'
+import * as SwitchPrimitive from '@radix-ui/react-switch'
+
+const Switch = React.forwardRef<
+ React.ElementRef,
+ React.ComponentProps
+>((props, forwardedRef) => {
+ const { className, ...itemProps } = props
+
+ return (
+
+ )
+})
+
+const SwitchThumb = React.forwardRef<
+ React.ElementRef,
+ React.ComponentProps
+>((props, forwardedRef) => {
+ const { className, ...itemProps } = props
+
+ return (
+
+ )
+})
+
+export { Switch, SwitchThumb }
diff --git a/lama_cleaner/app/src/store/Atoms.tsx b/lama_cleaner/app/src/store/Atoms.tsx
index dbfe682..f37164a 100644
--- a/lama_cleaner/app/src/store/Atoms.tsx
+++ b/lama_cleaner/app/src/store/Atoms.tsx
@@ -1,4 +1,5 @@
import { atom } from 'recoil'
+import { HDStrategy } from '../components/Setting/HDSettingBlock'
export const fileState = atom({
key: 'fileState',
@@ -9,3 +10,20 @@ export const shortcutsState = atom({
key: 'shortcutsState',
default: false,
})
+
+export interface Setting {
+ show: boolean
+ hdStrategy: HDStrategy
+ hdStrategyResizeLimit: string
+ hdStrategyCropTrigerSize: string
+}
+
+export const settingState = atom({
+ key: 'settingsState',
+ default: {
+ show: false,
+ hdStrategy: HDStrategy.ORIGINAL,
+ hdStrategyResizeLimit: '2048',
+ hdStrategyCropTrigerSize: '2048',
+ },
+})
diff --git a/lama_cleaner/app/src/styles/_Colors.scss b/lama_cleaner/app/src/styles/_Colors.scss
index f138b3f..468735a 100644
--- a/lama_cleaner/app/src/styles/_Colors.scss
+++ b/lama_cleaner/app/src/styles/_Colors.scss
@@ -17,13 +17,22 @@
--modal-bg: var(--page-bg);
--modal-text-color: rgb(0, 0, 0);
--modal-hotkey-border-color: rgb(0, 0, 0);
- --model-mask-bg: rgba(209,213,219,0.4);
+ --model-mask-bg: rgba(209, 213, 219, 0.4);
+
+ // Text
+ --text-color: #040404;
+ --text-color-gray: rgb(107, 111, 118);
// Shared
--btn-primary-bg: rgb(210, 210, 220);
- --btn-text-color: black;
- --btn-text-hover-color: black;
+ --btn-text-color: var(--text-color);
+ --btn-text-hover-color: #040404;
--btn-border-color: rgb(100, 100, 120);
--btn-primary-hover-bg: var(--yellow-accent);
--animation-pulsing-bg: rgb(255, 255, 255, 0.5);
+
+ // switch
+ --switch-root-background-color: rgb(223, 225, 228);
+ --switch-thumb-color: var(--page-bg);
+ --switch-thumb-checked-color: var(--page-bg);
}
diff --git a/lama_cleaner/app/src/styles/_ColorsDark.scss b/lama_cleaner/app/src/styles/_ColorsDark.scss
index a288203..6a48fc3 100644
--- a/lama_cleaner/app/src/styles/_ColorsDark.scss
+++ b/lama_cleaner/app/src/styles/_ColorsDark.scss
@@ -3,7 +3,7 @@
// Theme
--page-bg: #040404;
- --page-text-color: #F9F9F9;
+ --page-text-color: #f9f9f9;
--yellow-accent: #ffcc00;
--link-color: var(--yellow-accent);
--border-color: rgb(100, 100, 120);
@@ -17,14 +17,23 @@
--modal-bg: var(--page-bg);
--modal-text-color: var(--page-text-color);
// --modal-hotkey-bg: rgb(60, 60, 90);
- --modal-hotkey-border-color: var(--page-text-color);;
+ --modal-hotkey-border-color: var(--page-text-color);
--model-mask-bg: rgba(76, 76, 87, 0.4);
+ // Text
+ --text-color: white;
+ --text-color-gray: rgb(138, 143, 152);
+
// Shared
--btn-primary-bg: rgb(140, 140, 180);
- --btn-text-color: white;
+ --btn-text-color: var(--text-color);
--btn-text-hover-color: var(--page-bg);
--btn-border-color: var(--yellow-accent);
--btn-primary-hover-bg: var(--yellow-accent);
--animation-pulsing-bg: rgb(240, 240, 255);
+
+ // switch
+ --switch-root-background-color: rgb(60, 63, 68);
+ --switch-thumb-color: rgb(31, 32, 35);
+ --switch-thumb-checked-color: white;
}
diff --git a/lama_cleaner/app/src/styles/_index.scss b/lama_cleaner/app/src/styles/_index.scss
index ac169b6..e8362a6 100644
--- a/lama_cleaner/app/src/styles/_index.scss
+++ b/lama_cleaner/app/src/styles/_index.scss
@@ -11,11 +11,15 @@
@use '../components/Header/Header';
@use '../components/Header/ThemeChanger';
@use '../components/Shortcuts/Shortcuts';
+@use '../components/Setting/Setting.scss';
// Shared
@use '../components/FileSelect/FileSelect';
@use '../components/shared/Button';
@use '../components/shared/Modal';
+@use '../components/shared/Selector';
+@use '../components/shared/Switch';
+@use '../components/shared/NumberInput';
// Main CSS
*,
diff --git a/lama_cleaner/app/yarn.lock b/lama_cleaner/app/yarn.lock
index b6b75cf..153b58d 100644
--- a/lama_cleaner/app/yarn.lock
+++ b/lama_cleaner/app/yarn.lock
@@ -1164,6 +1164,13 @@
dependencies:
regenerator-runtime "^0.13.4"
+"@babel/runtime@^7.13.10":
+ version "7.17.9"
+ resolved "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.17.9.tgz#d19fbf802d01a8cb6cf053a64e472d42c434ba72"
+ integrity sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==
+ dependencies:
+ regenerator-runtime "^0.13.4"
+
"@babel/template@^7.10.4", "@babel/template@^7.15.4", "@babel/template@^7.3.3":
version "7.15.4"
resolved "https://registry.npmjs.org/@babel/template/-/template-7.15.4.tgz"
@@ -1537,6 +1544,113 @@
schema-utils "^2.6.5"
source-map "^0.7.3"
+"@radix-ui/primitive@0.1.0":
+ version "0.1.0"
+ resolved "https://registry.npmmirror.com/@radix-ui/primitive/-/primitive-0.1.0.tgz#6206b97d379994f0d1929809db035733b337e543"
+ integrity sha512-tqxZKybwN5Fa3VzZry4G6mXAAb9aAqKmPtnVbZpL0vsBwvOHTBwsjHVPXylocYLwEtBY9SCe665bYnNB515uoA==
+ dependencies:
+ "@babel/runtime" "^7.13.10"
+
+"@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"
+ integrity sha512-eyclbh+b77k+69Dk72q3694OHrn9B3QsoIRx7ywX341U9RK1ThgQjMFZoPtmZNQTksXHLNEiefR8hGVeFyInGg==
+ 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"
+ integrity sha512-PkyVX1JsLBioeu0jB9WvRpDBBLtLZohVDT3BB5CTSJqActma8S8030P57mWZb4baZifMvN7KKWPAA40UmWKkQg==
+ dependencies:
+ "@babel/runtime" "^7.13.10"
+
+"@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"
+ integrity sha512-IPc4H/63bes0IZ1GJJozSEkSWcDyhNGtKFWUpJ+XtaLyQ1X3x7Mf6fWwWhDcpqlYEP+5WtAvfqcyEsyjP+ZhBQ==
+ dependencies:
+ "@babel/runtime" "^7.13.10"
+ "@radix-ui/react-use-layout-effect" "0.1.0"
+
+"@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"
+ integrity sha512-Au9+n4/DhvjR0IHhvZ1LPdx/OW+3CGDie30ZyCkbSHIuLp4/CV4oPPGBwJ1vY99Jog3zyQhsGww9MXj8O9Aj/A==
+ dependencies:
+ "@babel/runtime" "^7.13.10"
+ "@radix-ui/react-compose-refs" "0.1.0"
+ "@radix-ui/react-context" "0.1.1"
+ "@radix-ui/react-id" "0.1.5"
+ "@radix-ui/react-primitive" "0.1.4"
+
+"@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"
+ integrity sha512-6gSl2IidySupIMJFjYnDIkIWRyQdbu/AHK7rbICPani+LW4b0XdxBXc46og/iZvuwW8pjCS8I2SadIerv84xYA==
+ dependencies:
+ "@babel/runtime" "^7.13.10"
+ "@radix-ui/react-slot" "0.1.2"
+
+"@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"
+ integrity sha512-ADkqfL+agEzEguU3yS26jfB50hRrwf7U4VTwAOZEmi/g+ITcBWe12yM46ueS/UCIMI9Py+gFUaAdxgxafFvY2Q==
+ dependencies:
+ "@babel/runtime" "^7.13.10"
+ "@radix-ui/react-compose-refs" "0.1.0"
+
+"@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"
+ integrity sha512-ITtslJPK+Yi34iNf7K9LtsPaLD76oRIVzn0E8JpEO5HW8gpRBGb2NNI9mxKtEB30TVqIcdjdL10AmuIfOMwjtg==
+ dependencies:
+ "@babel/runtime" "^7.13.10"
+ "@radix-ui/primitive" "0.1.0"
+ "@radix-ui/react-compose-refs" "0.1.0"
+ "@radix-ui/react-context" "0.1.1"
+ "@radix-ui/react-label" "0.1.5"
+ "@radix-ui/react-primitive" "0.1.4"
+ "@radix-ui/react-use-controllable-state" "0.1.0"
+ "@radix-ui/react-use-previous" "0.1.1"
+ "@radix-ui/react-use-size" "0.1.1"
+
+"@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"
+ integrity sha512-Va041McOFFl+aV+sejvl0BS2aeHx86ND9X/rVFmEFQKTXCp6xgUK0NGUAGcgBlIjnJSbMYPGEk1xKSSlVcN2Aw==
+ 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"
+ integrity sha512-zv7CX/PgsRl46a52Tl45TwqwVJdmqnlQEQhaYMz/yBOD2sx2gCkCFSoF/z9mpnYWmS6DTLNTg5lIps3fV6EnXg==
+ dependencies:
+ "@babel/runtime" "^7.13.10"
+ "@radix-ui/react-use-callback-ref" "0.1.0"
+
+"@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"
+ integrity sha512-+wdeS51Y+E1q1Wmd+1xSSbesZkpVj4jsg0BojCbopWvgq5iBvixw5vgemscdh58ep98BwUbsFYnrywFhV9yrVg==
+ 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"
+ integrity sha512-O/ZgrDBr11dR8rhO59ED8s5zIXBRFi8MiS+CmFGfi7MJYdLbfqVOmQU90Ghf87aifEgWe6380LA69KBneaShAg==
+ 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"
+ integrity sha512-pTgWM5qKBu6C7kfKxrKPoBI2zZYZmp2cSXzpUiGM3qEBQlMLtYhaY2JXdXUCxz+XmD1YEjc8oRwvyfsD4AG4WA==
+ dependencies:
+ "@babel/runtime" "^7.13.10"
+
"@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"