@razorpay/blade
Version:
The Design System that powers Razorpay
143 lines (139 loc) • 6.37 kB
JavaScript
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
import _defineProperty from '@babel/runtime/helpers/defineProperty';
import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties';
import React__default from 'react';
import ReactDOM from 'react-dom';
import { TabNavContext } from './TabNavContext.js';
import { TabNavIndicator } from './TabNavIndicator.web.js';
import { useResize } from '../../../utils/useResize.js';
import '../../Box/BaseBox/index.js';
import '../../Box/styledProps/index.js';
import '../../../utils/metaAttribute/index.js';
import '../../../utils/makeAnalyticsAttribute/index.js';
import { jsx, jsxs } from 'react/jsx-runtime';
import { BaseBox } from '../../Box/BaseBox/BaseBox.web.js';
import { metaAttribute } from '../../../utils/metaAttribute/metaAttribute.web.js';
import { MetaConstants } from '../../../utils/metaAttribute/metaConstants.js';
import { makeAnalyticsAttribute } from '../../../utils/makeAnalyticsAttribute/makeAnalyticsAttribute.js';
import { getStyledProps } from '../../Box/styledProps/getStyledProps.js';
var _excluded = ["children"],
_excluded2 = ["children", "items"];
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
var TabNavItems = function TabNavItems(_ref) {
var children = _ref.children,
rest = _objectWithoutProperties(_ref, _excluded);
return /*#__PURE__*/jsx(BaseBox, _objectSpread(_objectSpread(_objectSpread(_objectSpread({}, rest), {}, {
display: "flex",
width: "100%",
gap: "spacing.0",
position: "relative",
left: "-1px"
}, metaAttribute({
name: MetaConstants.TabNavItems
})), makeAnalyticsAttribute(rest)), {}, {
children: React__default.Children.map(children, function (child, index) {
return /*#__PURE__*/React__default.cloneElement(child, {
__isInsideTabNavItems: true,
__index: index
});
})
}));
};
var TabNav = function TabNav(_ref2) {
var children = _ref2.children,
items = _ref2.items,
rest = _objectWithoutProperties(_ref2, _excluded2);
var ref = React__default.useRef(null);
var itemsRowRef = React__default.useRef(null);
var _React$useState = React__default.useState(items),
_React$useState2 = _slicedToArray(_React$useState, 2),
controlledItems = _React$useState2[0],
setControlledItems = _React$useState2[1];
var overflowingItems = controlledItems.filter(function (item) {
var _item$isAlwaysOverflo;
return (_item$isAlwaysOverflo = item.isAlwaysOverflowing) !== null && _item$isAlwaysOverflo !== void 0 ? _item$isAlwaysOverflo : item.isOverflowing;
});
var _items = controlledItems.filter(function (item) {
return !item.isAlwaysOverflowing && !item.isOverflowing;
});
// We need to memoize this callback otherwise it will cause infinite re-renders
// Because the ResizeObserver callback will be a new reference on every render
// and it will trigger a re-render
var resizeCallback = React__default.useCallback(function (resizeInfo) {
var target = resizeInfo.target;
var updateItems = function updateItems() {
setControlledItems(function (items) {
return items.map(function (item, index) {
// never overflow the first item
if (index === 0) return _objectSpread(_objectSpread({}, item), {}, {
isOverflowing: false
});
// add padding to the offsetX to account the "More" menu's width changing due to the selection state (eg: More:ProdctName)
// Currently, hardcoding this to 150, we can make this dynamic too but that's causing layout thrashing
// because first we need to calculate the width of the "More" menu and then update the items
var padding = 150;
var offset = item.offsetX + padding - target.getBoundingClientRect().left;
if (offset > target.offsetWidth) {
return _objectSpread(_objectSpread({}, item), {}, {
isOverflowing: true
});
} else {
return _objectSpread(_objectSpread({}, item), {}, {
isOverflowing: false
});
}
});
});
};
// https://github.com/webpack/webpack/issues/14814
var flushSync = ReactDOM['flushSync'.toString()];
// Using flushSync to avoid layout thrashing,
// this will force React to flush all pending updates and only then update the DOM
if (flushSync !== undefined) {
flushSync(updateItems);
} else {
updateItems();
}
}, []);
useResize(ref, resizeCallback);
return /*#__PURE__*/jsx(TabNavContext.Provider, {
value: {
containerRef: ref,
controlledItems: controlledItems,
setControlledItems: setControlledItems
},
children: /*#__PURE__*/jsx(BaseBox, _objectSpread(_objectSpread(_objectSpread(_objectSpread({
as: "nav",
display: "flex",
width: "100%",
alignItems: "center",
alignSelf: "center",
position: "relative"
}, getStyledProps(rest)), makeAnalyticsAttribute(rest)), metaAttribute({
name: MetaConstants.TabNav
})), {}, {
ref: ref,
children: /*#__PURE__*/jsx(BaseBox, {
display: "flex",
width: "100%",
position: "relative",
children: /*#__PURE__*/jsxs(BaseBox, {
ref: itemsRowRef,
display: "flex",
flexDirection: "row",
width: "max-content",
position: "relative",
children: [children({
items: _items,
overflowingItems: overflowingItems
}), /*#__PURE__*/jsx(TabNavIndicator, {
containerRef: itemsRowRef
})]
})
})
}))
});
};
export { TabNav, TabNavItems };
//# sourceMappingURL=TabNav.web.js.map