|
| 1 | +/* eslint-disable max-lines */ |
| 2 | + |
1 | 3 | import type { DeepReadonly } from '#lib/types'; |
2 | 4 | import { Logger } from '#lib/logger'; |
3 | 5 |
|
@@ -156,28 +158,67 @@ export const toggleFullScreen = function toggleFullScreen(): void { |
156 | 158 | } |
157 | 159 | }; |
158 | 160 |
|
| 161 | +/** Gets the size of one `--unit` in pixels. */ |
| 162 | +export const getOneUnitSizeInPixels = function getOneUnitSizeInPixels(): number { |
| 163 | + const element = document.createElement('div'); |
| 164 | + element.style.position = 'absolute'; |
| 165 | + element.style.visibility = 'hidden'; |
| 166 | + element.style.height = 'var(--unit)'; |
| 167 | + document.body.appendChild(element); |
| 168 | + const pixels = element.getBoundingClientRect().height; |
| 169 | + document.body.removeChild(element); |
| 170 | + return pixels; |
| 171 | +}; |
| 172 | + |
| 173 | +interface scrollUsingUnitArgs { |
| 174 | + readonly amount: number; |
| 175 | + /** Wether to move down that many slides instead of units. */ |
| 176 | + readonly slides?: boolean; |
| 177 | +} |
| 178 | + |
| 179 | +/** Scrolls the window down by `amount * --unit` in pixels. */ |
| 180 | +export const scrollUsingUnit = function scrollUsingUnit({ |
| 181 | + amount, |
| 182 | + slides = false, |
| 183 | +}: scrollUsingUnitArgs): void { |
| 184 | + let modifier = 1; |
| 185 | + if (slides) { |
| 186 | + const marginBetweenSlides = 1; |
| 187 | + const value = getComputedStyle(document.body).getPropertyValue('--height').trim(); |
| 188 | + modifier = Number.parseFloat(value) + marginBetweenSlides; |
| 189 | + } |
| 190 | + |
| 191 | + const pixels = getOneUnitSizeInPixels() * amount * modifier; |
| 192 | + Logger.debug(`Scrolling by ${pixels} pixels`); |
| 193 | + if (!Number.isNaN(pixels)) document.body.scrollBy({ behavior: 'smooth', left: 0, top: pixels }); |
| 194 | +}; |
| 195 | + |
159 | 196 | /** Handles key presses on the document, and moves slides accordingly. */ |
160 | 197 | // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types |
161 | 198 | export const handleKeyPresses = function handleKeyPresses(event: KeyboardEvent): void { |
162 | | - if (isPDF()) return; |
163 | | - |
164 | 199 | switch (event.key) { |
165 | 200 | case 'Enter': |
166 | 201 | case ' ': |
167 | 202 | case 'd': |
168 | 203 | case 'l': |
169 | 204 | case 'ArrowRight': |
170 | | - goToNextSlide(); |
| 205 | + if (!isPDF()) goToNextSlide(); |
171 | 206 | break; |
172 | 207 | case 'a': |
173 | 208 | case 'h': |
174 | 209 | case 'ArrowLeft': |
175 | | - goToPreviousSlide(); |
| 210 | + if (!isPDF()) goToPreviousSlide(); |
176 | 211 | break; |
177 | 212 | case 'f': |
178 | 213 | case 'F11': |
179 | 214 | toggleFullScreen(); |
180 | 215 | break; |
| 216 | + case 'ArrowDown': |
| 217 | + if (isPDF()) scrollUsingUnit({ amount: 1, slides: true }); |
| 218 | + break; |
| 219 | + case 'ArrowUp': |
| 220 | + if (isPDF()) scrollUsingUnit({ amount: -1, slides: true }); |
| 221 | + break; |
181 | 222 | default: |
182 | 223 | } |
183 | 224 | }; |
@@ -268,6 +309,8 @@ export const setupScriptCode = /*JavaScript*/ ` |
268 | 309 | ${handleUrlHashChange.toString()} |
269 | 310 | ${handleMousePresses.toString()} |
270 | 311 | ${toggleFullScreen.toString()} |
| 312 | + ${getOneUnitSizeInPixels.toString()} |
| 313 | + ${scrollUsingUnit.toString()} |
271 | 314 | ${handleKeyPresses.toString()} |
272 | 315 | ${handleScrollEvents.toString()} |
273 | 316 | ${handleTouchEvents.toString()} |
|
0 commit comments