UNPKG

vcc-ui

Version:

A React library for building user interfaces at Volvo Cars

275 lines (273 loc) 9.09 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.TabNavContext = exports.TabNav = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _propTypes = _interopRequireDefault(require("prop-types")); var _react = _interopRequireWildcard(require("react")); var _useTheme = require("../../styling/use-theme"); var _block = require("../block"); var _click = require("../click"); var _flex = require("../flex"); var _icon = require("../icon"); var _inline = require("../inline"); var _nav = require("../nav"); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-nocheck const TabNavContext = exports.TabNavContext = /*#__PURE__*/(0, _react.createContext)({}); const styles = { nav: _ref => { let { theme, reverseOut } = _ref; return { flexDirection: 'row', borderBottomStyle: 'solid', borderBottomWidth: 1, borderBottomColor: reverseOut ? theme.color.primitive.grey100 : theme.color.ornament.divider, backgroundColor: reverseOut ? theme.color.primitive.grey100 : theme.color.background.secondary, lineHeight: 1.3 }; }, scrollContainer: { flex: '0 1 auto', overflowY: 'hidden', overflowX: 'auto', msOverflowY: 'hidden', msOverflowX: 'auto', msOverflowStyle: 'none', '::-webkit-scrollbar': { display: 'none' } }, itemContainer: { flexDirection: 'row', padding: '0 0 0 19px', '> button:focus-visible': { outlineOffset: -2 } }, stickyLeft: _ref2 => { let { isCentered } = _ref2; return { flexShrink: 0, flexBasis: 0, flexGrow: isCentered ? 1 : 0, msFlex: '1 0 auto', flexDirection: 'row', justifyContent: 'flex-start', alignItems: 'center' }; }, stickyRight: { flexShrink: 0, flexBasis: 0, flexGrow: 1, msFlex: '1 0 auto', alignItems: 'center', justifyContent: 'flex-end', flexDirection: 'row' }, border: _ref3 => { let { animatedMargin, duration, theme } = _ref3; return { width: 0, height: duration === 0 ? 0 : 3, marginRight: '0 !important', backgroundColor: theme.color.ornament.highlight, transitionProperty: `margin-${animatedMargin}, width`, transitionTimingFunction: 'ease-out', transitionDuration: duration + 'ms' }; }, backButton: _ref4 => { let { reverseOut, showBackButtonOn = [], theme } = _ref4; return { fontSize: 15, padding: '16px 10px 19px', verticalAlign: 'middle', fontWeight: 300, fontFamily: theme.fontTypes.NOVUM, whiteSpace: 'nowrap', flexShrink: '0', color: reverseOut ? theme.color.primitive.white : theme.color.foreground.primary, display: showBackButtonOn.some(size => size === 's') ? 'inline' : 'none', '> img': { marginRight: 8, transitionProperty: 'transform', transitionTimingFunction: 'ease-out', transitionDuration: '0.3s', transform: 'translate(0, 1px)' }, ':hover > img': { transform: 'translate(-5px, 1px)' }, [theme.breakpoints.onlyM]: { display: showBackButtonOn.some(size => size === 'm') ? 'inline' : 'none' }, [theme.breakpoints.fromL]: { display: showBackButtonOn.some(size => size === 'l') ? 'inline' : 'none' } }; }, backButtonText: _ref5 => { let { theme } = _ref5; return { [theme.breakpoints.onlyS]: { display: 'none' } }; } }; function BackButton(_ref6) { let { backButtonConfig = {}, showBackButtonOn, reverseOut } = _ref6; const theme = (0, _useTheme.useTheme)(); const { href, clickHandler, text } = backButtonConfig; const keyboardNavigationProps = (0, _nav.useKeyboardNavigation)(); const styleProps = { theme, reverseOut, showBackButtonOn }; return /*#__PURE__*/_react.default.createElement(_click.Click, (0, _extends2.default)({ onClick: clickHandler ? clickHandler : () => {}, href: href }, keyboardNavigationProps, { extend: styles.backButton(styleProps) }), /*#__PURE__*/_react.default.createElement(_icon.Icon, { type: "navigation-chevronback-12", color: reverseOut ? 'inverted' : 'action' }), /*#__PURE__*/_react.default.createElement(_inline.Inline, { extend: styles.backButtonText }, text || '')); } function TabNavBorder() { const { borderRef, duration } = (0, _react.useContext)(TabNavContext); const theme = (0, _useTheme.useTheme)(); const animatedMargin = theme.direction === 'rtl' ? 'right' : 'left'; return /*#__PURE__*/_react.default.createElement(_block.Block, { ref: borderRef, extend: styles.border({ animatedMargin, duration, theme }) }); } /** * @deprecated Use `<nav>` element instead. See [TabNav](https://developer.volvocars.com/design-system/web/?path=/docs/components-tabs--docs) */ const TabNav = exports.TabNav = /*#__PURE__*/(0, _react.forwardRef)((_ref7, ref) => { let { children, duration = 160, enableLineTransition = false, textAlign = 'center', stickyChildrenLeft = null, stickyChildrenRight = null, showBackButtonOn = ['s', 'm', 'l'], backButton: backButtonConfig = {}, 'aria-label': ariaLabel } = _ref7; const [active, setActive] = (0, _react.useState)(false); const scrollRef = (0, _react.useRef)(null); const borderRef = (0, _react.useRef)(null); const theme = (0, _useTheme.useTheme)(); const isCentered = textAlign === 'center'; const backButtonVisible = !!(backButtonConfig.clickHandler || backButtonConfig.href); const styleProps = { theme, isCentered }; const context = { active, setActive, scrollRef, borderRef, duration: enableLineTransition ? duration : 0 }; return /*#__PURE__*/_react.default.createElement(_flex.Flex, { as: "nav", ref: ref, extend: styles.nav(styleProps) }, /*#__PURE__*/_react.default.createElement(_nav.KeyboardNavigationProvider, null, /*#__PURE__*/_react.default.createElement(_flex.Flex, { extend: styles.stickyLeft(styleProps) }, backButtonVisible ? /*#__PURE__*/_react.default.createElement(BackButton, { backButtonConfig: backButtonConfig, showBackButtonOn: showBackButtonOn }) : null, stickyChildrenLeft), /*#__PURE__*/_react.default.createElement(TabNavContext.Provider, { value: context }, /*#__PURE__*/_react.default.createElement(_flex.Flex, { ref: scrollRef, extend: styles.scrollContainer }, /*#__PURE__*/_react.default.createElement(_flex.Flex, { extend: styles.itemContainer, role: "tablist", "aria-label": ariaLabel }, /*#__PURE__*/_react.default.createElement(_flex.Flex, { extend: { paddingRight: 1 } }), children, /*#__PURE__*/_react.default.createElement(_flex.Flex, { extend: { paddingRight: 1 } })), /*#__PURE__*/_react.default.createElement(TabNavBorder, null))), /*#__PURE__*/_react.default.createElement(_flex.Flex, { extend: styles.stickyRight }, stickyChildrenRight))); }); TabNav.displayName = 'TabNav'; TabNav.propTypes = { /** Text-align: left or center */ textAlign: _propTypes.default.oneOf(['center', 'left']), /** Back button text, href, click handler */ backButton: _propTypes.default.shape({ text: _propTypes.default.string, href: _propTypes.default.string, clickHandler: _propTypes.default.func }), /** A JSX node */ // @ts-ignore children: _propTypes.default.node, /** A JSX node sticky to the left */ // @ts-ignore stickyChildrenLeft: _propTypes.default.node, /** A JSX node sticky to the right */ // @ts-ignore stickyChildrenRight: _propTypes.default.node, /** Which viewports to show the back button on */ showBackButtonOn: _propTypes.default.arrayOf(_propTypes.default.oneOf(['s', 'm', 'l'])), /** Enable fancy transition when changing active tabs */ enableLineTransition: _propTypes.default.bool, /** Set duration of lineTransition animation */ duration: _propTypes.default.number, 'aria-label': _propTypes.default.string };