@internetarchive/collection-browser 1.14.10-alpha.3 → 1.14.10-alpha1

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 (293) hide show
  1. package/.editorconfig +29 -29
  2. package/.husky/pre-commit +4 -4
  3. package/LICENSE +661 -661
  4. package/README.md +83 -83
  5. package/dist/index.d.ts +9 -9
  6. package/dist/index.js +9 -9
  7. package/dist/src/app-root.d.ts +79 -72
  8. package/dist/src/app-root.js +564 -432
  9. package/dist/src/app-root.js.map +1 -1
  10. package/dist/src/assets/img/icons/arrow-left.d.ts +2 -2
  11. package/dist/src/assets/img/icons/arrow-left.js +2 -2
  12. package/dist/src/assets/img/icons/arrow-right.d.ts +2 -2
  13. package/dist/src/assets/img/icons/arrow-right.js +2 -2
  14. package/dist/src/assets/img/icons/chevron.d.ts +2 -2
  15. package/dist/src/assets/img/icons/chevron.js +2 -2
  16. package/dist/src/assets/img/icons/contract.d.ts +2 -2
  17. package/dist/src/assets/img/icons/contract.js +2 -2
  18. package/dist/src/assets/img/icons/empty-query.d.ts +2 -2
  19. package/dist/src/assets/img/icons/empty-query.js +2 -2
  20. package/dist/src/assets/img/icons/expand.d.ts +2 -2
  21. package/dist/src/assets/img/icons/expand.js +2 -2
  22. package/dist/src/assets/img/icons/eye-closed.d.ts +2 -2
  23. package/dist/src/assets/img/icons/eye-closed.js +2 -2
  24. package/dist/src/assets/img/icons/eye.d.ts +2 -2
  25. package/dist/src/assets/img/icons/eye.js +2 -2
  26. package/dist/src/assets/img/icons/favorite-filled.d.ts +1 -1
  27. package/dist/src/assets/img/icons/favorite-filled.js +2 -2
  28. package/dist/src/assets/img/icons/login-required.d.ts +1 -1
  29. package/dist/src/assets/img/icons/login-required.js +2 -2
  30. package/dist/src/assets/img/icons/mediatype/account.d.ts +1 -1
  31. package/dist/src/assets/img/icons/mediatype/account.js +2 -2
  32. package/dist/src/assets/img/icons/mediatype/audio.d.ts +1 -1
  33. package/dist/src/assets/img/icons/mediatype/audio.js +2 -2
  34. package/dist/src/assets/img/icons/mediatype/collection.d.ts +1 -1
  35. package/dist/src/assets/img/icons/mediatype/collection.js +2 -2
  36. package/dist/src/assets/img/icons/mediatype/data.d.ts +1 -1
  37. package/dist/src/assets/img/icons/mediatype/data.js +2 -2
  38. package/dist/src/assets/img/icons/mediatype/etree.d.ts +1 -1
  39. package/dist/src/assets/img/icons/mediatype/etree.js +2 -2
  40. package/dist/src/assets/img/icons/mediatype/film.d.ts +1 -1
  41. package/dist/src/assets/img/icons/mediatype/film.js +2 -2
  42. package/dist/src/assets/img/icons/mediatype/images.d.ts +1 -1
  43. package/dist/src/assets/img/icons/mediatype/images.js +2 -2
  44. package/dist/src/assets/img/icons/mediatype/radio.d.ts +1 -1
  45. package/dist/src/assets/img/icons/mediatype/radio.js +2 -2
  46. package/dist/src/assets/img/icons/mediatype/search.d.ts +1 -1
  47. package/dist/src/assets/img/icons/mediatype/search.js +2 -2
  48. package/dist/src/assets/img/icons/mediatype/software.d.ts +1 -1
  49. package/dist/src/assets/img/icons/mediatype/software.js +2 -2
  50. package/dist/src/assets/img/icons/mediatype/texts.d.ts +1 -1
  51. package/dist/src/assets/img/icons/mediatype/texts.js +2 -2
  52. package/dist/src/assets/img/icons/mediatype/tv.d.ts +1 -1
  53. package/dist/src/assets/img/icons/mediatype/tv.js +2 -2
  54. package/dist/src/assets/img/icons/mediatype/video.d.ts +1 -1
  55. package/dist/src/assets/img/icons/mediatype/video.js +2 -2
  56. package/dist/src/assets/img/icons/mediatype/web.d.ts +1 -1
  57. package/dist/src/assets/img/icons/mediatype/web.js +2 -2
  58. package/dist/src/assets/img/icons/null-result.d.ts +2 -2
  59. package/dist/src/assets/img/icons/null-result.js +2 -2
  60. package/dist/src/assets/img/icons/restricted.d.ts +1 -1
  61. package/dist/src/assets/img/icons/restricted.js +2 -2
  62. package/dist/src/assets/img/icons/reviews.d.ts +1 -1
  63. package/dist/src/assets/img/icons/reviews.js +2 -2
  64. package/dist/src/assets/img/icons/upload.d.ts +1 -1
  65. package/dist/src/assets/img/icons/upload.js +2 -2
  66. package/dist/src/assets/img/icons/views.d.ts +1 -1
  67. package/dist/src/assets/img/icons/views.js +2 -2
  68. package/dist/src/circular-activity-indicator.d.ts +5 -5
  69. package/dist/src/circular-activity-indicator.js +17 -17
  70. package/dist/src/collection-browser.d.ts +533 -533
  71. package/dist/src/collection-browser.js +1897 -1891
  72. package/dist/src/collection-browser.js.map +1 -1
  73. package/dist/src/collection-facets/facet-row.d.ts +30 -0
  74. package/dist/src/collection-facets/facet-row.js +245 -0
  75. package/dist/src/collection-facets/facet-row.js.map +1 -0
  76. package/dist/src/collection-facets/facet-tombstone-row.d.ts +5 -5
  77. package/dist/src/collection-facets/facet-tombstone-row.js +15 -15
  78. package/dist/src/collection-facets/facets-template.d.ts +17 -20
  79. package/dist/src/collection-facets/facets-template.js +122 -264
  80. package/dist/src/collection-facets/facets-template.js.map +1 -1
  81. package/dist/src/collection-facets/more-facets-content.d.ts +77 -77
  82. package/dist/src/collection-facets/more-facets-content.js +359 -359
  83. package/dist/src/collection-facets/more-facets-pagination.d.ts +36 -36
  84. package/dist/src/collection-facets/more-facets-pagination.js +196 -196
  85. package/dist/src/collection-facets/toggle-switch.d.ts +41 -41
  86. package/dist/src/collection-facets/toggle-switch.js +94 -94
  87. package/dist/src/collection-facets.d.ts +104 -104
  88. package/dist/src/collection-facets.js +506 -506
  89. package/dist/src/empty-placeholder.d.ts +23 -23
  90. package/dist/src/empty-placeholder.js +74 -74
  91. package/dist/src/expanded-date-picker.d.ts +43 -43
  92. package/dist/src/expanded-date-picker.js +109 -109
  93. package/dist/src/language-code-handler/language-code-handler.d.ts +37 -37
  94. package/dist/src/language-code-handler/language-code-handler.js +26 -26
  95. package/dist/src/language-code-handler/language-code-mapping.d.ts +1 -1
  96. package/dist/src/language-code-handler/language-code-mapping.js +562 -562
  97. package/dist/src/manage/manage-bar.d.ts +26 -26
  98. package/dist/src/manage/manage-bar.js +53 -53
  99. package/dist/src/mediatype/mediatype-config.d.ts +3 -3
  100. package/dist/src/mediatype/mediatype-config.js +91 -91
  101. package/dist/src/models.d.ts +180 -164
  102. package/dist/src/models.js +269 -269
  103. package/dist/src/models.js.map +1 -1
  104. package/dist/src/restoration-state-handler.d.ts +70 -70
  105. package/dist/src/restoration-state-handler.js +355 -355
  106. package/dist/src/sort-filter-bar/alpha-bar-tooltip.d.ts +6 -6
  107. package/dist/src/sort-filter-bar/alpha-bar-tooltip.js +24 -24
  108. package/dist/src/sort-filter-bar/alpha-bar.d.ts +21 -21
  109. package/dist/src/sort-filter-bar/alpha-bar.js +128 -128
  110. package/dist/src/sort-filter-bar/img/compact.d.ts +1 -1
  111. package/dist/src/sort-filter-bar/img/compact.js +2 -2
  112. package/dist/src/sort-filter-bar/img/list.d.ts +1 -1
  113. package/dist/src/sort-filter-bar/img/list.js +2 -2
  114. package/dist/src/sort-filter-bar/img/sort-toggle-disabled.d.ts +1 -1
  115. package/dist/src/sort-filter-bar/img/sort-toggle-disabled.js +2 -2
  116. package/dist/src/sort-filter-bar/img/sort-toggle-down.d.ts +1 -1
  117. package/dist/src/sort-filter-bar/img/sort-toggle-down.js +2 -2
  118. package/dist/src/sort-filter-bar/img/sort-toggle-up.d.ts +1 -1
  119. package/dist/src/sort-filter-bar/img/sort-toggle-up.js +2 -2
  120. package/dist/src/sort-filter-bar/img/sort-triangle.d.ts +1 -1
  121. package/dist/src/sort-filter-bar/img/sort-triangle.js +2 -2
  122. package/dist/src/sort-filter-bar/img/tile.d.ts +1 -1
  123. package/dist/src/sort-filter-bar/img/tile.js +2 -2
  124. package/dist/src/sort-filter-bar/sort-filter-bar.d.ts +208 -208
  125. package/dist/src/sort-filter-bar/sort-filter-bar.js +638 -637
  126. package/dist/src/sort-filter-bar/sort-filter-bar.js.map +1 -1
  127. package/dist/src/styles/item-image-styles.d.ts +8 -8
  128. package/dist/src/styles/item-image-styles.js +9 -9
  129. package/dist/src/styles/sr-only.d.ts +1 -1
  130. package/dist/src/styles/sr-only.js +2 -2
  131. package/dist/src/tiles/base-tile-component.d.ts +19 -19
  132. package/dist/src/tiles/base-tile-component.js +63 -63
  133. package/dist/src/tiles/collection-browser-loading-tile.d.ts +5 -5
  134. package/dist/src/tiles/collection-browser-loading-tile.js +15 -15
  135. package/dist/src/tiles/grid/account-tile.d.ts +18 -18
  136. package/dist/src/tiles/grid/account-tile.js +72 -72
  137. package/dist/src/tiles/grid/collection-tile.d.ts +15 -15
  138. package/dist/src/tiles/grid/collection-tile.js +80 -80
  139. package/dist/src/tiles/grid/item-tile.d.ts +27 -27
  140. package/dist/src/tiles/grid/item-tile.js +134 -134
  141. package/dist/src/tiles/grid/search-tile.d.ts +10 -10
  142. package/dist/src/tiles/grid/search-tile.js +51 -51
  143. package/dist/src/tiles/grid/styles/tile-grid-shared-styles.d.ts +1 -1
  144. package/dist/src/tiles/grid/styles/tile-grid-shared-styles.js +8 -8
  145. package/dist/src/tiles/grid/tile-stats.d.ts +11 -11
  146. package/dist/src/tiles/grid/tile-stats.js +48 -48
  147. package/dist/src/tiles/hover/hover-pane-controller.d.ts +219 -219
  148. package/dist/src/tiles/hover/hover-pane-controller.js +352 -352
  149. package/dist/src/tiles/hover/tile-hover-pane.d.ts +15 -15
  150. package/dist/src/tiles/hover/tile-hover-pane.js +38 -38
  151. package/dist/src/tiles/image-block.d.ts +17 -17
  152. package/dist/src/tiles/image-block.js +73 -73
  153. package/dist/src/tiles/item-image.d.ts +36 -36
  154. package/dist/src/tiles/item-image.js +127 -127
  155. package/dist/src/tiles/list/tile-list-compact-header.d.ts +6 -6
  156. package/dist/src/tiles/list/tile-list-compact-header.js +38 -38
  157. package/dist/src/tiles/list/tile-list-compact.d.ts +15 -15
  158. package/dist/src/tiles/list/tile-list-compact.js +114 -114
  159. package/dist/src/tiles/list/tile-list.d.ts +46 -46
  160. package/dist/src/tiles/list/tile-list.js +302 -302
  161. package/dist/src/tiles/mediatype-icon.d.ts +9 -9
  162. package/dist/src/tiles/mediatype-icon.js +47 -47
  163. package/dist/src/tiles/overlay/icon-overlay.d.ts +10 -10
  164. package/dist/src/tiles/overlay/icon-overlay.js +40 -40
  165. package/dist/src/tiles/overlay/icon-text-overlay.d.ts +9 -9
  166. package/dist/src/tiles/overlay/icon-text-overlay.js +38 -38
  167. package/dist/src/tiles/overlay/text-overlay.d.ts +10 -10
  168. package/dist/src/tiles/overlay/text-overlay.js +42 -42
  169. package/dist/src/tiles/text-snippet-block.d.ts +27 -27
  170. package/dist/src/tiles/text-snippet-block.js +73 -73
  171. package/dist/src/tiles/tile-dispatcher.d.ts +64 -64
  172. package/dist/src/tiles/tile-dispatcher.js +231 -231
  173. package/dist/src/tiles/tile-display-value-provider.d.ts +43 -43
  174. package/dist/src/tiles/tile-display-value-provider.js +80 -80
  175. package/dist/src/utils/analytics-events.d.ts +25 -25
  176. package/dist/src/utils/analytics-events.js +27 -27
  177. package/dist/src/utils/array-equals.d.ts +4 -4
  178. package/dist/src/utils/array-equals.js +10 -10
  179. package/dist/src/utils/format-count.d.ts +7 -7
  180. package/dist/src/utils/format-count.js +76 -76
  181. package/dist/src/utils/format-date.d.ts +2 -2
  182. package/dist/src/utils/format-date.js +25 -25
  183. package/dist/src/utils/format-unit-size.d.ts +2 -2
  184. package/dist/src/utils/format-unit-size.js +33 -33
  185. package/dist/src/utils/local-date-from-utc.d.ts +9 -9
  186. package/dist/src/utils/local-date-from-utc.js +15 -15
  187. package/dist/src/utils/sha1.d.ts +2 -2
  188. package/dist/src/utils/sha1.js +8 -8
  189. package/dist/test/collection-browser.test.d.ts +1 -1
  190. package/dist/test/collection-browser.test.js +1130 -1098
  191. package/dist/test/collection-browser.test.js.map +1 -1
  192. package/dist/test/collection-facets/facet-row.test.d.ts +1 -0
  193. package/dist/test/collection-facets/facet-row.test.js +235 -0
  194. package/dist/test/collection-facets/facet-row.test.js.map +1 -0
  195. package/dist/test/collection-facets/facets-template.test.d.ts +1 -1
  196. package/dist/test/collection-facets/facets-template.test.js +110 -141
  197. package/dist/test/collection-facets/facets-template.test.js.map +1 -1
  198. package/dist/test/collection-facets/more-facets-content.test.d.ts +1 -1
  199. package/dist/test/collection-facets/more-facets-content.test.js +133 -133
  200. package/dist/test/collection-facets/more-facets-pagination.test.d.ts +1 -1
  201. package/dist/test/collection-facets/more-facets-pagination.test.js +117 -117
  202. package/dist/test/collection-facets/toggle-switch.test.d.ts +1 -1
  203. package/dist/test/collection-facets/toggle-switch.test.js +73 -73
  204. package/dist/test/collection-facets.test.d.ts +2 -2
  205. package/dist/test/collection-facets.test.js +651 -682
  206. package/dist/test/collection-facets.test.js.map +1 -1
  207. package/dist/test/empty-placeholder.test.d.ts +1 -1
  208. package/dist/test/empty-placeholder.test.js +63 -63
  209. package/dist/test/expanded-date-picker.test.d.ts +1 -1
  210. package/dist/test/expanded-date-picker.test.js +95 -95
  211. package/dist/test/icon-overlay.test.d.ts +1 -1
  212. package/dist/test/icon-overlay.test.js +24 -24
  213. package/dist/test/image-block.test.d.ts +1 -1
  214. package/dist/test/image-block.test.js +48 -48
  215. package/dist/test/item-image.test.d.ts +1 -1
  216. package/dist/test/item-image.test.js +86 -86
  217. package/dist/test/manage/manage-bar.test.d.ts +1 -1
  218. package/dist/test/manage/manage-bar.test.js +72 -72
  219. package/dist/test/mediatype-config.test.d.ts +1 -1
  220. package/dist/test/mediatype-config.test.js +16 -16
  221. package/dist/test/mocks/mock-analytics-handler.d.ts +10 -10
  222. package/dist/test/mocks/mock-analytics-handler.js +15 -15
  223. package/dist/test/mocks/mock-collection-name-cache.d.ts +9 -9
  224. package/dist/test/mocks/mock-collection-name-cache.js +17 -17
  225. package/dist/test/mocks/mock-search-responses.d.ts +21 -21
  226. package/dist/test/mocks/mock-search-responses.js +709 -709
  227. package/dist/test/mocks/mock-search-service.d.ts +15 -15
  228. package/dist/test/mocks/mock-search-service.js +50 -50
  229. package/dist/test/restoration-state-handler.test.d.ts +1 -1
  230. package/dist/test/restoration-state-handler.test.js +270 -270
  231. package/dist/test/sort-filter-bar/alpha-bar-tooltip.test.d.ts +1 -1
  232. package/dist/test/sort-filter-bar/alpha-bar-tooltip.test.js +12 -12
  233. package/dist/test/sort-filter-bar/alpha-bar.test.d.ts +1 -1
  234. package/dist/test/sort-filter-bar/alpha-bar.test.js +73 -73
  235. package/dist/test/sort-filter-bar/sort-filter-bar.test.d.ts +1 -1
  236. package/dist/test/sort-filter-bar/sort-filter-bar.test.js +378 -378
  237. package/dist/test/text-overlay.test.d.ts +1 -1
  238. package/dist/test/text-overlay.test.js +48 -48
  239. package/dist/test/text-snippet-block.test.d.ts +1 -1
  240. package/dist/test/text-snippet-block.test.js +57 -57
  241. package/dist/test/tile-stats.test.d.ts +1 -1
  242. package/dist/test/tile-stats.test.js +33 -33
  243. package/dist/test/tiles/grid/account-tile.test.d.ts +1 -1
  244. package/dist/test/tiles/grid/account-tile.test.js +76 -76
  245. package/dist/test/tiles/grid/collection-tile.test.d.ts +1 -1
  246. package/dist/test/tiles/grid/collection-tile.test.js +73 -73
  247. package/dist/test/tiles/grid/item-tile.test.d.ts +1 -1
  248. package/dist/test/tiles/grid/item-tile.test.js +254 -254
  249. package/dist/test/tiles/grid/search-tile.test.d.ts +1 -1
  250. package/dist/test/tiles/grid/search-tile.test.js +51 -51
  251. package/dist/test/tiles/hover/hover-pane-controller.test.d.ts +1 -1
  252. package/dist/test/tiles/hover/hover-pane-controller.test.js +258 -258
  253. package/dist/test/tiles/hover/tile-hover-pane.test.d.ts +1 -1
  254. package/dist/test/tiles/hover/tile-hover-pane.test.js +13 -13
  255. package/dist/test/tiles/list/tile-list-compact.test.d.ts +1 -1
  256. package/dist/test/tiles/list/tile-list-compact.test.js +143 -143
  257. package/dist/test/tiles/list/tile-list.test.d.ts +1 -1
  258. package/dist/test/tiles/list/tile-list.test.js +242 -242
  259. package/dist/test/tiles/tile-dispatcher.test.d.ts +1 -1
  260. package/dist/test/tiles/tile-dispatcher.test.js +94 -94
  261. package/dist/test/tiles/tile-display-value-provider.test.d.ts +1 -1
  262. package/dist/test/tiles/tile-display-value-provider.test.js +141 -141
  263. package/dist/test/utils/array-equals.test.d.ts +1 -1
  264. package/dist/test/utils/array-equals.test.js +26 -26
  265. package/dist/test/utils/format-count.test.d.ts +1 -1
  266. package/dist/test/utils/format-count.test.js +23 -23
  267. package/dist/test/utils/format-date.test.d.ts +1 -1
  268. package/dist/test/utils/format-date.test.js +17 -17
  269. package/dist/test/utils/format-unit-size.test.d.ts +1 -1
  270. package/dist/test/utils/format-unit-size.test.js +17 -17
  271. package/dist/test/utils/local-date-from-utc.test.d.ts +1 -1
  272. package/dist/test/utils/local-date-from-utc.test.js +26 -26
  273. package/local.archive.org.cert +86 -86
  274. package/local.archive.org.key +27 -27
  275. package/package.json +5 -5
  276. package/renovate.json +6 -6
  277. package/src/app-root.ts +230 -90
  278. package/src/collection-browser.ts +23 -18
  279. package/src/collection-facets/facet-row.ts +274 -0
  280. package/src/collection-facets/facets-template.ts +49 -196
  281. package/src/models.ts +18 -2
  282. package/src/sort-filter-bar/sort-filter-bar.ts +1 -0
  283. package/test/collection-browser.test.ts +36 -4
  284. package/test/collection-facets/facet-row.test.ts +328 -0
  285. package/test/collection-facets/facets-template.test.ts +72 -110
  286. package/test/collection-facets.test.ts +69 -101
  287. package/tsconfig.json +21 -21
  288. package/web-dev-server.config.mjs +30 -30
  289. package/web-test-runner.config.mjs +41 -41
  290. package/dist/src/selected-facets.d.ts +0 -67
  291. package/dist/src/selected-facets.js +0 -149
  292. package/dist/src/selected-facets.js.map +0 -1
  293. package/src/selected-facets.ts +0 -216
@@ -0,0 +1,274 @@
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 type { CollectionNameCacheInterface } from '@internetarchive/collection-name-cache';
11
+ import eyeIcon from '../assets/img/icons/eye';
12
+ import eyeClosedIcon from '../assets/img/icons/eye-closed';
13
+ import type {
14
+ FacetOption,
15
+ FacetBucket,
16
+ FacetEventDetails,
17
+ FacetState,
18
+ } from '../models';
19
+
20
+ @customElement('facet-row')
21
+ export class FacetRow extends LitElement {
22
+ //
23
+ // UI STATE
24
+ //
25
+
26
+ /** The name of the facet group to which this facet belongs (e.g., "mediatype") */
27
+ @property({ type: String }) facetType?: FacetOption;
28
+
29
+ /** The facet bucket containing details about the state, count, and key for this row */
30
+ @property({ type: Object }) bucket?: FacetBucket;
31
+
32
+ /** The collection name cache for converting collection identifiers to titles */
33
+ @property({ type: Object })
34
+ collectionNameCache?: CollectionNameCacheInterface;
35
+
36
+ //
37
+ // COMPONENT LIFECYCLE METHODS
38
+ //
39
+
40
+ render() {
41
+ return html`${this.facetRowTemplate}`;
42
+ }
43
+
44
+ //
45
+ // TEMPLATE GETTERS
46
+ //
47
+
48
+ /**
49
+ * Template for the full facet row, including the positive/negative checks,
50
+ * the display name, and the count.
51
+ */
52
+ private get facetRowTemplate(): TemplateResult | typeof nothing {
53
+ const { bucket, facetType } = this;
54
+ if (!bucket || !facetType) return nothing;
55
+
56
+ const showOnlyCheckboxId = `${facetType}:${bucket.key}-show-only`;
57
+ const negativeCheckboxId = `${facetType}:${bucket.key}-negative`;
58
+
59
+ // For collections, we need to asynchronously load the collection name
60
+ // so we use the `async-collection-name` widget.
61
+ // For other facet types, we just have a static value to use.
62
+ const bucketTextDisplay =
63
+ facetType !== 'collection'
64
+ ? html`${bucket.displayText ?? bucket.key}`
65
+ : html`<a href="/details/${bucket.key}">
66
+ <async-collection-name
67
+ .collectionNameCache=${this.collectionNameCache}
68
+ .identifier=${bucket.key}
69
+ placeholder="-"
70
+ ></async-collection-name>
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
+ return html`
86
+ <div class="facet-row-container">
87
+ <div class="facet-checkboxes">
88
+ <input
89
+ type="checkbox"
90
+ .name=${facetType}
91
+ .value=${bucket.key}
92
+ @click=${(e: Event) => {
93
+ this.facetClicked(e, false);
94
+ }}
95
+ .checked=${facetSelected}
96
+ class="select-facet-checkbox"
97
+ title=${onlyShowText}
98
+ id=${showOnlyCheckboxId}
99
+ />
100
+ <input
101
+ type="checkbox"
102
+ id=${negativeCheckboxId}
103
+ .name=${facetType}
104
+ .value=${bucket.key}
105
+ @click=${(e: Event) => {
106
+ this.facetClicked(e, true);
107
+ }}
108
+ .checked=${facetHidden}
109
+ class="hide-facet-checkbox"
110
+ />
111
+ <label
112
+ for=${negativeCheckboxId}
113
+ class="hide-facet-icon${facetHidden ? ' active' : ''}"
114
+ title=${showHideText}
115
+ >
116
+ <span class="eye">${eyeIcon}</span>
117
+ <span class="eye-closed">${eyeClosedIcon}</span>
118
+ </label>
119
+ </div>
120
+ <label
121
+ for=${showOnlyCheckboxId}
122
+ class="facet-info-display"
123
+ title=${onlyShowText}
124
+ aria-label=${ariaLabel}
125
+ >
126
+ <div class="facet-title">${bucketTextDisplay}</div>
127
+ <div class="facet-count">${bucket.count.toLocaleString()}</div>
128
+ </label>
129
+ </div>
130
+ `;
131
+ }
132
+
133
+ //
134
+ // EVENT HANDLERS & DISPATCHERS
135
+ //
136
+
137
+ /**
138
+ * Handler for whenever this facet is clicked & its state changes
139
+ */
140
+ private facetClicked(e: Event, negative: boolean) {
141
+ const { bucket, facetType } = this;
142
+ if (!bucket || !facetType) return;
143
+
144
+ const target = e.target as HTMLInputElement;
145
+ const { checked } = target;
146
+ bucket.state = FacetRow.getFacetState(checked, negative);
147
+
148
+ this.dispatchFacetClickEvent({
149
+ facetType,
150
+ bucket,
151
+ negative,
152
+ });
153
+ }
154
+
155
+ /**
156
+ * Emits a `facetClick` event with details about this facet & its current state
157
+ */
158
+ private dispatchFacetClickEvent(detail: FacetEventDetails) {
159
+ const event = new CustomEvent<FacetEventDetails>('facetClick', {
160
+ detail,
161
+ });
162
+ this.dispatchEvent(event);
163
+ }
164
+
165
+ //
166
+ // OTHER METHODS
167
+ //
168
+
169
+ /**
170
+ * Returns the composed facet state corresponding to a positive or negative facet's checked state
171
+ */
172
+ static getFacetState(checked: boolean, negative: boolean): FacetState {
173
+ let state: FacetState;
174
+ if (checked) {
175
+ state = negative ? 'hidden' : 'selected';
176
+ } else {
177
+ state = 'none';
178
+ }
179
+ return state;
180
+ }
181
+
182
+ //
183
+ // STYLES
184
+ //
185
+
186
+ static get styles(): CSSResultGroup {
187
+ const facetRowBorderTop = css`var(--facet-row-border-top, 1px solid transparent)`;
188
+ const facetRowBorderBottom = css`var(--facet-row-border-bottom, 1px solid transparent)`;
189
+
190
+ return css`
191
+ async-collection-name {
192
+ display: contents;
193
+ }
194
+ .facet-checkboxes {
195
+ margin: 0 5px 0 0;
196
+ display: flex;
197
+ height: 15px;
198
+ }
199
+ .facet-checkboxes input:first-child {
200
+ margin-right: 5px;
201
+ }
202
+ .facet-checkboxes input {
203
+ height: 15px;
204
+ width: 15px;
205
+ margin: 0;
206
+ }
207
+ .facet-row-container {
208
+ display: flex;
209
+ font-weight: 500;
210
+ font-size: 1.2rem;
211
+ margin: 2.5px auto;
212
+ height: auto;
213
+ border-top: ${facetRowBorderTop};
214
+ border-bottom: ${facetRowBorderBottom};
215
+ overflow: hidden;
216
+ }
217
+ .facet-info-display {
218
+ display: flex;
219
+ flex: 1 1 0%;
220
+ cursor: pointer;
221
+ flex-wrap: wrap;
222
+ }
223
+ .facet-title {
224
+ word-break: break-word;
225
+ display: inline-block;
226
+ flex: 1 1 0%;
227
+ }
228
+ .facet-count {
229
+ text-align: right;
230
+ }
231
+ .select-facet-checkbox {
232
+ cursor: pointer;
233
+ display: inline-block;
234
+ }
235
+ .hide-facet-checkbox {
236
+ display: none;
237
+ }
238
+ .hide-facet-icon {
239
+ width: 15px;
240
+ height: 15px;
241
+ cursor: pointer;
242
+ opacity: 0.3;
243
+ display: inline-block;
244
+ }
245
+ .hide-facet-icon:hover,
246
+ .active {
247
+ opacity: 1;
248
+ }
249
+ .hide-facet-icon:hover .eye,
250
+ .hide-facet-icon .eye-closed {
251
+ display: none;
252
+ }
253
+ .hide-facet-icon:hover .eye-closed,
254
+ .hide-facet-icon.active .eye-closed {
255
+ display: inline;
256
+ }
257
+ .hide-facet-icon.active .eye {
258
+ display: none;
259
+ }
260
+ .sorting-icon {
261
+ cursor: pointer;
262
+ }
263
+
264
+ a:link,
265
+ a:visited {
266
+ text-decoration: none;
267
+ color: var(--ia-theme-link-color, #4b64ff);
268
+ }
269
+ a:hover {
270
+ text-decoration: underline;
271
+ }
272
+ `;
273
+ }
274
+ }
@@ -1,18 +1,22 @@
1
- import { css, html, LitElement, TemplateResult, CSSResultGroup } from 'lit';
1
+ import {
2
+ css,
3
+ html,
4
+ LitElement,
5
+ TemplateResult,
6
+ CSSResultGroup,
7
+ nothing,
8
+ } from 'lit';
2
9
  import { customElement, property } from 'lit/decorators.js';
3
10
  import { repeat } from 'lit/directives/repeat.js';
4
11
  import type { CollectionNameCacheInterface } from '@internetarchive/collection-name-cache';
5
- import eyeIcon from '../assets/img/icons/eye';
6
- import eyeClosedIcon from '../assets/img/icons/eye-closed';
7
12
  import {
8
13
  FacetGroup,
9
- FacetOption,
10
14
  FacetBucket,
11
15
  SelectedFacets,
12
16
  getDefaultSelectedFacets,
13
17
  FacetEventDetails,
14
- FacetState,
15
18
  } from '../models';
19
+ import { FacetRow } from './facet-row';
16
20
 
17
21
  @customElement('facets-template')
18
22
  export class FacetsTemplate extends LitElement {
@@ -22,34 +26,24 @@ export class FacetsTemplate extends LitElement {
22
26
 
23
27
  @property({ type: String }) renderOn?: string;
24
28
 
25
- @property({ type: String }) collectionPagePath: string = '/details/';
26
-
27
29
  @property({ type: Object })
28
30
  collectionNameCache?: CollectionNameCacheInterface;
29
31
 
30
- private facetClicked(e: Event, count: number, negative: boolean) {
31
- const target = e.target as HTMLInputElement;
32
- const { checked, name, value } = target;
33
- if (checked) {
34
- this.facetChecked(name as FacetOption, value, count, negative);
32
+ private facetClicked(e: CustomEvent<FacetEventDetails>) {
33
+ const { bucket, negative } = e.detail;
34
+ if (bucket.state === 'none') {
35
+ this.facetUnchecked(bucket);
35
36
  } else {
36
- this.facetUnchecked(name as FacetOption, value);
37
+ this.facetChecked(bucket, negative);
37
38
  }
38
39
 
39
- this.dispatchFacetClickEvent(
40
- name as FacetOption,
41
- this.getFacetState(checked, negative),
42
- negative
43
- );
40
+ this.dispatchFacetClickEvent(e.detail);
44
41
  }
45
42
 
46
- private facetChecked(
47
- key: FacetOption,
48
- value: string,
49
- count: number,
50
- negative: boolean
51
- ) {
52
- const { selectedFacets } = this;
43
+ private facetChecked(bucket: FacetBucket, negative: boolean) {
44
+ const { facetGroup, selectedFacets } = this;
45
+ if (!facetGroup) return;
46
+
53
47
  let newFacets: SelectedFacets;
54
48
  if (selectedFacets) {
55
49
  newFacets = {
@@ -58,17 +52,19 @@ export class FacetsTemplate extends LitElement {
58
52
  } else {
59
53
  newFacets = getDefaultSelectedFacets();
60
54
  }
61
- newFacets[key][value] = {
62
- state: this.getFacetState(true, negative),
63
- count,
64
- } as FacetBucket;
55
+ newFacets[facetGroup.key][bucket.key] = {
56
+ ...bucket,
57
+ state: FacetRow.getFacetState(true, negative),
58
+ };
65
59
 
66
60
  this.selectedFacets = newFacets;
67
61
  this.dispatchSelectedFacetsChanged();
68
62
  }
69
63
 
70
- private facetUnchecked(key: FacetOption, value: string) {
71
- const { selectedFacets } = this;
64
+ private facetUnchecked(bucket: FacetBucket) {
65
+ const { facetGroup, selectedFacets } = this;
66
+ if (!facetGroup) return;
67
+
72
68
  let newFacets: SelectedFacets;
73
69
  if (selectedFacets) {
74
70
  newFacets = {
@@ -77,30 +73,15 @@ export class FacetsTemplate extends LitElement {
77
73
  } else {
78
74
  newFacets = getDefaultSelectedFacets();
79
75
  }
80
- delete newFacets[key][value];
76
+ delete newFacets[facetGroup.key][bucket.key];
81
77
 
82
78
  this.selectedFacets = newFacets;
83
79
  this.dispatchSelectedFacetsChanged();
84
80
  }
85
81
 
86
- /** Returns the composed facet state corresponding to a positive or negative facet's checked state */
87
- private getFacetState(checked: boolean, negative: boolean): FacetState {
88
- let state: FacetState;
89
- if (checked) {
90
- state = negative ? 'hidden' : 'selected';
91
- } else {
92
- state = 'none';
93
- }
94
- return state;
95
- }
96
-
97
- private dispatchFacetClickEvent(
98
- key: FacetOption,
99
- state: FacetState,
100
- negative: boolean
101
- ) {
82
+ private dispatchFacetClickEvent(detail: FacetEventDetails) {
102
83
  const event = new CustomEvent<FacetEventDetails>('facetClick', {
103
- detail: { key, state, negative },
84
+ detail,
104
85
  composed: true,
105
86
  });
106
87
  this.dispatchEvent(event);
@@ -115,8 +96,11 @@ export class FacetsTemplate extends LitElement {
115
96
  this.dispatchEvent(event);
116
97
  }
117
98
 
118
- private getFacetsTemplate(facetGroup: FacetGroup): TemplateResult {
119
- let facetsBucket = facetGroup?.buckets as FacetBucket[];
99
+ private get facetsTemplate(): TemplateResult | typeof nothing {
100
+ const { facetGroup } = this;
101
+ if (!facetGroup) return nothing;
102
+
103
+ let facetBuckets = facetGroup.buckets as FacetBucket[];
120
104
 
121
105
  /**
122
106
  * sorting FacetBucket before render page / modal
@@ -124,105 +108,34 @@ export class FacetsTemplate extends LitElement {
124
108
  * - second, suppressed/hidden items should be after selected having sorted
125
109
  * - and then no-selected / not suppressed items should render having sorted
126
110
  */
127
- facetsBucket = [
128
- ...facetsBucket
111
+ facetBuckets = [
112
+ ...facetBuckets
129
113
  .filter(x => x.state === 'selected')
130
114
  .sort((a, b) => (a.count < b.count ? 1 : -1)),
131
- ...facetsBucket
115
+ ...facetBuckets
132
116
  .filter(x => x.state === 'hidden')
133
117
  .sort((a, b) => (a.count < b.count ? 1 : -1)),
134
- ...facetsBucket.filter(x => x.state === 'none'),
118
+ ...facetBuckets.filter(x => x.state === 'none'),
135
119
  ];
136
120
 
137
121
  return html`
138
122
  <div class="facets-on-${this.renderOn}">
139
123
  ${repeat(
140
- facetsBucket,
124
+ facetBuckets,
141
125
  bucket => `${facetGroup.key}:${bucket.key}`,
142
- bucket => {
143
- const showOnlyCheckboxId = `${facetGroup.key}:${bucket.key}-show-only`;
144
- const negativeCheckboxId = `${facetGroup.key}:${bucket.key}-negative`;
145
- // for collections, we need to asynchronously load the collection name
146
- // so we use the `async-collection-name` widget and for the rest, we have
147
- // a static value to use
148
- const bucketTextDisplay =
149
- facetGroup.key !== 'collection'
150
- ? html`${bucket.displayText ?? bucket.key}`
151
- : html`<a href="${this.collectionPagePath}${bucket.key}">
152
- <async-collection-name
153
- .collectionNameCache=${this.collectionNameCache}
154
- .identifier=${bucket.key}
155
- placeholder="-"
156
- ></async-collection-name>
157
- </a> `;
158
- const facetHidden = bucket.state === 'hidden';
159
- const facetSelected = bucket.state === 'selected';
160
- const titleText = `${facetGroup.key}: ${
161
- bucket.displayText ?? bucket.key
162
- }`;
163
- const onlyShowText = facetSelected
164
- ? `Show all ${facetGroup.key}s`
165
- : `Only show ${titleText}`;
166
- const hideText = `Hide ${titleText}`;
167
- const unhideText = `Unhide ${titleText}`;
168
- const showHideText = facetHidden ? unhideText : hideText;
169
- const ariaLabel = `${titleText}, ${bucket.count} results`;
170
- return html`
171
- <div class="facet-row">
172
- <div class="facet-checkbox">
173
- <input
174
- type="checkbox"
175
- .name=${facetGroup.key}
176
- .value=${bucket.key}
177
- @click=${(e: Event) => {
178
- this.facetClicked(e, bucket.count, false);
179
- }}
180
- .checked=${facetSelected}
181
- class="select-facet-checkbox"
182
- title=${onlyShowText}
183
- id=${showOnlyCheckboxId}
184
- />
185
- <input
186
- type="checkbox"
187
- id=${negativeCheckboxId}
188
- .name=${facetGroup.key}
189
- .value=${bucket.key}
190
- @click=${(e: Event) => {
191
- this.facetClicked(e, bucket.count, true);
192
- }}
193
- .checked=${facetHidden}
194
- class="hide-facet-checkbox"
195
- />
196
- <label
197
- for=${negativeCheckboxId}
198
- class="hide-facet-icon${facetHidden ? ' active' : ''}"
199
- title=${showHideText}
200
- >
201
- <span class="eye">${eyeIcon}</span>
202
- <span class="eye-closed">${eyeClosedIcon}</span>
203
- </label>
204
- </div>
205
- <label
206
- for=${showOnlyCheckboxId}
207
- class="facet-info-display"
208
- title=${onlyShowText}
209
- aria-label=${ariaLabel}
210
- >
211
- <div class="facet-title">${bucketTextDisplay}</div>
212
- <div class="facet-count">
213
- ${bucket.count.toLocaleString()}
214
- </div>
215
- </label>
216
- </div>
217
- `;
218
- }
126
+ bucket => html`<facet-row
127
+ .facetType=${facetGroup.key}
128
+ .bucket=${bucket}
129
+ .collectionNameCache=${this.collectionNameCache}
130
+ @facetClick=${this.facetClicked}
131
+ ></facet-row>`
219
132
  )}
220
133
  </div>
221
134
  `;
222
135
  }
223
136
 
224
137
  render() {
225
- return html`${this.getFacetsTemplate(this.facetGroup as FacetGroup)}`;
138
+ return html`${this.facetsTemplate}`;
226
139
  }
227
140
 
228
141
  static get styles(): CSSResultGroup {
@@ -236,9 +149,7 @@ export class FacetsTemplate extends LitElement {
236
149
  column-gap: 15px;
237
150
  column-count: 3;
238
151
  }
239
- async-collection-name {
240
- display: contents;
241
- }
152
+
242
153
  ul.facet-list {
243
154
  list-style: none;
244
155
  margin: 0;
@@ -248,19 +159,7 @@ export class FacetsTemplate extends LitElement {
248
159
  margin-bottom: 0.2rem;
249
160
  display: grid;
250
161
  }
251
- .facet-checkbox {
252
- margin: 0 5px 0 0;
253
- display: flex;
254
- height: 15px;
255
- }
256
- .facet-checkbox input:first-child {
257
- margin-right: 5px;
258
- }
259
- .facet-checkbox input {
260
- height: 15px;
261
- width: 15px;
262
- margin: 0;
263
- }
162
+
264
163
  .facet-row {
265
164
  display: flex;
266
165
  font-weight: 500;
@@ -271,52 +170,6 @@ export class FacetsTemplate extends LitElement {
271
170
  border-bottom: var(--facet-row-border-bottom, 1px solid transparent);
272
171
  overflow: hidden;
273
172
  }
274
- .facet-info-display {
275
- display: flex;
276
- flex: 1 1 0%;
277
- cursor: pointer;
278
- flex-wrap: wrap;
279
- }
280
- .facet-title {
281
- word-break: break-word;
282
- display: inline-block;
283
- flex: 1 1 0%;
284
- }
285
- .facet-count {
286
- text-align: right;
287
- }
288
- .select-facet-checkbox {
289
- cursor: pointer;
290
- display: inline-block;
291
- }
292
- .hide-facet-checkbox {
293
- display: none;
294
- }
295
- .hide-facet-icon {
296
- width: 15px;
297
- height: 15px;
298
- cursor: pointer;
299
- opacity: 0.3;
300
- display: inline-block;
301
- }
302
- .hide-facet-icon:hover,
303
- .active {
304
- opacity: 1;
305
- }
306
- .hide-facet-icon:hover .eye,
307
- .hide-facet-icon .eye-closed {
308
- display: none;
309
- }
310
- .hide-facet-icon:hover .eye-closed,
311
- .hide-facet-icon.active .eye-closed {
312
- display: inline;
313
- }
314
- .hide-facet-icon.active .eye {
315
- display: none;
316
- }
317
- .sorting-icon {
318
- cursor: pointer;
319
- }
320
173
 
321
174
  a:link,
322
175
  a:visited {
package/src/models.ts CHANGED
@@ -295,6 +295,9 @@ export const prefixFilterAggregationKeys: Record<PrefixFilterType, string> = {
295
295
  creator: 'firstCreator',
296
296
  };
297
297
 
298
+ /**
299
+ * Union of the facet types that are available in the sidebar.
300
+ */
298
301
  export type FacetOption =
299
302
  | 'subject'
300
303
  | 'lending'
@@ -322,9 +325,22 @@ export interface FacetGroup {
322
325
  buckets: FacetBucket[];
323
326
  }
324
327
 
328
+ /**
329
+ * Information about a user interaction event on a facet.
330
+ */
325
331
  export type FacetEventDetails = {
326
- key: FacetOption;
327
- state: FacetState;
332
+ /**
333
+ * The type of facet that was interacted with (e.g., 'mediatype', 'language', ...).
334
+ */
335
+ facetType: FacetOption;
336
+ /**
337
+ * The bucket corresponding to the facet that was interacted with, including the
338
+ * updated state of the facet after the interaction.
339
+ */
340
+ bucket: FacetBucket;
341
+ /**
342
+ * Whether the interaction occurred on a negative facet.
343
+ */
328
344
  negative: boolean;
329
345
  };
330
346
 
@@ -130,6 +130,7 @@ export class SortFilterBar
130
130
  return html`
131
131
  <div id="container">
132
132
  <section id="sort-bar" aria-label="Sorting options">
133
+ <slot name="sortbar-left-slot"></slot>
133
134
  <div class="sort-direction-container">
134
135
  ${this.sortDirectionSelectorTemplate}
135
136
  </div>