@internetarchive/collection-browser 0.4.9 → 0.4.10-alpha.2

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 (243) hide show
  1. package/.editorconfig +29 -29
  2. package/.github/workflows/ci.yml +26 -26
  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/LICENSE +661 -661
  8. package/README.md +83 -83
  9. package/dist/index.d.ts +9 -9
  10. package/dist/index.js +9 -9
  11. package/dist/src/app-root.d.ts +50 -50
  12. package/dist/src/app-root.js +278 -278
  13. package/dist/src/assets/img/icons/arrow-left.d.ts +2 -2
  14. package/dist/src/assets/img/icons/arrow-left.js +2 -2
  15. package/dist/src/assets/img/icons/arrow-right.d.ts +2 -2
  16. package/dist/src/assets/img/icons/arrow-right.js +2 -2
  17. package/dist/src/assets/img/icons/chevron.d.ts +2 -2
  18. package/dist/src/assets/img/icons/chevron.js +2 -2
  19. package/dist/src/assets/img/icons/empty-query.d.ts +2 -2
  20. package/dist/src/assets/img/icons/empty-query.js +2 -2
  21. package/dist/src/assets/img/icons/eye-closed.d.ts +2 -2
  22. package/dist/src/assets/img/icons/eye-closed.js +2 -2
  23. package/dist/src/assets/img/icons/eye.d.ts +2 -2
  24. package/dist/src/assets/img/icons/eye.js +2 -2
  25. package/dist/src/assets/img/icons/favorite-filled.d.ts +1 -1
  26. package/dist/src/assets/img/icons/favorite-filled.js +2 -2
  27. package/dist/src/assets/img/icons/login-required.d.ts +1 -1
  28. package/dist/src/assets/img/icons/login-required.js +2 -2
  29. package/dist/src/assets/img/icons/mediatype/account.d.ts +1 -1
  30. package/dist/src/assets/img/icons/mediatype/account.js +2 -2
  31. package/dist/src/assets/img/icons/mediatype/audio.d.ts +1 -1
  32. package/dist/src/assets/img/icons/mediatype/audio.js +2 -2
  33. package/dist/src/assets/img/icons/mediatype/collection.d.ts +1 -1
  34. package/dist/src/assets/img/icons/mediatype/collection.js +2 -2
  35. package/dist/src/assets/img/icons/mediatype/data.d.ts +1 -1
  36. package/dist/src/assets/img/icons/mediatype/data.js +2 -2
  37. package/dist/src/assets/img/icons/mediatype/etree.d.ts +1 -1
  38. package/dist/src/assets/img/icons/mediatype/etree.js +2 -2
  39. package/dist/src/assets/img/icons/mediatype/film.d.ts +1 -1
  40. package/dist/src/assets/img/icons/mediatype/film.js +2 -2
  41. package/dist/src/assets/img/icons/mediatype/images.d.ts +1 -1
  42. package/dist/src/assets/img/icons/mediatype/images.js +2 -2
  43. package/dist/src/assets/img/icons/mediatype/radio.d.ts +1 -1
  44. package/dist/src/assets/img/icons/mediatype/radio.js +2 -2
  45. package/dist/src/assets/img/icons/mediatype/software.d.ts +1 -1
  46. package/dist/src/assets/img/icons/mediatype/software.js +2 -2
  47. package/dist/src/assets/img/icons/mediatype/texts.d.ts +1 -1
  48. package/dist/src/assets/img/icons/mediatype/texts.js +2 -2
  49. package/dist/src/assets/img/icons/mediatype/tv.d.ts +1 -1
  50. package/dist/src/assets/img/icons/mediatype/tv.js +2 -2
  51. package/dist/src/assets/img/icons/mediatype/video.d.ts +1 -1
  52. package/dist/src/assets/img/icons/mediatype/video.js +2 -2
  53. package/dist/src/assets/img/icons/mediatype/web.d.ts +1 -1
  54. package/dist/src/assets/img/icons/mediatype/web.js +2 -2
  55. package/dist/src/assets/img/icons/null-result.d.ts +2 -2
  56. package/dist/src/assets/img/icons/null-result.js +2 -2
  57. package/dist/src/assets/img/icons/restricted.d.ts +1 -1
  58. package/dist/src/assets/img/icons/restricted.js +2 -2
  59. package/dist/src/assets/img/icons/reviews.d.ts +1 -1
  60. package/dist/src/assets/img/icons/reviews.js +2 -2
  61. package/dist/src/assets/img/icons/upload.d.ts +1 -1
  62. package/dist/src/assets/img/icons/upload.js +2 -2
  63. package/dist/src/assets/img/icons/views.d.ts +1 -1
  64. package/dist/src/assets/img/icons/views.js +2 -2
  65. package/dist/src/circular-activity-indicator.d.ts +5 -5
  66. package/dist/src/circular-activity-indicator.js +17 -17
  67. package/dist/src/collection-browser.d.ts +279 -281
  68. package/dist/src/collection-browser.js +1156 -1202
  69. package/dist/src/collection-browser.js.map +1 -1
  70. package/dist/src/collection-facets/facet-tombstone-row.d.ts +5 -5
  71. package/dist/src/collection-facets/facet-tombstone-row.js +15 -15
  72. package/dist/src/collection-facets/facets-template.d.ts +16 -16
  73. package/dist/src/collection-facets/facets-template.js +125 -125
  74. package/dist/src/collection-facets/more-facets-content.d.ts +75 -77
  75. package/dist/src/collection-facets/more-facets-content.js +340 -357
  76. package/dist/src/collection-facets/more-facets-content.js.map +1 -1
  77. package/dist/src/collection-facets/more-facets-pagination.d.ts +36 -36
  78. package/dist/src/collection-facets/more-facets-pagination.js +192 -192
  79. package/dist/src/collection-facets.d.ts +81 -83
  80. package/dist/src/collection-facets.js +375 -393
  81. package/dist/src/collection-facets.js.map +1 -1
  82. package/dist/src/empty-placeholder.d.ts +11 -11
  83. package/dist/src/empty-placeholder.js +42 -42
  84. package/dist/src/language-code-handler/language-code-handler.d.ts +37 -37
  85. package/dist/src/language-code-handler/language-code-handler.js +26 -26
  86. package/dist/src/language-code-handler/language-code-mapping.d.ts +1 -1
  87. package/dist/src/language-code-handler/language-code-mapping.js +562 -562
  88. package/dist/src/mediatype/mediatype-config.d.ts +3 -3
  89. package/dist/src/mediatype/mediatype-config.js +85 -85
  90. package/dist/src/models.d.ts +115 -115
  91. package/dist/src/models.js +125 -125
  92. package/dist/src/models.js.map +1 -1
  93. package/dist/src/restoration-state-handler.d.ts +45 -45
  94. package/dist/src/restoration-state-handler.js +230 -230
  95. package/dist/src/sort-filter-bar/alpha-bar-tooltip.d.ts +6 -6
  96. package/dist/src/sort-filter-bar/alpha-bar-tooltip.js +24 -24
  97. package/dist/src/sort-filter-bar/alpha-bar.d.ts +20 -20
  98. package/dist/src/sort-filter-bar/alpha-bar.js +128 -128
  99. package/dist/src/sort-filter-bar/img/compact.d.ts +1 -1
  100. package/dist/src/sort-filter-bar/img/compact.js +2 -2
  101. package/dist/src/sort-filter-bar/img/list.d.ts +1 -1
  102. package/dist/src/sort-filter-bar/img/list.js +2 -2
  103. package/dist/src/sort-filter-bar/img/sort-triangle.d.ts +1 -1
  104. package/dist/src/sort-filter-bar/img/sort-triangle.js +2 -2
  105. package/dist/src/sort-filter-bar/img/tile.d.ts +1 -1
  106. package/dist/src/sort-filter-bar/img/tile.js +2 -2
  107. package/dist/src/sort-filter-bar/sort-filter-bar.d.ts +113 -108
  108. package/dist/src/sort-filter-bar/sort-filter-bar.js +614 -548
  109. package/dist/src/sort-filter-bar/sort-filter-bar.js.map +1 -1
  110. package/dist/src/styles/item-image-styles.d.ts +8 -8
  111. package/dist/src/styles/item-image-styles.js +9 -9
  112. package/dist/src/tiles/collection-browser-loading-tile.d.ts +5 -5
  113. package/dist/src/tiles/collection-browser-loading-tile.js +15 -15
  114. package/dist/src/tiles/grid/account-tile.d.ts +20 -20
  115. package/dist/src/tiles/grid/account-tile.js +64 -64
  116. package/dist/src/tiles/grid/collection-tile.d.ts +17 -17
  117. package/dist/src/tiles/grid/collection-tile.js +71 -71
  118. package/dist/src/tiles/grid/item-tile.d.ts +32 -32
  119. package/dist/src/tiles/grid/item-tile.js +129 -126
  120. package/dist/src/tiles/grid/item-tile.js.map +1 -1
  121. package/dist/src/tiles/grid/styles/tile-grid-shared-styles.d.ts +1 -1
  122. package/dist/src/tiles/grid/styles/tile-grid-shared-styles.js +7 -7
  123. package/dist/src/tiles/grid/tile-stats.d.ts +10 -10
  124. package/dist/src/tiles/grid/tile-stats.js +40 -40
  125. package/dist/src/tiles/hover/hover-pane-controller.d.ts +219 -219
  126. package/dist/src/tiles/hover/hover-pane-controller.js +352 -352
  127. package/dist/src/tiles/hover/tile-hover-pane.d.ts +15 -15
  128. package/dist/src/tiles/hover/tile-hover-pane.js +38 -38
  129. package/dist/src/tiles/image-block.d.ts +17 -17
  130. package/dist/src/tiles/image-block.js +72 -72
  131. package/dist/src/tiles/item-image.d.ts +35 -35
  132. package/dist/src/tiles/item-image.js +117 -117
  133. package/dist/src/tiles/list/account-label.d.ts +1 -1
  134. package/dist/src/tiles/list/account-label.js +6 -6
  135. package/dist/src/tiles/list/date-label.d.ts +1 -1
  136. package/dist/src/tiles/list/date-label.js +12 -12
  137. package/dist/src/tiles/list/tile-list-compact-header.d.ts +12 -12
  138. package/dist/src/tiles/list/tile-list-compact-header.js +41 -41
  139. package/dist/src/tiles/list/tile-list-compact.d.ts +21 -21
  140. package/dist/src/tiles/list/tile-list-compact.js +99 -99
  141. package/dist/src/tiles/list/tile-list.d.ts +55 -55
  142. package/dist/src/tiles/list/tile-list.js +301 -301
  143. package/dist/src/tiles/mediatype-icon.d.ts +9 -9
  144. package/dist/src/tiles/mediatype-icon.js +47 -47
  145. package/dist/src/tiles/overlay/icon-overlay.d.ts +10 -10
  146. package/dist/src/tiles/overlay/icon-overlay.js +40 -40
  147. package/dist/src/tiles/overlay/icon-text-overlay.d.ts +9 -9
  148. package/dist/src/tiles/overlay/icon-text-overlay.js +38 -38
  149. package/dist/src/tiles/overlay/text-overlay.d.ts +10 -10
  150. package/dist/src/tiles/overlay/text-overlay.js +42 -42
  151. package/dist/src/tiles/text-snippet-block.d.ts +27 -27
  152. package/dist/src/tiles/text-snippet-block.js +73 -73
  153. package/dist/src/tiles/tile-dispatcher.d.ts +58 -58
  154. package/dist/src/tiles/tile-dispatcher.js +194 -194
  155. package/dist/src/utils/analytics-events.d.ts +22 -22
  156. package/dist/src/utils/analytics-events.js +24 -24
  157. package/dist/src/utils/format-count.d.ts +7 -7
  158. package/dist/src/utils/format-count.js +76 -76
  159. package/dist/src/utils/format-date.d.ts +2 -2
  160. package/dist/src/utils/format-date.js +23 -23
  161. package/dist/src/utils/format-unit-size.d.ts +2 -2
  162. package/dist/src/utils/format-unit-size.js +33 -33
  163. package/dist/test/collection-browser.test.d.ts +1 -1
  164. package/dist/test/collection-browser.test.js +584 -584
  165. package/dist/test/collection-facets/facets-template.test.d.ts +1 -1
  166. package/dist/test/collection-facets/facets-template.test.js +62 -62
  167. package/dist/test/collection-facets/more-facets-content.test.d.ts +1 -1
  168. package/dist/test/collection-facets/more-facets-content.test.js +114 -114
  169. package/dist/test/collection-facets/more-facets-pagination.test.d.ts +1 -1
  170. package/dist/test/collection-facets/more-facets-pagination.test.js +117 -117
  171. package/dist/test/collection-facets.test.d.ts +2 -2
  172. package/dist/test/collection-facets.test.js +460 -508
  173. package/dist/test/collection-facets.test.js.map +1 -1
  174. package/dist/test/empty-placeholder.test.d.ts +1 -1
  175. package/dist/test/empty-placeholder.test.js +33 -33
  176. package/dist/test/icon-overlay.test.d.ts +1 -1
  177. package/dist/test/icon-overlay.test.js +24 -24
  178. package/dist/test/image-block.test.d.ts +1 -1
  179. package/dist/test/image-block.test.js +48 -48
  180. package/dist/test/item-image.test.d.ts +1 -1
  181. package/dist/test/item-image.test.js +84 -84
  182. package/dist/test/mediatype-config.test.d.ts +1 -1
  183. package/dist/test/mediatype-config.test.js +16 -16
  184. package/dist/test/mocks/mock-analytics-handler.d.ts +10 -10
  185. package/dist/test/mocks/mock-analytics-handler.js +15 -15
  186. package/dist/test/mocks/mock-collection-name-cache.d.ts +7 -7
  187. package/dist/test/mocks/mock-collection-name-cache.js +13 -13
  188. package/dist/test/mocks/mock-search-responses.d.ts +12 -12
  189. package/dist/test/mocks/mock-search-responses.js +341 -341
  190. package/dist/test/mocks/mock-search-service.d.ts +13 -13
  191. package/dist/test/mocks/mock-search-service.js +40 -40
  192. package/dist/test/restoration-state-handler.test.d.ts +1 -1
  193. package/dist/test/restoration-state-handler.test.js +125 -125
  194. package/dist/test/sort-filter-bar/alpha-bar-tooltip.test.d.ts +1 -1
  195. package/dist/test/sort-filter-bar/alpha-bar-tooltip.test.js +12 -12
  196. package/dist/test/sort-filter-bar/alpha-bar.test.d.ts +1 -1
  197. package/dist/test/sort-filter-bar/alpha-bar.test.js +73 -73
  198. package/dist/test/sort-filter-bar/sort-filter-bar.test.d.ts +1 -1
  199. package/dist/test/sort-filter-bar/sort-filter-bar.test.js +208 -197
  200. package/dist/test/sort-filter-bar/sort-filter-bar.test.js.map +1 -1
  201. package/dist/test/text-overlay.test.d.ts +1 -1
  202. package/dist/test/text-overlay.test.js +48 -48
  203. package/dist/test/text-snippet-block.test.d.ts +1 -1
  204. package/dist/test/text-snippet-block.test.js +57 -57
  205. package/dist/test/tile-stats.test.d.ts +1 -1
  206. package/dist/test/tile-stats.test.js +33 -33
  207. package/dist/test/tiles/grid/account-tile.test.d.ts +1 -1
  208. package/dist/test/tiles/grid/account-tile.test.js +76 -76
  209. package/dist/test/tiles/grid/collection-tile.test.d.ts +1 -1
  210. package/dist/test/tiles/grid/collection-tile.test.js +73 -73
  211. package/dist/test/tiles/grid/item-tile.test.d.ts +1 -1
  212. package/dist/test/tiles/grid/item-tile.test.js +158 -158
  213. package/dist/test/tiles/hover/hover-pane-controller.test.d.ts +1 -1
  214. package/dist/test/tiles/hover/hover-pane-controller.test.js +257 -257
  215. package/dist/test/tiles/hover/tile-hover-pane.test.d.ts +1 -1
  216. package/dist/test/tiles/hover/tile-hover-pane.test.js +13 -13
  217. package/dist/test/tiles/list/tile-list-compact.test.d.ts +1 -1
  218. package/dist/test/tiles/list/tile-list-compact.test.js +92 -92
  219. package/dist/test/tiles/list/tile-list.test.d.ts +1 -1
  220. package/dist/test/tiles/list/tile-list.test.js +163 -163
  221. package/dist/test/tiles/tile-dispatcher.test.d.ts +1 -1
  222. package/dist/test/tiles/tile-dispatcher.test.js +67 -67
  223. package/dist/test/utils/format-count.test.d.ts +1 -1
  224. package/dist/test/utils/format-count.test.js +23 -23
  225. package/dist/test/utils/format-date.test.d.ts +1 -1
  226. package/dist/test/utils/format-date.test.js +17 -17
  227. package/dist/test/utils/format-unit-size.test.d.ts +1 -1
  228. package/dist/test/utils/format-unit-size.test.js +17 -17
  229. package/local.archive.org.cert +86 -86
  230. package/local.archive.org.key +27 -27
  231. package/package.json +4 -3
  232. package/renovate.json +6 -6
  233. package/src/collection-browser.ts +2 -61
  234. package/src/collection-facets/more-facets-content.ts +2 -22
  235. package/src/collection-facets.ts +1 -24
  236. package/src/models.ts +6 -6
  237. package/src/sort-filter-bar/sort-filter-bar.ts +283 -197
  238. package/src/tiles/grid/item-tile.ts +5 -1
  239. package/test/collection-facets.test.ts +0 -67
  240. package/test/sort-filter-bar/sort-filter-bar.test.ts +56 -39
  241. package/tsconfig.json +21 -21
  242. package/web-dev-server.config.mjs +30 -30
  243. package/web-test-runner.config.mjs +41 -41
@@ -11,6 +11,12 @@ import type {
11
11
  SharedResizeObserverInterface,
12
12
  SharedResizeObserverResizeHandlerInterface,
13
13
  } from '@internetarchive/shared-resize-observer';
14
+ import '@internetarchive/ia-dropdown';
15
+ import type {
16
+ IaDropdown,
17
+ optionInterface,
18
+ } from '@internetarchive/ia-dropdown/dist/src/ia-dropdown';
19
+ import type { SortDirection } from '@internetarchive/search-service';
14
20
  import {
15
21
  CollectionDisplayMode,
16
22
  PrefixFilterCounts,
@@ -57,26 +63,28 @@ export class SortFilterBar
57
63
 
58
64
  @state() viewSortSelectorVisible = false;
59
65
 
60
- @state() desktopSelectorBarWidth = 0;
66
+ @state() desktopSortContainerWidth = 0;
61
67
 
62
68
  @state() selectorBarContainerWidth = 0;
63
69
 
64
70
  @state() hoveringOverDateSortOptions = false;
65
71
 
66
- @query('#desktop-sort-selector')
67
- private desktopSortSelector!: HTMLUListElement;
72
+ @query('#desktop-sort-container')
73
+ private desktopSortContainer!: HTMLUListElement;
68
74
 
69
75
  @query('#sort-selector-container')
70
76
  private sortSelectorContainer!: HTMLDivElement;
71
77
 
78
+ @query('#views-dropdown')
79
+ private viewsDropdown!: IaDropdown;
80
+
81
+ @query('#date-dropdown')
82
+ private dateDropdown!: IaDropdown;
83
+
72
84
  render() {
73
85
  return html`
74
86
  <div id="container">
75
87
  <div id="sort-bar">
76
- <div id="sort-direction-container">
77
- ${this.sortDirectionSelectorTemplate}
78
- </div>
79
-
80
88
  <div id="sort-selector-container">
81
89
  ${this.mobileSortSelectorTemplate}
82
90
  ${this.desktopSortSelectorTemplate}
@@ -86,14 +94,12 @@ export class SortFilterBar
86
94
  </div>
87
95
 
88
96
  ${this.viewSortSelectorVisible && !this.mobileSelectorVisible
89
- ? this.viewSortSelector
97
+ ? this.dropdownBackdrop
90
98
  : nothing}
91
99
  ${this.dateSortSelectorVisible && !this.mobileSelectorVisible
92
- ? this.dateSortSelector
100
+ ? this.dropdownBackdrop
93
101
  : nothing}
94
102
  ${this.alphaBarTemplate}
95
-
96
- <div id="bottom-shadow"></div>
97
103
  </div>
98
104
  `;
99
105
  }
@@ -167,7 +173,7 @@ export class SortFilterBar
167
173
  });
168
174
 
169
175
  resizeObserver.removeObserver({
170
- target: this.desktopSortSelector,
176
+ target: this.desktopSortContainer,
171
177
  handler: this,
172
178
  });
173
179
  }
@@ -180,13 +186,13 @@ export class SortFilterBar
180
186
  });
181
187
 
182
188
  this.resizeObserver.addObserver({
183
- target: this.desktopSortSelector,
189
+ target: this.desktopSortContainer,
184
190
  handler: this,
185
191
  });
186
192
  }
187
193
 
188
194
  private get mobileSelectorVisible() {
189
- return this.selectorBarContainerWidth - 10 < this.desktopSelectorBarWidth;
195
+ return this.selectorBarContainerWidth - 10 < this.desktopSortContainerWidth;
190
196
  }
191
197
 
192
198
  private get alphaBarTemplate(): TemplateResult | typeof nothing {
@@ -205,8 +211,8 @@ export class SortFilterBar
205
211
  }
206
212
 
207
213
  handleResize(entry: ResizeObserverEntry): void {
208
- if (entry.target === this.desktopSortSelector) {
209
- this.desktopSelectorBarWidth = entry.contentRect.width;
214
+ if (entry.target === this.desktopSortContainer) {
215
+ this.desktopSortContainerWidth = entry.contentRect.width;
210
216
  } else if (entry.target === this.sortSelectorContainer) {
211
217
  this.selectorBarContainerWidth = entry.contentRect.width;
212
218
  }
@@ -214,101 +220,130 @@ export class SortFilterBar
214
220
 
215
221
  private get sortDirectionSelectorTemplate() {
216
222
  return html`
217
- <div id="sort-direction-selector">
218
- <button
223
+ <button
224
+ id="sort-direction-selector"
225
+ ?disabled=${this.selectedSort === 'relevance'}
226
+ @click=${this.toggleSortDirection}
227
+ >
228
+ <div
219
229
  id="sort-ascending-btn"
220
230
  class="sort-button ${this.sortDirection === 'asc' ? 'selected' : ''}"
221
- ?disabled=${this.selectedSort === 'relevance'}
222
- @click=${() => {
223
- this.setSortDirections('asc');
224
- }}
225
231
  >
226
232
  ${sortIcon}
227
- </button>
228
- <button
233
+ </div>
234
+ <div
229
235
  id="sort-descending-btn"
230
236
  class="sort-button ${this.sortDirection === 'desc' ? 'selected' : ''}"
231
- ?disabled=${this.selectedSort === 'relevance'}
232
- @click=${() => {
233
- this.setSortDirections('desc');
234
- }}
235
237
  >
236
238
  ${sortIcon}
237
- </button>
238
- </div>
239
+ </div>
240
+ </button>
239
241
  `;
240
242
  }
241
243
 
242
244
  private get desktopSortSelectorTemplate() {
243
245
  return html`
244
- <ul
245
- id="desktop-sort-selector"
246
+ <div
247
+ id="desktop-sort-container"
246
248
  class=${this.mobileSelectorVisible ? 'hidden' : 'visible'}
247
249
  >
248
- <li id="sort-by-text">Sort By</li>
249
- <li>
250
- ${this.showRelevance
251
- ? this.getSortDisplayOption(SortField.relevance)
252
- : nothing}
253
- </li>
254
- <li>
255
- ${this.getSortDisplayOption(SortField.weeklyview, {
256
- clickEvent: () => {
257
- if (!this.viewOptionSelected)
258
- this.setSelectedSort(SortField.weeklyview);
259
- this.viewSortSelectorVisible = !this.viewSortSelectorVisible;
260
- this.dateSortSelectorVisible = false;
261
- this.alphaSelectorVisible = null;
262
- this.selectedTitleFilter = null;
263
- this.selectedCreatorFilter = null;
264
- this.emitTitleLetterChangedEvent();
265
- this.emitCreatorLetterChangedEvent();
266
- },
267
- displayName: html`${this.viewSortField}`,
268
- isSelected: () => this.viewOptionSelected,
269
- })}
270
- </li>
271
- <li>
272
- ${this.getSortDisplayOption(SortField.title, {
273
- clickEvent: () => {
274
- this.alphaSelectorVisible = 'title';
275
- this.selectedCreatorFilter = null;
276
- this.dateSortSelectorVisible = false;
277
- this.viewSortSelectorVisible = false;
278
- this.setSelectedSort(SortField.title);
279
- this.emitCreatorLetterChangedEvent();
280
- },
281
- })}
282
- </li>
283
- <li>
284
- ${this.getSortDisplayOption(SortField.date, {
285
- clickEvent: () => {
286
- if (!this.dateOptionSelected)
287
- this.setSelectedSort(SortField.date);
288
- this.dateSortSelectorVisible = !this.dateSortSelectorVisible;
289
- this.viewSortSelectorVisible = false;
290
- this.alphaSelectorVisible = null;
291
- this.selectedTitleFilter = null;
292
- this.selectedCreatorFilter = null;
293
- this.emitTitleLetterChangedEvent();
294
- this.emitCreatorLetterChangedEvent();
295
- },
296
- displayName: html`${this.dateSortField}`,
297
- isSelected: () => this.dateOptionSelected,
298
- })}
299
- </li>
300
- <li>
301
- ${this.getSortDisplayOption(SortField.creator, {
302
- clickEvent: () => {
303
- this.alphaSelectorVisible = 'creator';
304
- this.selectedTitleFilter = null;
305
- this.dateSortSelectorVisible = false;
306
- this.setSelectedSort(SortField.creator);
307
- this.emitTitleLetterChangedEvent();
308
- },
309
- })}
310
- </li>
311
- </ul>
250
+ <span id="sort-by-text">Sort by</span>
251
+ <div id="sort-direction-container">
252
+ ${this.sortDirectionSelectorTemplate}
253
+ </div>
254
+ <ul id="desktop-sort-selector">
255
+ <li>
256
+ ${this.showRelevance
257
+ ? this.getSortDisplayOption(SortField.relevance)
258
+ : nothing}
259
+ </li>
260
+ <li>
261
+ ${this.getSortDropdown({
262
+ optionSelectedHandler: () => {
263
+ this.dateSortSelectorVisible = false;
264
+ this.alphaSelectorVisible = null;
265
+ this.selectedTitleFilter = null;
266
+ this.selectedCreatorFilter = null;
267
+ this.emitTitleLetterChangedEvent();
268
+ this.emitCreatorLetterChangedEvent();
269
+ },
270
+ clickHandler: () => {
271
+ if (!this.viewsDropdown.open && !this.viewOptionSelected)
272
+ this.setSelectedSort(SortField.weeklyview);
273
+ this.dateDropdown.open = false;
274
+ this.viewSortSelectorVisible = this.viewsDropdown.open;
275
+ this.viewsDropdown.classList.toggle(
276
+ 'open',
277
+ this.viewsDropdown.open
278
+ );
279
+ },
280
+ displayName: html`${this.viewSortField}`,
281
+ id: 'views-dropdown',
282
+ isSelected: () => this.viewOptionSelected,
283
+ dropdownOptions: [
284
+ this.getDropdownOption(SortField.weeklyview),
285
+ this.getDropdownOption(SortField.alltimeview),
286
+ ],
287
+ selectedOption: this.viewOptionSelected ? this.selectedSort : '',
288
+ })}
289
+ </li>
290
+ <li>
291
+ ${this.getSortDisplayOption(SortField.title, {
292
+ clickEvent: () => {
293
+ this.alphaSelectorVisible = 'title';
294
+ this.selectedCreatorFilter = null;
295
+ this.dateSortSelectorVisible = false;
296
+ this.viewSortSelectorVisible = false;
297
+ this.setSelectedSort(SortField.title);
298
+ this.emitCreatorLetterChangedEvent();
299
+ },
300
+ })}
301
+ </li>
302
+ <li>
303
+ ${this.getSortDropdown({
304
+ optionSelectedHandler: () => {
305
+ this.viewSortSelectorVisible = false;
306
+ this.alphaSelectorVisible = null;
307
+ this.selectedTitleFilter = null;
308
+ this.selectedCreatorFilter = null;
309
+ this.emitTitleLetterChangedEvent();
310
+ this.emitCreatorLetterChangedEvent();
311
+ },
312
+ clickHandler: () => {
313
+ if (!this.dateDropdown.open && !this.dateOptionSelected)
314
+ this.setSelectedSort(SortField.date);
315
+ this.viewsDropdown.open = false;
316
+ this.dateSortSelectorVisible = this.dateDropdown.open;
317
+ this.dateDropdown.classList.toggle(
318
+ 'open',
319
+ this.dateDropdown.open
320
+ );
321
+ },
322
+ displayName: html`${this.dateSortField}`,
323
+ id: 'date-dropdown',
324
+ isSelected: () => this.dateOptionSelected,
325
+ dropdownOptions: [
326
+ this.getDropdownOption(SortField.date),
327
+ this.getDropdownOption(SortField.datearchived),
328
+ this.getDropdownOption(SortField.datereviewed),
329
+ this.getDropdownOption(SortField.dateadded),
330
+ ],
331
+ selectedOption: this.dateOptionSelected ? this.selectedSort : '',
332
+ })}
333
+ </li>
334
+ <li>
335
+ ${this.getSortDisplayOption(SortField.creator, {
336
+ clickEvent: () => {
337
+ this.alphaSelectorVisible = 'creator';
338
+ this.selectedTitleFilter = null;
339
+ this.dateSortSelectorVisible = false;
340
+ this.setSelectedSort(SortField.creator);
341
+ this.emitTitleLetterChangedEvent();
342
+ },
343
+ })}
344
+ </li>
345
+ </ul>
346
+ </div>
312
347
  `;
313
348
  }
314
349
 
@@ -353,28 +388,76 @@ export class SortFilterBar
353
388
  this.emitCreatorLetterChangedEvent();
354
389
  }
355
390
  }}
356
- class=${isSelected() ? 'selected' : ''}
391
+ class=${isSelected() ? 'selected' : nothing}
357
392
  >
358
393
  ${displayName}
359
394
  </a>
360
395
  `;
361
396
  }
362
397
 
398
+ private getSortDropdown(options?: {
399
+ optionSelectedHandler?: (e: Event) => void;
400
+ clickHandler?: (e: PointerEvent) => void;
401
+ isSelected?: () => boolean;
402
+ displayName?: TemplateResult;
403
+ id?: string;
404
+ dropdownOptions?: optionInterface[];
405
+ selectedOption?: string;
406
+ }): TemplateResult {
407
+ return html`
408
+ <ia-dropdown
409
+ id=${options?.id ?? nothing}
410
+ class=${options?.isSelected?.() ? 'selected' : nothing}
411
+ displayCaret
412
+ closeOnSelect
413
+ includeSelectedOption
414
+ .openViaButton=${false}
415
+ .options=${options?.dropdownOptions}
416
+ .selectedOption=${options?.selectedOption}
417
+ @optionSelected=${options?.optionSelectedHandler ?? nothing}
418
+ @click=${options?.clickHandler ?? nothing}
419
+ >
420
+ <span class="dropdown-label" slot="dropdown-label">
421
+ ${options?.displayName ?? ''}
422
+ </span>
423
+ </ia-dropdown>
424
+ `;
425
+ }
426
+
427
+ private getDropdownOption(sortField: SortField): optionInterface {
428
+ return {
429
+ id: sortField,
430
+ selectedHandler: () => {
431
+ this.selectDropdownSortField(sortField);
432
+ },
433
+ label: html`
434
+ <span class="dropdown-option-label">
435
+ ${SortFieldDisplayName[sortField]}
436
+ </span>
437
+ `,
438
+ };
439
+ }
440
+
363
441
  private get mobileSortSelectorTemplate() {
364
442
  return html`
365
- <select
366
- id="mobile-sort-selector"
367
- @change=${this.mobileSortChanged}
443
+ <div
444
+ id="mobile-sort-container"
368
445
  class=${this.mobileSelectorVisible ? 'visible' : 'hidden'}
369
446
  >
370
- ${Object.keys(SortField).map(
371
- field => html`
372
- <option value="${field}" ?selected=${this.selectedSort === field}>
373
- ${SortFieldDisplayName[field as SortField]}
374
- </option>
375
- `
376
- )}
377
- </select>
447
+ <span id="sort-by-text">Sort by</span>
448
+ <div id="sort-direction-container">
449
+ ${this.sortDirectionSelectorTemplate}
450
+ </div>
451
+ <select id="mobile-sort-selector" @change=${this.mobileSortChanged}>
452
+ ${Object.keys(SortField).map(
453
+ field => html`
454
+ <option value="${field}" ?selected=${this.selectedSort === field}>
455
+ ${SortFieldDisplayName[field as SortField]}
456
+ </option>
457
+ `
458
+ )}
459
+ </select>
460
+ </div>
378
461
  `;
379
462
  }
380
463
 
@@ -437,72 +520,38 @@ export class SortFilterBar
437
520
  `;
438
521
  }
439
522
 
440
- private get dateSortSelector() {
523
+ private get dropdownBackdrop() {
441
524
  return html`
442
525
  <div
443
- id="date-sort-selector-backdrop"
444
- @keyup=${() => {
445
- this.dateSortSelectorVisible = false;
446
- }}
447
- @click=${() => {
448
- this.dateSortSelectorVisible = false;
449
- }}
526
+ id="sort-selector-backdrop"
527
+ @keyup=${this.closeDropdowns}
528
+ @click=${this.closeDropdowns}
450
529
  ></div>
451
- <div id="date-sort-selector">
452
- <ul>
453
- <li>${this.getDateSortButton(SortField.datearchived)}</li>
454
- <li>${this.getDateSortButton(SortField.date)}</li>
455
- <li>${this.getDateSortButton(SortField.datereviewed)}</li>
456
- <li>${this.getDateSortButton(SortField.dateadded)}</li>
457
- </ul>
458
- </div>
459
530
  `;
460
531
  }
461
532
 
462
- private get viewSortSelector() {
463
- return html`
464
- <div
465
- id="view-sort-selector-backdrop"
466
- @keyup=${() => {
467
- this.viewSortSelectorVisible = false;
468
- }}
469
- @click=${() => {
470
- this.viewSortSelectorVisible = false;
471
- }}
472
- ></div>
473
- <div id="view-sort-selector">
474
- <ul>
475
- <li>${this.getDateSortButton(SortField.alltimeview)}</li>
476
- <li>${this.getDateSortButton(SortField.weeklyview)}</li>
477
- </ul>
478
- </div>
479
- `;
480
- }
481
-
482
- private getDateSortButton(sortField: SortField) {
483
- return html`
484
- <button
485
- @click=${() => {
486
- this.selectDateSort(sortField);
487
- }}
488
- class=${this.selectedSort === sortField ? 'selected' : ''}
489
- >
490
- ${SortFieldDisplayName[sortField]}
491
- </button>
492
- `;
533
+ private closeDropdowns() {
534
+ this.viewsDropdown.open = false;
535
+ this.dateDropdown.open = false;
536
+ this.viewSortSelectorVisible = false;
537
+ this.dateSortSelectorVisible = false;
493
538
  }
494
539
 
495
- private selectDateSort(sortField: SortField) {
540
+ private selectDropdownSortField(sortField: SortField) {
496
541
  this.dateSortSelectorVisible = false;
497
542
  this.viewSortSelectorVisible = false;
498
543
  this.setSelectedSort(sortField);
499
544
  }
500
545
 
501
- private setSortDirections(sortDirection: 'asc' | 'desc') {
546
+ private setSortDirection(sortDirection: SortDirection) {
502
547
  this.sortDirection = sortDirection;
503
548
  this.emitSortChangedEvent();
504
549
  }
505
550
 
551
+ private toggleSortDirection() {
552
+ this.setSortDirection(this.sortDirection === 'desc' ? 'asc' : 'desc');
553
+ }
554
+
506
555
  private setSelectedSort(sort: SortField) {
507
556
  this.selectedSort = sort;
508
557
  this.emitSortChangedEvent();
@@ -656,9 +705,8 @@ export class SortFilterBar
656
705
  #sort-bar {
657
706
  display: flex;
658
707
  justify-content: space-between;
659
- border: 1px solid rgb(232, 232, 232);
708
+ border-bottom: 1px solid #2c2c2c;
660
709
  align-items: center;
661
- padding: 0.5rem 1.5rem;
662
710
  }
663
711
 
664
712
  #sort-direction-container {
@@ -666,14 +714,10 @@ export class SortFilterBar
666
714
  }
667
715
 
668
716
  #sort-by-text {
669
- text-transform: uppercase;
670
- }
671
-
672
- #bottom-shadow {
673
- height: 1px;
674
- width: 100%;
675
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
676
- background-color: #bbb;
717
+ margin-right: 10px;
718
+ font-size: 1.4rem;
719
+ font-weight: bold;
720
+ white-space: nowrap;
677
721
  }
678
722
 
679
723
  ul {
@@ -688,12 +732,28 @@ export class SortFilterBar
688
732
  padding: 0;
689
733
  }
690
734
 
735
+ #sort-direction-selector {
736
+ display: flex;
737
+ flex-direction: column;
738
+ margin-right: 5px;
739
+ padding: 0;
740
+ border: none;
741
+ appearance: none;
742
+ background: transparent;
743
+ cursor: pointer;
744
+ }
745
+
746
+ #sort-direction-selector:disabled {
747
+ cursor: default;
748
+ }
749
+
691
750
  .sort-button {
751
+ display: flex;
752
+ align-items: center;
692
753
  background: none;
693
754
  color: inherit;
694
755
  border: none;
695
756
  padding: 0;
696
- cursor: pointer;
697
757
  outline: inherit;
698
758
  width: 12px;
699
759
  height: 12px;
@@ -704,9 +764,8 @@ export class SortFilterBar
704
764
  opacity: 1;
705
765
  }
706
766
 
707
- .sort-button:disabled {
767
+ #sort-direction-selector:disabled .sort-button {
708
768
  opacity: 0.25;
709
- cursor: default;
710
769
  }
711
770
 
712
771
  #date-sort-selector,
@@ -757,42 +816,45 @@ export class SortFilterBar
757
816
  transform: rotate(180deg);
758
817
  }
759
818
 
760
- #sort-direction-selector {
819
+ #sort-selector-container {
820
+ flex: 1;
761
821
  display: flex;
762
- flex-direction: column;
763
- gap: 3px;
764
- margin-right: 1rem;
822
+ justify-content: flex-start;
823
+ align-items: center;
765
824
  }
766
825
 
767
- #sort-selector-container {
768
- flex: 1;
826
+ #desktop-sort-container,
827
+ #mobile-sort-container {
828
+ display: flex;
829
+ justify-content: flex-start;
830
+ align-items: center;
769
831
  }
770
832
 
771
833
  /*
772
834
  we move the desktop sort selector offscreen instead of display: none
773
835
  because we need to observe the width of it vs its container to determine
774
- if it's wide enough to display the desktop version and if you displY: none,
836
+ if it's wide enough to display the desktop version and if you display: none,
775
837
  the width becomes 0
776
838
  */
777
- #desktop-sort-selector.hidden {
839
+ #desktop-sort-container.hidden {
778
840
  position: absolute;
779
841
  top: -9999px;
780
842
  left: -9999px;
843
+ visibility: hidden;
781
844
  }
782
845
 
783
- #mobile-sort-selector.hidden {
846
+ #mobile-sort-container.hidden {
784
847
  display: none;
785
848
  }
786
849
 
787
- #date-sort-selector-backdrop,
788
- #view-sort-selector-backdrop {
850
+ #sort-selector-backdrop {
789
851
  position: fixed;
790
852
  top: 0;
791
853
  left: 0;
792
- width: 100%;
793
- height: 100%;
854
+ width: 100vw;
855
+ height: 100vh;
794
856
  z-index: 1;
795
- background-color: rgba(255, 255, 255, 0.5);
857
+ background-color: transparent;
796
858
  }
797
859
 
798
860
  #desktop-sort-selector {
@@ -802,30 +864,22 @@ export class SortFilterBar
802
864
  #desktop-sort-selector li {
803
865
  display: flex;
804
866
  align-items: center;
867
+ padding-left: 5px;
868
+ padding-right: 5px;
805
869
  }
806
870
 
807
871
  #desktop-sort-selector li a {
872
+ padding: 0 5px;
808
873
  text-decoration: none;
809
- text-transform: uppercase;
810
874
  font-size: 1.4rem;
811
875
  color: #333;
812
- line-height: 2.5;
876
+ line-height: 2;
813
877
  }
814
878
 
815
879
  #desktop-sort-selector li a.selected {
816
880
  font-weight: bold;
817
881
  }
818
882
 
819
- #desktop-sort-selector li::after {
820
- content: '•';
821
- padding-left: 1rem;
822
- padding-right: 1rem;
823
- }
824
-
825
- #desktop-sort-selector li:first-child::after {
826
- content: '';
827
- }
828
-
829
883
  #desktop-sort-selector li:last-child::after {
830
884
  content: '';
831
885
  }
@@ -841,7 +895,7 @@ export class SortFilterBar
841
895
  appearance: none;
842
896
  cursor: pointer;
843
897
  -webkit-appearance: none;
844
- opacity: 0.5;
898
+ opacity: 0.3;
845
899
  }
846
900
 
847
901
  #display-style-selector button.active {
@@ -852,5 +906,37 @@ export class SortFilterBar
852
906
  width: 24px;
853
907
  height: 24px;
854
908
  }
909
+
910
+ ia-dropdown {
911
+ --dropdownTextColor: white;
912
+ --dropdownFontSize: 1.4rem;
913
+ --dropdownOffsetTop: 0;
914
+ --dropdownBorderTopWidth: 0;
915
+ --dropdownBorderTopLeftRadius: 0;
916
+ --dropdownBorderTopRightRadius: 0;
917
+ --dropdownWhiteSpace: nowrap;
918
+ --dropdownListZIndex: 2;
919
+ --dropdownCaretColor: #2c2c2c;
920
+ --dropdownSelectedTextColor: white;
921
+ --dropdownSelectedBgColor: #2c2c2c;
922
+ --caretHeight: 9px;
923
+ --caretWidth: 14px;
924
+ }
925
+ ia-dropdown.selected .dropdown-label {
926
+ font-weight: bold;
927
+ }
928
+ ia-dropdown.open {
929
+ z-index: 2;
930
+ }
931
+
932
+ .dropdown-label {
933
+ display: inline-block;
934
+ height: 100%;
935
+ padding-left: 5px;
936
+ font-size: 1.4rem;
937
+ line-height: 2;
938
+ color: #2c2c2c;
939
+ white-space: nowrap;
940
+ }
855
941
  `;
856
942
  }