working positive and negative prompts

This commit is contained in:
caranicas 2022-10-02 18:18:35 -04:00
parent 84b291a57a
commit 2607ef5fe0
30 changed files with 602 additions and 205 deletions

View File

@ -60,6 +60,7 @@ export const toggleBetaConfig = async (branch: string) => {
export interface ImageRequest { export interface ImageRequest {
session_id: string; session_id: string;
prompt: string; prompt: string;
negative_prompt: string;
seed: number; seed: number;
num_outputs: number; num_outputs: number;
num_inference_steps: number; num_inference_steps: number;

View File

@ -47,9 +47,9 @@ export const buttonStyle = recipe({
}, },
accent: { accent: {
// @ts-expect-error // @ts-expect-error
'--button-hue': vars.backgroundAccentMain, '--button-hue': vars.backgroundAccentHue,
'--button-base-saturation': vars.colorMod.saturation.normal, '--button-base-saturation': vars.backgroundAccentSaturation,
'--button-base-lightness': vars.colorMod.lightness.normal, '--button-base-lightness': vars.backgroundAccentLightness,
}, },
clear: { clear: {
backgroundColor: "transparent", backgroundColor: "transparent",
@ -58,8 +58,8 @@ export const buttonStyle = recipe({
type: { type: {
fill: { fill: {
backgroundColor: `hsl(var(--button-hue),${vars.colorMod.saturation.normal},${vars.colorMod.lightness.normal})`, backgroundColor: `hsl(var(--button-hue),var(--button-base-saturation),${vars.colorMod.lightness.normal})`,
border: `1px solid hsl(var(--button-hue),${vars.colorMod.saturation.normal},${vars.colorMod.lightness.normal})`, border: `1px solid hsl(var(--button-hue),var(--button-base-saturation),${vars.colorMod.lightness.normal})`,
":hover": { ":hover": {
backgroundColor: `hsl(var(--button-hue),${vars.colorMod.saturation.bright},${vars.colorMod.lightness.normal})`, backgroundColor: `hsl(var(--button-hue),${vars.colorMod.saturation.bright},${vars.colorMod.lightness.normal})`,
border: `1px solid hsl(var(--button-hue),${vars.colorMod.saturation.bright},${vars.colorMod.lightness.normal})`, border: `1px solid hsl(var(--button-hue),${vars.colorMod.saturation.bright},${vars.colorMod.lightness.normal})`,
@ -81,7 +81,7 @@ export const buttonStyle = recipe({
}, },
outline: { outline: {
backgroundColor: "transparent", backgroundColor: "transparent",
border: `1px solid hsl(var(--button-hue),${vars.colorMod.saturation.normal},${vars.colorMod.lightness.normal})`, border: `1px solid hsl(var(--button-hue),var(--button-base-saturation),${vars.colorMod.lightness.normal})`,
":hover": { ":hover": {
borderColor: `hsl(var(--button-hue),${vars.colorMod.saturation.bright},${vars.colorMod.lightness.normal})`, borderColor: `hsl(var(--button-hue),${vars.colorMod.saturation.bright},${vars.colorMod.lightness.normal})`,
}, },
@ -100,7 +100,7 @@ export const buttonStyle = recipe({
}, },
action: { action: {
backgroundColor: "transparent", backgroundColor: "transparent",
color: `hsl(var(--button-hue),${vars.colorMod.saturation.normal},${vars.colorMod.lightness.normal})`, color: `hsl(var(--button-hue),var(--button-base-saturation),${vars.colorMod.lightness.normal})`,
textDecoration: "underline", textDecoration: "underline",
":hover": { ":hover": {
color: `hsl(var(--button-hue),${vars.colorMod.saturation.bright},${vars.colorMod.lightness.normal})`, color: `hsl(var(--button-hue),${vars.colorMod.saturation.bright},${vars.colorMod.lightness.normal})`,
@ -121,6 +121,10 @@ export const buttonStyle = recipe({
}, },
size: { size: {
slim: {
padding: vars.spacing.min,
fontSize: vars.fonts.sizes.Caption,
},
large: { large: {
width: "100%", width: "100%",
fontSize: vars.fonts.sizes.Headline, fontSize: vars.fonts.sizes.Headline,

View File

@ -20,6 +20,7 @@ export const card = recipe({
background: vars.backgroundDark, background: vars.backgroundDark,
}, },
}, },
rounded: { rounded: {
true: { true: {
borderRadius: vars.trim.smallBorderRadius, borderRadius: vars.trim.smallBorderRadius,

View File

@ -250,7 +250,6 @@ export default function MakeButton() {
return; return;
} }
debugger;
makeImages(options).catch((e) => { makeImages(options).catch((e) => {
console.log('HAS QUEUE ERROR'); console.log('HAS QUEUE ERROR');
console.log(e); console.log(e);

View File

@ -1,4 +1,5 @@
import React from "react"; import React, { useState } from "react";
import { v4 as uuidv4 } from "uuid";
import { import {
ModifierPreview, ModifierPreview,
useImageCreate useImageCreate
@ -6,9 +7,16 @@ import {
import { API_URL } from "../../../api"; import { API_URL } from "../../../api";
import {
IconFont,
} from "../../../styles/shared.css";
import { import {
ModifierTagMain, ModifierTagMain,
tagPreview ModifierActions,
tagPreview,
TagText,
TagToggle,
} from "./modifierTags.css"; } from "./modifierTags.css";
interface ModifierTagProps { interface ModifierTagProps {
@ -21,6 +29,25 @@ export default function ModifierTag({ name, category, previews }: ModifierTagPro
const previewType: 'portrait' | 'landscape' = "portrait"; const previewType: 'portrait' | 'landscape' = "portrait";
const [showActions, setShowActions] = useState(false);
const handleHover = () => {
setShowActions(true);
};
const handleLeave = () => {
setShowActions(false);
};
const addCreateTag = useImageCreate((state) => state.addCreateTag);
const setPositivePrompt = () => {
addCreateTag({ id: uuidv4(), name, type: 'positive' });
}
const setNegativePrompt = () => {
addCreateTag({ id: uuidv4(), name, type: 'negative' });
}
const hasTag = useImageCreate((state) => state.hasTag(category, name)) const hasTag = useImageCreate((state) => state.hasTag(category, name))
? "selected" ? "selected"
: ""; : "";
@ -30,10 +57,23 @@ export default function ModifierTag({ name, category, previews }: ModifierTagPro
toggleTag(category, name); toggleTag(category, name);
}; };
// , hasTag].join(" ")
return ( return (
<div className={[ModifierTagMain, hasTag].join(" ")} onClick={_toggleTag}> <div className={ModifierTagMain}
<p>{name}</p> onMouseEnter={handleHover}
<div className={tagPreview}> onMouseLeave={handleLeave}>
<p className={!showActions ? TagText : TagToggle}>{name}</p>
{showActions && (
<div className={ModifierActions}>
<button onClick={setPositivePrompt}>
<i className={[IconFont, 'fa-solid', 'fa-plus'].join(" ")}></i>
</button>
<button onClick={setNegativePrompt}>
<i className={[IconFont, 'fa-solid', 'fa-minus'].join(" ")}></i>
</button>
</div>
)}
{/* <div className={tagPreview}>
{previews.map((preview) => { {previews.map((preview) => {
if (preview.name !== previewType) { if (preview.name !== previewType) {
return null; return null;
@ -47,7 +87,7 @@ export default function ModifierTag({ name, category, previews }: ModifierTagPro
/> />
); );
})} })}
</div> </div> */}
</div> </div>
); );
} }

View File

@ -1,22 +1,20 @@
import { style, globalStyle } from "@vanilla-extract/css"; import { style, globalStyle } from "@vanilla-extract/css";
import { vars } from '../../../styles/theme/index.css';
// .modifierTag.selected { import { card } from '../../_recipes/card.css';
// background-color: rgb(131, 11, 121);
// }
export const ModifierTagMain = style([
export const ModifierTagMain = style({ card({
display: "inline-block", backing: 'normal',
padding: "6px", level: 1,
backgroundColor: "rgb(38, 77, 141)", info: true
color: "#fff", }), {
borderRadius: "5px", position: "relative",
margin: "5px", width: "fit-content",
}); borderColor: `hsl(${vars.brandHue}, ${vars.colorMod.saturation.normal}, ${vars.colorMod.lightness.normal})`,
padding: vars.spacing.small,
// export const ModifierTagSelected = style({ }
// backgroundColor: "rgb(131, 11, 121)", ]);
// });
globalStyle(`${ModifierTagMain}.selected`, { globalStyle(`${ModifierTagMain}.selected`, {
backgroundColor: "rgb(131, 11, 121)", backgroundColor: "rgb(131, 11, 121)",
@ -29,6 +27,34 @@ globalStyle(`${ModifierTagMain} p`, {
}); });
export const TagText = style({
opacity: 1,
});
export const TagToggle = style({
opacity: 0.3,
});
export const ModifierActions = style({
position: "absolute",
top: "0",
left: "0",
height: "100%",
width: "100%",
display: "flex",
flexDirection: "row",
});
globalStyle(`${ModifierActions} button`, {
flexGrow: 1,
backgroundColor: "transparent",
border: "none",
boxShadow: `inset 0 0 24px 0px rgb(255 255 255 / 50%)`,
borderRadius: "5px",
padding: "0",
});
export const tagPreview = style({ export const tagPreview = style({
display: 'flex', display: 'flex',
justifyContent: 'center', justifyContent: 'center',

View File

@ -0,0 +1,68 @@
import React, { useState } from "react";
import { useImageCreate } from "../../../stores/imageCreateStore";
import {
IconFont,
} from "../../../styles/shared.css";
import {
PromptTagMain,
TagToggle,
TagRemoveButton,
PromptTagText,
PromptTagToggle
} from "./promptTag.css";
interface PromptTagProps {
id: string;
name: string;
category?: string;
previews?: string[];
type: string;
};
export default function PromptTag({ id, name, category, previews, type }: PromptTagProps) {
const [showToggle, setShowToggle] = useState(false);
const removeCreateTag = useImageCreate((state) => state.removeCreateTag);
const changeCreateTagType = useImageCreate((state) => state.changeCreateTagType);
const handleHover = () => {
setShowToggle(true);
};
const handleLeave = () => {
setShowToggle(false);
};
const toggleType = () => {
if (type === 'positive') {
changeCreateTagType(id, 'negative');
}
else {
changeCreateTagType(id, 'positive');
}
};
const handleRemove = () => {
console.log('remove');
removeCreateTag(id);
};
return (
<div
onMouseEnter={handleHover}
onMouseLeave={handleLeave}
className={[PromptTagMain, type].join(' ')}>
<p className={!showToggle ? PromptTagText : PromptTagToggle}>{name}</p>
{showToggle && <button className={TagToggle} onClick={toggleType}>
{type === 'positive' ? <i className={[IconFont, 'fa-solid', 'fa-minus'].join(" ")}></i> : <i className={[IconFont, 'fa-solid', 'fa-plus'].join(" ")}></i>}
</button>}
{showToggle && <button className={TagRemoveButton} onClick={handleRemove}>
<i className={[IconFont, 'fa-solid', 'fa-close'].join(" ")}></i>
</button>}
</div>
);
};

View File

@ -0,0 +1,55 @@
/* eslint-disable @typescript-eslint/restrict-template-expressions */
import { style, globalStyle } from '@vanilla-extract/css';
import { XButton } from "../../../styles/shared.css";
import { vars } from '../../../styles/theme/index.css';
import { card } from '../../_recipes/card.css';
export const PromptTagMain = style([
card({
backing: 'normal',
level: 1,
info: true
}), {
position: "relative",
width: "fit-content",
backgroundColor: `hsl(${vars.backgroundLight}, ${vars.colorMod.saturation.normal}, ${vars.colorMod.lightness.normal})`,
padding: vars.spacing.small,
}
]);
export const PromptTagText = style({
opacity: 1,
fontSize: vars.fonts.sizes.Plain,
});
export const PromptTagToggle = style({
opacity: 0.3,
fontSize: vars.fonts.sizes.Plain,
});
globalStyle(`${PromptTagMain}.positive`, {
borderColor: `hsl(${vars.brandHue}, ${vars.colorMod.saturation.normal}, ${vars.colorMod.lightness.normal})`,
});
globalStyle(`${PromptTagMain}.negative`, {
borderColor: `hsl(${vars.errorHue}, ${vars.colorMod.saturation.normal}, ${vars.colorMod.lightness.normal})`,
});
export const TagToggle = style({
position: "absolute",
top: "0",
right: "0",
height: "100%",
width: "100%",
border: "none",
backgroundColor: "transparent",
boxShadow: `inset 0 0 24px 0px rgb(255 255 255 / 50%)`,
});
export const TagRemoveButton = style([XButton, {
top: '-4px',
left: '4px',
padding: '0',
}]);

View File

@ -8,5 +8,5 @@ export const AdvancedSettingsList = style({
}); });
export const AdvancedSettingGrouping = style({ export const AdvancedSettingGrouping = style({
marginTop: vars.spacing.medium, marginTop: vars.spacing.small,
}); });

View File

@ -66,7 +66,7 @@ export default function ImprovementSettings() {
})} })}
onClick={toggleImprovementOpen} onClick={toggleImprovementOpen}
> >
<h4>Improvement Settings</h4> Improvement Settings
</button> </button>
{improvementOpen && ( {improvementOpen && (
<> <>

View File

@ -79,7 +79,7 @@ export default function PropertySettings() {
type: 'action', type: 'action',
color: 'accent', color: 'accent',
})} onClick={togglePropertyOpen}> })} onClick={togglePropertyOpen}>
<h4>Property Settings</h4> Property Settings
</button> </button>
{propertyOpen && ( {propertyOpen && (
<> <>

View File

@ -36,7 +36,7 @@ export default function WorkflowSettings() {
type: 'action', type: 'action',
color: 'accent', color: 'accent',
})} onClick={toggleWorkflowOpen}> })} onClick={toggleWorkflowOpen}>
<h4>Workflow Settings</h4> Workflow Settings
</button> </button>
{workflowOpen && ( {workflowOpen && (
<> <>

View File

@ -1,22 +0,0 @@
import React from "react";
import { useImageCreate } from "../../../../../stores/imageCreateStore";
import ModifierTag from "../../../../molecules/modifierTag";
export default function ActiveTags() {
const selectedtags = useImageCreate((state) => state.selectedTags());
return (
<div className="selected-tags">
<p>Active Tags</p>
<ul>
{selectedtags.map((tag) => (
<li key={tag.modifier}>
{/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */}
<ModifierTag category={tag.category!} name={tag.modifier} previews={tag.previews} />
</li>
))}
</ul>
</div>
);
}

View File

@ -13,20 +13,8 @@ export const CreationBasicMain = style([
}] }]
); );
globalStyle(`${CreationBasicMain} > *`, {
marginBottom: "10px",
});
export const PromptDisplay = style({}); export const PromptDisplay = style({});
globalStyle(`${PromptDisplay} > p`, { globalStyle(`${CreationBasicMain} > *`, {
fontSize: "1.5em", marginBottom: '10px'
fontWeight: "bold",
marginBottom: "10px",
});
globalStyle(`${PromptDisplay} > textarea`, {
width: "100%",
resize: "vertical",
height: "100px",
}); });

View File

@ -1,13 +0,0 @@
import { style, globalStyle } from "@vanilla-extract/css";
import { vars } from "../../../../../styles/theme/index.css";
export const CreationActionMain = style({
display: "flex",
flexDirection: "column",
width: "100%",
marginTop: vars.spacing.medium,
});
globalStyle(`${CreationActionMain} button`, {
marginBottom: vars.spacing.medium,
});

View File

@ -1,18 +0,0 @@
import React from "react";
import MakeButton from "../../../../molecules/makeButton";
import ShowQueue from "../showQueue";
import {
CreationActionMain
} from "./creationActions.css";
export default function CreationActions() {
return (
<div className={CreationActionMain}>
<MakeButton></MakeButton>
{/* <ShowQueue></ShowQueue> */}
</div>
);
}

View File

@ -6,13 +6,12 @@ import {
PromptDisplay, PromptDisplay,
} from "./basicCreation.css"; } from "./basicCreation.css";
// import MakeButton from "./makeButton"; import MakeButton from "../../../molecules/makeButton";
// import StopButton from "./stopButton";
// import ClearQueue from "./clearQueue";
import CreationActions from "./creationActions";
import SeedImage from "./seedImage";
import ActiveTags from "./activeTags";
import PromptCreator from "./promptCreator";
// import CreationActions from "./creationActions";
import SeedImage from "./seedImage";
import ActiveTags from "./promptCreator/activeTags";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@ -30,15 +29,9 @@ export default function BasicCreation() {
return ( return (
<div className={CreationBasicMain}> <div className={CreationBasicMain}>
<div className={PromptDisplay}> <MakeButton></MakeButton>
<p>{t("home.editor-title")}</p> <PromptCreator></PromptCreator>
<textarea value={promptText} onChange={handlePromptChange}></textarea>
</div>
<CreationActions></CreationActions>
<SeedImage></SeedImage> <SeedImage></SeedImage>
<ActiveTags></ActiveTags>
</div> </div>
); );
} }

View File

@ -0,0 +1,18 @@
import { style } from '@vanilla-extract/css';
import { vars } from '../../../../../../styles/theme/index.css';
export const ActiveTagListMain = style({
display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
gap: '10px',
width: '100%',
height: '100%',
overflow: 'visible',
scrollbarWidth: 'none',
msOverflowStyle: 'none',
'::-webkit-scrollbar': {
display: 'none',
},
});

View File

@ -0,0 +1,39 @@
import React from "react";
import { useImageCreate } from "../../../../../../stores/imageCreateStore";
import ModifierTag from "../../../../../molecules/modifierTag";
// import {
// card
// } from '../../../../../_recipes/card.css';
import PromptTag from "../../../../../molecules/promptTag";
import {
ActiveTagListMain
} from "./activeTags.css";
export default function ActiveTags() {
const selectedtags = useImageCreate((state) => state.selectedTags());
const createTags = useImageCreate((state) => state.createTags);
return (
<div>
<ul className={ActiveTagListMain}>
{createTags.map((tag) => {
console.log(tag);
return (
<li key={tag.id}>
{/* @ts-expect-error */}
<PromptTag id={tag.id} name={tag.name} category={tag?.category} previews={tag?.previews} type={tag.type} />
</li>)
}
)}
</ul>
</div>
);
}

View File

@ -0,0 +1,108 @@
import React, { useState, ChangeEvent, KeyboardEventHandler, Fragment } from "react";
import { v4 as uuidv4 } from "uuid";
import { Switch } from '@headlessui/react'
import { useImageCreate } from "../../../../../stores/imageCreateStore";
import ActiveTags from "./activeTags";
import {
IconFont,
} from "../../../../../styles/shared.css";
import {
buttonStyle,
} from "../../../../_recipes/button.css";
import {
PromptCreatorMain,
ToggleGroupMain,
ToggleMain,
ToggleLabel,
ToggleEnabled,
TogglePill,
buttonRow,
} from "./promptCreator.css";
import { useTranslation } from "react-i18next";
import { type } from "os";
interface TagTypeProps {
positive: boolean;
setPositive: (positive: boolean) => void;
};
function TagTypeToggle({ positive, setPositive }: TagTypeProps) {
return (
<Switch.Group as={Fragment}>
<div className={ToggleGroupMain}>
<Switch.Label> Type </Switch.Label>
<Switch className={ToggleMain} checked={positive} onChange={setPositive}>
<span
className={TogglePill}
>
{positive
? <i className={[IconFont, 'fa-solid', 'fa-plus'].join(" ")}></i>
: <i className={[IconFont, 'fa-solid', 'fa-minus'].join(" ")}></i>}
</span>
</Switch>
</div>
</Switch.Group>
);
}
export default function PromptCreator() {
const [positive, setPositive] = useState(true)
const [tagText, setTagText] = useState('An astronaut riding a horse');
const addCreateTag = useImageCreate((state) => state.addCreateTag);
const { t } = useTranslation();
const checkForEnter = (event: KeyboardEventHandler<HTMLInputElement>) => {
// @ts-expect-error
if (event.key === "Enter") {
if (tagText !== '') {
const type = positive ? "positive" : "negative";
tagText.split(',').map((tag) => tag.trim()).forEach((tag) => {
addCreateTag({ id: uuidv4(), name: tag, type });
});
//debugger;
setTagText('');
}
}
};
return (
<div className={PromptCreatorMain}>
<div>
<p>{t("home.editor-title")}</p>
{/* @ts-expect-error */}
<input value={tagText} onKeyDown={checkForEnter} onChange={(event) => {
setTagText(event.target.value)
}}></input>
</div>
<div className={buttonRow}>
<button
className={buttonStyle(
{
size: 'slim'
}
)}
onClick={() => {
}}
>
Add Prompt
</button>
<TagTypeToggle positive={positive} setPositive={setPositive}></TagTypeToggle>
</div>
<ActiveTags></ActiveTags>
</div >
);
}

View File

@ -0,0 +1,79 @@
import { style, globalStyle } from '@vanilla-extract/css';
import { vars } from "../../../../../styles/theme/index.css";
export const PromptCreatorMain = style({
display: 'flex',
flexDirection: 'column',
width: '100%',
height: '100%',
marginBottom: 0,
});
globalStyle(`${PromptCreatorMain} input`, {
width: '100%',
});
globalStyle(`${PromptCreatorMain} > div`, {
marginBottom: vars.spacing.small,
});
export const ToggleGroupMain = style({
// '--toggle-size': '30px',
});
export const ToggleMain = style({
background: vars.backgroundDark,
height: '22px',
borderRadius: '15px',
width: '34px',
border: 0,
position: 'relative',
display: 'inline-flex',
padding: 0,
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
boxShadow: `0 0 2px 0 ${vars.backgroundDark}`,
});
export const ToggleLabel = style({
});
export const ToggleEnabled = style({
});
globalStyle(`${ToggleMain}[data-headlessui-state="checked"]`, {
background: vars.backgroundLight,
});
export const TogglePill = style({
display: 'inline-flex',
height: '18px',
width: '30px',
borderRadius: '15px',
background: vars.backgroundDark,
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
});
globalStyle(`${ToggleMain}[data-headlessui-state="checked"] ${TogglePill}`, {
background: vars.backgroundAccentMain,
});
globalStyle(`${TogglePill} p`, {
color: vars.colors.text.normal,
});
export const buttonRow = style({
marginTop: vars.spacing.small,
display: 'flex',
flexDirection: 'row',
});
globalStyle(`${buttonRow} > button`, {
flexGrow: 1,
marginRight: vars.spacing.medium,
});

View File

@ -1,11 +1,14 @@
import React, { useRef, ChangeEvent } from "react"; import React, { useRef, ChangeEvent } from "react";
import { XButton } from "../../../../../styles/shared.css";
import { import {
ImageInputDisplay, ImageInputDisplay,
InputLabel, InputLabel,
ImageInput, ImageInput,
ImageFixer, ImageFixer,
XButton,
} from "./seedImage.css"; } from "./seedImage.css";
import { import {

View File

@ -21,21 +21,3 @@ export const ImageInput = style({
export const ImageFixer = style({ export const ImageFixer = style({
marginLeft: "20px", marginLeft: "20px",
}); });
// just a 1 off component for now
// dont bother bringing in line with the rest of the app
export const XButton = style({
position: "absolute",
transform: "translateX(-50%) translateY(-35%)",
background: "black",
color: "white",
border: "2pt solid #ccc",
padding: "0",
cursor: "pointer",
outline: "inherit",
borderRadius: "8pt",
width: "16pt",
height: "16pt",
fontFamily: "Verdana",
fontSize: "8pt",
});

View File

@ -15,12 +15,17 @@ export const ImageModifierGrouping = style({
marginTop: vars.spacing.medium, marginTop: vars.spacing.medium,
}); });
globalStyle(`${ImageModifierGrouping} h4`, {
fontSize: vars.fonts.sizes.Plain,
});
export const ModifierListStyle = style({ export const ModifierListStyle = style({
paddingLeft: 0, paddingLeft: 0,
listStyleType: "none", listStyleType: "none",
display: "flex", display: "flex",
flexWrap: "wrap", flexWrap: "wrap",
gap: vars.spacing.small,
}); });
globalStyle(`${ModifierListStyle} li`, { globalStyle(`${ModifierListStyle} li`, {

View File

@ -22,6 +22,7 @@ export default function ImageDisplay({ info, data }: CompletedImagesType) {
const createFileName = () => { const createFileName = () => {
const { const {
prompt, prompt,
negative_prompt,
seed, seed,
num_inference_steps, num_inference_steps,
guidance_scale, guidance_scale,
@ -74,6 +75,7 @@ export default function ImageDisplay({ info, data }: CompletedImagesType) {
<div className={imageDisplayContent}> <div className={imageDisplayContent}>
<div> <div>
<p> {info?.prompt}</p> <p> {info?.prompt}</p>
<p> {info?.negative_prompt}</p>
<div> <div>
<button className={buttonStyle( <button className={buttonStyle(

View File

@ -42,11 +42,20 @@ interface ModifiersList {
type ModifiersOptionList = ModifiersList[]; type ModifiersOptionList = ModifiersList[];
export interface promptTag {
id: string;
name: string;
type: 'positive' | 'negative';
}
interface ImageCreateState { interface ImageCreateState {
parallelCount: number; parallelCount: number;
requestOptions: ImageRequest; requestOptions: ImageRequest;
allModifiers: ModifiersOptionList; allModifiers: ModifiersOptionList;
tags: string[];
createTags: promptTag[];
// negativeTags: promptTag[];
tagMap: Record<string, string[]>; tagMap: Record<string, string[]>;
isInpainting: boolean; isInpainting: boolean;
@ -59,6 +68,11 @@ interface ImageCreateState {
toggleTag: (category: string, tag: string) => void; toggleTag: (category: string, tag: string) => void;
hasTag: (category: string, tag: string) => boolean; hasTag: (category: string, tag: string) => boolean;
selectedTags: () => ModifierObject[]; selectedTags: () => ModifierObject[];
addCreateTag: (tag: promptTag) => void;
removeCreateTag: (id: string) => void;
changeCreateTagType: (id: string, type: 'positive' | 'negative') => void;
reorderCreateTag: (tag: promptTag, index: number) => void;
builtRequest: () => ImageRequest; builtRequest: () => ImageRequest;
uiOptions: ImageCreationUiOptions; uiOptions: ImageCreationUiOptions;
@ -85,6 +99,7 @@ export const useImageCreate = create<ImageCreateState>(
requestOptions: { requestOptions: {
session_id: new Date().getTime().toString(), session_id: new Date().getTime().toString(),
prompt: "a photograph of an astronaut riding a horse", prompt: "a photograph of an astronaut riding a horse",
negative_prompt: "",
seed: useRandomSeed(), seed: useRandomSeed(),
num_outputs: 1, num_outputs: 1,
num_inference_steps: 50, num_inference_steps: 50,
@ -108,7 +123,8 @@ export const useImageCreate = create<ImageCreateState>(
}, },
// selected tags // selected tags
tags: [] as string[], createTags: [] as promptTag[],
// negativeTags: [] as promptTag[],
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
tagMap: {} as Record<string, string[]>, tagMap: {} as Record<string, string[]>,
@ -202,7 +218,48 @@ export const useImageCreate = create<ImageCreateState>(
return selected; return selected;
}, },
addCreateTag: (tag: promptTag) => {
set(
produce((state) => {
state.createTags.push(tag);
})
);
},
removeCreateTag: (id: string) => {
set(
produce((state) => {
// @ts-expect-error
state.createTags = state.createTags.filter((t) => t.id !== id);
})
);
},
changeCreateTagType: (id: string, type: 'positive' | 'negative') => {
set(
produce((state) => {
// @ts-expect-error
const tag = state.createTags.find((t) => t.id === id);
if (tag) {
tag.type = type;
}
})
);
},
reorderCreateTag: (tag: promptTag, index: number) => {
set(
produce((state) => {
const tagIndex = state.createTags.indexOf(tag);
if (tagIndex !== -1) {
state.createTags.splice(tagIndex, 1);
state.createTags.splice(index, 0, tag);
}
})
);
},
// the request body to send to the server // the request body to send to the server
// this is a computed value, just adding the tags to the request // this is a computed value, just adding the tags to the request
@ -212,13 +269,17 @@ export const useImageCreate = create<ImageCreateState>(
const selectedTags = get().selectedTags(); const selectedTags = get().selectedTags();
const tags = selectedTags.map((t: ModifierObject) => t.modifier); const tags = selectedTags.map((t: ModifierObject) => t.modifier);
const positivePrompt = state.createTags.filter((t) => t.type === "positive").map((t) => t.name).join(",");
const negativePrompt = state.createTags.filter((t) => t.type === "negative").map((t) => t.name).join(",");
// join all the tags with a comma and add it to the prompt // join all the tags with a comma and add it to the prompt
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
const prompt = `${requestOptions.prompt}, ${tags.join(",")}`; // const prompt = `${requestOptions.prompt}, ${tags.join(",")}`;
const request = { const request = {
...requestOptions, ...requestOptions,
prompt, prompt: positivePrompt,
negative_prompt: negativePrompt,
}; };
// if we arent using auto save clear the save path // if we arent using auto save clear the save path
if (!state.uiOptions.isUseAutoSave) { if (!state.uiOptions.isUseAutoSave) {

View File

@ -19,6 +19,24 @@ export const IconFont = style({
}); });
export const XButton = style({
position: "absolute",
transform: "translateX(-50%) translateY(-35%)",
background: "black",
color: "white",
border: "2pt solid #ccc",
padding: "0",
cursor: "pointer",
outline: "inherit",
borderRadius: "8pt",
width: "16pt",
height: "16pt",
fontFamily: "Verdana",
fontSize: "8pt",
});
export const MenuButton = style({ export const MenuButton = style({
display: "block", display: "block",
width: "100%", width: "100%",
@ -33,6 +51,5 @@ export const MenuButton = style({
globalStyle(`${MenuButton}> h4`, { globalStyle(`${MenuButton}> h4`, {
color: "#e7ba71", color: "#e7ba71",
}); });

View File

@ -4,49 +4,6 @@ import {
createTheme, createTheme,
} from "@vanilla-extract/css"; } from "@vanilla-extract/css";
// const colors = createThemeContract({
// brand: null,
// brandDimmed: null,
// brandHover: null,
// brandActive: null,
// brandAccent: null,
// brandAccentDimmed: null,
// brandAccentActive: null,
// secondary: null,
// secondaryDimmed: null,
// secondaryHover: null,
// secondaryActive: null,
// secondaryAccent: null,
// secondaryAccentDimmed: null,
// secondaryAccentActive: null,
// background: null,
// backgroundAccent: null,
// backgroundAlt: null,
// backgroundAltAccent: null,
// backgroundDark: null,
// backgroundDarkAccent: null,
// text: {
// normal: null,
// dimmed: null,
// secondary: null,
// secondaryDimmed: null,
// accent: null,
// accentDimmed: null,
// },
// link: null,
// warning: null,
// error: null,
// success: null,
// });
const app = createGlobalTheme(":root", { const app = createGlobalTheme(":root", {
spacing: { spacing: {
none: "0", none: "0",
@ -107,6 +64,10 @@ const app = createGlobalTheme(":root", {
backgroundDark: 'hsl(225, 3%, 7%)', backgroundDark: 'hsl(225, 3%, 7%)',
backgroundAccentMain: 'hsl(225, 6%, 30%)', backgroundAccentMain: 'hsl(225, 6%, 30%)',
backgroundAccentHue: '225',
backgroundAccentSaturation: '26%',
backgroundAccentLightness: '70%',
// this is depricated // this is depricated
colors: { colors: {
text: { text: {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long