UNPKG

@lote-design-system/marketing-blocks

Version:
376 lines (336 loc) 12.5 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties"; import _defineProperty from "@babel/runtime/helpers/esm/defineProperty"; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } import React, { useState } from 'react'; import PropTypes from 'prop-types'; import { Transition } from 'react-transition-group'; import styled, { css } from 'styled-components'; import { pick, omit } from 'lodash'; import { rem } from 'polished'; import { Icon } from '@lote-design-system/icons'; import { Container, Button } from '@lote-design-system/core'; import { LogoDefault } from '../svg'; // => Dependent styled-components // Our main component depends upon the following styled-components const NavBar = styled.nav.withConfig({ displayName: "NavBar3__NavBar", componentId: "sc-1jxtonv-0" })(["padding:", " 0;", ";", ";", ";"], rem(16), ({ fixed }) => { if (fixed === 'top') { return css(["position:fixed;top:0;right:0;left:0;z-index:1030;"]); } else if (fixed === 'bottom') { return css(["position:fixed;right:0;bottom:0;left:0;z-index:1030;"]); } else { return css([""]); } }, ({ sticky }) => { if (sticky) { return css(["@supports ((position:-webkit-sticky) or (position:sticky)){position:sticky;top:0;z-index:1020;}"]); } else { return css([""]); } }, ({ styled }) => { if (styled) { return css(["&{", ";}"], styled); } }); const NavBarContainer = styled(Container).withConfig({ displayName: "NavBar3__NavBarContainer", componentId: "sc-1jxtonv-1" })(["max-width:", ";position:relative;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;"], ({ theme }) => theme.maxContainerWidth); const NavBarBrand = styled.a.withConfig({ displayName: "NavBar3__NavBarBrand", componentId: "sc-1jxtonv-2" })(["display:inline-flex;align-items:center;padding:", " 0;white-space:nowrap;margin-right:", ";> svg,> img{width:56px;height:56px;}", "{display:none;}"], rem(4), rem(64), ({ theme }) => theme.mediaQueries.lg); const NavBarButtonToggler = styled(Button).withConfig({ displayName: "NavBar3__NavBarButtonToggler", componentId: "sc-1jxtonv-3" })(["width:48px;height:48px;padding:", " ", ";display:inline-flex;justify-content:center;align-items:center;", "{display:none;}"], rem(4), rem(12), ({ theme }) => theme.mediaQueries.lg); /** * Returns the styles for the container collapsing. * @param timeout {number} - The duration of the transition, in milliseconds. * @return {string[]} - These styles will only apply when the container is collapsing. */ const collapsingStyles = timeout => { return css(["&{position:relative;height:0;overflow:hidden;transition:height ", "s ease;}"], timeout / 1000); }; const NavBarMenu = styled.div.withConfig({ displayName: "NavBar3__NavBarMenu", componentId: "sc-1jxtonv-4" })(["flex-basis:100%;", " flex-grow:1;align-items:center;justify-content:space-between;", "{display:flex;flex-basis:auto;}", ""], '' /* Breaks the justify-content: space-between property. */ , ({ theme }) => theme.mediaQueries.lg, ({ status, timeout }) => { if (status === 'entering') { return css(["", ""], collapsingStyles(timeout)); } else if (status === 'exiting') { return css(["", ""], collapsingStyles(timeout)); } else if (status === 'exited') { return css(["display:none;"]); } }); // NavBarList Section i.e. unordered list display on the left side // ================================================================= // Unordered List const NavBarList = styled.ul.withConfig({ displayName: "NavBar3__NavBarList", componentId: "sc-1jxtonv-5" })(["", " display:flex;", " flex-direction:column;margin-bottom:0;padding-left:0;list-style:none;", "{flex-direction:row;}"], '' /* Main properties */ , '' /* Default it will always vertical */ , ({ theme }) => theme.mediaQueries.lg); // Anchor const NavBarListLink = styled.a.withConfig({ displayName: "NavBar3__NavBarListLink", componentId: "sc-1jxtonv-6" })(["font-size:14px;color:", ";display:block;font-weight:500;padding:8px 16px;transition:color 0.4s linear;:hover{color:", ";}@media (max-width:991px){padding:12px 16px;}"], ({ theme: { colors } }) => colors.text.primary, ({ theme: { colors } }) => colors.primary); // ListItem const NavBarListItem = styled.li.withConfig({ displayName: "NavBar3__NavBarListItem", componentId: "sc-1jxtonv-7" })(["", ";"], props => props.active ? css(["> ", "{color:", ";}"], NavBarListLink, ({ theme: { colors } }) => colors.primary) : css([""])); // End ================================= // NavBarCenterBrand const NavBarCenterBrand = styled.a.withConfig({ displayName: "NavBar3__NavBarCenterBrand", componentId: "sc-1jxtonv-8" })(["color:", ";display:none;align-items:center;padding:", " 0;white-space:nowrap;margin-right:", ";> svg,> img{width:56px;height:56px;}", "{display:inline-flex;}"], ({ theme: { colors } }) => colors.primary, rem(4), rem(64), ({ theme }) => theme.mediaQueries.lg); // <= End Dependent styled-components const linkShape = { id: PropTypes.number.isRequired, href: PropTypes.string.isRequired, text: PropTypes.string.isRequired, active: PropTypes.bool }; const leftLinkSchema = [{ id: 1, href: '/', text: 'Home', active: true }, { id: 2, href: '/', text: 'Features' }, { id: 3, href: '/', text: 'Pricing' }, { id: 4, href: '/', text: 'Services' }]; const rightLinkSchema = [{ id: 1, href: '/', text: 'Sign in' }, { id: 2, href: '/', text: 'Sign up' }, { id: 3, href: '/', text: 'Free Trail' }]; const TransitionPropTypeKeys = ['in', 'mountOnEnter', 'unmountOnExit', 'appear', 'enter', 'exit', 'timeout', 'onEnter', 'onEntering', 'onEntered', 'onExit', 'onExiting', 'onExited']; const propTypes = { /** Render new styles on the NavBar Container. */ styledCSS: PropTypes.string, /** Position an element at the top/bottom of the viewport, from edge to edge. Fixed NavBars use position: fixed, meaning they’re pulled from the normal flow of the DOM and may require custom CSS (e.g., padding-top on the <body>) to prevent overlap with other elements. */ fixed: PropTypes.oneOf(['top', 'bottom']), /** Position an element at the top of the viewport, from edge to edge, but only after you scroll past it. */ sticky: PropTypes.bool, /** The logo appear on the NavBar, default it will be ui-kit logo. */ logo: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), /** Links appear on the left side of the NavBar, same links also render on the Drawer. */ leftLinks: PropTypes.arrayOf(PropTypes.shape(linkShape)).isRequired, /** Links appear on the right side of the NavBar, same links also render on the Drawer. */ rightLinks: PropTypes.arrayOf(PropTypes.shape(linkShape)).isRequired }; const defaultProps = _objectSpread(_objectSpread({}, Transition.defaultProps), {}, { logo: /*#__PURE__*/React.createElement(LogoDefault, { fill: "#01a1ff" }), leftLinks: leftLinkSchema, rightLinks: rightLinkSchema, /* Transition on the first mount set appear to false. */ appear: false, /* Enable enter transitions. */ enter: true, /* Enable exit transitions. */ exit: true, /* The duration of the transition, in milliseconds. */ timeout: 350 }); /** * Returns the height of the node. * @param node {*} - The height of the node you want to get * @return {number} - Returns height of the node */ const getHeight = node => { return node.scrollHeight; }; /** * Returns the JSX or null for the logo. * @param logo {*} - The logo will React.element or a path * @return {null|*} - Returns the JSX or null */ const renderLogo = logo => { if (React.isValidElement(logo)) { return logo; } else if (typeof logo === 'string' && logo.length > 0) { return /*#__PURE__*/React.createElement("img", { src: logo, alt: "Brand Logo" }); } else { return null; } }; /** * Render schema for the NavBar * @param leftData {Array} - Left side schema for the NavBar * @param logo {*} - The logo will React.element or a path * @param rightData {Array} - Right side schema for the NavBar * @return {null|*} */ const renderBody = (leftData, logo, rightData) => { if (Array.isArray(leftData) && leftData.length > 0 && Array.isArray(rightData) && rightData.length > 0) { return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(NavBarList, null, leftData.map(({ id, href, text, active }) => /*#__PURE__*/React.createElement(NavBarListItem, { key: id, active: active }, /*#__PURE__*/React.createElement(NavBarListLink, { href: href }, text)))), /*#__PURE__*/React.createElement(NavBarCenterBrand, { href: "/" }, renderLogo(logo)), /*#__PURE__*/React.createElement(NavBarList, null, rightData.map(({ id, href, text, active }) => /*#__PURE__*/React.createElement(NavBarListItem, { key: id, active: active }, /*#__PURE__*/React.createElement(NavBarListLink, { href: href }, text))))); } else { return null; } }; export const NavBar3 = props => { const [height, setHeight] = useState(null); const [isOpen, setIsOpen] = useState(false); const toggle = () => setIsOpen(!isOpen); const { styledCSS, fixed, sticky, logo: Logo, leftLinks, rightLinks } = props, attributes = _objectWithoutProperties(props, ["styledCSS", "fixed", "sticky", "logo", "leftLinks", "rightLinks"]); const onEntering = (node, isAppearing) => { setHeight(getHeight(node)); props.onEntering(node, isAppearing); }; const onEntered = (node, isAppearing) => { setHeight(null); props.onEntered(node, isAppearing); }; const onExit = node => { setHeight(getHeight(node)); props.onExit(node); }; const onExiting = node => { // getting this variable triggers a reflow const _unused = node.offsetHeight; // eslint-disable-line no-unused-vars setHeight(0); props.onExiting(node); }; const onExited = node => { setHeight(null); props.onExited(node); }; // Get the timeout value const timeout = attributes.timeout; // pick Transition props const transitionProps = pick(attributes, TransitionPropTypeKeys); // remove Transition props const attr = omit(attributes, TransitionPropTypeKeys); const heightVal = height === null ? null : height; return /*#__PURE__*/React.createElement(NavBar, _extends({ styled: styledCSS, fixed: fixed, sticky: sticky }, attr), /*#__PURE__*/React.createElement(NavBarContainer, { fluid: true }, /*#__PURE__*/React.createElement(NavBarBrand, { href: "/" }, renderLogo(Logo)), /*#__PURE__*/React.createElement(NavBarButtonToggler, { basic: true, variation: "primarySubtle", active: isOpen, onClick: toggle }, isOpen ? /*#__PURE__*/React.createElement(Icon, { name: "x" }) : /*#__PURE__*/React.createElement(Icon, { name: "menu" })), /*#__PURE__*/React.createElement(Transition, _extends({}, transitionProps, { in: isOpen, onEntering: onEntering, onEntered: onEntered, onExit: onExit, onExiting: onExiting, onExited: onExited }), status => { return /*#__PURE__*/React.createElement(NavBarMenu, { status: status, timeout: timeout, style: { height: heightVal } }, renderBody(leftLinks, Logo, rightLinks)); }))); }; NavBar3.propTypes = propTypes; NavBar3.defaultProps = defaultProps;