Nested Groups Fixes
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
|
||||
import type { DisplayedLine } from './types';
|
||||
import { browser } from '$app/environment';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
export interface KeyboardHandlerOptions {
|
||||
getIsTyping: () => boolean;
|
||||
@@ -31,14 +32,9 @@ export function scrollToSelected(
|
||||
): void {
|
||||
if (!bodyElement || selectedIndex < 0) return;
|
||||
|
||||
const buttons = bodyElement.querySelectorAll('.tui-button');
|
||||
const btnIndices = displayedLines
|
||||
.map((item, idx) => item.parsed.line.type === 'button' ? idx : -1)
|
||||
.filter(idx => idx !== -1);
|
||||
|
||||
const selectedButton = Array.from(buttons).find((_, i) => {
|
||||
return btnIndices[i] === selectedIndex;
|
||||
}) as HTMLElement | undefined;
|
||||
// Get all buttons in DOM order (including nested ones in groups)
|
||||
const allButtons = bodyElement.querySelectorAll('.tui-button');
|
||||
const selectedButton = allButtons[selectedIndex] as HTMLElement | undefined;
|
||||
|
||||
if (selectedButton && bodyElement) {
|
||||
const containerRect = bodyElement.getBoundingClientRect();
|
||||
@@ -67,7 +63,8 @@ export function handleNavigation(line: { action?: () => void; href?: string; ext
|
||||
if (isExternal) {
|
||||
window.open(line.href, '_blank', 'noopener,noreferrer');
|
||||
} else {
|
||||
window.location.href = line.href;
|
||||
// Use SvelteKit's goto for client-side navigation (no page reload)
|
||||
goto(line.href);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,30 +96,48 @@ export function createKeyboardHandler(options: KeyboardHandlerOptions) {
|
||||
|
||||
if (!getInteractive() || !getIsComplete()) return;
|
||||
|
||||
const buttonIndices = getButtonIndices();
|
||||
if (buttonIndices.length === 0) return;
|
||||
const bodyElement = getBodyElement();
|
||||
if (!bodyElement) return;
|
||||
|
||||
// Get all buttons from the DOM (including nested ones in groups)
|
||||
const allButtons = bodyElement.querySelectorAll('.tui-button');
|
||||
const buttonCount = allButtons.length;
|
||||
if (buttonCount === 0) return;
|
||||
|
||||
const selectedIndex = getSelectedIndex();
|
||||
const currentButtonIdx = buttonIndices.indexOf(selectedIndex);
|
||||
const displayedLines = getDisplayedLines();
|
||||
const bodyElement = getBodyElement();
|
||||
|
||||
if (event.key === 'ArrowDown' || event.key === 'j') {
|
||||
event.preventDefault();
|
||||
const nextIdx = (currentButtonIdx + 1) % buttonIndices.length;
|
||||
const newSelectedIndex = buttonIndices[nextIdx];
|
||||
setSelectedIndex(newSelectedIndex);
|
||||
scrollToSelected(bodyElement, newSelectedIndex, displayedLines, scrollMargin);
|
||||
const nextIdx = selectedIndex < 0 ? 0 : (selectedIndex + 1) % buttonCount;
|
||||
setSelectedIndex(nextIdx);
|
||||
scrollToSelected(bodyElement, nextIdx, displayedLines, scrollMargin);
|
||||
// Update visual selection on buttons
|
||||
allButtons.forEach((btn, i) => btn.classList.toggle('selected', i === nextIdx));
|
||||
} else if (event.key === 'ArrowUp' || event.key === 'k') {
|
||||
event.preventDefault();
|
||||
const prevIdx = (currentButtonIdx - 1 + buttonIndices.length) % buttonIndices.length;
|
||||
const newSelectedIndex = buttonIndices[prevIdx];
|
||||
setSelectedIndex(newSelectedIndex);
|
||||
scrollToSelected(bodyElement, newSelectedIndex, displayedLines, scrollMargin);
|
||||
const prevIdx = selectedIndex < 0 ? buttonCount - 1 : (selectedIndex - 1 + buttonCount) % buttonCount;
|
||||
setSelectedIndex(prevIdx);
|
||||
scrollToSelected(bodyElement, prevIdx, displayedLines, scrollMargin);
|
||||
// Update visual selection on buttons
|
||||
allButtons.forEach((btn, i) => btn.classList.toggle('selected', i === prevIdx));
|
||||
} else if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
const selectedLine = displayedLines[selectedIndex]?.parsed.line;
|
||||
handleNavigation(selectedLine);
|
||||
if (selectedIndex >= 0 && selectedIndex < buttonCount) {
|
||||
const selectedButton = allButtons[selectedIndex] as HTMLElement;
|
||||
if (selectedButton) {
|
||||
// Read navigation data from button data attributes
|
||||
const href = selectedButton.dataset.href;
|
||||
const isExternal = selectedButton.dataset.external === 'true';
|
||||
|
||||
if (href) {
|
||||
handleNavigation({ href, external: isExternal });
|
||||
} else {
|
||||
// Fallback to click for buttons with actions (non-navigational)
|
||||
selectedButton.click();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user