mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
Fix Sliders unable to take typed input (#2407)
So far the slider component was unable to take typed input due to a bunch of issues that were a pain to solve. This PR fixes it. Things to test: - Moving the slider also updates the value in the input text box. - Input text box next to slider can be changed in two ways: If you type a manual value, the slider will be updated when you lose focus from the input box. If you use the stepper icons to update the values, the slider should update immediately. - Make sure the reset buttons next to the slider are updating correctly and make sure this updates both the slider and the input box values. - Brush Size slider -> make sure the hotkeys are updating the input box too.
This commit is contained in:
commit
f36114eb94
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
4
frontend/dist/index.html
vendored
4
frontend/dist/index.html
vendored
@ -7,7 +7,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>InvokeAI - A Stable Diffusion Toolkit</title>
|
<title>InvokeAI - A Stable Diffusion Toolkit</title>
|
||||||
<link rel="shortcut icon" type="icon" href="./assets/favicon.0d253ced.ico" />
|
<link rel="shortcut icon" type="icon" href="./assets/favicon.0d253ced.ico" />
|
||||||
<script type="module" crossorigin src="./assets/index.d5dcf0c5.js"></script>
|
<script type="module" crossorigin src="./assets/index.1d13f8a7.js"></script>
|
||||||
<link rel="stylesheet" href="./assets/index.8badc8b4.css">
|
<link rel="stylesheet" href="./assets/index.8badc8b4.css">
|
||||||
<script type="module">try{import.meta.url;import("_").catch(()=>1);}catch(e){}window.__vite_is_modern_browser=true;</script>
|
<script type="module">try{import.meta.url;import("_").catch(()=>1);}catch(e){}window.__vite_is_modern_browser=true;</script>
|
||||||
<script type="module">!function(){if(window.__vite_is_modern_browser)return;console.warn("vite: loading legacy build because dynamic import or import.meta.url is unsupported, syntax error above should be ignored");var e=document.getElementById("vite-legacy-polyfill"),n=document.createElement("script");n.src=e.src,n.onload=function(){System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))},document.body.appendChild(n)}();</script>
|
<script type="module">!function(){if(window.__vite_is_modern_browser)return;console.warn("vite: loading legacy build because dynamic import or import.meta.url is unsupported, syntax error above should be ignored");var e=document.getElementById("vite-legacy-polyfill"),n=document.createElement("script");n.src=e.src,n.onload=function(){System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))},document.body.appendChild(n)}();</script>
|
||||||
@ -18,6 +18,6 @@
|
|||||||
|
|
||||||
<script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
|
<script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
|
||||||
<script nomodule crossorigin id="vite-legacy-polyfill" src="./assets/polyfills-legacy-dde3a68a.js"></script>
|
<script nomodule crossorigin id="vite-legacy-polyfill" src="./assets/polyfills-legacy-dde3a68a.js"></script>
|
||||||
<script nomodule crossorigin id="vite-legacy-entry" data-src="./assets/index-legacy-dad2eee9.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
|
<script nomodule crossorigin id="vite-legacy-entry" data-src="./assets/index-legacy-65b0dda3.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -23,7 +23,7 @@ import {
|
|||||||
Tooltip,
|
Tooltip,
|
||||||
TooltipProps,
|
TooltipProps,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import React, { FocusEvent, useEffect, useMemo, useState } from 'react';
|
import React, { FocusEvent, useMemo, useState, useEffect } from 'react';
|
||||||
import { BiReset } from 'react-icons/bi';
|
import { BiReset } from 'react-icons/bi';
|
||||||
import IAIIconButton, { IAIIconButtonProps } from './IAIIconButton';
|
import IAIIconButton, { IAIIconButtonProps } from './IAIIconButton';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
@ -81,7 +81,7 @@ export default function IAISlider(props: IAIFullSliderProps) {
|
|||||||
withInput = false,
|
withInput = false,
|
||||||
isInteger = false,
|
isInteger = false,
|
||||||
inputWidth = '5.5rem',
|
inputWidth = '5.5rem',
|
||||||
inputReadOnly = true,
|
inputReadOnly = false,
|
||||||
withReset = false,
|
withReset = false,
|
||||||
hideTooltip = false,
|
hideTooltip = false,
|
||||||
isCompact = false,
|
isCompact = false,
|
||||||
@ -103,32 +103,35 @@ export default function IAISlider(props: IAIFullSliderProps) {
|
|||||||
...rest
|
...rest
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const [localInputValue, setLocalInputValue] = useState<string>(String(value));
|
const [localInputValue, setLocalInputValue] = useState<
|
||||||
|
string | number | undefined
|
||||||
|
>(String(value));
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setLocalInputValue(value);
|
||||||
|
}, [value]);
|
||||||
|
|
||||||
const numberInputMax = useMemo(
|
const numberInputMax = useMemo(
|
||||||
() => (sliderNumberInputProps?.max ? sliderNumberInputProps.max : max),
|
() => (sliderNumberInputProps?.max ? sliderNumberInputProps.max : max),
|
||||||
[max, sliderNumberInputProps?.max]
|
[max, sliderNumberInputProps?.max]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
const handleSliderChange = (v: number) => {
|
||||||
if (String(value) !== localInputValue && localInputValue !== '') {
|
onChange(v);
|
||||||
setLocalInputValue(String(value));
|
};
|
||||||
}
|
|
||||||
}, [value, localInputValue, setLocalInputValue]);
|
|
||||||
|
|
||||||
const handleInputBlur = (e: FocusEvent<HTMLInputElement>) => {
|
const handleInputBlur = (e: FocusEvent<HTMLInputElement>) => {
|
||||||
|
if (e.target.value === '') e.target.value = String(min);
|
||||||
const clamped = _.clamp(
|
const clamped = _.clamp(
|
||||||
isInteger ? Math.floor(Number(e.target.value)) : Number(e.target.value),
|
isInteger ? Math.floor(Number(e.target.value)) : Number(localInputValue),
|
||||||
min,
|
min,
|
||||||
numberInputMax
|
numberInputMax
|
||||||
);
|
);
|
||||||
setLocalInputValue(String(clamped));
|
|
||||||
onChange(clamped);
|
onChange(clamped);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleInputChange = (v: number | string) => {
|
const handleInputChange = (v: number | string) => {
|
||||||
setLocalInputValue(String(v));
|
setLocalInputValue(v);
|
||||||
onChange(Number(v));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleResetDisable = () => {
|
const handleResetDisable = () => {
|
||||||
@ -172,7 +175,7 @@ export default function IAISlider(props: IAIFullSliderProps) {
|
|||||||
min={min}
|
min={min}
|
||||||
max={max}
|
max={max}
|
||||||
step={step}
|
step={step}
|
||||||
onChange={handleInputChange}
|
onChange={handleSliderChange}
|
||||||
onMouseEnter={() => setShowTooltip(true)}
|
onMouseEnter={() => setShowTooltip(true)}
|
||||||
onMouseLeave={() => setShowTooltip(false)}
|
onMouseLeave={() => setShowTooltip(false)}
|
||||||
focusThumbOnChange={false}
|
focusThumbOnChange={false}
|
||||||
@ -236,13 +239,19 @@ export default function IAISlider(props: IAIFullSliderProps) {
|
|||||||
<NumberInputField
|
<NumberInputField
|
||||||
className="invokeai__slider-number-input"
|
className="invokeai__slider-number-input"
|
||||||
width={inputWidth}
|
width={inputWidth}
|
||||||
minWidth={inputWidth}
|
|
||||||
readOnly={inputReadOnly}
|
readOnly={inputReadOnly}
|
||||||
|
minWidth={inputWidth}
|
||||||
{...sliderNumberInputFieldProps}
|
{...sliderNumberInputFieldProps}
|
||||||
/>
|
/>
|
||||||
<NumberInputStepper {...sliderNumberInputStepperProps}>
|
<NumberInputStepper {...sliderNumberInputStepperProps}>
|
||||||
<NumberIncrementStepper className="invokeai__slider-number-stepper" />
|
<NumberIncrementStepper
|
||||||
<NumberDecrementStepper className="invokeai__slider-number-stepper" />
|
onClick={() => onChange(Number(localInputValue))}
|
||||||
|
className="invokeai__slider-number-stepper"
|
||||||
|
/>
|
||||||
|
<NumberDecrementStepper
|
||||||
|
onClick={() => onChange(Number(localInputValue))}
|
||||||
|
className="invokeai__slider-number-stepper"
|
||||||
|
/>
|
||||||
</NumberInputStepper>
|
</NumberInputStepper>
|
||||||
</NumberInput>
|
</NumberInput>
|
||||||
)}
|
)}
|
||||||
|
@ -75,11 +75,12 @@ const BoundingBoxSettings = () => {
|
|||||||
step={64}
|
step={64}
|
||||||
value={boundingBoxDimensions.width}
|
value={boundingBoxDimensions.width}
|
||||||
onChange={handleChangeWidth}
|
onChange={handleChangeWidth}
|
||||||
handleReset={handleResetWidth}
|
|
||||||
sliderNumberInputProps={{ max: 4096 }}
|
sliderNumberInputProps={{ max: 4096 }}
|
||||||
withSliderMarks
|
withSliderMarks
|
||||||
withInput
|
withInput
|
||||||
|
inputReadOnly
|
||||||
withReset
|
withReset
|
||||||
|
handleReset={handleResetWidth}
|
||||||
/>
|
/>
|
||||||
<IAISlider
|
<IAISlider
|
||||||
label={t('options:height')}
|
label={t('options:height')}
|
||||||
@ -88,11 +89,12 @@ const BoundingBoxSettings = () => {
|
|||||||
step={64}
|
step={64}
|
||||||
value={boundingBoxDimensions.height}
|
value={boundingBoxDimensions.height}
|
||||||
onChange={handleChangeHeight}
|
onChange={handleChangeHeight}
|
||||||
handleReset={handleResetHeight}
|
|
||||||
sliderNumberInputProps={{ max: 4096 }}
|
sliderNumberInputProps={{ max: 4096 }}
|
||||||
withSliderMarks
|
withSliderMarks
|
||||||
withInput
|
withInput
|
||||||
|
inputReadOnly
|
||||||
withReset
|
withReset
|
||||||
|
handleReset={handleResetHeight}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
|
@ -124,11 +124,12 @@ const InfillAndScalingOptions = () => {
|
|||||||
step={64}
|
step={64}
|
||||||
value={scaledBoundingBoxDimensions.width}
|
value={scaledBoundingBoxDimensions.width}
|
||||||
onChange={handleChangeScaledWidth}
|
onChange={handleChangeScaledWidth}
|
||||||
handleReset={handleResetScaledWidth}
|
|
||||||
sliderNumberInputProps={{ max: 4096 }}
|
sliderNumberInputProps={{ max: 4096 }}
|
||||||
withSliderMarks
|
withSliderMarks
|
||||||
withInput
|
withInput
|
||||||
|
inputReadOnly
|
||||||
withReset
|
withReset
|
||||||
|
handleReset={handleResetScaledWidth}
|
||||||
/>
|
/>
|
||||||
<IAISlider
|
<IAISlider
|
||||||
isInputDisabled={!isManual}
|
isInputDisabled={!isManual}
|
||||||
@ -140,11 +141,12 @@ const InfillAndScalingOptions = () => {
|
|||||||
step={64}
|
step={64}
|
||||||
value={scaledBoundingBoxDimensions.height}
|
value={scaledBoundingBoxDimensions.height}
|
||||||
onChange={handleChangeScaledHeight}
|
onChange={handleChangeScaledHeight}
|
||||||
handleReset={handleResetScaledHeight}
|
|
||||||
sliderNumberInputProps={{ max: 4096 }}
|
sliderNumberInputProps={{ max: 4096 }}
|
||||||
withSliderMarks
|
withSliderMarks
|
||||||
withInput
|
withInput
|
||||||
|
inputReadOnly
|
||||||
withReset
|
withReset
|
||||||
|
handleReset={handleResetScaledHeight}
|
||||||
/>
|
/>
|
||||||
<InpaintReplace />
|
<InpaintReplace />
|
||||||
<IAISelect
|
<IAISelect
|
||||||
@ -166,12 +168,12 @@ const InfillAndScalingOptions = () => {
|
|||||||
onChange={(v) => {
|
onChange={(v) => {
|
||||||
dispatch(setTileSize(v));
|
dispatch(setTileSize(v));
|
||||||
}}
|
}}
|
||||||
handleReset={() => {
|
|
||||||
dispatch(setTileSize(32));
|
|
||||||
}}
|
|
||||||
withInput
|
withInput
|
||||||
withSliderMarks
|
withSliderMarks
|
||||||
withReset
|
withReset
|
||||||
|
handleReset={() => {
|
||||||
|
dispatch(setTileSize(32));
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
|
@ -36,7 +36,7 @@ export default function InpaintReplace() {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex alignItems={'center'} columnGap={'1rem'}>
|
<Flex alignItems={'center'} columnGap={'0.2rem'}>
|
||||||
<IAISlider
|
<IAISlider
|
||||||
label={t('options:inpaintReplace')}
|
label={t('options:inpaintReplace')}
|
||||||
value={inpaintReplace}
|
value={inpaintReplace}
|
||||||
@ -51,7 +51,8 @@ export default function InpaintReplace() {
|
|||||||
withSliderMarks
|
withSliderMarks
|
||||||
sliderMarkRightOffset={-2}
|
sliderMarkRightOffset={-2}
|
||||||
withReset
|
withReset
|
||||||
handleReset={() => dispatch(setInpaintReplace(1))}
|
handleReset={() => dispatch(setInpaintReplace(0.1))}
|
||||||
|
withInput
|
||||||
isResetDisabled={!shouldUseInpaintReplace}
|
isResetDisabled={!shouldUseInpaintReplace}
|
||||||
/>
|
/>
|
||||||
<IAISwitch
|
<IAISwitch
|
||||||
|
@ -1,113 +0,0 @@
|
|||||||
import { Flex } from '@chakra-ui/react';
|
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
|
||||||
import IAISlider from 'common/components/IAISlider';
|
|
||||||
import { optionsSelector } from 'features/options/store/optionsSelectors';
|
|
||||||
import {
|
|
||||||
setSeamBlur,
|
|
||||||
setSeamSize,
|
|
||||||
setSeamSteps,
|
|
||||||
setSeamStrength,
|
|
||||||
} from 'features/options/store/optionsSlice';
|
|
||||||
import _ from 'lodash';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
const selector = createSelector(
|
|
||||||
[optionsSelector],
|
|
||||||
(options) => {
|
|
||||||
const { seamSize, seamBlur, seamStrength, seamSteps } = options;
|
|
||||||
|
|
||||||
return {
|
|
||||||
seamSize,
|
|
||||||
seamBlur,
|
|
||||||
seamStrength,
|
|
||||||
seamSteps,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
{
|
|
||||||
memoizeOptions: {
|
|
||||||
resultEqualityCheck: _.isEqual,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const SeamCorrectionOptions = () => {
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
const { seamSize, seamBlur, seamStrength, seamSteps } =
|
|
||||||
useAppSelector(selector);
|
|
||||||
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Flex direction="column" gap="1rem">
|
|
||||||
<IAISlider
|
|
||||||
sliderMarkRightOffset={-6}
|
|
||||||
label={t('options:seamSize')}
|
|
||||||
min={1}
|
|
||||||
max={256}
|
|
||||||
sliderNumberInputProps={{ max: 512 }}
|
|
||||||
value={seamSize}
|
|
||||||
onChange={(v) => {
|
|
||||||
dispatch(setSeamSize(v));
|
|
||||||
}}
|
|
||||||
handleReset={() => dispatch(setSeamSize(96))}
|
|
||||||
withInput
|
|
||||||
withSliderMarks
|
|
||||||
withReset
|
|
||||||
/>
|
|
||||||
<IAISlider
|
|
||||||
sliderMarkRightOffset={-4}
|
|
||||||
label={t('options:seamBlur')}
|
|
||||||
min={0}
|
|
||||||
max={64}
|
|
||||||
sliderNumberInputProps={{ max: 512 }}
|
|
||||||
value={seamBlur}
|
|
||||||
onChange={(v) => {
|
|
||||||
dispatch(setSeamBlur(v));
|
|
||||||
}}
|
|
||||||
handleReset={() => {
|
|
||||||
dispatch(setSeamBlur(16));
|
|
||||||
}}
|
|
||||||
withInput
|
|
||||||
withSliderMarks
|
|
||||||
withReset
|
|
||||||
/>
|
|
||||||
<IAISlider
|
|
||||||
sliderMarkRightOffset={-7}
|
|
||||||
label={t('options:seamStrength')}
|
|
||||||
min={0.01}
|
|
||||||
max={0.99}
|
|
||||||
step={0.01}
|
|
||||||
value={seamStrength}
|
|
||||||
onChange={(v) => {
|
|
||||||
dispatch(setSeamStrength(v));
|
|
||||||
}}
|
|
||||||
handleReset={() => {
|
|
||||||
dispatch(setSeamStrength(0.7));
|
|
||||||
}}
|
|
||||||
withInput
|
|
||||||
withSliderMarks
|
|
||||||
withReset
|
|
||||||
/>
|
|
||||||
<IAISlider
|
|
||||||
sliderMarkRightOffset={-4}
|
|
||||||
label={t('options:seamSteps')}
|
|
||||||
min={1}
|
|
||||||
max={32}
|
|
||||||
sliderNumberInputProps={{ max: 100 }}
|
|
||||||
value={seamSteps}
|
|
||||||
onChange={(v) => {
|
|
||||||
dispatch(setSeamSteps(v));
|
|
||||||
}}
|
|
||||||
handleReset={() => {
|
|
||||||
dispatch(setSeamSteps(10));
|
|
||||||
}}
|
|
||||||
withInput
|
|
||||||
withSliderMarks
|
|
||||||
withReset
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SeamCorrectionOptions;
|
|
@ -0,0 +1,32 @@
|
|||||||
|
import type { RootState } from 'app/store';
|
||||||
|
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||||
|
import IAISlider from 'common/components/IAISlider';
|
||||||
|
import { setSeamBlur } from 'features/options/store/optionsSlice';
|
||||||
|
import React from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
export default function SeamBlur() {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const seamBlur = useAppSelector((state: RootState) => state.options.seamBlur);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IAISlider
|
||||||
|
sliderMarkRightOffset={-4}
|
||||||
|
label={t('options:seamBlur')}
|
||||||
|
min={0}
|
||||||
|
max={64}
|
||||||
|
sliderNumberInputProps={{ max: 512 }}
|
||||||
|
value={seamBlur}
|
||||||
|
onChange={(v) => {
|
||||||
|
dispatch(setSeamBlur(v));
|
||||||
|
}}
|
||||||
|
withInput
|
||||||
|
withSliderMarks
|
||||||
|
withReset
|
||||||
|
handleReset={() => {
|
||||||
|
dispatch(setSeamBlur(16));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
import { Flex } from '@chakra-ui/react';
|
||||||
|
import SeamBlur from './SeamBlur';
|
||||||
|
import SeamSize from './SeamSize';
|
||||||
|
import SeamSteps from './SeamSteps';
|
||||||
|
import SeamStrength from './SeamStrength';
|
||||||
|
|
||||||
|
const SeamCorrectionOptions = () => {
|
||||||
|
return (
|
||||||
|
<Flex direction="column" gap="1rem">
|
||||||
|
<SeamSize />
|
||||||
|
<SeamBlur />
|
||||||
|
<SeamStrength />
|
||||||
|
<SeamSteps />
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SeamCorrectionOptions;
|
@ -0,0 +1,31 @@
|
|||||||
|
import type { RootState } from 'app/store';
|
||||||
|
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||||
|
import IAISlider from 'common/components/IAISlider';
|
||||||
|
import { setSeamSize } from 'features/options/store/optionsSlice';
|
||||||
|
import React from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
export default function SeamSize() {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const seamSize = useAppSelector((state: RootState) => state.options.seamSize);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IAISlider
|
||||||
|
sliderMarkRightOffset={-6}
|
||||||
|
label={t('options:seamSize')}
|
||||||
|
min={1}
|
||||||
|
max={256}
|
||||||
|
sliderNumberInputProps={{ max: 512 }}
|
||||||
|
value={seamSize}
|
||||||
|
onChange={(v) => {
|
||||||
|
dispatch(setSeamSize(v));
|
||||||
|
}}
|
||||||
|
withInput
|
||||||
|
withSliderMarks
|
||||||
|
withReset
|
||||||
|
handleReset={() => dispatch(setSeamSize(96))}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
import type { RootState } from 'app/store';
|
||||||
|
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||||
|
import IAISlider from 'common/components/IAISlider';
|
||||||
|
import { setSeamSteps } from 'features/options/store/optionsSlice';
|
||||||
|
import React from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
export default function SeamSteps() {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const seamSteps = useAppSelector(
|
||||||
|
(state: RootState) => state.options.seamSteps
|
||||||
|
);
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IAISlider
|
||||||
|
sliderMarkRightOffset={-4}
|
||||||
|
label={t('options:seamSteps')}
|
||||||
|
min={1}
|
||||||
|
max={32}
|
||||||
|
sliderNumberInputProps={{ max: 999 }}
|
||||||
|
value={seamSteps}
|
||||||
|
onChange={(v) => {
|
||||||
|
dispatch(setSeamSteps(v));
|
||||||
|
}}
|
||||||
|
withInput
|
||||||
|
withSliderMarks
|
||||||
|
withReset
|
||||||
|
handleReset={() => {
|
||||||
|
dispatch(setSeamSteps(10));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
import { RootState } from 'app/store';
|
||||||
|
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||||
|
import IAISlider from 'common/components/IAISlider';
|
||||||
|
import { setSeamStrength } from 'features/options/store/optionsSlice';
|
||||||
|
import React from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
export default function SeamStrength() {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const seamStrength = useAppSelector(
|
||||||
|
(state: RootState) => state.options.seamStrength
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IAISlider
|
||||||
|
sliderMarkRightOffset={-7}
|
||||||
|
label={t('options:seamStrength')}
|
||||||
|
min={0.01}
|
||||||
|
max={0.99}
|
||||||
|
step={0.01}
|
||||||
|
value={seamStrength}
|
||||||
|
onChange={(v) => {
|
||||||
|
dispatch(setSeamStrength(v));
|
||||||
|
}}
|
||||||
|
withInput
|
||||||
|
withSliderMarks
|
||||||
|
withReset
|
||||||
|
handleReset={() => {
|
||||||
|
dispatch(setSeamStrength(0.7));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
@ -36,9 +36,9 @@ export default function ImageToImageStrength(props: ImageToImageStrengthProps) {
|
|||||||
isInteger={false}
|
isInteger={false}
|
||||||
styleClass={styleClass}
|
styleClass={styleClass}
|
||||||
withInput
|
withInput
|
||||||
withReset
|
|
||||||
withSliderMarks
|
withSliderMarks
|
||||||
inputWidth={'5.5rem'}
|
inputWidth={'5.5rem'}
|
||||||
|
withReset
|
||||||
handleReset={handleImg2ImgStrengthReset}
|
handleReset={handleImg2ImgStrengthReset}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// import { Feature } from 'app/features';
|
// import { Feature } from 'app/features';
|
||||||
import { Feature } from 'app/features';
|
import { Feature } from 'app/features';
|
||||||
import ImageToImageStrength from 'features/options/components/AdvancedOptions/ImageToImage/ImageToImageStrength';
|
import ImageToImageStrength from 'features/options/components/AdvancedOptions/ImageToImage/ImageToImageStrength';
|
||||||
import SeamCorrectionOptions from 'features/options/components/AdvancedOptions/Canvas/SeamCorrectionOptions';
|
import SeamCorrectionOptions from 'features/options/components/AdvancedOptions/Canvas/SeamCorrectionOptions/SeamCorrectionOptions';
|
||||||
import SeedOptions from 'features/options/components/AdvancedOptions/Seed/SeedOptions';
|
import SeedOptions from 'features/options/components/AdvancedOptions/Seed/SeedOptions';
|
||||||
import GenerateVariationsToggle from 'features/options/components/AdvancedOptions/Variations/GenerateVariations';
|
import GenerateVariationsToggle from 'features/options/components/AdvancedOptions/Variations/GenerateVariations';
|
||||||
import VariationsOptions from 'features/options/components/AdvancedOptions/Variations/VariationsOptions';
|
import VariationsOptions from 'features/options/components/AdvancedOptions/Variations/VariationsOptions';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user