Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
515 changes: 515 additions & 0 deletions frontend/src/components/ComplexFields.tsx

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions frontend/src/components/DenoisingStepsSlider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export function DenoisingStepsSlider({
<LabelWithTooltip
label="Denoising Step List"
tooltip={tooltip}
className="text-sm text-foreground"
className="text-sm font-medium"
/>
<div className="flex items-center gap-2">
<Button
Expand Down Expand Up @@ -170,7 +170,8 @@ export function DenoisingStepsSlider({
{localValue.map((stepValue, index) => (
<SliderWithInput
key={index}
label={`Step ${index + 1}:`}
label={`Step ${index + 1}`}
labelClassName="text-xs text-muted-foreground w-12"
value={stepValue}
onValueChange={value => handleStepValueChange(index, value)}
onValueCommit={value => handleStepCommit(index, value)}
Expand Down
105 changes: 104 additions & 1 deletion frontend/src/components/InputAndControlsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ import { TimelinePromptEditor } from "./TimelinePromptEditor";
import type { TimelinePrompt } from "./PromptTimeline";
import { ImageManager } from "./ImageManager";
import { Button } from "./ui/button";
import {
type ConfigSchemaLike,
type PrimitiveFieldType,
COMPLEX_COMPONENTS,
parseInputFields,
} from "../lib/schemaSettings";
import { SchemaPrimitiveField } from "./PrimitiveFields";

interface InputAndControlsPanelProps {
className?: string;
Expand Down Expand Up @@ -79,6 +86,14 @@ interface InputAndControlsPanelProps {
extensionMode?: ExtensionMode;
onExtensionModeChange?: (mode: ExtensionMode) => void;
onSendExtensionFrames?: () => void;
// Schema-driven input fields (category "input"), shown below Prompts
configSchema?: ConfigSchemaLike;
schemaFieldOverrides?: Record<string, unknown>;
onSchemaFieldOverrideChange?: (
key: string,
value: unknown,
isRuntimeParam?: boolean
) => void;
}

export function InputAndControlsPanel({
Expand Down Expand Up @@ -133,6 +148,9 @@ export function InputAndControlsPanel({
extensionMode = "firstframe",
onExtensionModeChange,
onSendExtensionFrames,
configSchema,
schemaFieldOverrides,
onSchemaFieldOverrideChange,
}: InputAndControlsPanelProps) {
// Helper function to determine if playhead is at the end of timeline
const isAtEndOfTimeline = () => {
Expand Down Expand Up @@ -240,7 +258,7 @@ export function InputAndControlsPanel({
/* Spout Receiver Configuration */
<div className="flex items-center gap-3">
<LabelWithTooltip
label="Sender Name:"
label="Sender Name"
tooltip="The name of the sender to receive video from Spout-compatible apps like TouchDesigner, Resolume, OBS. Leave empty to receive from any sender."
className="text-xs text-muted-foreground whitespace-nowrap"
/>
Expand Down Expand Up @@ -529,6 +547,91 @@ export function InputAndControlsPanel({
);
})()}
</div>

{/* Schema-driven input fields (category "input"), below app-defined sections */}
{configSchema &&
Comment thread
yondonfu marked this conversation as resolved.
(() => {
const parsedInputFields = parseInputFields(configSchema, inputMode);
if (parsedInputFields.length === 0) return null;
const enumValuesByRef: Record<string, string[]> = {};
if (configSchema?.$defs) {
for (const [defName, def] of Object.entries(
configSchema.$defs as Record<string, { enum?: unknown[] }>
)) {
if (def?.enum && Array.isArray(def.enum)) {
enumValuesByRef[defName] = def.enum as string[];
}
}
}
return (
<div className="space-y-2">
{parsedInputFields.map(({ key, prop, ui, fieldType }) => {
const comp = ui.component;
const isRuntimeParam = ui.is_load_param === false;
const disabled =
(isStreaming && !isRuntimeParam) || _isPipelineLoading;
const value = schemaFieldOverrides?.[key] ?? prop.default;
const setValue = (v: unknown) =>
onSchemaFieldOverrideChange?.(key, v, isRuntimeParam);
if (comp === "image") {
const path = value == null ? null : String(value);
return (
<div key={key} className="space-y-1">
{ui.label != null && (
<span className="text-xs text-muted-foreground">
{ui.label}
</span>
)}
<ImageManager
images={path ? [path] : []}
onImagesChange={images =>
onSchemaFieldOverrideChange?.(
key,
images[0] ?? null,
isRuntimeParam
)
}
disabled={disabled}
maxImages={1}
hideLabel
/>
</div>
);
}
if (
comp &&
(COMPLEX_COMPONENTS as readonly string[]).includes(comp)
) {
return null;
}
const enumValues =
fieldType === "enum" && typeof prop.$ref === "string"
? enumValuesByRef[prop.$ref.split("/").pop() ?? ""]
: undefined;
const primitiveType: PrimitiveFieldType | undefined =
typeof fieldType === "string" &&
!(COMPLEX_COMPONENTS as readonly string[]).includes(
fieldType
)
? (fieldType as PrimitiveFieldType)
: undefined;
return (
<SchemaPrimitiveField
key={key}
fieldKey={key}
prop={prop}
value={value}
onChange={setValue}
disabled={disabled}
label={ui.label}
fieldType={primitiveType}
enumValues={enumValues}
/>
);
})}
</div>
);
})()}
</CardContent>
</Card>
);
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/LoRAManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ export function LoRAManager({

<div className="flex items-center gap-2">
<LabelWithTooltip
label="Strategy:"
label="Strategy"
tooltip={PARAMETER_METADATA.loraMergeStrategy.tooltip}
className="text-xs text-muted-foreground w-16"
/>
Expand All @@ -208,7 +208,7 @@ export function LoRAManager({

<div className="flex items-center gap-2">
<LabelWithTooltip
label="Scale:"
label="Scale"
tooltip={getScaleAdjustmentInfo(lora).tooltipText}
className="text-xs text-muted-foreground w-16"
/>
Expand Down
Loading
Loading