@digital-ai/plugin-dai-release
Version:
Frontend functionalities for the dai-release backstage plugin
114 lines (111 loc) • 4.15 kB
JavaScript
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