import React from 'react'; import { useComponentCompare } from '@teambit/component.ui.component-compare.context'; import type { APIDiffResult, APIDiffChange, APIDiffDetail } from './api-compare.types'; import styles from './api-compare.module.scss'; export type { APIDiffResult, APIDiffChange, APIDiffDetail }; function impactClass(impact: string): string { switch (impact) { case 'BREAKING': return styles.removedBadge; case 'NON_BREAKING': return styles.addedBadge; case 'PATCH': return styles.modifiedBadge; default: return styles.summaryBadge; } } function impactLabel(impact: string): string { switch (impact) { case 'BREAKING': return 'Breaking'; case 'NON_BREAKING': return 'Non-breaking'; case 'PATCH': return 'Patch'; default: return impact; } } function getStatusClass(status: string): string { switch (status) { case 'ADDED': return styles.statusAdded; case 'REMOVED': return styles.statusRemoved; case 'MODIFIED': return styles.statusModified; default: return styles.statusBadge; } } function getStatusLabel(status: string): string { switch (status) { case 'ADDED': return '+ Added'; case 'REMOVED': return '- Removed'; case 'MODIFIED': return '~ Modified'; default: return status; } } function dotClass(impact: string): string { switch (impact) { case 'BREAKING': return styles.dotBreaking; case 'NON_BREAKING': return styles.dotNonBreaking; default: return styles.dotPatch; } } function DetailItem({ detail }: { detail: APIDiffDetail }) { return (
  • {detail.description}
  • ); } function APIDiffEntry({ change }: { change: APIDiffChange }) { const [expanded, setExpanded] = React.useState(change.status === 'MODIFIED'); const [showSignatures, setShowSignatures] = React.useState(false); const hasBody = change.status === 'MODIFIED' ? (change.changes && change.changes.length > 0) || change.baseSignature || change.compareSignature : change.baseSignature || change.compareSignature; return (
    hasBody && setExpanded(!expanded)} role="button" tabIndex={0} aria-expanded={hasBody ? expanded : undefined} onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); hasBody && setExpanded(!expanded); } }} > {getStatusLabel(change.status)} {change.exportName} {change.schemaType} {impactLabel(change.impact)} {hasBody && }
    {expanded && hasBody && (
    {change.status === 'MODIFIED' && change.changes && change.changes.length > 0 && ( )} {change.status === 'MODIFIED' && (change.baseSignature || change.compareSignature) && ( <> {showSignatures && ( <> {change.baseSignature && (
    Base
    {change.baseSignature}
    )} {change.compareSignature && (
    Compare
    {change.compareSignature}
    )} )} )} {change.status === 'ADDED' && change.compareSignature && (
    {change.compareSignature}
    )} {change.status === 'REMOVED' && change.baseSignature && (
    {change.baseSignature}
    )}
    )}
    ); } function ChangeSection({ title, changes }: { title: string; changes: APIDiffChange[] }) { if (changes.length === 0) return null; const sorted = [...changes].sort((a, b) => { const order: Record = { REMOVED: 0, MODIFIED: 1, ADDED: 2 }; return (order[a.status] ?? 3) - (order[b.status] ?? 3); }); return ( <>

    {title}

    {sorted.map((change) => ( ))}
    ); } export function APICompare() { const compareContext = useComponentCompare(); const apiDiffResult: APIDiffResult | null | undefined = (compareContext as any)?.apiDiffResult; if (apiDiffResult === undefined) { return
    Loading API diff...
    ; } if (!apiDiffResult || !apiDiffResult.hasChanges) { return
    No API changes between these versions
    ; } const { publicChanges, internalChanges, added, removed, modified, breaking, impact } = apiDiffResult; return (
    {impactLabel(impact)} | {added > 0 && +{added} added} {removed > 0 && -{removed} removed} {modified > 0 && ~{modified} modified} {breaking > 0 && {breaking} breaking}
    ); }