UNPKG

@sanity/ui-workshop

Version:

An environment for designing, reviewing, and quality-testing React components.

91 lines (72 loc) 2.06 kB
import {set} from 'segmented-property' import {WorkshopScope} from '../config' import {MenuCollection, MenuList, MenuScope, MenuStory} from './types' /** @internal */ export function parseMenuNode( collections: MenuCollection[], node: Record<string, unknown>, name?: string, ): Array<MenuList | MenuScope | MenuStory> { if (node.__scope__) { const scope = node.__scope__ as WorkshopScope if (scope.name === '@@root@@') { return scope.stories.map((s) => ({type: 'story', ...s})) } return [ { type: 'scope', name: scope.name || '@@root@@', title: scope.title || '(root)', scope, }, ] } const coll = collections.find((c) => c.name === name) const entries = Object.entries(node).filter(([key]) => key !== '__scope__') const items = entries.flatMap(([key, child]) => parseMenuNode(coll?.children || [], child as Record<string, unknown>, key), ) return [ { type: 'list', name, title: coll?.title || name, items, }, ] } /** @internal */ export function buildMenu( collections: MenuCollection[], scopes: WorkshopScope[], ): MenuList | MenuScope { const scopeMap: {[key: string]: WorkshopScope} = {} // Merge scopes for (const scope of scopes) { const scopeName = scope.name || '@@root@@' const prevScope: WorkshopScope = scopeMap[scopeName] || { name: scopeName, title: scope.title, stories: [], } const mergedScope: WorkshopScope = { ...prevScope, name: scopeName, stories: prevScope.stories.concat(scope.stories), } scopeMap[scopeName] = mergedScope } let tree = {} for (const scope of Object.values(scopeMap)) { tree = set(tree, scope.name || '@@root@@', {__scope__: scope}) } const rootNode: MenuList = { type: 'list', name: '@@root@@', items: [], } for (const [key, entry] of Object.entries(tree)) { rootNode.items.push(...parseMenuNode(collections, entry as Record<string, unknown>, key)) } return rootNode }