@internetarchive/collection-browser 3.4.1-alpha-webdev7761.4 → 3.4.1

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 (216) hide show
  1. package/.editorconfig +29 -29
  2. package/.github/workflows/ci.yml +27 -27
  3. package/.github/workflows/gh-pages-main.yml +39 -39
  4. package/.github/workflows/npm-publish.yml +39 -39
  5. package/.github/workflows/pr-preview.yml +38 -38
  6. package/.husky/pre-commit +4 -4
  7. package/.prettierignore +1 -1
  8. package/LICENSE +661 -661
  9. package/README.md +83 -83
  10. package/dist/src/app-root.js +28 -19
  11. package/dist/src/app-root.js.map +1 -1
  12. package/dist/src/collection-browser.d.ts +4 -24
  13. package/dist/src/collection-browser.js +125 -286
  14. package/dist/src/collection-browser.js.map +1 -1
  15. package/dist/src/collection-facets/facet-row.js +143 -143
  16. package/dist/src/collection-facets/facet-row.js.map +1 -1
  17. package/dist/src/collection-facets/more-facets-content.d.ts +1 -1
  18. package/dist/src/collection-facets/more-facets-content.js +48 -34
  19. package/dist/src/collection-facets/more-facets-content.js.map +1 -1
  20. package/dist/src/collection-facets/more-facets-pagination.js +10 -6
  21. package/dist/src/collection-facets/more-facets-pagination.js.map +1 -1
  22. package/dist/src/collection-facets/smart-facets/heuristics/wikidata/wikidata-heuristic.js +21 -16
  23. package/dist/src/collection-facets/smart-facets/heuristics/wikidata/wikidata-heuristic.js.map +1 -1
  24. package/dist/src/collection-facets/smart-facets/smart-facet-bar.js +10 -7
  25. package/dist/src/collection-facets/smart-facets/smart-facet-bar.js.map +1 -1
  26. package/dist/src/collection-facets/smart-facets/smart-facet-button.js +2 -3
  27. package/dist/src/collection-facets/smart-facets/smart-facet-button.js.map +1 -1
  28. package/dist/src/collection-facets/smart-facets/smart-facet-dropdown.js +11 -9
  29. package/dist/src/collection-facets/smart-facets/smart-facet-dropdown.js.map +1 -1
  30. package/dist/src/collection-facets/smart-facets/smart-facet-heuristics.js +7 -7
  31. package/dist/src/collection-facets/smart-facets/smart-facet-heuristics.js.map +1 -1
  32. package/dist/src/collection-facets/toggle-switch.js +6 -4
  33. package/dist/src/collection-facets/toggle-switch.js.map +1 -1
  34. package/dist/src/collection-facets.js +310 -309
  35. package/dist/src/collection-facets.js.map +1 -1
  36. package/dist/src/data-source/collection-browser-data-source-interface.d.ts +1 -10
  37. package/dist/src/data-source/collection-browser-data-source-interface.js.map +1 -1
  38. package/dist/src/data-source/collection-browser-data-source.d.ts +1 -19
  39. package/dist/src/data-source/collection-browser-data-source.js +65 -71
  40. package/dist/src/data-source/collection-browser-data-source.js.map +1 -1
  41. package/dist/src/data-source/collection-browser-query-state.d.ts +2 -1
  42. package/dist/src/data-source/collection-browser-query-state.js.map +1 -1
  43. package/dist/src/data-source/models.d.ts +0 -11
  44. package/dist/src/data-source/models.js.map +1 -1
  45. package/dist/src/empty-placeholder.js +18 -19
  46. package/dist/src/empty-placeholder.js.map +1 -1
  47. package/dist/src/expanded-date-picker.js +10 -6
  48. package/dist/src/expanded-date-picker.js.map +1 -1
  49. package/dist/src/language-code-handler/language-code-handler.js +2 -2
  50. package/dist/src/language-code-handler/language-code-handler.js.map +1 -1
  51. package/dist/src/manage/manage-bar.js +15 -9
  52. package/dist/src/manage/manage-bar.js.map +1 -1
  53. package/dist/src/manage/remove-items-modal-content.js +2 -2
  54. package/dist/src/manage/remove-items-modal-content.js.map +1 -1
  55. package/dist/src/models.d.ts +6 -2
  56. package/dist/src/models.js +54 -46
  57. package/dist/src/models.js.map +1 -1
  58. package/dist/src/restoration-state-handler.d.ts +2 -1
  59. package/dist/src/restoration-state-handler.js +19 -12
  60. package/dist/src/restoration-state-handler.js.map +1 -1
  61. package/dist/src/sort-filter-bar/alpha-bar.js +14 -9
  62. package/dist/src/sort-filter-bar/alpha-bar.js.map +1 -1
  63. package/dist/src/sort-filter-bar/sort-filter-bar.js +24 -14
  64. package/dist/src/sort-filter-bar/sort-filter-bar.js.map +1 -1
  65. package/dist/src/tiles/base-tile-component.js +2 -1
  66. package/dist/src/tiles/base-tile-component.js.map +1 -1
  67. package/dist/src/tiles/grid/account-tile.js +7 -5
  68. package/dist/src/tiles/grid/account-tile.js.map +1 -1
  69. package/dist/src/tiles/grid/collection-tile.js +6 -3
  70. package/dist/src/tiles/grid/collection-tile.js.map +1 -1
  71. package/dist/src/tiles/grid/item-tile.js +33 -23
  72. package/dist/src/tiles/grid/item-tile.js.map +1 -1
  73. package/dist/src/tiles/grid/search-tile.js +2 -1
  74. package/dist/src/tiles/grid/search-tile.js.map +1 -1
  75. package/dist/src/tiles/grid/tile-stats.js +3 -2
  76. package/dist/src/tiles/grid/tile-stats.js.map +1 -1
  77. package/dist/src/tiles/hover/hover-pane-controller.js +28 -21
  78. package/dist/src/tiles/hover/hover-pane-controller.js.map +1 -1
  79. package/dist/src/tiles/hover/tile-hover-pane.js +4 -3
  80. package/dist/src/tiles/hover/tile-hover-pane.js.map +1 -1
  81. package/dist/src/tiles/image-block.js +8 -5
  82. package/dist/src/tiles/image-block.js.map +1 -1
  83. package/dist/src/tiles/item-image.js +19 -12
  84. package/dist/src/tiles/item-image.js.map +1 -1
  85. package/dist/src/tiles/list/tile-list-compact.js +25 -17
  86. package/dist/src/tiles/list/tile-list-compact.js.map +1 -1
  87. package/dist/src/tiles/list/tile-list.js +55 -34
  88. package/dist/src/tiles/list/tile-list.js.map +1 -1
  89. package/dist/src/tiles/overlay/icon-overlay.js +2 -1
  90. package/dist/src/tiles/overlay/icon-overlay.js.map +1 -1
  91. package/dist/src/tiles/overlay/text-overlay.js +4 -2
  92. package/dist/src/tiles/overlay/text-overlay.js.map +1 -1
  93. package/dist/src/tiles/text-snippet-block.js +4 -2
  94. package/dist/src/tiles/text-snippet-block.js.map +1 -1
  95. package/dist/src/tiles/tile-dispatcher.js +30 -22
  96. package/dist/src/tiles/tile-dispatcher.js.map +1 -1
  97. package/dist/src/tiles/tile-display-value-provider.js +9 -5
  98. package/dist/src/tiles/tile-display-value-provider.js.map +1 -1
  99. package/dist/src/tiles/tile-mediatype-icon.js +19 -12
  100. package/dist/src/tiles/tile-mediatype-icon.js.map +1 -1
  101. package/dist/src/utils/collapse-repeated-quotes.js +1 -1
  102. package/dist/src/utils/collapse-repeated-quotes.js.map +1 -1
  103. package/dist/src/utils/facet-utils.js +5 -3
  104. package/dist/src/utils/facet-utils.js.map +1 -1
  105. package/dist/src/utils/format-count.js +10 -10
  106. package/dist/src/utils/format-count.js.map +1 -1
  107. package/dist/src/utils/resolve-mediatype.js +3 -2
  108. package/dist/src/utils/resolve-mediatype.js.map +1 -1
  109. package/dist/test/collection-browser.test.js +380 -336
  110. package/dist/test/collection-browser.test.js.map +1 -1
  111. package/dist/test/collection-facets/facet-row.test.js +52 -37
  112. package/dist/test/collection-facets/facet-row.test.js.map +1 -1
  113. package/dist/test/collection-facets/facets-template.test.js +23 -17
  114. package/dist/test/collection-facets/facets-template.test.js.map +1 -1
  115. package/dist/test/collection-facets/more-facets-content.test.js +32 -22
  116. package/dist/test/collection-facets/more-facets-content.test.js.map +1 -1
  117. package/dist/test/collection-facets/more-facets-pagination.test.js +22 -16
  118. package/dist/test/collection-facets/more-facets-pagination.test.js.map +1 -1
  119. package/dist/test/collection-facets/toggle-switch.test.js +19 -22
  120. package/dist/test/collection-facets/toggle-switch.test.js.map +1 -1
  121. package/dist/test/collection-facets.test.js +77 -60
  122. package/dist/test/collection-facets.test.js.map +1 -1
  123. package/dist/test/empty-placeholder.test.js +17 -11
  124. package/dist/test/empty-placeholder.test.js.map +1 -1
  125. package/dist/test/expanded-date-picker.test.js +14 -8
  126. package/dist/test/expanded-date-picker.test.js.map +1 -1
  127. package/dist/test/icon-overlay.test.js +6 -7
  128. package/dist/test/icon-overlay.test.js.map +1 -1
  129. package/dist/test/image-block.test.js +26 -16
  130. package/dist/test/image-block.test.js.map +1 -1
  131. package/dist/test/item-image.test.js +32 -23
  132. package/dist/test/item-image.test.js.map +1 -1
  133. package/dist/test/manage/manage-bar.test.js +33 -21
  134. package/dist/test/manage/manage-bar.test.js.map +1 -1
  135. package/dist/test/manage/remove-items-modal-content.test.js +15 -10
  136. package/dist/test/manage/remove-items-modal-content.test.js.map +1 -1
  137. package/dist/test/mocks/mock-search-service.js +3 -2
  138. package/dist/test/mocks/mock-search-service.js.map +1 -1
  139. package/dist/test/restoration-state-handler.test.js +54 -14
  140. package/dist/test/restoration-state-handler.test.js.map +1 -1
  141. package/dist/test/review-block.test.js +18 -16
  142. package/dist/test/review-block.test.js.map +1 -1
  143. package/dist/test/sort-filter-bar/alpha-bar-tooltip.test.js +3 -2
  144. package/dist/test/sort-filter-bar/alpha-bar-tooltip.test.js.map +1 -1
  145. package/dist/test/sort-filter-bar/alpha-bar.test.js +24 -18
  146. package/dist/test/sort-filter-bar/alpha-bar.test.js.map +1 -1
  147. package/dist/test/sort-filter-bar/sort-filter-bar.test.js +180 -178
  148. package/dist/test/sort-filter-bar/sort-filter-bar.test.js.map +1 -1
  149. package/dist/test/text-overlay.test.js +15 -16
  150. package/dist/test/text-overlay.test.js.map +1 -1
  151. package/dist/test/text-snippet-block.test.js +19 -14
  152. package/dist/test/text-snippet-block.test.js.map +1 -1
  153. package/dist/test/tile-stats.test.js +34 -73
  154. package/dist/test/tile-stats.test.js.map +1 -1
  155. package/dist/test/tiles/grid/account-tile.test.js +25 -25
  156. package/dist/test/tiles/grid/account-tile.test.js.map +1 -1
  157. package/dist/test/tiles/grid/collection-tile.test.js +19 -13
  158. package/dist/test/tiles/grid/collection-tile.test.js.map +1 -1
  159. package/dist/test/tiles/grid/item-tile.test.js +91 -64
  160. package/dist/test/tiles/grid/item-tile.test.js.map +1 -1
  161. package/dist/test/tiles/grid/search-tile.test.js +13 -9
  162. package/dist/test/tiles/grid/search-tile.test.js.map +1 -1
  163. package/dist/test/tiles/hover/hover-pane-controller.test.js +35 -23
  164. package/dist/test/tiles/hover/hover-pane-controller.test.js.map +1 -1
  165. package/dist/test/tiles/hover/tile-hover-pane.test.js +16 -12
  166. package/dist/test/tiles/hover/tile-hover-pane.test.js.map +1 -1
  167. package/dist/test/tiles/list/tile-list-compact.test.js +48 -34
  168. package/dist/test/tiles/list/tile-list-compact.test.js.map +1 -1
  169. package/dist/test/tiles/list/tile-list.test.js +105 -76
  170. package/dist/test/tiles/list/tile-list.test.js.map +1 -1
  171. package/dist/test/tiles/tile-dispatcher.test.js +30 -17
  172. package/dist/test/tiles/tile-dispatcher.test.js.map +1 -1
  173. package/dist/test/tiles/tile-mediatype-icon.test.js +24 -12
  174. package/dist/test/tiles/tile-mediatype-icon.test.js.map +1 -1
  175. package/eslint.config.mjs +53 -53
  176. package/index.html +24 -24
  177. package/local.archive.org.cert +86 -86
  178. package/local.archive.org.key +27 -27
  179. package/package.json +118 -120
  180. package/renovate.json +6 -6
  181. package/src/collection-browser.ts +15 -246
  182. package/src/collection-facets/facet-row.ts +296 -299
  183. package/src/collection-facets/more-facets-content.ts +8 -5
  184. package/src/collection-facets.ts +995 -1010
  185. package/src/data-source/collection-browser-data-source-interface.ts +333 -345
  186. package/src/data-source/collection-browser-data-source.ts +1401 -1441
  187. package/src/data-source/collection-browser-query-state.ts +65 -59
  188. package/src/data-source/models.ts +43 -56
  189. package/src/models.ts +870 -866
  190. package/src/restoration-state-handler.ts +544 -546
  191. package/test/collection-browser.test.ts +2403 -2413
  192. package/test/restoration-state-handler.test.ts +510 -480
  193. package/tsconfig.json +20 -25
  194. package/vite.config.ts +22 -29
  195. package/web-dev-server.config.mjs +30 -30
  196. package/web-test-runner.config.mjs +41 -41
  197. package/dist/src/combo-box/caret-closed.d.ts +0 -2
  198. package/dist/src/combo-box/caret-closed.js +0 -7
  199. package/dist/src/combo-box/caret-closed.js.map +0 -1
  200. package/dist/src/combo-box/caret-open.d.ts +0 -2
  201. package/dist/src/combo-box/caret-open.js +0 -7
  202. package/dist/src/combo-box/caret-open.js.map +0 -1
  203. package/dist/src/combo-box/clear.d.ts +0 -2
  204. package/dist/src/combo-box/clear.js +0 -11
  205. package/dist/src/combo-box/clear.js.map +0 -1
  206. package/dist/src/combo-box/ia-combo-box.d.ts +0 -422
  207. package/dist/src/combo-box/ia-combo-box.js +0 -1203
  208. package/dist/src/combo-box/ia-combo-box.js.map +0 -1
  209. package/dist/src/combo-box/models.d.ts +0 -75
  210. package/dist/src/combo-box/models.js +0 -40
  211. package/dist/src/combo-box/models.js.map +0 -1
  212. package/src/combo-box/caret-closed.ts +0 -7
  213. package/src/combo-box/caret-open.ts +0 -7
  214. package/src/combo-box/clear.ts +0 -11
  215. package/src/combo-box/ia-combo-box.ts +0 -1288
  216. package/src/combo-box/models.ts +0 -113
@@ -1,299 +1,296 @@
1
- import {
2
- css,
3
- html,
4
- LitElement,
5
- TemplateResult,
6
- CSSResultGroup,
7
- nothing,
8
- } from 'lit';
9
- import { customElement, property } from 'lit/decorators.js';
10
- import eyeIcon from '../assets/img/icons/eye';
11
- import eyeClosedIcon from '../assets/img/icons/eye-closed';
12
- import type {
13
- FacetOption,
14
- FacetBucket,
15
- FacetEventDetails,
16
- FacetState,
17
- } from '../models';
18
- import type { CollectionTitles } from '../data-source/models';
19
- import { srOnlyStyle } from '../styles/sr-only';
20
-
21
- @customElement('facet-row')
22
- export class FacetRow extends LitElement {
23
- //
24
- // UI STATE
25
- //
26
-
27
- /** The name of the facet group to which this facet belongs (e.g., "mediatype") */
28
- @property({ type: String }) facetType?: FacetOption;
29
-
30
- /** The facet bucket containing details about the state, count, and key for this row */
31
- @property({ type: Object }) bucket?: FacetBucket;
32
-
33
- /** The collection name cache for converting collection identifiers to titles */
34
- @property({ type: Object })
35
- collectionTitles?: CollectionTitles;
36
-
37
- //
38
- // COMPONENT LIFECYCLE METHODS
39
- //
40
-
41
- render() {
42
- return html`${this.facetRowTemplate}`;
43
- }
44
-
45
- //
46
- // TEMPLATE GETTERS
47
- //
48
-
49
- /**
50
- * Template for the full facet row, including the positive/negative checks,
51
- * the display name, and the count.
52
- */
53
- private get facetRowTemplate(): TemplateResult | typeof nothing {
54
- const { bucket, facetType } = this;
55
- if (!bucket || !facetType) return nothing;
56
-
57
- const showOnlyCheckboxId = `${facetType}:${bucket.key}-show-only`;
58
- const negativeCheckboxId = `${facetType}:${bucket.key}-negative`;
59
-
60
- const extraNoteSpan = bucket.extraNote
61
- ? html`<span class="facet-note">${bucket.extraNote}</span>`
62
- : nothing;
63
-
64
- // For collections, we render the collection title as a link.
65
- // For other facet types, we just have a static value to use.
66
- const bucketTextDisplay =
67
- facetType !== 'collection'
68
- ? html`${bucket.displayText ?? bucket.key} ${extraNoteSpan}`
69
- : html`<a href="/details/${bucket.key}">
70
- ${this.collectionTitles?.get(bucket.key) ?? bucket.key}
71
- </a> `;
72
-
73
- const bucketCountText =
74
- bucket.count > 0 ? bucket.count.toLocaleString() : '';
75
-
76
- const facetHidden = bucket.state === 'hidden';
77
- const facetSelected = bucket.state === 'selected';
78
-
79
- const titleText = `${facetType}: ${bucket.displayText ?? bucket.key}`;
80
- const onlyShowText = facetSelected
81
- ? `Show all ${facetType}s`
82
- : `Only show ${titleText}`;
83
- const hideText = `Hide ${titleText}`;
84
- const unhideText = `Unhide ${titleText}`;
85
- const showHideText = facetHidden ? unhideText : hideText;
86
- const ariaLabel = `${titleText}, ${bucket.count} results`;
87
-
88
- // Added data-testid for Playwright testing
89
- return html`
90
- <div class="facet-row-container">
91
- <div class="facet-checkboxes">
92
- <input
93
- type="checkbox"
94
- .name=${facetType}
95
- .value=${bucket.key}
96
- @click=${(e: Event) => {
97
- this.facetClicked(e, false);
98
- }}
99
- .checked=${facetSelected}
100
- class="select-facet-checkbox"
101
- title=${onlyShowText}
102
- id=${showOnlyCheckboxId}
103
- data-testid=${showOnlyCheckboxId}
104
- />
105
- <div class="hide-facet-container">
106
- <input
107
- type="checkbox"
108
- id=${negativeCheckboxId}
109
- .name=${facetType}
110
- .value=${bucket.key}
111
- @click=${(e: Event) => {
112
- this.facetClicked(e, true);
113
- }}
114
- .checked=${facetHidden}
115
- class="hide-facet-checkbox"
116
- />
117
- <label
118
- for=${negativeCheckboxId}
119
- class="hide-facet-icon${facetHidden ? ' active' : ''}"
120
- title=${showHideText}
121
- data-testid=${negativeCheckboxId}
122
- >
123
- <span class="sr-only">${showHideText}</span>
124
- <span class="eye eye-open">${eyeIcon}</span>
125
- <span class="eye eye-closed">${eyeClosedIcon}</span>
126
- </label>
127
- </div>
128
- </div>
129
- <label
130
- for=${showOnlyCheckboxId}
131
- class="facet-info-display"
132
- title=${onlyShowText}
133
- aria-label=${ariaLabel}
134
- >
135
- <div class="facet-title">${bucketTextDisplay}</div>
136
- <div class="facet-count">${bucketCountText}</div>
137
- </label>
138
- </div>
139
- `;
140
- }
141
-
142
- //
143
- // EVENT HANDLERS & DISPATCHERS
144
- //
145
-
146
- /**
147
- * Handler for whenever this facet is clicked & its state changes
148
- */
149
- private facetClicked(e: Event, negative: boolean) {
150
- const { bucket, facetType } = this;
151
- if (!bucket || !facetType) return;
152
-
153
- const target = e.target as HTMLInputElement;
154
- const { checked } = target;
155
- this.bucket = {
156
- ...bucket,
157
- state: FacetRow.getFacetState(checked, negative),
158
- };
159
-
160
- this.dispatchFacetClickEvent({
161
- facetType,
162
- bucket: this.bucket,
163
- negative,
164
- });
165
- }
166
-
167
- /**
168
- * Emits a `facetClick` event with details about this facet & its current state
169
- */
170
- private dispatchFacetClickEvent(detail: FacetEventDetails) {
171
- const event = new CustomEvent<FacetEventDetails>('facetClick', {
172
- detail,
173
- });
174
- this.dispatchEvent(event);
175
- }
176
-
177
- //
178
- // OTHER METHODS
179
- //
180
-
181
- /**
182
- * Returns the composed facet state corresponding to a positive or negative facet's checked state
183
- */
184
- static getFacetState(checked: boolean, negative: boolean): FacetState {
185
- let state: FacetState;
186
- if (checked) {
187
- state = negative ? 'hidden' : 'selected';
188
- } else {
189
- state = 'none';
190
- }
191
- return state;
192
- }
193
-
194
- //
195
- // STYLES
196
- //
197
-
198
- static get styles(): CSSResultGroup {
199
- const facetRowBorderTop = css`var(--facet-row-border-top, 1px solid transparent)`;
200
- const facetRowBorderBottom = css`var(--facet-row-border-bottom, 1px solid transparent)`;
201
- const checkboxHeight = css`15px`;
202
-
203
- const ownCss = css`
204
- .facet-checkboxes {
205
- margin: 0 5px 0 0;
206
- display: flex;
207
- height: ${checkboxHeight};
208
- }
209
- .facet-checkboxes input:first-child {
210
- margin-right: 5px;
211
- }
212
- .facet-checkboxes input {
213
- height: ${checkboxHeight};
214
- width: ${checkboxHeight};
215
- margin: 0;
216
- }
217
- .facet-row-container {
218
- display: flex;
219
- font-weight: 500;
220
- font-size: 1.2rem;
221
- margin: 0 auto;
222
- padding: 0.25rem 0;
223
- height: auto;
224
- border-top: ${facetRowBorderTop};
225
- border-bottom: ${facetRowBorderBottom};
226
- }
227
- .facet-info-display {
228
- display: flex;
229
- flex: 1 1 0%;
230
- cursor: pointer;
231
- flex-wrap: wrap;
232
- }
233
- .facet-title {
234
- word-break: break-word;
235
- display: inline-block;
236
- flex: 1 1 0%;
237
- }
238
- .facet-note {
239
- color: #bbb;
240
- }
241
- .facet-count {
242
- text-align: right;
243
- }
244
- .select-facet-checkbox {
245
- cursor: pointer;
246
- display: inline-block;
247
- }
248
- .hide-facet-checkbox {
249
- position: absolute;
250
- clip: rect(0, 0, 0, 0);
251
- pointer-events: none;
252
- }
253
- .hide-facet-checkbox:focus-visible + .hide-facet-icon {
254
- outline-style: auto;
255
- outline-offset: 2px;
256
- }
257
- .hide-facet-icon {
258
- width: ${checkboxHeight};
259
- height: ${checkboxHeight};
260
- cursor: pointer;
261
- display: flex;
262
- }
263
- .eye {
264
- width: ${checkboxHeight};
265
- height: ${checkboxHeight};
266
- opacity: 0.3;
267
- }
268
- .hide-facet-icon:hover .eye,
269
- .active .eye {
270
- opacity: 1;
271
- }
272
- .hide-facet-icon:hover .eye-open,
273
- .hide-facet-icon .eye-closed {
274
- display: none;
275
- }
276
- .hide-facet-icon:hover .eye-closed,
277
- .hide-facet-icon.active .eye-closed {
278
- display: inline;
279
- }
280
- .hide-facet-icon.active .eye-open {
281
- display: none;
282
- }
283
- .sorting-icon {
284
- cursor: pointer;
285
- }
286
-
287
- a:link,
288
- a:visited {
289
- text-decoration: none;
290
- color: var(--ia-theme-link-color, #4b64ff);
291
- }
292
- a:hover {
293
- text-decoration: underline;
294
- }
295
- `;
296
-
297
- return [srOnlyStyle, ownCss];
298
- }
299
- }
1
+ import {
2
+ css,
3
+ html,
4
+ LitElement,
5
+ TemplateResult,
6
+ CSSResultGroup,
7
+ nothing,
8
+ } from 'lit';
9
+ import { customElement, property } from 'lit/decorators.js';
10
+ import eyeIcon from '../assets/img/icons/eye';
11
+ import eyeClosedIcon from '../assets/img/icons/eye-closed';
12
+ import type {
13
+ FacetOption,
14
+ FacetBucket,
15
+ FacetEventDetails,
16
+ FacetState,
17
+ } from '../models';
18
+ import type { CollectionTitles } from '../data-source/models';
19
+ import { srOnlyStyle } from '../styles/sr-only';
20
+
21
+ @customElement('facet-row')
22
+ export class FacetRow extends LitElement {
23
+ //
24
+ // UI STATE
25
+ //
26
+
27
+ /** The name of the facet group to which this facet belongs (e.g., "mediatype") */
28
+ @property({ type: String }) facetType?: FacetOption;
29
+
30
+ /** The facet bucket containing details about the state, count, and key for this row */
31
+ @property({ type: Object }) bucket?: FacetBucket;
32
+
33
+ /** The collection name cache for converting collection identifiers to titles */
34
+ @property({ type: Object })
35
+ collectionTitles?: CollectionTitles;
36
+
37
+ //
38
+ // COMPONENT LIFECYCLE METHODS
39
+ //
40
+
41
+ render() {
42
+ return html`${this.facetRowTemplate}`;
43
+ }
44
+
45
+ //
46
+ // TEMPLATE GETTERS
47
+ //
48
+
49
+ /**
50
+ * Template for the full facet row, including the positive/negative checks,
51
+ * the display name, and the count.
52
+ */
53
+ private get facetRowTemplate(): TemplateResult | typeof nothing {
54
+ const { bucket, facetType } = this;
55
+ if (!bucket || !facetType) return nothing;
56
+
57
+ const showOnlyCheckboxId = `${facetType}:${bucket.key}-show-only`;
58
+ const negativeCheckboxId = `${facetType}:${bucket.key}-negative`;
59
+
60
+ const extraNoteSpan = bucket.extraNote
61
+ ? html`<span class="facet-note">${bucket.extraNote}</span>`
62
+ : nothing;
63
+
64
+ // For collections, we render the collection title as a link.
65
+ // For other facet types, we just have a static value to use.
66
+ const bucketTextDisplay =
67
+ facetType !== 'collection'
68
+ ? html`${bucket.displayText ?? bucket.key} ${extraNoteSpan}`
69
+ : html`<a href="/details/${bucket.key}">
70
+ ${this.collectionTitles?.get(bucket.key) ?? bucket.key}
71
+ </a> `;
72
+
73
+ const facetHidden = bucket.state === 'hidden';
74
+ const facetSelected = bucket.state === 'selected';
75
+
76
+ const titleText = `${facetType}: ${bucket.displayText ?? bucket.key}`;
77
+ const onlyShowText = facetSelected
78
+ ? `Show all ${facetType}s`
79
+ : `Only show ${titleText}`;
80
+ const hideText = `Hide ${titleText}`;
81
+ const unhideText = `Unhide ${titleText}`;
82
+ const showHideText = facetHidden ? unhideText : hideText;
83
+ const ariaLabel = `${titleText}, ${bucket.count} results`;
84
+
85
+ // Added data-testid for Playwright testing
86
+ return html`
87
+ <div class="facet-row-container">
88
+ <div class="facet-checkboxes">
89
+ <input
90
+ type="checkbox"
91
+ .name=${facetType}
92
+ .value=${bucket.key}
93
+ @click=${(e: Event) => {
94
+ this.facetClicked(e, false);
95
+ }}
96
+ .checked=${facetSelected}
97
+ class="select-facet-checkbox"
98
+ title=${onlyShowText}
99
+ id=${showOnlyCheckboxId}
100
+ data-testid=${showOnlyCheckboxId}
101
+ />
102
+ <div class="hide-facet-container">
103
+ <input
104
+ type="checkbox"
105
+ id=${negativeCheckboxId}
106
+ .name=${facetType}
107
+ .value=${bucket.key}
108
+ @click=${(e: Event) => {
109
+ this.facetClicked(e, true);
110
+ }}
111
+ .checked=${facetHidden}
112
+ class="hide-facet-checkbox"
113
+ />
114
+ <label
115
+ for=${negativeCheckboxId}
116
+ class="hide-facet-icon${facetHidden ? ' active' : ''}"
117
+ title=${showHideText}
118
+ data-testid=${negativeCheckboxId}
119
+ >
120
+ <span class="sr-only">${showHideText}</span>
121
+ <span class="eye eye-open">${eyeIcon}</span>
122
+ <span class="eye eye-closed">${eyeClosedIcon}</span>
123
+ </label>
124
+ </div>
125
+ </div>
126
+ <label
127
+ for=${showOnlyCheckboxId}
128
+ class="facet-info-display"
129
+ title=${onlyShowText}
130
+ aria-label=${ariaLabel}
131
+ >
132
+ <div class="facet-title">${bucketTextDisplay}</div>
133
+ <div class="facet-count">${bucket.count.toLocaleString()}</div>
134
+ </label>
135
+ </div>
136
+ `;
137
+ }
138
+
139
+ //
140
+ // EVENT HANDLERS & DISPATCHERS
141
+ //
142
+
143
+ /**
144
+ * Handler for whenever this facet is clicked & its state changes
145
+ */
146
+ private facetClicked(e: Event, negative: boolean) {
147
+ const { bucket, facetType } = this;
148
+ if (!bucket || !facetType) return;
149
+
150
+ const target = e.target as HTMLInputElement;
151
+ const { checked } = target;
152
+ this.bucket = {
153
+ ...bucket,
154
+ state: FacetRow.getFacetState(checked, negative),
155
+ };
156
+
157
+ this.dispatchFacetClickEvent({
158
+ facetType,
159
+ bucket: this.bucket,
160
+ negative,
161
+ });
162
+ }
163
+
164
+ /**
165
+ * Emits a `facetClick` event with details about this facet & its current state
166
+ */
167
+ private dispatchFacetClickEvent(detail: FacetEventDetails) {
168
+ const event = new CustomEvent<FacetEventDetails>('facetClick', {
169
+ detail,
170
+ });
171
+ this.dispatchEvent(event);
172
+ }
173
+
174
+ //
175
+ // OTHER METHODS
176
+ //
177
+
178
+ /**
179
+ * Returns the composed facet state corresponding to a positive or negative facet's checked state
180
+ */
181
+ static getFacetState(checked: boolean, negative: boolean): FacetState {
182
+ let state: FacetState;
183
+ if (checked) {
184
+ state = negative ? 'hidden' : 'selected';
185
+ } else {
186
+ state = 'none';
187
+ }
188
+ return state;
189
+ }
190
+
191
+ //
192
+ // STYLES
193
+ //
194
+
195
+ static get styles(): CSSResultGroup {
196
+ const facetRowBorderTop = css`var(--facet-row-border-top, 1px solid transparent)`;
197
+ const facetRowBorderBottom = css`var(--facet-row-border-bottom, 1px solid transparent)`;
198
+ const checkboxHeight = css`15px`;
199
+
200
+ const ownCss = css`
201
+ .facet-checkboxes {
202
+ margin: 0 5px 0 0;
203
+ display: flex;
204
+ height: ${checkboxHeight};
205
+ }
206
+ .facet-checkboxes input:first-child {
207
+ margin-right: 5px;
208
+ }
209
+ .facet-checkboxes input {
210
+ height: ${checkboxHeight};
211
+ width: ${checkboxHeight};
212
+ margin: 0;
213
+ }
214
+ .facet-row-container {
215
+ display: flex;
216
+ font-weight: 500;
217
+ font-size: 1.2rem;
218
+ margin: 0 auto;
219
+ padding: 0.25rem 0;
220
+ height: auto;
221
+ border-top: ${facetRowBorderTop};
222
+ border-bottom: ${facetRowBorderBottom};
223
+ }
224
+ .facet-info-display {
225
+ display: flex;
226
+ flex: 1 1 0%;
227
+ cursor: pointer;
228
+ flex-wrap: wrap;
229
+ }
230
+ .facet-title {
231
+ word-break: break-word;
232
+ display: inline-block;
233
+ flex: 1 1 0%;
234
+ }
235
+ .facet-note {
236
+ color: #bbb;
237
+ }
238
+ .facet-count {
239
+ text-align: right;
240
+ }
241
+ .select-facet-checkbox {
242
+ cursor: pointer;
243
+ display: inline-block;
244
+ }
245
+ .hide-facet-checkbox {
246
+ position: absolute;
247
+ clip: rect(0, 0, 0, 0);
248
+ pointer-events: none;
249
+ }
250
+ .hide-facet-checkbox:focus-visible + .hide-facet-icon {
251
+ outline-style: auto;
252
+ outline-offset: 2px;
253
+ }
254
+ .hide-facet-icon {
255
+ width: ${checkboxHeight};
256
+ height: ${checkboxHeight};
257
+ cursor: pointer;
258
+ display: flex;
259
+ }
260
+ .eye {
261
+ width: ${checkboxHeight};
262
+ height: ${checkboxHeight};
263
+ opacity: 0.3;
264
+ }
265
+ .hide-facet-icon:hover .eye,
266
+ .active .eye {
267
+ opacity: 1;
268
+ }
269
+ .hide-facet-icon:hover .eye-open,
270
+ .hide-facet-icon .eye-closed {
271
+ display: none;
272
+ }
273
+ .hide-facet-icon:hover .eye-closed,
274
+ .hide-facet-icon.active .eye-closed {
275
+ display: inline;
276
+ }
277
+ .hide-facet-icon.active .eye-open {
278
+ display: none;
279
+ }
280
+ .sorting-icon {
281
+ cursor: pointer;
282
+ }
283
+
284
+ a:link,
285
+ a:visited {
286
+ text-decoration: none;
287
+ color: var(--ia-theme-link-color, #4b64ff);
288
+ }
289
+ a:hover {
290
+ text-decoration: underline;
291
+ }
292
+ `;
293
+
294
+ return [srOnlyStyle, ownCss];
295
+ }
296
+ }
@@ -38,7 +38,7 @@ import type {
38
38
  PageSpecifierParams,
39
39
  TVChannelAliases,
40
40
  } from '../data-source/models';
41
- import '@internetarchive/ia-activity-indicator';
41
+ import '@internetarchive/elements/ia-status-indicator/ia-status-indicator';
42
42
  import './more-facets-pagination';
43
43
  import './facets-template';
44
44
  import {
@@ -424,9 +424,12 @@ export class MoreFacetsContent extends LitElement {
424
424
  }
425
425
 
426
426
  private get loaderTemplate(): TemplateResult {
427
- return html`<div class="facets-loader">
428
- <ia-activity-indicator .mode=${'processing'}></ia-activity-indicator>
429
- </div> `;
427
+ return html`
428
+ <ia-status-indicator
429
+ class="facets-loader"
430
+ mode="loading"
431
+ ></ia-status-indicator>
432
+ `;
430
433
  }
431
434
 
432
435
  /**
@@ -596,8 +599,8 @@ export class MoreFacetsContent extends LitElement {
596
599
  padding: 10px;
597
600
  }
598
601
  .facets-loader {
602
+ --icon-width: 70px;
599
603
  margin-bottom: 20px;
600
- width: 70px;
601
604
  display: block;
602
605
  margin-left: auto;
603
606
  margin-right: auto;