Merge branch 'feature/mvp' of https://github.com/storytold/storyteller-frontend into feature/mvp

This commit is contained in:
Victor committed 2024-01-10 23:14:39 -08:00
commit c91512e046
7 files changed
+423 -189

No files matched your search

+1
View File
@@ -70,6 +70,7 @@
"react-share": "^4.4.1",
"react-twitch-embed": "^3.0.1",
"react-wavesurfer.js": "^0.0.8",
"react-range-slider-input": "^3.0.7",
"sass": "^1.57.1",
"typescript": "^3.7.5",
"universal-cookie": "^6.1.1",
@@ -1,8 +1,9 @@
@import "scss/colours.scss";
.fy-number-slider {
display: flex;
gap: 2rem;
gap: 0.5rem;
align-items: center;
margin-bottom: .75rem;
.fy-number-slider-range {
flex-grow: 1;
@@ -13,28 +14,29 @@
width: fit-content;
padding: 6px;
border-radius: 8px;
background-color: #2f2f42;
border-width: 1px;
border-color: rgba(#fff, 0.12);
background-color: $secondary;
border-width: 0px;
border-color: none;
color: rgba(#fff, 0.85);
font-weight: 500;
flex-shrink: 0;
}
.fy-number-slider-track {
height: .5rem;
width: 100%;
margin: 0 0 0 .6875rem; // margin half width of thumb, so that thumb does not overlap margins at minimum position
height: 6px;
margin: 0 0 0 0.6875rem; // margin half width of thumb, so that thumb does not overlap margins at minimum position
background-color: #4f4f66;
border-radius: .25rem;
border-radius: 0.25rem;
}
.fy-number-slider-thumb {
height: 1.375rem;
width: 1.375rem;
height: 16px;
width: 16px;
background-color: #e66462;
border-radius: 50%;
box-shadow: 0px 0px 10px rgba(#000, 0.15);
&:hover { background-color: #fff }
&:hover {
background-color: #fff;
}
}
}
}
@@ -1,4 +1,4 @@
import React from 'react';
import React from "react";
import { Range } from "react-range";
import Tippy from "@tippyjs/react";
import { Label } from "components/common";
@@ -6,38 +6,87 @@ import "./NumberSlider.scss";
interface Props {
label?: string;
max?: number,
min?: number,
name?: string,
onChange?: any,
required?: boolean,
step?: number,
thumbTip?: string,
value?: number
max?: number;
min?: number;
name?: string;
onChange?: any;
required?: boolean;
step?: number;
thumbTip?: string;
value?: number;
}
const renderTrack = ({ props: { style, ...props }, children }: any) =>
const renderTrack = ({ props: { style, ...props }, children }: any) => (
<div {...{ ...props, className: "fy-number-slider-track", style }}>
{ children }
</div>;
{children}
</div>
);
const thumb = (thumbTip = "") => ({ props: { style, ...props }}: any) => {
return <Tippy {...{ arrow: false, content: thumbTip, placement: "bottom", theme: "range-slider" }} >
<div {...{ ...props, className: "fy-number-slider-thumb", style }}></div>
</Tippy>
};
const thumb =
(thumbTip = "") =>
({ props: { style, ...props } }: any) => {
return (
<Tippy
{...{
arrow: false,
content: thumbTip,
placement: "bottom",
theme: "range-slider",
}}
>
<div
{...{ ...props, className: "fy-number-slider-thumb", style }}
></div>
</Tippy>
);
};
export default function NumberSlider({ label, max, min, name, onChange: inChange = () => {}, required, step = 1, thumbTip, value = 0 }: Props) {
export default function NumberSlider({
label,
max,
min,
name,
onChange: inChange = () => {},
required,
step = 1,
thumbTip,
value = 0,
}: Props) {
const onChange = (newVal: number[]) =>
inChange({
target: { ...(name && { name }), type: "number", value: newVal[0] },
});
const onChange = (newVal: number[]) => inChange({ target: { ...name && { name }, type: "number", value: newVal[0] }});
return <>
<Label {...{ label, required }}/>
<div {...{ className: `fy-number-slider` }}>
<div {...{ className: "fy-number-slider-range" }}>
<Range {...{ max, min, onChange, renderThumb: thumb(thumbTip), renderTrack, step, thumbTip, values: [value] }}/>
return (
<div>
<Label {...{ label, required }} />
<div {...{ className: `fy-number-slider` }}>
<input
{...{
className: "fy-number-slider-value",
min,
max,
name,
onChange: inChange,
type: "number",
value,
}}
/>
<div {...{ className: "fy-number-slider-range" }}>
<Range
{...{
max,
min,
onChange,
renderThumb: thumb(thumbTip),
renderTrack,
step,
thumbTip,
values: [value],
}}
/>
</div>
</div>
<input {...{ className: "fy-number-slider-value", min, max, name, onChange: inChange, type: "number", value }}/>
</div>
</>;
};
);
}
@@ -1,31 +1,55 @@
@import "scss/colours.scss";
.fy-segment-buttons {
display: grid;
grid-auto-flow: column;
grid-auto-columns: 1fr;
gap: 2px;
padding: 0;
display: grid;
grid-auto-flow: column;
grid-auto-columns: 1fr;
gap: 1px;
padding: 0;
li {
background-color: $secondary;
border-radius: .125rem;
cursor: pointer;
display: inline-flex;
flex: 1;
white-space: nowrap;
justify-content: center;
align-items: center;
height: 3rem;
padding: 0 .75rem;
transition: .25s background-color ease-in-out;
li {
background-color: $secondary;
border-radius: 0.125rem;
cursor: pointer;
display: inline-flex;
flex: 1;
flex-direction: column;
white-space: nowrap;
justify-content: center;
align-items: center;
min-height: 3rem;
padding: 0.75rem;
transition: 0.1s background-color ease-in-out;
font-size: 14px;
&:hover { background-color: lighten($secondary, 5%) !important; }
&:first-of-type { border-radius: .5rem .125rem .125rem .5rem; }
&:last-of-type { border-radius: .125rem .5rem .5rem .125rem; }
&.fy-selected-segment {
background-color: $primary;
&:hover { background-color: lighten($primary, 5%) !important; }
}
}
}
&:hover {
background-color: lighten($secondary, 5%) !important;
}
&:first-of-type {
border-radius: 0.5rem 0.125rem 0.125rem 0.5rem;
}
&:last-of-type {
border-radius: 0.125rem 0.5rem 0.5rem 0.125rem;
}
&.fy-selected-segment {
background-color: lighten($secondary, 12%);
&:hover {
background-color: lighten($secondary, 12%) !important;
}
}
p {
font-size: 12px;
opacity: 0.8;
margin: 0;
padding: 0;
}
.fy-segment-button-icon {
font-size: 24px;
margin-bottom: 0.5rem;
color: lighten($secondary, 60%);
}
}
}
@@ -1,25 +1,58 @@
import React from 'react';
import { Label } from "components/common";
import React from "react";
import { Label } from "components/common";
import "./SegmentButtons.scss";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { IconDefinition, fa0 } from "@fortawesome/pro-solid-svg-icons";
interface Props {
label?: string;
subLabel?: string;
name?: string;
onChange?: any;
options?: any;
value?: string | number;
icon?: IconDefinition | undefined;
}
export default function SegmentButtons({ label, name, onChange, options = [], value: inValue = "" }: Props) {
export default function SegmentButtons({
label,
subLabel,
name,
icon,
onChange,
options = [],
value: inValue = "",
}: Props) {
// const onClick = ({ target }: any) => onChange();
return <>
<Label {...{ label }}/>
<ul {...{ className: "fy-segment-buttons" }}>
{ options.map(({ label = "", value = "" },key: number) => <li {...{
...value === inValue && { className: "fy-selected-segment" },
key,
onClick: ({ target }: any) => onChange({ target: { name, type: "option", value } })
}}>{ label }</li>) }
</ul>
</>;
};
return (
<div>
<Label {...{ label }} />
<ul {...{ className: "fy-segment-buttons mb-0" }}>
{options.map(
(
{ label = "", value = "", icon = fa0, subLabel = "" },
key: number
) => (
<li
{...{
...(value === inValue && { className: "fy-selected-segment" }),
key,
onClick: ({ target }: any) =>
onChange({ target: { name, type: "option", value } }),
}}
>
{icon === fa0 ? null : (
<FontAwesomeIcon
icon={icon}
className="fy-segment-button-icon"
/>
)}
{label}
{subLabel && <p>{subLabel}</p>}
</li>
)
)}
</ul>
</div>
);
}
@@ -1,142 +1,249 @@
import React, { useState } from "react";
import { Button, NumberSlider, Panel, SegmentButtons, TempSelect, TempTextArea } from "components/common";
import { useChanger } from 'hooks';
import { onChanger } from 'resources';
import {
Button,
NumberSlider,
Panel,
SegmentButtons,
TempSelect,
TempTextArea,
} from "components/common";
// import { useChanger } from "hooks";
import { onChanger } from "resources";
import Accordion from "components/common/Accordion";
import {
faRectangleLandscape,
faRectanglePortrait,
faSquare,
} from "@fortawesome/pro-solid-svg-icons";
interface SdInferencePanelProps {}
export default function SdInferencePanel(props: SdInferencePanelProps) {
const [seed, seedSet] = useState(5);
const [sampler, samplerSet] = useState("DPM++");
const [width, widthSet] = useState(256);
const [height, heightSet] = useState(256);
const [cfgScale, cfgScaleSet] = useState(1);
const [sampler, samplerSet] = useState("DPM++ 2M Karras");
const [aspectRatio, aspectRatioSet] = useState("square");
const [cfgScale, cfgScaleSet] = useState(7);
const [loRAPath, loRAPathSet] = useState(1);
const [checkPoint, checkPointSet] = useState(1);
// const [checkPoint, checkPointSet] = useState(1);
const [batchSize, batchSizeSet] = useState(1);
const [batchCount, batchCountSet] = useState(1);
const onChange = onChanger({ batchCountSet, batchSizeSet, cfgScaleSet, checkPointSet, heightSet, loRAPathSet, samplerSet, seedSet, widthSet });
const [prompt, setPrompt] = useState("");
const [negativePrompt, setNegativePrompt] = useState("");
const onChange = onChanger({
batchCountSet,
batchSizeSet,
cfgScaleSet,
// checkPointSet,
loRAPathSet,
samplerSet,
seedSet,
aspectRatioSet,
setPrompt,
setNegativePrompt,
});
const samplerOpts = [
{ label: "DPM++", value: "DPM++" },
{ label: "2M", value: "2M" },
{ label: "karras", value: "karras" },
{ label: "DPM++ 2M Karras", value: "DPM++ 2M Karras" },
{ label: "DPM++ SDE Karras", value: "DPM++ SDE Karras" },
{ label: "DPM++ 2M SDE Exponential", value: "DPM++ 2M SDE Exponential" },
{ label: "DPM++ 2M SDE Karras", value: "DPM++ 2M SDE Karras" },
{ label: "Euler a", value: "Euler a" },
{ label: "Euler", value: "Euler" },
{ label: "LMS", value: "LMS" },
{ label: "Heun", value: "Heun" },
{ label: "DPM2", value: "DPM2" },
{ label: "DPM2 a", value: "DPM2 a" },
{ label: "DPM++ 2S a", value: "DPM++ 2S a" },
{ label: "DPM++ 2M", value: "DPM++ 2M" },
{ label: "DPM++ SDE", value: "DPM++ SDE" },
{ label: "DPM++ 2M SDE", value: "DPM++ 2M SDE" },
{ label: "DPM++ 2M SDE Heun", value: "DPM++ 2M SDE Heun" },
{ label: "DPM++ 2M SDE Heun Karras", value: "DPM++ 2M SDE Heun Karras" },
{
label: "DPM++ 2M SDE Heun Exponential",
value: "DPM++ 2M SDE Heun Exponential",
},
{ label: "DPM++ 3M SDE", value: "DPM++ 3M SDE" },
{ label: "DPM++ 3M SDE Karras", value: "DPM++ 3M SDE Karras" },
{ label: "DPM++ 3M SDE Exponential", value: "DPM++ 3M SDE Exponential" },
{ label: "DPM fast", value: "DPM fast" },
{ label: "DPM adaptive", value: "DPM adaptive" },
{ label: "LMS Karras", value: "LMS Karras" },
{ label: "DPM2 Karras", value: "DPM2 Karras" },
{ label: "DPM2 a Karras", value: "DPM2 a Karras" },
{ label: "DPM++ 2S a Karras", value: "DPM++ 2S a Karras" },
];
const dimensionOpts = [
{ label: "256", value: 256 },
{ label: "512", value: 512 },
{ label: "1024", value: 1024 }
{ label: "Square", value: "square", icon: faSquare, subLabel: "512x512" },
{
label: "Landscape",
value: "landscape",
icon: faRectangleLandscape,
subLabel: "768x512",
},
{
label: "Portrait",
value: "portrait",
icon: faRectanglePortrait,
subLabel: "512x768",
},
];
const tempDeleteMeOpts = [
{ label: "Something", value: 1 },
{ label: "Something else", value: 2 },
{ label: "Another thing", value: 3 }
{ label: "Another thing", value: 3 },
];
const batchSizeOpts = [
{ label: "1", value: 1 },
{ label: "2", value: 2 },
{ label: "3", value: 3 },
{ label: "4", value: 4 }
{ label: "4", value: 4 },
];
const batchCountOpts = [
{ label: "1", value: 1 },
{ label: "2", value: 2 }
{ label: "2", value: 2 },
];
// console.log("🚨",Math.pow(2,32));
const handlePromptChange = (
event: React.ChangeEvent<HTMLTextAreaElement>
) => {
setPrompt(event.target.value);
};
const { setProps } = useChanger({
prompt: useState("")
});
const handleNegativePromptChange = (
event: React.ChangeEvent<HTMLTextAreaElement>
) => {
setNegativePrompt(event.target.value);
};
return <Panel padding={true}>
<TempTextArea {...{
label: "Prompt",
placeholder: "Enter a prompt",
...setProps("prompt")
}}/>
<TempTextArea {...{
label: "Negative prompt",
name: "negativePrompt",
placeholder: "Enter a negative prompt"
}}/>
<NumberSlider {...{
min: 5,
max: 128,
name: "seed",
label: "Seed value",
onChange,
thumbTip: "Seed value",
value: seed
}}/>
<TempSelect {...{
label: "Sampler",
name: "sampler",
onChange,
options: samplerOpts,
value: sampler
}}/>
<SegmentButtons {...{
label: "Width",
name: "width",
onChange,
options: dimensionOpts,
value: width
}}/>
<SegmentButtons {...{
label: "Height",
name: "height",
onChange,
options: dimensionOpts,
value: height
}}/>
<NumberSlider {...{
min: 1,
max: 64,
name: "cfgScale",
label: "Cfg sscale",
onChange,
thumbTip: "Cfg sscale",
value: cfgScale
}}/>
<TempSelect {...{
label: "loRA path",
name: "loraPath",
onChange,
options: tempDeleteMeOpts,
value: loRAPath
}}/>
<TempSelect {...{
label: "Check point",
name: "checkPoint",
onChange,
options: tempDeleteMeOpts,
value: checkPoint
}}/>
<SegmentButtons {...{
label: "Batch size",
name: "batchSize",
onChange,
options: batchSizeOpts,
value: batchSize
}}/>
<SegmentButtons {...{
label: "Batch count",
name: "batchCount",
onChange,
options: batchCountOpts,
value: batchCount
}}/>
<div className="d-flex gap-3 justify-content-end">
<Button {...{
label: "Enqueue"
}} />
</div>
</Panel>;
return (
<Panel padding={true}>
<h4 className="fw-semibold mb-4">Generate an Image</h4>
<div className="d-flex flex-column gap-3 mb-4">
<TempTextArea
{...{
label: "Prompt",
placeholder: "Enter a prompt",
onChange: handlePromptChange,
value: prompt,
required: true,
}}
/>
<TempTextArea
{...{
label: "Negative prompt",
name: "negativePrompt",
placeholder: "Enter a negative prompt",
onChange: handleNegativePromptChange,
value: negativePrompt,
}}
/>
<SegmentButtons
{...{
label: "Aspect Ratio",
name: "aspectRatio",
onChange,
options: dimensionOpts,
value: aspectRatio,
}}
/>
</div>
<Accordion>
<Accordion.Item title="Advanced">
<div className="p-3 d-flex flex-column gap-3">
<NumberSlider
{...{
min: 5,
max: 128,
name: "seed",
label: "Seed value",
onChange,
thumbTip: "Seed value",
value: seed,
}}
/>
<TempSelect
{...{
label: "Sampler",
name: "sampler",
onChange,
options: samplerOpts,
value: sampler,
}}
/>
<NumberSlider
{...{
min: 1,
max: 30,
name: "cfgScale",
label: "CFG Scale",
onChange,
thumbTip: "CFG Scale",
value: cfgScale,
}}
/>
<TempSelect
{...{
label: "loRA path",
name: "loraPath",
onChange,
options: tempDeleteMeOpts,
value: loRAPath,
}}
/>
{/* Checkpoint Use weight token */}
{/* <TempSelect
{...{
label: "Checkpoint",
name: "checkPoint",
onChange,
options: tempDeleteMeOpts,
value: checkPoint,
}}
/> */}
<SegmentButtons
{...{
label: "Batch size",
name: "batchSize",
onChange,
options: batchSizeOpts,
value: batchSize,
}}
/>
<SegmentButtons
{...{
label: "Batch count",
name: "batchCount",
onChange,
options: batchCountOpts,
value: batchCount,
}}
/>
</div>
</Accordion.Item>
</Accordion>
<div className="d-flex gap-2 justify-content-end mt-4">
<Button
{...{
label: "Clear All",
variant: "secondary",
}}
/>
<Button
{...{
label: "Generate Image",
disabled: prompt === "",
}}
/>
</div>
</Panel>
);
}
+18
View File
@@ -4591,6 +4591,7 @@ __metadata:
moment: ^2.29.4
prettier: ^3.1.0
pretty-quick: ^3.1.3
react-range-slider-input: ^3.0.7
universal-cookie: ^6.1.1
yarn: ^1.22.19
languageName: unknown
@@ -8590,6 +8591,13 @@ __metadata:
languageName: node
linkType: hard
"core-js@npm:^3.22.4":
version: 3.35.0
resolution: "core-js@npm:3.35.0"
checksum: 25c224aca3df012b98f08f13ccbd8171ef5852acd33fd5e58e106d27f5f0c97de2fdbc520f0b4364d26253caf2deb3e5d265310f57d2a66ae6cc922850e649f0
languageName: node
linkType: hard
"core-util-is@npm:1.0.2":
version: 1.0.2
resolution: "core-util-is@npm:1.0.2"
@@ -17878,6 +17886,16 @@ __metadata:
languageName: node
linkType: hard
"react-range-slider-input@npm:^3.0.7":
version: 3.0.7
resolution: "react-range-slider-input@npm:3.0.7"
dependencies:
clsx: ^1.1.1
core-js: ^3.22.4
checksum: e304c950e1bd9a3140ae14519522221614d7000a30b8dea112e856fd267264305210cb6d6ffa73179a52f770e852b011d8534127dab44684307e673272cfecf7
languageName: node
linkType: hard
"react-range@npm:^1.8.14":
version: 1.8.14
resolution: "react-range@npm:1.8.14"