74 lines
2.4 KiB
TypeScript
74 lines
2.4 KiB
TypeScript
import React from 'react';
|
|
|
|
const NBSP = String.fromCharCode(160);
|
|
|
|
export interface CorrespondentLinkEntry {
|
|
id?: string | number | null;
|
|
name?: string | null;
|
|
key?: string;
|
|
}
|
|
|
|
interface CorrespondentLinksProps {
|
|
correspondents?: CorrespondentLinkEntry[];
|
|
activeCorrespondentIdSet?: Set<string | number>;
|
|
onCorrespondentClick?: (id: string | number) => void;
|
|
}
|
|
|
|
const CorrespondentLinks: React.FC<CorrespondentLinksProps> = ({
|
|
correspondents,
|
|
activeCorrespondentIdSet,
|
|
onCorrespondentClick,
|
|
}) => {
|
|
if (!Array.isArray(correspondents) || correspondents.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
const activeSet = activeCorrespondentIdSet || new Set<string | number>();
|
|
const handleClick = (event: React.MouseEvent<HTMLButtonElement> | React.KeyboardEvent<HTMLButtonElement>, correspondent: CorrespondentLinkEntry) => {
|
|
if (!onCorrespondentClick || correspondent.id == null) {
|
|
return;
|
|
}
|
|
event.stopPropagation();
|
|
onCorrespondentClick(correspondent.id);
|
|
};
|
|
|
|
return correspondents.map((correspondent, index) => {
|
|
const isActive = correspondent.id != null && activeSet.has(correspondent.id);
|
|
const hasHandler = Boolean(onCorrespondentClick) && correspondent.id != null;
|
|
const classNames = ['doc-correspondent-link'];
|
|
if (isActive) classNames.push('is-active');
|
|
if (!hasHandler) classNames.push('is-static');
|
|
const isLast = index === correspondents.length - 1;
|
|
const fallbackLabel = correspondent.name ?? '—';
|
|
const label = isLast ? `${fallbackLabel}:${NBSP}` : fallbackLabel;
|
|
|
|
return (
|
|
<React.Fragment
|
|
key={correspondent.key ?? correspondent.id ?? `${fallbackLabel}-${index}`}
|
|
>
|
|
<button
|
|
type="button"
|
|
className={classNames.join(' ')}
|
|
aria-disabled={hasHandler ? undefined : true}
|
|
onClick={(event) => handleClick(event, correspondent)}
|
|
onKeyDown={(event) => {
|
|
if (!hasHandler) {
|
|
return;
|
|
}
|
|
if (event.key === 'Enter' || event.key === ' ') {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
handleClick(event, correspondent);
|
|
}
|
|
}}
|
|
>
|
|
{label}
|
|
</button>
|
|
{isLast ? null : <span className="doc-correspondent-link__separator">, </span>}
|
|
</React.Fragment>
|
|
);
|
|
});
|
|
};
|
|
|
|
export default CorrespondentLinks;
|