Files
windmill/frontend/src/lib/keyboardChain.ts
Guilhem 11595a1931 fix(frontend): flow log viewer add keyboard navigation (#6523)
* prevent navigation in the flow when the preview is open

* keyboardNav with registration link

* Improve keyboard nav UI

* Focus log with keyboard nav

* Add native focus

* initialize focused on key down

* fix log expand not sticking

* Improve tree structure

* nit

* nit

* Update active section on click

* add tooltip for keyboard navigation
2025-09-03 18:27:08 +00:00

48 lines
1.8 KiB
TypeScript

export type NavigationChain = Record<string, { upId?: string | null; downId?: string | null }>
// Update navigation chain: remove old chain between first/last, insert new chain
export function updateLinks(navigationChain: NavigationChain, newChain: NavigationChain) {
if (Object.keys(newChain).length === 0) return navigationChain
const firstLink = Object.keys(newChain).find((link) => newChain[link].upId === null)
const lastLink = Object.keys(newChain).find((link) => newChain[link].downId === null)
//If the chain has no end or start, return the navigationChain
if (!firstLink || !lastLink) return navigationChain
const cleaned = { ...navigationChain }
const inserted = { ...newChain }
// Check if the chain needs to be inserted
if (!cleaned[lastLink] && cleaned[firstLink]) {
// connect the beginning of the new chain to the beginning of the chain
inserted[firstLink].upId = cleaned[firstLink]?.upId
//connect the end of new the new chain to the beginning of the chain
const nextLink = cleaned[firstLink]?.downId
if (nextLink) {
inserted[lastLink].downId = nextLink
cleaned[nextLink].upId = lastLink
}
} else if (cleaned[lastLink] && cleaned[firstLink]) {
// If the end of the chain matches a link in the navigationChain, and the beginning delete the chain in the middle and replace it with the new chain
inserted[firstLink].upId = cleaned[firstLink]?.upId
inserted[lastLink].downId = cleaned[lastLink]?.downId
if (firstLink !== lastLink) {
const toDelete: string[] = []
let current = cleaned[firstLink]?.downId
while (current && current !== lastLink && !toDelete.includes(current)) {
toDelete.push(current)
current = cleaned[current]?.downId
}
toDelete.forEach((itemId) => {
delete cleaned[itemId]
})
}
}
return { ...cleaned, ...inserted }
}