"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "OverflowContext", { enumerable: true, get: function get() { return _context.OverflowContext; } }); exports.default = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties")); var React = _interopRequireWildcard(require("react")); var _classnames = _interopRequireDefault(require("classnames")); var _rcResizeObserver = _interopRequireDefault(require("rc-resize-observer")); var _useLayoutEffect = _interopRequireDefault(require("rc-util/lib/hooks/useLayoutEffect")); var _Item = _interopRequireDefault(require("./Item")); var _useEffectState11 = _interopRequireWildcard(require("./hooks/useEffectState")); var _RawItem = _interopRequireDefault(require("./RawItem")); var _context = require("./context"); var _excluded = ["prefixCls", "data", "renderItem", "renderRawItem", "itemKey", "itemWidth", "ssr", "style", "className", "maxCount", "renderRest", "renderRawRest", "suffix", "component", "itemComponent", "onVisibleChange"]; function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } var RESPONSIVE = 'responsive'; var INVALIDATE = 'invalidate'; function defaultRenderRest(omittedItems) { return "+ ".concat(omittedItems.length, " ..."); } function Overflow(props, ref) { var _props$prefixCls = props.prefixCls, prefixCls = _props$prefixCls === void 0 ? 'rc-overflow' : _props$prefixCls, _props$data = props.data, data = _props$data === void 0 ? [] : _props$data, renderItem = props.renderItem, renderRawItem = props.renderRawItem, itemKey = props.itemKey, _props$itemWidth = props.itemWidth, itemWidth = _props$itemWidth === void 0 ? 10 : _props$itemWidth, ssr = props.ssr, style = props.style, className = props.className, maxCount = props.maxCount, renderRest = props.renderRest, renderRawRest = props.renderRawRest, suffix = props.suffix, _props$component = props.component, Component = _props$component === void 0 ? 'div' : _props$component, itemComponent = props.itemComponent, onVisibleChange = props.onVisibleChange, restProps = (0, _objectWithoutProperties2.default)(props, _excluded); var fullySSR = ssr === 'full'; var notifyEffectUpdate = (0, _useEffectState11.useBatcher)(); var _useEffectState = (0, _useEffectState11.default)(notifyEffectUpdate, null), _useEffectState2 = (0, _slicedToArray2.default)(_useEffectState, 2), containerWidth = _useEffectState2[0], setContainerWidth = _useEffectState2[1]; var mergedContainerWidth = containerWidth || 0; var _useEffectState3 = (0, _useEffectState11.default)(notifyEffectUpdate, new Map()), _useEffectState4 = (0, _slicedToArray2.default)(_useEffectState3, 2), itemWidths = _useEffectState4[0], setItemWidths = _useEffectState4[1]; var _useEffectState5 = (0, _useEffectState11.default)(notifyEffectUpdate, 0), _useEffectState6 = (0, _slicedToArray2.default)(_useEffectState5, 2), prevRestWidth = _useEffectState6[0], setPrevRestWidth = _useEffectState6[1]; var _useEffectState7 = (0, _useEffectState11.default)(notifyEffectUpdate, 0), _useEffectState8 = (0, _slicedToArray2.default)(_useEffectState7, 2), restWidth = _useEffectState8[0], setRestWidth = _useEffectState8[1]; var _useEffectState9 = (0, _useEffectState11.default)(notifyEffectUpdate, 0), _useEffectState10 = (0, _slicedToArray2.default)(_useEffectState9, 2), suffixWidth = _useEffectState10[0], setSuffixWidth = _useEffectState10[1]; var _useState = (0, React.useState)(null), _useState2 = (0, _slicedToArray2.default)(_useState, 2), suffixFixedStart = _useState2[0], setSuffixFixedStart = _useState2[1]; var _useState3 = (0, React.useState)(null), _useState4 = (0, _slicedToArray2.default)(_useState3, 2), displayCount = _useState4[0], setDisplayCount = _useState4[1]; var mergedDisplayCount = React.useMemo(function () { if (displayCount === null && fullySSR) { return Number.MAX_SAFE_INTEGER; } return displayCount || 0; }, [displayCount, containerWidth]); var _useState5 = (0, React.useState)(false), _useState6 = (0, _slicedToArray2.default)(_useState5, 2), restReady = _useState6[0], setRestReady = _useState6[1]; var itemPrefixCls = "".concat(prefixCls, "-item"); // Always use the max width to avoid blink var mergedRestWidth = Math.max(prevRestWidth, restWidth); // ================================= Data ================================= var isResponsive = maxCount === RESPONSIVE; var shouldResponsive = data.length && isResponsive; var invalidate = maxCount === INVALIDATE; /** * When is `responsive`, we will always render rest node to get the real width of it for calculation */ var showRest = shouldResponsive || typeof maxCount === 'number' && data.length > maxCount; var mergedData = (0, React.useMemo)(function () { var items = data; if (shouldResponsive) { if (containerWidth === null && fullySSR) { items = data; } else { items = data.slice(0, Math.min(data.length, mergedContainerWidth / itemWidth)); } } else if (typeof maxCount === 'number') { items = data.slice(0, maxCount); } return items; }, [data, itemWidth, containerWidth, maxCount, shouldResponsive]); var omittedItems = (0, React.useMemo)(function () { if (shouldResponsive) { return data.slice(mergedDisplayCount + 1); } return data.slice(mergedData.length); }, [data, mergedData, shouldResponsive, mergedDisplayCount]); // ================================= Item ================================= var getKey = (0, React.useCallback)(function (item, index) { var _ref; if (typeof itemKey === 'function') { return itemKey(item); } return (_ref = itemKey && (item === null || item === void 0 ? void 0 : item[itemKey])) !== null && _ref !== void 0 ? _ref : index; }, [itemKey]); var mergedRenderItem = (0, React.useCallback)(renderItem || function (item) { return item; }, [renderItem]); function updateDisplayCount(count, suffixFixedStartVal, notReady) { // React 18 will sync render even when the value is same in some case. // We take `mergedData` as deps which may cause dead loop if it's dynamic generate. // ref: https://github.com/ant-design/ant-design/issues/36559 if (displayCount === count && (suffixFixedStartVal === undefined || suffixFixedStartVal === suffixFixedStart)) { return; } setDisplayCount(count); if (!notReady) { setRestReady(count < data.length - 1); onVisibleChange === null || onVisibleChange === void 0 ? void 0 : onVisibleChange(count); } if (suffixFixedStartVal !== undefined) { setSuffixFixedStart(suffixFixedStartVal); } } // ================================= Size ================================= function onOverflowResize(_, element) { setContainerWidth(element.clientWidth); } function registerSize(key, width) { setItemWidths(function (origin) { var clone = new Map(origin); if (width === null) { clone.delete(key); } else { clone.set(key, width); } return clone; }); } function registerOverflowSize(_, width) { setRestWidth(width); setPrevRestWidth(restWidth); } function registerSuffixSize(_, width) { setSuffixWidth(width); } // ================================ Effect ================================ function getItemWidth(index) { return itemWidths.get(getKey(mergedData[index], index)); } (0, _useLayoutEffect.default)(function () { if (mergedContainerWidth && typeof mergedRestWidth === 'number' && mergedData) { var totalWidth = suffixWidth; var len = mergedData.length; var lastIndex = len - 1; // When data count change to 0, reset this since not loop will reach if (!len) { updateDisplayCount(0, null); return; } for (var i = 0; i < len; i += 1) { var currentItemWidth = getItemWidth(i); // Fully will always render if (fullySSR) { currentItemWidth = currentItemWidth || 0; } // Break since data not ready if (currentItemWidth === undefined) { updateDisplayCount(i - 1, undefined, true); break; } // Find best match totalWidth += currentItemWidth; if ( // Only one means `totalWidth` is the final width lastIndex === 0 && totalWidth <= mergedContainerWidth || // Last two width will be the final width i === lastIndex - 1 && totalWidth + getItemWidth(lastIndex) <= mergedContainerWidth) { // Additional check if match the end updateDisplayCount(lastIndex, null); break; } else if (totalWidth + mergedRestWidth > mergedContainerWidth) { // Can not hold all the content to show rest updateDisplayCount(i - 1, totalWidth - currentItemWidth - suffixWidth + restWidth); break; } } if (suffix && getItemWidth(0) + suffixWidth > mergedContainerWidth) { setSuffixFixedStart(null); } } }, [mergedContainerWidth, itemWidths, restWidth, suffixWidth, getKey, mergedData]); // ================================ Render ================================ var displayRest = restReady && !!omittedItems.length; var suffixStyle = {}; if (suffixFixedStart !== null && shouldResponsive) { suffixStyle = { position: 'absolute', left: suffixFixedStart, top: 0 }; } var itemSharedProps = { prefixCls: itemPrefixCls, responsive: shouldResponsive, component: itemComponent, invalidate: invalidate }; // >>>>> Choice render fun by `renderRawItem` var internalRenderItemNode = renderRawItem ? function (item, index) { var key = getKey(item, index); return /*#__PURE__*/React.createElement(_context.OverflowContext.Provider, { key: key, value: (0, _objectSpread2.default)((0, _objectSpread2.default)({}, itemSharedProps), {}, { order: index, item: item, itemKey: key, registerSize: registerSize, display: index <= mergedDisplayCount }) }, renderRawItem(item, index)); } : function (item, index) { var key = getKey(item, index); return /*#__PURE__*/React.createElement(_Item.default, (0, _extends2.default)({}, itemSharedProps, { order: index, key: key, item: item, renderItem: mergedRenderItem, itemKey: key, registerSize: registerSize, display: index <= mergedDisplayCount })); }; // >>>>> Rest node var restNode; var restContextProps = { order: displayRest ? mergedDisplayCount : Number.MAX_SAFE_INTEGER, className: "".concat(itemPrefixCls, "-rest"), registerSize: registerOverflowSize, display: displayRest }; if (!renderRawRest) { var mergedRenderRest = renderRest || defaultRenderRest; restNode = /*#__PURE__*/React.createElement(_Item.default, (0, _extends2.default)({}, itemSharedProps, restContextProps), typeof mergedRenderRest === 'function' ? mergedRenderRest(omittedItems) : mergedRenderRest); } else if (renderRawRest) { restNode = /*#__PURE__*/React.createElement(_context.OverflowContext.Provider, { value: (0, _objectSpread2.default)((0, _objectSpread2.default)({}, itemSharedProps), restContextProps) }, renderRawRest(omittedItems)); } var overflowNode = /*#__PURE__*/React.createElement(Component, (0, _extends2.default)({ className: (0, _classnames.default)(!invalidate && prefixCls, className), style: style, ref: ref }, restProps), mergedData.map(internalRenderItemNode), showRest ? restNode : null, suffix && /*#__PURE__*/React.createElement(_Item.default, (0, _extends2.default)({}, itemSharedProps, { responsive: isResponsive, responsiveDisabled: !shouldResponsive, order: mergedDisplayCount, className: "".concat(itemPrefixCls, "-suffix"), registerSize: registerSuffixSize, display: true, style: suffixStyle }), suffix)); if (isResponsive) { overflowNode = /*#__PURE__*/React.createElement(_rcResizeObserver.default, { onResize: onOverflowResize, disabled: !shouldResponsive }, overflowNode); } return overflowNode; } var ForwardOverflow = /*#__PURE__*/React.forwardRef(Overflow); ForwardOverflow.displayName = 'Overflow'; ForwardOverflow.Item = _RawItem.default; ForwardOverflow.RESPONSIVE = RESPONSIVE; ForwardOverflow.INVALIDATE = INVALIDATE; // Convert to generic type var _default = ForwardOverflow; exports.default = _default;