aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoris2023-09-13 09:28:23 +0200
committerJoris2023-09-13 09:28:23 +0200
commit3cb3108646f81ea838a03923d9d51895e61fdb74 (patch)
treef6790e655dee63639f1a771eade1cf68a00c3508
parentc8ffa6722ef948879fa6ed9642ad134a2193fa4b (diff)
Go to previous or next book with left and right
-rw-r--r--src/view/books.ts62
-rw-r--r--src/view/components/modal.ts12
2 files changed, 60 insertions, 14 deletions
diff --git a/src/view/books.ts b/src/view/books.ts
index 7cb3cc1..5ec019a 100644
--- a/src/view/books.ts
+++ b/src/view/books.ts
@@ -6,18 +6,56 @@ export function view(books: Rx<Array<Book.Book>>): Html {
return h('div',
{ className: 'g-Books' },
withVar<Book.Book | undefined>(undefined, (focusBook, updateFocusBook) => [
- focusBook.map(book => book && bookDetailModal({
- book,
- onClose: () => updateFocusBook(_ => undefined)
- })),
- books.map(bs => bs.map(book => viewBook({
- book,
- onSelect: (book) => updateFocusBook(_ => book)
- })))
+ books.map(bs => [
+ focusBook.map(book => {
+ if (book !== undefined) {
+ let onKeyup = keyupHandler({
+ books: bs,
+ book,
+ onUpdate: (book: Book.Book) => updateFocusBook(_ => book)
+ })
+
+ return bookDetailModal({
+ book,
+ onClose: () => updateFocusBook(_ => undefined),
+ onmount: () => addEventListener('keyup', onKeyup),
+ onunmount: () => removeEventListener('keyup', onKeyup)
+ })
+ }
+ }),
+ bs.map(book => viewBook({
+ book,
+ onSelect: (book) => updateFocusBook(_ => book)
+ }))
+ ])
])
)
}
+interface KeyupHandlerParams {
+ books: Array<Book.Book>
+ book: Book.Book
+ onUpdate: (book: Book.Book) => void
+}
+
+function keyupHandler({ books, book, onUpdate }: KeyupHandlerParams): ((e: KeyboardEvent) => void) {
+ return (e: KeyboardEvent) => {
+ if (e.key === 'ArrowLeft') {
+ const indexedBooks = books.map((b, i) => ({ b, i }))
+ const focus = indexedBooks.find(({ b }) => b == book)
+ if (focus !== undefined && focus.i > 0) {
+ onUpdate(books[focus.i - 1])
+ }
+ } else if (e.key === 'ArrowRight') {
+ const indexedBooks = books.map((b, i) => ({ b, i }))
+ const focus = indexedBooks.find(({ b }) => b == book)
+ if (focus !== undefined && focus.i < books.length - 1) {
+ onUpdate(books[focus.i + 1])
+ }
+ }
+ }
+}
+
interface ViewBookParams {
book: Book.Book
onSelect: (book: Book.Book) => void
@@ -38,9 +76,11 @@ function viewBook({ book, onSelect }: ViewBookParams): Html {
interface BookDetailModalParams {
book: Book.Book
onClose: () => void
+ onmount: () => void
+ onunmount: () => void
}
-function bookDetailModal({ book, onClose }: BookDetailModalParams): Html {
+function bookDetailModal({ book, onClose, onmount, onunmount }: BookDetailModalParams): Html {
return Modal.view({
header: h('div',
h('div', { className: 'g-BookDetail__Title' }, `${book.title}, ${book.date}`),
@@ -61,7 +101,9 @@ function bookDetailModal({ book, onClose }: BookDetailModalParams): Html {
.map(str => h('p', str))
)
),
- onClose
+ onClose,
+ onmount,
+ onunmount
})
}
diff --git a/src/view/components/modal.ts b/src/view/components/modal.ts
index 95f907c..5e845e1 100644
--- a/src/view/components/modal.ts
+++ b/src/view/components/modal.ts
@@ -1,15 +1,19 @@
import { h, Html } from 'lib/rx'
interface Params {
- header: Html,
- body: Html,
+ header: Html
+ body: Html
onClose: () => void
+ onmount?: (element: Element) => void
+ onunmount?: (element: Element) => void
}
-export function view({ header, body, onClose }: Params): Html {
+export function view({ header, body, onClose, onmount, onunmount }: Params): Html {
return h('div',
{ className: 'g-Modal',
- onclick: () => onClose()
+ onclick: () => onClose(),
+ onmount: (element: Element) => onmount && onmount(element),
+ onunmount: (element: Element) => onunmount && onunmount(element)
},
h('div',
{ className: 'g-Modal__Content',