responsive-breadcrumb
Version:
responsive react breadcrumb
161 lines (148 loc) • 8.85 kB
JavaScript
;
var React = require('react');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
var ELLIPSIS_BUTTON_WIDTH = 40;
var MIN_DISPLAY_WIDTH = 80;
function calcFixedItemWidth(items, parentEleWidth) {
var totalWidth = items.reduce(function (acc, curr) { return acc + curr.width; }, 0);
for (var _i = 0, items_1 = items; _i < items_1.length; _i++) {
var item = items_1[_i];
if (item.width <= MIN_DISPLAY_WIDTH)
continue;
var gap = totalWidth - parentEleWidth;
var reduce = item.width - MIN_DISPLAY_WIDTH;
if (gap > reduce) {
item.idealWidth = MIN_DISPLAY_WIDTH;
totalWidth -= reduce;
if (totalWidth <= parentEleWidth)
break;
}
else {
item.idealWidth = item.width - gap;
break;
}
}
return items;
}
function calcBreadcrumb(items, parentEleWidth) {
var totalWidth = items.reduce(function (acc, curr) { return acc + curr.width; }, 0);
if (totalWidth <= parentEleWidth) {
return items;
}
if (items.length <= 3) {
return calcFixedItemWidth(items, parentEleWidth);
}
var first = items.shift();
var lastOne = items.pop();
var lastTwo = items.pop();
var displayItems = [first, lastTwo, lastOne];
var existWidth = displayItems.reduce(function (acc, curr) { return acc + curr.width; }, 0);
var remaindWidth = parentEleWidth - existWidth - ELLIPSIS_BUTTON_WIDTH;
if (remaindWidth <= 0) {
displayItems = calcFixedItemWidth(displayItems, parentEleWidth - ELLIPSIS_BUTTON_WIDTH);
items.forEach(function (item) { return (item.omit = true); });
return displayItems.concat(items);
}
var totalRestWidth = items.reduce(function (acc, curr) { return acc + curr.width; }, 0);
for (var _i = 0, items_2 = items; _i < items_2.length; _i++) {
var item = items_2[_i];
totalRestWidth -= item.width;
item.omit = true;
if (totalRestWidth <= remaindWidth)
break;
}
return displayItems.concat(items);
}
function styleInject(css, ref) {
if (ref === void 0) ref = {};
var insertAt = ref.insertAt;
if (!css || typeof document === 'undefined') {
return;
}
var head = document.head || document.getElementsByTagName('head')[0];
var style = document.createElement('style');
style.type = 'text/css';
if (insertAt === 'top') {
if (head.firstChild) {
head.insertBefore(style, head.firstChild);
} else {
head.appendChild(style);
}
} else {
head.appendChild(style);
}
if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
}
var css_248z = ".responsive_breadcrumb {\n display: flex;\n align-items: center;\n white-space: nowrap;\n}\n\n.rb_item {\n display: flex;\n align-items: center;\n color: #858e99;\n cursor: pointer;\n}\n\n.rb_item .rb_name {\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.rb_last_item {\n color: #263035;\n cursor: default;\n}\n\n.rb_separator {\n margin: 0 4px;\n}\n\n.rb_omit_wrapper {\n position: relative;\n}\n\n.rb_omit_wrapper:hover .rb_omit_list {\n display: block;\n}\n\n.rb_omit_list {\n display: none;\n position: absolute;\n padding: 4px;\n max-width: 200px;\n white-space: nowrap;\n background-color: #fff;\n box-shadow: 0px 9px 28px 8px rgba(87, 98, 114, 0.05),\n 0px 6px 10px rgba(87, 98, 114, 0.05),\n 0px 3px 6px -4px rgba(87, 98, 114, 0.05);\n border-radius: 4px;\n transform: translate(-50%, 0px);\n animation: raise-up 0.3s;\n}\n\n.rb_omit_item {\n padding: 6px;\n color: #858e99;\n border-radius: 4px;\n cursor: pointer;\n overflow: hidden;\n text-overflow: ellipsis;\n transition: background-color 0.2s;\n}\n\n.rb_omit_item:hover {\n background-color: #f3f4f5;\n}\n\n.clone_list {\n position: fixed;\n top: 99px;\n left: 0;\n /* opacity: 0; */\n}\n\n@keyframes raise-up {\n 0% {\n transform: translate(-50%, -12px) scaleY(0.9);\n }\n}\n";
styleInject(css_248z);
function Breadcrumb(props) {
var className = props.className, items = props.items, _a = props.separator, separator = _a === void 0 ? '>' : _a, onClick = props.onClick;
var clsName = className ? "responsive_breadcrumb ".concat(className) : 'responsive_breadcrumb';
var breadcrumbRef = React.useRef(null);
var cloneListRef = React.useRef(null);
var calcedItemList = React.useRef([]);
var _b = React.useState([]), breadcrumbList = _b[0], setBreadcrumbList = _b[1];
var lastIndex = breadcrumbList.length - 1;
React.useEffect(function () {
cloneListRef.current.style.display = 'flex';
calcedItemList.current = [];
calcBreadcrumbList(items);
}, [items]);
function calcBreadcrumbList(items) {
if (!cloneListRef.current)
return;
var parent = breadcrumbRef.current.parentElement;
var children = cloneListRef.current.children;
var itemDatas = [];
var localItems = items.concat();
for (var i = 0; i < children.length; i++) {
itemDatas.push({ index: i, width: children[i].clientWidth });
}
calcedItemList.current = calcBreadcrumb(itemDatas, parent.clientWidth).sort(function (a, b) { return a.index - b.index; });
if (calcedItemList.current.some(function (item) { return item.omit; })) {
var omitList = calcedItemList.current.filter(function (item) { return item.omit; });
var startIndex = omitList[0].index;
var lastIndex_1 = omitList[omitList.length - 1].index;
localItems.splice(startIndex, lastIndex_1 - startIndex + 1, {
name: '...',
key: 'omit-list',
omitList: localItems.slice(startIndex, lastIndex_1 + 1)
});
calcedItemList.current.splice(startIndex, lastIndex_1 - startIndex + 1, {});
}
setBreadcrumbList(localItems);
cloneListRef.current.style.display = 'none';
}
return (React__default["default"].createElement("div", { className: clsName, ref: breadcrumbRef },
React__default["default"].createElement("div", { className: "".concat(clsName, " clone_list"), ref: cloneListRef }, items.map(function (item, index) {
var key = item.key, name = item.name;
var itemKey = key || name || index;
var isLastItem = index === lastIndex;
return (React__default["default"].createElement("div", { className: isLastItem ? 'rb_item rb_last_item' : 'rb_item', key: itemKey },
React__default["default"].createElement("span", { className: "rb_name" }, name),
isLastItem ? null : React__default["default"].createElement("div", { className: "rb_separator" }, separator)));
})),
breadcrumbList.map(function (item, index) {
var _a;
var key = item.key, name = item.name, omitList = item.omitList;
var itemKey = key || name || index;
var isLastItem = index === lastIndex;
var idealWidth = (_a = calcedItemList.current[index]) === null || _a === void 0 ? void 0 : _a.idealWidth;
if (Array.isArray(omitList)) {
return (React__default["default"].createElement("div", { className: "rb_item", key: itemKey },
React__default["default"].createElement("div", { className: "rb_omit_wrapper" },
React__default["default"].createElement("span", { className: "rb_name" }, name),
React__default["default"].createElement("div", { className: "rb_omit_list" }, omitList.map(function (omitItem) { return (React__default["default"].createElement("div", { className: "rb_omit_item", key: omitItem.key || omitItem.name, title: omitItem.name, onClick: function () { return onClick(omitItem); } }, omitItem.name)); }))),
React__default["default"].createElement("div", { className: "rb_separator" }, separator)));
}
return (React__default["default"].createElement("div", { className: isLastItem ? 'rb_item rb_last_item' : 'rb_item', key: itemKey, title: name, style: idealWidth ? { width: idealWidth } : undefined, onClick: isLastItem ? undefined : function () { return onClick(item); } },
React__default["default"].createElement("span", { className: "rb_name" }, name),
isLastItem ? null : React__default["default"].createElement("div", { className: "rb_separator" }, separator)));
})));
}
module.exports = Breadcrumb;