@internetarchive/bookreader 5.0.0-9-multiple-files → 5.0.0-90

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (333) hide show
  1. package/.eslintrc.js +21 -19
  2. package/.github/workflows/node.js.yml +81 -7
  3. package/.github/workflows/npm-publish.yml +6 -20
  4. package/.testcaferc.js +10 -0
  5. package/BookReader/BookReader.css +505 -1442
  6. package/BookReader/BookReader.js +2 -21564
  7. package/BookReader/BookReader.js.LICENSE.txt +20 -20
  8. package/BookReader/BookReader.js.map +1 -1
  9. package/BookReader/ia-bookreader-bundle.js +1782 -0
  10. package/BookReader/ia-bookreader-bundle.js.LICENSE.txt +7 -0
  11. package/BookReader/ia-bookreader-bundle.js.map +1 -0
  12. package/BookReader/icons/1up.svg +1 -12
  13. package/BookReader/icons/2up.svg +1 -15
  14. package/BookReader/icons/advance.svg +3 -26
  15. package/BookReader/icons/chevron-right.svg +1 -1
  16. package/BookReader/icons/close-circle-dark.svg +1 -0
  17. package/BookReader/icons/close-circle.svg +1 -1
  18. package/BookReader/icons/fullscreen.svg +1 -17
  19. package/BookReader/icons/fullscreen_exit.svg +1 -17
  20. package/BookReader/icons/hamburger.svg +1 -15
  21. package/BookReader/icons/left-arrow.svg +1 -12
  22. package/BookReader/icons/magnify-minus.svg +1 -16
  23. package/BookReader/icons/magnify-plus.svg +1 -17
  24. package/BookReader/icons/magnify.svg +1 -15
  25. package/BookReader/icons/pause.svg +1 -23
  26. package/BookReader/icons/play.svg +1 -22
  27. package/BookReader/icons/playback-speed.svg +1 -34
  28. package/BookReader/icons/read-aloud.svg +1 -22
  29. package/BookReader/icons/review.svg +3 -22
  30. package/BookReader/icons/thumbnails.svg +1 -17
  31. package/BookReader/icons/voice.svg +1 -0
  32. package/BookReader/icons/volume-full.svg +1 -22
  33. package/BookReader/images/BRicons.svg +5 -94
  34. package/BookReader/images/books_graphic.svg +1 -177
  35. package/BookReader/images/icon_book.svg +1 -12
  36. package/BookReader/images/icon_bookmark.svg +1 -12
  37. package/BookReader/images/icon_gear.svg +1 -14
  38. package/BookReader/images/icon_hamburger.svg +1 -20
  39. package/BookReader/images/icon_home.svg +1 -21
  40. package/BookReader/images/icon_info.svg +1 -11
  41. package/BookReader/images/icon_one_page.svg +1 -8
  42. package/BookReader/images/icon_pause.svg +1 -1
  43. package/BookReader/images/icon_play.svg +1 -1
  44. package/BookReader/images/icon_playback-rate.svg +1 -15
  45. package/BookReader/images/icon_search_button.svg +1 -8
  46. package/BookReader/images/icon_share.svg +1 -9
  47. package/BookReader/images/icon_skip-ahead.svg +1 -6
  48. package/BookReader/images/icon_skip-back.svg +2 -13
  49. package/BookReader/images/icon_speaker.svg +1 -18
  50. package/BookReader/images/icon_speaker_open.svg +1 -10
  51. package/BookReader/images/icon_thumbnails.svg +1 -12
  52. package/BookReader/images/icon_toc.svg +1 -5
  53. package/BookReader/images/icon_two_pages.svg +1 -9
  54. package/BookReader/images/marker_chap-off.svg +1 -11
  55. package/BookReader/images/marker_chap-on.svg +1 -11
  56. package/BookReader/images/marker_srch-on.svg +1 -11
  57. package/BookReader/images/unviewable_page.png +0 -0
  58. package/BookReader/jquery-3.js +2 -0
  59. package/BookReader/jquery-3.js.LICENSE.txt +24 -0
  60. package/BookReader/plugins/plugin.archive_analytics.js +1 -172
  61. package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
  62. package/BookReader/plugins/plugin.autoplay.js +1 -165
  63. package/BookReader/plugins/plugin.autoplay.js.map +1 -1
  64. package/BookReader/plugins/plugin.chapters.js +22 -301
  65. package/BookReader/plugins/plugin.chapters.js.LICENSE.txt +1 -0
  66. package/BookReader/plugins/plugin.chapters.js.map +1 -1
  67. package/BookReader/plugins/plugin.iframe.js +1 -74
  68. package/BookReader/plugins/plugin.iframe.js.map +1 -1
  69. package/BookReader/plugins/plugin.iiif.js +2 -0
  70. package/BookReader/plugins/plugin.iiif.js.map +1 -0
  71. package/BookReader/plugins/plugin.resume.js +1 -368
  72. package/BookReader/plugins/plugin.resume.js.map +1 -1
  73. package/BookReader/plugins/plugin.search.js +2 -1420
  74. package/BookReader/plugins/plugin.search.js.LICENSE.txt +1 -0
  75. package/BookReader/plugins/plugin.search.js.map +1 -1
  76. package/BookReader/plugins/plugin.text_selection.js +2 -1080
  77. package/BookReader/plugins/plugin.text_selection.js.LICENSE.txt +1 -0
  78. package/BookReader/plugins/plugin.text_selection.js.map +1 -1
  79. package/BookReader/plugins/plugin.tts.js +2 -9193
  80. package/BookReader/plugins/plugin.tts.js.LICENSE.txt +2 -0
  81. package/BookReader/plugins/plugin.tts.js.map +1 -1
  82. package/BookReader/plugins/plugin.url.js +1 -269
  83. package/BookReader/plugins/plugin.url.js.map +1 -1
  84. package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -379
  85. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
  86. package/BookReader/webcomponents-bundle.js +3 -0
  87. package/BookReader/webcomponents-bundle.js.LICENSE.txt +9 -0
  88. package/BookReader/webcomponents-bundle.js.map +1 -0
  89. package/BookReaderDemo/BookReaderDemo.css +18 -19
  90. package/BookReaderDemo/BookReaderJSAdvanced.js +0 -3
  91. package/BookReaderDemo/BookReaderJSSimple.js +1 -0
  92. package/BookReaderDemo/IADemoBr.js +144 -0
  93. package/BookReaderDemo/demo-advanced.html +2 -2
  94. package/BookReaderDemo/demo-embed-iframe-src.html +2 -1
  95. package/BookReaderDemo/demo-fullscreen-mobile.html +3 -5
  96. package/BookReaderDemo/demo-fullscreen.html +2 -4
  97. package/BookReaderDemo/demo-iiif.html +99 -12
  98. package/BookReaderDemo/demo-internetarchive.html +214 -18
  99. package/BookReaderDemo/demo-multiple.html +2 -1
  100. package/BookReaderDemo/demo-preview-pages.html +526 -525
  101. package/BookReaderDemo/demo-simple.html +2 -1
  102. package/BookReaderDemo/demo-vendor-fullscreen.html +2 -4
  103. package/BookReaderDemo/ia-multiple-volumes-manifest.js +170 -0
  104. package/BookReaderDemo/immersion-1up.html +2 -2
  105. package/BookReaderDemo/immersion-mode.html +2 -4
  106. package/BookReaderDemo/toggle_controls.html +3 -2
  107. package/BookReaderDemo/view_mode.html +2 -1
  108. package/BookReaderDemo/viewmode-cycle.html +2 -3
  109. package/CHANGELOG.md +595 -33
  110. package/README.md +14 -1
  111. package/babel.config.js +20 -0
  112. package/codecov.yml +6 -0
  113. package/index.html +5 -2
  114. package/jsconfig.json +19 -0
  115. package/netlify.toml +9 -0
  116. package/package.json +70 -62
  117. package/renovate.json +52 -0
  118. package/scripts/preversion.js +0 -1
  119. package/src/BookNavigator/assets/bookmark-colors.js +1 -1
  120. package/src/BookNavigator/assets/button-base.js +10 -2
  121. package/src/BookNavigator/assets/ia-logo.js +17 -0
  122. package/src/BookNavigator/assets/icon_checkmark.js +1 -1
  123. package/src/BookNavigator/assets/icon_close.js +1 -1
  124. package/src/BookNavigator/book-navigator.js +590 -0
  125. package/src/BookNavigator/bookmarks/bookmark-button.js +3 -2
  126. package/src/BookNavigator/bookmarks/bookmark-edit.js +3 -4
  127. package/src/BookNavigator/bookmarks/bookmarks-list.js +2 -3
  128. package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +4 -9
  129. package/src/BookNavigator/bookmarks/bookmarks-provider.js +27 -17
  130. package/src/BookNavigator/bookmarks/ia-bookmarks.js +116 -67
  131. package/src/BookNavigator/delete-modal-actions.js +1 -1
  132. package/src/BookNavigator/downloads/downloads-provider.js +36 -21
  133. package/src/BookNavigator/downloads/downloads.js +29 -25
  134. package/src/BookNavigator/search/search-provider.js +80 -28
  135. package/src/BookNavigator/search/search-results.js +29 -26
  136. package/src/BookNavigator/sharing.js +27 -0
  137. package/src/BookNavigator/viewable-files.js +95 -0
  138. package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +13 -12
  139. package/src/BookNavigator/visual-adjustments/visual-adjustments.js +7 -7
  140. package/src/BookReader/BookModel.js +76 -41
  141. package/src/BookReader/DragScrollable.js +233 -0
  142. package/src/BookReader/ImageCache.js +48 -15
  143. package/src/BookReader/Mode1Up.js +56 -351
  144. package/src/BookReader/Mode1UpLit.js +388 -0
  145. package/src/BookReader/Mode2Up.js +73 -1318
  146. package/src/BookReader/Mode2UpLit.js +777 -0
  147. package/src/BookReader/ModeCoordinateSpace.js +29 -0
  148. package/src/BookReader/ModeSmoothZoom.js +312 -0
  149. package/src/BookReader/ModeThumb.js +19 -13
  150. package/src/BookReader/Navbar/Navbar.js +70 -54
  151. package/src/BookReader/PageContainer.js +116 -22
  152. package/src/BookReader/ReduceSet.js +3 -3
  153. package/src/BookReader/Toolbar/Toolbar.js +14 -41
  154. package/src/BookReader/events.js +2 -3
  155. package/src/BookReader/options.js +73 -15
  156. package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
  157. package/src/BookReader/utils/ScrollClassAdder.js +31 -0
  158. package/src/BookReader/utils/SelectionObserver.js +45 -0
  159. package/src/BookReader/utils/classes.js +1 -1
  160. package/src/BookReader/utils.js +128 -13
  161. package/src/BookReader.js +562 -1078
  162. package/src/BookReaderPlugin.js +44 -0
  163. package/src/assets/icons/close-circle-dark.svg +1 -0
  164. package/src/assets/icons/magnify-minus.svg +3 -7
  165. package/src/assets/icons/magnify-plus.svg +3 -7
  166. package/src/assets/icons/voice.svg +1 -0
  167. package/src/assets/images/unviewable_page.png +0 -0
  168. package/src/css/BookReader.scss +1 -17
  169. package/src/css/_BRBookmarks.scss +1 -1
  170. package/src/css/_BRComponent.scss +1 -1
  171. package/src/css/_BRicon.scss +8 -2
  172. package/src/css/_BRmain.scss +33 -27
  173. package/src/css/_BRnav.scss +12 -42
  174. package/src/css/_BRpages.scss +170 -42
  175. package/src/css/_BRsearch.scss +68 -230
  176. package/src/css/_BRtoolbar.scss +5 -5
  177. package/src/css/_TextSelection.scss +87 -27
  178. package/src/css/_colorbox.scss +2 -2
  179. package/src/css/_controls.scss +24 -7
  180. package/src/css/_icons.scss +7 -1
  181. package/src/ia-bookreader/ia-bookreader.js +224 -0
  182. package/src/plugins/plugin.archive_analytics.js +84 -78
  183. package/src/plugins/plugin.autoplay.js +99 -104
  184. package/src/plugins/plugin.chapters.js +237 -191
  185. package/src/plugins/plugin.iframe.js +1 -1
  186. package/src/plugins/plugin.iiif.js +141 -0
  187. package/src/plugins/plugin.resume.js +53 -50
  188. package/src/plugins/plugin.text_selection.js +503 -175
  189. package/src/plugins/plugin.vendor-fullscreen.js +7 -7
  190. package/src/plugins/search/plugin.search.js +183 -121
  191. package/src/plugins/search/utils.js +43 -0
  192. package/src/plugins/search/view.js +67 -202
  193. package/src/plugins/tts/AbstractTTSEngine.js +75 -45
  194. package/src/plugins/tts/FestivalTTSEngine.js +21 -31
  195. package/src/plugins/tts/PageChunk.js +16 -23
  196. package/src/plugins/tts/PageChunkIterator.js +11 -17
  197. package/src/plugins/tts/WebTTSEngine.js +88 -72
  198. package/src/plugins/tts/plugin.tts.js +310 -350
  199. package/src/plugins/tts/utils.js +16 -26
  200. package/src/plugins/url/UrlPlugin.js +191 -0
  201. package/src/plugins/{plugin.url.js → url/plugin.url.js} +47 -18
  202. package/src/util/browserSniffing.js +22 -0
  203. package/src/util/docCookies.js +21 -2
  204. package/src/util/strings.js +1 -0
  205. package/tests/e2e/README.md +37 -0
  206. package/tests/e2e/autoplay.test.js +9 -6
  207. package/tests/e2e/base.test.js +8 -16
  208. package/tests/e2e/helpers/base.js +55 -50
  209. package/tests/e2e/helpers/debug.js +1 -1
  210. package/tests/e2e/helpers/mockSearch.js +19 -22
  211. package/tests/e2e/helpers/params.js +17 -0
  212. package/tests/e2e/helpers/rightToLeft.js +8 -14
  213. package/tests/e2e/helpers/search.js +73 -0
  214. package/tests/e2e/models/Navigation.js +20 -37
  215. package/tests/e2e/rightToLeft.test.js +4 -5
  216. package/tests/e2e/viewmode.test.js +40 -33
  217. package/tests/jest/BookNavigator/book-navigator.test.js +661 -0
  218. package/tests/jest/BookNavigator/bookmarks/bookmark-button.test.js +43 -0
  219. package/tests/{karma → jest}/BookNavigator/bookmarks/bookmark-edit.test.js +25 -26
  220. package/tests/{karma → jest}/BookNavigator/bookmarks/bookmarks-list.test.js +41 -42
  221. package/tests/jest/BookNavigator/bookmarks/ia-bookmarks.test.js +45 -0
  222. package/tests/jest/BookNavigator/downloads/downloads-provider.test.js +67 -0
  223. package/tests/jest/BookNavigator/downloads/downloads.test.js +53 -0
  224. package/tests/jest/BookNavigator/search/search-provider.test.js +167 -0
  225. package/tests/{karma/BookNavigator → jest/BookNavigator/search}/search-results.test.js +109 -60
  226. package/tests/jest/BookNavigator/sharing/sharing-provider.test.js +49 -0
  227. package/tests/jest/BookNavigator/viewable-files/viewable-files-provider.test.js +80 -0
  228. package/tests/jest/BookNavigator/visual-adjustments.test.js +200 -0
  229. package/tests/{BookReader → jest/BookReader}/BookModel.test.js +74 -14
  230. package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +193 -0
  231. package/tests/{BookReader → jest/BookReader}/ImageCache.test.js +4 -4
  232. package/tests/jest/BookReader/Mode1UpLit.test.js +73 -0
  233. package/tests/jest/BookReader/Mode2Up.test.js +98 -0
  234. package/tests/jest/BookReader/Mode2UpLit.test.js +190 -0
  235. package/tests/jest/BookReader/ModeCoordinateSpace.test.js +16 -0
  236. package/tests/jest/BookReader/ModeSmoothZoom.test.js +218 -0
  237. package/tests/jest/BookReader/ModeThumb.test.js +71 -0
  238. package/tests/{BookReader → jest/BookReader}/Navbar/Navbar.test.js +42 -29
  239. package/tests/jest/BookReader/PageContainer.test.js +238 -0
  240. package/tests/{BookReader → jest/BookReader}/ReduceSet.test.js +1 -1
  241. package/tests/{BookReader → jest/BookReader}/Toolbar/Toolbar.test.js +3 -3
  242. package/tests/jest/BookReader/utils/HTMLDimensionsCacher.test.js +59 -0
  243. package/tests/jest/BookReader/utils/ScrollClassAdder.test.js +49 -0
  244. package/tests/jest/BookReader/utils/SelectionObserver.test.js +57 -0
  245. package/tests/{BookReader → jest/BookReader}/utils/classes.test.js +1 -1
  246. package/tests/jest/BookReader/utils.test.js +250 -0
  247. package/tests/jest/BookReader.keyboard.test.js +190 -0
  248. package/tests/{BookReader.options.test.js → jest/BookReader.options.test.js} +10 -2
  249. package/tests/{BookReader.test.js → jest/BookReader.test.js} +43 -53
  250. package/tests/jest/plugins/plugin.archive_analytics.test.js +20 -0
  251. package/tests/jest/plugins/plugin.autoplay.test.js +35 -0
  252. package/tests/jest/plugins/plugin.chapters.test.js +195 -0
  253. package/tests/{plugins → jest/plugins}/plugin.iframe.test.js +4 -4
  254. package/tests/{plugins → jest/plugins}/plugin.resume.test.js +22 -35
  255. package/tests/jest/plugins/plugin.text_selection.test.js +316 -0
  256. package/tests/{plugins → jest/plugins}/plugin.vendor-fullscreen.test.js +2 -2
  257. package/tests/{plugins → jest/plugins}/search/plugin.search.test.js +26 -47
  258. package/tests/{plugins → jest/plugins}/search/plugin.search.view.test.js +42 -9
  259. package/tests/jest/plugins/search/utils.js +25 -0
  260. package/tests/jest/plugins/search/utils.test.js +29 -0
  261. package/tests/{plugins → jest/plugins}/tts/AbstractTTSEngine.test.js +30 -10
  262. package/tests/{plugins → jest/plugins}/tts/FestivalTTSEngine.test.js +4 -4
  263. package/tests/{plugins → jest/plugins}/tts/PageChunk.test.js +1 -1
  264. package/tests/{plugins → jest/plugins}/tts/PageChunkIterator.test.js +3 -3
  265. package/tests/{plugins → jest/plugins}/tts/WebTTSEngine.test.js +47 -1
  266. package/tests/{plugins → jest/plugins}/tts/utils.test.js +1 -60
  267. package/tests/jest/plugins/url/UrlPlugin.test.js +198 -0
  268. package/tests/{plugins → jest/plugins/url}/plugin.url.test.js +57 -18
  269. package/tests/jest/setup.js +3 -0
  270. package/tests/{util → jest/util}/browserSniffing.test.js +1 -1
  271. package/tests/jest/util/docCookies.test.js +24 -0
  272. package/tests/{util → jest/util}/strings.test.js +1 -1
  273. package/tests/{utils.js → jest/utils.js} +38 -0
  274. package/webpack.config.js +16 -10
  275. package/.babelrc +0 -12
  276. package/.dependabot/config.yml +0 -6
  277. package/.testcaferc.json +0 -5
  278. package/BookReader/bookreader-component-bundle.js +0 -14330
  279. package/BookReader/bookreader-component-bundle.js.LICENSE.txt +0 -38
  280. package/BookReader/bookreader-component-bundle.js.map +0 -1
  281. package/BookReader/icons/sort-ascending.svg +0 -1
  282. package/BookReader/icons/sort-descending.svg +0 -1
  283. package/BookReader/jquery-1.10.1.js +0 -108
  284. package/BookReader/jquery-1.10.1.js.LICENSE.txt +0 -24
  285. package/BookReader/plugins/plugin.menu_toggle.js +0 -369
  286. package/BookReader/plugins/plugin.menu_toggle.js.map +0 -1
  287. package/BookReader/plugins/plugin.mobile_nav.js +0 -335
  288. package/BookReader/plugins/plugin.mobile_nav.js.map +0 -1
  289. package/BookReaderDemo/BookReaderJSAutoplay.js +0 -56
  290. package/BookReaderDemo/IIIFBookReader.js +0 -207
  291. package/BookReaderDemo/bookreader-template-bundle.js +0 -7178
  292. package/BookReaderDemo/demo-autoplay.html +0 -38
  293. package/BookReaderDemo/demo-iiif.js +0 -26
  294. package/BookReaderDemo/demo-plugin-menu-toggle.html +0 -34
  295. package/karma.conf.js +0 -23
  296. package/src/BookNavigator/BookModel.js +0 -14
  297. package/src/BookNavigator/BookNavigator.js +0 -452
  298. package/src/BookNavigator/assets/book-loader.js +0 -27
  299. package/src/BookNavigator/assets/icon_sort_ascending.js +0 -5
  300. package/src/BookNavigator/assets/icon_sort_descending.js +0 -5
  301. package/src/BookNavigator/br-fullscreen-mgr.js +0 -83
  302. package/src/BookNavigator/search/a-search-result.js +0 -55
  303. package/src/BookNavigator/volumes/volumes-provider.js +0 -108
  304. package/src/BookNavigator/volumes/volumes.js +0 -162
  305. package/src/BookReader/DebugConsole.js +0 -54
  306. package/src/BookReaderComponent/BookReaderComponent.js +0 -112
  307. package/src/ItemNavigator/ItemNavigator.js +0 -372
  308. package/src/ItemNavigator/providers/sharing.js +0 -29
  309. package/src/assets/icons/sort-ascending.svg +0 -1
  310. package/src/assets/icons/sort-descending.svg +0 -1
  311. package/src/css/_MobileNav.scss +0 -194
  312. package/src/dragscrollable-br.js +0 -261
  313. package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
  314. package/src/plugins/plugin.mobile_nav.js +0 -287
  315. package/tests/BookReader/BookReaderPublicFunctions.test.js +0 -171
  316. package/tests/BookReader/DebugConsole.test.js +0 -25
  317. package/tests/BookReader/Mode1Up.test.js +0 -164
  318. package/tests/BookReader/Mode2Up.test.js +0 -247
  319. package/tests/BookReader/PageContainer.test.js +0 -115
  320. package/tests/BookReader/utils.test.js +0 -109
  321. package/tests/e2e/helpers/desktopSearch.js +0 -72
  322. package/tests/e2e/helpers/mobileSearch.js +0 -85
  323. package/tests/e2e/ia-production/ia-prod-base.js +0 -17
  324. package/tests/karma/BookNavigator/book-navigator.test.js +0 -132
  325. package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -201
  326. package/tests/karma/BookNavigator/volumes.test.js +0 -133
  327. package/tests/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
  328. package/tests/plugins/plugin.archive_analytics.test.js +0 -23
  329. package/tests/plugins/plugin.autoplay.test.js +0 -52
  330. package/tests/plugins/plugin.chapters.test.js +0 -130
  331. package/tests/plugins/plugin.mobile_nav.test.js +0 -66
  332. package/tests/plugins/plugin.text_selection.test.js +0 -203
  333. package/tests/util/docCookies.test.js +0 -15
@@ -0,0 +1,590 @@
1
+ // eslint-disable-next-line no-unused-vars
2
+ import { SharedResizeObserver } from '@internetarchive/shared-resize-observer';
3
+ // eslint-disable-next-line no-unused-vars
4
+ import { ModalManager } from '@internetarchive/modal-manager';
5
+ import { css, html, LitElement, nothing } from 'lit';
6
+ import SearchProvider from './search/search-provider.js';
7
+ import DownloadProvider from './downloads/downloads-provider.js';
8
+ import VisualAdjustmentProvider from './visual-adjustments/visual-adjustments-provider.js';
9
+ import BookmarksProvider from './bookmarks/bookmarks-provider.js';
10
+ import SharingProvider from './sharing.js';
11
+ import ViewableFilesProvider from './viewable-files.js';
12
+ import iaLogo from './assets/ia-logo.js';
13
+
14
+ const events = {
15
+ menuUpdated: 'menuUpdated',
16
+ updateSideMenu: 'updateSideMenu',
17
+ PostInit: 'PostInit',
18
+ ViewportInFullScreen: 'ViewportInFullScreen',
19
+ };
20
+ export class BookNavigator extends LitElement {
21
+ static get properties() {
22
+ return {
23
+ itemMD: { type: Object },
24
+ bookReaderLoaded: { type: Boolean },
25
+ bookreader: { type: Object },
26
+ bookIsRestricted: { type: Boolean },
27
+ downloadableTypes: { type: Array },
28
+ isAdmin: { type: Boolean },
29
+ lendingInitialized: { type: Boolean },
30
+ lendingStatus: { type: Object },
31
+ menuProviders: { type: Object },
32
+ menuShortcuts: { type: Array },
33
+ signedIn: { type: Boolean },
34
+ loaded: { type: Boolean },
35
+ sharedObserver: { type: Object, attribute: false },
36
+ modal: { type: Object, attribute: false },
37
+ fullscreenBranding: { type: Object },
38
+ };
39
+ }
40
+
41
+ constructor() {
42
+ super();
43
+ this.itemMD = undefined;
44
+ this.loaded = false;
45
+ this.bookReaderCannotLoad = false;
46
+ this.bookReaderLoaded = false;
47
+ this.bookreader = null;
48
+ this.bookIsRestricted = false;
49
+ this.downloadableTypes = [];
50
+ this.isAdmin = false;
51
+ this.lendingInitialized = false;
52
+ this.lendingStatus = {};
53
+ this.menuProviders = {};
54
+ this.menuShortcuts = [];
55
+ this.signedIn = false;
56
+ /** @type {ModalManager} */
57
+ this.modal = undefined;
58
+ /** @type {SharedResizeObserver} */
59
+ this.sharedObserver = undefined;
60
+ this.fullscreenBranding = iaLogo;
61
+ // Untracked properties
62
+ this.sharedObserverHandler = undefined;
63
+ this.brWidth = 0;
64
+ this.brHeight = 0;
65
+ this.shortcutOrder = [
66
+ /**
67
+ * sets exit FS button (`this.fullscreenBranding1)
68
+ * when `br.options.enableFSLogoShortcut`
69
+ */
70
+ 'fullscreen',
71
+ 'volumes',
72
+ 'chapters',
73
+ 'search',
74
+ 'bookmarks',
75
+ ];
76
+ }
77
+
78
+ disconnectedCallback() {
79
+ this.sharedObserver.removeObserver({
80
+ target: this.mainBRContainer,
81
+ handler: this.sharedObserverHandler,
82
+ });
83
+ }
84
+
85
+ firstUpdated() {
86
+ this.bindEventListeners();
87
+ this.emitPostInit();
88
+ this.loaded = true;
89
+ }
90
+
91
+ updated(changed) {
92
+ if (!this.bookreader || !this.itemMD || !this.bookReaderLoaded) {
93
+ return;
94
+ }
95
+
96
+ const reload = changed.has('loaded') && this.loaded;
97
+ if (reload
98
+ || changed.has('itemMD')
99
+ || changed.has('bookreader')
100
+ || changed.has('signedIn')
101
+ || changed.has('isAdmin')
102
+ || changed.has('modal')) {
103
+ this.initializeBookSubmenus();
104
+ }
105
+
106
+ if (changed.has('sharedObserver') && this.bookreader) {
107
+ this.loadSharedObserver();
108
+ this.initializeBookSubmenus();
109
+ }
110
+
111
+ if (changed.has('downloadableTypes')) {
112
+ this.initializeBookSubmenus();
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Global event emitter for when Book Navigator loads
118
+ */
119
+ emitPostInit() {
120
+ // emit global event when book nav has loaded with current bookreader selector
121
+ this.dispatchEvent(new CustomEvent(`BrBookNav:${events.PostInit}`, {
122
+ detail: { brSelector: this.bookreader?.el },
123
+ bubbles: true,
124
+ composed: true,
125
+ }));
126
+ }
127
+
128
+ /**
129
+ * @typedef {{
130
+ * baseHost: string,
131
+ * modal: ModalManager,
132
+ * sharedObserver: SharedResizeObserver,
133
+ * bookreader: BookReader,
134
+ * item: Item,
135
+ * signedIn: boolean,
136
+ * isAdmin: boolean,
137
+ * onProviderChange: (BookReader, object) => void,
138
+ * }} baseProviderConfig
139
+ *
140
+ * @return {baseProviderConfig}
141
+ */
142
+ get baseProviderConfig() {
143
+ return {
144
+ baseHost: this.baseHost,
145
+ modal: this.modal,
146
+ sharedObserver: this.sharedObserver,
147
+ bookreader: this.bookreader,
148
+ item: this.itemMD,
149
+ signedIn: this.signedIn,
150
+ isAdmin: this.isAdmin,
151
+ onProviderChange: () => {},
152
+ };
153
+ }
154
+
155
+ get isWideEnoughToOpenMenu() {
156
+ return this.brWidth >= 640;
157
+ }
158
+ /**
159
+ * Instantiates books submenus & their update callbacks
160
+ *
161
+ * NOTE: we are doing our best to scope bookreader's instance.
162
+ * If your submenu provider uses a bookreader instance to read, manually
163
+ * manipulate BookReader, please update the navigator's instance of it
164
+ * to keep it in sync.
165
+ */
166
+ initializeBookSubmenus() {
167
+ const providers = {
168
+ visualAdjustments: new VisualAdjustmentProvider({
169
+ ...this.baseProviderConfig,
170
+ /** Update menu contents */
171
+ onProviderChange: () => {
172
+ this.updateMenuContents();
173
+ },
174
+ }),
175
+ };
176
+
177
+ if (this.baseProviderConfig.item) {
178
+ // Share options currently rely on IA item metadata
179
+ providers.share = new SharingProvider(this.baseProviderConfig);
180
+ }
181
+
182
+ if (this.shouldShowDownloadsMenu()) {
183
+ providers.downloads = new DownloadProvider(this.baseProviderConfig);
184
+ }
185
+
186
+ if (this.bookreader.options.enableSearch) {
187
+ providers.search = new SearchProvider({
188
+ ...this.baseProviderConfig,
189
+ /**
190
+ * Search specific menu updates
191
+ * @param {BookReader} brInstance
192
+ * @param {{ searchCanceled: boolean }} searchUpdates
193
+ */
194
+ onProviderChange: (brInstance = null, searchUpdates = {}) => {
195
+ if (brInstance) {
196
+ /* refresh br instance reference */
197
+ this.bookreader = brInstance;
198
+ }
199
+
200
+ this.updateMenuContents();
201
+
202
+ if (searchUpdates.openMenu === false) {
203
+ return;
204
+ }
205
+
206
+ if (this.isWideEnoughToOpenMenu && !searchUpdates?.searchCanceled) {
207
+ /* open side search menu */
208
+ setTimeout(() => {
209
+ this.updateSideMenu('search', 'open');
210
+ }, 0);
211
+ }
212
+ },
213
+ });
214
+ }
215
+
216
+ if (this.bookreader.options.enableBookmarks) {
217
+ providers.bookmarks = new BookmarksProvider({
218
+ ...this.baseProviderConfig,
219
+ onProviderChange: (bookmarks) => {
220
+ const method = Object.keys(bookmarks).length ? 'add' : 'remove';
221
+ this[`${method}MenuShortcut`]('bookmarks');
222
+ this.updateMenuContents();
223
+ },
224
+ });
225
+ }
226
+
227
+ // add shortcut for volumes if multipleBooksList exists
228
+ if (this.bookreader.options.enableMultipleBooks) {
229
+ providers.volumes = new ViewableFilesProvider({
230
+ ...this.baseProviderConfig,
231
+ onProviderChange: (brInstance = null, volumesUpdates = {}) => {
232
+ if (brInstance) {
233
+ /* refresh br instance reference */
234
+ this.bookreader = brInstance;
235
+ }
236
+ this.updateMenuContents();
237
+ if (this.isWideEnoughToOpenMenu) {
238
+ /* open side search menu */
239
+ setTimeout(() => {
240
+ this.updateSideMenu('volumes', 'open');
241
+ });
242
+ }
243
+ },
244
+ });
245
+ }
246
+
247
+ Object.assign(this.menuProviders, providers);
248
+ this.addMenuShortcut('search');
249
+ this.addMenuShortcut('volumes');
250
+ this.updateMenuContents();
251
+ }
252
+
253
+ /** gets element that houses the bookreader in light dom */
254
+ get mainBRContainer() {
255
+ return document.querySelector(this.bookreader?.el);
256
+ }
257
+
258
+ /** Fullscreen Shortcut */
259
+ addFullscreenShortcut() {
260
+ const closeFS = {
261
+ icon: this.fullscreenShortcut,
262
+ id: 'fullscreen',
263
+ };
264
+ this.menuShortcuts.push(closeFS);
265
+ this.sortMenuShortcuts();
266
+ this.emitMenuShortcutsUpdated();
267
+ }
268
+
269
+ deleteFullscreenShortcut() {
270
+ const updatedShortcuts = this.menuShortcuts.filter(({ id }) => {
271
+ return id !== 'fullscreen';
272
+ });
273
+ this.menuShortcuts = updatedShortcuts;
274
+ this.sortMenuShortcuts();
275
+ this.emitMenuShortcutsUpdated();
276
+ }
277
+
278
+ closeFullscreen() {
279
+ this.bookreader.exitFullScreen();
280
+ }
281
+
282
+ get fullscreenShortcut() {
283
+ return html`
284
+ <button
285
+ @click=${() => this.closeFullscreen()}
286
+ title="Exit fullscreen view"
287
+ >${this.fullscreenBranding}</button>
288
+ `;
289
+ }
290
+ /** End Fullscreen Shortcut */
291
+
292
+ /**
293
+ * Open side menu
294
+ * @param {string} menuId
295
+ * @param {('open'|'close'|'toggle')} action
296
+ */
297
+ updateSideMenu(menuId = '', action = 'open') {
298
+ if (!menuId) {
299
+ return;
300
+ }
301
+ const event = new CustomEvent(
302
+ events.updateSideMenu, {
303
+ detail: { menuId, action },
304
+ },
305
+ );
306
+ this.dispatchEvent(event);
307
+ }
308
+
309
+ /**
310
+ * Sets order of menu and emits custom event when done
311
+ */
312
+ updateMenuContents() {
313
+ const {
314
+ search, downloads, visualAdjustments, share, bookmarks, volumes, chapters,
315
+ } = this.menuProviders;
316
+ const availableMenus = [volumes, chapters, search, bookmarks, visualAdjustments, share].filter((menu) => !!menu);
317
+
318
+ if (this.shouldShowDownloadsMenu()) {
319
+ downloads?.update(this.downloadableTypes);
320
+ availableMenus.splice(-2, 0, downloads);
321
+ }
322
+
323
+ const event = new CustomEvent(
324
+ events.menuUpdated, {
325
+ detail: availableMenus,
326
+ },
327
+ );
328
+ this.dispatchEvent(event);
329
+ }
330
+
331
+ /**
332
+ * Confirms if we should show the downloads menu
333
+ * @returns {bool}
334
+ */
335
+ shouldShowDownloadsMenu() {
336
+ if (!this.downloadableTypes.length) { return false; }
337
+ if (this.bookIsRestricted === false) { return true; }
338
+ if (this.isAdmin) { return true; }
339
+ const { user_loan_record = {} } = this.lendingStatus;
340
+ const hasNoLoanRecord = Array.isArray(user_loan_record); /* (bc PHP assoc. arrays) */
341
+
342
+ if (hasNoLoanRecord) { return false; }
343
+
344
+ const hasValidLoan = user_loan_record.type && (user_loan_record.type !== 'SESSION_LOAN');
345
+ return hasValidLoan;
346
+ }
347
+
348
+ /**
349
+ * Adds a provider object to the menuShortcuts array property if it isn't
350
+ * already added. menuShortcuts are then sorted by shortcutOrder and
351
+ * a menuShortcutsUpdated event is emitted.
352
+ *
353
+ * @param {string} menuId - a string matching the id property of a provider
354
+ */
355
+ addMenuShortcut(menuId) {
356
+ if (this.menuShortcuts.find((m) => m.id === menuId)) {
357
+ // menu is already there
358
+ return;
359
+ }
360
+
361
+ if (!this.menuProviders[menuId]) {
362
+ // no provider for this menu
363
+ return;
364
+ }
365
+
366
+ this.menuShortcuts.push(this.menuProviders[menuId]);
367
+ this.sortMenuShortcuts();
368
+ this.emitMenuShortcutsUpdated();
369
+ }
370
+
371
+ /**
372
+ * Removes a provider object from the menuShortcuts array and emits a
373
+ * menuShortcutsUpdated event.
374
+ *
375
+ * @param {string} menuId - a string matching the id property of a provider
376
+ */
377
+ removeMenuShortcut(menuId) {
378
+ this.menuShortcuts = this.menuShortcuts.filter((m) => m.id !== menuId);
379
+ this.emitMenuShortcutsUpdated();
380
+ }
381
+
382
+ /**
383
+ * Sorts the menuShortcuts property by comparing each provider's id to
384
+ * the id in each iteration over the shortcutOrder array.
385
+ */
386
+ sortMenuShortcuts() {
387
+ this.menuShortcuts = this.shortcutOrder.reduce((shortcuts, id) => {
388
+ const menu = this.menuShortcuts.find((m) => m.id === id);
389
+ if (menu) { shortcuts.push(menu); }
390
+ return shortcuts;
391
+ }, []);
392
+ }
393
+
394
+ emitMenuShortcutsUpdated() {
395
+ const event = new CustomEvent('menuShortcutsUpdated', {
396
+ detail: this.menuShortcuts,
397
+ });
398
+ this.dispatchEvent(event);
399
+ }
400
+
401
+ emitLoadingStatusUpdate(loaded) {
402
+ const event = new CustomEvent('loadingStateUpdated', {
403
+ detail: { loaded },
404
+ });
405
+ this.dispatchEvent(event);
406
+ }
407
+
408
+ /**
409
+ * Core bookreader event handler registry
410
+ *
411
+ * NOTE: we are trying to keep bookreader's instance in scope
412
+ * Please update Book Navigator's instance reference of it to keep it current
413
+ */
414
+ bindEventListeners() {
415
+ window.addEventListener('BookReader:PostInit', (e) => {
416
+ this.bookreader = e.detail.props;
417
+ this.bookreader.shell = this;
418
+ this.bookReaderLoaded = true;
419
+ this.bookReaderCannotLoad = false;
420
+ this.emitLoadingStatusUpdate(true);
421
+ this.loadSharedObserver();
422
+ setTimeout(() => {
423
+ this.bookreader.resize();
424
+ }, 0);
425
+ });
426
+ window.addEventListener('BookReader:fullscreenToggled', (event) => {
427
+ const { detail: { props: brInstance = null } } = event;
428
+ if (brInstance) {
429
+ this.bookreader = brInstance;
430
+ }
431
+ this.manageFullScreenBehavior();
432
+ }, { passive: true });
433
+ window.addEventListener('BookReader:ToggleSearchMenu', (event) => {
434
+ this.dispatchEvent(new CustomEvent(events.updateSideMenu, {
435
+ detail: { menuId: 'search', action: 'toggle' },
436
+ }));
437
+ });
438
+ window.addEventListener('LendingFlow:PostInit', ({ detail }) => {
439
+ const {
440
+ downloadTypesAvailable, lendingStatus, isAdmin, previewType,
441
+ } = detail;
442
+ this.lendingInitialized = true;
443
+ this.downloadableTypes = downloadTypesAvailable;
444
+ this.lendingStatus = lendingStatus;
445
+ this.isAdmin = isAdmin;
446
+ this.bookReaderCannotLoad = previewType === 'singlePagePreview';
447
+ this.emitLoadingStatusUpdate(true);
448
+ });
449
+ window.addEventListener('BRJSIA:PostInit', ({ detail }) => {
450
+ const { isRestricted, downloadURLs } = detail;
451
+ this.bookReaderLoaded = true;
452
+ this.downloadableTypes = downloadURLs;
453
+ this.bookIsRestricted = isRestricted;
454
+ });
455
+ window.addEventListener('contextmenu', (e) => this.manageContextMenuVisibility(e), { capture: true });
456
+ }
457
+
458
+ /** Display an element's context menu */
459
+ manageContextMenuVisibility(e) {
460
+ window.archive_analytics?.send_event(
461
+ 'BookReader',
462
+ `contextmenu-${this.bookIsRestricted ? 'restricted' : 'unrestricted'}`,
463
+ e.target?.classList?.value,
464
+ );
465
+ if (!this.bookIsRestricted) {
466
+ return;
467
+ }
468
+
469
+ const imagePane = e.target.classList.value.match(/BRscreen|BRpageimage/g);
470
+ if (!imagePane) {
471
+ return;
472
+ }
473
+
474
+ e.preventDefault();
475
+ return false;
476
+ }
477
+
478
+ loadSharedObserver() {
479
+ this.sharedObserverHandler = { handleResize: this.handleResize.bind(this) };
480
+ this.sharedObserver?.addObserver({
481
+ target: this.mainBRContainer,
482
+ handler: this.sharedObserverHandler,
483
+ });
484
+ }
485
+
486
+ /**
487
+ * Uses resize observer to fire BookReader's `resize` functionality
488
+ * We do not want to trigger resize IF:
489
+ * - book animation is happening
490
+ * - book is in fullscreen (fullscreen is handled separately)
491
+ *
492
+ * @param { target: HTMLElement, contentRect: DOMRectReadOnly } entry
493
+ */
494
+ handleResize({ contentRect, target }) {
495
+ const startBrWidth = this.brWidth;
496
+ const startBrHeight = this.brHeight;
497
+ const { animating } = this.bookreader;
498
+
499
+ if (target === this.mainBRContainer) {
500
+ this.brWidth = contentRect.width;
501
+ this.brHeight = contentRect.height;
502
+ }
503
+
504
+ if (!startBrWidth && this.brWidth) {
505
+ // loading up, let's update side menus
506
+ this.initializeBookSubmenus();
507
+ }
508
+
509
+ const widthChange = startBrWidth !== this.brWidth;
510
+ const heightChange = startBrHeight !== this.brHeight;
511
+
512
+ if (!animating && (widthChange || heightChange)) {
513
+ this.bookreader?.resize();
514
+ }
515
+ }
516
+
517
+ /**
518
+ * Manages Fullscreen behavior
519
+ * This makes sure that controls are _always_ in view
520
+ * We need this to accommodate LOAN BAR during fullscreen
521
+ */
522
+ manageFullScreenBehavior() {
523
+ this.emitFullScreenState();
524
+
525
+ if (!this.bookreader.options.enableFSLogoShortcut) {
526
+ return;
527
+ }
528
+
529
+ const isFullScreen = this.bookreader.isFullscreen();
530
+ if (isFullScreen) {
531
+ this.addFullscreenShortcut();
532
+ } else {
533
+ this.deleteFullscreenShortcut();
534
+ }
535
+ }
536
+
537
+ /**
538
+ * Relays fullscreen toggle events
539
+ */
540
+ emitFullScreenState() {
541
+ const isFullScreen = this.bookreader.isFullscreen();
542
+ const event = new CustomEvent('ViewportInFullScreen', {
543
+ detail: { isFullScreen },
544
+ });
545
+ this.dispatchEvent(event);
546
+ }
547
+
548
+ get itemImage() {
549
+ const identifier = this.itemMD?.metadata.identifier;
550
+ const url = `https://${this.baseHost}/services/img/${identifier}`;
551
+ return html`<img class="cover-img" src=${url} alt="cover image for ${identifier}">`;
552
+ }
553
+
554
+ get placeholder() {
555
+ return html`<div class="placeholder">${this.itemImage}</div>`;
556
+ }
557
+
558
+ render() {
559
+ return html`<div id="book-navigator__root">
560
+ ${this.bookReaderCannotLoad ? this.placeholder : nothing}
561
+ ${!this.bookReaderCannotLoad ? html`<slot name="main"></slot>` : nothing}
562
+ </div>
563
+ `;
564
+ }
565
+
566
+ static get styles() {
567
+ return css`
568
+ :host,
569
+ #book-navigator__root,
570
+ slot,
571
+ slot > * {
572
+ display: block;
573
+ height: inherit;
574
+ width: inherit;
575
+ }
576
+ .placeholder {
577
+ display: flex;
578
+ align-items: center;
579
+ justify-content: center;
580
+ flex-direction: column;
581
+ margin: 5%;
582
+ }
583
+ .cover-img {
584
+ max-height: 300px;
585
+ }
586
+ `;
587
+ }
588
+ }
589
+
590
+ customElements.define('book-navigator', BookNavigator);
@@ -1,4 +1,4 @@
1
- import { LitElement, html, css } from 'lit-element';
1
+ import { LitElement, html, css } from 'lit';
2
2
 
3
3
  export default class BookmarkButton extends LitElement {
4
4
  static get styles() {
@@ -12,7 +12,7 @@ export default class BookmarkButton extends LitElement {
12
12
  height: 4rem;
13
13
  width: 4rem;
14
14
  background: transparent;
15
- cursor: url('/images/bookreader/bookmark-add.png'), pointer;
15
+ cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24' viewBox='0 0 16 24' width='16'%3E%3Cg fill='%23333' fill-rule='evenodd'%3E%3Cpath d='m15 0c.5522847 0 1 .44771525 1 1v23l-8-5.4545455-8 5.4545455v-23c0-.55228475.44771525-1 1-1zm-2 2h-10c-.51283584 0-.93550716.38604019-.99327227.88337887l-.00672773.11662113v18l6-4.3181818 6 4.3181818v-18c0-.51283584-.3860402-.93550716-.8833789-.99327227z'/%3E%3Cpath d='m8.75 6v2.25h2.25v1.5h-2.25v2.25h-1.5v-2.25h-2.25v-1.5h2.25v-2.25z' fill-rule='nonzero'/%3E%3C/g%3E%3C/svg%3E"), pointer;
16
16
  position: relative;
17
17
  }
18
18
  button > * {
@@ -40,6 +40,7 @@ export default class BookmarkButton extends LitElement {
40
40
  constructor() {
41
41
  super();
42
42
  this.state = 'hollow';
43
+ this.side = undefined;
43
44
  }
44
45
 
45
46
  handleClick(e) {
@@ -1,6 +1,5 @@
1
- import { nothing } from 'lit-html';
2
- import { repeat } from 'lit-html/directives/repeat.js';
3
- import { css, html, LitElement } from 'lit-element';
1
+ import { repeat } from 'lit/directives/repeat.js';
2
+ import { css, html, LitElement, nothing } from 'lit';
4
3
  import bookmarkColorsCSS from '../assets/bookmark-colors.js';
5
4
  import buttonCSS from '../assets/button-base.js';
6
5
 
@@ -208,7 +207,7 @@ export class IABookmarkEdit extends LitElement {
208
207
  grid-gap: 0 1rem;
209
208
  justify-items: stretch;
210
209
  }
211
- `
210
+ `;
212
211
  return [buttonCSS, bookmarkColorsCSS, bookmarkEditCSS];
213
212
  }
214
213
  }
@@ -1,6 +1,5 @@
1
- import { nothing } from 'lit-html';
2
- import { repeat } from 'lit-html/directives/repeat.js';
3
- import { css, html, LitElement } from 'lit-element';
1
+ import { repeat } from 'lit/directives/repeat.js';
2
+ import { css, html, LitElement, nothing } from 'lit';
4
3
  import './bookmark-edit.js';
5
4
  import '@internetarchive/icon-edit-pencil/icon-edit-pencil.js';
6
5
  import bookmarkColorsCSS from '../assets/bookmark-colors.js';
@@ -1,20 +1,15 @@
1
- import { LitElement, html, css } from 'lit-element';
1
+ import { LitElement, html } from 'lit';
2
2
  import buttonStyles from '../assets/button-base.js';
3
3
 
4
4
  class BookmarksLogin extends LitElement {
5
5
  static get properties() {
6
6
  return {
7
- url: { type: String }
8
- }
7
+ url: { type: String },
8
+ };
9
9
  }
10
10
 
11
11
  static get styles() {
12
- const mainCss = css`
13
- a {
14
- text-decoration: none;
15
- }
16
- `;
17
- return [buttonStyles, mainCss];
12
+ return buttonStyles;
18
13
  }
19
14
 
20
15
  constructor() {