import React, { useEffect, useLayoutEffect, useRef, useState } from 'react'; import { isEqual, truncate } from 'lodash'; import { RecordInstance, AttributeField } from 'wdk-client/Utils/WdkModel'; import { safeHtml, wrappable } from 'wdk-client/Utils/ComponentUtils'; import { Tooltip } from '@veupathdb/components/lib/components/widgets/Tooltip'; import { useIsRefOverflowingHorizontally } from 'wdk-client/Hooks/Overflow'; interface AttributeCellProps { attribute: AttributeField; recordInstance: RecordInstance; } function AttributeCell(props: AttributeCellProps) { const { attribute, recordInstance } = props; const attributeValue = recordInstance.attributes[attribute.name]; const key = typeof attributeValue === 'string' ? attributeValue : attributeValue?.displayText || attributeValue?.url || ''; return ; } function AttributeCellInner({ attribute, recordInstance, }: AttributeCellProps) { const value = recordInstance.attributes[attribute.name]; const defaultStyleSpec: React.CSSProperties = { whiteSpace: 'nowrap', maxWidth: `${attribute.truncateTo}ch`, }; const ref = useRef(null); const [ styleSpec, setStyleSpec ] = useState(defaultStyleSpec); const isOverflowing = useIsRefOverflowingHorizontally(ref); useLayoutEffect(() => { if (!ref.current) return; if ( ref.current.innerText.length > attribute.truncateTo && isEqual(styleSpec, defaultStyleSpec) && isOverflowing ) { setStyleSpec({ ...defaultStyleSpec, overflow: 'hidden', textOverflow: 'ellipsis', }) } }); useEffect(() => { setStyleSpec(defaultStyleSpec) }, [value]); if (value == null) return null; if (typeof value === 'string') { const cellContent = safeHtml(value, { style: styleSpec, ref, }, 'div'); return !('overflow' in styleSpec) ? cellContent : {cellContent} } const { url, displayText } = value; const display = displayText || url; const truncatedDisplay = truncateValue(display, attribute.truncateTo); return (
); } export default wrappable(AttributeCell); function truncateValue(value: string, length: number) { return length ? truncate(value, { length }) : value; }