@primer/blueprints
Advanced tools
Comparing version 0.0.0-16066f1 to 0.0.0-1f7e8bb
import React, { useEffect, useState } from 'react'; | ||
import ReactDOM, { findDOMNode } from 'react-dom'; | ||
import { Button, BorderBox, Absolute, Box, StyledOcticon, Relative, Text, Link, Avatar, Flex, Sticky } from '@primer/components'; | ||
import Octicon, { Clippy, getIconByName, MarkGithub, PrimitiveDot, Comment, Info, FileCode, Alert } from '@githubprimer/octicons-react'; | ||
import { Button, BorderBox, Absolute, Box, StyledOcticon, Relative, Text, Link, Avatar, Flex, theme, Sticky } from '@primer/components'; | ||
import Octicon, { Clippy, getIconByName, ChevronDown, MarkGithub, ChevronRight, PrimitiveDot, Comment, Info, FileCode, Alert } from '@githubprimer/octicons-react'; | ||
import getConfig from 'next/config'; | ||
import TreeModel from 'tree-model'; | ||
import { join } from 'path'; | ||
import Measure from 'react-measure'; | ||
@@ -11,7 +12,7 @@ import HTMLtoJSX from 'html-2-jsx'; | ||
import 'prism-github/prism-github.scss'; | ||
import 'prop-types'; | ||
import PropTypes from 'prop-types'; | ||
import styled from 'styled-components'; | ||
import { space, color, themeGet, get } from 'styled-system'; | ||
import NextLink from 'next/link'; | ||
import styled from 'styled-components'; | ||
import { withRouter } from 'next/router'; | ||
import { join } from 'path'; | ||
@@ -413,2 +414,29 @@ function _classCallCheck(instance, Constructor) { | ||
function sortCompare(a, b, get$$1) { | ||
var aa = get$$1(a); | ||
var bb = get$$1(b); | ||
return typeof aa === 'string' && typeof bb === 'string' ? aa.localeCompare(bb) : undefined; | ||
} | ||
function nodeSort(a, b) { | ||
return sortCompare(a, b, function (node) { | ||
return node.meta.sort_title || node.meta.title; | ||
}); | ||
} | ||
function addPath(el, path) { | ||
// if there's no path, just return the element | ||
if (!path) return el; // if this is a link it'll have an "href"; otherwise, add "path" | ||
var prop = el.props.href ? 'href' : 'path'; | ||
var value = el.props[prop]; | ||
var props = {}; // if there's a value and it's not absolute, prefix it with the path | ||
if (value && !value.match(/^(\/|https?:)/)) { | ||
props[prop] = join(path, value); | ||
} else { | ||
props[prop] = path; | ||
} | ||
return React.cloneElement(el, props); | ||
} | ||
var Frame = | ||
@@ -701,2 +729,87 @@ /*#__PURE__*/ | ||
function _templateObject2() { | ||
var data = _taggedTemplateLiteral(["\n ", ";\n ", ";\n"]); | ||
_templateObject2 = function _templateObject2() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
function _templateObject() { | ||
var data = _taggedTemplateLiteral(["\n & > summary {\n list-style: none;\n }\n & > summary::-webkit-details-marker {\n display: none;\n }\n"]); | ||
_templateObject = function _templateObject() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
var DetailsReset = styled('details')(_templateObject()); | ||
function getRenderer(children) { | ||
return typeof children === 'function' ? children : function () { | ||
return children; | ||
}; | ||
} | ||
function DetailsBase(_ref) { | ||
var children = _ref.children, | ||
overlay = _ref.overlay, | ||
_ref$render = _ref.render, | ||
render = _ref$render === void 0 ? getRenderer(children) : _ref$render, | ||
rest = _objectWithoutProperties(_ref, ["children", "overlay", "render"]); | ||
var _useState = useState(Boolean(rest.open)), | ||
_useState2 = _slicedToArray(_useState, 2), | ||
open = _useState2[0], | ||
setOpen = _useState2[1]; | ||
function toggle(event) { | ||
if (event) event.preventDefault(); | ||
if (overlay) { | ||
openMenu(); | ||
} else { | ||
setOpen(!open); | ||
} | ||
} | ||
function openMenu() { | ||
if (!open) { | ||
setOpen(true); | ||
document.addEventListener('click', closeMenu); | ||
} | ||
} | ||
function closeMenu() { | ||
setOpen(false); | ||
document.removeEventListener('click', closeMenu); | ||
} | ||
return React.createElement(DetailsReset, _extends({}, rest, { | ||
open: open, | ||
overlay: overlay | ||
}), render({ | ||
open: open, | ||
toggle: toggle | ||
})); | ||
} | ||
DetailsBase.displayName = "DetailsBase"; | ||
var Details = styled(DetailsBase)(_templateObject2(), space, color); | ||
Details.defaultProps = { | ||
theme: theme, | ||
overlay: false | ||
}; | ||
Details.propTypes = { | ||
children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]), | ||
className: PropTypes.string, | ||
open: PropTypes.bool, | ||
overlay: PropTypes.bool, | ||
render: PropTypes.func, | ||
theme: PropTypes.object | ||
}; | ||
function Link$1(_ref) { | ||
@@ -714,6 +827,76 @@ var href = _ref.href, | ||
function _templateObject() { | ||
var get$1 = function get$$1(key) { | ||
return themeGet(key, get(theme, key)); | ||
}; | ||
var getDirectionStyles = function getDirectionStyles(theme$$1, direction) { | ||
var map = { | ||
w: "\n top: 0;\n right: 100%;\n left: auto;\n width: auto;\n margin-top: 0;\n margin-right: 10px;\n\n &::before {\n top: 10px;\n right: -16px;\n left: auto;\n border-color: transparent;\n border-left-color: ".concat(get$1('colors.blackfade15')(theme$$1), ";\n }\n\n &::after {\n top: 11px;\n right: -14px;\n left: auto;\n border-color: transparent;\n border-left-color: ").concat(get$1('colors.white')(theme$$1), ";\n }\n "), | ||
e: "\n top: 0;\n left: 100%;\n width: auto;\n margin-top: 0;\n margin-left: 10px;\n\n &::before {\n top: 10px;\n left: -16px;\n border-color: transparent;\n border-right-color: ".concat(get$1('colors.blackfade15')(theme$$1), ";\n }\n\n &::after {\n top: 11px;\n left: -14px;\n border-color: transparent;\n border-right-color: ").concat(get$1('colors.white')(theme$$1), ";\n }\n "), | ||
ne: "\n top: auto;\n bottom: 100%;\n left: 0;\n margin-bottom: 3px;\n\n &::before,\n &::after {\n top: auto;\n right: auto;\n }\n\n &::before {\n bottom: -8px;\n left: 9px;\n border-top: 8px solid ".concat(get$1('colors.blackfade15')(theme$$1), ";\n border-bottom: 0;\n border-left: 8px solid transparent;\n }\n\n &::after {\n bottom: -7px;\n left: 10px;\n border-top: 7px solid ").concat(get$1('colors.white')(theme$$1), ";\n border-right: 7px solid transparent;\n border-bottom: 0;\n border-left: 7px solid transparent;\n }\n "), | ||
s: "\n right: 50%;\n left: auto;\n transform: translateX(50%);\n\n &::before {\n top: -16px;\n right: 50%;\n transform: translateX(50%);\n }\n\n &::after {\n top: -14px;\n right: 50%;\n transform: translateX(50%);\n }\n ", | ||
sw: "\n right: 0;\n left: auto;\n\n &::before {\n top: -16px;\n right: 9px;\n left: auto;\n }\n\n &::after {\n top: -14px;\n right: 10px;\n left: auto;\n }\n ", | ||
se: "\n &::before {\n top: -16px;\n left: 9px;\n }\n\n &::after {\n top: -14px;\n left: 10px;\n }\n " | ||
}; | ||
return map[direction]; | ||
}; | ||
function _templateObject$1() { | ||
var data = _taggedTemplateLiteral(["\n color: ", ";\n display: block;\n padding: 0 ", "px;\n line-height: 30px;\n &:hover {\n color: ", ";\n background-color: ", ";\n text-decoration: none;\n }\n &:last-child:hover {\n border-bottom-left-radius: 4px;\n border-bottom-right-radius: 4px;\n }\n &:first-child:hover {\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n }\n"]); | ||
_templateObject$1 = function _templateObject() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
var NavItem = styled(Link)(_templateObject$1(), theme.colors.blue[2], theme.space[3], theme.colors.black, theme.colors.blue[4]); | ||
function _templateObject$2() { | ||
var data = _taggedTemplateLiteral(["\n box-shadow: 0px 4px 12px rgba(27, 31, 35, 0.15);\n border: 1px solid rgba(219, 237, 255, 0.3);\n border-radius: 4px;\n ", ";\n"]); | ||
_templateObject$2 = function _templateObject() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
var DropdownMenu = styled.div(_templateObject$2(), function (props) { | ||
return props.direction ? getDirectionStyles(props.theme, props.direction) : ''; | ||
}); | ||
function NavDropdown(_ref) { | ||
var children = _ref.children, | ||
title = _ref.title, | ||
_ref$direction = _ref.direction, | ||
direction = _ref$direction === void 0 ? 'sw' : _ref$direction; | ||
return React.createElement(Box, null, React.createElement(Details, { | ||
style: { | ||
position: 'relative' | ||
}, | ||
overlay: true, | ||
mx: 3, | ||
render: function render(_ref2) { | ||
var toggle = _ref2.toggle; | ||
return React.createElement(React.Fragment, null, React.createElement(Text, { | ||
fontWeight: "bold", | ||
color: "blue.2", | ||
is: "summary", | ||
onClick: toggle | ||
}, title, " ", React.createElement(StyledOcticon, { | ||
icon: ChevronDown | ||
})), React.createElement(DropdownMenu, { | ||
as: Absolute, | ||
zIndex: 90, | ||
bg: "black", | ||
direction: direction | ||
}, children)); | ||
} | ||
})); | ||
} | ||
NavDropdown.displayName = "NavDropdown"; | ||
function _templateObject$3() { | ||
var data = _taggedTemplateLiteral(["\n box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);\n"]); | ||
_templateObject = function _templateObject() { | ||
_templateObject$3 = function _templateObject() { | ||
return data; | ||
@@ -724,3 +907,3 @@ }; | ||
} | ||
var BoxShadow = styled(Box)(_templateObject()); | ||
var BoxShadow = styled(Box)(_templateObject$3()); | ||
@@ -756,10 +939,19 @@ var HeaderText = function HeaderText(props) { | ||
justifyContent: "center" | ||
}, React.createElement(Octicon, { | ||
}, React.createElement(StyledOcticon, { | ||
color: "blue.4", | ||
icon: MarkGithub, | ||
size: "medium" | ||
}), React.createElement(HeaderText, { | ||
ml: 3 | ||
ml: 3, | ||
color: "blue.4", | ||
fontFamily: "mono" | ||
}, "Primer"), React.createElement(StyledOcticon, { | ||
icon: ChevronRight, | ||
mx: 2, | ||
color: "blue.2" | ||
}), React.createElement(HeaderText, { | ||
fontWeight: "bold" | ||
}, title))), React.createElement(Box, { | ||
display: ['none', 'none', 'block'] | ||
}, React.createElement(HeaderText, null, children)), React.createElement(Box, { | ||
display: ['none', 'none', 'flex'] | ||
}, children), React.createElement(Box, { | ||
display: ['block', 'block', 'none'] | ||
@@ -788,3 +980,3 @@ }, React.createElement(Link$1, { | ||
/** | ||
* The NodeLink component takes an `href` and optional `children`. | ||
* The PageLink component takes an `href` and optional `children`. | ||
* If no `children` are provided, we look up the "node" of the corresponding | ||
@@ -801,11 +993,11 @@ * page in the tree (the one whose `path` matches the given `href`) and use | ||
* | ||
* The following instance of NodeLink should render a link to "/foo/bar" with | ||
* The following instance of PageLink should render a link to "/foo/bar" with | ||
* "Foo Bar" as its text: | ||
* | ||
* ```jsx | ||
* <NodeLink href="/foo/bar" /> | ||
* <PageLink href="/foo/bar" /> | ||
* ``` | ||
*/ | ||
function NodeLink(props) { | ||
function PageLink(props) { | ||
var href = props.href, | ||
@@ -824,19 +1016,92 @@ content = props.children; | ||
} | ||
NodeLink.displayName = "NodeLink"; | ||
PageLink.displayName = "PageLink"; | ||
var NavLink = withRouter(function (_ref) { | ||
var _ref$is = _ref.is, | ||
Tag = _ref$is === void 0 ? NodeLink : _ref$is, | ||
href = _ref.href, | ||
var href = _ref.href, | ||
router = _ref.router, | ||
rest = _objectWithoutProperties(_ref, ["is", "href", "router"]); | ||
rest = _objectWithoutProperties(_ref, ["href", "router"]); | ||
return React.createElement(Tag, _extends({ | ||
return React.createElement(Box, rest, React.createElement(PageLink, _extends({ | ||
href: href, | ||
color: "white", | ||
px: 4, | ||
fontWeight: router.pathname === href ? 'bold' : null | ||
}, rest)); | ||
color: router.pathname === href ? 'black' : undefined, | ||
fontSize: 1 | ||
}, rest))); | ||
}); | ||
/** | ||
* A <Section> gets a `path` and optional children. If it has children it will | ||
* render those and prepend each child's `href` prop with the provided `path`. | ||
* This means that you can do: | ||
* | ||
* ```jsx | ||
* <Section path="/section"> | ||
* <Link href="foo">Links to /section/foo</Link> | ||
* </Section> | ||
* ``` | ||
* | ||
* If no children are provided, it renders a <NavList> with the provided | ||
* `path`. | ||
*/ | ||
var Section = function Section(_ref) { | ||
var path = _ref.path, | ||
children = _ref.children; | ||
return React.createElement(BorderBox, { | ||
p: 5, | ||
border: 0, | ||
borderBottom: 1, | ||
borderRadius: 0, | ||
width: "100%" | ||
}, children && path ? React.Children.map(children, function (child) { | ||
return addPath(child, path); | ||
}) : React.createElement(NavList, { | ||
path: path | ||
})); | ||
}; | ||
Section.displayName = "Section"; | ||
/** | ||
* A <Section.Link> is really just a <PageLink> that's bold when its `href` | ||
* matches the current path, wrapped in a <Box> for whitespace. | ||
*/ | ||
var SectionLink = withRouter(function (_ref2) { | ||
var href = _ref2.href, | ||
router = _ref2.router, | ||
rest = _objectWithoutProperties(_ref2, ["href", "router"]); | ||
return React.createElement(Box, rest, React.createElement(PageLink, _extends({ | ||
href: href | ||
}, rest, { | ||
fontSize: 2, | ||
fontWeight: router.pathname.startsWith(href) ? 'bold' : null | ||
}))); | ||
}); | ||
Section.Link = SectionLink; | ||
/** | ||
* A <NavList> renders a <Section.Link> for the given `path` and looks up the | ||
* path in the page tree. If a node is found, it renders a <NavLink> for each | ||
* of the node's children. | ||
*/ | ||
function NavList(_ref) { | ||
var path = _ref.path; | ||
var node = rootPage.first(function (node) { | ||
return node.path === path; | ||
}); | ||
var children = node ? node.children.sort(nodeSort) : []; | ||
return React.createElement(React.Fragment, null, React.createElement(Section.Link, { | ||
color: "gray.9", | ||
href: path, | ||
mb: 3 | ||
}), children.map(function (child) { | ||
return React.createElement(NavLink, { | ||
mt: 2, | ||
href: child.path, | ||
key: child.path | ||
}); | ||
})); | ||
} | ||
function Outline(_ref) { | ||
@@ -876,6 +1141,6 @@ var outline = _ref.outline, | ||
function _templateObject$1() { | ||
function _templateObject$4() { | ||
var data = _taggedTemplateLiteral(["\n display: inline-block;\n white-space: nowrap;\n"]); | ||
_templateObject$1 = function _templateObject() { | ||
_templateObject$4 = function _templateObject() { | ||
return data; | ||
@@ -886,3 +1151,3 @@ }; | ||
} | ||
var StyledLabel = styled(BorderBox)(_templateObject$1()); | ||
var StyledLabel = styled(BorderBox)(_templateObject$4()); | ||
var STATUS_COLORS = { | ||
@@ -981,108 +1246,24 @@ stable: 'green.6', | ||
function SideNav(props) { | ||
return React.createElement(Relative, { | ||
is: "nav" | ||
}, React.createElement(Box, _extends({ | ||
id: "sidenav" | ||
}, props), React.createElement(Flex, { | ||
flexDirection: "column", | ||
alignItems: "start" | ||
}, React.createElement(Router, null, React.createElement(RouteMatch, { | ||
path: "/blueprints" | ||
}, React.createElement(Section, { | ||
path: "components" | ||
})))))); | ||
} | ||
SideNav.displayName = "SideNav"; | ||
/** | ||
* A <Section> gets a `path` and optional children. If it has children it will | ||
* render those and prepend each child's `href` prop with the provided `path`. | ||
* This means that you can do: | ||
* <RouteMatch> is just a way to conditionally render content without a wrapper | ||
* element when contained directly in a <Router>: | ||
* | ||
* ```jsx | ||
* <Section path="/section"> | ||
* <Link href="foo">Links to /section/foo</Link> | ||
* </Section> | ||
* <Router> | ||
* <RouteMatch path="/some/dir"> | ||
* this will only show up on pages whose path begins with "/some/dir" | ||
* </RouteMatch> | ||
* </Router> | ||
* ``` | ||
* | ||
* If no children are provided, it renders a <NavList> with the provided | ||
* `path`. | ||
*/ | ||
var Section = function Section(_ref) { | ||
function RouteMatch(_ref) { | ||
var path = _ref.path, | ||
children = _ref.children; | ||
return React.createElement(BorderBox, { | ||
p: 5, | ||
border: 0, | ||
borderBottom: 1, | ||
borderRadius: 0, | ||
width: "100%" | ||
}, children && path ? React.Children.map(children, function (child) { | ||
return path ? React.Children.map(children, function (child) { | ||
return addPath(child, path); | ||
}) : React.createElement(NavList, { | ||
path: path | ||
})); | ||
}; | ||
Section.displayName = "Section"; | ||
/** | ||
* A <NavList> renders a <SectionLink> for the given `path` and looks up the | ||
* path in the page tree. If a node is found, it renders a <NavLink> for each | ||
* of the node's children. | ||
*/ | ||
function NavList(_ref2) { | ||
var path = _ref2.path; | ||
var node = rootPage.first(function (node) { | ||
return node.path === path; | ||
}); | ||
var children = node ? node.children.sort(nodeSort) : []; | ||
return React.createElement(React.Fragment, null, React.createElement(SectionLink, { | ||
href: path, | ||
mb: 3 | ||
}), children.map(function (child) { | ||
return React.createElement(NavLink$1, { | ||
href: child.path, | ||
key: child.path | ||
}); | ||
})); | ||
}) : children; | ||
} | ||
/** | ||
* A <SectionLink> is really just a <NodeLink> that's bold when its `href` | ||
* matches the current path, wrapped in a <Box> for whitespace. | ||
*/ | ||
var SectionLink = withRouter(function (_ref3) { | ||
var href = _ref3.href, | ||
router = _ref3.router, | ||
rest = _objectWithoutProperties(_ref3, ["href", "router"]); | ||
return React.createElement(Box, rest, React.createElement(NodeLink, { | ||
href: href, | ||
color: "gray.9", | ||
fontSize: 2, | ||
fontWeight: router.pathname.startsWith(href) ? 'bold' : null | ||
})); | ||
}); | ||
/** | ||
* A <NavLink> is a <NodeLink> that turns black when its `href` matches the | ||
* current path, wrapped in a <Box> for whitespace. | ||
*/ | ||
var NavLink$1 = withRouter(function (_ref4) { | ||
var href = _ref4.href, | ||
router = _ref4.router, | ||
rest = _objectWithoutProperties(_ref4, ["href", "router"]); | ||
return React.createElement(Box, { | ||
mt: 2 | ||
}, React.createElement(NodeLink, _extends({ | ||
href: href, | ||
color: router.pathname === href ? 'black' : undefined, | ||
fontSize: 1 | ||
}, rest))); | ||
}); | ||
/** | ||
* This is inspired by React Router's <Router> component, in that it looks for | ||
@@ -1094,5 +1275,5 @@ * children with the `path` prop and only renders the _first_ one that matches | ||
var Router = withRouter(function (_ref5) { | ||
var router = _ref5.router, | ||
children = _ref5.children; | ||
var Router = withRouter(function (_ref) { | ||
var router = _ref.router, | ||
children = _ref.children; | ||
var matched = false; | ||
@@ -1109,52 +1290,16 @@ return React.Children.toArray(children).map(function (child) { | ||
}); | ||
/** | ||
* <RouteMatch> is just a way to conditionally render content without a wrapper | ||
* element when contained directly in a <Router>: | ||
* | ||
* ```jsx | ||
* <Router> | ||
* <RouteMatch path="/some/dir"> | ||
* this will only show up on pages whose path begins with "/some/dir" | ||
* </RouteMatch> | ||
* </Router> | ||
* ``` | ||
*/ | ||
function RouteMatch(_ref6) { | ||
var path = _ref6.path, | ||
children = _ref6.children; | ||
return path ? React.Children.map(children, function (child) { | ||
return addPath(child, path); | ||
}) : children; | ||
function SideNav(props) { | ||
return React.createElement(Relative, { | ||
is: "nav" | ||
}, React.createElement(Box, _extends({ | ||
id: "sidenav" | ||
}, props), React.createElement(Flex, { | ||
flexDirection: "column", | ||
alignItems: "start" | ||
}, React.createElement(Router, null, props.children)))); | ||
} | ||
function sortCompare(a, b, get) { | ||
var aa = get(a); | ||
var bb = get(b); | ||
return typeof aa === 'string' && typeof bb === 'string' ? aa.localeCompare(bb) : undefined; | ||
} | ||
SideNav.displayName = "SideNav"; | ||
function nodeSort(a, b) { | ||
return sortCompare(a, b, function (node) { | ||
return node.meta.sort_title || node.meta.title; | ||
}); | ||
} | ||
function addPath(el, path) { | ||
// if there's no path, just return the element | ||
if (!path) return el; // if this is a link it'll have an "href"; otherwise, add "path" | ||
var prop = el.props.href ? 'href' : 'path'; | ||
var value = el.props[prop]; | ||
var props = {}; // if there's a value and it's not absolute, prefix it with the path | ||
if (value && !value.match(/^(\/|https?:)/)) { | ||
props[prop] = join(path, value); | ||
} else { | ||
props[prop] = path; | ||
} | ||
return React.cloneElement(el, props); | ||
} | ||
export { ClipboardCopy, CodeExample, Contributors, Frame, Header, Link$1 as Link, NavLink, NodeLink, Outline, PackageHeader, SideNav, StatusLabel, CommonStyles, CommonScripts, config, assetPrefix, assetPath, getAssetPath, requirePage, pathMap, pageTree, rootPage }; | ||
export { ClipboardCopy, CodeExample, Contributors, Details, Frame, Header, Link$1 as Link, NavDropdown, NavItem, NavLink, NavList, Outline, PackageHeader, PageLink, RouteMatch, Router, Section, SideNav, StatusLabel, CommonStyles, CommonScripts, config, assetPrefix, assetPath, getAssetPath, requirePage, pathMap, pageTree, rootPage, sortCompare, nodeSort, addPath }; |
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('react-dom'), require('@primer/components'), require('@githubprimer/octicons-react'), require('next/config'), require('tree-model'), require('react-measure'), require('html-2-jsx'), require('react-live'), require('prism-github/prism-github.scss'), require('prop-types'), require('next/link'), require('styled-components'), require('next/router'), require('path')) : | ||
typeof define === 'function' && define.amd ? define(['exports', 'react', 'react-dom', '@primer/components', '@githubprimer/octicons-react', 'next/config', 'tree-model', 'react-measure', 'html-2-jsx', 'react-live', 'prism-github/prism-github.scss', 'prop-types', 'next/link', 'styled-components', 'next/router', 'path'], factory) : | ||
(factory((global.primer = {}),global.React,global.ReactDOM,global.components,global.Octicon,global.getConfig,global.TreeModel,global.Measure,global.HTMLtoJSX,global.reactLive,null,global.propTypes,global.NextLink,global.styled,global.router,global.path)); | ||
}(this, (function (exports,React,ReactDOM,components,Octicon,getConfig,TreeModel,Measure,HTMLtoJSX,reactLive,prismGithub_scss,propTypes,NextLink,styled,router,path) { 'use strict'; | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('react-dom'), require('@primer/components'), require('@githubprimer/octicons-react'), require('next/config'), require('tree-model'), require('path'), require('react-measure'), require('html-2-jsx'), require('react-live'), require('prism-github/prism-github.scss'), require('prop-types'), require('styled-components'), require('styled-system'), require('next/link'), require('next/router')) : | ||
typeof define === 'function' && define.amd ? define(['exports', 'react', 'react-dom', '@primer/components', '@githubprimer/octicons-react', 'next/config', 'tree-model', 'path', 'react-measure', 'html-2-jsx', 'react-live', 'prism-github/prism-github.scss', 'prop-types', 'styled-components', 'styled-system', 'next/link', 'next/router'], factory) : | ||
(factory((global.primer = {}),global.React,global.ReactDOM,global.components,global.Octicon,global.getConfig,global.TreeModel,global.path,global.Measure,global.HTMLtoJSX,global.reactLive,null,global.PropTypes,global.styled,global.styledSystem,global.NextLink,global.router)); | ||
}(this, (function (exports,React,ReactDOM,components,Octicon,getConfig,TreeModel,path,Measure,HTMLtoJSX,reactLive,prismGithub_scss,PropTypes,styled,styledSystem,NextLink,router) { 'use strict'; | ||
@@ -14,5 +14,5 @@ var React__default = 'default' in React ? React['default'] : React; | ||
HTMLtoJSX = HTMLtoJSX && HTMLtoJSX.hasOwnProperty('default') ? HTMLtoJSX['default'] : HTMLtoJSX; | ||
propTypes = propTypes && propTypes.hasOwnProperty('default') ? propTypes['default'] : propTypes; | ||
PropTypes = PropTypes && PropTypes.hasOwnProperty('default') ? PropTypes['default'] : PropTypes; | ||
styled = styled && styled.hasOwnProperty('default') ? styled['default'] : styled; | ||
NextLink = NextLink && NextLink.hasOwnProperty('default') ? NextLink['default'] : NextLink; | ||
styled = styled && styled.hasOwnProperty('default') ? styled['default'] : styled; | ||
@@ -414,2 +414,29 @@ function _classCallCheck(instance, Constructor) { | ||
function sortCompare(a, b, get) { | ||
var aa = get(a); | ||
var bb = get(b); | ||
return typeof aa === 'string' && typeof bb === 'string' ? aa.localeCompare(bb) : undefined; | ||
} | ||
function nodeSort(a, b) { | ||
return sortCompare(a, b, function (node) { | ||
return node.meta.sort_title || node.meta.title; | ||
}); | ||
} | ||
function addPath(el, path$$1) { | ||
// if there's no path, just return the element | ||
if (!path$$1) return el; // if this is a link it'll have an "href"; otherwise, add "path" | ||
var prop = el.props.href ? 'href' : 'path'; | ||
var value = el.props[prop]; | ||
var props = {}; // if there's a value and it's not absolute, prefix it with the path | ||
if (value && !value.match(/^(\/|https?:)/)) { | ||
props[prop] = path.join(path$$1, value); | ||
} else { | ||
props[prop] = path$$1; | ||
} | ||
return React__default.cloneElement(el, props); | ||
} | ||
var Frame = | ||
@@ -702,2 +729,87 @@ /*#__PURE__*/ | ||
function _templateObject2() { | ||
var data = _taggedTemplateLiteral(["\n ", ";\n ", ";\n"]); | ||
_templateObject2 = function _templateObject2() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
function _templateObject() { | ||
var data = _taggedTemplateLiteral(["\n & > summary {\n list-style: none;\n }\n & > summary::-webkit-details-marker {\n display: none;\n }\n"]); | ||
_templateObject = function _templateObject() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
var DetailsReset = styled('details')(_templateObject()); | ||
function getRenderer(children) { | ||
return typeof children === 'function' ? children : function () { | ||
return children; | ||
}; | ||
} | ||
function DetailsBase(_ref) { | ||
var children = _ref.children, | ||
overlay = _ref.overlay, | ||
_ref$render = _ref.render, | ||
render = _ref$render === void 0 ? getRenderer(children) : _ref$render, | ||
rest = _objectWithoutProperties(_ref, ["children", "overlay", "render"]); | ||
var _useState = React.useState(Boolean(rest.open)), | ||
_useState2 = _slicedToArray(_useState, 2), | ||
open = _useState2[0], | ||
setOpen = _useState2[1]; | ||
function toggle(event) { | ||
if (event) event.preventDefault(); | ||
if (overlay) { | ||
openMenu(); | ||
} else { | ||
setOpen(!open); | ||
} | ||
} | ||
function openMenu() { | ||
if (!open) { | ||
setOpen(true); | ||
document.addEventListener('click', closeMenu); | ||
} | ||
} | ||
function closeMenu() { | ||
setOpen(false); | ||
document.removeEventListener('click', closeMenu); | ||
} | ||
return React__default.createElement(DetailsReset, _extends({}, rest, { | ||
open: open, | ||
overlay: overlay | ||
}), render({ | ||
open: open, | ||
toggle: toggle | ||
})); | ||
} | ||
DetailsBase.displayName = "DetailsBase"; | ||
var Details = styled(DetailsBase)(_templateObject2(), styledSystem.space, styledSystem.color); | ||
Details.defaultProps = { | ||
theme: components.theme, | ||
overlay: false | ||
}; | ||
Details.propTypes = { | ||
children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]), | ||
className: PropTypes.string, | ||
open: PropTypes.bool, | ||
overlay: PropTypes.bool, | ||
render: PropTypes.func, | ||
theme: PropTypes.object | ||
}; | ||
function Link(_ref) { | ||
@@ -715,6 +827,76 @@ var href = _ref.href, | ||
function _templateObject() { | ||
var get = function get(key) { | ||
return styledSystem.themeGet(key, styledSystem.get(components.theme, key)); | ||
}; | ||
var getDirectionStyles = function getDirectionStyles(theme, direction) { | ||
var map = { | ||
w: "\n top: 0;\n right: 100%;\n left: auto;\n width: auto;\n margin-top: 0;\n margin-right: 10px;\n\n &::before {\n top: 10px;\n right: -16px;\n left: auto;\n border-color: transparent;\n border-left-color: ".concat(get('colors.blackfade15')(theme), ";\n }\n\n &::after {\n top: 11px;\n right: -14px;\n left: auto;\n border-color: transparent;\n border-left-color: ").concat(get('colors.white')(theme), ";\n }\n "), | ||
e: "\n top: 0;\n left: 100%;\n width: auto;\n margin-top: 0;\n margin-left: 10px;\n\n &::before {\n top: 10px;\n left: -16px;\n border-color: transparent;\n border-right-color: ".concat(get('colors.blackfade15')(theme), ";\n }\n\n &::after {\n top: 11px;\n left: -14px;\n border-color: transparent;\n border-right-color: ").concat(get('colors.white')(theme), ";\n }\n "), | ||
ne: "\n top: auto;\n bottom: 100%;\n left: 0;\n margin-bottom: 3px;\n\n &::before,\n &::after {\n top: auto;\n right: auto;\n }\n\n &::before {\n bottom: -8px;\n left: 9px;\n border-top: 8px solid ".concat(get('colors.blackfade15')(theme), ";\n border-bottom: 0;\n border-left: 8px solid transparent;\n }\n\n &::after {\n bottom: -7px;\n left: 10px;\n border-top: 7px solid ").concat(get('colors.white')(theme), ";\n border-right: 7px solid transparent;\n border-bottom: 0;\n border-left: 7px solid transparent;\n }\n "), | ||
s: "\n right: 50%;\n left: auto;\n transform: translateX(50%);\n\n &::before {\n top: -16px;\n right: 50%;\n transform: translateX(50%);\n }\n\n &::after {\n top: -14px;\n right: 50%;\n transform: translateX(50%);\n }\n ", | ||
sw: "\n right: 0;\n left: auto;\n\n &::before {\n top: -16px;\n right: 9px;\n left: auto;\n }\n\n &::after {\n top: -14px;\n right: 10px;\n left: auto;\n }\n ", | ||
se: "\n &::before {\n top: -16px;\n left: 9px;\n }\n\n &::after {\n top: -14px;\n left: 10px;\n }\n " | ||
}; | ||
return map[direction]; | ||
}; | ||
function _templateObject$1() { | ||
var data = _taggedTemplateLiteral(["\n color: ", ";\n display: block;\n padding: 0 ", "px;\n line-height: 30px;\n &:hover {\n color: ", ";\n background-color: ", ";\n text-decoration: none;\n }\n &:last-child:hover {\n border-bottom-left-radius: 4px;\n border-bottom-right-radius: 4px;\n }\n &:first-child:hover {\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n }\n"]); | ||
_templateObject$1 = function _templateObject() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
var NavItem = styled(components.Link)(_templateObject$1(), components.theme.colors.blue[2], components.theme.space[3], components.theme.colors.black, components.theme.colors.blue[4]); | ||
function _templateObject$2() { | ||
var data = _taggedTemplateLiteral(["\n box-shadow: 0px 4px 12px rgba(27, 31, 35, 0.15);\n border: 1px solid rgba(219, 237, 255, 0.3);\n border-radius: 4px;\n ", ";\n"]); | ||
_templateObject$2 = function _templateObject() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
var DropdownMenu = styled.div(_templateObject$2(), function (props) { | ||
return props.direction ? getDirectionStyles(props.theme, props.direction) : ''; | ||
}); | ||
function NavDropdown(_ref) { | ||
var children = _ref.children, | ||
title = _ref.title, | ||
_ref$direction = _ref.direction, | ||
direction = _ref$direction === void 0 ? 'sw' : _ref$direction; | ||
return React__default.createElement(components.Box, null, React__default.createElement(Details, { | ||
style: { | ||
position: 'relative' | ||
}, | ||
overlay: true, | ||
mx: 3, | ||
render: function render(_ref2) { | ||
var toggle = _ref2.toggle; | ||
return React__default.createElement(React__default.Fragment, null, React__default.createElement(components.Text, { | ||
fontWeight: "bold", | ||
color: "blue.2", | ||
is: "summary", | ||
onClick: toggle | ||
}, title, " ", React__default.createElement(components.StyledOcticon, { | ||
icon: Octicon.ChevronDown | ||
})), React__default.createElement(DropdownMenu, { | ||
as: components.Absolute, | ||
zIndex: 90, | ||
bg: "black", | ||
direction: direction | ||
}, children)); | ||
} | ||
})); | ||
} | ||
NavDropdown.displayName = "NavDropdown"; | ||
function _templateObject$3() { | ||
var data = _taggedTemplateLiteral(["\n box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);\n"]); | ||
_templateObject = function _templateObject() { | ||
_templateObject$3 = function _templateObject() { | ||
return data; | ||
@@ -725,3 +907,3 @@ }; | ||
} | ||
var BoxShadow = styled(components.Box)(_templateObject()); | ||
var BoxShadow = styled(components.Box)(_templateObject$3()); | ||
@@ -757,10 +939,19 @@ var HeaderText = function HeaderText(props) { | ||
justifyContent: "center" | ||
}, React__default.createElement(Octicon__default, { | ||
}, React__default.createElement(components.StyledOcticon, { | ||
color: "blue.4", | ||
icon: Octicon.MarkGithub, | ||
size: "medium" | ||
}), React__default.createElement(HeaderText, { | ||
ml: 3 | ||
ml: 3, | ||
color: "blue.4", | ||
fontFamily: "mono" | ||
}, "Primer"), React__default.createElement(components.StyledOcticon, { | ||
icon: Octicon.ChevronRight, | ||
mx: 2, | ||
color: "blue.2" | ||
}), React__default.createElement(HeaderText, { | ||
fontWeight: "bold" | ||
}, title))), React__default.createElement(components.Box, { | ||
display: ['none', 'none', 'block'] | ||
}, React__default.createElement(HeaderText, null, children)), React__default.createElement(components.Box, { | ||
display: ['none', 'none', 'flex'] | ||
}, children), React__default.createElement(components.Box, { | ||
display: ['block', 'block', 'none'] | ||
@@ -789,3 +980,3 @@ }, React__default.createElement(Link, { | ||
/** | ||
* The NodeLink component takes an `href` and optional `children`. | ||
* The PageLink component takes an `href` and optional `children`. | ||
* If no `children` are provided, we look up the "node" of the corresponding | ||
@@ -802,11 +993,11 @@ * page in the tree (the one whose `path` matches the given `href`) and use | ||
* | ||
* The following instance of NodeLink should render a link to "/foo/bar" with | ||
* The following instance of PageLink should render a link to "/foo/bar" with | ||
* "Foo Bar" as its text: | ||
* | ||
* ```jsx | ||
* <NodeLink href="/foo/bar" /> | ||
* <PageLink href="/foo/bar" /> | ||
* ``` | ||
*/ | ||
function NodeLink(props) { | ||
function PageLink(props) { | ||
var href = props.href, | ||
@@ -825,19 +1016,92 @@ content = props.children; | ||
} | ||
NodeLink.displayName = "NodeLink"; | ||
PageLink.displayName = "PageLink"; | ||
var NavLink = router.withRouter(function (_ref) { | ||
var _ref$is = _ref.is, | ||
Tag = _ref$is === void 0 ? NodeLink : _ref$is, | ||
href = _ref.href, | ||
var href = _ref.href, | ||
router$$1 = _ref.router, | ||
rest = _objectWithoutProperties(_ref, ["is", "href", "router"]); | ||
rest = _objectWithoutProperties(_ref, ["href", "router"]); | ||
return React__default.createElement(Tag, _extends({ | ||
return React__default.createElement(components.Box, rest, React__default.createElement(PageLink, _extends({ | ||
href: href, | ||
color: "white", | ||
px: 4, | ||
fontWeight: router$$1.pathname === href ? 'bold' : null | ||
}, rest)); | ||
color: router$$1.pathname === href ? 'black' : undefined, | ||
fontSize: 1 | ||
}, rest))); | ||
}); | ||
/** | ||
* A <Section> gets a `path` and optional children. If it has children it will | ||
* render those and prepend each child's `href` prop with the provided `path`. | ||
* This means that you can do: | ||
* | ||
* ```jsx | ||
* <Section path="/section"> | ||
* <Link href="foo">Links to /section/foo</Link> | ||
* </Section> | ||
* ``` | ||
* | ||
* If no children are provided, it renders a <NavList> with the provided | ||
* `path`. | ||
*/ | ||
var Section = function Section(_ref) { | ||
var path$$1 = _ref.path, | ||
children = _ref.children; | ||
return React__default.createElement(components.BorderBox, { | ||
p: 5, | ||
border: 0, | ||
borderBottom: 1, | ||
borderRadius: 0, | ||
width: "100%" | ||
}, children && path$$1 ? React__default.Children.map(children, function (child) { | ||
return addPath(child, path$$1); | ||
}) : React__default.createElement(NavList, { | ||
path: path$$1 | ||
})); | ||
}; | ||
Section.displayName = "Section"; | ||
/** | ||
* A <Section.Link> is really just a <PageLink> that's bold when its `href` | ||
* matches the current path, wrapped in a <Box> for whitespace. | ||
*/ | ||
var SectionLink = router.withRouter(function (_ref2) { | ||
var href = _ref2.href, | ||
router$$1 = _ref2.router, | ||
rest = _objectWithoutProperties(_ref2, ["href", "router"]); | ||
return React__default.createElement(components.Box, rest, React__default.createElement(PageLink, _extends({ | ||
href: href | ||
}, rest, { | ||
fontSize: 2, | ||
fontWeight: router$$1.pathname.startsWith(href) ? 'bold' : null | ||
}))); | ||
}); | ||
Section.Link = SectionLink; | ||
/** | ||
* A <NavList> renders a <Section.Link> for the given `path` and looks up the | ||
* path in the page tree. If a node is found, it renders a <NavLink> for each | ||
* of the node's children. | ||
*/ | ||
function NavList(_ref) { | ||
var path$$1 = _ref.path; | ||
var node = rootPage.first(function (node) { | ||
return node.path === path$$1; | ||
}); | ||
var children = node ? node.children.sort(nodeSort) : []; | ||
return React__default.createElement(React__default.Fragment, null, React__default.createElement(Section.Link, { | ||
color: "gray.9", | ||
href: path$$1, | ||
mb: 3 | ||
}), children.map(function (child) { | ||
return React__default.createElement(NavLink, { | ||
mt: 2, | ||
href: child.path, | ||
key: child.path | ||
}); | ||
})); | ||
} | ||
function Outline(_ref) { | ||
@@ -877,6 +1141,6 @@ var outline = _ref.outline, | ||
function _templateObject$1() { | ||
function _templateObject$4() { | ||
var data = _taggedTemplateLiteral(["\n display: inline-block;\n white-space: nowrap;\n"]); | ||
_templateObject$1 = function _templateObject() { | ||
_templateObject$4 = function _templateObject() { | ||
return data; | ||
@@ -887,3 +1151,3 @@ }; | ||
} | ||
var StyledLabel = styled(components.BorderBox)(_templateObject$1()); | ||
var StyledLabel = styled(components.BorderBox)(_templateObject$4()); | ||
var STATUS_COLORS = { | ||
@@ -982,108 +1246,24 @@ stable: 'green.6', | ||
function SideNav(props) { | ||
return React__default.createElement(components.Relative, { | ||
is: "nav" | ||
}, React__default.createElement(components.Box, _extends({ | ||
id: "sidenav" | ||
}, props), React__default.createElement(components.Flex, { | ||
flexDirection: "column", | ||
alignItems: "start" | ||
}, React__default.createElement(Router, null, React__default.createElement(RouteMatch, { | ||
path: "/blueprints" | ||
}, React__default.createElement(Section, { | ||
path: "components" | ||
})))))); | ||
} | ||
SideNav.displayName = "SideNav"; | ||
/** | ||
* A <Section> gets a `path` and optional children. If it has children it will | ||
* render those and prepend each child's `href` prop with the provided `path`. | ||
* This means that you can do: | ||
* <RouteMatch> is just a way to conditionally render content without a wrapper | ||
* element when contained directly in a <Router>: | ||
* | ||
* ```jsx | ||
* <Section path="/section"> | ||
* <Link href="foo">Links to /section/foo</Link> | ||
* </Section> | ||
* <Router> | ||
* <RouteMatch path="/some/dir"> | ||
* this will only show up on pages whose path begins with "/some/dir" | ||
* </RouteMatch> | ||
* </Router> | ||
* ``` | ||
* | ||
* If no children are provided, it renders a <NavList> with the provided | ||
* `path`. | ||
*/ | ||
var Section = function Section(_ref) { | ||
function RouteMatch(_ref) { | ||
var path$$1 = _ref.path, | ||
children = _ref.children; | ||
return React__default.createElement(components.BorderBox, { | ||
p: 5, | ||
border: 0, | ||
borderBottom: 1, | ||
borderRadius: 0, | ||
width: "100%" | ||
}, children && path$$1 ? React__default.Children.map(children, function (child) { | ||
return path$$1 ? React__default.Children.map(children, function (child) { | ||
return addPath(child, path$$1); | ||
}) : React__default.createElement(NavList, { | ||
path: path$$1 | ||
})); | ||
}; | ||
Section.displayName = "Section"; | ||
/** | ||
* A <NavList> renders a <SectionLink> for the given `path` and looks up the | ||
* path in the page tree. If a node is found, it renders a <NavLink> for each | ||
* of the node's children. | ||
*/ | ||
function NavList(_ref2) { | ||
var path$$1 = _ref2.path; | ||
var node = rootPage.first(function (node) { | ||
return node.path === path$$1; | ||
}); | ||
var children = node ? node.children.sort(nodeSort) : []; | ||
return React__default.createElement(React__default.Fragment, null, React__default.createElement(SectionLink, { | ||
href: path$$1, | ||
mb: 3 | ||
}), children.map(function (child) { | ||
return React__default.createElement(NavLink$1, { | ||
href: child.path, | ||
key: child.path | ||
}); | ||
})); | ||
}) : children; | ||
} | ||
/** | ||
* A <SectionLink> is really just a <NodeLink> that's bold when its `href` | ||
* matches the current path, wrapped in a <Box> for whitespace. | ||
*/ | ||
var SectionLink = router.withRouter(function (_ref3) { | ||
var href = _ref3.href, | ||
router$$1 = _ref3.router, | ||
rest = _objectWithoutProperties(_ref3, ["href", "router"]); | ||
return React__default.createElement(components.Box, rest, React__default.createElement(NodeLink, { | ||
href: href, | ||
color: "gray.9", | ||
fontSize: 2, | ||
fontWeight: router$$1.pathname.startsWith(href) ? 'bold' : null | ||
})); | ||
}); | ||
/** | ||
* A <NavLink> is a <NodeLink> that turns black when its `href` matches the | ||
* current path, wrapped in a <Box> for whitespace. | ||
*/ | ||
var NavLink$1 = router.withRouter(function (_ref4) { | ||
var href = _ref4.href, | ||
router$$1 = _ref4.router, | ||
rest = _objectWithoutProperties(_ref4, ["href", "router"]); | ||
return React__default.createElement(components.Box, { | ||
mt: 2 | ||
}, React__default.createElement(NodeLink, _extends({ | ||
href: href, | ||
color: router$$1.pathname === href ? 'black' : undefined, | ||
fontSize: 1 | ||
}, rest))); | ||
}); | ||
/** | ||
* This is inspired by React Router's <Router> component, in that it looks for | ||
@@ -1095,5 +1275,5 @@ * children with the `path` prop and only renders the _first_ one that matches | ||
var Router = router.withRouter(function (_ref5) { | ||
var router$$1 = _ref5.router, | ||
children = _ref5.children; | ||
var Router = router.withRouter(function (_ref) { | ||
var router$$1 = _ref.router, | ||
children = _ref.children; | ||
var matched = false; | ||
@@ -1110,62 +1290,33 @@ return React__default.Children.toArray(children).map(function (child) { | ||
}); | ||
/** | ||
* <RouteMatch> is just a way to conditionally render content without a wrapper | ||
* element when contained directly in a <Router>: | ||
* | ||
* ```jsx | ||
* <Router> | ||
* <RouteMatch path="/some/dir"> | ||
* this will only show up on pages whose path begins with "/some/dir" | ||
* </RouteMatch> | ||
* </Router> | ||
* ``` | ||
*/ | ||
function RouteMatch(_ref6) { | ||
var path$$1 = _ref6.path, | ||
children = _ref6.children; | ||
return path$$1 ? React__default.Children.map(children, function (child) { | ||
return addPath(child, path$$1); | ||
}) : children; | ||
function SideNav(props) { | ||
return React__default.createElement(components.Relative, { | ||
is: "nav" | ||
}, React__default.createElement(components.Box, _extends({ | ||
id: "sidenav" | ||
}, props), React__default.createElement(components.Flex, { | ||
flexDirection: "column", | ||
alignItems: "start" | ||
}, React__default.createElement(Router, null, props.children)))); | ||
} | ||
function sortCompare(a, b, get) { | ||
var aa = get(a); | ||
var bb = get(b); | ||
return typeof aa === 'string' && typeof bb === 'string' ? aa.localeCompare(bb) : undefined; | ||
} | ||
SideNav.displayName = "SideNav"; | ||
function nodeSort(a, b) { | ||
return sortCompare(a, b, function (node) { | ||
return node.meta.sort_title || node.meta.title; | ||
}); | ||
} | ||
function addPath(el, path$$1) { | ||
// if there's no path, just return the element | ||
if (!path$$1) return el; // if this is a link it'll have an "href"; otherwise, add "path" | ||
var prop = el.props.href ? 'href' : 'path'; | ||
var value = el.props[prop]; | ||
var props = {}; // if there's a value and it's not absolute, prefix it with the path | ||
if (value && !value.match(/^(\/|https?:)/)) { | ||
props[prop] = path.join(path$$1, value); | ||
} else { | ||
props[prop] = path$$1; | ||
} | ||
return React__default.cloneElement(el, props); | ||
} | ||
exports.ClipboardCopy = ClipboardCopy; | ||
exports.CodeExample = CodeExample; | ||
exports.Contributors = Contributors; | ||
exports.Details = Details; | ||
exports.Frame = Frame; | ||
exports.Header = Header; | ||
exports.Link = Link; | ||
exports.NavDropdown = NavDropdown; | ||
exports.NavItem = NavItem; | ||
exports.NavLink = NavLink; | ||
exports.NodeLink = NodeLink; | ||
exports.NavList = NavList; | ||
exports.Outline = Outline; | ||
exports.PackageHeader = PackageHeader; | ||
exports.PageLink = PageLink; | ||
exports.RouteMatch = RouteMatch; | ||
exports.Router = Router; | ||
exports.Section = Section; | ||
exports.SideNav = SideNav; | ||
@@ -1183,2 +1334,5 @@ exports.StatusLabel = StatusLabel; | ||
exports.rootPage = rootPage; | ||
exports.sortCompare = sortCompare; | ||
exports.nodeSort = nodeSort; | ||
exports.addPath = addPath; | ||
@@ -1185,0 +1339,0 @@ Object.defineProperty(exports, '__esModule', { value: true }); |
{ | ||
"name": "@primer/blueprints", | ||
"version": "0.0.0-16066f1", | ||
"version": "0.0.0-1f7e8bb", | ||
"description": "Components for GitHub Documentation Sites", | ||
@@ -35,3 +35,3 @@ "main": "dist/index.umd.js", | ||
"@mdx-js/tag": "0.15.0", | ||
"@primer/components": "^8.2.0-beta", | ||
"@primer/components": "11.0.0", | ||
"@svgr/webpack": "2.4.1", | ||
@@ -86,3 +86,4 @@ "@zeit/next-css": "^1.0.1", | ||
"sass.macro": "0.1.0", | ||
"styled-components": "^4.1.2", | ||
"styled-system": "4.0.4", | ||
"styled-components": "4.1.3", | ||
"title-case": "^2.1.1", | ||
@@ -89,0 +90,0 @@ "tree-model": "^1.0.7", |
export {default as ClipboardCopy} from './ClipboardCopy' | ||
export {default as CodeExample} from './CodeExample' | ||
export {default as Contributors} from './Contributors' | ||
export {default as Details} from './Details' | ||
export {default as Frame} from './Frame' | ||
export {default as Header} from './Header' | ||
export {default as Link} from './Link' | ||
export {default as NavDropdown} from './NavDropdown' | ||
export {default as NavItem} from './NavItem' | ||
export {default as NavLink} from './NavLink' | ||
export {default as NodeLink} from './NodeLink' | ||
export {default as NavList} from './NavList' | ||
export {default as Outline} from './Outline' | ||
export {default as PackageHeader} from './PackageHeader' | ||
export {default as PageLink} from './PageLink' | ||
export {default as RouteMatch} from './RouteMatch' | ||
export {default as Router} from './Router' | ||
export {default as Section} from './Section' | ||
export {default as SideNav} from './SideNav' | ||
export {default as StatusLabel} from './StatusLabel' |
@@ -0,1 +1,6 @@ | ||
import {themeGet, get as getKey} from 'styled-system' | ||
import {theme} from '@primer/components' | ||
export const get = key => themeGet(key, getKey(theme, key)) | ||
export const CONTENT_MAX_WIDTH = 1012 |
import React from 'react' | ||
import PropTypes from 'prop-types' | ||
import styled from 'styled-components' | ||
import Octicon, {MarkGithub} from '@githubprimer/octicons-react' | ||
import {Text, Flex, Sticky, BorderBox, Box} from '@primer/components' | ||
import {MarkGithub, ChevronRight} from '@githubprimer/octicons-react' | ||
import {Text, Flex, Sticky, BorderBox, Box, StyledOcticon} from '@primer/components' | ||
import Link from './Link' | ||
import NavDropdown from './NavDropdown' | ||
@@ -20,8 +21,10 @@ const BoxShadow = styled(Box)` | ||
<Flex alignItems="center" justifyContent="center"> | ||
<Octicon icon={MarkGithub} size="medium" /> | ||
<HeaderText ml={3}>{title}</HeaderText> | ||
<StyledOcticon color='blue.4' icon={MarkGithub} size="medium" /> | ||
<HeaderText ml={3} color='blue.4' fontFamily='mono'>Primer</HeaderText> | ||
<StyledOcticon icon={ChevronRight} mx={2} color='blue.2'/> | ||
<HeaderText fontWeight='bold'>{title}</HeaderText> | ||
</Flex> | ||
</Link> | ||
<Box display={['none', 'none', 'block']}> | ||
<HeaderText>{children}</HeaderText> | ||
<Box display={['none', 'none', 'flex']}> | ||
{children} | ||
</Box> | ||
@@ -28,0 +31,0 @@ <Box display={['block', 'block', 'none']}> |
import React from 'react' | ||
import {withRouter} from 'next/router' | ||
import NodeLink from './NodeLink' | ||
import {Box} from '@primer/components' | ||
import PageLink from './PageLink' | ||
export default withRouter(({is: Tag = NodeLink, href, router, ...rest}) => ( | ||
<Tag href={href} color="white" px={4} fontWeight={router.pathname === href ? 'bold' : null} {...rest} /> | ||
)) | ||
const NavLink = withRouter(({href, router, ...rest}) => { | ||
return ( | ||
<Box {...rest}> | ||
<PageLink href={href} color={router.pathname === href ? 'black' : undefined} fontSize={1} {...rest} /> | ||
</Box> | ||
) | ||
}) | ||
export default NavLink |
import React from 'react' | ||
import {join} from 'path' | ||
import {withRouter} from 'next/router' | ||
import {Box, BorderBox, Flex, Relative} from '@primer/components' | ||
import NodeLink from './NodeLink' | ||
import {rootPage} from './utils' | ||
import {Box, Flex, Relative} from '@primer/components' | ||
import Router from './Router' | ||
export default function SideNav(props) { | ||
function SideNav(props) { | ||
return ( | ||
@@ -13,7 +10,3 @@ <Relative is="nav"> | ||
<Flex flexDirection="column" alignItems="start"> | ||
<Router> | ||
<RouteMatch path="/blueprints"> | ||
<Section path="components" /> | ||
</RouteMatch> | ||
</Router> | ||
<Router>{props.children}</Router> | ||
</Flex> | ||
@@ -25,122 +18,2 @@ </Box> | ||
/** | ||
* A <Section> gets a `path` and optional children. If it has children it will | ||
* render those and prepend each child's `href` prop with the provided `path`. | ||
* This means that you can do: | ||
* | ||
* ```jsx | ||
* <Section path="/section"> | ||
* <Link href="foo">Links to /section/foo</Link> | ||
* </Section> | ||
* ``` | ||
* | ||
* If no children are provided, it renders a <NavList> with the provided | ||
* `path`. | ||
*/ | ||
const Section = ({path, children}) => ( | ||
<BorderBox p={5} border={0} borderBottom={1} borderRadius={0} width="100%"> | ||
{children && path ? React.Children.map(children, child => addPath(child, path)) : <NavList path={path} />} | ||
</BorderBox> | ||
) | ||
/** | ||
* A <NavList> renders a <SectionLink> for the given `path` and looks up the | ||
* path in the page tree. If a node is found, it renders a <NavLink> for each | ||
* of the node's children. | ||
*/ | ||
function NavList({path}) { | ||
const node = rootPage.first(node => node.path === path) | ||
const children = node ? node.children.sort(nodeSort) : [] | ||
return ( | ||
<> | ||
<SectionLink href={path} mb={3} /> | ||
{children.map(child => ( | ||
<NavLink href={child.path} key={child.path} /> | ||
))} | ||
</> | ||
) | ||
} | ||
/** | ||
* A <SectionLink> is really just a <NodeLink> that's bold when its `href` | ||
* matches the current path, wrapped in a <Box> for whitespace. | ||
*/ | ||
const SectionLink = withRouter(({href, router, ...rest}) => ( | ||
<Box {...rest}> | ||
<NodeLink href={href} color="gray.9" fontSize={2} fontWeight={router.pathname.startsWith(href) ? 'bold' : null} /> | ||
</Box> | ||
)) | ||
/** | ||
* A <NavLink> is a <NodeLink> that turns black when its `href` matches the | ||
* current path, wrapped in a <Box> for whitespace. | ||
*/ | ||
const NavLink = withRouter(({href, router, ...rest}) => { | ||
return ( | ||
<Box mt={2}> | ||
<NodeLink href={href} color={router.pathname === href ? 'black' : undefined} fontSize={1} {...rest} /> | ||
</Box> | ||
) | ||
}) | ||
/** | ||
* This is inspired by React Router's <Router> component, in that it looks for | ||
* children with the `path` prop and only renders the _first_ one that matches | ||
* the beginning of the current path. Children without a `path` prop are always | ||
* rendered. | ||
*/ | ||
const Router = withRouter(({router, children}) => { | ||
let matched = false | ||
return React.Children.toArray(children).map(child => { | ||
if (child.props.path) { | ||
if (!matched && router.pathname.indexOf(child.props.path) === 0) { | ||
return (matched = child) | ||
} | ||
} else { | ||
return child | ||
} | ||
}) | ||
}) | ||
/** | ||
* <RouteMatch> is just a way to conditionally render content without a wrapper | ||
* element when contained directly in a <Router>: | ||
* | ||
* ```jsx | ||
* <Router> | ||
* <RouteMatch path="/some/dir"> | ||
* this will only show up on pages whose path begins with "/some/dir" | ||
* </RouteMatch> | ||
* </Router> | ||
* ``` | ||
*/ | ||
function RouteMatch({path, children}) { | ||
return path ? React.Children.map(children, child => addPath(child, path)) : children | ||
} | ||
function sortCompare(a, b, get) { | ||
const aa = get(a) | ||
const bb = get(b) | ||
return typeof aa === 'string' && typeof bb === 'string' ? aa.localeCompare(bb) : undefined | ||
} | ||
function nodeSort(a, b) { | ||
return sortCompare(a, b, node => node.meta.sort_title || node.meta.title) | ||
} | ||
function addPath(el, path) { | ||
// if there's no path, just return the element | ||
if (!path) return el | ||
// if this is a link it'll have an "href"; otherwise, add "path" | ||
const prop = el.props.href ? 'href' : 'path' | ||
const value = el.props[prop] | ||
const props = {} | ||
// if there's a value and it's not absolute, prefix it with the path | ||
if (value && !value.match(/^(\/|https?:)/)) { | ||
props[prop] = join(path, value) | ||
} else { | ||
props[prop] = path | ||
} | ||
return React.cloneElement(el, props) | ||
} | ||
export default SideNav |
import React from 'react' | ||
import getConfig from 'next/config' | ||
import TreeModel from 'tree-model' | ||
import {join} from 'path' | ||
@@ -88,1 +89,28 @@ export const CommonStyles = () => { | ||
} | ||
export function sortCompare(a, b, get) { | ||
const aa = get(a) | ||
const bb = get(b) | ||
return typeof aa === 'string' && typeof bb === 'string' ? aa.localeCompare(bb) : undefined | ||
} | ||
export function nodeSort(a, b) { | ||
return sortCompare(a, b, node => node.meta.sort_title || node.meta.title) | ||
} | ||
export function addPath(el, path) { | ||
// if there's no path, just return the element | ||
if (!path) return el | ||
// if this is a link it'll have an "href"; otherwise, add "path" | ||
const prop = el.props.href ? 'href' : 'path' | ||
const value = el.props[prop] | ||
const props = {} | ||
// if there's a value and it's not absolute, prefix it with the path | ||
if (value && !value.match(/^(\/|https?:)/)) { | ||
props[prop] = join(path, value) | ||
} else { | ||
props[prop] = path | ||
} | ||
return React.cloneElement(el, props) | ||
} |
116234
30
3301
62