pure-styled-components
Version:
Styled Component design system based on Pure CSS for React/Preact
178 lines (154 loc) • 4.06 kB
JavaScript
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
import React, { PureComponent } from "react";
import PropTypes from "prop-types";
import styled from "styled-components";
import findByType from "../../utils/findByType";
import Item from "./Item";
const scrollableHorizontal = (isScrollable, isHorizontal) => {
if (isScrollable && isHorizontal) {
return `
white-space: nowrap;
overflow-y: hidden;
overflow-x: auto;
-ms-overflow-style: none;
-webkit-overflow-scrolling: touch;
/* a little extra padding for this style to allow for scrollbars */
padding: .5em 0;
::-webkit-scrollbar {
display: none;
}
& .list {
display: inline-block;
}
`;
}
return ``;
};
const horizontalMenu = isHorizontal => {
if (isHorizontal) {
return `
width: 100%;
white-space: nowrap;
& .list {
display: inline-block;
}
/* Initial menus should be inline-block so that they are horizontal */
& .item,
& .heading,
& .separator {
display: inline-block;
*display: inline;
zoom: 1;
vertical-align: middle;
}
& .separator {
width: 1px;
height: 1.3em;
margin: 0 .3em;
}
& .dropdown {
left: 0;
top: auto;
width: inherit;
}
`;
}
return ``;
};
const selectedMenu = isSelected => {
if (isSelected) {
return `
& > .link {
color: #000;
}
`;
}
return ``;
};
const Heading = styled.span`
display: block;
text-decoration: none;
white-space: nowrap;
text-transform: uppercase;
color: #565d64;
padding: 0.5em 1em;
`;
const List = styled.ul`
list-style: none;
margin: 0;
padding: 0;
`;
class BaseMenu extends PureComponent {
renderMenu() {
const {
children
} = this.props;
const listType = [List.displayName] || [List.name];
const headingType = [Heading.displayName] || [Heading.name];
const items = React.Children.map(children, child => {
const childType = child && child.type && (child.type.displayName || child.type.name);
if (childType.includes(listType)) {
return child.props.children.map(item => React.createElement(Item, {
className: "item",
key: item.props.children
}, item.props.children));
}
if (childType.includes(headingType)) {
return React.createElement(Heading, {
className: "heading"
}, child.props.children);
}
});
if (!items) {
return null;
}
return React.createElement(List, {
className: "list"
}, items);
}
render() {
const {
className
} = this.props;
return React.createElement("nav", _extends({
className: className
}, this.props), this.renderMenu());
}
}
BaseMenu.Heading = Heading;
BaseMenu.List = List;
BaseMenu.Item = Item;
/**
* Simple CSS and React for menus. See <List.Heading> and <List.Item>.
*
* @visibleName Menu
*/
const Menu = styled(BaseMenu)`
box-sizing: border-box;
position: relative;
&.separator {
background-color: #ccc;
height: 1px;
margin: 0.3em 0;
}
${props => horizontalMenu(props.horizontal)};
${props => selectedMenu(props.selected)};
${props => scrollableHorizontal(props.selected, props.horizontal)};
`;
Menu.propTypes = {
/**
* Makes menu items display horizontal (inline)
*/
horizontal: PropTypes.bool,
/**
* Makes menu items appear selected
*/
selected: PropTypes.bool,
/**
* Child components (array or single element)
*/
children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired
};
/** @component */
export default Menu;
//# sourceMappingURL=Menu.js.map