@internetarchive/bookreader 5.0.0-101 → 5.0.0-102

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 (106) hide show
  1. package/BookReader/474.js +1 -1
  2. package/BookReader/474.js.map +1 -1
  3. package/BookReader/BookReader.css +71 -8
  4. package/BookReader/BookReader.js +1 -1
  5. package/BookReader/BookReader.js.LICENSE.txt +1 -1
  6. package/BookReader/BookReader.js.map +1 -1
  7. package/BookReader/ia-bookreader-bundle.js +52 -52
  8. package/BookReader/ia-bookreader-bundle.js.LICENSE.txt +7 -1
  9. package/BookReader/ia-bookreader-bundle.js.map +1 -1
  10. package/BookReader/icons/1up.svg +1 -1
  11. package/BookReader/icons/2up.svg +1 -1
  12. package/BookReader/icons/advance.svg +1 -1
  13. package/BookReader/icons/chevron-right.svg +1 -1
  14. package/BookReader/icons/close-circle-dark.svg +1 -1
  15. package/BookReader/icons/close-circle.svg +1 -1
  16. package/BookReader/icons/fullscreen.svg +1 -1
  17. package/BookReader/icons/fullscreen_exit.svg +1 -1
  18. package/BookReader/icons/hamburger.svg +1 -1
  19. package/BookReader/icons/left-arrow.svg +1 -1
  20. package/BookReader/icons/magnify-minus.svg +1 -1
  21. package/BookReader/icons/magnify-plus.svg +1 -1
  22. package/BookReader/icons/magnify.svg +1 -1
  23. package/BookReader/icons/pause.svg +1 -1
  24. package/BookReader/icons/play.svg +1 -1
  25. package/BookReader/icons/playback-speed.svg +1 -1
  26. package/BookReader/icons/read-aloud.svg +1 -1
  27. package/BookReader/icons/review.svg +1 -1
  28. package/BookReader/icons/slider-toggle.svg +1 -0
  29. package/BookReader/icons/thumbnails.svg +1 -1
  30. package/BookReader/icons/voice.svg +1 -1
  31. package/BookReader/icons/volume-full.svg +1 -1
  32. package/BookReader/images/BRicons.svg +2 -2
  33. package/BookReader/images/books_graphic.svg +1 -1
  34. package/BookReader/images/icon_book.svg +1 -1
  35. package/BookReader/images/icon_bookmark.svg +1 -1
  36. package/BookReader/images/icon_gear.svg +1 -1
  37. package/BookReader/images/icon_hamburger.svg +1 -1
  38. package/BookReader/images/icon_home.svg +1 -1
  39. package/BookReader/images/icon_info.svg +1 -1
  40. package/BookReader/images/icon_one_page.svg +1 -1
  41. package/BookReader/images/icon_pause.svg +1 -1
  42. package/BookReader/images/icon_play.svg +1 -1
  43. package/BookReader/images/icon_playback-rate.svg +1 -1
  44. package/BookReader/images/icon_search_button.svg +1 -1
  45. package/BookReader/images/icon_share.svg +1 -1
  46. package/BookReader/images/icon_skip-back.svg +1 -1
  47. package/BookReader/images/icon_speaker.svg +1 -1
  48. package/BookReader/images/icon_speaker_open.svg +1 -1
  49. package/BookReader/images/icon_thumbnails.svg +1 -1
  50. package/BookReader/images/icon_toc.svg +1 -1
  51. package/BookReader/images/icon_two_pages.svg +1 -1
  52. package/BookReader/images/marker_chap-off.svg +1 -1
  53. package/BookReader/images/marker_chap-on.svg +1 -1
  54. package/BookReader/images/marker_srch-on.svg +1 -1
  55. package/BookReader/images/translate.svg +1 -1
  56. package/BookReader/jquery-3.js +1 -1
  57. package/BookReader/plugins/plugin.archive_analytics.js +1 -1
  58. package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
  59. package/BookReader/plugins/plugin.autoplay.js +1 -1
  60. package/BookReader/plugins/plugin.autoplay.js.map +1 -1
  61. package/BookReader/plugins/plugin.chapters.js +2 -2
  62. package/BookReader/plugins/plugin.chapters.js.LICENSE.txt +1 -1
  63. package/BookReader/plugins/plugin.chapters.js.map +1 -1
  64. package/BookReader/plugins/plugin.experiments.js +1 -1
  65. package/BookReader/plugins/plugin.experiments.js.LICENSE.txt +1 -1
  66. package/BookReader/plugins/plugin.experiments.js.map +1 -1
  67. package/BookReader/plugins/plugin.iframe.js +1 -1
  68. package/BookReader/plugins/plugin.iframe.js.map +1 -1
  69. package/BookReader/plugins/plugin.iiif.js +1 -1
  70. package/BookReader/plugins/plugin.iiif.js.map +1 -1
  71. package/BookReader/plugins/plugin.resume.js +1 -1
  72. package/BookReader/plugins/plugin.resume.js.map +1 -1
  73. package/BookReader/plugins/plugin.search.js +1 -1
  74. package/BookReader/plugins/plugin.search.js.LICENSE.txt +1 -1
  75. package/BookReader/plugins/plugin.search.js.map +1 -1
  76. package/BookReader/plugins/plugin.text_selection.js +1 -1
  77. package/BookReader/plugins/plugin.text_selection.js.LICENSE.txt +1 -1
  78. package/BookReader/plugins/plugin.text_selection.js.map +1 -1
  79. package/BookReader/plugins/plugin.translate.js +4 -4
  80. package/BookReader/plugins/plugin.translate.js.LICENSE.txt +1 -1
  81. package/BookReader/plugins/plugin.translate.js.map +1 -1
  82. package/BookReader/plugins/plugin.tts.js +1 -1
  83. package/BookReader/plugins/plugin.tts.js.LICENSE.txt +1 -1
  84. package/BookReader/plugins/plugin.tts.js.map +1 -1
  85. package/BookReader/plugins/plugin.url.js +1 -1
  86. package/BookReader/plugins/plugin.url.js.map +1 -1
  87. package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -1
  88. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
  89. package/BookReader/plugins/translator-worker.js +1 -1
  90. package/BookReader/plugins/translator-worker.js.map +1 -1
  91. package/BookReader/webcomponents-bundle.js +1 -1
  92. package/BookReader/webcomponents-bundle.js.map +1 -1
  93. package/package.json +20 -20
  94. package/src/BookNavigator/search/search-results.js +84 -63
  95. package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +4 -4
  96. package/src/BookNavigator/visual-adjustments/visual-adjustments.js +77 -59
  97. package/src/BookReader/Navbar/Navbar.js +54 -71
  98. package/src/BookReader/options.js +6 -0
  99. package/src/BookReader.js +12 -0
  100. package/src/assets/icons/slider-toggle.svg +1 -0
  101. package/src/css/_BRnav.scss +57 -4
  102. package/src/css/_icons.scss +7 -0
  103. package/src/plugins/plugin.text_selection.js +9 -0
  104. package/src/plugins/search/plugin.search.js +4 -0
  105. package/src/plugins/search/utils.js +8 -1
  106. package/src/plugins/search/view.js +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@internetarchive/bookreader",
3
- "version": "5.0.0-101",
3
+ "version": "5.0.0-102",
4
4
  "description": "The Internet Archive BookReader.",
5
5
  "type": "module",
6
6
  "files": [
@@ -47,28 +47,28 @@
47
47
  "lit": "^2.5.0"
48
48
  },
49
49
  "devDependencies": {
50
- "@babel/core": "7.25.8",
51
- "@babel/eslint-parser": "7.25.7",
50
+ "@babel/core": "7.28.4",
51
+ "@babel/eslint-parser": "7.28.5",
52
52
  "@babel/plugin-proposal-class-properties": "7.18.6",
53
- "@babel/plugin-proposal-decorators": "7.25.7",
54
- "@babel/preset-env": "7.25.8",
53
+ "@babel/plugin-proposal-decorators": "7.28.0",
54
+ "@babel/preset-env": "7.28.3",
55
55
  "@iiif/presentation-2": "^1.0.4",
56
56
  "@iiif/presentation-3": "^2.1.3",
57
57
  "@open-wc/testing-helpers": "3.0.1",
58
- "@types/jest": "29.5.14",
58
+ "@types/jest": "30.0.0",
59
59
  "@webcomponents/webcomponentsjs": "^2.6.0",
60
- "babel-loader": "9.2.1",
60
+ "babel-loader": "10.0.0",
61
61
  "concurrently": "9.0.1",
62
- "core-js": "3.38.1",
62
+ "core-js": "3.46.0",
63
63
  "cpx2": "8.0.0",
64
- "eslint": "^7.32.0",
64
+ "eslint": "7.32.0",
65
65
  "eslint-plugin-no-jquery": "^2.7.0",
66
- "eslint-plugin-testcafe": "^0.2.1",
66
+ "eslint-plugin-testcafe": "0.2.1",
67
67
  "http-server": "14.1.1",
68
68
  "hypothesis": "^1.1627.0",
69
69
  "interactjs": "^1.10.18",
70
70
  "iso-language-codes": "2.0.0",
71
- "jest": "29.7.0",
71
+ "jest": "30.2.0",
72
72
  "jest-environment-jsdom": "^29.7.0",
73
73
  "jquery": "3.6.1",
74
74
  "jquery-colorbox": "1.6.4",
@@ -77,19 +77,19 @@
77
77
  "jquery.browser": "0.1.0",
78
78
  "live-server": "1.2.2",
79
79
  "regenerator-runtime": "0.14.1",
80
- "sass": "1.79.5",
81
- "sinon": "19.0.2",
80
+ "sass": "1.93.2",
81
+ "sinon": "21.0.0",
82
82
  "soundmanager2": "2.97.20170602",
83
- "svgo": "3.3.2",
84
- "testcafe": "3.6.2",
83
+ "svgo": "4.0.0",
84
+ "testcafe": "3.7.2",
85
85
  "testcafe-browser-provider-browserstack": "^1.13.2-alpha.1",
86
- "webpack": "5.95.0",
87
- "webpack-cli": "5.1.4"
86
+ "webpack": "5.102.1",
87
+ "webpack-cli": "6.0.1"
88
88
  },
89
89
  "jest": {
90
90
  "testEnvironment": "jsdom",
91
91
  "transformIgnorePatterns": [
92
- "node_modules/(?!(sinon|lit-html|lit-element|lit|@lit|@internetarchive|@open-wc)/)"
92
+ "node_modules/(?!(sinon|lit-html|lit-element|lit|@lit|@lit-labs|@internetarchive|@open-wc)/)"
93
93
  ],
94
94
  "moduleNameMapper": {
95
95
  "^@/(.*)$": "<rootDir>/$1"
@@ -116,8 +116,8 @@
116
116
  "build-hypothesis:watch": "npx cpx --watch --verbose \"node_modules/hypothesis/**/*\" BookReader/hypothesis",
117
117
  "build-js": "npx webpack",
118
118
  "build-js:watch": "npx webpack --mode=development --watch",
119
- "build-css": "npx sass --no-source-map ./src/css/BookReader.scss ./BookReader/BookReader.css",
120
- "build-css:watch": "npx sass --watch --no-source-map ./src/css/BookReader.scss ./BookReader/BookReader.css",
119
+ "build-css": "npx sass --silence-deprecation=import --no-source-map ./src/css/BookReader.scss ./BookReader/BookReader.css",
120
+ "build-css:watch": "npx sass --silence-deprecation=import --watch --no-source-map ./src/css/BookReader.scss ./BookReader/BookReader.css",
121
121
  "clean": "rm -r BookReader/ || true",
122
122
  "lint": "npx eslint src/ tests/ *.js *.cjs",
123
123
  "lint:fix": "npx eslint --fix src/ tests/ *.js *.cjs",
@@ -5,6 +5,7 @@ import '@internetarchive/ia-activity-indicator/ia-activity-indicator.js';
5
5
  import checkmarkIcon from '../assets/icon_checkmark.js';
6
6
  import closeIcon from '../assets/icon_close.js';
7
7
  import buttonCSS from '../assets/button-base.js';
8
+ import { ifDefined } from 'lit/directives/if-defined.js';
8
9
  /** @typedef {import('@/src/plugins/search/plugin.search.js').SearchInsideMatch} SearchInsideMatch */
9
10
 
10
11
  export class IABookSearchResults extends LitElement {
@@ -15,7 +16,6 @@ export class IABookSearchResults extends LitElement {
15
16
  queryInProgress: { type: Boolean },
16
17
  renderHeader: { type: Boolean },
17
18
  renderSearchAllFiles: { type: Boolean },
18
- displayResultImages: { type: Boolean },
19
19
  errorMessage: { type: String },
20
20
  };
21
21
  }
@@ -29,7 +29,6 @@ export class IABookSearchResults extends LitElement {
29
29
  this.queryInProgress = false;
30
30
  this.renderHeader = false;
31
31
  this.renderSearchAllFiles = false;
32
- this.displayResultImages = false;
33
32
  this.errorMessage = '';
34
33
 
35
34
  this.bindBookReaderListeners();
@@ -107,13 +106,13 @@ export class IABookSearchResults extends LitElement {
107
106
 
108
107
  get resultsCount() {
109
108
  const count = this.results.length;
110
- return count ? html`<p>(${count} result${count > 1 ? 's' : ''})</p>` : nothing;
109
+ return count ? `${count} result${count > 1 ? 's' : ''}` : nothing;
111
110
  }
112
111
 
113
112
  get headerSection() {
114
113
  const header = html`<header>
115
114
  <h3>Search inside</h3>
116
- ${this.resultsCount}
115
+ ${this.resultsCount ? html`(${this.resultsCount})` : nothing}
117
116
  </header>`;
118
117
  return this.renderHeader ? header : nothing;
119
118
  }
@@ -129,7 +128,7 @@ export class IABookSearchResults extends LitElement {
129
128
  get loadingIndicator() {
130
129
  return html`
131
130
  <div class="loading">
132
- <ia-activity-indicator mode="processing"></ia-activity-indicator>
131
+ <ia-activity-indicator mode="processing" aria-hidden="true" role="presentation"></ia-activity-indicator>
133
132
  <p>Searching</p>
134
133
  <button class="ia-button external cancel-search" @click=${this.cancelSearch}>Cancel</button>
135
134
  </div>
@@ -137,36 +136,37 @@ export class IABookSearchResults extends LitElement {
137
136
  }
138
137
 
139
138
  get resultsSet() {
140
- const resultsClass = this.displayResultImages ? 'show-image' : '';
141
139
  return html`
142
- <ul class="results ${resultsClass}">
140
+ <nav aria-label="Search results">
141
+ <div>
142
+ ${this.resultsCount}
143
+ <a
144
+ href="#"
145
+ class="skip-link"
146
+ @click=${(e) => {
147
+ e.preventDefault();
148
+ this.shadowRoot.querySelector('.results li:last-child .result-item').focus();
149
+ }}
150
+ >Skip to last result</a>
151
+ </div>
152
+ <ul class="results">
143
153
  ${this.results.map(match => html`
144
- <li @click=${this.selectResult.bind(this, match)}>
145
- ${match.cover ? html`<img src="${match.cover}" />` : nothing}
146
- <h4>${match.title || nothing}</h4>
147
- <p class="page-num">Page ${match.displayPageNumber}</p>
148
- <p>${unsafeHTML(match.html)}</p>
154
+ <li>
155
+ <button class="result-item" @click=${this.selectResult.bind(this, match)}>
156
+ <span class="page-num">Page ${match.displayPageNumber}</span> <span lang=${ifDefined(match.lang)}>${unsafeHTML(match.html)}</span>
157
+ </button>
149
158
  </li>
150
159
  `)}
151
160
  </ul>
152
- `;
153
- }
154
-
155
- get searchForm() {
156
- return html`
157
- <form action="" method="get" @submit=${this.performSearch}>
158
- <fieldset>
159
- ${this.searchMultipleControls}
160
- <input
161
- type="search"
162
- name="query"
163
- alt="Search inside this book."
164
- @keyup=${this.setQuery}
165
- @search=${this.setQuery}
166
- .value=${this.query}
167
- />
168
- </fieldset>
169
- </form>
161
+ <a
162
+ href="#"
163
+ class="skip-link"
164
+ @click=${(e) => {
165
+ e.preventDefault();
166
+ this.shadowRoot.querySelector('.results li:first-child .result-item').focus();
167
+ }}
168
+ >Skip to first result</a>
169
+ </nav>
170
170
  `;
171
171
  }
172
172
 
@@ -176,21 +176,29 @@ export class IABookSearchResults extends LitElement {
176
176
  `;
177
177
  }
178
178
 
179
- get searchCTA() {
180
- return html`<p class="search-cta"><em>Please enter text to search for</em></p>`;
181
- }
182
-
183
179
  render() {
184
180
  const showSearchCTA = (!this.queryInProgress && !this.errorMessage)
185
181
  && (!this.queryInProgress && !this.results.length);
186
182
  return html`
187
183
  ${this.headerSection}
188
- ${this.searchForm}
189
- <div class="results-container">
184
+ <form action="" method="get" @submit=${this.performSearch}>
185
+ ${this.searchMultipleControls}
186
+ <input
187
+ type="search"
188
+ name="query"
189
+ id="br-search-input"
190
+ @keyup=${this.setQuery}
191
+ @search=${this.setQuery}
192
+ .value=${this.query}
193
+ />
194
+ <label class="search-cta ${showSearchCTA ? '' : 'sr-only'}" for="br-search-input">
195
+ Please enter text to search for
196
+ </label>
197
+ </form>
198
+ <div class="results-container" aria-live="polite">
190
199
  ${this.queryInProgress ? this.loadingIndicator : nothing}
191
200
  ${this.errorMessage ? this.setErrorMessage : nothing}
192
201
  ${this.results.length ? this.resultsSet : nothing}
193
- ${showSearchCTA ? this.searchCTA : nothing}
194
202
  </div>
195
203
  `;
196
204
  }
@@ -211,6 +219,15 @@ export class IABookSearchResults extends LitElement {
211
219
  box-sizing: border-box;
212
220
  }
213
221
 
222
+ .skip-link {
223
+ position: absolute;
224
+ left: -9999px;
225
+ }
226
+ .skip-link:focus {
227
+ position: static;
228
+ left: auto;
229
+ }
230
+
214
231
  mark {
215
232
  padding: 0 .2rem;
216
233
  color: ${searchResultText};
@@ -238,9 +255,8 @@ export class IABookSearchResults extends LitElement {
238
255
  font-style: italic;
239
256
  }
240
257
 
241
- fieldset {
258
+ form {
242
259
  padding: 0 0 1rem 0;
243
- border: none;
244
260
  }
245
261
 
246
262
  [type="checkbox"] {
@@ -303,13 +319,15 @@ export class IABookSearchResults extends LitElement {
303
319
  background: #fff;
304
320
  }
305
321
 
306
- p.page-num {
322
+ .page-num {
307
323
  font-weight: bold;
308
324
  padding-bottom: 0;
309
325
  }
310
326
 
311
- p.search-cta {
327
+ .search-cta {
328
+ padding: 10px 0;
312
329
  text-align: center;
330
+ font-style: italic;
313
331
  }
314
332
 
315
333
  .results-container {
@@ -322,33 +340,24 @@ export class IABookSearchResults extends LitElement {
322
340
  list-style: none;
323
341
  }
324
342
 
325
- ul.show-image li {
326
- display: grid;
327
- }
328
-
329
- li {
343
+ .result-item {
330
344
  cursor: pointer;
331
- grid-template-columns: 30px 1fr;
332
- grid-gap: 0 .5rem;
333
- }
334
-
335
- li img {
345
+ margin-top: 8px;
346
+ font-size: 12px;
347
+ padding: 5px;
348
+ border-radius: 4px;
336
349
  display: block;
337
350
  width: 100%;
351
+ /* Reset button styles */
352
+ background: none;
353
+ border: none;
354
+ text-align: left;
355
+ font-family: inherit;
356
+ transition: background-color 0.2s;
338
357
  }
339
358
 
340
- li h4 {
341
- grid-column: 2 / 3;
342
- padding: 0 0 2rem 0;
343
- margin: 0;
344
- font-weight: normal;
345
- }
346
-
347
- li p {
348
- grid-column: 2 / 3;
349
- padding: 0 0 1.5rem 0;
350
- margin: 0;
351
- font-size: 1.2rem;
359
+ .result-item:hover {
360
+ background-color: rgba(255, 255, 255, 0.1);
352
361
  }
353
362
 
354
363
  .loading {
@@ -367,6 +376,18 @@ export class IABookSearchResults extends LitElement {
367
376
  height: 40px;
368
377
  margin: 0 auto;
369
378
  }
379
+
380
+ .sr-only {
381
+ position: absolute !important;
382
+ width: 1px !important;
383
+ height: 1px !important;
384
+ padding: 0 !important;
385
+ margin: -1px !important;
386
+ overflow: hidden !important;
387
+ clip: rect(0 0 0 0) !important;
388
+ white-space: nowrap !important;
389
+ border: 0 !important;
390
+ }
370
391
  `;
371
392
  return [buttonCSS, mainCSS];
372
393
  }
@@ -7,17 +7,17 @@ const visualAdjustmentOptions = [{
7
7
  name: 'Adjust brightness',
8
8
  active: false,
9
9
  min: 0,
10
- max: 150,
10
+ max: 200,
11
11
  step: 1,
12
- value: 100,
12
+ value: 120,
13
13
  }, {
14
14
  id: 'contrast',
15
15
  name: 'Adjust contrast',
16
16
  active: false,
17
17
  min: 0,
18
- max: 150,
18
+ max: 200,
19
19
  step: 1,
20
- value: 100,
20
+ value: 120,
21
21
  }, {
22
22
  id: 'invert',
23
23
  name: 'Invert colors (dark mode)',
@@ -1,7 +1,6 @@
1
- import { css, html, LitElement } from "lit";
1
+ import { css, html, LitElement, nothing } from "lit";
2
+ import { classMap } from 'lit/directives/class-map.js';
2
3
  import { repeat } from "lit/directives/repeat.js";
3
- import { nothing } from "lit";
4
- import checkmarkIcon from '../assets/icon_checkmark.js';
5
4
  import "@internetarchive/icon-magnify-minus/icon-magnify-minus.js";
6
5
  import "@internetarchive/icon-magnify-plus/icon-magnify-plus.js";
7
6
 
@@ -99,6 +98,13 @@ export class IABookVisualAdjustments extends LitElement {
99
98
  this.options = updatedOptions;
100
99
  this.activeCount = this.activeOptions.length;
101
100
  this.emitOptionChangedEvent(checkedOption.id);
101
+ if (checkedOption.active && checkedOption.value !== undefined) {
102
+ // move focus to the range input
103
+ const rangeInput = this.shadowRoot.querySelector(`input[name="${checkedOption.id}_range"]`);
104
+ requestAnimationFrame(() => {
105
+ rangeInput?.focus();
106
+ });
107
+ }
102
108
  }
103
109
 
104
110
  setRangeValue(id, value) {
@@ -110,7 +116,8 @@ export class IABookVisualAdjustments extends LitElement {
110
116
  /* render */
111
117
  rangeSlider(option) {
112
118
  return html`
113
- <div class=${`range${option.active ? " visible" : ""}`}>
119
+ <label class=${`range${option.active ? " visible" : ""}`}>
120
+ <span class="sr-only">${option.name}</span>
114
121
  <input
115
122
  type="range"
116
123
  name="${option.id}_range"
@@ -118,30 +125,30 @@ export class IABookVisualAdjustments extends LitElement {
118
125
  max=${option.max || 100}
119
126
  step=${option.step || 1}
120
127
  .value=${option.value}
128
+ aria-valuetext=${`${option.value}%`}
121
129
  @input=${(e) => this.setRangeValue(option.id, e.target.value)}
122
130
  @change=${() => this.emitOptionChangedEvent()}
123
131
  />
124
- <p>${option.value}%</p>
125
- </div>
132
+ <span aria-hidden="true">${option.value}%</span>
133
+ </label>
126
134
  `;
127
135
  }
128
136
 
129
137
  adjustmentCheckbox(option) {
130
- const formID = `adjustment_${option.id}`;
131
- return html`<li>
132
- <label for="${formID}">
133
- <span class="name">${option.name}</span>
134
- <input
135
- type="checkbox"
136
- name="${formID}"
137
- id="${formID}"
138
- @change=${() => this.changeActiveStateFor(option.id)}
139
- ?checked=${option.active}
140
- />
141
- <span class="icon"></span>
142
- </label>
143
- ${option.value !== undefined ? this.rangeSlider(option) : nothing}
144
- </li>`;
138
+ return html`
139
+ <div
140
+ class="adjustment-option ${classMap({active: option.active, 'has-range': option.value !== undefined})}">
141
+ <label class="checkbox-label">
142
+ ${option.name}
143
+ <input
144
+ type="checkbox"
145
+ @change=${() => this.changeActiveStateFor(option.id)}
146
+ ?checked=${option.active}
147
+ />
148
+ </label>
149
+ ${option.value !== undefined ? this.rangeSlider(option) : nothing}
150
+ </div>
151
+ `;
145
152
  }
146
153
 
147
154
  get headerSection() {
@@ -158,11 +165,11 @@ export class IABookVisualAdjustments extends LitElement {
158
165
  get zoomControls() {
159
166
  return html`
160
167
  <h4>Adjust zoom</h4>
161
- <button class="zoom_out" @click=${this.emitZoomOut} title="zoom out">
162
- <ia-icon-magnify-minus></ia-icon-magnify-minus>
168
+ <button class="zoom_out" @click=${this.emitZoomOut} title="Zoom out" aria-label="Zoom out">
169
+ <ia-icon-magnify-minus aria-hidden="true" role="presentation"></ia-icon-magnify-minus>
163
170
  </button>
164
- <button class="zoom_in" @click=${this.emitZoomIn} title="zoom in">
165
- <ia-icon-magnify-plus></ia-icon-magnify-plus>
171
+ <button class="zoom_in" @click=${this.emitZoomIn} title="Zoom in" aria-label="Zoom in">
172
+ <ia-icon-magnify-plus aria-hidden="true" role="presentation"></ia-icon-magnify-plus>
166
173
  </button>
167
174
  `;
168
175
  }
@@ -171,9 +178,7 @@ export class IABookVisualAdjustments extends LitElement {
171
178
  render() {
172
179
  return html`
173
180
  ${this.headerSection}
174
- <ul>
175
- ${repeat(this.options, (option) => option.id, this.adjustmentCheckbox.bind(this))}
176
- </ul>
181
+ ${repeat(this.options, (option) => option.id, this.adjustmentCheckbox.bind(this))}
177
182
  ${this.showZoomControls ? this.zoomControls : nothing}
178
183
  `;
179
184
  }
@@ -186,6 +191,7 @@ export class IABookVisualAdjustments extends LitElement {
186
191
  overflow-y: auto;
187
192
  font-size: 1.4rem;
188
193
  box-sizing: border-box;
194
+ padding: 10px 10px 0 0;
189
195
  }
190
196
 
191
197
  header {
@@ -207,49 +213,48 @@ export class IABookVisualAdjustments extends LitElement {
207
213
  font-style: italic;
208
214
  }
209
215
 
210
- ul {
211
- padding: 1rem 2rem 0 0;
212
- list-style: none;
213
- margin-top: 0;
216
+ .adjustment-option {
217
+ border: 2px solid transparent;
218
+ border-radius: 4px;
219
+ margin-bottom: 4px;
214
220
  }
215
-
216
- [type="checkbox"] {
217
- display: none;
221
+ .adjustment-option.has-range.active {
222
+ border: 2px solid rgba(255, 255, 255, 0.2);
218
223
  }
219
224
 
220
- label {
225
+ .checkbox-label {
221
226
  display: flex;
222
227
  justify-content: space-between;
223
- align-items: baseline;
228
+ align-items: center;
224
229
  font-size: 1.4rem;
225
230
  font-weight: bold;
226
- line-height: 150%;
227
- vertical-align: middle;
231
+ cursor: pointer;
232
+ padding: 6px 8px;
233
+ transition: background-color 0.2s;
234
+ border-radius: inherit;
228
235
  }
229
-
230
- .icon {
231
- display: inline-block;
232
- width: 14px;
233
- height: 14px;
234
- margin-left: .7rem;
235
- border: 1px solid var(--primaryTextColor);
236
- border-radius: 2px;
237
- background: var(--activeButtonBg) 50% 50% no-repeat;
236
+ .checkbox-label:hover {
237
+ background-color: rgba(255, 255, 255, 0.1);
238
238
  }
239
- :checked + .icon {
240
- background-image: url('${checkmarkIcon}');
239
+ .adjustment-option.has-range.active > .checkbox-label {
240
+ border-radius: 4px 4px 0 0;
241
+ }
242
+
243
+ [type="checkbox"] {
244
+ transform: scale(1.5);
241
245
  }
242
246
 
243
247
  .range {
244
248
  display: none;
245
- padding-top: .5rem;
249
+ padding: 10px;
250
+ align-items: center;
251
+ gap: 10px;
246
252
  }
247
253
  .range.visible {
248
254
  display: flex;
249
255
  }
250
-
251
- .range p {
252
- margin-left: 1rem;
256
+ .range input[type="range"] {
257
+ flex: 1;
253
258
  }
254
259
 
255
260
  h4 {
@@ -262,19 +267,32 @@ export class IABookVisualAdjustments extends LitElement {
262
267
  -webkit-appearance: none;
263
268
  appearance: none;
264
269
  border: none;
265
- border-radius: 0;
266
270
  background: transparent;
267
- outline: none;
268
271
  cursor: pointer;
269
272
  --iconFillColor: var(--primaryTextColor);
270
273
  --iconStrokeColor: var(--primaryTextColor);
271
274
  height: 4rem;
272
275
  width: 4rem;
276
+ transition: background-color 0.2s;
277
+ border-radius: 4px;
273
278
  }
274
279
 
275
- button * {
276
- display: inline-block;
277
- }`;
280
+ button:hover {
281
+ background-color: rgba(255, 255, 255, 0.1);
282
+ }
283
+
284
+ .sr-only {
285
+ position: absolute !important;
286
+ width: 1px !important;
287
+ height: 1px !important;
288
+ padding: 0 !important;
289
+ margin: -1px !important;
290
+ overflow: hidden !important;
291
+ clip: rect(0 0 0 0) !important;
292
+ white-space: nowrap !important;
293
+ border: 0 !important;
294
+ }
295
+ `;
278
296
  }
279
297
  }
280
298
  customElements.define('ia-book-visual-adjustments', IABookVisualAdjustments);