mirror of
https://github.com/storytold/artcraft.git
synced 2026-10-27 04:00:10 -04:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f1678c97b4 | ||
|
|
7c6cc86399 | ||
|
|
b96300f0a5 |
+1
-25
@@ -6,7 +6,7 @@ import {
|
||||
type IconDefinition,
|
||||
} from "@fortawesome/pro-solid-svg-icons";
|
||||
import { Button } from "@storyteller/ui-button";
|
||||
import { PopoverMenu, type PopoverItem } from "@storyteller/ui-popover";
|
||||
import { type PopoverItem } from "@storyteller/ui-popover";
|
||||
import Seo from "../../components/seo";
|
||||
import Footer from "../../components/footer";
|
||||
|
||||
@@ -49,8 +49,6 @@ export function CreateMediaPageShell({
|
||||
emptyStateTitle,
|
||||
emptyStateSubtitle,
|
||||
bottomOffset,
|
||||
modelItems,
|
||||
onModelChange,
|
||||
glowOrbs,
|
||||
gridContent,
|
||||
promptBox,
|
||||
@@ -146,28 +144,6 @@ export function CreateMediaPageShell({
|
||||
)}
|
||||
|
||||
{promptBox}
|
||||
|
||||
<div
|
||||
className="animate-fade-in-up fixed bottom-3 left-6 z-20 hidden items-center gap-5 lg:flex"
|
||||
style={{ animationDelay: "300ms" }}
|
||||
>
|
||||
<div
|
||||
className="rounded-xl border border-white/10 px-3 py-2 shadow-lg backdrop-blur-xl"
|
||||
style={{ backgroundColor: "rgba(30, 30, 33, 0.85)" }}
|
||||
>
|
||||
<PopoverMenu
|
||||
items={modelItems}
|
||||
onSelect={onModelChange}
|
||||
mode="hoverSelect"
|
||||
panelTitle="Select Model"
|
||||
panelClassName="min-w-[300px]"
|
||||
buttonClassName="bg-transparent border-0 shadow-none p-0 text-lg hover:bg-transparent text-white/80 hover:text-white"
|
||||
showIconsInList
|
||||
triggerLabel="Model"
|
||||
maxListHeight={400}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -633,7 +633,7 @@ export const MentionTextarea = forwardRef<HTMLDivElement, MentionTextareaProps>(
|
||||
onBlur={onBlur}
|
||||
className={twMerge(
|
||||
className,
|
||||
"outline-none whitespace-pre-wrap break-words overflow-y-auto",
|
||||
"outline-none whitespace-pre-wrap break-words overflow-y-auto resize-y",
|
||||
)}
|
||||
/>
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ import {
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import {
|
||||
faChevronDown,
|
||||
faChevronUp,
|
||||
faMusic,
|
||||
faUserGroup,
|
||||
faVideo,
|
||||
@@ -143,8 +145,25 @@ export const PromptBox = forwardRef<HTMLDivElement, PromptBoxProps>(
|
||||
const highlightRef = useRef<HTMLDivElement>(null);
|
||||
const mentionEditorRef = useRef<HTMLDivElement>(null);
|
||||
const [isFocused, setIsFocused] = useState(false);
|
||||
const [isExpanded, setIsExpanded] = useState(false);
|
||||
const [showImagePrompts, setShowImagePrompts] = useState(false);
|
||||
|
||||
const EXPANDED_HEIGHT = "clamp(120px, calc(100vh - 700px), 500px)";
|
||||
|
||||
const toggleExpand = () => {
|
||||
setIsExpanded((prev) => {
|
||||
const next = !prev;
|
||||
const height = next ? EXPANDED_HEIGHT : "auto";
|
||||
if (textareaRef.current) {
|
||||
textareaRef.current.style.height = height;
|
||||
}
|
||||
if (mentionEditorRef.current) {
|
||||
mentionEditorRef.current.style.height = height;
|
||||
}
|
||||
return next;
|
||||
});
|
||||
};
|
||||
|
||||
// @-mention state
|
||||
const [mentionOpen, setMentionOpen] = useState(false);
|
||||
const [mentionFilter, setMentionFilter] = useState("");
|
||||
@@ -167,13 +186,14 @@ export const PromptBox = forwardRef<HTMLDivElement, PromptBoxProps>(
|
||||
);
|
||||
}, [mentionItems, mentionFilter]);
|
||||
|
||||
// Auto-resize textarea
|
||||
// Auto-resize textarea (skip when expanded)
|
||||
useEffect(() => {
|
||||
if (isExpanded) return;
|
||||
if (textareaRef.current) {
|
||||
textareaRef.current.style.height = "auto";
|
||||
textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`;
|
||||
}
|
||||
}, [prompt]);
|
||||
}, [prompt, isExpanded]);
|
||||
|
||||
// Move caret to end on mount so autoFocus doesn't leave it at position 0
|
||||
useEffect(() => {
|
||||
@@ -402,7 +422,10 @@ export const PromptBox = forwardRef<HTMLDivElement, PromptBoxProps>(
|
||||
onChange={onPromptChange}
|
||||
mentionItems={mentionItems}
|
||||
placeholder={placeholder}
|
||||
className="max-h-[5.5em] w-full text-white"
|
||||
className={twMerge(
|
||||
"promptbox-scrollbar min-h-[2.5em] w-full text-white",
|
||||
isExpanded ? "max-h-[500px]" : "max-h-[5.5em]",
|
||||
)}
|
||||
colorMap={mentionColorMap}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter" && !e.shiftKey && !e.metaKey) {
|
||||
@@ -419,7 +442,10 @@ export const PromptBox = forwardRef<HTMLDivElement, PromptBoxProps>(
|
||||
<div
|
||||
ref={highlightRef}
|
||||
aria-hidden
|
||||
className="pointer-events-none absolute inset-0 max-h-[5.5em] overflow-y-auto whitespace-pre-wrap break-words text-sm text-white"
|
||||
className={twMerge(
|
||||
"pointer-events-none absolute inset-0 overflow-y-auto whitespace-pre-wrap break-words text-sm text-white",
|
||||
isExpanded ? "max-h-[500px]" : "max-h-[5.5em]",
|
||||
)}
|
||||
>
|
||||
{renderHighlightedPrompt()}
|
||||
</div>
|
||||
@@ -431,7 +457,8 @@ export const PromptBox = forwardRef<HTMLDivElement, PromptBoxProps>(
|
||||
autoFocus
|
||||
placeholder={placeholder}
|
||||
className={twMerge(
|
||||
"max-h-[5.5em] w-full flex-1 resize-none overflow-y-auto bg-transparent text-md text-white placeholder-white/50 focus:outline-none",
|
||||
"promptbox-scrollbar min-h-[2.5em] w-full flex-1 resize-y overflow-y-auto bg-transparent text-md text-white placeholder-white/50 focus:outline-none",
|
||||
isExpanded ? "max-h-[500px]" : "max-h-[5.5em]",
|
||||
hasMentionItems && "text-transparent caret-white",
|
||||
)}
|
||||
value={prompt}
|
||||
@@ -515,9 +542,7 @@ export const PromptBox = forwardRef<HTMLDivElement, PromptBoxProps>(
|
||||
{/* Toolbar */}
|
||||
<div className="mt-2 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
|
||||
<div className="flex flex-wrap items-center gap-1.5 sm:gap-2">
|
||||
{modelSelector && (
|
||||
<div className="lg:hidden">{modelSelector}</div>
|
||||
)}
|
||||
{modelSelector}
|
||||
{leftToolbar}
|
||||
</div>
|
||||
<div className="flex items-center gap-2 sm:shrink-0">
|
||||
@@ -533,6 +558,25 @@ export const PromptBox = forwardRef<HTMLDivElement, PromptBoxProps>(
|
||||
</GenerateButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Expand / Collapse toggle — hidden on small screens */}
|
||||
<div className="absolute -bottom-1 left-1/2 hidden -translate-x-1/2 sm:block">
|
||||
<Tooltip
|
||||
content={isExpanded ? "Collapse" : "Expand"}
|
||||
position="top"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={toggleExpand}
|
||||
className="px-3 py-0.5 text-white/30 transition-colors hover:text-white/90"
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={isExpanded ? faChevronUp : faChevronDown}
|
||||
className="text-xs"
|
||||
/>
|
||||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -71,6 +71,30 @@
|
||||
background-color: rgba(46, 46, 49, 0.85) !important;
|
||||
}
|
||||
|
||||
/* Minimal thin scrollbar for prompt textareas */
|
||||
.promptbox-scrollbar {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: rgba(255, 255, 255, 0.2) transparent;
|
||||
}
|
||||
|
||||
.promptbox-scrollbar::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
.promptbox-scrollbar::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.promptbox-scrollbar::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 9999px;
|
||||
}
|
||||
|
||||
.promptbox-scrollbar::-webkit-scrollbar-thumb:hover {
|
||||
background-color: rgba(255, 255, 255, 0.35);
|
||||
}
|
||||
|
||||
|
||||
@keyframes fade-in-up {
|
||||
from {
|
||||
opacity: 0;
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
{
|
||||
"path": "../../libs/components/gravatar/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../../libs/components/slider-v2/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../../libs/components/tab-selector/tsconfig.lib.json"
|
||||
},
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
{
|
||||
"path": "../../libs/components/gravatar"
|
||||
},
|
||||
{
|
||||
"path": "../../libs/components/slider-v2"
|
||||
},
|
||||
{
|
||||
"path": "../../libs/components/tab-selector"
|
||||
},
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"path": "../../common"
|
||||
},
|
||||
{
|
||||
"path": "../loading-spinner"
|
||||
"path": "../../api"
|
||||
},
|
||||
{
|
||||
"path": "../close-button"
|
||||
@@ -24,10 +24,10 @@
|
||||
"path": "../modal"
|
||||
},
|
||||
{
|
||||
"path": "../../tauri-api"
|
||||
"path": "../toaster"
|
||||
},
|
||||
{
|
||||
"path": "../../api"
|
||||
"path": "../../tauri-api"
|
||||
},
|
||||
{
|
||||
"path": "../action-reminder-modal"
|
||||
@@ -38,6 +38,9 @@
|
||||
{
|
||||
"path": "../tooltip"
|
||||
},
|
||||
{
|
||||
"path": "../loading-spinner"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
},
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
"path": "../../common/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../loading-spinner/tsconfig.lib.json"
|
||||
"path": "../../api/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../close-button/tsconfig.lib.json"
|
||||
@@ -65,10 +65,10 @@
|
||||
"path": "../modal/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../../tauri-api/tsconfig.lib.json"
|
||||
"path": "../toaster/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../../api/tsconfig.lib.json"
|
||||
"path": "../../tauri-api/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../action-reminder-modal/tsconfig.lib.json"
|
||||
@@ -78,6 +78,9 @@
|
||||
},
|
||||
{
|
||||
"path": "../tooltip/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../loading-spinner/tsconfig.lib.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user