diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 980d57676..5d62d464c 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -39,3 +39,4 @@ export * from './overlays' export * from './block' export * from './recaptcha' export * from './recaptcha-field' +export * from './menu' diff --git a/packages/core/src/menu/MenuLevelBuilder.tsx b/packages/core/src/menu/MenuLevelBuilder.tsx new file mode 100644 index 000000000..81ab9899c --- /dev/null +++ b/packages/core/src/menu/MenuLevelBuilder.tsx @@ -0,0 +1,67 @@ +import {ReactNode} from 'react' + +export interface BaseMenuItem { + id: string + title: ReactNode +} + +export type MenuTree = Item & { + sub?: MenuTree[] +} + +export class MenuLevel { + constructor(public items: Item[] = [], public activeId: string = '') {} +} + +export class MenuLevelBuilder { + constructor(protected items: MenuTree[]) {} + + protected buildLevels( + activeId: string, + items: MenuTree[], + levels: MenuLevel[], + depth = 0, + parentActive = false + ): boolean { + if (levels.length <= depth) levels[depth] = new MenuLevel() + const level = levels[depth] + let activeItem: MenuTree | undefined + for (let item of items) { + const currentActive = item.id === activeId + const sub = item.sub + const childActive = + sub && sub.length > 0 + ? this.buildLevels( + activeId, + sub, + levels, + depth + 1, + currentActive || parentActive + ) + : false + if (currentActive) activeItem = item + if (childActive && !activeItem) activeItem = item + } + + if (activeItem) { + level.items = items + level.activeId = activeItem.id + } else if (parentActive) { + level.items = items + level.activeId = items[0].id + } + + return !!activeItem + } + + /** + * Split MenuTree structure to levels. + * + * @param activeId current menu item id + */ + levels(activeId: string): MenuLevel[] { + const result: MenuLevel[] = [] + this.buildLevels(activeId, this.items, result) + return result + } +} diff --git a/packages/core/src/menu/index.ts b/packages/core/src/menu/index.ts new file mode 100644 index 000000000..a8db89a5b --- /dev/null +++ b/packages/core/src/menu/index.ts @@ -0,0 +1 @@ +export * from './MenuLevelBuilder'