@internetarchive/bookreader 5.0.0-4 → 5.0.0-40-a1

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 (228) hide show
  1. package/.eslintrc.js +17 -15
  2. package/.github/workflows/node.js.yml +75 -4
  3. package/.github/workflows/npm-publish.yml +2 -16
  4. package/.testcaferc.js +10 -0
  5. package/BookReader/BookReader.css +83 -323
  6. package/BookReader/BookReader.js +1 -1
  7. package/BookReader/BookReader.js.LICENSE.txt +24 -0
  8. package/BookReader/BookReader.js.map +1 -1
  9. package/BookReader/ia-bookreader-bundle.js +1623 -0
  10. package/BookReader/{bookreader-component-bundle.js.LICENSE.txt → ia-bookreader-bundle.js.LICENSE.txt} +14 -10
  11. package/BookReader/ia-bookreader-bundle.js.map +1 -0
  12. package/BookReader/icons/close-circle-dark.svg +1 -0
  13. package/BookReader/icons/magnify-minus.svg +1 -1
  14. package/BookReader/icons/magnify-plus.svg +1 -1
  15. package/BookReader/icons/voice.svg +1 -0
  16. package/BookReader/plugins/plugin.archive_analytics.js +1 -1
  17. package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
  18. package/BookReader/plugins/plugin.autoplay.js +1 -1
  19. package/BookReader/plugins/plugin.autoplay.js.map +1 -1
  20. package/BookReader/plugins/plugin.chapters.js +1 -1
  21. package/BookReader/plugins/plugin.chapters.js.map +1 -1
  22. package/BookReader/plugins/plugin.iframe.js +1 -1
  23. package/BookReader/plugins/plugin.iframe.js.map +1 -1
  24. package/BookReader/plugins/plugin.mobile_nav.js +1 -1
  25. package/BookReader/plugins/plugin.mobile_nav.js.map +1 -1
  26. package/BookReader/plugins/plugin.resume.js +1 -1
  27. package/BookReader/plugins/plugin.resume.js.map +1 -1
  28. package/BookReader/plugins/plugin.search.js +1 -1
  29. package/BookReader/plugins/plugin.search.js.map +1 -1
  30. package/BookReader/plugins/plugin.text_selection.js +1 -1
  31. package/BookReader/plugins/plugin.text_selection.js.map +1 -1
  32. package/BookReader/plugins/plugin.tts.js +1 -1
  33. package/BookReader/plugins/plugin.tts.js.map +1 -1
  34. package/BookReader/plugins/plugin.url.js +1 -1
  35. package/BookReader/plugins/plugin.url.js.map +1 -1
  36. package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -1
  37. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
  38. package/BookReader/webcomponents-bundle.js +3 -0
  39. package/BookReader/webcomponents-bundle.js.LICENSE.txt +9 -0
  40. package/BookReader/webcomponents-bundle.js.map +1 -0
  41. package/BookReaderDemo/BookReaderDemo.css +14 -1
  42. package/BookReaderDemo/IADemoBr.js +120 -0
  43. package/BookReaderDemo/demo-advanced.html +1 -1
  44. package/BookReaderDemo/demo-autoplay.html +1 -0
  45. package/BookReaderDemo/demo-embed-iframe-src.html +1 -0
  46. package/BookReaderDemo/demo-fullscreen-mobile.html +1 -0
  47. package/BookReaderDemo/demo-fullscreen.html +1 -0
  48. package/BookReaderDemo/demo-iiif.html +1 -0
  49. package/BookReaderDemo/demo-internetarchive.html +74 -17
  50. package/BookReaderDemo/demo-multiple.html +1 -0
  51. package/BookReaderDemo/demo-preview-pages.html +1 -0
  52. package/BookReaderDemo/demo-simple.html +1 -0
  53. package/BookReaderDemo/demo-vendor-fullscreen.html +1 -0
  54. package/BookReaderDemo/ia-multiple-volumes-manifest.js +170 -0
  55. package/BookReaderDemo/immersion-1up.html +1 -0
  56. package/BookReaderDemo/immersion-mode.html +1 -0
  57. package/BookReaderDemo/toggle_controls.html +1 -0
  58. package/BookReaderDemo/view_mode.html +1 -0
  59. package/BookReaderDemo/viewmode-cycle.html +1 -2
  60. package/CHANGELOG.md +166 -0
  61. package/README.md +14 -1
  62. package/babel.config.js +18 -0
  63. package/codecov.yml +6 -0
  64. package/index.html +3 -0
  65. package/jsconfig.json +19 -0
  66. package/package.json +62 -47
  67. package/renovate.json +43 -0
  68. package/src/BookNavigator/assets/bookmark-colors.js +1 -1
  69. package/src/BookNavigator/assets/button-base.js +9 -2
  70. package/src/BookNavigator/assets/ia-logo.js +17 -0
  71. package/src/BookNavigator/assets/icon_checkmark.js +1 -1
  72. package/src/BookNavigator/assets/icon_close.js +1 -1
  73. package/src/BookNavigator/assets/icon_sort_asc.js +5 -0
  74. package/src/BookNavigator/assets/icon_sort_desc.js +5 -0
  75. package/src/BookNavigator/assets/icon_sort_neutral.js +5 -0
  76. package/src/BookNavigator/assets/icon_volumes.js +11 -0
  77. package/src/BookNavigator/book-navigator.js +556 -0
  78. package/src/BookNavigator/bookmarks/bookmark-button.js +3 -2
  79. package/src/BookNavigator/bookmarks/bookmark-edit.js +4 -4
  80. package/src/BookNavigator/bookmarks/bookmarks-list.js +3 -3
  81. package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +3 -8
  82. package/src/BookNavigator/bookmarks/bookmarks-provider.js +23 -12
  83. package/src/BookNavigator/bookmarks/ia-bookmarks.js +98 -62
  84. package/src/BookNavigator/delete-modal-actions.js +1 -1
  85. package/src/BookNavigator/downloads/downloads-provider.js +23 -17
  86. package/src/BookNavigator/downloads/downloads.js +17 -25
  87. package/src/BookNavigator/search/a-search-result.js +3 -3
  88. package/src/BookNavigator/search/search-provider.js +57 -24
  89. package/src/BookNavigator/search/search-results.js +8 -20
  90. package/src/BookNavigator/sharing.js +27 -0
  91. package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +11 -13
  92. package/src/BookNavigator/visual-adjustments/visual-adjustments.js +4 -3
  93. package/src/BookNavigator/volumes/volumes-provider.js +114 -0
  94. package/src/BookNavigator/volumes/volumes.js +188 -0
  95. package/src/BookReader/DebugConsole.js +3 -3
  96. package/src/BookReader/DragScrollable.js +233 -0
  97. package/src/BookReader/Mode1Up.js +51 -351
  98. package/src/BookReader/Mode1UpLit.js +441 -0
  99. package/src/BookReader/Mode2Up.js +104 -71
  100. package/src/BookReader/ModeSmoothZoom.js +179 -0
  101. package/src/BookReader/ModeThumb.js +16 -8
  102. package/src/BookReader/Navbar/Navbar.js +2 -31
  103. package/src/BookReader/PageContainer.js +57 -6
  104. package/src/BookReader/ReduceSet.js +1 -1
  105. package/src/BookReader/Toolbar/Toolbar.js +7 -7
  106. package/src/BookReader/options.js +10 -0
  107. package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
  108. package/src/BookReader/utils/ScrollClassAdder.js +31 -0
  109. package/src/BookReader/utils.js +68 -13
  110. package/src/BookReader.js +375 -289
  111. package/src/assets/icons/close-circle-dark.svg +1 -0
  112. package/src/assets/icons/magnify-minus.svg +3 -7
  113. package/src/assets/icons/magnify-plus.svg +3 -7
  114. package/src/assets/icons/voice.svg +1 -0
  115. package/src/css/BookReader.scss +0 -12
  116. package/src/css/_BRComponent.scss +1 -1
  117. package/src/css/_BRmain.scss +19 -24
  118. package/src/css/_BRnav.scss +4 -26
  119. package/src/css/_BRpages.scss +35 -0
  120. package/src/css/_BRsearch.scss +11 -215
  121. package/src/css/_TextSelection.scss +14 -17
  122. package/src/css/_colorbox.scss +2 -2
  123. package/src/css/_controls.scss +16 -3
  124. package/src/css/_icons.scss +6 -0
  125. package/src/ia-bookreader/ia-bookreader.js +224 -0
  126. package/src/plugins/plugin.chapters.js +26 -33
  127. package/src/plugins/plugin.mobile_nav.js +11 -10
  128. package/src/plugins/plugin.resume.js +3 -3
  129. package/src/plugins/plugin.text_selection.js +26 -39
  130. package/src/plugins/plugin.vendor-fullscreen.js +4 -4
  131. package/src/plugins/search/plugin.search.js +106 -107
  132. package/src/plugins/search/view.js +50 -163
  133. package/src/plugins/tts/AbstractTTSEngine.js +46 -37
  134. package/src/plugins/tts/FestivalTTSEngine.js +12 -13
  135. package/src/plugins/tts/PageChunk.js +15 -21
  136. package/src/plugins/tts/PageChunkIterator.js +8 -12
  137. package/src/plugins/tts/WebTTSEngine.js +64 -68
  138. package/src/plugins/tts/plugin.tts.js +79 -108
  139. package/src/plugins/url/UrlPlugin.js +184 -0
  140. package/src/plugins/{plugin.url.js → url/plugin.url.js} +28 -6
  141. package/tests/e2e/README.md +37 -0
  142. package/tests/e2e/autoplay.test.js +2 -2
  143. package/tests/e2e/base.test.js +7 -7
  144. package/tests/e2e/helpers/base.js +8 -3
  145. package/tests/e2e/helpers/debug.js +1 -1
  146. package/tests/e2e/helpers/desktopSearch.js +14 -13
  147. package/tests/e2e/helpers/mobileSearch.js +3 -3
  148. package/tests/e2e/helpers/params.js +17 -0
  149. package/tests/e2e/models/Navigation.js +12 -3
  150. package/tests/e2e/rightToLeft.test.js +4 -5
  151. package/tests/e2e/viewmode.test.js +38 -33
  152. package/tests/{BookReader → jest/BookReader}/BookModel.test.js +3 -3
  153. package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +176 -0
  154. package/tests/{BookReader → jest/BookReader}/DebugConsole.test.js +1 -1
  155. package/tests/{BookReader → jest/BookReader}/ImageCache.test.js +4 -4
  156. package/tests/jest/BookReader/Mode1UpLit.test.js +88 -0
  157. package/tests/{BookReader → jest/BookReader}/Mode2Up.test.js +5 -7
  158. package/tests/jest/BookReader/ModeSmoothZoom.test.js +149 -0
  159. package/tests/jest/BookReader/ModeThumb.test.js +71 -0
  160. package/tests/{BookReader → jest/BookReader}/Navbar/Navbar.test.js +7 -7
  161. package/tests/{BookReader → jest/BookReader}/PageContainer.test.js +79 -6
  162. package/tests/{BookReader → jest/BookReader}/ReduceSet.test.js +1 -1
  163. package/tests/{BookReader → jest/BookReader}/Toolbar/Toolbar.test.js +2 -2
  164. package/tests/jest/BookReader/utils/HTMLDimensionsCacher.test.js +59 -0
  165. package/tests/jest/BookReader/utils/ScrollClassAdder.test.js +49 -0
  166. package/tests/{BookReader → jest/BookReader}/utils/classes.test.js +1 -1
  167. package/tests/jest/BookReader/utils.test.js +136 -0
  168. package/tests/jest/BookReader.keyboard.test.js +190 -0
  169. package/tests/{BookReader.options.test.js → jest/BookReader.options.test.js} +9 -1
  170. package/tests/{BookReader.test.js → jest/BookReader.test.js} +20 -4
  171. package/tests/{plugins → jest/plugins}/plugin.archive_analytics.test.js +2 -2
  172. package/tests/{plugins → jest/plugins}/plugin.autoplay.test.js +2 -2
  173. package/tests/{plugins → jest/plugins}/plugin.chapters.test.js +8 -8
  174. package/tests/{plugins → jest/plugins}/plugin.iframe.test.js +2 -2
  175. package/tests/{plugins → jest/plugins}/plugin.mobile_nav.test.js +5 -5
  176. package/tests/{plugins → jest/plugins}/plugin.resume.test.js +3 -3
  177. package/tests/{plugins → jest/plugins}/plugin.text_selection.test.js +39 -47
  178. package/tests/{plugins → jest/plugins}/plugin.vendor-fullscreen.test.js +2 -2
  179. package/tests/{plugins → jest/plugins}/search/plugin.search.test.js +24 -25
  180. package/tests/{plugins → jest/plugins}/search/plugin.search.view.test.js +6 -6
  181. package/tests/{plugins → jest/plugins}/tts/AbstractTTSEngine.test.js +6 -6
  182. package/tests/{plugins → jest/plugins}/tts/FestivalTTSEngine.test.js +4 -4
  183. package/tests/{plugins → jest/plugins}/tts/PageChunk.test.js +1 -1
  184. package/tests/{plugins → jest/plugins}/tts/PageChunkIterator.test.js +3 -3
  185. package/tests/{plugins → jest/plugins}/tts/WebTTSEngine.test.js +1 -1
  186. package/tests/{plugins → jest/plugins}/tts/utils.test.js +3 -3
  187. package/tests/jest/plugins/url/UrlPlugin.test.js +190 -0
  188. package/tests/{plugins → jest/plugins/url}/plugin.url.test.js +33 -14
  189. package/tests/{util → jest/util}/browserSniffing.test.js +1 -1
  190. package/tests/{util → jest/util}/docCookies.test.js +1 -1
  191. package/tests/{util → jest/util}/strings.test.js +1 -1
  192. package/tests/{utils.js → jest/utils.js} +38 -0
  193. package/tests/karma/BookNavigator/book-navigator.test.js +501 -0
  194. package/tests/karma/BookNavigator/bookmarks/bookmark-button.test.js +44 -0
  195. package/tests/karma/BookNavigator/bookmarks/bookmark-edit.test.js +1 -3
  196. package/tests/karma/BookNavigator/bookmarks/bookmarks-list.test.js +3 -4
  197. package/tests/karma/BookNavigator/bookmarks/ia-bookmarks.test.js +57 -0
  198. package/tests/karma/BookNavigator/downloads/downloads-provider.test.js +67 -0
  199. package/tests/karma/BookNavigator/downloads/downloads.test.js +54 -0
  200. package/tests/karma/BookNavigator/search/search-provider.test.js +123 -0
  201. package/tests/karma/BookNavigator/{search-results.test.js → search/search-results.test.js} +1 -4
  202. package/tests/karma/BookNavigator/sharing/sharing-provider.test.js +49 -0
  203. package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -2
  204. package/tests/karma/BookNavigator/volumes/volumes-provider.test.js +184 -0
  205. package/tests/karma/BookNavigator/volumes/volumes.test.js +98 -0
  206. package/webpack.config.js +10 -4
  207. package/.babelrc +0 -12
  208. package/.dependabot/config.yml +0 -6
  209. package/.testcaferc.json +0 -5
  210. package/BookReader/bookreader-component-bundle.js +0 -1450
  211. package/BookReader/bookreader-component-bundle.js.map +0 -1
  212. package/BookReader/plugins/plugin.menu_toggle.js +0 -2
  213. package/BookReader/plugins/plugin.menu_toggle.js.map +0 -1
  214. package/BookReaderDemo/bookreader-template-bundle.js +0 -7178
  215. package/BookReaderDemo/demo-plugin-menu-toggle.html +0 -34
  216. package/src/BookNavigator/BookModel.js +0 -14
  217. package/src/BookNavigator/BookNavigator.js +0 -435
  218. package/src/BookNavigator/assets/book-loader.js +0 -27
  219. package/src/BookNavigator/br-fullscreen-mgr.js +0 -83
  220. package/src/BookReaderComponent/BookReaderComponent.js +0 -112
  221. package/src/ItemNavigator/ItemNavigator.js +0 -372
  222. package/src/ItemNavigator/providers/sharing.js +0 -29
  223. package/src/dragscrollable-br.js +0 -261
  224. package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
  225. package/tests/BookReader/BookReaderPublicFunctions.test.js +0 -171
  226. package/tests/BookReader/Mode1Up.test.js +0 -164
  227. package/tests/BookReader/utils.test.js +0 -109
  228. package/tests/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
@@ -1,12 +1,11 @@
1
1
  /* eslint-disable class-methods-use-this */
2
- import { nothing } from 'lit-html';
3
- import { css, html, LitElement } from 'lit-element';
2
+ import { css, html, LitElement, nothing } from 'lit';
4
3
  import '@internetarchive/ia-activity-indicator/ia-activity-indicator';
5
- import { BookSearchResult } from './a-search-result.js';
4
+ import './a-search-result.js';
6
5
  import checkmarkIcon from '../assets/icon_checkmark.js';
7
6
  import closeIcon from '../assets/icon_close.js';
7
+ import buttonCSS from '../assets/button-base.js';
8
8
 
9
- customElements.define('book-search-result', BookSearchResult);
10
9
 
11
10
  export class IABookSearchResults extends LitElement {
12
11
  static get properties() {
@@ -91,10 +90,7 @@ export class IABookSearchResults extends LitElement {
91
90
  }
92
91
 
93
92
  dispatchSearchCanceled() {
94
- this.dispatchEvent(new CustomEvent('bookSearchCanceled', {
95
- bubbles: true,
96
- composed: true,
97
- }));
93
+ this.dispatchEvent(new Event('bookSearchCanceled'));
98
94
  }
99
95
 
100
96
  get resultsCount() {
@@ -123,6 +119,7 @@ export class IABookSearchResults extends LitElement {
123
119
  <div class="loading">
124
120
  <ia-activity-indicator mode="processing"></ia-activity-indicator>
125
121
  <p>Searching</p>
122
+ <button class="ia-button external cancel-search" @click=${this.cancelSearch}>Cancel</button>
126
123
  </div>
127
124
  `;
128
125
  }
@@ -189,7 +186,7 @@ export class IABookSearchResults extends LitElement {
189
186
  const searchResultBorder = css`var(--searchResultBorder, #adaedc)`;
190
187
  const activeButtonBg = css`(--tertiaryBGColor, #333)`;
191
188
 
192
- return css`
189
+ const mainCSS = css`
193
190
  :host {
194
191
  display: block;
195
192
  height: 100%;
@@ -349,17 +346,6 @@ export class IABookSearchResults extends LitElement {
349
346
  font-size: 1.2rem;
350
347
  }
351
348
 
352
- .loading button {
353
- -webkit-appearance: none;
354
- appearance: none;
355
- padding: .5rem .7rem;
356
- font: normal 1.4rem "Helvetica Neue", Helvetica, Arial, sans-serif;
357
- border: 1px solid #656565;
358
- border-radius: 3px;
359
- cursor: pointer;
360
- background: transparent;
361
- }
362
-
363
349
  ia-activity-indicator {
364
350
  display: block;
365
351
  width: 40px;
@@ -367,5 +353,7 @@ export class IABookSearchResults extends LitElement {
367
353
  margin: 0 auto;
368
354
  }
369
355
  `;
356
+ return [buttonCSS, mainCSS];
370
357
  }
371
358
  }
359
+ customElements.define('ia-book-search-results', IABookSearchResults);
@@ -0,0 +1,27 @@
1
+ import { html } from 'lit';
2
+ import '@internetarchive/icon-share/icon-share';
3
+ import '@internetarchive/ia-sharing-options';
4
+
5
+ export default class SharingProvider {
6
+ constructor({
7
+ item,
8
+ baseHost,
9
+ bookreader
10
+ }) {
11
+ const { identifier, creator, title } = item?.metadata;
12
+ const creatorToUse = Array.isArray(creator) ? creator[0] : creator;
13
+ const subPrefix = bookreader.options.subPrefix || '';
14
+ const label = `Share this book`;
15
+ this.icon = html`<ia-icon-share style="width: var(--iconWidth); height: var(--iconHeight);"></ia-icon-share>`;
16
+ this.label = label;
17
+ this.id = 'share';
18
+ this.component = html`<ia-sharing-options
19
+ .identifier=${identifier}
20
+ .type=${`book`}
21
+ .creator=${creatorToUse}
22
+ .description=${title}
23
+ .baseHost=${baseHost}
24
+ .fileSubPrefix=${subPrefix}
25
+ ></ia-sharing-options>`;
26
+ }
27
+ }
@@ -1,8 +1,6 @@
1
- import { html } from 'lit-element';
2
-
3
- /* define subpanel */
4
- import { IABookVisualAdjustments } from './visual-adjustments.js';
5
- customElements.define('ia-book-visual-adjustments', IABookVisualAdjustments);
1
+ import { html } from 'lit';
2
+ import '@internetarchive/icon-visual-adjustment/icon-visual-adjustment';
3
+ import './visual-adjustments';
6
4
 
7
5
  const visualAdjustmentOptions = [{
8
6
  id: 'brightness',
@@ -30,11 +28,11 @@ const visualAdjustmentOptions = [{
30
28
  active: false,
31
29
  }];
32
30
 
33
- export default class {
31
+ export default class VisualAdjustmentsProvider {
34
32
  constructor(options) {
35
- const { onOptionChange = () => {}, bookContainerSelector, bookreader } = options;
36
- this.onOptionChange = onOptionChange;
37
- this.bookContainerSelector = bookContainerSelector;
33
+ const { onProviderChange, bookreader } = options;
34
+ this.onProviderChange = onProviderChange;
35
+ this.bookContainer = bookreader.refs.$brContainer;
38
36
  this.bookreader = bookreader;
39
37
 
40
38
  this.onAdjustmentChange = this.onAdjustmentChange.bind(this);
@@ -44,7 +42,7 @@ export default class {
44
42
  this.onZoomOut = this.onZoomOut.bind(this);
45
43
 
46
44
  this.activeCount = 0;
47
- this.icon = html`<ia-icon icon="visualAdjustment" style="width: var(--iconWidth); height: var(--iconHeight);"></ia-icon>`;
45
+ this.icon = html`<ia-icon-visual-adjustment style="width: var(--iconWidth); height: var(--iconHeight);"></ia-icon-visual-adjustment>`;
48
46
  this.label = 'Visual Adjustments';
49
47
  this.menuDetails = this.updateOptionsCount();
50
48
  this.id = 'adjustment';
@@ -63,7 +61,7 @@ export default class {
63
61
  }
64
62
 
65
63
  onZoomOut() {
66
- this.bookreader.zoom();
64
+ this.bookreader.zoom(-1);
67
65
  }
68
66
 
69
67
  onAdjustmentChange(event) {
@@ -79,7 +77,7 @@ export default class {
79
77
  return newValue ? [...values, newValue] : values;
80
78
  }, []).join(' ');
81
79
 
82
- document.querySelector(this.bookContainerSelector).style.setProperty('filter', filters);
80
+ this.bookContainer.css('filter', filters);
83
81
 
84
82
  this.optionUpdateComplete(event);
85
83
  }
@@ -87,7 +85,7 @@ export default class {
87
85
  optionUpdateComplete(event) {
88
86
  this.activeCount = event.detail.activeCount;
89
87
  this.updateOptionsCount(event);
90
- this.onOptionChange(event);
88
+ this.onProviderChange();
91
89
  }
92
90
 
93
91
  updateOptionsCount() {
@@ -1,6 +1,6 @@
1
- import { css, html, LitElement } from "lit-element";
2
- import { repeat } from "lit-html/directives/repeat.js";
3
- import { nothing } from "lit-html";
1
+ import { css, html, LitElement } from "lit";
2
+ import { repeat } from "lit/directives/repeat.js";
3
+ import { nothing } from "lit";
4
4
  import checkmarkIcon from '../assets/icon_checkmark.js';
5
5
  import "@internetarchive/icon-magnify-minus/icon-magnify-minus";
6
6
  import "@internetarchive/icon-magnify-plus/icon-magnify-plus";
@@ -277,3 +277,4 @@ export class IABookVisualAdjustments extends LitElement {
277
277
  }`;
278
278
  }
279
279
  }
280
+ customElements.define('ia-book-visual-adjustments', IABookVisualAdjustments);
@@ -0,0 +1,114 @@
1
+ import { html } from 'lit';
2
+
3
+ import sortDescIcon from '../assets/icon_sort_desc.js';
4
+ import sortAscIcon from '../assets/icon_sort_asc.js';
5
+ import sortNeutralIcon from '../assets/icon_sort_neutral.js';
6
+ import volumesIcon from '../assets/icon_volumes.js';
7
+
8
+ import './volumes.js';
9
+
10
+ const sortType = {
11
+ title_asc: 'title_asc',
12
+ title_desc: 'title_desc',
13
+ default: 'default'
14
+ };
15
+ export default class VolumesProvider {
16
+ /**
17
+ * @param {import('../../BookReader').default} bookreader
18
+ */
19
+ constructor({ baseHost, bookreader, onProviderChange }) {
20
+ this.onProviderChange = onProviderChange;
21
+ this.component = document.createElement("viewable-files");
22
+
23
+ const files = bookreader.options.multipleBooksList.by_subprefix;
24
+ this.viewableFiles = Object.keys(files).map(item => files[item]);
25
+ this.volumeCount = Object.keys(files).length;
26
+
27
+ /** @type {import('../../BookReader').default} */
28
+ this.bookreader = bookreader;
29
+
30
+ this.component.subPrefix = bookreader.options.subPrefix || "";
31
+ this.component.hostUrl = baseHost;
32
+ this.component.viewableFiles = this.viewableFiles;
33
+
34
+ this.id = "volumes";
35
+ this.label = `Viewable files (${this.volumeCount})`;
36
+ this.icon = html`${volumesIcon}`;
37
+
38
+ this.sortOrderBy = sortType.default;
39
+
40
+ // get sort state from query param
41
+ if (this.bookreader.urlPlugin) {
42
+ this.bookreader.urlPlugin.pullFromAddressBar();
43
+
44
+ const urlSortValue = this.bookreader.urlPlugin.getUrlParam('sort');
45
+ if (urlSortValue === sortType.title_asc || urlSortValue === sortType.title_desc) {
46
+ this.sortOrderBy = urlSortValue;
47
+ }
48
+ }
49
+ this.sortVolumes(this.sortOrderBy);
50
+ }
51
+
52
+ get sortButton() {
53
+ const sortIcons = {
54
+ default: html`
55
+ <button class="sort-by neutral-icon" aria-label="Sort volumes in initial order" @click=${() => this.sortVolumes("title_asc")}>${sortNeutralIcon}</button>
56
+ `,
57
+ title_asc: html`
58
+ <button class="sort-by asc-icon" aria-label="Sort volumes in ascending order" @click=${() => this.sortVolumes("title_desc")}>${sortAscIcon}</button>
59
+ `,
60
+ title_desc: html`
61
+ <button class="sort-by desc-icon" aria-label="Sort volumes in descending order" @click=${() => this.sortVolumes("default")}>${sortDescIcon}</button>
62
+ `,
63
+ };
64
+
65
+ return sortIcons[this.sortOrderBy];
66
+ }
67
+
68
+ /**
69
+ * @param {'default' | 'title_asc' | 'title_desc'} sortByType
70
+ */
71
+ sortVolumes(sortByType) {
72
+ let sortedFiles = [];
73
+
74
+ const files = this.viewableFiles;
75
+ sortedFiles = files.sort((a, b) => {
76
+ if (sortByType === sortType.title_asc) return a.title.localeCompare(b.title);
77
+ else if (sortByType === sortType.title_desc) return b.title.localeCompare(a.title);
78
+ else return a.orig_sort - b.orig_sort;
79
+ });
80
+
81
+ this.sortOrderBy = sortByType;
82
+ this.component.sortOrderBy = sortByType;
83
+ this.component.viewableFiles = [...sortedFiles];
84
+ this.actionButton = this.sortButton;
85
+
86
+ if (this.bookreader.urlPlugin) {
87
+ this.bookreader.urlPlugin.pullFromAddressBar();
88
+ if (this.sortOrderBy !== sortType.default) {
89
+ this.bookreader.urlPlugin.setUrlParam('sort', sortByType);
90
+ } else {
91
+ this.bookreader.urlPlugin.removeUrlParam('sort');
92
+ }
93
+ }
94
+
95
+ this.onProviderChange(this.bookreader);
96
+
97
+ this.multipleFilesClicked(sortByType);
98
+ }
99
+
100
+ /**
101
+ * @param {'default' | 'title_asc' | 'title_desc'} orderBy
102
+ */
103
+ multipleFilesClicked(orderBy) {
104
+ if (!window.archive_analytics) {
105
+ return;
106
+ }
107
+ window.archive_analytics?.send_event_no_sampling(
108
+ 'BookReader',
109
+ `VolumesSort|${orderBy}`,
110
+ window.location.path,
111
+ );
112
+ }
113
+
114
+ }
@@ -0,0 +1,188 @@
1
+ import { css, html, LitElement, nothing } from 'lit';
2
+ import { repeat } from 'lit/directives/repeat.js';
3
+
4
+ export class Volumes extends LitElement {
5
+ static get properties() {
6
+ return {
7
+ subPrefix: { type: String },
8
+ hostUrl: { type: String },
9
+ viewableFiles: { type: Array },
10
+ sortOrderBy: { type: String },
11
+ };
12
+ }
13
+
14
+ constructor() {
15
+ super();
16
+ this.hostUrl = '';
17
+ this.sortOrderBy = '';
18
+ this.subPrefix = '';
19
+ this.viewableFiles = [];
20
+ }
21
+
22
+ firstUpdated() {
23
+ const activeFile = this.shadowRoot.querySelector('.content.active');
24
+ // allow for css animations to run before scrolling to active file
25
+ setTimeout(() => {
26
+ // scroll active file into view if needed
27
+ // note: `scrollIntoViewIfNeeded` handles auto-scroll gracefully for Chrome, Safari
28
+ // Firefox does not have this capability yet as it does not support `scrollIntoViewIfNeeded`
29
+ if (activeFile?.scrollIntoViewIfNeeded) {
30
+ activeFile?.scrollIntoViewIfNeeded(true);
31
+ return;
32
+ }
33
+
34
+ // Todo: support `scrollIntoView` or `parentContainer.crollTop = x` for FF & "IE 11"
35
+ // currently, the hard `position: absolutes` misaligns subpanel when `scrollIntoView` is applied :(
36
+ }, 350);
37
+ }
38
+
39
+ volumeItemWithImageTitle(item) {
40
+ const hrefUrl = this.sortOrderBy === 'default'
41
+ ? `${this.hostUrl}${item.url_path}`
42
+ : `${this.hostUrl}${item.url_path}?sort=${this.sortOrderBy}`;
43
+
44
+ return html`
45
+ <li class="content active">
46
+ <div class="separator"></div>
47
+ <a class="container" href="${hrefUrl}">
48
+ <div class="image">
49
+ <img src="${item.image}">
50
+ </div>
51
+ <div class="text">
52
+ <p class="item-title">${item.title}</p>
53
+ <small>by: ${item.author}</small>
54
+ </div>
55
+ </a>
56
+ </li>
57
+ `;
58
+ }
59
+
60
+ volumeItem(item) {
61
+ const activeClass = this.subPrefix === item.file_subprefix ? ' active' : '';
62
+
63
+ const hrefUrl = this.sortOrderBy === 'default'
64
+ ? `${this.hostUrl}${item.url_path}`
65
+ : `${this.hostUrl}${item.url_path}?sort=${this.sortOrderBy}`;
66
+
67
+ return html`
68
+ <li>
69
+ <div class="separator"></div>
70
+ <div class="content${activeClass}">
71
+ <a href="https://${hrefUrl}">
72
+ <p class="item-title">${item.title}</p>
73
+ </a>
74
+ </div>
75
+ </li>
76
+ `;
77
+ }
78
+
79
+ get volumesList() {
80
+ const volumes = repeat(this.viewableFiles, volume => volume?.file_prefix, this.volumeItem.bind(this));
81
+ return html`
82
+ <ul>
83
+ ${volumes}
84
+ <div class="separator"></div>
85
+ </ul>
86
+ `;
87
+ }
88
+
89
+ render() {
90
+ return html`
91
+ ${this.viewableFiles.length ? this.volumesList : nothing}
92
+ `;
93
+ }
94
+
95
+ static get styles() {
96
+ return css`
97
+ :host {
98
+ display: block;
99
+ overflow-y: auto;
100
+ box-sizing: border-box;
101
+ color: var(--primaryTextColor);
102
+ margin-top: 14px;
103
+ margin-bottom: 2rem;
104
+ --activeBorderWidth: 2px;
105
+ }
106
+
107
+ a {
108
+ color: #ffffff;
109
+ text-decoration: none
110
+ }
111
+
112
+ img {
113
+ width: 35px;
114
+ height: 45px;
115
+ }
116
+
117
+ ul {
118
+ padding: 0;
119
+ list-style: none;
120
+ margin: var(--activeBorderWidth) 0.5rem 1rem 0;
121
+ }
122
+
123
+ ul > li:first-child .separator {
124
+ display: none;
125
+ }
126
+
127
+ li {
128
+ cursor: pointer;
129
+ outline: none;
130
+ position: relative;
131
+ }
132
+
133
+ li .content {
134
+ padding: 2px 0 4px 2px;
135
+ border: var(--activeBorderWidth) solid transparent;
136
+ padding: .2rem 0 .4rem .2rem;
137
+ }
138
+
139
+ li .content.active {
140
+ border: var(--activeBorderWidth) solid #538bc5;
141
+ }
142
+
143
+ small {
144
+ font-style: italic;
145
+ white-space: initial;
146
+ }
147
+
148
+ .container {
149
+ display: flex;
150
+ align-items: center;
151
+ justify-content: center
152
+ }
153
+
154
+ .item-title {
155
+ margin-block-start: 0em;
156
+ margin-block-end: 0em;
157
+ font-size: 14px;
158
+ font-weight: bold;
159
+ word-wrap: break-word;
160
+ padding-left: 5px;
161
+ }
162
+
163
+ .separator {
164
+ background-color: var(--secondaryBGColor);
165
+ width: 98%;
166
+ margin: 1px auto;
167
+ height: 1px;
168
+ }
169
+
170
+ .text {
171
+ padding-left: 10px;
172
+ }
173
+
174
+ .icon {
175
+ display: inline-block;
176
+ width: 14px;
177
+ height: 14px;
178
+ margin-left: .7rem;
179
+ border: 1px solid var(--primaryTextColor);
180
+ border-radius: 2px;
181
+ background: var(--activeButtonBg) 50% 50% no-repeat;
182
+ }
183
+
184
+ `;
185
+ }
186
+ }
187
+
188
+ customElements.define('viewable-files', Volumes);
@@ -19,7 +19,7 @@ export class DebugConsole {
19
19
  </form>`);
20
20
  this.$log.append(this.$form);
21
21
 
22
- this.$form.submit(ev => {
22
+ this.$form.on("submit", ev => {
23
23
  ev.preventDefault();
24
24
  const result = eval(this.$form.find('input').val());
25
25
  this.logToScreen([result]);
@@ -29,7 +29,7 @@ export class DebugConsole {
29
29
  console.log = (...args) => {
30
30
  _realLog(...args);
31
31
  this.logToScreen(args);
32
- }
32
+ };
33
33
 
34
34
  window.onerror = (...args) => this.logToScreen(args);
35
35
  }
@@ -40,7 +40,7 @@ export class DebugConsole {
40
40
  */
41
41
  logToScreen(args) {
42
42
  const html = args.map(JSON.stringify).join(',');
43
- const $lastEntry = this.$log.children('.log-entry:last-child')
43
+ const $lastEntry = this.$log.children('.log-entry:last-child');
44
44
  if ($lastEntry.find('.entry-code').html() == html) {
45
45
  $lastEntry.find('.count').text(`(${++this.currentRun})`);
46
46
  } else {