133 lines
4.1 KiB
TypeScript
133 lines
4.1 KiB
TypeScript
import type { CustomWorldSuggestedAction } from '../../../packages/shared/src/contracts/customWorldAgent';
|
|
|
|
type CustomWorldAgentQuickActionsProps = {
|
|
suggestedActions: CustomWorldSuggestedAction[];
|
|
disabled: boolean;
|
|
canDraftFoundation: boolean;
|
|
showEntityActions?: boolean;
|
|
showSummaryAction?: boolean;
|
|
onRequestSummary: () => void;
|
|
onDraftFoundation: () => void;
|
|
onGenerateCharacter?: () => void;
|
|
onGenerateLandmark?: () => void;
|
|
onGenerateRoleAssets?: () => void;
|
|
showRoleAssetAction?: boolean;
|
|
onFocusSuggestedAction: (action?: CustomWorldSuggestedAction) => void;
|
|
};
|
|
|
|
function QuickActionButton(props: {
|
|
label: string;
|
|
onClick: () => void;
|
|
disabled: boolean;
|
|
tone?: 'default' | 'sky' | 'amber';
|
|
}) {
|
|
const { label, onClick, disabled, tone = 'default' } = props;
|
|
|
|
return (
|
|
<button
|
|
type="button"
|
|
onClick={onClick}
|
|
disabled={disabled}
|
|
className={`rounded-[1.1rem] border px-4 py-3 text-left text-sm transition disabled:cursor-not-allowed disabled:opacity-45 ${
|
|
tone === 'amber'
|
|
? 'border-amber-300/20 bg-amber-500/10 text-amber-100 hover:text-white'
|
|
: tone === 'sky'
|
|
? 'border-sky-300/20 bg-sky-500/10 text-sky-100 hover:text-white'
|
|
: 'border-white/10 bg-black/20 text-zinc-200 hover:text-white'
|
|
}`}
|
|
>
|
|
{label}
|
|
</button>
|
|
);
|
|
}
|
|
|
|
export function CustomWorldAgentQuickActions({
|
|
suggestedActions,
|
|
disabled,
|
|
canDraftFoundation,
|
|
showEntityActions = false,
|
|
showSummaryAction = true,
|
|
onRequestSummary,
|
|
onDraftFoundation,
|
|
onGenerateCharacter,
|
|
onGenerateLandmark,
|
|
onGenerateRoleAssets,
|
|
showRoleAssetAction = false,
|
|
onFocusSuggestedAction,
|
|
}: CustomWorldAgentQuickActionsProps) {
|
|
const summaryAction = suggestedActions.find(
|
|
(action) => action.type === 'request_summary',
|
|
);
|
|
const draftAction = suggestedActions.find(
|
|
(action) => action.type === 'draft_foundation',
|
|
);
|
|
const refinementActions = suggestedActions.filter(
|
|
(action) =>
|
|
action.type !== 'request_summary' && action.type !== 'draft_foundation',
|
|
);
|
|
|
|
return (
|
|
<div className="rounded-[1.5rem] border border-white/10 bg-black/18 px-4 py-4">
|
|
<div className="text-[11px] font-bold tracking-[0.2em] text-zinc-400">
|
|
快捷动作
|
|
</div>
|
|
<div className="mt-3 flex flex-col gap-2">
|
|
{showSummaryAction ? (
|
|
<QuickActionButton
|
|
label={summaryAction?.label ?? '总结当前设定'}
|
|
onClick={onRequestSummary}
|
|
disabled={disabled}
|
|
tone="sky"
|
|
/>
|
|
) : null}
|
|
{draftAction && canDraftFoundation ? (
|
|
<QuickActionButton
|
|
label={draftAction.label}
|
|
onClick={onDraftFoundation}
|
|
disabled={disabled}
|
|
tone="amber"
|
|
/>
|
|
) : null}
|
|
{showEntityActions && onGenerateCharacter ? (
|
|
<QuickActionButton
|
|
label="新增角色"
|
|
onClick={onGenerateCharacter}
|
|
disabled={disabled}
|
|
/>
|
|
) : null}
|
|
{showEntityActions && onGenerateLandmark ? (
|
|
<QuickActionButton
|
|
label="新增场景"
|
|
onClick={onGenerateLandmark}
|
|
disabled={disabled}
|
|
/>
|
|
) : null}
|
|
{showRoleAssetAction && onGenerateRoleAssets ? (
|
|
<QuickActionButton
|
|
label="生成角色主图与动作"
|
|
onClick={onGenerateRoleAssets}
|
|
disabled={disabled}
|
|
tone="amber"
|
|
/>
|
|
) : null}
|
|
{refinementActions.length > 0 ? (
|
|
refinementActions.slice(0, 2).map((action) => (
|
|
<QuickActionButton
|
|
key={action.id}
|
|
label={action.label}
|
|
onClick={() => onFocusSuggestedAction(action)}
|
|
disabled={disabled}
|
|
/>
|
|
))
|
|
) : !draftAction || !canDraftFoundation ? (
|
|
<QuickActionButton
|
|
label={showEntityActions ? '继续精修当前草稿' : '继续补充设定'}
|
|
onClick={() => onFocusSuggestedAction()}
|
|
disabled={disabled}
|
|
/>
|
|
) : null}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|