|
33 | 33 | getNextFocusedIndex, |
34 | 34 | selectFocusedItem |
35 | 35 | } from './drawer-keyboard-helpers' |
36 | | - import { isInputFocused } from './helpers' |
37 | 36 |
|
38 | 37 | const flipDurationMs = 150 |
39 | 38 |
|
|
76 | 75 | return { groupedItems: grouped, ungroupedItems: ungrouped } |
77 | 76 | }) |
78 | 77 |
|
| 78 | + // Items in display order (matches visual rendering order) |
| 79 | + let itemsInDisplayOrder = $derived.by(() => { |
| 80 | + const displayOrder: DrawerOption[] = [] |
| 81 | +
|
| 82 | + if (hasGroups && groups) { |
| 83 | + // Add grouped items in group order, only if group is open (when collapsible) |
| 84 | + groups.forEach((group) => { |
| 85 | + const isOpen = collapsibleGroups ? openGroups[group.slug] : true |
| 86 | + if (isOpen) { |
| 87 | + const groupItems = groupedItems.get(group.slug) || [] |
| 88 | + displayOrder.push(...groupItems) |
| 89 | + } |
| 90 | + }) |
| 91 | + } |
| 92 | +
|
| 93 | + // Add ungrouped items |
| 94 | + displayOrder.push(...ungroupedItems) |
| 95 | +
|
| 96 | + return displayOrder |
| 97 | + }) |
| 98 | +
|
79 | 99 | let openGroups = $state<Record<string, boolean>>({}) |
80 | 100 | let groupDndItems = $state<Record<string, DndItem[]>>({}) |
81 | 101 | let ungroupedDndItems = $state<DndItem[]>([]) |
|
413 | 433 | } |
414 | 434 |
|
415 | 435 | let focusedItemValue = $derived.by(() => { |
416 | | - const focusableItems = getFocusableItems(items) |
| 436 | + const focusableItems = getFocusableItems(itemsInDisplayOrder) |
417 | 437 | if (focusedIndex >= 0 && focusedIndex < focusableItems.length) { |
418 | 438 | return focusableItems[focusedIndex].value |
419 | 439 | } |
420 | 440 | return null |
421 | 441 | }) |
422 | 442 |
|
423 | 443 | function handleKeyDown(event: KeyboardEvent) { |
424 | | - // Don't handle if any input is focused or container doesn't exist |
425 | | - if (isInputFocused() || !containerRef || !document.body.contains(containerRef)) return |
| 444 | + // Don't handle if container doesn't exist |
| 445 | + if (!containerRef || !document.body.contains(containerRef)) return |
426 | 446 |
|
427 | | - const focusableItems = getFocusableItems(items) |
| 447 | + const focusableItems = getFocusableItems(itemsInDisplayOrder) |
428 | 448 | if (focusableItems.length === 0) return |
429 | 449 |
|
430 | 450 | if (event.key === 'ArrowDown') { |
|
435 | 455 | focusedIndex = getNextFocusedIndex(focusedIndex, 'up', focusableItems.length) |
436 | 456 | } else if (event.key === ' ' || event.key === 'Enter') { |
437 | 457 | event.preventDefault() |
438 | | - const result = selectFocusedItem(items, focusedIndex, multiple) |
| 458 | + const result = selectFocusedItem(itemsInDisplayOrder, focusedIndex, multiple) |
439 | 459 | if (result) { |
440 | 460 | if (result.shouldUpdate) { |
441 | 461 | updateItem(result.item) |
|
484 | 504 | > |
485 | 505 | {#if collapsibleGroups} |
486 | 506 | <button |
487 | | - class="cursor-pointer flex items-center justify-between h-8 pl-2.5 pr-2.5 py-2.5 text-base font-medium text-foreground-default-secondary w-full hover:bg-background-default-secondary rounded-lg overflow-clip flex-shrink-0" |
| 507 | + class="cursor-pointer flex items-center justify-between h-8 pl-2.5 pr-2.5 py-2.5 text-base font-medium text-foreground-default-secondary w-full hover:bg-background-default-secondary rounded-lg overflow-clip flex-shrink-0 outline-none" |
488 | 508 | onclick={() => toggleGroup(group.slug)} |
489 | 509 | > |
490 | 510 | <div class="flex items-center gap-1.5"> |
|
0 commit comments