/** * The create-worktree dialog: name input with the sanitizer mirror for * instant feedback, a base-branch picker (default: the checkout's current * branch), and readable rejection copy. Success registers the worktree as a * workspace and starts a new session in it (the owner owns that flow). * @module dsh-git-graph/client/chips/CreateWorktreeDialog */ import { useState } from 'react' import type { Translate } from '@deepseek-ai/dsh-client-ui-slots' import { sanitizeWorktreeName } from '../../core/git-command.ts' import type { BranchRow, WorktreeAddResult } from '../../core/types.ts' import type { GitGraphKey } from '../locales.ts' import { errorMessage } from './error-copy.ts' import { Backdrop } from './Chip.tsx' import css from './context.module.css' /** Props of the create-worktree dialog. */ export interface CreateWorktreeDialogProps { /** Local branches for the base picker. */ branches: BranchRow[] /** The checkout's current branch (the picker default); empty when detached. */ currentBranch: string /** The create flow: host worktree-add, then workspace registration + session start. */ onCreate: (name: string, baseRef: string | undefined) => Promise /** Close the dialog (cancel or after a successful create). */ onClose: () => void t: Translate } /** * The create-worktree-and-start-session dialog. * @param props - see {@link CreateWorktreeDialogProps}. */ export function CreateWorktreeDialog({ branches, currentBranch, onCreate, onClose, t }: CreateWorktreeDialogProps) { const [name, setName] = useState('') const [baseRef, setBaseRef] = useState(currentBranch) const [pending, setPending] = useState(false) const [error, setError] = useState(null) const sanitized = sanitizeWorktreeName(name) const submit = (): void => { if (pending) return if (sanitized === null) { setError(t('error.invalidWorktreeName')) return } setPending(true) setError(null) void onCreate(sanitized, baseRef === '' ? undefined : baseRef).then((result) => { if (result.ok) { onClose() return } setError(errorMessage(result.error, t)) }).finally(() => { setPending(false) }) } return ( <>

{t('worktree.dialog.title')}

{t('worktree.dialog.description')}

{ setName(event.target.value) }} placeholder={t('worktree.dialog.namePlaceholder')} onKeyDown={(event) => { if (event.key === 'Enter') submit() }} autoFocus />
{error !== null &&
{error}
}
) }