- Enhanced cursor behavior for new tools: semantic select, mask lasso, and mask rectangle. - Updated mask edit state to include mask asset ID and kind. - Implemented inpaint region commands for adding, applying, and removing inpaint regions. - Introduced new operations for lasso and semantic selection tools. - Created UI components for candidate review and inpaint region management. - Added tests for inpaint region commands to ensure functionality. - Updated various components to support new inpaint features and improve user experience.
26 lines
2.0 KiB
TypeScript
26 lines
2.0 KiB
TypeScript
import { Star } from "@phosphor-icons/react";
|
|
import { commandIds } from "@commands/ids";
|
|
import type { GenerationState } from "@editor/state";
|
|
import type { AppStore } from "@editor/store";
|
|
|
|
export function CandidateReviewPanel({ generation, dispatch }: { generation: GenerationState; dispatch: AppStore["dispatch"] }) {
|
|
if (generation.candidates.length === 0) return null;
|
|
const selectedId = generation.selectedCandidateId ?? generation.candidates[0]?.id;
|
|
return (
|
|
<section className="grid gap-2 border-b border-white/[0.07] pb-3">
|
|
<div className="flex items-center justify-between px-1"><strong className="text-sm text-white/85">Results</strong><span className="text-xs text-white/35">{generation.candidates.length} candidates</span></div>
|
|
<div className="grid grid-cols-2 gap-2">
|
|
{generation.candidates.map((candidate) => (
|
|
<div key={candidate.id} className={`group relative overflow-hidden rounded-lg border ${candidate.id === selectedId ? "border-sky-300" : "border-white/10"}`}>
|
|
<button type="button" className="block w-full" onClick={() => dispatch(commandIds.generationSelectCandidate, { candidateId: candidate.id })}>
|
|
<img src={candidate.source} alt={`Candidate seed ${candidate.seed}`} className="aspect-square w-full bg-black/25 object-cover" />
|
|
<span className="flex items-center justify-between px-2 py-1 text-[0.65rem] text-white/45"><span>Seed {candidate.seed}</span><span>{candidate.settings.inpaint.profile}</span></span>
|
|
</button>
|
|
<button type="button" aria-label={candidate.favorite ? "Remove favorite" : "Favorite candidate"} aria-pressed={candidate.favorite} className={`absolute right-1.5 top-1.5 rounded-md bg-black/65 p-1.5 ${candidate.favorite ? "text-amber-300" : "text-white/60 opacity-0 group-hover:opacity-100"}`} onClick={() => dispatch(commandIds.generationToggleCandidateFavorite, { candidateId: candidate.id })}><Star size={16} weight={candidate.favorite ? "fill" : "regular"} /></button>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|