import { useEffect, useState } from 'react'; import { History } from 'lucide-react'; import { useFieldHistory, useFieldHistoryScope } from './FieldHistoryProvider'; import { FieldHistoryModal } from './FieldHistoryModal'; interface FieldHistoryLabelProps { label: string; path?: string; /** Size/weight utilities only - the component owns the muted/primary color. */ className?: string; /** `inherit` keeps the surrounding text color until the field has history, for a value shown without a label. */ tone?: 'muted' | 'inherit'; } /** * Owns the history decision + modal for a `` label; layout-agnostic (callers place it). * Mirrors `FieldRow`'s (src/utils/renderField.tsx) trigger/plain/modal behavior exactly: the label * is the only trigger, the value is never clickable, and a `FieldHistoryModal` mounts alongside the * trigger. Safe with no `FieldHistoryProvider`/`FieldHistoryScope` above it -- both hooks return * inert defaults in that case (isActive=false, scope=null), so `timeline` is always `null` and this * renders as a plain muted label. */ export function FieldHistoryLabel({ label, path, className, tone = 'muted' }: FieldHistoryLabelProps) { const scope = useFieldHistoryScope(); const { isActive, getFieldHistory, reportShownField, attributionFor } = useFieldHistory(); const [isHistoryOpen, setIsHistoryOpen] = useState(false); const timeline = isActive && scope?.id && path ? getFieldHistory(scope.resourceType, scope.id, path, label) : null; const fieldKey = isActive && scope?.id && path ? `${scope.resourceType}/${scope.id}/${path}` : null; const changed = Boolean(timeline); useEffect(() => (fieldKey && reportShownField ? reportShownField(fieldKey, changed) : undefined), [fieldKey, changed, reportShownField]); if (!timeline) { return {label}; } return ( <> setIsHistoryOpen(false)} attribution={scope?.id ? attributionFor(scope.resourceType, scope.id) : undefined} /> ); } export default FieldHistoryLabel;