@internetarchive/collection-browser 4.5.2 → 4.6.0

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 (520) hide show
  1. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/.editorconfig +29 -0
  2. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/.github/workflows/ci.yml +27 -0
  3. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/.github/workflows/gh-pages-main.yml +39 -0
  4. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/.github/workflows/npm-publish.yml +39 -0
  5. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/.github/workflows/pr-preview.yml +38 -0
  6. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/.husky/pre-commit +1 -0
  7. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/.prettierignore +1 -0
  8. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/LICENSE +661 -0
  9. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/README.md +84 -0
  10. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/eslint.config.mjs +53 -0
  11. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/index.html +24 -0
  12. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/index.ts +29 -0
  13. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/local.archive.org.cert +86 -0
  14. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/local.archive.org.key +27 -0
  15. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/package.json +120 -0
  16. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/renovate.json +6 -0
  17. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/app-root.ts +1284 -0
  18. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/arrow-left.ts +10 -0
  19. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/arrow-right.ts +10 -0
  20. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/chevron.ts +4 -0
  21. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/close-circle-dark.ts +5 -0
  22. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/contract.ts +9 -0
  23. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/empty-query.ts +5 -0
  24. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/expand.ts +9 -0
  25. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/eye-closed.ts +5 -0
  26. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/eye.ts +5 -0
  27. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/favorite-filled.ts +10 -0
  28. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/favorite-unfilled.ts +9 -0
  29. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/filter.ts +10 -0
  30. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/login-required.ts +18 -0
  31. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/account.ts +14 -0
  32. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/audio.ts +14 -0
  33. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/collection.ts +12 -0
  34. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/data.ts +15 -0
  35. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/etree.ts +14 -0
  36. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/film.ts +14 -0
  37. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/images.ts +13 -0
  38. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/radio.ts +15 -0
  39. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/search.ts +14 -0
  40. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/software.ts +13 -0
  41. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/texts.ts +13 -0
  42. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/tv-commercial.ts +12 -0
  43. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/tv-fact-check.ts +12 -0
  44. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/tv-quote.ts +12 -0
  45. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/tv.ts +14 -0
  46. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/video.ts +14 -0
  47. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/web.ts +13 -0
  48. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/null-result.ts +5 -0
  49. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/quote.ts +7 -0
  50. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/restricted.ts +13 -0
  51. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/reviews.ts +11 -0
  52. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/upload.ts +12 -0
  53. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/views.ts +11 -0
  54. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/circular-activity-indicator.ts +64 -0
  55. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-browser.ts +3165 -0
  56. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/facet-row.ts +309 -0
  57. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/facet-tombstone-row.ts +40 -0
  58. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/facets-template.ts +85 -0
  59. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/models.ts +10 -0
  60. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/more-facets-content.ts +644 -0
  61. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/more-facets-pagination.ts +294 -0
  62. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/dedupe.ts +44 -0
  63. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/heuristics/browser-language/browser-language-heuristic.ts +27 -0
  64. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/heuristics/index.ts +3 -0
  65. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/heuristics/query-keywords/query-keywords-heuristic.ts +17 -0
  66. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/heuristics/query-keywords/query-keywords-map.ts +70 -0
  67. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/heuristics/wikidata/wikidata-entity-map.ts +79 -0
  68. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/heuristics/wikidata/wikidata-heuristic.ts +93 -0
  69. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/models.ts +36 -0
  70. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/smart-facet-bar.ts +437 -0
  71. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/smart-facet-button.ts +145 -0
  72. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/smart-facet-dropdown.ts +185 -0
  73. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/smart-facet-equals.ts +16 -0
  74. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/smart-facet-heuristics.ts +26 -0
  75. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/toggle-switch.ts +174 -0
  76. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets.ts +1013 -0
  77. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/data-source/collection-browser-data-source-interface.ts +351 -0
  78. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/data-source/collection-browser-data-source.ts +1474 -0
  79. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/data-source/collection-browser-query-state.ts +60 -0
  80. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/data-source/models.ts +56 -0
  81. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/empty-placeholder.ts +192 -0
  82. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/expanded-date-picker.ts +191 -0
  83. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/language-code-handler/language-code-handler.ts +64 -0
  84. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/language-code-handler/language-code-mapping.ts +564 -0
  85. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/manage/manage-bar.ts +276 -0
  86. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/manage/remove-items-modal-content.ts +102 -0
  87. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/mediatype/mediatype-config.ts +146 -0
  88. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/models.ts +895 -0
  89. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/restoration-state-handler.ts +550 -0
  90. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/sort-filter-bar/alpha-bar-tooltip.ts +53 -0
  91. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/sort-filter-bar/alpha-bar.ts +252 -0
  92. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/sort-filter-bar/img/compact.ts +5 -0
  93. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/sort-filter-bar/img/list.ts +5 -0
  94. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/sort-filter-bar/img/sort-toggle-disabled.ts +15 -0
  95. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/sort-filter-bar/img/sort-toggle-down.ts +17 -0
  96. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/sort-filter-bar/img/sort-toggle-up.ts +17 -0
  97. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/sort-filter-bar/img/sort-triangle.ts +5 -0
  98. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/sort-filter-bar/img/tile.ts +5 -0
  99. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/sort-filter-bar/sort-filter-bar.ts +733 -0
  100. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/styles/ia-button.ts +139 -0
  101. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/styles/item-image-styles.ts +124 -0
  102. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/styles/sr-only.ts +18 -0
  103. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/styles/tile-action-styles.ts +59 -0
  104. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/base-tile-component.ts +124 -0
  105. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/collection-browser-loading-tile.ts +26 -0
  106. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/grid/account-tile.ts +113 -0
  107. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/grid/collection-tile.ts +184 -0
  108. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/grid/item-tile.ts +347 -0
  109. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/grid/search-tile.ts +90 -0
  110. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/grid/styles/tile-grid-shared-styles.ts +130 -0
  111. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/grid/tile-stats.ts +211 -0
  112. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/hover/hover-pane-controller.ts +638 -0
  113. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/hover/tile-hover-pane.ts +184 -0
  114. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/image-block.ts +162 -0
  115. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/item-image.ts +214 -0
  116. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/list/tile-list-compact-header.ts +112 -0
  117. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/list/tile-list-compact.ts +278 -0
  118. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/list/tile-list.ts +718 -0
  119. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/models.ts +21 -0
  120. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/overlay/icon-overlay.ts +57 -0
  121. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/overlay/text-overlay.ts +79 -0
  122. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/review-block.ts +130 -0
  123. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/text-snippet-block.ts +132 -0
  124. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/tile-dispatcher.ts +637 -0
  125. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/tile-display-value-provider.ts +133 -0
  126. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/tile-mediatype-icon.ts +133 -0
  127. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/utils/analytics-events.ts +29 -0
  128. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/utils/array-equals.ts +8 -0
  129. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/utils/collapse-repeated-quotes.ts +13 -0
  130. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/utils/date-filter-field.ts +11 -0
  131. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/utils/facet-utils.ts +183 -0
  132. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/utils/format-count.ts +95 -0
  133. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/utils/format-date.ts +62 -0
  134. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/utils/format-unit-size.ts +43 -0
  135. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/utils/local-date-from-utc.ts +15 -0
  136. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/utils/log.ts +14 -0
  137. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/utils/resolve-mediatype.ts +26 -0
  138. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/utils/sha1.ts +9 -0
  139. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/collection-browser.test.ts +2639 -0
  140. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/collection-facets/facet-row.test.ts +421 -0
  141. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/collection-facets/facets-template.test.ts +139 -0
  142. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/collection-facets/more-facets-content.test.ts +231 -0
  143. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/collection-facets/more-facets-pagination.test.ts +201 -0
  144. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/collection-facets/toggle-switch.test.ts +164 -0
  145. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/collection-facets.test.ts +928 -0
  146. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/data-source/collection-browser-data-source.test.ts +193 -0
  147. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/empty-placeholder.test.ts +88 -0
  148. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/expanded-date-picker.test.ts +201 -0
  149. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/icon-overlay.test.ts +38 -0
  150. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/image-block.test.ts +247 -0
  151. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/item-image.test.ts +220 -0
  152. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/manage/manage-bar.test.ts +347 -0
  153. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/manage/remove-items-modal-content.test.ts +81 -0
  154. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/mediatype-config.test.ts +11 -0
  155. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/mocks/mock-analytics-handler.ts +30 -0
  156. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/mocks/mock-search-responses.ts +1364 -0
  157. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/mocks/mock-search-service.ts +134 -0
  158. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/restoration-state-handler.test.ts +480 -0
  159. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/review-block.test.ts +62 -0
  160. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/sort-filter-bar/alpha-bar-tooltip.test.ts +17 -0
  161. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/sort-filter-bar/alpha-bar.test.ts +101 -0
  162. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/sort-filter-bar/sort-filter-bar.test.ts +443 -0
  163. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/text-overlay.test.ts +55 -0
  164. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/text-snippet-block.test.ts +85 -0
  165. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tile-stats.test.ts +191 -0
  166. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tiles/grid/account-tile.test.ts +121 -0
  167. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tiles/grid/collection-tile.test.ts +114 -0
  168. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tiles/grid/item-tile.test.ts +520 -0
  169. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tiles/grid/search-tile.test.ts +75 -0
  170. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tiles/hover/hover-pane-controller.test.ts +482 -0
  171. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tiles/hover/tile-hover-pane.test.ts +80 -0
  172. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tiles/list/tile-list-compact-header.test.ts +43 -0
  173. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tiles/list/tile-list-compact.test.ts +282 -0
  174. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tiles/list/tile-list.test.ts +576 -0
  175. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tiles/tile-dispatcher.test.ts +320 -0
  176. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tiles/tile-display-value-provider.test.ts +172 -0
  177. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tiles/tile-mediatype-icon.test.ts +160 -0
  178. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/utils/array-equals.test.ts +31 -0
  179. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/utils/format-count.test.ts +32 -0
  180. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/utils/format-date.test.ts +89 -0
  181. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/utils/format-unit-size.test.ts +21 -0
  182. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/utils/local-date-from-utc.test.ts +37 -0
  183. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/tsconfig.json +25 -0
  184. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/types/dompurify.d.ts +1 -0
  185. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/vite.config.ts +29 -0
  186. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/web-dev-server.config.mjs +30 -0
  187. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/web-test-runner.config.mjs +52 -0
  188. package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/yarn.lock +5965 -0
  189. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/.editorconfig +29 -0
  190. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/.github/workflows/ci.yml +29 -0
  191. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/.github/workflows/gh-pages-main.yml +41 -0
  192. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/.github/workflows/npm-publish.yml +42 -0
  193. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/.github/workflows/pr-preview.yml +40 -0
  194. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/.husky/pre-commit +1 -0
  195. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/.prettierignore +1 -0
  196. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/LICENSE +661 -0
  197. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/README.md +68 -0
  198. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/eslint.config.mjs +53 -0
  199. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/index.html +24 -0
  200. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/index.ts +29 -0
  201. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/local.archive.org.cert +86 -0
  202. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/local.archive.org.key +27 -0
  203. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/package.json +129 -0
  204. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/pnpm-lock.yaml +7366 -0
  205. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/pnpm-workspace.yaml +46 -0
  206. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/renovate.json +6 -0
  207. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/app-root.ts +1284 -0
  208. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/arrow-left.ts +10 -0
  209. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/arrow-right.ts +10 -0
  210. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/chevron.ts +4 -0
  211. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/close-circle-dark.ts +5 -0
  212. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/contract.ts +9 -0
  213. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/empty-query.ts +5 -0
  214. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/expand.ts +9 -0
  215. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/eye-closed.ts +5 -0
  216. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/eye.ts +5 -0
  217. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/favorite-filled.ts +10 -0
  218. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/favorite-unfilled.ts +9 -0
  219. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/filter.ts +10 -0
  220. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/login-required.ts +18 -0
  221. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/mediatype/account.ts +14 -0
  222. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/mediatype/audio.ts +14 -0
  223. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/mediatype/collection.ts +12 -0
  224. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/mediatype/data.ts +15 -0
  225. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/mediatype/etree.ts +14 -0
  226. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/mediatype/film.ts +14 -0
  227. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/mediatype/images.ts +13 -0
  228. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/mediatype/radio.ts +15 -0
  229. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/mediatype/search.ts +14 -0
  230. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/mediatype/software.ts +13 -0
  231. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/mediatype/texts.ts +13 -0
  232. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/mediatype/tv-commercial.ts +12 -0
  233. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/mediatype/tv-fact-check.ts +12 -0
  234. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/mediatype/tv-quote.ts +12 -0
  235. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/mediatype/tv.ts +14 -0
  236. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/mediatype/video.ts +14 -0
  237. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/mediatype/web.ts +13 -0
  238. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/null-result.ts +5 -0
  239. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/quote.ts +7 -0
  240. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/restricted.ts +13 -0
  241. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/reviews.ts +11 -0
  242. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/upload.ts +12 -0
  243. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/assets/img/icons/views.ts +11 -0
  244. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/circular-activity-indicator.ts +64 -0
  245. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/collection-browser.ts +3165 -0
  246. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/collection-facets/facet-row.ts +309 -0
  247. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/collection-facets/facet-tombstone-row.ts +40 -0
  248. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/collection-facets/facets-template.ts +85 -0
  249. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/collection-facets/models.ts +10 -0
  250. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/collection-facets/more-facets-content.ts +644 -0
  251. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/collection-facets/more-facets-pagination.ts +294 -0
  252. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/collection-facets/smart-facets/dedupe.ts +44 -0
  253. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/collection-facets/smart-facets/heuristics/browser-language/browser-language-heuristic.ts +27 -0
  254. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/collection-facets/smart-facets/heuristics/index.ts +3 -0
  255. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/collection-facets/smart-facets/heuristics/query-keywords/query-keywords-heuristic.ts +17 -0
  256. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/collection-facets/smart-facets/heuristics/query-keywords/query-keywords-map.ts +70 -0
  257. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/collection-facets/smart-facets/heuristics/wikidata/wikidata-entity-map.ts +79 -0
  258. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/collection-facets/smart-facets/heuristics/wikidata/wikidata-heuristic.ts +93 -0
  259. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/collection-facets/smart-facets/models.ts +36 -0
  260. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/collection-facets/smart-facets/smart-facet-bar.ts +437 -0
  261. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/collection-facets/smart-facets/smart-facet-button.ts +145 -0
  262. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/collection-facets/smart-facets/smart-facet-dropdown.ts +185 -0
  263. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/collection-facets/smart-facets/smart-facet-equals.ts +16 -0
  264. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/collection-facets/smart-facets/smart-facet-heuristics.ts +26 -0
  265. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/collection-facets/toggle-switch.ts +174 -0
  266. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/collection-facets.ts +1013 -0
  267. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/data-source/collection-browser-data-source-interface.ts +351 -0
  268. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/data-source/collection-browser-data-source.ts +1474 -0
  269. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/data-source/collection-browser-query-state.ts +60 -0
  270. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/data-source/models.ts +56 -0
  271. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/empty-placeholder.ts +192 -0
  272. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/expanded-date-picker.ts +191 -0
  273. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/language-code-handler/language-code-handler.ts +64 -0
  274. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/language-code-handler/language-code-mapping.ts +564 -0
  275. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/manage/manage-bar.ts +276 -0
  276. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/manage/remove-items-modal-content.ts +102 -0
  277. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/mediatype/mediatype-config.ts +146 -0
  278. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/models.ts +895 -0
  279. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/restoration-state-handler.ts +550 -0
  280. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/sort-filter-bar/alpha-bar-tooltip.ts +53 -0
  281. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/sort-filter-bar/alpha-bar.ts +252 -0
  282. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/sort-filter-bar/img/compact.ts +5 -0
  283. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/sort-filter-bar/img/list.ts +5 -0
  284. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/sort-filter-bar/img/sort-toggle-disabled.ts +15 -0
  285. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/sort-filter-bar/img/sort-toggle-down.ts +17 -0
  286. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/sort-filter-bar/img/sort-toggle-up.ts +17 -0
  287. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/sort-filter-bar/img/sort-triangle.ts +5 -0
  288. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/sort-filter-bar/img/tile.ts +5 -0
  289. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/sort-filter-bar/sort-filter-bar.ts +733 -0
  290. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/styles/ia-button.ts +139 -0
  291. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/styles/item-image-styles.ts +124 -0
  292. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/styles/sr-only.ts +18 -0
  293. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/styles/tile-action-styles.ts +59 -0
  294. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/tiles/base-tile-component.ts +124 -0
  295. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/tiles/collection-browser-loading-tile.ts +26 -0
  296. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/tiles/grid/account-tile.ts +113 -0
  297. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/tiles/grid/collection-tile.ts +184 -0
  298. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/tiles/grid/item-tile.ts +347 -0
  299. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/tiles/grid/search-tile.ts +90 -0
  300. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/tiles/grid/styles/tile-grid-shared-styles.ts +130 -0
  301. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/tiles/grid/tile-stats.ts +211 -0
  302. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/tiles/hover/hover-pane-controller.ts +638 -0
  303. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/tiles/hover/tile-hover-pane.ts +184 -0
  304. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/tiles/image-block.ts +162 -0
  305. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/tiles/item-image.ts +214 -0
  306. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/tiles/list/tile-list-compact-header.ts +112 -0
  307. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/tiles/list/tile-list-compact.ts +278 -0
  308. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/tiles/list/tile-list.ts +718 -0
  309. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/tiles/models.ts +21 -0
  310. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/tiles/overlay/icon-overlay.ts +57 -0
  311. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/tiles/overlay/text-overlay.ts +79 -0
  312. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/tiles/review-block.ts +130 -0
  313. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/tiles/text-snippet-block.ts +132 -0
  314. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/tiles/tile-dispatcher.ts +637 -0
  315. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/tiles/tile-display-value-provider.ts +133 -0
  316. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/tiles/tile-mediatype-icon.ts +133 -0
  317. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/utils/analytics-events.ts +29 -0
  318. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/utils/array-equals.ts +8 -0
  319. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/utils/collapse-repeated-quotes.ts +13 -0
  320. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/utils/date-filter-field.ts +11 -0
  321. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/utils/facet-utils.ts +183 -0
  322. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/utils/format-count.ts +95 -0
  323. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/utils/format-date.ts +62 -0
  324. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/utils/format-unit-size.ts +43 -0
  325. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/utils/local-date-from-utc.ts +15 -0
  326. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/utils/log.ts +14 -0
  327. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/utils/resolve-mediatype.ts +26 -0
  328. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/src/utils/sha1.ts +9 -0
  329. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/collection-browser.test.ts +2639 -0
  330. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/collection-facets/facet-row.test.ts +421 -0
  331. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/collection-facets/facets-template.test.ts +139 -0
  332. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/collection-facets/more-facets-content.test.ts +231 -0
  333. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/collection-facets/more-facets-pagination.test.ts +201 -0
  334. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/collection-facets/toggle-switch.test.ts +164 -0
  335. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/collection-facets.test.ts +928 -0
  336. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/data-source/collection-browser-data-source.test.ts +193 -0
  337. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/empty-placeholder.test.ts +88 -0
  338. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/expanded-date-picker.test.ts +201 -0
  339. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/icon-overlay.test.ts +38 -0
  340. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/image-block.test.ts +247 -0
  341. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/item-image.test.ts +220 -0
  342. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/manage/manage-bar.test.ts +347 -0
  343. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/manage/remove-items-modal-content.test.ts +81 -0
  344. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/mediatype-config.test.ts +11 -0
  345. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/mocks/mock-analytics-handler.ts +30 -0
  346. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/mocks/mock-search-responses.ts +1364 -0
  347. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/mocks/mock-search-service.ts +134 -0
  348. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/restoration-state-handler.test.ts +480 -0
  349. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/review-block.test.ts +62 -0
  350. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/sort-filter-bar/alpha-bar-tooltip.test.ts +17 -0
  351. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/sort-filter-bar/alpha-bar.test.ts +101 -0
  352. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/sort-filter-bar/sort-filter-bar.test.ts +443 -0
  353. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/text-overlay.test.ts +55 -0
  354. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/text-snippet-block.test.ts +85 -0
  355. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/tile-stats.test.ts +191 -0
  356. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/tiles/grid/account-tile.test.ts +121 -0
  357. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/tiles/grid/collection-tile.test.ts +114 -0
  358. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/tiles/grid/item-tile.test.ts +520 -0
  359. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/tiles/grid/search-tile.test.ts +75 -0
  360. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/tiles/hover/hover-pane-controller.test.ts +482 -0
  361. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/tiles/hover/tile-hover-pane.test.ts +80 -0
  362. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/tiles/list/tile-list-compact-header.test.ts +43 -0
  363. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/tiles/list/tile-list-compact.test.ts +282 -0
  364. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/tiles/list/tile-list.test.ts +576 -0
  365. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/tiles/tile-dispatcher.test.ts +320 -0
  366. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/tiles/tile-display-value-provider.test.ts +172 -0
  367. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/tiles/tile-mediatype-icon.test.ts +160 -0
  368. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/utils/array-equals.test.ts +31 -0
  369. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/utils/format-count.test.ts +32 -0
  370. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/utils/format-date.test.ts +89 -0
  371. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/utils/format-unit-size.test.ts +21 -0
  372. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/test/utils/local-date-from-utc.test.ts +37 -0
  373. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/tsconfig.json +25 -0
  374. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/types/dompurify.d.ts +1 -0
  375. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/vite.config.ts +29 -0
  376. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/web-dev-server.config.mjs +30 -0
  377. package/.claude/worktrees/WEBDEV-9119-migrate-to-pnpm/web-test-runner.config.mjs +52 -0
  378. package/.editorconfig +29 -29
  379. package/.github/workflows/ci.yml +27 -27
  380. package/.github/workflows/gh-pages-main.yml +39 -39
  381. package/.github/workflows/npm-publish.yml +39 -39
  382. package/.github/workflows/pr-preview.yml +38 -38
  383. package/.husky/pre-commit +1 -1
  384. package/.prettierignore +1 -1
  385. package/LICENSE +661 -661
  386. package/README.md +83 -83
  387. package/dist/index.js.map +1 -1
  388. package/dist/src/app-root.d.ts +1 -1
  389. package/dist/src/app-root.js +683 -683
  390. package/dist/src/app-root.js.map +1 -1
  391. package/dist/src/assets/img/icons/arrow-left.d.ts +1 -1
  392. package/dist/src/assets/img/icons/arrow-right.d.ts +1 -1
  393. package/dist/src/assets/img/icons/chevron.d.ts +1 -1
  394. package/dist/src/assets/img/icons/close-circle-dark.d.ts +1 -1
  395. package/dist/src/assets/img/icons/contract.d.ts +1 -1
  396. package/dist/src/assets/img/icons/empty-query.d.ts +1 -1
  397. package/dist/src/assets/img/icons/expand.d.ts +1 -1
  398. package/dist/src/assets/img/icons/eye-closed.d.ts +1 -1
  399. package/dist/src/assets/img/icons/eye.d.ts +1 -1
  400. package/dist/src/assets/img/icons/favorite-filled.d.ts +1 -1
  401. package/dist/src/assets/img/icons/favorite-unfilled.d.ts +1 -1
  402. package/dist/src/assets/img/icons/filter.d.ts +1 -1
  403. package/dist/src/assets/img/icons/login-required.d.ts +1 -1
  404. package/dist/src/assets/img/icons/mediatype/account.d.ts +1 -1
  405. package/dist/src/assets/img/icons/mediatype/audio.d.ts +1 -1
  406. package/dist/src/assets/img/icons/mediatype/collection.d.ts +1 -1
  407. package/dist/src/assets/img/icons/mediatype/data.d.ts +1 -1
  408. package/dist/src/assets/img/icons/mediatype/etree.d.ts +1 -1
  409. package/dist/src/assets/img/icons/mediatype/film.d.ts +1 -1
  410. package/dist/src/assets/img/icons/mediatype/images.d.ts +1 -1
  411. package/dist/src/assets/img/icons/mediatype/radio.d.ts +1 -1
  412. package/dist/src/assets/img/icons/mediatype/search.d.ts +1 -1
  413. package/dist/src/assets/img/icons/mediatype/software.d.ts +1 -1
  414. package/dist/src/assets/img/icons/mediatype/texts.d.ts +1 -1
  415. package/dist/src/assets/img/icons/mediatype/tv-commercial.d.ts +1 -1
  416. package/dist/src/assets/img/icons/mediatype/tv-fact-check.d.ts +1 -1
  417. package/dist/src/assets/img/icons/mediatype/tv-quote.d.ts +1 -1
  418. package/dist/src/assets/img/icons/mediatype/tv.d.ts +1 -1
  419. package/dist/src/assets/img/icons/mediatype/video.d.ts +1 -1
  420. package/dist/src/assets/img/icons/mediatype/web.d.ts +1 -1
  421. package/dist/src/assets/img/icons/null-result.d.ts +1 -1
  422. package/dist/src/assets/img/icons/quote.d.ts +1 -1
  423. package/dist/src/assets/img/icons/restricted.d.ts +1 -1
  424. package/dist/src/assets/img/icons/reviews.d.ts +1 -1
  425. package/dist/src/assets/img/icons/upload.d.ts +1 -1
  426. package/dist/src/assets/img/icons/views.d.ts +1 -1
  427. package/dist/src/circular-activity-indicator.d.ts +1 -1
  428. package/dist/src/collection-browser.js +766 -766
  429. package/dist/src/collection-browser.js.map +1 -1
  430. package/dist/src/collection-facets/facet-row.js +143 -143
  431. package/dist/src/collection-facets/facet-row.js.map +1 -1
  432. package/dist/src/collection-facets/facet-tombstone-row.d.ts +1 -1
  433. package/dist/src/collection-facets/facets-template.js +24 -24
  434. package/dist/src/collection-facets/facets-template.js.map +1 -1
  435. package/dist/src/collection-facets/smart-facets/smart-facet-button.d.ts +1 -1
  436. package/dist/src/collection-facets/smart-facets/smart-facet-dropdown.d.ts +1 -1
  437. package/dist/src/collection-facets/toggle-switch.d.ts +1 -1
  438. package/dist/src/data-source/collection-browser-data-source-interface.js.map +1 -1
  439. package/dist/src/data-source/collection-browser-data-source.js.map +1 -1
  440. package/dist/src/restoration-state-handler.js.map +1 -1
  441. package/dist/src/sort-filter-bar/alpha-bar-tooltip.d.ts +1 -1
  442. package/dist/src/sort-filter-bar/img/compact.d.ts +1 -1
  443. package/dist/src/sort-filter-bar/img/list.d.ts +1 -1
  444. package/dist/src/sort-filter-bar/img/sort-toggle-disabled.d.ts +1 -1
  445. package/dist/src/sort-filter-bar/img/sort-toggle-down.d.ts +1 -1
  446. package/dist/src/sort-filter-bar/img/sort-toggle-up.d.ts +1 -1
  447. package/dist/src/sort-filter-bar/img/sort-triangle.d.ts +1 -1
  448. package/dist/src/sort-filter-bar/img/tile.d.ts +1 -1
  449. package/dist/src/styles/tile-action-styles.js +43 -43
  450. package/dist/src/styles/tile-action-styles.js.map +1 -1
  451. package/dist/src/tiles/base-tile-component.js +11 -11
  452. package/dist/src/tiles/base-tile-component.js.map +1 -1
  453. package/dist/src/tiles/collection-browser-loading-tile.d.ts +1 -1
  454. package/dist/src/tiles/grid/item-tile.js +138 -138
  455. package/dist/src/tiles/grid/item-tile.js.map +1 -1
  456. package/dist/src/tiles/hover/hover-pane-controller.js +40 -32
  457. package/dist/src/tiles/hover/hover-pane-controller.js.map +1 -1
  458. package/dist/src/tiles/image-block.d.ts +1 -1
  459. package/dist/src/tiles/item-image.d.ts +1 -1
  460. package/dist/src/tiles/list/tile-list-compact-header.d.ts +1 -1
  461. package/dist/src/tiles/list/tile-list-compact-header.js +62 -62
  462. package/dist/src/tiles/list/tile-list-compact-header.js.map +1 -1
  463. package/dist/src/tiles/list/tile-list-compact.d.ts +1 -1
  464. package/dist/src/tiles/list/tile-list-compact.js +123 -123
  465. package/dist/src/tiles/list/tile-list-compact.js.map +1 -1
  466. package/dist/src/tiles/list/tile-list.js +310 -310
  467. package/dist/src/tiles/list/tile-list.js.map +1 -1
  468. package/dist/src/tiles/models.js.map +1 -1
  469. package/dist/src/tiles/tile-dispatcher.d.ts +1 -1
  470. package/dist/src/tiles/tile-dispatcher.js +286 -286
  471. package/dist/src/tiles/tile-dispatcher.js.map +1 -1
  472. package/dist/src/tiles/tile-display-value-provider.js.map +1 -1
  473. package/dist/src/tiles/tile-mediatype-icon.d.ts +1 -1
  474. package/dist/src/utils/date-filter-field.js.map +1 -1
  475. package/dist/test/collection-browser.test.js +203 -203
  476. package/dist/test/collection-browser.test.js.map +1 -1
  477. package/dist/test/collection-facets/facet-row.test.js +31 -31
  478. package/dist/test/collection-facets/facet-row.test.js.map +1 -1
  479. package/dist/test/tiles/grid/item-tile.test.js +77 -77
  480. package/dist/test/tiles/grid/item-tile.test.js.map +1 -1
  481. package/dist/test/tiles/hover/hover-pane-controller.test.js +57 -50
  482. package/dist/test/tiles/hover/hover-pane-controller.test.js.map +1 -1
  483. package/dist/test/tiles/list/tile-list.test.js +134 -134
  484. package/dist/test/tiles/list/tile-list.test.js.map +1 -1
  485. package/dist/test/tiles/tile-dispatcher.test.js +92 -92
  486. package/dist/test/tiles/tile-dispatcher.test.js.map +1 -1
  487. package/eslint.config.mjs +53 -53
  488. package/index.html +24 -24
  489. package/index.ts +29 -29
  490. package/local.archive.org.cert +86 -86
  491. package/local.archive.org.key +27 -27
  492. package/package.json +120 -120
  493. package/renovate.json +6 -6
  494. package/src/app-root.ts +1284 -1284
  495. package/src/collection-browser.ts +3165 -3165
  496. package/src/collection-facets/facet-row.ts +309 -309
  497. package/src/collection-facets/facets-template.ts +85 -85
  498. package/src/data-source/collection-browser-data-source-interface.ts +351 -351
  499. package/src/data-source/collection-browser-data-source.ts +1474 -1474
  500. package/src/restoration-state-handler.ts +550 -550
  501. package/src/styles/tile-action-styles.ts +59 -59
  502. package/src/tiles/base-tile-component.ts +124 -124
  503. package/src/tiles/grid/item-tile.ts +347 -347
  504. package/src/tiles/hover/hover-pane-controller.ts +638 -630
  505. package/src/tiles/list/tile-list-compact-header.ts +112 -112
  506. package/src/tiles/list/tile-list-compact.ts +278 -278
  507. package/src/tiles/list/tile-list.ts +718 -718
  508. package/src/tiles/models.ts +21 -21
  509. package/src/tiles/tile-dispatcher.ts +637 -637
  510. package/src/tiles/tile-display-value-provider.ts +133 -133
  511. package/src/utils/date-filter-field.ts +11 -11
  512. package/test/collection-browser.test.ts +2639 -2639
  513. package/test/collection-facets/facet-row.test.ts +421 -421
  514. package/test/tiles/grid/item-tile.test.ts +520 -520
  515. package/test/tiles/hover/hover-pane-controller.test.ts +482 -454
  516. package/test/tiles/list/tile-list.test.ts +576 -576
  517. package/test/tiles/tile-dispatcher.test.ts +320 -320
  518. package/tsconfig.json +25 -25
  519. package/web-dev-server.config.mjs +30 -30
  520. package/web-test-runner.config.mjs +52 -52
@@ -0,0 +1,718 @@
1
+ import { css, html, nothing, PropertyValues, TemplateResult } from 'lit';
2
+ import { ifDefined } from 'lit/directives/if-defined.js';
3
+ import { join } from 'lit/directives/join.js';
4
+ import { map } from 'lit/directives/map.js';
5
+ import { unsafeHTML } from 'lit/directives/unsafe-html.js';
6
+ import { customElement, property, state } from 'lit/decorators.js';
7
+ import { msg, str } from '@lit/localize';
8
+ import DOMPurify from 'dompurify';
9
+
10
+ import type { SortParam } from '@internetarchive/search-service';
11
+ import { suppressedCollections } from '../../models';
12
+ import type { CollectionTitles } from '../../data-source/models';
13
+ import { BaseTileComponent } from '../base-tile-component';
14
+
15
+ import { formatCount, NumberFormat } from '../../utils/format-count';
16
+ import type { DateFormat } from '../../utils/format-date';
17
+ import { isFirstMillisecondOfUTCYear } from '../../utils/local-date-from-utc';
18
+ import { tileActionStyles } from '../../styles/tile-action-styles';
19
+
20
+ import '../image-block';
21
+ import '../review-block';
22
+ import '../text-snippet-block';
23
+ import '../tile-mediatype-icon';
24
+
25
+ @customElement('tile-list')
26
+ export class TileList extends BaseTileComponent {
27
+ /*
28
+ * Reactive properties inherited from BaseTileComponent:
29
+ * - model?: TileModel;
30
+ * - tileActions: TileAction[] = [];
31
+ * - currentWidth?: number;
32
+ * - currentHeight?: number;
33
+ * - baseNavigationUrl?: string;
34
+ * - baseImageUrl?: string;
35
+ * - collectionPagePath?: string;
36
+ * - sortParam: SortParam | null = null;
37
+ * - defaultSortParam: SortParam | null = null;
38
+ * - creatorFilter?: string;
39
+ * - mobileBreakpoint?: number;
40
+ * - loggedIn = false;
41
+ * - suppressBlurring = false;
42
+ * - useLocalTime = false;
43
+ */
44
+
45
+ @property({ type: Object })
46
+ collectionTitles?: CollectionTitles;
47
+
48
+ @state() private collectionLinks: (TemplateResult | typeof nothing)[] = [];
49
+
50
+ render() {
51
+ return html`
52
+ <div id="list-line" class="${this.classSize}">
53
+ ${this.classSize === 'mobile'
54
+ ? this.mobileTemplate
55
+ : this.desktopTemplate}
56
+ </div>
57
+ `;
58
+ }
59
+
60
+ /**
61
+ * Templates
62
+ */
63
+ private get mobileTemplate() {
64
+ return html`
65
+ <div id="list-line-top">
66
+ <div id="list-line-left">
67
+ ${this.imageBlockTemplate} ${this.renderTileActions('list-detail')}
68
+ </div>
69
+ <div id="list-line-right">
70
+ <div id="title-line">
71
+ <div id="title">${this.titleTemplate}</div>
72
+ ${this.iconRightTemplate}
73
+ </div>
74
+ </div>
75
+ </div>
76
+ <div id="list-line-bottom">${this.detailsTemplate}</div>
77
+ `;
78
+ }
79
+
80
+ private get desktopTemplate() {
81
+ return html`
82
+ <div id="list-line-left">
83
+ ${this.imageBlockTemplate} ${this.renderTileActions('list-detail')}
84
+ </div>
85
+ <div id="list-line-right">
86
+ <div id="title-line">
87
+ <div id="title">${this.titleTemplate}</div>
88
+ ${this.iconRightTemplate}
89
+ </div>
90
+ ${this.detailsTemplate}
91
+ </div>
92
+ `;
93
+ }
94
+
95
+ private get imageBlockTemplate() {
96
+ if (!this.model) return nothing;
97
+
98
+ const isCollection = this.model.mediatype === 'collection';
99
+ const href = this.displayValueProvider.itemPageUrl(
100
+ this.model.identifier,
101
+ isCollection,
102
+ );
103
+
104
+ return html`<a
105
+ id="image-link"
106
+ title=${msg(str`View ${this.model?.title}`)}
107
+ href=${href}
108
+ >
109
+ <image-block
110
+ .model=${this.model}
111
+ .baseImageUrl=${this.baseImageUrl}
112
+ .isCompactTile=${false}
113
+ .isListTile=${true}
114
+ .viewSize=${this.classSize}
115
+ .loggedIn=${this.loggedIn}
116
+ .suppressBlurring=${this.suppressBlurring}
117
+ >
118
+ </image-block>
119
+ </a> `;
120
+ }
121
+
122
+ private get detailsTemplate() {
123
+ return html`
124
+ ${this.itemLineTemplate} ${this.creatorTemplate}
125
+ <div id="dates-line">
126
+ ${this.datePublishedTemplate} ${this.dateSortByTemplate}
127
+ ${this.webArchivesCaptureDatesTemplate}
128
+ </div>
129
+ <div id="views-line">
130
+ ${this.viewsTemplate} ${this.ratingTemplate} ${this.reviewsTemplate}
131
+ </div>
132
+ ${this.topicsTemplate} ${this.collectionsTemplate}
133
+ ${this.descriptionTemplate} ${this.textSnippetsTemplate}
134
+ ${this.reviewBlockTemplate}
135
+ `;
136
+ }
137
+
138
+ // Data templates
139
+ private get iconRightTemplate() {
140
+ return html`
141
+ <a
142
+ id="icon-right"
143
+ href=${this.mediatypeURL}
144
+ title=${msg(str`See more: ${this.model?.mediatype}`)}
145
+ >
146
+ <tile-mediatype-icon .model=${this.model}> </tile-mediatype-icon>
147
+ </a>
148
+ `;
149
+ }
150
+
151
+ private get titleTemplate() {
152
+ if (!this.model?.title) {
153
+ return nothing;
154
+ }
155
+
156
+ // If the model has a server-specified href, use it
157
+ // Otherwise construct a details link using the identifier
158
+ return this.model?.href
159
+ ? html`<a href="${this.baseNavigationUrl}${this.model.href}"
160
+ >${this.model.title ?? this.model.identifier}</a
161
+ >`
162
+ : this.detailsLink(
163
+ this.model.identifier,
164
+ this.model.title,
165
+ this.model.mediatype === 'collection',
166
+ );
167
+ }
168
+
169
+ private get itemLineTemplate() {
170
+ const source = this.sourceTemplate;
171
+ const volume = this.volumeTemplate;
172
+ const issue = this.issueTemplate;
173
+ if (!source && !volume && !issue) {
174
+ return nothing;
175
+ }
176
+ return html` <div id="item-line">${source} ${volume} ${issue}</div> `;
177
+ }
178
+
179
+ private get sourceTemplate() {
180
+ if (!this.model?.source) {
181
+ return nothing;
182
+ }
183
+ return html`
184
+ <div id="source" class="metadata">
185
+ ${this.labelTemplate(msg('Source'))}
186
+ ${this.searchLink('source', this.model.source)}
187
+ </div>
188
+ `;
189
+ }
190
+
191
+ private get volumeTemplate() {
192
+ return this.metadataTemplate(this.model?.volume, msg('Volume'));
193
+ }
194
+
195
+ private get issueTemplate() {
196
+ return this.metadataTemplate(this.model?.issue, msg('Issue'));
197
+ }
198
+
199
+ private get creatorTemplate() {
200
+ // "Archivist since" if account
201
+ if (this.model?.mediatype === 'account') {
202
+ return html`
203
+ <div id="creator" class="metadata">
204
+ <span class="label"
205
+ >${this.displayValueProvider.accountLabel ?? nothing}</span
206
+ >
207
+ </div>
208
+ `;
209
+ }
210
+ // "Creator" if not account tile
211
+ if (!this.model?.creators || this.model.creators.length === 0) {
212
+ return nothing;
213
+ }
214
+ return html`
215
+ <div id="creator" class="metadata">
216
+ ${this.labelTemplate(msg('By'))}
217
+ ${join(
218
+ map(this.model.creators, id => this.searchLink('creator', id)),
219
+ ', ',
220
+ )}
221
+ </div>
222
+ `;
223
+ }
224
+
225
+ private get datePublishedTemplate() {
226
+ // If we're showing a date published of Jan 1 at midnight, only show the year.
227
+ // This is because items with only a year for their publication date are normalized to
228
+ // Jan 1 at midnight timestamps in the search engine documents.
229
+ const date: Date | undefined = this.model?.datePublished;
230
+ let format: DateFormat = 'long';
231
+ if (isFirstMillisecondOfUTCYear(date)) {
232
+ format = 'year-only';
233
+ }
234
+
235
+ return this.metadataTemplate(
236
+ this.getFormattedDate(date, format),
237
+ msg('Published'),
238
+ );
239
+ }
240
+
241
+ // Show date label/value when sorted by date type
242
+ // Except datePublished which is always shown
243
+ private get dateSortByTemplate() {
244
+ if (
245
+ this.effectiveSort &&
246
+ (this.effectiveSort.field === 'addeddate' ||
247
+ this.effectiveSort.field === 'reviewdate' ||
248
+ this.effectiveSort.field === 'publicdate')
249
+ ) {
250
+ return this.metadataTemplate(
251
+ this.getFormattedDate(this.date, 'long'),
252
+ this.displayValueProvider.dateLabel,
253
+ );
254
+ }
255
+ return nothing;
256
+ }
257
+
258
+ private get viewsTemplate() {
259
+ const isWeeklySort = this.effectiveSort?.field === 'week';
260
+ const viewCount = isWeeklySort
261
+ ? this.model?.weeklyViewCount // weekly views
262
+ : this.model?.viewCount; // all-time views
263
+ if (viewCount == null) return nothing;
264
+
265
+ // when its a search-tile, we don't have any stats to show
266
+ if (this.model?.mediatype === 'search') {
267
+ return this.metadataTemplate('(Favorited search query)', '');
268
+ }
269
+
270
+ return this.metadataTemplate(
271
+ `${formatCount(viewCount, this.formatSize)}`,
272
+ this.displayValueProvider.viewsLabel,
273
+ );
274
+ }
275
+
276
+ private get ratingTemplate() {
277
+ return this.metadataTemplate(this.model?.averageRating, msg('Avg Rating'));
278
+ }
279
+
280
+ private get reviewsTemplate() {
281
+ return this.metadataTemplate(this.model?.commentCount, msg('Reviews'));
282
+ }
283
+
284
+ private get topicsTemplate() {
285
+ if (!this.model?.subjects || this.model.subjects.length === 0) {
286
+ return nothing;
287
+ }
288
+ return html`
289
+ <div id="topics" class="metadata">
290
+ ${this.labelTemplate(msg('Topics'))}
291
+ ${join(
292
+ map(this.model.subjects, id => this.searchLink('subject', id)),
293
+ ', ',
294
+ )}
295
+ </div>
296
+ `;
297
+ }
298
+
299
+ private get collectionsTemplate() {
300
+ if (!this.collectionLinks || this.collectionLinks.length === 0) {
301
+ return nothing;
302
+ }
303
+ return html`
304
+ <div id="collections" class="metadata">
305
+ ${this.labelTemplate(msg('Collections'))}
306
+ ${join(this.collectionLinks, ', ')}
307
+ </div>
308
+ `;
309
+ }
310
+
311
+ private get descriptionTemplate() {
312
+ return this.metadataTemplate(
313
+ // Sanitize away any HTML tags and convert line breaks to spaces.
314
+ unsafeHTML(
315
+ DOMPurify.sanitize(this.model?.description?.replace(/\n/g, ' ') ?? ''),
316
+ ),
317
+ '',
318
+ 'description',
319
+ );
320
+ }
321
+
322
+ private get reviewBlockTemplate(): TemplateResult | typeof nothing {
323
+ if (!this.model?.review) return nothing;
324
+
325
+ const { reviewtitle, reviewbody, stars } = this.model.review;
326
+ return html`
327
+ <review-block
328
+ viewsize="list"
329
+ title=${ifDefined(reviewtitle)}
330
+ body=${ifDefined(reviewbody)}
331
+ starRating=${ifDefined(stars)}
332
+ >
333
+ </review-block>
334
+ `;
335
+ }
336
+
337
+ private get textSnippetsTemplate(): TemplateResult | typeof nothing {
338
+ if (!this.hasSnippets) return nothing;
339
+
340
+ return html`<text-snippet-block
341
+ viewsize="list"
342
+ .snippets=${this.model?.snippets}
343
+ ></text-snippet-block>`;
344
+ }
345
+
346
+ private get hasSnippets(): boolean {
347
+ return !!this.model?.snippets?.length;
348
+ }
349
+
350
+ private get webArchivesCaptureDatesTemplate():
351
+ | TemplateResult
352
+ | typeof nothing {
353
+ if (!this.model?.captureDates || !this.model.title) return nothing;
354
+
355
+ return html`
356
+ <ul class="capture-dates">
357
+ ${map(
358
+ this.model.captureDates,
359
+ date =>
360
+ html`<li>
361
+ ${this.displayValueProvider.webArchivesCaptureLink(
362
+ this.model!.title,
363
+ date,
364
+ )}
365
+ </li>`,
366
+ )}
367
+ </ul>
368
+ `;
369
+ }
370
+
371
+ // Utility functions
372
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
373
+ private metadataTemplate(text: any, label = '', id?: string) {
374
+ if (!text) return nothing;
375
+ return html`
376
+ <div id=${ifDefined(id)} class="metadata">
377
+ ${this.labelTemplate(label)} ${text}
378
+ </div>
379
+ `;
380
+ }
381
+
382
+ private labelTemplate(label: string) {
383
+ return html` ${label
384
+ ? html`<span class="label">${label}: </span>`
385
+ : nothing}`;
386
+ }
387
+
388
+ private searchLink(field: string, searchTerm: string) {
389
+ if (!field || !searchTerm) {
390
+ return nothing;
391
+ }
392
+ const query = encodeURIComponent(`${field}:"${searchTerm}"`);
393
+ // No whitespace after closing tag
394
+ // Note: single ' for href='' to wrap " in query var gets changed back by yarn format
395
+ return html`<a
396
+ href="${this.baseNavigationUrl}/search?query=${query}"
397
+ rel="nofollow"
398
+ >
399
+ ${DOMPurify.sanitize(searchTerm)}</a
400
+ >`;
401
+ }
402
+
403
+ private detailsLink(
404
+ identifier?: string,
405
+ text?: string,
406
+ isCollection = false,
407
+ ): TemplateResult | typeof nothing {
408
+ if (!identifier) return nothing;
409
+
410
+ const linkText = text ?? identifier;
411
+ const linkHref = this.displayValueProvider.itemPageUrl(
412
+ identifier,
413
+ isCollection,
414
+ );
415
+
416
+ return html`<a href=${linkHref}> ${DOMPurify.sanitize(linkText)} </a>`;
417
+ }
418
+
419
+ /** The URL of this item's mediatype collection, if defined. */
420
+ private get mediatypeURL(): string | typeof nothing {
421
+ // NB: baseNavigationUrl can be an empty string
422
+ if (this.baseNavigationUrl === undefined || !this.model?.mediatype)
423
+ return nothing;
424
+
425
+ // Need special handling for certain mediatypes that don't have a top-level collection page
426
+ switch (this.model.mediatype) {
427
+ case 'collection':
428
+ return `${this.baseNavigationUrl}/search?query=mediatype:collection&sort=-downloads`;
429
+ case 'account':
430
+ return nothing;
431
+ default:
432
+ return this.displayValueProvider.itemPageUrl(
433
+ this.model.mediatype,
434
+ true,
435
+ );
436
+ }
437
+ }
438
+
439
+ protected updated(changed: PropertyValues): void {
440
+ if (changed.has('model') || changed.has('collectionTitles')) {
441
+ this.buildCollectionLinks();
442
+ }
443
+ }
444
+
445
+ private async buildCollectionLinks() {
446
+ if (!this.model?.collections || this.model.collections.length === 0) {
447
+ return;
448
+ }
449
+
450
+ // Note: quirk of Lit: need to replace collectionLinks array,
451
+ // otherwise it will not re-render. Can't simply alter the array.
452
+ this.collectionLinks = [];
453
+ const newCollectionLinks: (TemplateResult | typeof nothing)[] = [];
454
+ for (const collection of this.model.collections) {
455
+ // Don't include favorites or collections that are meant to be suppressed
456
+ if (
457
+ !suppressedCollections[collection] &&
458
+ !collection.startsWith('fav-')
459
+ ) {
460
+ newCollectionLinks.push(
461
+ this.detailsLink(
462
+ collection,
463
+ this.collectionTitles?.get(collection) ?? collection,
464
+ true,
465
+ ),
466
+ );
467
+ }
468
+ }
469
+ this.collectionLinks = newCollectionLinks;
470
+ }
471
+
472
+ /*
473
+ * TODO: fix field names to match model in src/collection-browser.ts
474
+ * private get dateSortSelector()
475
+ * @see src/models.ts
476
+ */
477
+ private get date(): Date | undefined {
478
+ switch (this.effectiveSort?.field) {
479
+ case 'date':
480
+ return this.model?.datePublished;
481
+ case 'reviewdate':
482
+ return this.model?.dateReviewed;
483
+ case 'addeddate':
484
+ return this.model?.dateAdded;
485
+ default:
486
+ return this.model?.dateArchived; // publicdate
487
+ }
488
+ }
489
+
490
+ /**
491
+ * Returns the active sort param if one is set, or the default sort param otherwise.
492
+ */
493
+ private get effectiveSort(): SortParam | null {
494
+ return this.sortParam ?? this.defaultSortParam;
495
+ }
496
+
497
+ private get classSize(): string {
498
+ if (
499
+ this.mobileBreakpoint &&
500
+ this.currentWidth &&
501
+ this.currentWidth < this.mobileBreakpoint
502
+ ) {
503
+ return 'mobile';
504
+ }
505
+ return 'desktop';
506
+ }
507
+
508
+ private get formatSize(): NumberFormat {
509
+ if (
510
+ this.mobileBreakpoint &&
511
+ this.currentWidth &&
512
+ this.currentWidth < this.mobileBreakpoint
513
+ ) {
514
+ return 'short';
515
+ }
516
+ return 'long';
517
+ }
518
+
519
+ static get styles() {
520
+ return [
521
+ tileActionStyles,
522
+ css`
523
+ html {
524
+ font-size: unset;
525
+ }
526
+
527
+ div {
528
+ font-size: 14px;
529
+ }
530
+
531
+ div a {
532
+ text-decoration: none;
533
+ }
534
+
535
+ div a:link {
536
+ color: var(--ia-theme-link-color, #4b64ff);
537
+ }
538
+
539
+ .label {
540
+ font-weight: bold;
541
+ }
542
+
543
+ #list-line.mobile {
544
+ --infiniteScrollerRowGap: 20px;
545
+ --infiniteScrollerRowHeight: auto;
546
+ }
547
+
548
+ #list-line.desktop {
549
+ --infiniteScrollerRowGap: 30px;
550
+ --infiniteScrollerRowHeight: auto;
551
+ }
552
+
553
+ /* fields */
554
+ #icon-right {
555
+ width: 20px;
556
+ padding-top: 5px;
557
+ --iconHeight: 20px;
558
+ --iconWidth: 20px;
559
+ --iconTextAlign: right;
560
+ margin-top: -8px;
561
+ text-align: right;
562
+ }
563
+
564
+ #title {
565
+ color: #4b64ff;
566
+ text-decoration: none;
567
+ font-size: 22px;
568
+ font-weight: bold;
569
+ /* align top of text with image */
570
+ line-height: 25px;
571
+ margin-top: -4px;
572
+ padding-bottom: 2px;
573
+ flex-grow: 1;
574
+
575
+ display: -webkit-box;
576
+ -webkit-box-orient: vertical;
577
+ -webkit-line-clamp: 3;
578
+ overflow: hidden;
579
+ overflow-wrap: anywhere;
580
+ }
581
+
582
+ .metadata {
583
+ line-height: 20px;
584
+ }
585
+
586
+ #description,
587
+ #creator,
588
+ #topics,
589
+ #source {
590
+ text-align: left;
591
+ overflow: hidden;
592
+ text-overflow: ellipsis;
593
+ -webkit-box-orient: vertical;
594
+ display: -webkit-box;
595
+ word-break: break-word;
596
+ -webkit-line-clamp: 3; /* number of lines to show */
597
+ line-clamp: 3;
598
+
599
+ /*
600
+ * Safari doesn't always respect the line-clamping rules above,
601
+ * so we add this to ensure these fields still get truncated
602
+ */
603
+ max-height: 60px;
604
+ }
605
+
606
+ #collections {
607
+ display: -webkit-box;
608
+ -webkit-box-orient: vertical;
609
+ -webkit-line-clamp: 3;
610
+ overflow: hidden;
611
+ overflow-wrap: anywhere;
612
+ }
613
+
614
+ #collections > a {
615
+ display: inline-block;
616
+ }
617
+
618
+ #icon {
619
+ padding-top: 5px;
620
+ }
621
+
622
+ #description {
623
+ padding-top: 10px;
624
+ }
625
+
626
+ /* Top level container */
627
+ #list-line {
628
+ display: flex;
629
+ }
630
+
631
+ #list-line.mobile {
632
+ flex-direction: column;
633
+ }
634
+
635
+ #list-line.desktop {
636
+ column-gap: 10px;
637
+ }
638
+
639
+ #list-line-top {
640
+ display: flex;
641
+ column-gap: 7px;
642
+ }
643
+
644
+ #list-line-bottom {
645
+ padding-top: 4px;
646
+ }
647
+
648
+ #list-line-right,
649
+ #list-line-top,
650
+ #list-line-bottom {
651
+ width: 100%;
652
+ }
653
+
654
+ /*
655
+ * If the container becomes very tiny, don't let the thumbnail side take
656
+ * up too much space. Shouldn't make a difference on ordinary viewport sizes.
657
+ */
658
+ #list-line-left {
659
+ max-width: 25%;
660
+
661
+ display: flex;
662
+ flex-direction: column;
663
+ row-gap: 5px;
664
+ }
665
+
666
+ div a:hover {
667
+ text-decoration: underline;
668
+ }
669
+
670
+ /* Lines containing multiple div as row */
671
+ #item-line,
672
+ #dates-line,
673
+ #views-line,
674
+ #title-line {
675
+ display: flex;
676
+ flex-direction: row;
677
+ column-gap: 10px;
678
+ }
679
+
680
+ /*
681
+ * With the exception of the title line, allow these to wrap if
682
+ * the space becomes too small to accommodate them together.
683
+ *
684
+ * The title line is excluded because it contains the mediatype icon
685
+ * which we don't want to wrap.
686
+ */
687
+ #item-line,
688
+ #dates-line,
689
+ #views-line {
690
+ flex-wrap: wrap;
691
+ }
692
+
693
+ .capture-dates {
694
+ margin: 0;
695
+ padding: 0;
696
+ list-style-type: none;
697
+ }
698
+
699
+ .capture-dates a:link {
700
+ text-decoration: none;
701
+ color: var(--ia-theme-link-color, #4b64ff);
702
+ }
703
+ .capture-dates a:hover {
704
+ text-decoration: underline;
705
+ }
706
+
707
+ /*
708
+ * Tile-list (extended) action row sits under the thumbnail in the left
709
+ * column. The image-block above already has its own bottom padding via
710
+ * the parent's row-gap, so we don't need extra spacing here.
711
+ */
712
+ .tile-actions.list-detail {
713
+ width: 100%;
714
+ }
715
+ `,
716
+ ];
717
+ }
718
+ }