@internetarchive/collection-browser 0.2.12 → 0.2.14-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 (270) hide show
  1. package/dist/index.d.ts +9 -0
  2. package/dist/index.js +1 -0
  3. package/dist/index.js.map +1 -0
  4. package/dist/src/app-root.d.ts +33 -0
  5. package/dist/src/app-root.js +311 -0
  6. package/dist/src/app-root.js.map +1 -0
  7. package/dist/src/assets/img/icons/arrow-left.d.ts +2 -0
  8. package/dist/src/assets/img/icons/arrow-left.js +10 -0
  9. package/dist/src/assets/img/icons/arrow-left.js.map +1 -0
  10. package/dist/src/assets/img/icons/arrow-right.d.ts +2 -0
  11. package/dist/src/assets/img/icons/arrow-right.js +10 -0
  12. package/dist/src/assets/img/icons/arrow-right.js.map +1 -0
  13. package/dist/src/assets/img/icons/chevron.d.ts +2 -0
  14. package/dist/src/assets/img/icons/chevron.js +4 -0
  15. package/dist/src/assets/img/icons/chevron.js.map +1 -0
  16. package/dist/src/assets/img/icons/empty-query.d.ts +2 -0
  17. package/dist/src/assets/img/icons/empty-query.js +5 -0
  18. package/dist/src/assets/img/icons/empty-query.js.map +1 -0
  19. package/dist/src/assets/img/icons/eye-closed.d.ts +2 -0
  20. package/dist/src/assets/img/icons/eye-closed.js +5 -0
  21. package/dist/src/assets/img/icons/eye-closed.js.map +1 -0
  22. package/dist/src/assets/img/icons/eye.d.ts +2 -0
  23. package/dist/src/assets/img/icons/eye.js +5 -0
  24. package/dist/src/assets/img/icons/eye.js.map +1 -0
  25. package/dist/src/assets/img/icons/favorite-filled.d.ts +1 -0
  26. package/dist/src/assets/img/icons/favorite-filled.js +11 -0
  27. package/dist/src/assets/img/icons/favorite-filled.js.map +1 -0
  28. package/dist/src/assets/img/icons/login-required.d.ts +1 -0
  29. package/dist/src/assets/img/icons/login-required.js +30 -0
  30. package/dist/src/assets/img/icons/login-required.js.map +1 -0
  31. package/dist/src/assets/img/icons/mediatype/account.d.ts +1 -0
  32. package/dist/src/assets/img/icons/mediatype/account.js +14 -0
  33. package/dist/src/assets/img/icons/mediatype/account.js.map +1 -0
  34. package/dist/src/assets/img/icons/mediatype/audio.d.ts +1 -0
  35. package/dist/src/assets/img/icons/mediatype/audio.js +14 -0
  36. package/dist/src/assets/img/icons/mediatype/audio.js.map +1 -0
  37. package/dist/src/assets/img/icons/mediatype/collection.d.ts +1 -0
  38. package/dist/src/assets/img/icons/mediatype/collection.js +12 -0
  39. package/dist/src/assets/img/icons/mediatype/collection.js.map +1 -0
  40. package/dist/src/assets/img/icons/mediatype/data.d.ts +1 -0
  41. package/dist/src/assets/img/icons/mediatype/data.js +15 -0
  42. package/dist/src/assets/img/icons/mediatype/data.js.map +1 -0
  43. package/dist/src/assets/img/icons/mediatype/etree.d.ts +1 -0
  44. package/dist/src/assets/img/icons/mediatype/etree.js +14 -0
  45. package/dist/src/assets/img/icons/mediatype/etree.js.map +1 -0
  46. package/dist/src/assets/img/icons/mediatype/film.d.ts +1 -0
  47. package/dist/src/assets/img/icons/mediatype/film.js +14 -0
  48. package/dist/src/assets/img/icons/mediatype/film.js.map +1 -0
  49. package/dist/src/assets/img/icons/mediatype/images.d.ts +1 -0
  50. package/dist/src/assets/img/icons/mediatype/images.js +13 -0
  51. package/dist/src/assets/img/icons/mediatype/images.js.map +1 -0
  52. package/dist/src/assets/img/icons/mediatype/radio.d.ts +1 -0
  53. package/dist/src/assets/img/icons/mediatype/radio.js +15 -0
  54. package/dist/src/assets/img/icons/mediatype/radio.js.map +1 -0
  55. package/dist/src/assets/img/icons/mediatype/software.d.ts +1 -0
  56. package/dist/src/assets/img/icons/mediatype/software.js +13 -0
  57. package/dist/src/assets/img/icons/mediatype/software.js.map +1 -0
  58. package/dist/src/assets/img/icons/mediatype/texts.d.ts +1 -0
  59. package/dist/src/assets/img/icons/mediatype/texts.js +13 -0
  60. package/dist/src/assets/img/icons/mediatype/texts.js.map +1 -0
  61. package/dist/src/assets/img/icons/mediatype/tv.d.ts +1 -0
  62. package/dist/src/assets/img/icons/mediatype/tv.js +14 -0
  63. package/dist/src/assets/img/icons/mediatype/tv.js.map +1 -0
  64. package/dist/src/assets/img/icons/mediatype/video.d.ts +1 -0
  65. package/dist/src/assets/img/icons/mediatype/video.js +14 -0
  66. package/dist/src/assets/img/icons/mediatype/video.js.map +1 -0
  67. package/dist/src/assets/img/icons/mediatype/web.d.ts +1 -0
  68. package/dist/src/assets/img/icons/mediatype/web.js +13 -0
  69. package/dist/src/assets/img/icons/mediatype/web.js.map +1 -0
  70. package/dist/src/assets/img/icons/null-result.d.ts +2 -0
  71. package/dist/src/assets/img/icons/null-result.js +5 -0
  72. package/dist/src/assets/img/icons/null-result.js.map +1 -0
  73. package/dist/src/assets/img/icons/restricted.d.ts +1 -0
  74. package/dist/src/assets/img/icons/restricted.js +29 -0
  75. package/dist/src/assets/img/icons/restricted.js.map +1 -0
  76. package/dist/src/assets/img/icons/reviews.d.ts +1 -0
  77. package/dist/src/assets/img/icons/reviews.js +11 -0
  78. package/dist/src/assets/img/icons/reviews.js.map +1 -0
  79. package/dist/src/assets/img/icons/upload.d.ts +1 -0
  80. package/dist/src/assets/img/icons/upload.js +12 -0
  81. package/dist/src/assets/img/icons/upload.js.map +1 -0
  82. package/dist/src/assets/img/icons/views.d.ts +1 -0
  83. package/dist/src/assets/img/icons/views.js +11 -0
  84. package/dist/src/assets/img/icons/views.js.map +1 -0
  85. package/dist/src/circular-activity-indicator.d.ts +5 -0
  86. package/dist/src/circular-activity-indicator.js +66 -0
  87. package/dist/src/circular-activity-indicator.js.map +1 -0
  88. package/dist/src/collection-browser.d.ts +216 -0
  89. package/dist/src/collection-browser.js +1248 -0
  90. package/dist/src/collection-browser.js.map +1 -0
  91. package/dist/src/collection-facets/more-facets-content.d.ts +50 -0
  92. package/dist/src/collection-facets/more-facets-content.js +354 -0
  93. package/dist/src/collection-facets/more-facets-content.js.map +1 -0
  94. package/dist/src/collection-facets/more-facets-pagination.d.ts +27 -0
  95. package/dist/src/collection-facets/more-facets-pagination.js +193 -0
  96. package/dist/src/collection-facets/more-facets-pagination.js.map +1 -0
  97. package/dist/src/collection-facets.d.ts +80 -0
  98. package/dist/src/collection-facets.js +662 -0
  99. package/dist/src/collection-facets.js.map +1 -0
  100. package/dist/src/empty-placeholder.d.ts +11 -0
  101. package/dist/src/empty-placeholder.js +83 -0
  102. package/dist/src/empty-placeholder.js.map +1 -0
  103. package/dist/src/language-code-handler/language-code-handler.d.ts +37 -0
  104. package/dist/src/language-code-handler/language-code-handler.js +27 -0
  105. package/dist/src/language-code-handler/language-code-handler.js.map +1 -0
  106. package/dist/src/language-code-handler/language-code-mapping.d.ts +1 -0
  107. package/dist/src/language-code-handler/language-code-mapping.js +563 -0
  108. package/dist/src/language-code-handler/language-code-mapping.js.map +1 -0
  109. package/dist/src/mediatype/mediatype-config.d.ts +3 -0
  110. package/dist/src/mediatype/mediatype-config.js +86 -0
  111. package/dist/src/mediatype/mediatype-config.js.map +1 -0
  112. package/dist/src/models.d.ts +84 -0
  113. package/dist/src/models.js +58 -0
  114. package/dist/src/models.js.map +1 -0
  115. package/dist/src/restoration-state-handler.d.ts +38 -0
  116. package/dist/src/restoration-state-handler.js +204 -0
  117. package/dist/src/restoration-state-handler.js.map +1 -0
  118. package/dist/src/sort-filter-bar/alpha-bar.d.ts +9 -0
  119. package/dist/src/sort-filter-bar/alpha-bar.js +98 -0
  120. package/dist/src/sort-filter-bar/alpha-bar.js.map +1 -0
  121. package/dist/src/sort-filter-bar/img/compact.d.ts +1 -0
  122. package/dist/src/sort-filter-bar/img/compact.js +5 -0
  123. package/dist/src/sort-filter-bar/img/compact.js.map +1 -0
  124. package/dist/src/sort-filter-bar/img/list.d.ts +1 -0
  125. package/dist/src/sort-filter-bar/img/list.js +5 -0
  126. package/dist/src/sort-filter-bar/img/list.js.map +1 -0
  127. package/dist/src/sort-filter-bar/img/sort-triangle.d.ts +1 -0
  128. package/dist/src/sort-filter-bar/img/sort-triangle.js +5 -0
  129. package/dist/src/sort-filter-bar/img/sort-triangle.js.map +1 -0
  130. package/dist/src/sort-filter-bar/img/tile.d.ts +1 -0
  131. package/dist/src/sort-filter-bar/img/tile.js +5 -0
  132. package/dist/src/sort-filter-bar/img/tile.js.map +1 -0
  133. package/dist/src/sort-filter-bar/sort-filter-bar.d.ts +85 -0
  134. package/dist/src/sort-filter-bar/sort-filter-bar.js +698 -0
  135. package/dist/src/sort-filter-bar/sort-filter-bar.js.map +1 -0
  136. package/dist/src/styles/item-image-styles.d.ts +8 -0
  137. package/dist/src/styles/item-image-styles.js +102 -0
  138. package/dist/src/styles/item-image-styles.js.map +1 -0
  139. package/dist/src/tiles/collection-browser-loading-tile.d.ts +5 -0
  140. package/dist/src/tiles/collection-browser-loading-tile.js +32 -0
  141. package/dist/src/tiles/collection-browser-loading-tile.js.map +1 -0
  142. package/dist/src/tiles/grid/account-tile.d.ts +8 -0
  143. package/dist/src/tiles/grid/account-tile.js +126 -0
  144. package/dist/src/tiles/grid/account-tile.js.map +1 -0
  145. package/dist/src/tiles/grid/collection-tile.d.ts +7 -0
  146. package/dist/src/tiles/grid/collection-tile.js +159 -0
  147. package/dist/src/tiles/grid/collection-tile.js.map +1 -0
  148. package/dist/src/tiles/grid/item-tile.d.ts +21 -0
  149. package/dist/src/tiles/grid/item-tile.js +183 -0
  150. package/dist/src/tiles/grid/item-tile.js.map +1 -0
  151. package/dist/src/tiles/grid/tile-stats.d.ts +10 -0
  152. package/dist/src/tiles/grid/tile-stats.js +134 -0
  153. package/dist/src/tiles/grid/tile-stats.js.map +1 -0
  154. package/dist/src/tiles/image-block.d.ts +17 -0
  155. package/dist/src/tiles/image-block.js +136 -0
  156. package/dist/src/tiles/image-block.js.map +1 -0
  157. package/dist/src/tiles/item-image.d.ts +31 -0
  158. package/dist/src/tiles/item-image.js +118 -0
  159. package/dist/src/tiles/item-image.js.map +1 -0
  160. package/dist/src/tiles/list/account-label.d.ts +1 -0
  161. package/dist/src/tiles/list/account-label.js +7 -0
  162. package/dist/src/tiles/list/account-label.js.map +1 -0
  163. package/dist/src/tiles/list/date-label.d.ts +1 -0
  164. package/dist/src/tiles/list/date-label.js +13 -0
  165. package/dist/src/tiles/list/date-label.js.map +1 -0
  166. package/dist/src/tiles/list/tile-list-compact-header.d.ts +12 -0
  167. package/dist/src/tiles/list/tile-list-compact-header.js +84 -0
  168. package/dist/src/tiles/list/tile-list-compact-header.js.map +1 -0
  169. package/dist/src/tiles/list/tile-list-compact.d.ts +20 -0
  170. package/dist/src/tiles/list/tile-list-compact.js +180 -0
  171. package/dist/src/tiles/list/tile-list-compact.js.map +1 -0
  172. package/dist/src/tiles/list/tile-list.d.ts +48 -0
  173. package/dist/src/tiles/list/tile-list.js +455 -0
  174. package/dist/src/tiles/list/tile-list.js.map +1 -0
  175. package/dist/src/tiles/mediatype-icon.d.ts +9 -0
  176. package/dist/src/tiles/mediatype-icon.js +82 -0
  177. package/dist/src/tiles/mediatype-icon.js.map +1 -0
  178. package/dist/src/tiles/overlay/icon-overlay.d.ts +7 -0
  179. package/dist/src/tiles/overlay/icon-overlay.js +43 -0
  180. package/dist/src/tiles/overlay/icon-overlay.js.map +1 -0
  181. package/dist/src/tiles/overlay/text-overlay.d.ts +8 -0
  182. package/dist/src/tiles/overlay/text-overlay.js +57 -0
  183. package/dist/src/tiles/overlay/text-overlay.js.map +1 -0
  184. package/dist/src/tiles/tile-dispatcher.d.ts +36 -0
  185. package/dist/src/tiles/tile-dispatcher.js +215 -0
  186. package/dist/src/tiles/tile-dispatcher.js.map +1 -0
  187. package/dist/src/utils/format-count.d.ts +7 -0
  188. package/dist/src/utils/format-count.js +76 -0
  189. package/dist/src/utils/format-count.js.map +1 -0
  190. package/dist/src/utils/format-date.d.ts +2 -0
  191. package/dist/src/utils/format-date.js +24 -0
  192. package/dist/src/utils/format-date.js.map +1 -0
  193. package/dist/test/collection-browser.test.d.ts +1 -0
  194. package/dist/test/collection-browser.test.js +47 -0
  195. package/dist/test/collection-browser.test.js.map +1 -0
  196. package/dist/test/collection-facets/more-facets-content.test.d.ts +1 -0
  197. package/dist/test/collection-facets/more-facets-content.test.js +75 -0
  198. package/dist/test/collection-facets/more-facets-content.test.js.map +1 -0
  199. package/dist/test/collection-facets/more-facets-pagination.test.d.ts +1 -0
  200. package/dist/test/collection-facets/more-facets-pagination.test.js +38 -0
  201. package/dist/test/collection-facets/more-facets-pagination.test.js.map +1 -0
  202. package/dist/test/empty-placeholder.test.d.ts +1 -0
  203. package/dist/test/empty-placeholder.test.js +34 -0
  204. package/dist/test/empty-placeholder.test.js.map +1 -0
  205. package/dist/test/icon-overlay.test.d.ts +1 -0
  206. package/dist/test/icon-overlay.test.js +31 -0
  207. package/dist/test/icon-overlay.test.js.map +1 -0
  208. package/dist/test/item-image.test.d.ts +1 -0
  209. package/dist/test/item-image.test.js +73 -0
  210. package/dist/test/item-image.test.js.map +1 -0
  211. package/dist/test/mediatype-config.test.d.ts +1 -0
  212. package/dist/test/mediatype-config.test.js +17 -0
  213. package/dist/test/mediatype-config.test.js.map +1 -0
  214. package/dist/test/mocks/mock-collection-name-cache.d.ts +7 -0
  215. package/dist/test/mocks/mock-collection-name-cache.js +14 -0
  216. package/dist/test/mocks/mock-collection-name-cache.js.map +1 -0
  217. package/dist/test/mocks/mock-search-responses.d.ts +3 -0
  218. package/dist/test/mocks/mock-search-responses.js +45 -0
  219. package/dist/test/mocks/mock-search-responses.js.map +1 -0
  220. package/dist/test/mocks/mock-search-service.d.ts +8 -0
  221. package/dist/test/mocks/mock-search-service.js +16 -0
  222. package/dist/test/mocks/mock-search-service.js.map +1 -0
  223. package/dist/test/text-overlay.test.d.ts +1 -0
  224. package/dist/test/text-overlay.test.js +48 -0
  225. package/dist/test/text-overlay.test.js.map +1 -0
  226. package/dist/test/tile-stats.test.d.ts +1 -0
  227. package/dist/test/tile-stats.test.js +42 -0
  228. package/dist/test/tile-stats.test.js.map +1 -0
  229. package/dist/test/tiles/grid/item-tile.test.d.ts +1 -0
  230. package/dist/test/tiles/grid/item-tile.test.js +96 -0
  231. package/dist/test/tiles/grid/item-tile.test.js.map +1 -0
  232. package/dist/test/utils/format-count.test.d.ts +1 -0
  233. package/dist/test/utils/format-count.test.js +24 -0
  234. package/dist/test/utils/format-count.test.js.map +1 -0
  235. package/dist/test/utils/format-date.test.d.ts +1 -0
  236. package/dist/test/utils/format-date.test.js +18 -0
  237. package/dist/test/utils/format-date.test.js.map +1 -0
  238. package/package.json +5 -2
  239. package/src/app-root.ts +28 -2
  240. package/src/assets/img/icons/arrow-left.ts +10 -0
  241. package/src/assets/img/icons/arrow-right.ts +10 -0
  242. package/src/collection-browser.ts +8 -2
  243. package/src/collection-facets/more-facets-content.ts +371 -0
  244. package/src/collection-facets/more-facets-pagination.ts +201 -0
  245. package/src/collection-facets.ts +119 -3
  246. package/src/restoration-state-handler.ts +1 -1
  247. package/src/sort-filter-bar/sort-filter-bar.ts +1 -1
  248. package/src/tiles/grid/account-tile.ts +1 -1
  249. package/src/tiles/grid/collection-tile.ts +1 -1
  250. package/src/tiles/grid/item-tile.ts +2 -2
  251. package/src/tiles/image-block.ts +1 -1
  252. package/src/tiles/item-image.ts +1 -1
  253. package/src/tiles/list/tile-list-compact-header.ts +2 -2
  254. package/src/tiles/list/tile-list-compact.ts +2 -2
  255. package/src/tiles/list/tile-list.ts +4 -4
  256. package/src/tiles/tile-dispatcher.ts +2 -2
  257. package/test/collection-browser.test.ts +1 -1
  258. package/test/collection-facets/more-facets-content.test.ts +113 -0
  259. package/test/collection-facets/more-facets-pagination.test.ts +70 -0
  260. package/test/empty-placeholder.test.ts +2 -1
  261. package/test/icon-overlay.test.ts +1 -1
  262. package/test/item-image.test.ts +2 -2
  263. package/test/mocks/mock-collection-name-cache.ts +1 -1
  264. package/test/mocks/mock-search-responses.ts +14 -1
  265. package/test/mocks/mock-search-service.ts +2 -2
  266. package/test/text-overlay.test.ts +1 -1
  267. package/test/tile-stats.test.ts +1 -1
  268. package/test/tiles/grid/item-tile.test.ts +1 -1
  269. package/tsconfig.json +3 -2
  270. package/types/dompurify.d.ts +1 -0
@@ -0,0 +1,201 @@
1
+ import { css, CSSResultGroup, html, LitElement, nothing } from 'lit';
2
+ import { customElement, property, state } from 'lit/decorators.js';
3
+ import arrowLeftIcon from '../assets/img/icons/arrow-left';
4
+ import arrowRightIcon from '../assets/img/icons/arrow-right';
5
+
6
+ @customElement('more-facets-pagination')
7
+ export class MoreFacetsPagination extends LitElement {
8
+ /**
9
+ * Total number of pages
10
+ */
11
+ @property({ type: Number }) size?: any | undefined;
12
+
13
+ /**
14
+ * Number of pages can be moved in back/forward
15
+ */
16
+ @property({ type: Number }) step = 2;
17
+
18
+ @state() pages?: number[] = [];
19
+
20
+ @state() currentPage = 1;
21
+
22
+ firstUpdated() {
23
+ this.observePageCount();
24
+ }
25
+
26
+ observePageCount() {
27
+ this.pages = [];
28
+ let startPage = this.currentPage - this.step;
29
+ let endPage = this.currentPage + this.step;
30
+
31
+ if (startPage <= 0) {
32
+ endPage += -startPage + 1;
33
+ startPage = 1;
34
+ }
35
+
36
+ if (endPage >= this.size) {
37
+ startPage = Math.max(startPage - (endPage - this.size), 1);
38
+ endPage = this.size;
39
+ }
40
+
41
+ // create first page node
42
+ this.createFirstNode(startPage);
43
+
44
+ // create middle pages node
45
+ this.createMiddelNode(startPage, endPage);
46
+
47
+ // create last page node
48
+ this.createLastNode(endPage);
49
+ }
50
+
51
+ private createFirstNode(startPage: number) {
52
+ if (startPage > 1) {
53
+ this.pages?.push(1);
54
+ this.pages?.push(0); // let's asssume 0 is for ellipsis template
55
+ }
56
+ }
57
+
58
+ private createMiddelNode(startPage: number, endPage: number) {
59
+ for (let page = startPage; page <= endPage; page += 1) {
60
+ this.pages?.push(page);
61
+ }
62
+ }
63
+
64
+ private createLastNode(endPage: number) {
65
+ if (endPage < this.size) {
66
+ this.pages?.push(0); // let's asssume 0 is for ellipsis template
67
+ this.pages?.push(this.size);
68
+ }
69
+ }
70
+
71
+ private get getEllipsisTemplate() {
72
+ return html`<i>...</i>`;
73
+ }
74
+
75
+ private emitPageClick() {
76
+ this.dispatchEvent(
77
+ new CustomEvent('pageNumberClicked', {
78
+ detail: { page: this.currentPage },
79
+ })
80
+ );
81
+ }
82
+
83
+ private onRewind() {
84
+ this.currentPage -= 1;
85
+ if (this.currentPage < 1) {
86
+ this.currentPage = 1;
87
+ }
88
+ this.observePageCount();
89
+ this.emitPageClick();
90
+ }
91
+
92
+ private onForward() {
93
+ this.currentPage += 1;
94
+ if (this.currentPage > this.size) {
95
+ this.currentPage = this.size;
96
+ }
97
+ this.observePageCount();
98
+ this.emitPageClick();
99
+ }
100
+
101
+ private onChange(page: number) {
102
+ this.currentPage = page;
103
+ this.observePageCount();
104
+ this.emitPageClick();
105
+ }
106
+
107
+ private getPageTemplate(page: number) {
108
+ return html`
109
+ <button
110
+ @click="${() => this.onChange(page)}"
111
+ class="${this.currentPage === page ? 'current' : nothing}"
112
+ >
113
+ ${page}
114
+ </button>
115
+ `;
116
+ }
117
+
118
+ private get getPagesTemplate() {
119
+ return html`
120
+ ${this.pages?.map(
121
+ page =>
122
+ html`${page !== 0
123
+ ? this.getPageTemplate(page)
124
+ : this.getEllipsisTemplate}`
125
+ )}
126
+ `;
127
+ }
128
+
129
+ render() {
130
+ return html`
131
+ <div class="facets-pagination">
132
+ <button class="arrow-icon" @click=${this.onRewind}>
133
+ <span class="sr-only">Rewind pagination:</span>
134
+ ${arrowLeftIcon}
135
+ </button>
136
+ <div class="page-numbers">${this.getPagesTemplate}</div>
137
+ <button class="arrow-icon" @click=${this.onForward}>
138
+ <span class="sr-only">Forward pagination:</span>
139
+ ${arrowRightIcon}
140
+ </button>
141
+ </div>
142
+ `;
143
+ }
144
+
145
+ static get styles(): CSSResultGroup {
146
+ return css`
147
+ .facets-pagination {
148
+ user-select: none;
149
+ margin-top: 10px;
150
+ background-color: rgb(239, 239, 239);
151
+ text-align: center;
152
+ font-size: 3.2rem;
153
+ }
154
+ .facets-pagination button {
155
+ border: none;
156
+ background: none;
157
+ }
158
+ .facets-pagination .arrow-icon {
159
+ width: 2.5rem;
160
+ vertical-align: initial;
161
+ }
162
+
163
+ .facets-pagination button,
164
+ .facets-pagination i {
165
+ background: none;
166
+ border: 0;
167
+ cursor: pointer;
168
+ border-radius: 100%;
169
+ margin: 10px;
170
+ padding: 5px;
171
+ font-size: 1.4rem;
172
+ vertical-align: middle;
173
+ display: inline-block;
174
+ min-width: 2.5rem;
175
+ }
176
+ .facets-pagination i {
177
+ cursor: auto;
178
+ display: inline;
179
+ }
180
+ .facets-pagination button.current {
181
+ background: black;
182
+ color: white;
183
+ }
184
+
185
+ .page-numbers {
186
+ display: inline-block;
187
+ }
188
+
189
+ .sr-only {
190
+ position: absolute;
191
+ width: 1px;
192
+ height: 1px;
193
+ padding: 0;
194
+ margin: -1px;
195
+ overflow: hidden;
196
+ clip: rect(0, 0, 0, 0);
197
+ border: 0;
198
+ }
199
+ `;
200
+ }
201
+ }
@@ -9,11 +9,19 @@ import {
9
9
  } from 'lit';
10
10
  import { customElement, property, state } from 'lit/decorators.js';
11
11
  import { repeat } from 'lit/directives/repeat.js';
12
- import { Aggregation, Bucket } from '@internetarchive/search-service';
12
+ import type {
13
+ Aggregation,
14
+ Bucket,
15
+ SearchServiceInterface,
16
+ } from '@internetarchive/search-service';
13
17
  import '@internetarchive/histogram-date-range';
14
18
  import '@internetarchive/feature-feedback';
15
19
  import '@internetarchive/collection-name-cache';
16
- import { CollectionNameCacheInterface } from '@internetarchive/collection-name-cache';
20
+ import type { CollectionNameCacheInterface } from '@internetarchive/collection-name-cache';
21
+ import {
22
+ ModalConfig,
23
+ ModalManagerInterface,
24
+ } from '@internetarchive/modal-manager';
17
25
  import eyeIcon from './assets/img/icons/eye';
18
26
  import eyeClosedIcon from './assets/img/icons/eye-closed';
19
27
  import chevronIcon from './assets/img/icons/chevron';
@@ -24,7 +32,8 @@ import {
24
32
  FacetBucket,
25
33
  defaultSelectedFacets,
26
34
  } from './models';
27
- import { LanguageCodeHandlerInterface } from './language-code-handler/language-code-handler';
35
+ import type { LanguageCodeHandlerInterface } from './language-code-handler/language-code-handler';
36
+ import './collection-facets/more-facets-content';
28
37
 
29
38
  const facetDisplayOrder: FacetOption[] = [
30
39
  'mediatype',
@@ -55,6 +64,8 @@ const facetTitles: Record<FacetOption, string> = {
55
64
 
56
65
  @customElement('collection-facets')
57
66
  export class CollectionFacets extends LitElement {
67
+ @property({ type: Object }) searchService?: SearchServiceInterface;
68
+
58
69
  @property({ type: Object }) aggregations?: Record<string, Aggregation>;
59
70
 
60
71
  @property({ type: Object }) fullYearsHistogramAggregation?: Aggregation;
@@ -73,6 +84,10 @@ export class CollectionFacets extends LitElement {
73
84
 
74
85
  @property({ type: Boolean }) showHistogramDatePicker = false;
75
86
 
87
+ @property({ type: String }) fullQuery?: string;
88
+
89
+ @property({ type: Object }) modalManager?: ModalManagerInterface;
90
+
76
91
  @property({ type: Object })
77
92
  languageCodeHandler?: LanguageCodeHandlerInterface;
78
93
 
@@ -88,6 +103,12 @@ export class CollectionFacets extends LitElement {
88
103
  year: false,
89
104
  };
90
105
 
106
+ /**
107
+ * If listed facets on page more then this number,
108
+ * - show the more link button just below the facets group
109
+ */
110
+ private moreLinkEligibilityCount = 5;
111
+
91
112
  render() {
92
113
  return html`
93
114
  <div id="container" class="${this.facetsLoading ? 'loading' : ''}">
@@ -112,6 +133,7 @@ export class CollectionFacets extends LitElement {
112
133
  }
113
134
  }
114
135
 
136
+ // TODO: want to fire analytics?
115
137
  private dispatchFacetsChangedEvent() {
116
138
  const event = new CustomEvent<SelectedFacets>('facetsChanged', {
117
139
  detail: this.selectedFacets,
@@ -322,11 +344,92 @@ export class CollectionFacets extends LitElement {
322
344
  </h1>
323
345
  <div class="facet-group-content ${isOpen ? 'open' : ''}">
324
346
  ${this.getFacetTemplate(facetGroup)}
347
+ ${this.searchMoreFacetsLink(facetGroup)}
325
348
  </div>
326
349
  </div>
327
350
  `;
328
351
  }
329
352
 
353
+ /**
354
+ * Generate the More... link button just below the facets group
355
+ *
356
+ * TODO: want to fire analytics?
357
+ */
358
+ private searchMoreFacetsLink(
359
+ facetGroup: FacetGroup
360
+ ): TemplateResult | typeof nothing {
361
+ // don't render More... link if you facets is < this.moreLinkEligibilityCount
362
+ if (Object.keys(facetGroup.buckets).length < this.moreLinkEligibilityCount)
363
+ return nothing;
364
+
365
+ return html`<button
366
+ class="more-link"
367
+ @click=${() => {
368
+ this.showMoreFacetsModal(facetGroup);
369
+ }}
370
+ >
371
+ More...
372
+ </button>`;
373
+ }
374
+
375
+ async showMoreFacetsModal(facetGroup: FacetGroup): Promise<void> {
376
+ const facetAggrKey = Object.keys(aggregationToFacetOption).find(
377
+ value => aggregationToFacetOption[value] === facetGroup.key
378
+ );
379
+
380
+ // TODO - lets move sr-only style into modal-manager component as well
381
+ const headline = html`
382
+ <span
383
+ style="display:block;text-align:left;font-size:1.8rem;padding:0 10px;"
384
+ >
385
+ <span
386
+ style="position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip: rect(0,0,0,0);border:0;"
387
+ >More facets for:
388
+ </span>
389
+ ${facetTitles[facetGroup.key]}
390
+ <img
391
+ src="https://archive.org/images/filter-count.png"
392
+ style="height: 1.5rem;vertical-align: baseline;"
393
+ alt=""
394
+ />
395
+ </span>
396
+ `;
397
+
398
+ const message = html`
399
+ <more-facets-content
400
+ @facetsChanged=${(e: CustomEvent) => {
401
+ const event = new CustomEvent<SelectedFacets>('facetsChanged', {
402
+ detail: e.detail,
403
+ bubbles: true,
404
+ composed: true,
405
+ });
406
+ this.dispatchEvent(event);
407
+ }}
408
+ .facetKey=${facetGroup.key}
409
+ .facetAggregationKey=${facetAggrKey}
410
+ .fullQuery=${this.fullQuery}
411
+ .modalManager=${this.modalManager}
412
+ .searchService=${this.searchService}
413
+ .collectionNameCache=${this.collectionNameCache}
414
+ .languageCodeHandler=${this.languageCodeHandler}
415
+ .selectedFacets=${this.selectedFacets}
416
+ >
417
+ </more-facets-content>
418
+ `;
419
+
420
+ const config = new ModalConfig({
421
+ bodyColor: '#fff',
422
+ headerColor: '#194880',
423
+ showHeaderLogo: false,
424
+ closeOnBackdropClick: true, // TODO: want to fire analytics
425
+ title: html`Select filters`,
426
+ headline,
427
+ message,
428
+ });
429
+ this.modalManager?.classList.add('more-search-facets');
430
+ this.modalManager?.showModal({ config });
431
+ }
432
+
330
433
  /**
331
434
  * Generate the list template for each bucket in a facet group
332
435
  */
@@ -605,6 +708,19 @@ export class CollectionFacets extends LitElement {
605
708
  .hide-facet-icon.active .eye {
606
709
  display: none;
607
710
  }
711
+
712
+ .more-link {
713
+ font-size: 1.2rem;
714
+ text-decoration: none;
715
+ padding: 0px 4px;
716
+ background: white;
717
+ border: 0;
718
+ color: blue;
719
+ cursor: pointer;
720
+ }
721
+ .sorting-icon {
722
+ cursor: pointer;
723
+ }
608
724
  `;
609
725
  }
610
726
  }
@@ -1,4 +1,4 @@
1
- import { SortDirection, SortParam } from '@internetarchive/search-service';
1
+ import type { SortDirection, SortParam } from '@internetarchive/search-service';
2
2
  import { getCookie, setCookie } from 'typescript-cookie';
3
3
  import {
4
4
  MetadataFieldToSortField,
@@ -7,7 +7,7 @@ import {
7
7
  TemplateResult,
8
8
  } from 'lit';
9
9
  import { customElement, property, query, state } from 'lit/decorators.js';
10
- import {
10
+ import type {
11
11
  SharedResizeObserverInterface,
12
12
  SharedResizeObserverResizeHandlerInterface,
13
13
  } from '@internetarchive/shared-resize-observer';
@@ -1,6 +1,6 @@
1
1
  import { css, html, LitElement } from 'lit';
2
2
  import { customElement, property } from 'lit/decorators.js';
3
- import { TileModel } from '../../models';
3
+ import type { TileModel } from '../../models';
4
4
 
5
5
  import './tile-stats';
6
6
 
@@ -2,7 +2,7 @@ import { msg } from '@lit/localize';
2
2
  import { css, CSSResultGroup, html, LitElement } from 'lit';
3
3
  import { customElement, property } from 'lit/decorators.js';
4
4
  import { collectionIcon } from '../../assets/img/icons/mediatype/collection';
5
- import { TileModel } from '../../models';
5
+ import type { TileModel } from '../../models';
6
6
 
7
7
  @customElement('collection-tile')
8
8
  export class CollectionTile extends LitElement {
@@ -2,10 +2,10 @@
2
2
  import { css, CSSResultGroup, html, LitElement, nothing } from 'lit';
3
3
  import { customElement, property } from 'lit/decorators.js';
4
4
  import { ifDefined } from 'lit/directives/if-defined.js';
5
- import { SortParam } from '@internetarchive/search-service';
5
+ import type { SortParam } from '@internetarchive/search-service';
6
6
 
7
7
  import { formatDate } from '../../utils/format-date';
8
- import { TileModel } from '../../models';
8
+ import type { TileModel } from '../../models';
9
9
 
10
10
  import '../image-block';
11
11
  import '../item-image';
@@ -2,7 +2,7 @@ import { css, CSSResultGroup, html, LitElement, nothing } from 'lit';
2
2
  import { customElement, property } from 'lit/decorators.js';
3
3
  import { ClassInfo, classMap } from 'lit/directives/class-map.js';
4
4
 
5
- import { TileModel } from '../models';
5
+ import type { TileModel } from '../models';
6
6
 
7
7
  import './overlay/icon-overlay';
8
8
  import './overlay/text-overlay';
@@ -2,7 +2,7 @@ import { css, CSSResultGroup, html, LitElement } from 'lit';
2
2
  import { customElement, property, query, state } from 'lit/decorators.js';
3
3
  import { ClassInfo, classMap } from 'lit/directives/class-map.js';
4
4
 
5
- import { TileModel } from '../models';
5
+ import type { TileModel } from '../models';
6
6
 
7
7
  import {
8
8
  baseItemImageStyles,
@@ -1,8 +1,8 @@
1
1
  import { css, html, LitElement } from 'lit';
2
2
  import { customElement, property } from 'lit/decorators.js';
3
- import { SortParam } from '@internetarchive/search-service';
3
+ import type { SortParam } from '@internetarchive/search-service';
4
4
  import { dateLabel } from './date-label';
5
- import { TileModel } from '../../models';
5
+ import type { TileModel } from '../../models';
6
6
 
7
7
  @customElement('tile-list-compact-header')
8
8
  export class TileListCompactHeader extends LitElement {
@@ -1,9 +1,9 @@
1
1
  import { css, html, LitElement } from 'lit';
2
2
  import { customElement, property } from 'lit/decorators.js';
3
- import { SortParam } from '@internetarchive/search-service';
4
3
  import DOMPurify from 'dompurify';
4
+ import type { SortParam } from '@internetarchive/search-service';
5
+ import type { TileModel } from '../../models';
5
6
 
6
- import { TileModel } from '../../models';
7
7
  import { formatCount, NumberFormat } from '../../utils/format-count';
8
8
  import { formatDate, DateFormat } from '../../utils/format-date';
9
9
  import { accountLabel } from './account-label';
@@ -10,14 +10,14 @@ import { ifDefined } from 'lit/directives/if-defined.js';
10
10
  import { join } from 'lit/directives/join.js';
11
11
  import { map } from 'lit/directives/map.js';
12
12
  import { customElement, property, state } from 'lit/decorators.js';
13
-
14
- import { CollectionNameCacheInterface } from '@internetarchive/collection-name-cache';
15
- import { SortParam } from '@internetarchive/search-service';
16
13
  import DOMPurify from 'dompurify';
17
14
 
15
+ import type { CollectionNameCacheInterface } from '@internetarchive/collection-name-cache';
16
+ import type { SortParam } from '@internetarchive/search-service';
17
+ import type { TileModel } from '../../models';
18
+
18
19
  import { dateLabel } from './date-label';
19
20
  import { accountLabel } from './account-label';
20
- import { TileModel } from '../../models';
21
21
  import { formatCount, NumberFormat } from '../../utils/format-count';
22
22
  import { formatDate, DateFormat } from '../../utils/format-date';
23
23
 
@@ -1,12 +1,12 @@
1
1
  import { css, html, LitElement, nothing, PropertyValues } from 'lit';
2
2
  import { customElement, property, query } from 'lit/decorators.js';
3
3
  import { ifDefined } from 'lit/directives/if-defined.js';
4
- import {
4
+ import type {
5
5
  SharedResizeObserverInterface,
6
6
  SharedResizeObserverResizeHandlerInterface,
7
7
  } from '@internetarchive/shared-resize-observer';
8
8
  import type { CollectionNameCacheInterface } from '@internetarchive/collection-name-cache';
9
- import { SortParam } from '@internetarchive/search-service';
9
+ import type { SortParam } from '@internetarchive/search-service';
10
10
  import type { TileDisplayMode, TileModel } from '../models';
11
11
  import './grid/collection-tile';
12
12
  import './grid/item-tile';
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable import/no-duplicates */
2
2
  import { expect, fixture } from '@open-wc/testing';
3
3
  import { html } from 'lit';
4
- import { CollectionBrowser } from '../src/collection-browser';
4
+ import type { CollectionBrowser } from '../src/collection-browser';
5
5
  import '../src/collection-browser';
6
6
  import { MockSearchService } from './mocks/mock-search-service';
7
7
  import { MockCollectionNameCache } from './mocks/mock-collection-name-cache';
@@ -0,0 +1,113 @@
1
+ /* eslint-disable import/no-duplicates */
2
+ import { expect, fixture, oneEvent } from '@open-wc/testing';
3
+ import { html } from 'lit';
4
+ import type { MoreFacetsContent } from '../../src/collection-facets/more-facets-content';
5
+ import '../../src/collection-facets/more-facets-content';
6
+ import { MockSearchService } from '../mocks/mock-search-service';
7
+
8
+ describe('More facets content', () => {
9
+ it('should render more facets template', async () => {
10
+ const el = await fixture<MoreFacetsContent>(
11
+ html`<more-facets-content></more-facets-content>`
12
+ );
13
+
14
+ el.facetsLoading = false;
15
+ await el.updateComplete;
16
+
17
+ expect(el.shadowRoot?.querySelector('.facets-content')).to.exist;
18
+ });
19
+
20
+ it('should render more facets loader template', async () => {
21
+ const el = await fixture<MoreFacetsContent>(
22
+ html`<more-facets-content></more-facets-content>`
23
+ );
24
+
25
+ el.facetsLoading = true;
26
+ await el.updateComplete;
27
+
28
+ expect(el.shadowRoot?.querySelector('.facets-loader')).to.exist;
29
+ });
30
+
31
+ it('should render more facets empty template', async () => {
32
+ const el = await fixture<MoreFacetsContent>(
33
+ html`<more-facets-content></more-facets-content>`
34
+ );
35
+
36
+ el.facetsLoading = false;
37
+ el.paginationSize = 0;
38
+ await el.updateComplete;
39
+
40
+ expect(
41
+ el.shadowRoot?.querySelector('#more-facets-page')?.textContent
42
+ ).to.contains('No result found. please try again later.');
43
+ });
44
+
45
+ it('should render pagination for more facets', async () => {
46
+ const searchService = new MockSearchService();
47
+
48
+ const el = await fixture<MoreFacetsContent>(
49
+ html`<more-facets-content
50
+ .searchService=${searchService}
51
+ ></more-facets-content>`
52
+ );
53
+
54
+ el.facetKey = 'mediatype';
55
+ el.facetsLoading = false;
56
+ el.paginationSize = 6;
57
+ await el.updateComplete;
58
+
59
+ expect(el.shadowRoot?.querySelectorAll('more-facets-pagination')).to.exist;
60
+ });
61
+
62
+ it('query for more facets content using search service', async () => {
63
+ const searchService = new MockSearchService();
64
+
65
+ const el = await fixture<MoreFacetsContent>(
66
+ html`<more-facets-content
67
+ .searchService=${searchService}
68
+ ></more-facets-content>`
69
+ );
70
+
71
+ el.facetKey = 'collection';
72
+ el.fullQuery = 'title:hello';
73
+ await el.updateComplete;
74
+
75
+ expect(searchService.searchParams?.query).to.equal('title:hello');
76
+ });
77
+
78
+ it('query for specific facets data', async () => {
79
+ const searchService = new MockSearchService();
80
+
81
+ const el = await fixture<MoreFacetsContent>(
82
+ html`<more-facets-content
83
+ .searchService=${searchService}
84
+ ></more-facets-content>`
85
+ );
86
+
87
+ el.facetKey = 'language';
88
+ el.facetsLoading = false;
89
+ await el.updateComplete;
90
+
91
+ expect(el.paginationSize).to.equal(1);
92
+ expect(el.shadowRoot?.querySelector('.facet-list')).to.exist;
93
+ expect(Object.keys(el.castedBuckets as []).length).to.equal(7);
94
+ });
95
+
96
+ it('page number clicked event', async () => {
97
+ const searchService = new MockSearchService();
98
+
99
+ const el = await fixture<MoreFacetsContent>(
100
+ html`<more-facets-content
101
+ .searchService=${searchService}
102
+ ></more-facets-content>`
103
+ );
104
+
105
+ setTimeout(() =>
106
+ el.dispatchEvent(
107
+ new CustomEvent('pageNumberClicked', { detail: { page: 15 } })
108
+ )
109
+ );
110
+ const { detail } = await oneEvent(el, 'pageNumberClicked');
111
+ expect(detail?.page).to.equal(15);
112
+ });
113
+ });