import { useState, type ReactNode } from "react";
import { PlusIcon } from "lucide-react";
import { Button } from "../components/button";
import {
CardStack,
CardStackContent,
CardStackEmpty,
CardStackEntry,
} from "../components/card-stack";
import {
defaultHeaderAuthPresets,
type HeaderAuthPreset,
type HeaderState,
SecretHeaderAuthRow,
} from "./secret-header-auth";
import type { SecretPickerSecret } from "./secret-picker";
export interface HeadersListProps {
readonly headers: readonly HeaderState[];
readonly onHeadersChange: (headers: HeaderState[]) => void;
readonly existingSecrets?: readonly SecretPickerSecret[];
/** Presets offered in the quick-add picker. Defaults to `defaultHeaderAuthPresets`. */
readonly presets?: readonly HeaderAuthPreset[];
/** When true, only allow a single header (hide add button, disable remove). */
readonly singleHeader?: boolean;
/** Text shown in the empty state. */
readonly emptyLabel?: ReactNode;
/**
* Display name of the source that owns these headers (e.g. "Axiom"). Used
* to derive unique default secret labels/IDs like `axiom-authorization`.
*/
readonly sourceName?: string;
}
export function HeadersList({
headers,
onHeadersChange,
existingSecrets = [],
presets = defaultHeaderAuthPresets,
singleHeader = false,
emptyLabel = "No headers",
sourceName,
}: HeadersListProps) {
const [picking, setPicking] = useState(false);
const canAddMore = !singleHeader || headers.length === 0;
const addHeaderFromPreset = (preset: HeaderAuthPreset) => {
onHeadersChange([
...headers,
{
name: preset.name,
prefix: preset.prefix,
presetKey: preset.key,
secretId: null,
},
]);
setPicking(false);
};
const updateHeader = (
index: number,
update: Partial<{
name: string;
secretId: string | null;
prefix?: string;
presetKey?: string;
}>,
) => {
onHeadersChange(
headers.map((entry, i) => (i === index ? { ...entry, ...update } : entry)),
);
};
const removeHeader = (index: number) => {
onHeadersChange(headers.filter((_, i) => i !== index));
};
return (
{picking ? (
setPicking(false)}
/>
) : headers.length === 0 ? (
canAddMore ? (
{emptyLabel}} onClick={() => setPicking(true)} />
) : (
{emptyLabel}
)
) : (
<>
{headers.map((header, index) => (
updateHeader(index, update)}
onSelectSecret={(secretId) => updateHeader(index, { secretId })}
onRemove={singleHeader ? undefined : () => removeHeader(index)}
existingSecrets={existingSecrets}
sourceName={sourceName}
/>
))}
{canAddMore && setPicking(true)} />}
>
)}
);
}
interface AddHeaderRowProps {
readonly onClick: () => void;
readonly leading?: ReactNode;
}
function AddHeaderRow({ onClick, leading }: AddHeaderRowProps) {
return (
// oxlint-disable-next-line react/forbid-elements
);
}
interface HeaderPresetPickerProps {
readonly presets: readonly HeaderAuthPreset[];
readonly onPick: (preset: HeaderAuthPreset) => void;
readonly onCancel: () => void;
}
function HeaderPresetPicker({ presets, onPick, onCancel }: HeaderPresetPickerProps) {
return (
{presets.map((preset) => (
))}
);
}