@lote-design-system/marketing-blocks
Version:
376 lines (336 loc) • 12.5 kB
JavaScript
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;