docusaurus/v1/lib/core/nav/SideNav.js
tsmrachel d5fd15ecbe feat: collapsible categories ()
* feat :  Collapsus - The Collapsible Menu

* updated docs

* fixed prettier

* fix for category not auto-expanding upon navigating to a subcategory under it

* as requested by endiliey. Do not merge this commit.

* Update api-site-config.md

* Update guides-navigation.md

* Update SideNav.js

* Update main.css

* Update SideNav.js

* Delete subcategory1.md

* Delete subcategory2.md

* Update sidebars.json
2019-01-23 14:13:27 -08:00

210 lines
6.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Copyright (c) 2017-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const React = require('react');
const classNames = require('classnames');
const siteConfig = require(`${process.cwd()}/siteConfig.js`);
const translation = require('../../server/translation.js');
const {getPath, idx} = require('../utils.js');
class SideNav extends React.Component {
// return appropriately translated category string
getLocalizedCategoryString(category) {
const categoryString =
idx(translation, [
this.props.language,
'localized-strings',
'categories',
category,
]) || category;
return categoryString;
}
// return appropriately translated label to use for doc/blog in sidebar
getLocalizedString(metadata) {
let localizedString;
const i18n = translation[this.props.language];
const id = metadata.localized_id;
const sbTitle = metadata.sidebar_label;
if (sbTitle) {
localizedString =
idx(i18n, ['localized-strings', 'docs', id, 'sidebar_label']) ||
sbTitle;
} else {
localizedString =
idx(i18n, ['localized-strings', 'docs', id, 'title']) || metadata.title;
}
return localizedString;
}
// return link to doc in sidebar
getLink(metadata) {
if (metadata.permalink) {
const targetLink = getPath(metadata.permalink, siteConfig.cleanUrl);
if (targetLink.match(/^https?:/)) {
return targetLink;
}
return siteConfig.baseUrl + targetLink;
}
if (metadata.path) {
return `${siteConfig.baseUrl}blog/${getPath(
metadata.path,
siteConfig.cleanUrl,
)}`;
}
return null;
}
renderCategory = categoryItem => {
let ulClassName = '';
let categoryClassName = 'navGroupCategoryTitle';
let arrow;
if (siteConfig.docsSideNavCollapsible) {
categoryClassName += ' collapsible';
ulClassName = 'hide';
arrow = <span className="arrow">&#8963;</span>;
}
return (
<div className="navGroup" key={categoryItem.title}>
<h3 className={categoryClassName}>
{this.getLocalizedCategoryString(categoryItem.title)}
{arrow}
</h3>
<ul className={ulClassName}>
{categoryItem.children.map(item => {
switch (item.type) {
case 'LINK':
return this.renderItemLink(item);
case 'SUBCATEGORY':
return this.renderSubcategory(item);
default:
return null;
}
})}
</ul>
</div>
);
};
renderSubcategory = subcategoryItem => (
<div className="navGroup subNavGroup" key={subcategoryItem.title}>
<h4 className="navGroupSubcategoryTitle">
{this.getLocalizedCategoryString(subcategoryItem.title)}
</h4>
<ul>{subcategoryItem.children.map(this.renderItemLink)}</ul>
</div>
);
renderItemLink = linkItem => {
const linkMetadata = linkItem.item;
const itemClasses = classNames('navListItem', {
navListItemActive: linkMetadata.id === this.props.current.id,
});
return (
<li className={itemClasses} key={linkMetadata.id}>
<a className="navItem" href={this.getLink(linkMetadata)}>
{this.getLocalizedString(linkMetadata)}
</a>
</li>
);
};
render() {
return (
<nav className="toc">
<div className="toggleNav">
<section className="navWrapper wrapper">
<div className="navBreadcrumb wrapper">
<div className="navToggle" id="navToggler">
<i />
</div>
<h2>
<i></i>
<span>
{this.getLocalizedCategoryString(this.props.current.category)}
</span>
</h2>
{siteConfig.onPageNav === 'separate' && (
<div className="tocToggler" id="tocToggler">
<i className="icon-toc" />
</div>
)}
</div>
<div className="navGroups">
{this.props.contents.map(this.renderCategory)}
</div>
</section>
</div>
<script
dangerouslySetInnerHTML={{
__html: `
var coll = document.getElementsByClassName('collapsible');
var checkActiveCategory = true;
for (var i = 0; i < coll.length; i++) {
var links = coll[i].nextElementSibling.getElementsByTagName('*');
if (checkActiveCategory){
for (var j = 0; j < links.length; j++) {
if (links[j].classList.contains('navListItemActive')){
coll[i].nextElementSibling.classList.toggle('hide');
coll[i].childNodes[1].classList.toggle('rotate');
checkActiveCategory = false;
break;
}
}
}
coll[i].addEventListener('click', function() {
var arrow = this.childNodes[1];
arrow.classList.toggle('rotate');
var content = this.nextElementSibling;
content.classList.toggle('hide');
});
}
document.addEventListener('DOMContentLoaded', function() {
createToggler('#navToggler', '#docsNav', 'docsSliderActive');
createToggler('#tocToggler', 'body', 'tocActive');
const headings = document.querySelector('.toc-headings');
headings && headings.addEventListener('click', function(event) {
if (event.target.tagName === 'A') {
document.body.classList.remove('tocActive');
}
}, false);
function createToggler(togglerSelector, targetSelector, className) {
var toggler = document.querySelector(togglerSelector);
var target = document.querySelector(targetSelector);
if (!toggler) {
return;
}
toggler.onclick = function(event) {
event.preventDefault();
target.classList.toggle(className);
};
}
});
`,
}}
/>
</nav>
);
}
}
SideNav.defaultProps = {
contents: [],
};
module.exports = SideNav;