diff --git a/packages/elements-core/package.json b/packages/elements-core/package.json index 4e5a4fefa..412b15128 100644 --- a/packages/elements-core/package.json +++ b/packages/elements-core/package.json @@ -1,6 +1,6 @@ { "name": "@stoplight/elements-core", - "version": "9.0.13", + "version": "9.0.14", "sideEffects": [ "web-components.min.js", "src/web-components/**", diff --git a/packages/elements-core/src/components/TableOfContents/TableOfContents.tsx b/packages/elements-core/src/components/TableOfContents/TableOfContents.tsx index 1842ad1eb..14415a517 100644 --- a/packages/elements-core/src/components/TableOfContents/TableOfContents.tsx +++ b/packages/elements-core/src/components/TableOfContents/TableOfContents.tsx @@ -84,6 +84,49 @@ export const TableOfContents = React.memo( }, []); const updatedTree = updateTocTree(tree, ''); + const findFirstMatchAndIndexMatch = React.useCallback( + (items: TableOfContentsGroupItem[], id: string | undefined): [TableOfContentsGroupItem | undefined, boolean] => { + let firstMatch: TableOfContentsGroupItem | undefined; + let hasAnyLastIndexMatch = false; + if (!id) return [firstMatch, hasAnyLastIndexMatch]; + + const walk = (arr: TableOfContentsGroupItem[], stack: TableOfContentsGroupItem[]): boolean => { + for (const itm of arr) { + const newStack = stack.concat(itm); + + const matches = ('slug' in itm && (itm as any).slug === id) || ('id' in itm && (itm as any).id === id); + if (matches) { + if (!firstMatch) firstMatch = itm; + const hasLastIndexMatch = newStack.some(el => 'index' in el && (el as any).index === lastActiveIndex); + if (hasLastIndexMatch) hasAnyLastIndexMatch = true; + } + + if ('items' in itm && Array.isArray((itm as any).items)) { + if (walk((itm as any).items, newStack)) return true; + } + } + + return false; + }; + + walk(items, []); + return [firstMatch, hasAnyLastIndexMatch]; + }, + [lastActiveIndex], + ); + + const [firstMatchItem, hasAnyLastIndexMatch] = React.useMemo( + () => findFirstMatchAndIndexMatch(updatedTree, activeId), + [updatedTree, activeId, findFirstMatchAndIndexMatch], + ); + + React.useEffect(() => { + if (!hasAnyLastIndexMatch && firstMatchItem && 'index' in firstMatchItem && firstMatchItem.index) { + setLastActiveIndex(firstMatchItem.index); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [firstMatchItem, hasAnyLastIndexMatch]); + const container = React.useRef(null); const child = React.useRef(null); const firstRender = useFirstRender(); diff --git a/packages/elements-dev-portal/package.json b/packages/elements-dev-portal/package.json index 0088440c0..2273c052a 100644 --- a/packages/elements-dev-portal/package.json +++ b/packages/elements-dev-portal/package.json @@ -1,6 +1,6 @@ { "name": "@stoplight/elements-dev-portal", - "version": "3.0.13", + "version": "3.0.14", "description": "UI components for composing beautiful developer documentation.", "keywords": [], "sideEffects": [ @@ -66,7 +66,7 @@ "dependencies": { "@stoplight/markdown-viewer": "^5.7.1", "@stoplight/mosaic": "^1.53.5", - "@stoplight/elements-core": "~9.0.13", + "@stoplight/elements-core": "~9.0.14", "@stoplight/path": "^1.3.2", "@stoplight/types": "^14.0.0", "classnames": "^2.2.6", diff --git a/packages/elements-dev-portal/src/version.ts b/packages/elements-dev-portal/src/version.ts index b27501da2..bd2b298ee 100644 --- a/packages/elements-dev-portal/src/version.ts +++ b/packages/elements-dev-portal/src/version.ts @@ -1,2 +1,2 @@ // auto-updated during build -export const appVersion = '3.0.10'; +export const appVersion = '3.0.14'; diff --git a/packages/elements/package.json b/packages/elements/package.json index cee4d949f..8920667e2 100644 --- a/packages/elements/package.json +++ b/packages/elements/package.json @@ -1,6 +1,6 @@ { "name": "@stoplight/elements", - "version": "9.0.13", + "version": "9.0.14", "description": "UI components for composing beautiful developer documentation.", "keywords": [], "sideEffects": [ @@ -63,7 +63,7 @@ ] }, "dependencies": { - "@stoplight/elements-core": "~9.0.13", + "@stoplight/elements-core": "~9.0.14", "@stoplight/http-spec": "^7.1.0", "@stoplight/json": "^3.18.1", "@stoplight/mosaic": "^1.53.5",