// __SDEFILE__ - This file is a dependency for the stand-alone environment
import { NavigationContext } from 'shared/context/navigation-context.mjs'
import { useContext } from 'react'
import Link from 'next/link'
import orderBy from 'lodash.orderby'
import {
CsetIcon,
DesignIcon,
DocsIcon,
RssIcon,
ShowcaseIcon,
UserIcon,
CodeIcon,
BulletIcon,
PlusIcon,
GitHubIcon,
RocketIcon,
TutorialIcon,
YouTubeIcon,
HeartIcon,
} from 'shared/components/icons.mjs'
import { Breadcrumbs } from 'shared/components/breadcrumbs.mjs'
export const ns = ['sections']
// List of icons matched to top-level slug
export const icons = {
// FreeSewing.dev
guides: (className = '') => ,
howtos: (className = '') => ,
reference: (className = '') => ,
tutorials: (className = '') => ,
training: (className = '') => ,
// FreeSewing.org
account: (className = '') => ,
blog: (className = '') => ,
designs: (className = '') => ,
docs: (className = '') => ,
showcase: (className = '') => ,
new: (className = '') => ,
support: (className = '') => ,
csets: (className = '') => ,
// Lab
code: (className = '') => ,
}
/* helper method to order nav entries */
const order = (obj) => orderBy(obj, ['o', 't'], ['asc', 'asc'])
// Component for the collapse toggle
// Exported for re-use
export const Chevron = ({ w = 8, m = 2 }) => (
)
// Helper method to filter out the real children
const currentChildren = (current) =>
Object.values(order(current)).filter((entry) => typeof entry === 'object')
// Shared classes for links
// Exported for re-use
export const linkClasses = `
py-1
text-base text-base-content sm:text-base-content
hover:text-secondary
sm:hover:text-secondary
`
// Figure out whether a page is on the path to the active page
export const isActive = (slug, active) => {
if (!slug) return false
if (slug === active) return true
let result = true
const slugParts = slug.split('/')
const activeParts = active.split('/')
for (const i in slugParts) {
if (slugParts[i] !== activeParts[i]) result = false
}
return result
}
const hasChildren = (page) => {
const keys = new Set([...Object.keys(page)])
for (const key of ['t', 's']) keys.delete(key)
return keys.size
}
// Component that renders a sublevel of navigation
const SubLevel = ({ nodes = {}, active = '' }) => (
{currentChildren(nodes).map((child) =>
hasChildren(child) ? (
-
{child.s === active ? <>•> : <>°>}
{child.t}
) : (
-
{child.s === active ? <>•> : <>°>}
{child.t}
)
)}
)
export const Icons = ({
ulClasses = '',
linkClasses = `grow text-lg lg:text-xl py-1 text-base-content sm:text-base-content
hover:text-secondary sm:hover:text-secondary hover:cursor-pointer
flex flex-col items-center`,
linkStyle = {},
}) => {
const { nav } = useContext(NavigationContext)
if (!nav) return null
const output = []
for (const page of order(nav)) {
output.push(
{icons[page.s] ? icons[page.s]('w-14 h-14') : }
{page.t}
)
}
return
}
export const Spacer = () => (
)
export const MainSections = () => {
const { sections = false, slug } = useContext(NavigationContext)
if (!sections) return null
// Ensure each page as an `o` key so we can put them in order
const sortableSections = sections.map((s) => ({ ...s, o: s.o ? s.o : s.t }))
const output = []
for (const page of orderBy(sortableSections, ['o', 't'])) {
const act = isActive(page.s, slug)
const txt = (
<>
{icons[page.s] ? (
icons[page.s](`w-6 h-6 ${act ? 'text-base-100 opacity-70' : ''}`)
) : (
)}
{page.t}
>
)
const item =
page.t === 'spacer' ? (
) : (
{act ? (
{txt}
) : (
{txt}
)}
)
output.push(item)
}
return
}
const getCrumb = (index, crumbs) => crumbs[index].s.split('/').pop()
export const ActiveSection = () => {
// Get navigation context
const { crumbs = [], nav = {}, slug } = useContext(NavigationContext)
// Don't bother if we don't know where we are
if (!crumbs || !Array.isArray(crumbs) || crumbs.length < 1) return null
let slice = 1
let nodes = nav
// Some sections are further trimmed
if (crumbs[0].s === 'docs') {
if (crumbs.length > 1 && crumbs[1].s === 'docs/faq') {
slice = 2
nodes = nav[getCrumb(1, crumbs)]
} else if (crumbs.length === 2) {
slice = 2
nodes = nav[getCrumb(1, crumbs)]
} else if (
crumbs.length === 4 &&
crumbs[1].s === 'docs/patterns' &&
crumbs[3].s.split('/').pop() === 'options'
) {
slice = 4
nodes = nav[getCrumb(1, crumbs)][getCrumb(2, crumbs)][getCrumb(3, crumbs)]
} else if (crumbs.length > 2 && crumbs[1].s === 'docs/patterns') {
slice = 3
nodes = nav[getCrumb(1, crumbs)][getCrumb(2, crumbs)]
}
}
return (
)
}