UNPKG

@digital-ai/plugin-dai-release

Version:

Frontend functionalities for the dai-release backstage plugin

114 lines (111 loc) 4.15 kB
import { DotChip, DotTooltip } from '@digital-ai/dot-components'; import React, { useRef, useState, useLayoutEffect } from 'react'; import { debounce } from 'lodash'; import { makeStyles } from '@material-ui/core'; const useStyles = makeStyles((theme) => ({ chipGroup: { display: "flex", gap: theme.spacing(1), width: "100%", "& .hidden-chip": { display: "none" } }, roundCorner: { borderRadius: "4px" }, ellipsis: { display: "inline-block", textOverflow: "ellipsis", whiteSpace: "nowrap", overflow: "hidden" } })); const useChipGroup = (exceedingChipsCountRef, elementsRef, containerRef) => { const [chipWidths, setChipWidths] = useState([]); const [containerWidth, setContainerWidth] = useState(0); const chipCounterWidth = exceedingChipsCountRef.current?.getBoundingClientRect().width || 0; useLayoutEffect(() => { const width = elementsRef.current.map( (el) => el.getBoundingClientRect().width ); setChipWidths(width); }, [elementsRef]); useLayoutEffect(() => { if (!containerRef.current) return () => { }; const handleResize = (width) => setContainerWidth(width); const handleDebounce = debounce(handleResize, 100); const observer = new ResizeObserver((entries) => { handleDebounce(entries[0].target.getBoundingClientRect().width); }); observer.observe(containerRef.current); return () => { observer.disconnect(); handleDebounce.cancel(); }; }, [containerRef]); return { chipWidths, containerWidth, chipCounterWidth }; }; const ChipGroup = ({ chipCharactersLimit, labels }) => { const containerRef = useRef(null); const exceedingChipsCountRef = useRef(null); const elementsRef = useRef([]); const classes = useStyles(); const { chipWidths, containerWidth, chipCounterWidth } = useChipGroup( exceedingChipsCountRef, elementsRef, containerRef ); const exceedingWidthChips = []; let remainingContainerWidth = containerWidth; const calculateGapWidth = (index, counterWidth) => { const isLastVisibleItem = index >= chipWidths.length - exceedingWidthChips.length - 1; const isChipCounterVisible = counterWidth > 0; return isLastVisibleItem && !isChipCounterVisible ? 0 : 8; }; chipWidths.forEach((width, index) => { const gapWidth = calculateGapWidth(index, chipCounterWidth); const totalTakenWidth = width + gapWidth; const isExceedingWidth = totalTakenWidth > remainingContainerWidth - chipCounterWidth; if (isExceedingWidth && index > 0) { exceedingWidthChips.push({ index, label: labels[index] }); } else { remainingContainerWidth -= totalTakenWidth; } }); const getTooltipWithExceedingChips = () => { return /* @__PURE__ */ React.createElement(React.Fragment, null, exceedingWidthChips.map((chip) => /* @__PURE__ */ React.createElement("div", { key: chip.label }, chip.label, /* @__PURE__ */ React.createElement("br", null)))); }; return /* @__PURE__ */ React.createElement("div", { className: classes.chipGroup, ref: containerRef }, labels.map((label, index) => { return /* @__PURE__ */ React.createElement( "span", { className: exceedingWidthChips.some( (exceedingChip) => exceedingChip.index === index ) ? "hidden-chip" : void 0, "data-testid": "chip-group-span", key: label, ref: (element) => { if (element !== null) { elementsRef.current[index] = element; } } }, /* @__PURE__ */ React.createElement(DotChip, { charactersLimit: chipCharactersLimit, size: "small" }, label) ); }), exceedingWidthChips.length > 0 && /* @__PURE__ */ React.createElement( "span", { "data-testid": "exceeding-width-chip-span", ref: exceedingChipsCountRef }, /* @__PURE__ */ React.createElement(DotTooltip, { title: getTooltipWithExceedingChips() }, /* @__PURE__ */ React.createElement(DotChip, { size: "small" }, `+${exceedingWidthChips.length.toString()}`)) )); }; export { ChipGroup, useChipGroup }; //# sourceMappingURL=ChipGroupComponent.esm.js.map