import { siteConfig } from 'site/site.config.mjs' import { useContext } from 'react' import { NavigationContext } from 'shared/context/navigation-context.mjs' import { pageHasChildren, isSlugPart } from 'shared/utils.mjs' import get from 'lodash.get' import { HomeIcon, RightIcon, BulletIcon } from 'shared/components/icons.mjs' import { Link, PageLink } from 'shared/components/link.mjs' import orderBy from 'lodash.orderby' import { icons } from 'shared/components/navigation/primary.mjs' import { useTranslation } from 'next-i18next' export const ns = ['sections'] /* * This returns only those children that are expected to show up * in the side navigation. Specifically: * - Key length needs to be longer than 1 * - Child pages cannot have m or h set (main section or hidden) * - Title may not be 'spacer' (header spacer) * * It also takes care of ordering them, and returns an array * * @params tree {object} - A navigation object as returned by useNavigation => siteNav */ const onlyValidChildren = (tree) => orderBy(tree, ['o', 't'], ['asc', 'asc']).filter( (entry) => typeof entry === 'object' && entry.t !== 'spacer' && !entry.m && !entry._ && !entry.h ) /* * This returns only those children that are main sections. Specifically: * - Key length needs to be longer than 1 * - Child pages cannot have m set (main section) * - Title may not be 'spacer' (header spacer) * * It also takes care of ordering them, and returns an array * * @params tree {object} - A navigation object as returned by useNavigation => siteNav */ const onlyMainSections = (tree) => orderBy(tree, ['o', 't'], ['asc', 'asc']).filter((entry) => entry.m) const SectionLink = ({ skey, tree, slug }) => tree[skey]._ ? null : tree[skey].s === slug ? ( // Underscore means always hide <> {tree[skey].t} {pageHasChildren(tree[skey]) &&
} ) : isSlugPart(tree[skey].s, slug) ? ( <> {tree[skey].t} {pageHasChildren(tree[skey]) &&
} ) : ( {tree[skey].t} ) /* * A React component to render a section of the navigation * * @param t {string} - The section title * @param s {string} - The section slug * @param tree {object} - The object describing any futher child pages * @param slug {string} - The slug of the currently active/viewed page */ const Section = ({ tree, // Object with the navigation slug, // Slug of the current page (used to make links active) }) => ( ) /* * A React component to render a main link navigation * * @param t {string} - The section title * @param s {string} - The section slug */ const MainLink = ({ t, // The link title/text s, // The link slug slug, // The current page slug }) => { const classes = '' + 'break-all py-2 px-2 block w-full font-bold text-lg ' + 'flex flex-row items-start gap-0.5 lg:gap-1 border-l-2' return s === slug ? ( {t} ) : ( {t} ) } /* * A React component to render breadcrumbs to the current page * * @param lead {string} - A lead to display before the cumbs (eg: You are here) */ export const Breadcrumbs = ({ lead = false }) => { // Grab siteNav and slug from the navigation context const { siteNav, slug } = useContext(NavigationContext) const { t } = useTranslation(['common']) if (slug === false) { console.log('No slug passed to Breadcrumbs') return null } // Start with the home crumb const crumbs = [] // Do we need a lead? if (lead) crumbs.push(
  • {t('youAreHere')}:
  • ) crumbs.push(
  • ) // Home page? if (slug === '') return // Then split the slug and add a crumb for each const chunks = slug.split('/') for (let i = 1; i <= chunks.length; i++) { const page = get(siteNav, chunks.slice(0, i)) if (page) { crumbs.push(
  • , i === chunks.length ? (
  • {page.t}
  • ) : (
  • ) ) } } return } /* * A React component to render sidebar navigation based on the siteNav object and current slug * * The main sections are determined in the navigation prebuild code. * We always display the navigation as: * - Always show all top-level entries * - Always show all direct children of all top-level entries (this allows for better discoverability) * - If we're deeper down, only expand the active page */ export const NavLinks = () => { // Grab siteNav and slug from the navigation context const { siteNav, slug } = useContext(NavigationContext) let subtree = siteNav /* * FreeSewing.org has a lot of content, especially the design docs get nested rather deep * So we trim the navigation tree so that the designs content is not overwhelming */ if (siteConfig.tld === 'org') { const chunks = slug.split('/') if (chunks[0] === 'docs') { if (chunks.length > 3) { if (chunks[1] === 'designs') subtree = siteNav.docs.designs[chunks[2]] } // If nothing matched, restrict it to the docs root if (subtree.blog) subtree = siteNav.docs } } return ( ) } /* * A React component to render sidebar navigation for the main sections */ export const MainSections = () => { // Grab siteNav and slug from the navigation context const { siteNav, slug } = useContext(NavigationContext) const output = [] for (const page of onlyMainSections(siteNav)) { const act = isSlugPart(page.s, slug) const txt = ( <> {icons[page.s] ? icons[page.s]('w-6 h-6') : } {page.t} ) const item = (
  • {act ? ( {txt} ) : ( {txt} )}
  • ) output.push(item) } return
      {output}
    }