mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-05-28 23:15:33 +08:00
140 lines
4.5 KiB
TypeScript
140 lines
4.5 KiB
TypeScript
import * as React from 'react';
|
|
|
|
import { cn } from '../../../lib/utils';
|
|
import { Alert } from './Alert';
|
|
import { Button } from './Button';
|
|
|
|
/* ─── Context ────────────────────────────────────────────────────── */
|
|
|
|
type ApprovalState = 'pending' | 'approved' | 'rejected' | undefined;
|
|
|
|
interface ConfirmationContextValue {
|
|
approval: ApprovalState;
|
|
}
|
|
|
|
const ConfirmationContext = React.createContext<ConfirmationContextValue | null>(null);
|
|
|
|
const useConfirmation = () => {
|
|
const context = React.useContext(ConfirmationContext);
|
|
if (!context) {
|
|
throw new Error('Confirmation components must be used within Confirmation');
|
|
}
|
|
return context;
|
|
};
|
|
|
|
/* ─── Confirmation (root) ────────────────────────────────────────── */
|
|
|
|
export interface ConfirmationProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
approval?: ApprovalState;
|
|
}
|
|
|
|
export const Confirmation: React.FC<ConfirmationProps> = ({
|
|
className,
|
|
approval = 'pending',
|
|
children,
|
|
...props
|
|
}) => {
|
|
const contextValue = React.useMemo(() => ({ approval }), [approval]);
|
|
|
|
return (
|
|
<ConfirmationContext.Provider value={contextValue}>
|
|
<Alert className={cn('flex flex-col gap-2', className)} {...props}>
|
|
{children}
|
|
</Alert>
|
|
</ConfirmationContext.Provider>
|
|
);
|
|
};
|
|
Confirmation.displayName = 'Confirmation';
|
|
|
|
/* ─── ConfirmationTitle ──────────────────────────────────────────── */
|
|
|
|
export type ConfirmationTitleProps = React.HTMLAttributes<HTMLDivElement>;
|
|
|
|
export const ConfirmationTitle: React.FC<ConfirmationTitleProps> = ({
|
|
className,
|
|
...props
|
|
}) => (
|
|
<div
|
|
data-slot="confirmation-title"
|
|
className={cn('text-muted-foreground inline text-sm', className)}
|
|
{...props}
|
|
/>
|
|
);
|
|
ConfirmationTitle.displayName = 'ConfirmationTitle';
|
|
|
|
/* ─── ConfirmationRequest — visible only when pending ────────────── */
|
|
|
|
export interface ConfirmationRequestProps {
|
|
children?: React.ReactNode;
|
|
}
|
|
|
|
export const ConfirmationRequest: React.FC<ConfirmationRequestProps> = ({ children }) => {
|
|
const { approval } = useConfirmation();
|
|
if (approval !== 'pending') return null;
|
|
return <>{children}</>;
|
|
};
|
|
ConfirmationRequest.displayName = 'ConfirmationRequest';
|
|
|
|
/* ─── ConfirmationAccepted — visible only when approved ──────────── */
|
|
|
|
export interface ConfirmationAcceptedProps {
|
|
children?: React.ReactNode;
|
|
}
|
|
|
|
export const ConfirmationAccepted: React.FC<ConfirmationAcceptedProps> = ({ children }) => {
|
|
const { approval } = useConfirmation();
|
|
if (approval !== 'approved') return null;
|
|
return <>{children}</>;
|
|
};
|
|
ConfirmationAccepted.displayName = 'ConfirmationAccepted';
|
|
|
|
/* ─── ConfirmationRejected — visible only when rejected ──────────── */
|
|
|
|
export interface ConfirmationRejectedProps {
|
|
children?: React.ReactNode;
|
|
}
|
|
|
|
export const ConfirmationRejected: React.FC<ConfirmationRejectedProps> = ({ children }) => {
|
|
const { approval } = useConfirmation();
|
|
if (approval !== 'rejected') return null;
|
|
return <>{children}</>;
|
|
};
|
|
ConfirmationRejected.displayName = 'ConfirmationRejected';
|
|
|
|
/* ─── ConfirmationActions — visible only when pending ────────────── */
|
|
|
|
export type ConfirmationActionsProps = React.HTMLAttributes<HTMLDivElement>;
|
|
|
|
export const ConfirmationActions: React.FC<ConfirmationActionsProps> = ({
|
|
className,
|
|
...props
|
|
}) => {
|
|
const { approval } = useConfirmation();
|
|
if (approval !== 'pending') return null;
|
|
|
|
return (
|
|
<div
|
|
data-slot="confirmation-actions"
|
|
className={cn('flex items-center justify-end gap-2 self-end', className)}
|
|
{...props}
|
|
/>
|
|
);
|
|
};
|
|
ConfirmationActions.displayName = 'ConfirmationActions';
|
|
|
|
/* ─── ConfirmationAction — styled button ─────────────────────────── */
|
|
|
|
export type ConfirmationActionProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
variant?: 'default' | 'outline' | 'ghost' | 'destructive';
|
|
};
|
|
|
|
export const ConfirmationAction: React.FC<ConfirmationActionProps> = ({
|
|
variant = 'default',
|
|
...props
|
|
}) => (
|
|
<Button className="h-8 px-3 text-sm" variant={variant} type="button" {...props} />
|
|
);
|
|
ConfirmationAction.displayName = 'ConfirmationAction';
|
|
|
|
export { useConfirmation };
|