(s: ScrollBoxHandle, act: ModalPagerAction | null, onBeforeJump: (delta: number) => void)
| 967 | * shift anchor+focus) instead of clearing it. Exported for testing. |
| 968 | */ |
| 969 | export function applyModalPagerAction(s: ScrollBoxHandle, act: ModalPagerAction | null, onBeforeJump: (delta: number) => void): boolean | null { |
| 970 | switch (act) { |
| 971 | case null: |
| 972 | return null; |
| 973 | case 'lineUp': |
| 974 | case 'lineDown': |
| 975 | { |
| 976 | const d = act === 'lineDown' ? 1 : -1; |
| 977 | onBeforeJump(d); |
| 978 | return jumpBy(s, d); |
| 979 | } |
| 980 | case 'halfPageUp': |
| 981 | case 'halfPageDown': |
| 982 | { |
| 983 | const half = Math.max(1, Math.floor(s.getViewportHeight() / 2)); |
| 984 | const d = act === 'halfPageDown' ? half : -half; |
| 985 | onBeforeJump(d); |
| 986 | return jumpBy(s, d); |
| 987 | } |
| 988 | case 'fullPageUp': |
| 989 | case 'fullPageDown': |
| 990 | { |
| 991 | const page = Math.max(1, s.getViewportHeight()); |
| 992 | const d = act === 'fullPageDown' ? page : -page; |
| 993 | onBeforeJump(d); |
| 994 | return jumpBy(s, d); |
| 995 | } |
| 996 | case 'top': |
| 997 | onBeforeJump(-(s.getScrollTop() + s.getPendingDelta())); |
| 998 | s.scrollTo(0); |
| 999 | return false; |
| 1000 | case 'bottom': |
| 1001 | { |
| 1002 | const max = Math.max(0, s.getScrollHeight() - s.getViewportHeight()); |
| 1003 | onBeforeJump(max - (s.getScrollTop() + s.getPendingDelta())); |
| 1004 | // Eager-write scrollTop before scrollToBottom — same double-shift |
| 1005 | // fix as scroll:bottom and jumpBy's max branch. |
| 1006 | s.scrollTo(max); |
| 1007 | s.scrollToBottom(); |
| 1008 | return true; |
| 1009 | } |
| 1010 | } |
| 1011 | } |
no test coverage detected