@internetarchive/collection-browser 4.7.0 → 4.8.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.
- package/.husky/pre-commit +0 -0
- package/dist/src/app-root.js +0 -2
- package/dist/src/app-root.js.map +1 -1
- package/dist/src/assets/img/icons/check.d.ts +2 -0
- package/dist/src/assets/img/icons/check.js +5 -0
- package/dist/src/assets/img/icons/check.js.map +1 -0
- package/dist/src/collection-facets/facet-row-template.d.ts +38 -0
- package/dist/src/collection-facets/facet-row-template.js +200 -0
- package/dist/src/collection-facets/facet-row-template.js.map +1 -0
- package/dist/src/collection-facets/facet-row.js +11 -186
- package/dist/src/collection-facets/facet-row.js.map +1 -1
- package/dist/src/collection-facets/models.d.ts +7 -2
- package/dist/src/collection-facets/models.js +7 -2
- package/dist/src/collection-facets/models.js.map +1 -1
- package/dist/src/collection-facets/more-facets-content.d.ts +87 -21
- package/dist/src/collection-facets/more-facets-content.js +477 -200
- package/dist/src/collection-facets/more-facets-content.js.map +1 -1
- package/dist/src/collection-facets/more-facets-scroller.d.ts +85 -0
- package/dist/src/collection-facets/more-facets-scroller.js +428 -0
- package/dist/src/collection-facets/more-facets-scroller.js.map +1 -0
- package/dist/src/collection-facets/page-window.d.ts +73 -0
- package/dist/src/collection-facets/page-window.js +202 -0
- package/dist/src/collection-facets/page-window.js.map +1 -0
- package/dist/src/collection-facets/toggle-switch.js +1 -0
- package/dist/src/collection-facets/toggle-switch.js.map +1 -1
- package/dist/src/models.d.ts +4 -0
- package/dist/src/models.js +16 -0
- package/dist/src/models.js.map +1 -1
- package/dist/src/utils/log.d.ts +1 -4
- package/dist/src/utils/normalize-filter-text.d.ts +28 -0
- package/dist/src/utils/normalize-filter-text.js +35 -0
- package/dist/src/utils/normalize-filter-text.js.map +1 -0
- package/dist/test/collection-facets/more-facets-content.test.js +367 -17
- package/dist/test/collection-facets/more-facets-content.test.js.map +1 -1
- package/dist/test/collection-facets/more-facets-scroller.test.d.ts +1 -0
- package/dist/test/collection-facets/more-facets-scroller.test.js +288 -0
- package/dist/test/collection-facets/more-facets-scroller.test.js.map +1 -0
- package/dist/test/collection-facets/page-window.test.d.ts +1 -0
- package/dist/test/collection-facets/page-window.test.js +175 -0
- package/dist/test/collection-facets/page-window.test.js.map +1 -0
- package/dist/test/mocks/mock-search-responses.d.ts +6 -0
- package/dist/test/mocks/mock-search-responses.js +52 -0
- package/dist/test/mocks/mock-search-responses.js.map +1 -1
- package/dist/test/mocks/mock-search-service.js +2 -1
- package/dist/test/mocks/mock-search-service.js.map +1 -1
- package/dist/test/utils/normalize-filter-text.test.d.ts +1 -0
- package/dist/test/utils/normalize-filter-text.test.js +69 -0
- package/dist/test/utils/normalize-filter-text.test.js.map +1 -0
- package/docs/design/column-virtualization.md +214 -0
- package/package.json +20 -16
- package/src/app-root.ts +0 -2
- package/src/assets/img/icons/check.ts +5 -0
- package/src/collection-facets/facet-row-template.ts +242 -0
- package/src/collection-facets/facet-row.ts +15 -202
- package/src/collection-facets/models.ts +8 -2
- package/src/collection-facets/more-facets-content.ts +528 -221
- package/src/collection-facets/more-facets-scroller.ts +485 -0
- package/src/collection-facets/page-window.ts +247 -0
- package/src/collection-facets/toggle-switch.ts +1 -0
- package/src/models.ts +17 -0
- package/src/utils/normalize-filter-text.ts +54 -0
- package/test/collection-facets/more-facets-content.test.ts +509 -24
- package/test/collection-facets/more-facets-scroller.test.ts +401 -0
- package/test/collection-facets/page-window.test.ts +208 -0
- package/test/mocks/mock-search-responses.ts +56 -0
- package/test/mocks/mock-search-service.ts +2 -0
- package/test/utils/normalize-filter-text.test.ts +87 -0
- package/web-test-runner.config.mjs +7 -2
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/.editorconfig +0 -29
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/.github/workflows/ci.yml +0 -27
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/.github/workflows/gh-pages-main.yml +0 -39
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/.github/workflows/npm-publish.yml +0 -39
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/.github/workflows/pr-preview.yml +0 -38
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/.husky/pre-commit +0 -1
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/.prettierignore +0 -1
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/LICENSE +0 -661
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/README.md +0 -84
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/eslint.config.mjs +0 -53
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/index.html +0 -24
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/index.ts +0 -29
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/local.archive.org.cert +0 -86
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/local.archive.org.key +0 -27
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/package.json +0 -120
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/renovate.json +0 -6
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/app-root.ts +0 -1284
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/arrow-left.ts +0 -10
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/arrow-right.ts +0 -10
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/chevron.ts +0 -4
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/close-circle-dark.ts +0 -5
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/contract.ts +0 -9
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/empty-query.ts +0 -5
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/expand.ts +0 -9
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/eye-closed.ts +0 -5
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/eye.ts +0 -5
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/favorite-filled.ts +0 -10
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/favorite-unfilled.ts +0 -9
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/filter.ts +0 -10
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/login-required.ts +0 -18
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/account.ts +0 -14
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/audio.ts +0 -14
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/collection.ts +0 -12
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/data.ts +0 -15
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/etree.ts +0 -14
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/film.ts +0 -14
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/images.ts +0 -13
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/radio.ts +0 -15
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/search.ts +0 -14
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/software.ts +0 -13
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/texts.ts +0 -13
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/tv-commercial.ts +0 -12
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/tv-fact-check.ts +0 -12
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/tv-quote.ts +0 -12
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/tv.ts +0 -14
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/video.ts +0 -14
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/mediatype/web.ts +0 -13
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/null-result.ts +0 -5
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/quote.ts +0 -7
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/restricted.ts +0 -13
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/reviews.ts +0 -11
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/upload.ts +0 -12
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/assets/img/icons/views.ts +0 -11
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/circular-activity-indicator.ts +0 -64
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-browser.ts +0 -3165
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/facet-row.ts +0 -309
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/facet-tombstone-row.ts +0 -40
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/facets-template.ts +0 -85
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/models.ts +0 -10
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/more-facets-content.ts +0 -644
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/more-facets-pagination.ts +0 -294
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/dedupe.ts +0 -44
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/heuristics/browser-language/browser-language-heuristic.ts +0 -27
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/heuristics/index.ts +0 -3
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/heuristics/query-keywords/query-keywords-heuristic.ts +0 -17
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/heuristics/query-keywords/query-keywords-map.ts +0 -70
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/heuristics/wikidata/wikidata-entity-map.ts +0 -79
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/heuristics/wikidata/wikidata-heuristic.ts +0 -93
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/models.ts +0 -36
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/smart-facet-bar.ts +0 -437
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/smart-facet-button.ts +0 -145
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/smart-facet-dropdown.ts +0 -185
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/smart-facet-equals.ts +0 -16
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/smart-facets/smart-facet-heuristics.ts +0 -26
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets/toggle-switch.ts +0 -174
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/collection-facets.ts +0 -1013
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/data-source/collection-browser-data-source-interface.ts +0 -351
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/data-source/collection-browser-data-source.ts +0 -1474
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/data-source/collection-browser-query-state.ts +0 -60
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/data-source/models.ts +0 -56
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/empty-placeholder.ts +0 -192
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/expanded-date-picker.ts +0 -191
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/language-code-handler/language-code-handler.ts +0 -64
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/language-code-handler/language-code-mapping.ts +0 -564
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/manage/manage-bar.ts +0 -276
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/manage/remove-items-modal-content.ts +0 -102
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/mediatype/mediatype-config.ts +0 -146
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/models.ts +0 -895
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/restoration-state-handler.ts +0 -550
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/sort-filter-bar/alpha-bar-tooltip.ts +0 -53
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/sort-filter-bar/alpha-bar.ts +0 -252
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/sort-filter-bar/img/compact.ts +0 -5
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/sort-filter-bar/img/list.ts +0 -5
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/sort-filter-bar/img/sort-toggle-disabled.ts +0 -15
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/sort-filter-bar/img/sort-toggle-down.ts +0 -17
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/sort-filter-bar/img/sort-toggle-up.ts +0 -17
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/sort-filter-bar/img/sort-triangle.ts +0 -5
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/sort-filter-bar/img/tile.ts +0 -5
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/sort-filter-bar/sort-filter-bar.ts +0 -733
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/styles/ia-button.ts +0 -139
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/styles/item-image-styles.ts +0 -124
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/styles/sr-only.ts +0 -18
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/styles/tile-action-styles.ts +0 -59
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/base-tile-component.ts +0 -124
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/collection-browser-loading-tile.ts +0 -26
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/grid/account-tile.ts +0 -113
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/grid/collection-tile.ts +0 -184
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/grid/item-tile.ts +0 -347
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/grid/search-tile.ts +0 -90
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/grid/styles/tile-grid-shared-styles.ts +0 -130
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/grid/tile-stats.ts +0 -211
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/hover/hover-pane-controller.ts +0 -638
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/hover/tile-hover-pane.ts +0 -184
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/image-block.ts +0 -162
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/item-image.ts +0 -214
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/list/tile-list-compact-header.ts +0 -112
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/list/tile-list-compact.ts +0 -278
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/list/tile-list.ts +0 -718
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/models.ts +0 -21
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/overlay/icon-overlay.ts +0 -57
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/overlay/text-overlay.ts +0 -79
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/review-block.ts +0 -130
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/text-snippet-block.ts +0 -132
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/tile-dispatcher.ts +0 -637
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/tile-display-value-provider.ts +0 -133
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/tiles/tile-mediatype-icon.ts +0 -133
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/utils/analytics-events.ts +0 -29
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/utils/array-equals.ts +0 -8
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/utils/collapse-repeated-quotes.ts +0 -13
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/utils/date-filter-field.ts +0 -11
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/utils/facet-utils.ts +0 -183
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/utils/format-count.ts +0 -95
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/utils/format-date.ts +0 -62
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/utils/format-unit-size.ts +0 -43
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/utils/local-date-from-utc.ts +0 -15
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/utils/log.ts +0 -14
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/utils/resolve-mediatype.ts +0 -26
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/src/utils/sha1.ts +0 -9
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/collection-browser.test.ts +0 -2639
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/collection-facets/facet-row.test.ts +0 -421
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/collection-facets/facets-template.test.ts +0 -139
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/collection-facets/more-facets-content.test.ts +0 -231
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/collection-facets/more-facets-pagination.test.ts +0 -201
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/collection-facets/toggle-switch.test.ts +0 -164
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/collection-facets.test.ts +0 -928
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/data-source/collection-browser-data-source.test.ts +0 -193
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/empty-placeholder.test.ts +0 -88
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/expanded-date-picker.test.ts +0 -201
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/icon-overlay.test.ts +0 -38
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/image-block.test.ts +0 -247
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/item-image.test.ts +0 -220
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/manage/manage-bar.test.ts +0 -347
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/manage/remove-items-modal-content.test.ts +0 -81
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/mediatype-config.test.ts +0 -11
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/mocks/mock-analytics-handler.ts +0 -30
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/mocks/mock-search-responses.ts +0 -1364
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/mocks/mock-search-service.ts +0 -134
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/restoration-state-handler.test.ts +0 -480
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/review-block.test.ts +0 -62
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/sort-filter-bar/alpha-bar-tooltip.test.ts +0 -17
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/sort-filter-bar/alpha-bar.test.ts +0 -101
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/sort-filter-bar/sort-filter-bar.test.ts +0 -443
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/text-overlay.test.ts +0 -55
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/text-snippet-block.test.ts +0 -85
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tile-stats.test.ts +0 -191
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tiles/grid/account-tile.test.ts +0 -121
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tiles/grid/collection-tile.test.ts +0 -114
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tiles/grid/item-tile.test.ts +0 -520
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tiles/grid/search-tile.test.ts +0 -75
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tiles/hover/hover-pane-controller.test.ts +0 -482
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tiles/hover/tile-hover-pane.test.ts +0 -80
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tiles/list/tile-list-compact-header.test.ts +0 -43
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tiles/list/tile-list-compact.test.ts +0 -282
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tiles/list/tile-list.test.ts +0 -576
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tiles/tile-dispatcher.test.ts +0 -320
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tiles/tile-display-value-provider.test.ts +0 -172
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/tiles/tile-mediatype-icon.test.ts +0 -160
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/utils/array-equals.test.ts +0 -31
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/utils/format-count.test.ts +0 -32
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/utils/format-date.test.ts +0 -89
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/utils/format-unit-size.test.ts +0 -21
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/test/utils/local-date-from-utc.test.ts +0 -37
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/tsconfig.json +0 -25
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/types/dompurify.d.ts +0 -1
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/vite.config.ts +0 -29
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/web-dev-server.config.mjs +0 -30
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/web-test-runner.config.mjs +0 -52
- package/.claude/worktrees/WEBDEV-8677-bump-field-parsers/yarn.lock +0 -5965
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/.editorconfig +0 -29
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/.github/workflows/ci.yml +0 -29
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/.github/workflows/gh-pages-main.yml +0 -41
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/.github/workflows/npm-publish.yml +0 -49
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/.github/workflows/pr-preview.yml +0 -40
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/.husky/pre-commit +0 -1
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/.prettierignore +0 -1
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/LICENSE +0 -661
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/README.md +0 -68
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/eslint.config.mjs +0 -53
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/index.html +0 -24
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/index.ts +0 -29
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/local.archive.org.cert +0 -86
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/local.archive.org.key +0 -27
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/package.json +0 -129
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/pnpm-lock.yaml +0 -7366
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/pnpm-workspace.yaml +0 -46
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/renovate.json +0 -6
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/app-root.ts +0 -1284
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/arrow-left.ts +0 -10
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/arrow-right.ts +0 -10
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/chevron.ts +0 -4
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/close-circle-dark.ts +0 -5
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/contract.ts +0 -9
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/empty-query.ts +0 -5
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/expand.ts +0 -9
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/eye-closed.ts +0 -5
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/eye.ts +0 -5
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/favorite-filled.ts +0 -10
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/favorite-unfilled.ts +0 -9
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/filter.ts +0 -10
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/login-required.ts +0 -18
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/mediatype/account.ts +0 -14
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/mediatype/audio.ts +0 -14
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/mediatype/collection.ts +0 -12
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/mediatype/data.ts +0 -15
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/mediatype/etree.ts +0 -14
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/mediatype/film.ts +0 -14
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/mediatype/images.ts +0 -13
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/mediatype/radio.ts +0 -15
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/mediatype/search.ts +0 -14
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/mediatype/software.ts +0 -13
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/mediatype/texts.ts +0 -13
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/mediatype/tv-commercial.ts +0 -12
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/mediatype/tv-fact-check.ts +0 -12
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/mediatype/tv-quote.ts +0 -12
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/mediatype/tv.ts +0 -14
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/mediatype/video.ts +0 -14
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/mediatype/web.ts +0 -13
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/null-result.ts +0 -5
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/quote.ts +0 -7
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/restricted.ts +0 -13
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/reviews.ts +0 -11
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/upload.ts +0 -12
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/assets/img/icons/views.ts +0 -11
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/circular-activity-indicator.ts +0 -64
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/collection-browser.ts +0 -3165
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/collection-facets/facet-row.ts +0 -309
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/collection-facets/facet-tombstone-row.ts +0 -40
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/collection-facets/facets-template.ts +0 -85
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/collection-facets/models.ts +0 -10
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/collection-facets/more-facets-content.ts +0 -644
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/collection-facets/more-facets-pagination.ts +0 -294
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/collection-facets/smart-facets/dedupe.ts +0 -44
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/collection-facets/smart-facets/heuristics/browser-language/browser-language-heuristic.ts +0 -27
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/collection-facets/smart-facets/heuristics/index.ts +0 -3
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/collection-facets/smart-facets/heuristics/query-keywords/query-keywords-heuristic.ts +0 -17
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/collection-facets/smart-facets/heuristics/query-keywords/query-keywords-map.ts +0 -70
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/collection-facets/smart-facets/heuristics/wikidata/wikidata-entity-map.ts +0 -79
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/collection-facets/smart-facets/heuristics/wikidata/wikidata-heuristic.ts +0 -93
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/collection-facets/smart-facets/models.ts +0 -36
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/collection-facets/smart-facets/smart-facet-bar.ts +0 -437
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/collection-facets/smart-facets/smart-facet-button.ts +0 -145
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/collection-facets/smart-facets/smart-facet-dropdown.ts +0 -185
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/collection-facets/smart-facets/smart-facet-equals.ts +0 -16
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/collection-facets/smart-facets/smart-facet-heuristics.ts +0 -26
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/collection-facets/toggle-switch.ts +0 -174
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/collection-facets.ts +0 -1013
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/data-source/collection-browser-data-source-interface.ts +0 -351
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/data-source/collection-browser-data-source.ts +0 -1474
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/data-source/collection-browser-query-state.ts +0 -60
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/data-source/models.ts +0 -56
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/empty-placeholder.ts +0 -192
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/expanded-date-picker.ts +0 -191
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/language-code-handler/language-code-handler.ts +0 -64
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/language-code-handler/language-code-mapping.ts +0 -564
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/manage/manage-bar.ts +0 -276
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/manage/remove-items-modal-content.ts +0 -102
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/mediatype/mediatype-config.ts +0 -146
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/models.ts +0 -895
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/restoration-state-handler.ts +0 -550
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/sort-filter-bar/alpha-bar-tooltip.ts +0 -53
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/sort-filter-bar/alpha-bar.ts +0 -252
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/sort-filter-bar/img/compact.ts +0 -5
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/sort-filter-bar/img/list.ts +0 -5
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/sort-filter-bar/img/sort-toggle-disabled.ts +0 -15
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/sort-filter-bar/img/sort-toggle-down.ts +0 -17
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/sort-filter-bar/img/sort-toggle-up.ts +0 -17
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/sort-filter-bar/img/sort-triangle.ts +0 -5
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/sort-filter-bar/img/tile.ts +0 -5
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/sort-filter-bar/sort-filter-bar.ts +0 -733
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/styles/ia-button.ts +0 -139
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/styles/item-image-styles.ts +0 -124
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/styles/sr-only.ts +0 -18
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/styles/tile-action-styles.ts +0 -59
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/tiles/base-tile-component.ts +0 -124
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/tiles/collection-browser-loading-tile.ts +0 -26
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/tiles/grid/account-tile.ts +0 -113
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/tiles/grid/collection-tile.ts +0 -184
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/tiles/grid/item-tile.ts +0 -347
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/tiles/grid/search-tile.ts +0 -90
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/tiles/grid/styles/tile-grid-shared-styles.ts +0 -130
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/tiles/grid/tile-stats.ts +0 -211
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/tiles/hover/hover-pane-controller.ts +0 -638
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/tiles/hover/tile-hover-pane.ts +0 -184
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/tiles/image-block.ts +0 -162
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/tiles/item-image.ts +0 -214
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/tiles/list/tile-list-compact-header.ts +0 -112
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/tiles/list/tile-list-compact.ts +0 -278
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/tiles/list/tile-list.ts +0 -718
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/tiles/models.ts +0 -21
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/tiles/overlay/icon-overlay.ts +0 -57
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/tiles/overlay/text-overlay.ts +0 -79
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/tiles/review-block.ts +0 -130
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/tiles/text-snippet-block.ts +0 -132
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/tiles/tile-dispatcher.ts +0 -637
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/tiles/tile-display-value-provider.ts +0 -133
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/tiles/tile-mediatype-icon.ts +0 -133
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/utils/analytics-events.ts +0 -29
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/utils/array-equals.ts +0 -8
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/utils/collapse-repeated-quotes.ts +0 -13
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/utils/date-filter-field.ts +0 -11
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/utils/facet-utils.ts +0 -183
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/utils/format-count.ts +0 -95
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/utils/format-date.ts +0 -62
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/utils/format-unit-size.ts +0 -43
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/utils/local-date-from-utc.ts +0 -15
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/utils/log.ts +0 -14
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/utils/resolve-mediatype.ts +0 -26
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/src/utils/sha1.ts +0 -9
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/collection-browser.test.ts +0 -2639
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/collection-facets/facet-row.test.ts +0 -421
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/collection-facets/facets-template.test.ts +0 -139
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/collection-facets/more-facets-content.test.ts +0 -231
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/collection-facets/more-facets-pagination.test.ts +0 -201
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/collection-facets/toggle-switch.test.ts +0 -164
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/collection-facets.test.ts +0 -928
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/data-source/collection-browser-data-source.test.ts +0 -193
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/empty-placeholder.test.ts +0 -88
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/expanded-date-picker.test.ts +0 -201
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/icon-overlay.test.ts +0 -38
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/image-block.test.ts +0 -247
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/item-image.test.ts +0 -220
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/manage/manage-bar.test.ts +0 -347
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/manage/remove-items-modal-content.test.ts +0 -81
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/mediatype-config.test.ts +0 -11
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/mocks/mock-analytics-handler.ts +0 -30
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/mocks/mock-search-responses.ts +0 -1364
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/mocks/mock-search-service.ts +0 -134
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/restoration-state-handler.test.ts +0 -480
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/review-block.test.ts +0 -62
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/sort-filter-bar/alpha-bar-tooltip.test.ts +0 -17
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/sort-filter-bar/alpha-bar.test.ts +0 -101
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/sort-filter-bar/sort-filter-bar.test.ts +0 -443
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/text-overlay.test.ts +0 -55
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/text-snippet-block.test.ts +0 -85
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/tile-stats.test.ts +0 -191
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/tiles/grid/account-tile.test.ts +0 -121
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/tiles/grid/collection-tile.test.ts +0 -114
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/tiles/grid/item-tile.test.ts +0 -520
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/tiles/grid/search-tile.test.ts +0 -75
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/tiles/hover/hover-pane-controller.test.ts +0 -482
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/tiles/hover/tile-hover-pane.test.ts +0 -80
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/tiles/list/tile-list-compact-header.test.ts +0 -43
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/tiles/list/tile-list-compact.test.ts +0 -282
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/tiles/list/tile-list.test.ts +0 -576
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/tiles/tile-dispatcher.test.ts +0 -320
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/tiles/tile-display-value-provider.test.ts +0 -172
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/tiles/tile-mediatype-icon.test.ts +0 -160
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/utils/array-equals.test.ts +0 -31
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/utils/format-count.test.ts +0 -32
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/utils/format-date.test.ts +0 -89
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/utils/format-unit-size.test.ts +0 -21
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/test/utils/local-date-from-utc.test.ts +0 -37
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/tsconfig.json +0 -25
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/types/dompurify.d.ts +0 -1
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/vite.config.ts +0 -29
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/web-dev-server.config.mjs +0 -30
- package/.claude/worktrees/WEBDEV-9127-fix-publish-dist-tag/web-test-runner.config.mjs +0 -52
- package/dist/src/collection-facets/more-facets-pagination.d.ts +0 -36
- package/dist/src/collection-facets/more-facets-pagination.js +0 -260
- package/dist/src/collection-facets/more-facets-pagination.js.map +0 -1
- package/dist/test/collection-facets/more-facets-pagination.test.d.ts +0 -1
- package/dist/test/collection-facets/more-facets-pagination.test.js +0 -126
- package/dist/test/collection-facets/more-facets-pagination.test.js.map +0 -1
- package/src/collection-facets/more-facets-pagination.ts +0 -294
- package/test/collection-facets/more-facets-pagination.test.ts +0 -201
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
const supportsScrollEnd = 'onscrollend' in window;
|
|
2
|
+
/**
|
|
3
|
+
* Windowing controller for a horizontal scroller of fixed-width columns that
|
|
4
|
+
* snaps to page boundaries. Tracks which pages should be in the DOM (`first`
|
|
5
|
+
* through `last`) and which page the scroller last came to rest on.
|
|
6
|
+
*
|
|
7
|
+
* All positions are arithmetic on `colWidth`; the only measurement is the
|
|
8
|
+
* scroller's width, which comes from a ResizeObserver.
|
|
9
|
+
*
|
|
10
|
+
* See docs/design/column-virtualization.md before changing this, especially
|
|
11
|
+
* its invariants.
|
|
12
|
+
*/
|
|
13
|
+
export class PageWindow {
|
|
14
|
+
constructor(host, cfg) {
|
|
15
|
+
this.host = host;
|
|
16
|
+
this.cfg = cfg;
|
|
17
|
+
/** Index of the first mounted page. */
|
|
18
|
+
this.first = 0;
|
|
19
|
+
/** Index of the last mounted page, or -1 when nothing is mounted. */
|
|
20
|
+
this.last = -1;
|
|
21
|
+
/** How many columns fit in the scroller, derived from its measured width. */
|
|
22
|
+
this.colsPerPage = 1;
|
|
23
|
+
/** The page the scroller last came to rest on. */
|
|
24
|
+
this.currentPage = 0;
|
|
25
|
+
this.viewportW = 0;
|
|
26
|
+
this.frame = 0;
|
|
27
|
+
this.landFrame = 0;
|
|
28
|
+
this.endTimer = 0;
|
|
29
|
+
/** Whether to re-check the resting page once the host has re-rendered. */
|
|
30
|
+
this.relandAfterUpdate = false;
|
|
31
|
+
/** Ref callback for the scroll container. */
|
|
32
|
+
this.attach = (el) => {
|
|
33
|
+
const next = el instanceof HTMLElement ? el : undefined;
|
|
34
|
+
if (next === this.scroller)
|
|
35
|
+
return;
|
|
36
|
+
this.detach();
|
|
37
|
+
if (!next)
|
|
38
|
+
return;
|
|
39
|
+
this.scroller = next;
|
|
40
|
+
next.addEventListener('scroll', this.onScroll, { passive: true });
|
|
41
|
+
if (supportsScrollEnd) {
|
|
42
|
+
next.addEventListener('scrollend', this.onScrollEnd);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
next.addEventListener('scroll', this.onScrollIdle, { passive: true });
|
|
46
|
+
}
|
|
47
|
+
this.ro = new ResizeObserver(([e]) => this.onResize(e.contentRect.width));
|
|
48
|
+
this.ro.observe(next);
|
|
49
|
+
};
|
|
50
|
+
this.onScroll = () => {
|
|
51
|
+
if (this.frame)
|
|
52
|
+
return;
|
|
53
|
+
this.frame = requestAnimationFrame(() => {
|
|
54
|
+
this.frame = 0;
|
|
55
|
+
this.recompute();
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
/** Fallback for browsers without `scrollend`: treat 120ms of quiet as rest. */
|
|
59
|
+
this.onScrollIdle = () => {
|
|
60
|
+
clearTimeout(this.endTimer);
|
|
61
|
+
this.endTimer = window.setTimeout(this.onScrollEnd, 120);
|
|
62
|
+
};
|
|
63
|
+
this.onScrollEnd = () => {
|
|
64
|
+
this.land();
|
|
65
|
+
};
|
|
66
|
+
host.addController(this);
|
|
67
|
+
}
|
|
68
|
+
get pageWidth() {
|
|
69
|
+
return this.cfg.colWidth * this.colsPerPage;
|
|
70
|
+
}
|
|
71
|
+
get pageCount() {
|
|
72
|
+
return Math.ceil(this.cfg.total / this.colsPerPage);
|
|
73
|
+
}
|
|
74
|
+
get totalWidth() {
|
|
75
|
+
return this.cfg.colWidth * this.cfg.total;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Width of page `i`. Every page is `pageWidth` except a partial last page,
|
|
79
|
+
* which is trimmed so that nothing extends the scroll area past `totalWidth`.
|
|
80
|
+
*/
|
|
81
|
+
pageSpan(i) {
|
|
82
|
+
return Math.min(this.pageWidth, this.totalWidth - i * this.pageWidth);
|
|
83
|
+
}
|
|
84
|
+
/** Updates the number of columns, e.g. when the dataset is filtered. */
|
|
85
|
+
setTotal(total) {
|
|
86
|
+
if (total === this.cfg.total)
|
|
87
|
+
return;
|
|
88
|
+
this.cfg.total = total;
|
|
89
|
+
this.recompute(true);
|
|
90
|
+
// The sizer hasn't resized yet, so wait for the host to render before
|
|
91
|
+
// reading where the scroller rests.
|
|
92
|
+
this.relandAfterUpdate = true;
|
|
93
|
+
}
|
|
94
|
+
/** Scrolls so that `page` sits at the start of the viewport. */
|
|
95
|
+
scrollToPage(page, behavior = 'auto') {
|
|
96
|
+
const target = Math.max(0, Math.min(page, this.pageCount - 1));
|
|
97
|
+
this.scroller?.scrollTo({ left: target * this.pageWidth, behavior });
|
|
98
|
+
}
|
|
99
|
+
hostUpdated() {
|
|
100
|
+
const el = this.scroller;
|
|
101
|
+
if (!el)
|
|
102
|
+
return;
|
|
103
|
+
// A resize changed the page width. The host has now moved the snap stubs,
|
|
104
|
+
// so put the page that held the anchor column back at the start.
|
|
105
|
+
if (this.realignTo !== undefined) {
|
|
106
|
+
const target = this.realignTo * this.pageWidth;
|
|
107
|
+
// After a layout change WebKit re-snaps to the snap point with the same
|
|
108
|
+
// index as before, which is now a different column. Assigning the
|
|
109
|
+
// position the scroller already has is a no-op that doesn't update that
|
|
110
|
+
// index, so nudge it first.
|
|
111
|
+
if (el.scrollLeft === target)
|
|
112
|
+
el.scrollLeft = target + 1;
|
|
113
|
+
el.scrollLeft = target;
|
|
114
|
+
this.realignTo = undefined;
|
|
115
|
+
this.relandAfterUpdate = true;
|
|
116
|
+
}
|
|
117
|
+
if (this.relandAfterUpdate && !this.landFrame) {
|
|
118
|
+
this.relandAfterUpdate = false;
|
|
119
|
+
// Next frame, so as not to update the host again from inside its update
|
|
120
|
+
this.landFrame = requestAnimationFrame(() => {
|
|
121
|
+
this.landFrame = 0;
|
|
122
|
+
this.land();
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
hostDisconnected() {
|
|
127
|
+
this.detach();
|
|
128
|
+
}
|
|
129
|
+
detach() {
|
|
130
|
+
const el = this.scroller;
|
|
131
|
+
if (!el)
|
|
132
|
+
return;
|
|
133
|
+
el.removeEventListener('scroll', this.onScroll);
|
|
134
|
+
el.removeEventListener('scroll', this.onScrollIdle);
|
|
135
|
+
el.removeEventListener('scrollend', this.onScrollEnd);
|
|
136
|
+
this.ro?.disconnect();
|
|
137
|
+
this.ro = undefined;
|
|
138
|
+
if (this.frame)
|
|
139
|
+
cancelAnimationFrame(this.frame);
|
|
140
|
+
if (this.landFrame)
|
|
141
|
+
cancelAnimationFrame(this.landFrame);
|
|
142
|
+
this.frame = 0;
|
|
143
|
+
this.landFrame = 0;
|
|
144
|
+
clearTimeout(this.endTimer);
|
|
145
|
+
this.scroller = undefined;
|
|
146
|
+
}
|
|
147
|
+
onResize(width) {
|
|
148
|
+
const el = this.scroller;
|
|
149
|
+
if (!el)
|
|
150
|
+
return;
|
|
151
|
+
this.viewportW = width;
|
|
152
|
+
const colsPerPage = Math.max(1, Math.floor(width / this.cfg.colWidth));
|
|
153
|
+
if (colsPerPage === this.colsPerPage) {
|
|
154
|
+
this.recompute();
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
// Columns never move (column c always starts at c * colWidth); only the
|
|
158
|
+
// page boundaries do. Keep the leftmost visible column on screen by
|
|
159
|
+
// realigning to whichever new page contains it.
|
|
160
|
+
const anchorCol = Math.round(el.scrollLeft / this.cfg.colWidth);
|
|
161
|
+
this.colsPerPage = colsPerPage;
|
|
162
|
+
this.realignTo = Math.floor(anchorCol / colsPerPage);
|
|
163
|
+
this.recompute(true);
|
|
164
|
+
}
|
|
165
|
+
recompute(force = false) {
|
|
166
|
+
const el = this.scroller;
|
|
167
|
+
if (!el)
|
|
168
|
+
return;
|
|
169
|
+
const pw = this.pageWidth;
|
|
170
|
+
const buf = this.cfg.buffer ?? 1;
|
|
171
|
+
const left = el.scrollLeft;
|
|
172
|
+
const first = Math.max(0, Math.floor(left / pw) - buf);
|
|
173
|
+
// Floor on both edges, so that first and last shift together at each page
|
|
174
|
+
// boundary rather than one just before it and one just after.
|
|
175
|
+
const last = Math.min(this.pageCount - 1, Math.floor((left + this.viewportW) / pw) + buf);
|
|
176
|
+
// Most scroll events end here: the window only changes at page boundaries
|
|
177
|
+
if (!force && first === this.first && last === this.last)
|
|
178
|
+
return;
|
|
179
|
+
this.first = first;
|
|
180
|
+
this.last = last;
|
|
181
|
+
this.host.requestUpdate();
|
|
182
|
+
}
|
|
183
|
+
/** Records which page the scroller is resting on. */
|
|
184
|
+
land() {
|
|
185
|
+
const el = this.scroller;
|
|
186
|
+
if (!el)
|
|
187
|
+
return;
|
|
188
|
+
const left = el.scrollLeft;
|
|
189
|
+
const maxLeft = this.totalWidth - this.viewportW;
|
|
190
|
+
// A partial last page can't reach its own snap point, so resting at the
|
|
191
|
+
// far end counts as landing on the last page.
|
|
192
|
+
const atEnd = left >= maxLeft - 1;
|
|
193
|
+
const page = atEnd ? this.pageCount - 1 : Math.round(left / this.pageWidth);
|
|
194
|
+
const clamped = Math.max(0, Math.min(page, this.pageCount - 1));
|
|
195
|
+
if (clamped !== this.currentPage) {
|
|
196
|
+
this.currentPage = clamped;
|
|
197
|
+
this.host.requestUpdate();
|
|
198
|
+
}
|
|
199
|
+
this.cfg.onRest?.(clamped);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=page-window.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-window.js","sourceRoot":"","sources":["../../../src/collection-facets/page-window.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController, ReactiveControllerHost } from 'lit';\n\nexport type PageWindowConfig = {\n /** Width in px of every column. Columns are uniform. */\n colWidth: number;\n\n /** Total number of columns in the dataset. */\n total: number;\n\n /** Pages kept mounted on each side of the visible ones. Defaults to 1. */\n buffer?: number;\n\n /**\n * Called each time the scroller comes to rest (or is re-laid out), with the\n * page it rests on. Fires even when that page hasn't changed.\n */\n onRest?: (page: number) => void;\n};\n\nconst supportsScrollEnd = 'onscrollend' in window;\n\n/**\n * Windowing controller for a horizontal scroller of fixed-width columns that\n * snaps to page boundaries. Tracks which pages should be in the DOM (`first`\n * through `last`) and which page the scroller last came to rest on.\n *\n * All positions are arithmetic on `colWidth`; the only measurement is the\n * scroller's width, which comes from a ResizeObserver.\n *\n * See docs/design/column-virtualization.md before changing this, especially\n * its invariants.\n */\nexport class PageWindow implements ReactiveController {\n /** Index of the first mounted page. */\n first = 0;\n\n /** Index of the last mounted page, or -1 when nothing is mounted. */\n last = -1;\n\n /** How many columns fit in the scroller, derived from its measured width. */\n colsPerPage = 1;\n\n /** The page the scroller last came to rest on. */\n currentPage = 0;\n\n private scroller?: HTMLElement;\n\n private viewportW = 0;\n\n private frame = 0;\n\n private landFrame = 0;\n\n private endTimer = 0;\n\n private ro?: ResizeObserver;\n\n /** Page to realign to once the host has re-rendered at a new page width. */\n private realignTo?: number;\n\n /** Whether to re-check the resting page once the host has re-rendered. */\n private relandAfterUpdate = false;\n\n constructor(\n private host: ReactiveControllerHost,\n private cfg: PageWindowConfig,\n ) {\n host.addController(this);\n }\n\n get pageWidth(): number {\n return this.cfg.colWidth * this.colsPerPage;\n }\n\n get pageCount(): number {\n return Math.ceil(this.cfg.total / this.colsPerPage);\n }\n\n get totalWidth(): number {\n return this.cfg.colWidth * this.cfg.total;\n }\n\n /**\n * Width of page `i`. Every page is `pageWidth` except a partial last page,\n * which is trimmed so that nothing extends the scroll area past `totalWidth`.\n */\n pageSpan(i: number): number {\n return Math.min(this.pageWidth, this.totalWidth - i * this.pageWidth);\n }\n\n /** Updates the number of columns, e.g. when the dataset is filtered. */\n setTotal(total: number): void {\n if (total === this.cfg.total) return;\n this.cfg.total = total;\n this.recompute(true);\n // The sizer hasn't resized yet, so wait for the host to render before\n // reading where the scroller rests.\n this.relandAfterUpdate = true;\n }\n\n /** Scrolls so that `page` sits at the start of the viewport. */\n scrollToPage(page: number, behavior: ScrollBehavior = 'auto'): void {\n const target = Math.max(0, Math.min(page, this.pageCount - 1));\n this.scroller?.scrollTo({ left: target * this.pageWidth, behavior });\n }\n\n /** Ref callback for the scroll container. */\n attach = (el?: Element): void => {\n const next = el instanceof HTMLElement ? el : undefined;\n if (next === this.scroller) return;\n this.detach();\n if (!next) return;\n\n this.scroller = next;\n next.addEventListener('scroll', this.onScroll, { passive: true });\n if (supportsScrollEnd) {\n next.addEventListener('scrollend', this.onScrollEnd);\n } else {\n next.addEventListener('scroll', this.onScrollIdle, { passive: true });\n }\n\n this.ro = new ResizeObserver(([e]) => this.onResize(e.contentRect.width));\n this.ro.observe(next);\n };\n\n hostUpdated(): void {\n const el = this.scroller;\n if (!el) return;\n // A resize changed the page width. The host has now moved the snap stubs,\n // so put the page that held the anchor column back at the start.\n if (this.realignTo !== undefined) {\n const target = this.realignTo * this.pageWidth;\n // After a layout change WebKit re-snaps to the snap point with the same\n // index as before, which is now a different column. Assigning the\n // position the scroller already has is a no-op that doesn't update that\n // index, so nudge it first.\n if (el.scrollLeft === target) el.scrollLeft = target + 1;\n el.scrollLeft = target;\n this.realignTo = undefined;\n this.relandAfterUpdate = true;\n }\n if (this.relandAfterUpdate && !this.landFrame) {\n this.relandAfterUpdate = false;\n // Next frame, so as not to update the host again from inside its update\n this.landFrame = requestAnimationFrame(() => {\n this.landFrame = 0;\n this.land();\n });\n }\n }\n\n hostDisconnected(): void {\n this.detach();\n }\n\n private detach(): void {\n const el = this.scroller;\n if (!el) return;\n el.removeEventListener('scroll', this.onScroll);\n el.removeEventListener('scroll', this.onScrollIdle);\n el.removeEventListener('scrollend', this.onScrollEnd);\n this.ro?.disconnect();\n this.ro = undefined;\n if (this.frame) cancelAnimationFrame(this.frame);\n if (this.landFrame) cancelAnimationFrame(this.landFrame);\n this.frame = 0;\n this.landFrame = 0;\n clearTimeout(this.endTimer);\n this.scroller = undefined;\n }\n\n private onResize(width: number): void {\n const el = this.scroller;\n if (!el) return;\n this.viewportW = width;\n\n const colsPerPage = Math.max(1, Math.floor(width / this.cfg.colWidth));\n if (colsPerPage === this.colsPerPage) {\n this.recompute();\n return;\n }\n\n // Columns never move (column c always starts at c * colWidth); only the\n // page boundaries do. Keep the leftmost visible column on screen by\n // realigning to whichever new page contains it.\n const anchorCol = Math.round(el.scrollLeft / this.cfg.colWidth);\n this.colsPerPage = colsPerPage;\n this.realignTo = Math.floor(anchorCol / colsPerPage);\n this.recompute(true);\n }\n\n private onScroll = (): void => {\n if (this.frame) return;\n this.frame = requestAnimationFrame(() => {\n this.frame = 0;\n this.recompute();\n });\n };\n\n /** Fallback for browsers without `scrollend`: treat 120ms of quiet as rest. */\n private onScrollIdle = (): void => {\n clearTimeout(this.endTimer);\n this.endTimer = window.setTimeout(this.onScrollEnd, 120);\n };\n\n private onScrollEnd = (): void => {\n this.land();\n };\n\n private recompute(force = false): void {\n const el = this.scroller;\n if (!el) return;\n const pw = this.pageWidth;\n const buf = this.cfg.buffer ?? 1;\n const left = el.scrollLeft;\n const first = Math.max(0, Math.floor(left / pw) - buf);\n // Floor on both edges, so that first and last shift together at each page\n // boundary rather than one just before it and one just after.\n const last = Math.min(\n this.pageCount - 1,\n Math.floor((left + this.viewportW) / pw) + buf,\n );\n // Most scroll events end here: the window only changes at page boundaries\n if (!force && first === this.first && last === this.last) return;\n this.first = first;\n this.last = last;\n this.host.requestUpdate();\n }\n\n /** Records which page the scroller is resting on. */\n private land(): void {\n const el = this.scroller;\n if (!el) return;\n const left = el.scrollLeft;\n const maxLeft = this.totalWidth - this.viewportW;\n // A partial last page can't reach its own snap point, so resting at the\n // far end counts as landing on the last page.\n const atEnd = left >= maxLeft - 1;\n const page = atEnd ? this.pageCount - 1 : Math.round(left / this.pageWidth);\n const clamped = Math.max(0, Math.min(page, this.pageCount - 1));\n if (clamped !== this.currentPage) {\n this.currentPage = clamped;\n this.host.requestUpdate();\n }\n this.cfg.onRest?.(clamped);\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toggle-switch.js","sourceRoot":"","sources":["../../../src/collection-facets/toggle-switch.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAkB,MAAM,KAAK,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAKzC,IAAM,YAAY,GAAlB,MAAM,YAAa,SAAQ,UAAU;IAArC;;QACL;;WAEG;QAC0C,cAAS,GAAW,EAAE,CAAC;QAQpE;;WAEG;QAC0C,eAAU,GAAW,EAAE,CAAC;QAQrE;;WAEG;QAC0C,SAAI,GAAS,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"toggle-switch.js","sourceRoot":"","sources":["../../../src/collection-facets/toggle-switch.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, LitElement, CSSResultGroup } from 'lit';\nimport { customElement, property, query } from 'lit/decorators.js';\nimport { srOnlyStyle } from '../styles/sr-only';\n\nexport type Side = 'left' | 'right';\n\n@customElement('toggle-switch')\nexport class ToggleSwitch extends LitElement {\n /**\n * The value this switch should have when toggled to the left.\n */\n @property({ type: String, attribute: true }) leftValue: string = '';\n\n /**\n * The human-readable label to display on the left side of this switch.\n * If none is provided, `leftValue` is used.\n */\n @property({ type: String, attribute: true }) leftLabel?: string;\n\n /**\n * The value this switch should have when toggled to the right.\n */\n @property({ type: String, attribute: true }) rightValue: string = '';\n\n /**\n * The human-readable label to display on the right side of this switch.\n * If none is provided, `rightValue` is used.\n */\n @property({ type: String, attribute: true }) rightLabel?: string;\n\n /**\n * Which side of the switch is selected (`'left'` or `'right'`).\n */\n @property({ type: String, attribute: true }) side: Side = 'left';\n\n @query('#switch-left')\n private leftRadio!: HTMLInputElement;\n\n render() {\n return html`\n <div id=\"container\">\n <label for=\"switch-left\">${this.leftLabel ?? this.leftValue}</label>\n <input\n type=\"radio\"\n id=\"switch-left\"\n class=\"sr-only\"\n name=\"switch\"\n .value=${this.leftValue}\n .checked=${this.side === 'left'}\n @change=${this.handleRadioChange}\n />\n <input\n type=\"radio\"\n id=\"switch-right\"\n class=\"sr-only\"\n name=\"switch\"\n .value=${this.rightValue}\n .checked=${this.side === 'right'}\n @change=${this.handleRadioChange}\n />\n <button\n id=\"switch-button\"\n class=${this.side}\n aria-hidden=\"true\"\n tabindex=\"-1\"\n @click=${this.handleClick}\n >\n <div id=\"knob\"></div>\n </button>\n <label for=\"switch-right\">${this.rightLabel ?? this.rightValue}</label>\n </div>\n `;\n }\n\n /**\n * The currently selected value of this switch.\n */\n get value(): string {\n return this.side === 'left' ? this.leftValue : this.rightValue;\n }\n\n /**\n * The label for the currently selected value of this switch.\n * Falls back to the current value if its label is not defined.\n */\n get selectedLabel(): string {\n return this.side === 'left'\n ? (this.leftLabel ?? this.leftValue)\n : (this.rightLabel ?? this.rightValue);\n }\n\n private handleClick(): void {\n this.side = this.side === 'left' ? 'right' : 'left';\n this.emitChangeEvent();\n }\n\n private handleRadioChange(): void {\n this.side = this.leftRadio.checked ? 'left' : 'right';\n this.emitChangeEvent();\n }\n\n private emitChangeEvent(): void {\n const event = new CustomEvent<string>('change', {\n detail: this.value,\n });\n this.dispatchEvent(event);\n }\n\n static get styles(): CSSResultGroup {\n const switchWidth = css`var(--switchWidth, 30px)`;\n const switchHeight = css`var(--switchHeight, 14px)`;\n const switchMarginLeft = css`var(--switchMarginLeft, 5px)`;\n const switchMarginRight = css`var(--switchMarginRight, 5px)`;\n const switchBorderWidth = css`var(--switchBorderWidth, 3px)`;\n const switchBgColor = css`var(--switchBgColor, #194880)`;\n const switchBorderColor = css`var(--switchBorderColor, #194880)`;\n const labelFontSize = css`var(--labelFontSize, 1.3rem)`;\n const knobColor = css`var(--knobColor, white)`;\n const knobTransitionDuration = css`var(--knobTransitionDuration, 0.25s)`;\n const knobTransitionFn = css`var(--knobTransitionFn, ease)`;\n\n return [\n srOnlyStyle,\n css`\n #container {\n display: inline-flex;\n align-items: center;\n flex-wrap: nowrap;\n font-size: ${labelFontSize};\n }\n\n #switch-button {\n width: ${switchWidth};\n height: ${switchHeight};\n margin: 0 ${switchMarginRight} 0 ${switchMarginLeft};\n padding: 0;\n border: ${switchBorderWidth} solid ${switchBorderColor};\n border-radius: ${switchHeight};\n box-sizing: content-box;\n background: ${switchBgColor};\n appearance: none;\n cursor: pointer;\n }\n\n #switch-button.left #knob {\n transform: translateX(0);\n }\n\n #switch-button.right #knob {\n transform: translateX(calc(${switchWidth} - ${switchHeight}));\n }\n\n #switch-button:focus-visible {\n outline: 2px solid black;\n outline-offset: 2px;\n }\n\n #knob {\n display: block;\n width: ${switchHeight};\n height: ${switchHeight};\n border-radius: 50%;\n background: ${knobColor};\n transition: transform ${knobTransitionDuration} ${knobTransitionFn};\n }\n\n @media (prefers-reduced-motion: reduce) {\n #knob {\n transition-duration: 0.001s !important; /* Imperceptibly fast */\n }\n }\n `,\n ];\n }\n}\n"]}
|
package/dist/src/models.d.ts
CHANGED
|
@@ -255,6 +255,10 @@ export declare const tvFacetDisplayOrder: FacetOption[];
|
|
|
255
255
|
* Human-readable titles for each facet group.
|
|
256
256
|
*/
|
|
257
257
|
export declare const facetTitles: Record<FacetOption, string>;
|
|
258
|
+
/**
|
|
259
|
+
* Human-readable plural titles for each facet group, for referring to its values.
|
|
260
|
+
*/
|
|
261
|
+
export declare const facetPluralTitles: Record<FacetOption, string>;
|
|
258
262
|
/**
|
|
259
263
|
* The default sort type to use for each facet type
|
|
260
264
|
*/
|
package/dist/src/models.js
CHANGED
|
@@ -429,6 +429,22 @@ export const facetTitles = {
|
|
|
429
429
|
person: 'Person',
|
|
430
430
|
sponsor: 'Sponsor',
|
|
431
431
|
};
|
|
432
|
+
/**
|
|
433
|
+
* Human-readable plural titles for each facet group, for referring to its values.
|
|
434
|
+
*/
|
|
435
|
+
export const facetPluralTitles = {
|
|
436
|
+
subject: 'Subjects',
|
|
437
|
+
lending: 'Availability',
|
|
438
|
+
mediatype: 'Media Types',
|
|
439
|
+
language: 'Languages',
|
|
440
|
+
creator: 'Creators',
|
|
441
|
+
collection: 'Collections',
|
|
442
|
+
year: 'Years',
|
|
443
|
+
clip_type: 'Clip Types',
|
|
444
|
+
program: 'Programs',
|
|
445
|
+
person: 'People',
|
|
446
|
+
sponsor: 'Sponsors',
|
|
447
|
+
};
|
|
432
448
|
/**
|
|
433
449
|
* The default sort type to use for each facet type
|
|
434
450
|
*/
|
package/dist/src/models.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/models.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TemplateResult } from 'lit';\nimport { msg } from '@lit/localize';\nimport type { MediaType } from '@internetarchive/field-parsers';\nimport {\n AggregationSortType,\n HitType,\n SearchReview,\n SearchResult,\n SortDirection,\n} from '@internetarchive/search-service';\nimport { collapseRepeatedQuotes } from './utils/collapse-repeated-quotes';\nimport { resolveMediatype } from './utils/resolve-mediatype';\n\nimport { loginRequiredIcon } from './assets/img/icons/login-required';\nimport { restrictedIcon } from './assets/img/icons/restricted';\n\n/**\n * Flags that can affect the visibility of content on a tile\n */\ninterface TileFlags {\n loginRequired: boolean;\n contentWarning: boolean;\n}\n\n/**\n * Different types of tile overlays, corresponding to the above flags.\n */\nexport type TileOverlayType = 'login-required' | 'content-warning';\n\nexport const TILE_OVERLAY_TEXT: Record<TileOverlayType, string> = {\n 'login-required': msg('Log in to view this item'),\n 'content-warning': msg('Content may be inappropriate'),\n};\n\nexport const TILE_OVERLAY_ICONS: Record<TileOverlayType, TemplateResult> = {\n 'login-required': loginRequiredIcon,\n 'content-warning': restrictedIcon,\n};\n\n/**\n * What type of request produced a given set of hits:\n * - `search_query`: Hits produced by an explicit user query and/or applied filters on any page\n * - `collection_members`: Hits produced for a collection page without any query or filters\n * - `profile_tab`: Hits produced for a tab of the profile page without any query or filters\n * - `unknown`: Hits produced via any other means\n */\nexport type HitRequestSource =\n | 'search_query'\n | 'collection_members'\n | 'profile_tab'\n | 'unknown';\n\n/**\n * Class for converting & storing raw search results in the correct format for UI tiles.\n */\nexport class TileModel {\n /** For TV hits. List of identifiers for any commercials contained. */\n adIds?: string[];\n\n averageRating?: number;\n\n /** For Web Archive hits on profile pages. List of capture dates for the current URL. */\n captureDates?: Date[];\n\n /** Whether this tile is currently checked for item management functions */\n checked: boolean;\n\n collectionIdentifier?: string;\n\n collectionName?: string;\n\n collectionFilesCount: number;\n\n collections: string[];\n\n collectionSize: number;\n\n commentCount: number;\n\n creator?: string;\n\n creators: string[];\n\n /** A string representation of the publication date, used strictly for passing preformatted dates to the parent */\n dateStr?: string;\n\n /** Date added to public search (software-defined) [from MD field: addeddate] */\n dateAdded?: Date;\n\n /** Date archived (software-defined) item created on archive.org [from MD field: publicdate] */\n dateArchived?: Date;\n\n /** Date work published in the world (user-defined) [from MD field: date] */\n datePublished?: Date;\n\n /** Date reviewed (user-created) most recent review [from MD field: reviewdate] */\n dateReviewed?: Date;\n\n description?: string;\n\n /** For TV hits. List of URLs for any fact-checks of the contained clips. */\n factChecks?: string[];\n\n favCount: number;\n\n hitRequestSource: HitRequestSource;\n\n hitType?: HitType;\n\n href?: string;\n\n identifier?: string;\n\n /** Whether this model represents a TV clip */\n isClip?: boolean;\n\n issue?: string;\n\n itemCount: number;\n\n mediatype: MediaType;\n\n review?: SearchReview;\n\n source?: string;\n\n snippets?: string[];\n\n subjects: string[];\n\n thumbnailUrl?: string;\n\n title: string;\n\n tvClipCount?: number;\n\n viewCount?: number;\n\n volume?: string;\n\n weeklyViewCount?: number;\n\n loginRequired: boolean;\n\n contentWarning: boolean;\n\n constructor(\n result: SearchResult,\n hitRequestSource: HitRequestSource = 'unknown',\n ) {\n const flags = this.getFlags(result);\n\n this.adIds = result.ad_id?.values;\n this.averageRating = result.avg_rating?.value;\n this.captureDates = result.capture_dates?.values;\n this.checked = false;\n this.collections = result.collection?.values ?? [];\n this.collectionFilesCount = result.collection_files_count?.value ?? 0;\n this.collectionSize = result.collection_size?.value ?? 0;\n this.commentCount = result.num_reviews?.value ?? 0;\n this.creator = result.creator?.value;\n this.creators = result.creator?.values ?? [];\n this.dateAdded = result.addeddate?.value;\n this.dateArchived = result.publicdate?.value;\n this.datePublished = result.date?.value;\n this.dateReviewed = result.reviewdate?.value;\n this.description = result.description?.values.join('\\n');\n this.factChecks = result.factcheck?.values;\n this.favCount = result.num_favorites?.value ?? 0;\n this.hitRequestSource = hitRequestSource;\n this.hitType = result.rawMetadata?.hit_type;\n this.href = collapseRepeatedQuotes(\n result.review?.__href__ ?? result.__href__?.value,\n );\n this.identifier = TileModel.cleanIdentifier(result.identifier);\n this.isClip = result.is_clip?.value;\n this.issue = result.issue?.value;\n this.itemCount = result.item_count?.value ?? 0;\n this.mediatype = resolveMediatype(result);\n this.review = result.review;\n this.snippets = result.highlight?.values ?? [];\n this.source = result.source?.value;\n this.subjects = result.subject?.values ?? [];\n this.thumbnailUrl = result.__img__?.value;\n this.title = result.title?.value ?? '';\n this.tvClipCount = result.num_clips?.value ?? 0;\n this.volume = result.volume?.value;\n this.viewCount = result.downloads?.value;\n this.weeklyViewCount = result.week?.value;\n this.loginRequired = flags.loginRequired;\n this.contentWarning = flags.contentWarning;\n }\n\n /**\n * Copies the contents of this TileModel onto a new instance\n */\n clone(): TileModel {\n const cloned = new TileModel({});\n cloned.adIds = this.adIds;\n cloned.averageRating = this.averageRating;\n cloned.captureDates = this.captureDates;\n cloned.checked = this.checked;\n cloned.collections = this.collections;\n cloned.collectionFilesCount = this.collectionFilesCount;\n cloned.collectionSize = this.collectionSize;\n cloned.commentCount = this.commentCount;\n cloned.creator = this.creator;\n cloned.creators = this.creators;\n cloned.dateStr = this.dateStr;\n cloned.dateAdded = this.dateAdded;\n cloned.dateArchived = this.dateArchived;\n cloned.datePublished = this.datePublished;\n cloned.dateReviewed = this.dateReviewed;\n cloned.description = this.description;\n cloned.factChecks = this.factChecks;\n cloned.favCount = this.favCount;\n cloned.hitRequestSource = this.hitRequestSource;\n cloned.hitType = this.hitType;\n cloned.href = this.href;\n cloned.identifier = this.identifier;\n cloned.isClip = this.isClip;\n cloned.issue = this.issue;\n cloned.itemCount = this.itemCount;\n cloned.mediatype = this.mediatype;\n cloned.snippets = this.snippets;\n cloned.source = this.source;\n cloned.subjects = this.subjects;\n cloned.thumbnailUrl = this.thumbnailUrl;\n cloned.title = this.title;\n cloned.tvClipCount = this.tvClipCount;\n cloned.volume = this.volume;\n cloned.viewCount = this.viewCount;\n cloned.weeklyViewCount = this.weeklyViewCount;\n cloned.loginRequired = this.loginRequired;\n cloned.contentWarning = this.contentWarning;\n return cloned;\n }\n\n /**\n * Whether this model represents the result of a TV search query.\n */\n get isTvSearchResult(): boolean {\n return (\n this.hitType === 'tv_clip' && this.hitRequestSource === 'search_query'\n );\n }\n\n /**\n * Determines the appropriate tile flags for the given search result\n * (login required and/or content warning)\n */\n private getFlags(result: SearchResult): TileFlags {\n const flags: TileFlags = {\n loginRequired: false,\n contentWarning: false,\n };\n\n // Check if item and item in \"modifying\" collection, setting above flags\n if (\n result.collection?.values.length &&\n result.mediatype?.value !== 'collection'\n ) {\n for (const collection of result.collection?.values ?? []) {\n if (collection === 'loggedin') {\n flags.loginRequired = true;\n if (flags.contentWarning) break;\n }\n if (collection === 'no-preview') {\n flags.contentWarning = true;\n if (flags.loginRequired) break;\n }\n }\n }\n\n return flags;\n }\n\n private static cleanIdentifier(\n identifier: string | undefined,\n ): string | undefined {\n // Some identifiers (e.g., from Whisper) represent documents rather than items, and\n // are suffixed with values that need to be stripped. Those values are separated\n // from the item identifier itself with '|'.\n const barIndex = identifier?.indexOf('|') ?? -1;\n const cleaned = barIndex > 0 ? identifier?.slice(0, barIndex) : identifier;\n return cleaned;\n }\n}\n\nexport type RequestKind = 'full' | 'hits' | 'aggregations';\n\nexport type CollectionDisplayMode = 'grid' | 'list-compact' | 'list-detail';\n\nexport type TileDisplayMode =\n | 'grid'\n | 'list-compact'\n | 'list-detail'\n | 'list-header';\n\n/**\n * This is mainly used to set the cookies for the collection display mode.\n *\n * It allows the user to set different modes for different contexts (collection page, search page, profile page etc).\n */\nexport type CollectionBrowserContext = 'collection' | 'search' | 'profile';\n\n/**\n * The sort fields shown in the sort filter bar\n */\nexport enum SortField {\n 'default' = 'default',\n 'unrecognized' = 'unrecognized',\n 'relevance' = 'relevance',\n 'alltimeview' = 'alltimeview',\n 'weeklyview' = 'weeklyview',\n 'title' = 'title',\n 'date' = 'date',\n 'datearchived' = 'datearchived',\n 'datereviewed' = 'datereviewed',\n 'dateadded' = 'dateadded',\n 'datefavorited' = 'datefavorited',\n 'creator' = 'creator',\n}\n\n/**\n * Views-related sort fields\n */\nexport const ALL_VIEWS_SORT_FIELDS = [\n SortField.weeklyview,\n SortField.alltimeview,\n] as const;\nexport type ViewsSortField = (typeof ALL_VIEWS_SORT_FIELDS)[number];\n\n/**\n * Date-related sort fields\n */\nexport const ALL_DATE_SORT_FIELDS = [\n SortField.datefavorited,\n SortField.date,\n SortField.datearchived,\n SortField.datereviewed,\n SortField.dateadded,\n] as const;\nexport type DateSortField = (typeof ALL_DATE_SORT_FIELDS)[number];\n\nexport interface SortOption {\n /**\n * The SortField enum member corresponding to this option.\n */\n field: SortField;\n\n /**\n * The default sort direction to apply when this sort option is first selected.\n */\n defaultSortDirection: SortDirection | null;\n\n /**\n * Whether this sort option allows its sort direction to be changed from the default.\n */\n canSetDirection: boolean;\n\n /**\n * Whether this sort option may appear in the sort bar.\n */\n shownInSortBar: boolean;\n\n /**\n * Whether this sort option should be saved to the URL.\n * If false, then no `sort` param will be added to the URL when this sort option\n * is selected.\n */\n shownInURL: boolean;\n\n /**\n * Whether this sort option is passed to the search service.\n * If false, then no sort param will be passed to the search service at all when\n * this sort option is selected.\n */\n handledBySearchService: boolean;\n\n /**\n * The string identifying this sort field to the search service & backend API.\n */\n searchServiceKey?: string;\n\n /**\n * The human-readable name to use for this option in the sort bar (if applicable).\n */\n displayName: string;\n\n /**\n * A list of URL param keys that should be mapped to this sort option.\n * E.g., both `title` and `titleSorter` in the URL map to the `SortField.title` option.\n */\n urlNames: (string | null | undefined)[];\n}\n\nexport const SORT_OPTIONS: Record<SortField, SortOption> = {\n // Default sort is the case where the user has not specified a sort option via the sort bar or URL.\n // In these cases, we defer to whatever sort the backend chooses.\n // For the search page, the default is always relevance sort.\n // For collection pages _without a query_, the default is usually weekly views, but this can be\n // overridden by the collection's `sort-by` metadata entry. If a query _is_ specified, then the\n // default is again relevance sort.\n // For fav-* collections only, the default is instead sorting by date favorited.\n [SortField.default]: {\n field: SortField.default,\n defaultSortDirection: null,\n canSetDirection: false,\n shownInSortBar: false,\n shownInURL: false,\n handledBySearchService: false, // We rely on the PPS default sort handling in these cases\n displayName: '',\n urlNames: ['', null, undefined], // Empty or nullish sort params result in default sorting\n },\n // Unrecognized sort is the case where the user has specified a sort in the URL, but it is not\n // one of the options listed in this map. We still want these unrecognized sorts to be applied\n // when searching, but they are not displayed in the sort bar and we do not actively manage\n // their URL param beyond flipping the direction as needed.\n [SortField.unrecognized]: {\n field: SortField.unrecognized,\n defaultSortDirection: null,\n canSetDirection: true,\n shownInSortBar: false,\n shownInURL: false,\n handledBySearchService: true, // The unrecognized sort param is passed along as-is\n displayName: '',\n urlNames: [],\n },\n // Relevance sort is unique in that it does not produce a URL param when it is set.\n // It is only available when there is a user-specified query that relevancy can be scored against.\n // Therefore, it does not appear as a sort bar option when browsing a collection with no query set.\n [SortField.relevance]: {\n field: SortField.relevance,\n defaultSortDirection: null,\n canSetDirection: false,\n shownInSortBar: true,\n shownInURL: false,\n handledBySearchService: false,\n displayName: 'Relevance',\n urlNames: ['_score'],\n },\n [SortField.alltimeview]: {\n field: SortField.alltimeview,\n defaultSortDirection: 'desc',\n canSetDirection: true,\n shownInSortBar: true,\n shownInURL: true,\n handledBySearchService: true,\n searchServiceKey: 'downloads',\n displayName: 'All-time views',\n urlNames: ['downloads'],\n },\n [SortField.weeklyview]: {\n field: SortField.weeklyview,\n defaultSortDirection: 'desc',\n canSetDirection: true,\n shownInSortBar: true,\n shownInURL: true,\n handledBySearchService: true,\n searchServiceKey: 'week',\n displayName: 'Weekly views',\n urlNames: ['week'],\n },\n [SortField.title]: {\n field: SortField.title,\n defaultSortDirection: 'asc',\n canSetDirection: true,\n shownInSortBar: true,\n shownInURL: true,\n handledBySearchService: true,\n searchServiceKey: 'titleSorter',\n displayName: 'Title',\n urlNames: ['title', 'titleSorter'],\n },\n [SortField.date]: {\n field: SortField.date,\n defaultSortDirection: 'desc',\n canSetDirection: true,\n shownInSortBar: true,\n shownInURL: true,\n handledBySearchService: true,\n searchServiceKey: 'date',\n displayName: 'Date published',\n urlNames: ['date'],\n },\n [SortField.datearchived]: {\n field: SortField.datearchived,\n defaultSortDirection: 'desc',\n canSetDirection: true,\n shownInSortBar: true,\n shownInURL: true,\n handledBySearchService: true,\n searchServiceKey: 'publicdate',\n displayName: 'Date archived',\n urlNames: ['publicdate'],\n },\n [SortField.datereviewed]: {\n field: SortField.datereviewed,\n defaultSortDirection: 'desc',\n canSetDirection: true,\n shownInSortBar: true,\n shownInURL: true,\n handledBySearchService: true,\n searchServiceKey: 'reviewdate',\n displayName: 'Date reviewed',\n urlNames: ['reviewdate'],\n },\n [SortField.dateadded]: {\n field: SortField.dateadded,\n defaultSortDirection: 'desc',\n canSetDirection: true,\n shownInSortBar: true,\n shownInURL: true,\n handledBySearchService: true,\n searchServiceKey: 'addeddate',\n displayName: 'Date added',\n urlNames: ['addeddate'],\n },\n [SortField.datefavorited]: {\n field: SortField.datefavorited,\n defaultSortDirection: 'desc',\n canSetDirection: false,\n shownInSortBar: true, // But only when viewing fav-* collections\n shownInURL: false,\n handledBySearchService: false,\n searchServiceKey: 'favoritedate',\n displayName: 'Date favorited',\n urlNames: ['favoritedate'],\n },\n [SortField.creator]: {\n field: SortField.creator,\n defaultSortDirection: 'asc',\n canSetDirection: true,\n shownInSortBar: true,\n shownInURL: true,\n handledBySearchService: true,\n searchServiceKey: 'creatorSorter',\n displayName: 'Creator',\n urlNames: ['creator', 'creatorSorter'],\n },\n};\n\n/**\n * Returns the SortOption corresponding to the given API sort name, or\n * the \"unrecognized\" SortOption if none matches.\n */\nexport function sortOptionFromAPIString(sortName?: string | null): SortOption {\n return (\n Object.values(SORT_OPTIONS).find(opt =>\n opt.urlNames.some(name => sortName === name),\n ) ?? SORT_OPTIONS[SortField.unrecognized]\n );\n}\n\nexport const defaultSortAvailability: Record<SortField, boolean> = {\n [SortField.relevance]: true,\n [SortField.weeklyview]: true,\n [SortField.alltimeview]: true,\n [SortField.title]: true,\n [SortField.datefavorited]: false,\n [SortField.date]: true,\n [SortField.datearchived]: true,\n [SortField.datereviewed]: true,\n [SortField.dateadded]: true,\n [SortField.creator]: true,\n [SortField.default]: false,\n [SortField.unrecognized]: false,\n};\n\nexport const favoritesSortAvailability: Record<SortField, boolean> = {\n ...defaultSortAvailability,\n [SortField.datefavorited]: true,\n};\n\nexport const tvSortAvailability: Record<SortField, boolean> = {\n ...defaultSortAvailability,\n [SortField.date]: false,\n [SortField.datereviewed]: false,\n [SortField.dateadded]: false,\n};\n\nexport const defaultProfileElementSorts: Record<\n string,\n Exclude<SortField, SortField.default>\n> = {\n uploads: SortField.datearchived,\n reviews: SortField.datereviewed,\n collections: SortField.datearchived,\n web_archives: SortField.datearchived,\n favorites: SortField.datefavorited,\n};\n\n/** A union of the fields that permit prefix filtering (e.g., alphabetical filtering) */\nexport type PrefixFilterType = 'title' | 'creator';\n\n/** A map from prefixes (e.g., initial letters) to the number of items matching that prefix */\nexport type PrefixFilterCounts = Record<string, number>;\n\n/**\n * A map from prefix filter types to the corresponding aggregation keys\n * that are needed to fetch the filter counts from the backend.\n */\nexport const prefixFilterAggregationKeys: Record<PrefixFilterType, string> = {\n title: 'firstTitle',\n creator: 'firstCreator',\n};\n\n/**\n * Different facet loading strategies that can be used with collection browser.\n * - `eager`: Facet data is always loaded as soon as a search is performed\n * - `lazy-mobile`: In the desktop layout, functions exactly as `eager`.\n * In the mobile layout, facet data will only be loaded once the \"Filters\" accordion is opened.\n * - `opt-in-or-login`: Same as `opt-in` for guest users not logged into an account, but same as `eager` for\n * any logged in user.\n * - `opt-in`: In the desktop layout, facet data will only be loaded after the user presses a \"Load Facets\" button.\n * In the mobile layout, functions exactly as `lazy-mobile`.\n * - `off`: Facet data will never be loaded, and a message will be displayed in place of facets\n * indicating that they are unavailable.\n */\nexport type FacetLoadStrategy =\n | 'eager'\n | 'lazy-mobile'\n | 'opt-in-or-login'\n | 'opt-in'\n | 'off';\n\n/**\n * Union of the facet types that are available in the sidebar.\n */\nexport type FacetOption =\n | 'subject'\n | 'lending'\n | 'mediatype'\n | 'language'\n | 'creator'\n | 'collection'\n | 'year'\n // TV-specific facet options:\n | 'clip_type'\n | 'program'\n | 'person'\n | 'sponsor';\n\nexport type SelectedFacetState = 'selected' | 'hidden';\n\nexport type FacetState = SelectedFacetState | 'none';\n\nexport interface FacetBucket {\n key: string;\n count: number;\n state: FacetState;\n // for some facets, we augment the key with a display value\n displayText?: string;\n // for TV channel facets, we add a parenthesized secondary name\n extraNote?: string;\n}\n\nexport interface FacetGroup {\n title: string;\n key: FacetOption;\n buckets: FacetBucket[];\n}\n\n/**\n * Information about a user interaction event on a facet.\n */\nexport type FacetEventDetails = {\n /**\n * The type of facet that was interacted with (e.g., 'mediatype', 'language', ...).\n */\n facetType: FacetOption;\n /**\n * The bucket corresponding to the facet that was interacted with, including the\n * updated state of the facet after the interaction.\n */\n bucket: FacetBucket;\n /**\n * Whether the interaction occurred on a negative facet.\n */\n negative: boolean;\n};\n\nexport type FacetValue = string;\n\nexport type SelectedFacets = Partial<\n Record<FacetOption, Record<FacetValue, FacetBucket>>\n>;\n\nexport const getDefaultSelectedFacets = (): Required<SelectedFacets> => ({\n subject: {},\n lending: {},\n mediatype: {},\n language: {},\n creator: {},\n collection: {},\n year: {},\n clip_type: {},\n program: {},\n person: {},\n sponsor: {},\n});\n\n/**\n * For TV search results, what types of TV clips to restrict the results to.\n */\nexport type TvClipFilterType = 'commercial' | 'fact check' | 'quote';\n\n/**\n * Map from allowed TV filtering parameters in the URL to their corresponding filter type\n */\nexport const tvClipURLParamsToFilters: Record<string, TvClipFilterType> = {\n only_commercials: 'commercial',\n only_factchecks: 'fact check',\n only_quotes: 'quote',\n};\n\n/**\n * Facet display order when presenting results for all search types *except* TV (see below).\n */\nexport const defaultFacetDisplayOrder: FacetOption[] = [\n 'mediatype',\n // 'lending', Commenting this out removes the lending facet from the sidebar for now\n 'year',\n 'subject',\n 'collection',\n 'creator',\n 'language',\n];\n\n/**\n * Specialized facet ordering when displaying TV search results\n */\nexport const tvFacetDisplayOrder: FacetOption[] = [\n 'program',\n 'creator',\n 'year',\n 'subject',\n // 'person', Omitting the Person facet group for now, though it may be re-added later with new semantics\n 'language',\n 'clip_type',\n];\n\n/**\n * Human-readable titles for each facet group.\n */\nexport const facetTitles: Record<FacetOption, string> = {\n subject: 'Subject',\n lending: 'Availability',\n mediatype: 'Media Type',\n language: 'Language',\n creator: 'Creator',\n collection: 'Collection',\n year: 'Year',\n clip_type: 'Clip Type',\n program: 'Program',\n person: 'Person',\n sponsor: 'Sponsor',\n};\n\n/**\n * The default sort type to use for each facet type\n */\nexport const defaultFacetSort: Record<FacetOption, AggregationSortType> = {\n subject: AggregationSortType.COUNT,\n lending: AggregationSortType.COUNT,\n mediatype: AggregationSortType.COUNT,\n language: AggregationSortType.COUNT,\n creator: AggregationSortType.COUNT,\n collection: AggregationSortType.COUNT,\n year: AggregationSortType.NUMERIC, // Year facets are ordered by their numeric value by default\n clip_type: AggregationSortType.COUNT,\n program: AggregationSortType.COUNT,\n person: AggregationSortType.COUNT,\n sponsor: AggregationSortType.COUNT,\n};\n\n/**\n * The default sort type to use for each facet type in TV search More... dialogs only\n */\nexport const tvMoreFacetSort: Record<FacetOption, AggregationSortType> = {\n ...defaultFacetSort,\n creator: AggregationSortType.ALPHABETICAL,\n program: AggregationSortType.ALPHABETICAL,\n};\n\n/**\n * The sort type corresponding to facet bucket values, for each facet type\n * (i.e., the opposite of \"sort by count\" for that type).\n */\nexport const valueFacetSort: Record<FacetOption, AggregationSortType> = {\n subject: AggregationSortType.ALPHABETICAL,\n lending: AggregationSortType.ALPHABETICAL,\n mediatype: AggregationSortType.ALPHABETICAL,\n language: AggregationSortType.ALPHABETICAL,\n creator: AggregationSortType.ALPHABETICAL,\n collection: AggregationSortType.ALPHABETICAL,\n year: AggregationSortType.NUMERIC, // Year facets' values should be compared numerically, not lexicographically (year 2001 > year 3)\n clip_type: AggregationSortType.ALPHABETICAL,\n program: AggregationSortType.ALPHABETICAL,\n person: AggregationSortType.ALPHABETICAL,\n sponsor: AggregationSortType.ALPHABETICAL,\n};\n\nexport type LendingFacetKey =\n | 'is_lendable'\n | 'is_borrowable'\n | 'available_to_borrow'\n | 'is_browsable'\n | 'available_to_browse'\n | 'is_readable'\n | 'available_to_waitlist';\n\n/**\n * Maps valid lending keys to whether they should be visible in the facet sidebar\n */\nexport const lendingFacetKeysVisibility: Record<LendingFacetKey, boolean> = {\n is_lendable: true,\n is_borrowable: false,\n available_to_borrow: true,\n is_browsable: false,\n available_to_browse: false,\n is_readable: true,\n available_to_waitlist: false,\n};\n\n/**\n * Most facet options allow any string as keys, while some others can only take on a\n * limited set of strings. This type just defines those restrictions for the specific\n * facet types where they apply.\n */\nexport type AllowedFacetKey<T extends FacetOption> = T extends 'lending'\n ? LendingFacetKey\n : T extends 'clip_type'\n ? TvClipFilterType\n : string;\n\n/**\n * A type mapping FacetOptions to objects that define custom display names for some\n * or all of their valid keys.\n */\nexport type FacetDisplayNameMap = {\n [K in FacetOption]?: Partial<Record<AllowedFacetKey<K>, string>>;\n};\n\nexport const customFacetDisplayNames: FacetDisplayNameMap = {\n lending: {\n is_lendable: 'Lending Library',\n available_to_borrow: 'Borrow 14 Days',\n is_readable: 'Always Available',\n },\n clip_type: {\n quote: 'Quote',\n commercial: 'Political Ad',\n 'fact check': 'Fact Check',\n },\n};\n\n/**\n * A record of which admin-only collections should be suppressed from being displayed\n * as facets or in an item's list of collections.\n */\nexport const suppressedCollections: Record<string, boolean> = {\n deemphasize: true,\n community: true,\n stream_only: true,\n samples_only: true,\n test_collection: true,\n printdisabled: true,\n 'openlibrary-ol': true,\n nationalemergencylibrary: true,\n china: true,\n americana: true,\n toronto: true,\n};\n\n/**\n * A record of manageable item\n */\nexport interface ManageableItem {\n identifier: string;\n title?: string;\n dateStr?: string;\n date?: string;\n}\n\n/**\n * Possible states for whether & how the user has overridden their user preference\n * for blurring behavior on tiles with sensitive content.\n * - `no-override`: The user has not overridden their user preference, so simply\n * respect the preference as given.\n * - `on`: The user has overridden their preference and wants tile blurring enabled.\n * - `off`: The user has overridden their preference and wants tile blurring disabled.\n */\nexport type TileBlurOverrideState = 'no-override' | 'on' | 'off';\n"]}
|
|
1
|
+
{"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/models.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAEpC,OAAO,EACL,mBAAmB,GAKpB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAe/D,MAAM,CAAC,MAAM,iBAAiB,GAAoC;IAChE,gBAAgB,EAAE,GAAG,CAAC,0BAA0B,CAAC;IACjD,iBAAiB,EAAE,GAAG,CAAC,8BAA8B,CAAC;CACvD,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAA4C;IACzE,gBAAgB,EAAE,iBAAiB;IACnC,iBAAiB,EAAE,cAAc;CAClC,CAAC;AAeF;;GAEG;AACH,MAAM,OAAO,SAAS;IA2FpB,YACE,MAAoB,EACpB,mBAAqC,SAAS;QAE9C,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAEpC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC;QAClC,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC;QAC9C,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC;QACjD,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,UAAU,EAAE,MAAM,IAAI,EAAE,CAAC;QACnD,IAAI,CAAC,oBAAoB,GAAG,MAAM,CAAC,sBAAsB,EAAE,KAAK,IAAI,CAAC,CAAC;QACtE,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,eAAe,EAAE,KAAK,IAAI,CAAC,CAAC;QACzD,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,CAAC;QACnD,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC;QACrC,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,OAAO,EAAE,MAAM,IAAI,EAAE,CAAC;QAC7C,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC;QACzC,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC;QAC7C,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC;QACxC,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC;QAC7C,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzD,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3C,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,aAAa,EAAE,KAAK,IAAI,CAAC,CAAC;QACjD,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;QACzC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC;QAC5C,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAChC,MAAM,CAAC,MAAM,EAAE,QAAQ,IAAI,MAAM,CAAC,QAAQ,EAAE,KAAK,CAClD,CAAC;QACF,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC,eAAe,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC/D,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC;QACpC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC;QACjC,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,UAAU,EAAE,KAAK,IAAI,CAAC,CAAC;QAC/C,IAAI,CAAC,SAAS,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,SAAS,EAAE,MAAM,IAAI,EAAE,CAAC;QAC/C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;QACnC,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,OAAO,EAAE,MAAM,IAAI,EAAE,CAAC;QAC7C,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC;QAC1C,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC;QACvC,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,SAAS,EAAE,KAAK,IAAI,CAAC,CAAC;QAChD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;QACnC,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC;QACzC,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC;QAC1C,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC;QACzC,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC,cAAc,CAAC;IAC7C,CAAC;IAED;;OAEG;IACH,KAAK;QACH,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,CAAC,CAAC;QACjC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QAC1B,MAAM,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC;QAC1C,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;QACxC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC9B,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;QACtC,MAAM,CAAC,oBAAoB,GAAG,IAAI,CAAC,oBAAoB,CAAC;QACxD,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC;QAC5C,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;QACxC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC9B,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAChC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC9B,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAClC,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;QACxC,MAAM,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC;QAC1C,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;QACxC,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;QACtC,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QACpC,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAChC,MAAM,CAAC,gBAAgB,GAAG,IAAI,CAAC,gBAAgB,CAAC;QAChD,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC9B,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACxB,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QACpC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC5B,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QAC1B,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAClC,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAClC,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAChC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC5B,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAChC,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;QACxC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QAC1B,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;QACtC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC5B,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAClC,MAAM,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC;QAC9C,MAAM,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC;QAC1C,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC;QAC5C,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,IAAI,gBAAgB;QAClB,OAAO,CACL,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,gBAAgB,KAAK,cAAc,CACvE,CAAC;IACJ,CAAC;IAED;;;OAGG;IACK,QAAQ,CAAC,MAAoB;QACnC,MAAM,KAAK,GAAc;YACvB,aAAa,EAAE,KAAK;YACpB,cAAc,EAAE,KAAK;SACtB,CAAC;QAEF,wEAAwE;QACxE,IACE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM;YAChC,MAAM,CAAC,SAAS,EAAE,KAAK,KAAK,YAAY,EACxC,CAAC;YACD,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,UAAU,EAAE,MAAM,IAAI,EAAE,EAAE,CAAC;gBACzD,IAAI,UAAU,KAAK,UAAU,EAAE,CAAC;oBAC9B,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC;oBAC3B,IAAI,KAAK,CAAC,cAAc;wBAAE,MAAM;gBAClC,CAAC;gBACD,IAAI,UAAU,KAAK,YAAY,EAAE,CAAC;oBAChC,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC;oBAC5B,IAAI,KAAK,CAAC,aAAa;wBAAE,MAAM;gBACjC,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,MAAM,CAAC,eAAe,CAC5B,UAA8B;QAE9B,mFAAmF;QACnF,gFAAgF;QAChF,4CAA4C;QAC5C,MAAM,QAAQ,GAAG,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;QAC3E,OAAO,OAAO,CAAC;IACjB,CAAC;CACF;AAmBD;;GAEG;AACH,MAAM,CAAN,IAAY,SAaX;AAbD,WAAY,SAAS;IACnB,gCAAqB,CAAA;IACrB,0CAA+B,CAAA;IAC/B,oCAAyB,CAAA;IACzB,wCAA6B,CAAA;IAC7B,sCAA2B,CAAA;IAC3B,4BAAiB,CAAA;IACjB,0BAAe,CAAA;IACf,0CAA+B,CAAA;IAC/B,0CAA+B,CAAA;IAC/B,oCAAyB,CAAA;IACzB,4CAAiC,CAAA;IACjC,gCAAqB,CAAA;AACvB,CAAC,EAbW,SAAS,KAAT,SAAS,QAapB;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,SAAS,CAAC,UAAU;IACpB,SAAS,CAAC,WAAW;CACb,CAAC;AAGX;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,SAAS,CAAC,aAAa;IACvB,SAAS,CAAC,IAAI;IACd,SAAS,CAAC,YAAY;IACtB,SAAS,CAAC,YAAY;IACtB,SAAS,CAAC,SAAS;CACX,CAAC;AAuDX,MAAM,CAAC,MAAM,YAAY,GAAkC;IACzD,mGAAmG;IACnG,iEAAiE;IACjE,6DAA6D;IAC7D,+FAA+F;IAC/F,+FAA+F;IAC/F,mCAAmC;IACnC,gFAAgF;IAChF,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE;QACnB,KAAK,EAAE,SAAS,CAAC,OAAO;QACxB,oBAAoB,EAAE,IAAI;QAC1B,eAAe,EAAE,KAAK;QACtB,cAAc,EAAE,KAAK;QACrB,UAAU,EAAE,KAAK;QACjB,sBAAsB,EAAE,KAAK,EAAE,0DAA0D;QACzF,WAAW,EAAE,EAAE;QACf,QAAQ,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,EAAE,yDAAyD;KAC3F;IACD,8FAA8F;IAC9F,8FAA8F;IAC9F,2FAA2F;IAC3F,2DAA2D;IAC3D,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE;QACxB,KAAK,EAAE,SAAS,CAAC,YAAY;QAC7B,oBAAoB,EAAE,IAAI;QAC1B,eAAe,EAAE,IAAI;QACrB,cAAc,EAAE,KAAK;QACrB,UAAU,EAAE,KAAK;QACjB,sBAAsB,EAAE,IAAI,EAAE,oDAAoD;QAClF,WAAW,EAAE,EAAE;QACf,QAAQ,EAAE,EAAE;KACb;IACD,mFAAmF;IACnF,kGAAkG;IAClG,mGAAmG;IACnG,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE;QACrB,KAAK,EAAE,SAAS,CAAC,SAAS;QAC1B,oBAAoB,EAAE,IAAI;QAC1B,eAAe,EAAE,KAAK;QACtB,cAAc,EAAE,IAAI;QACpB,UAAU,EAAE,KAAK;QACjB,sBAAsB,EAAE,KAAK;QAC7B,WAAW,EAAE,WAAW;QACxB,QAAQ,EAAE,CAAC,QAAQ,CAAC;KACrB;IACD,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE;QACvB,KAAK,EAAE,SAAS,CAAC,WAAW;QAC5B,oBAAoB,EAAE,MAAM;QAC5B,eAAe,EAAE,IAAI;QACrB,cAAc,EAAE,IAAI;QACpB,UAAU,EAAE,IAAI;QAChB,sBAAsB,EAAE,IAAI;QAC5B,gBAAgB,EAAE,WAAW;QAC7B,WAAW,EAAE,gBAAgB;QAC7B,QAAQ,EAAE,CAAC,WAAW,CAAC;KACxB;IACD,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE;QACtB,KAAK,EAAE,SAAS,CAAC,UAAU;QAC3B,oBAAoB,EAAE,MAAM;QAC5B,eAAe,EAAE,IAAI;QACrB,cAAc,EAAE,IAAI;QACpB,UAAU,EAAE,IAAI;QAChB,sBAAsB,EAAE,IAAI;QAC5B,gBAAgB,EAAE,MAAM;QACxB,WAAW,EAAE,cAAc;QAC3B,QAAQ,EAAE,CAAC,MAAM,CAAC;KACnB;IACD,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE;QACjB,KAAK,EAAE,SAAS,CAAC,KAAK;QACtB,oBAAoB,EAAE,KAAK;QAC3B,eAAe,EAAE,IAAI;QACrB,cAAc,EAAE,IAAI;QACpB,UAAU,EAAE,IAAI;QAChB,sBAAsB,EAAE,IAAI;QAC5B,gBAAgB,EAAE,aAAa;QAC/B,WAAW,EAAE,OAAO;QACpB,QAAQ,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC;KACnC;IACD,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE;QAChB,KAAK,EAAE,SAAS,CAAC,IAAI;QACrB,oBAAoB,EAAE,MAAM;QAC5B,eAAe,EAAE,IAAI;QACrB,cAAc,EAAE,IAAI;QACpB,UAAU,EAAE,IAAI;QAChB,sBAAsB,EAAE,IAAI;QAC5B,gBAAgB,EAAE,MAAM;QACxB,WAAW,EAAE,gBAAgB;QAC7B,QAAQ,EAAE,CAAC,MAAM,CAAC;KACnB;IACD,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE;QACxB,KAAK,EAAE,SAAS,CAAC,YAAY;QAC7B,oBAAoB,EAAE,MAAM;QAC5B,eAAe,EAAE,IAAI;QACrB,cAAc,EAAE,IAAI;QACpB,UAAU,EAAE,IAAI;QAChB,sBAAsB,EAAE,IAAI;QAC5B,gBAAgB,EAAE,YAAY;QAC9B,WAAW,EAAE,eAAe;QAC5B,QAAQ,EAAE,CAAC,YAAY,CAAC;KACzB;IACD,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE;QACxB,KAAK,EAAE,SAAS,CAAC,YAAY;QAC7B,oBAAoB,EAAE,MAAM;QAC5B,eAAe,EAAE,IAAI;QACrB,cAAc,EAAE,IAAI;QACpB,UAAU,EAAE,IAAI;QAChB,sBAAsB,EAAE,IAAI;QAC5B,gBAAgB,EAAE,YAAY;QAC9B,WAAW,EAAE,eAAe;QAC5B,QAAQ,EAAE,CAAC,YAAY,CAAC;KACzB;IACD,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE;QACrB,KAAK,EAAE,SAAS,CAAC,SAAS;QAC1B,oBAAoB,EAAE,MAAM;QAC5B,eAAe,EAAE,IAAI;QACrB,cAAc,EAAE,IAAI;QACpB,UAAU,EAAE,IAAI;QAChB,sBAAsB,EAAE,IAAI;QAC5B,gBAAgB,EAAE,WAAW;QAC7B,WAAW,EAAE,YAAY;QACzB,QAAQ,EAAE,CAAC,WAAW,CAAC;KACxB;IACD,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE;QACzB,KAAK,EAAE,SAAS,CAAC,aAAa;QAC9B,oBAAoB,EAAE,MAAM;QAC5B,eAAe,EAAE,KAAK;QACtB,cAAc,EAAE,IAAI,EAAE,0CAA0C;QAChE,UAAU,EAAE,KAAK;QACjB,sBAAsB,EAAE,KAAK;QAC7B,gBAAgB,EAAE,cAAc;QAChC,WAAW,EAAE,gBAAgB;QAC7B,QAAQ,EAAE,CAAC,cAAc,CAAC;KAC3B;IACD,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE;QACnB,KAAK,EAAE,SAAS,CAAC,OAAO;QACxB,oBAAoB,EAAE,KAAK;QAC3B,eAAe,EAAE,IAAI;QACrB,cAAc,EAAE,IAAI;QACpB,UAAU,EAAE,IAAI;QAChB,sBAAsB,EAAE,IAAI;QAC5B,gBAAgB,EAAE,eAAe;QACjC,WAAW,EAAE,SAAS;QACtB,QAAQ,EAAE,CAAC,SAAS,EAAE,eAAe,CAAC;KACvC;CACF,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,QAAwB;IAC9D,OAAO,CACL,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CACrC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,KAAK,IAAI,CAAC,CAC7C,IAAI,YAAY,CAAC,SAAS,CAAC,YAAY,CAAC,CAC1C,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,uBAAuB,GAA+B;IACjE,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,IAAI;IAC3B,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,IAAI;IAC5B,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,IAAI;IAC7B,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,IAAI;IACvB,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,KAAK;IAChC,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI;IACtB,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,IAAI;IAC9B,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,IAAI;IAC9B,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,IAAI;IAC3B,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,IAAI;IACzB,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK;IAC1B,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,KAAK;CAChC,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAA+B;IACnE,GAAG,uBAAuB;IAC1B,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,IAAI;CAChC,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAA+B;IAC5D,GAAG,uBAAuB;IAC1B,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK;IACvB,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,KAAK;IAC/B,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,KAAK;CAC7B,CAAC;AAEF,MAAM,CAAC,MAAM,0BAA0B,GAGnC;IACF,OAAO,EAAE,SAAS,CAAC,YAAY;IAC/B,OAAO,EAAE,SAAS,CAAC,YAAY;IAC/B,WAAW,EAAE,SAAS,CAAC,YAAY;IACnC,YAAY,EAAE,SAAS,CAAC,YAAY;IACpC,SAAS,EAAE,SAAS,CAAC,aAAa;CACnC,CAAC;AAQF;;;GAGG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAqC;IAC3E,KAAK,EAAE,YAAY;IACnB,OAAO,EAAE,cAAc;CACxB,CAAC;AAmFF,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAA6B,EAAE,CAAC,CAAC;IACvE,OAAO,EAAE,EAAE;IACX,OAAO,EAAE,EAAE;IACX,SAAS,EAAE,EAAE;IACb,QAAQ,EAAE,EAAE;IACZ,OAAO,EAAE,EAAE;IACX,UAAU,EAAE,EAAE;IACd,IAAI,EAAE,EAAE;IACR,SAAS,EAAE,EAAE;IACb,OAAO,EAAE,EAAE;IACX,MAAM,EAAE,EAAE;IACV,OAAO,EAAE,EAAE;CACZ,CAAC,CAAC;AAOH;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAqC;IACxE,gBAAgB,EAAE,YAAY;IAC9B,eAAe,EAAE,YAAY;IAC7B,WAAW,EAAE,OAAO;CACrB,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAkB;IACrD,WAAW;IACX,oFAAoF;IACpF,MAAM;IACN,SAAS;IACT,YAAY;IACZ,SAAS;IACT,UAAU;CACX,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAkB;IAChD,SAAS;IACT,SAAS;IACT,MAAM;IACN,SAAS;IACT,wGAAwG;IACxG,UAAU;IACV,WAAW;CACZ,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAgC;IACtD,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,cAAc;IACvB,SAAS,EAAE,YAAY;IACvB,QAAQ,EAAE,UAAU;IACpB,OAAO,EAAE,SAAS;IAClB,UAAU,EAAE,YAAY;IACxB,IAAI,EAAE,MAAM;IACZ,SAAS,EAAE,WAAW;IACtB,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;CACnB,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAgC;IAC5D,OAAO,EAAE,UAAU;IACnB,OAAO,EAAE,cAAc;IACvB,SAAS,EAAE,aAAa;IACxB,QAAQ,EAAE,WAAW;IACrB,OAAO,EAAE,UAAU;IACnB,UAAU,EAAE,aAAa;IACzB,IAAI,EAAE,OAAO;IACb,SAAS,EAAE,YAAY;IACvB,OAAO,EAAE,UAAU;IACnB,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,UAAU;CACpB,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAA6C;IACxE,OAAO,EAAE,mBAAmB,CAAC,KAAK;IAClC,OAAO,EAAE,mBAAmB,CAAC,KAAK;IAClC,SAAS,EAAE,mBAAmB,CAAC,KAAK;IACpC,QAAQ,EAAE,mBAAmB,CAAC,KAAK;IACnC,OAAO,EAAE,mBAAmB,CAAC,KAAK;IAClC,UAAU,EAAE,mBAAmB,CAAC,KAAK;IACrC,IAAI,EAAE,mBAAmB,CAAC,OAAO,EAAE,4DAA4D;IAC/F,SAAS,EAAE,mBAAmB,CAAC,KAAK;IACpC,OAAO,EAAE,mBAAmB,CAAC,KAAK;IAClC,MAAM,EAAE,mBAAmB,CAAC,KAAK;IACjC,OAAO,EAAE,mBAAmB,CAAC,KAAK;CACnC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAA6C;IACvE,GAAG,gBAAgB;IACnB,OAAO,EAAE,mBAAmB,CAAC,YAAY;IACzC,OAAO,EAAE,mBAAmB,CAAC,YAAY;CAC1C,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAA6C;IACtE,OAAO,EAAE,mBAAmB,CAAC,YAAY;IACzC,OAAO,EAAE,mBAAmB,CAAC,YAAY;IACzC,SAAS,EAAE,mBAAmB,CAAC,YAAY;IAC3C,QAAQ,EAAE,mBAAmB,CAAC,YAAY;IAC1C,OAAO,EAAE,mBAAmB,CAAC,YAAY;IACzC,UAAU,EAAE,mBAAmB,CAAC,YAAY;IAC5C,IAAI,EAAE,mBAAmB,CAAC,OAAO,EAAE,iGAAiG;IACpI,SAAS,EAAE,mBAAmB,CAAC,YAAY;IAC3C,OAAO,EAAE,mBAAmB,CAAC,YAAY;IACzC,MAAM,EAAE,mBAAmB,CAAC,YAAY;IACxC,OAAO,EAAE,mBAAmB,CAAC,YAAY;CAC1C,CAAC;AAWF;;GAEG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAqC;IAC1E,WAAW,EAAE,IAAI;IACjB,aAAa,EAAE,KAAK;IACpB,mBAAmB,EAAE,IAAI;IACzB,YAAY,EAAE,KAAK;IACnB,mBAAmB,EAAE,KAAK;IAC1B,WAAW,EAAE,IAAI;IACjB,qBAAqB,EAAE,KAAK;CAC7B,CAAC;AAqBF,MAAM,CAAC,MAAM,uBAAuB,GAAwB;IAC1D,OAAO,EAAE;QACP,WAAW,EAAE,iBAAiB;QAC9B,mBAAmB,EAAE,gBAAgB;QACrC,WAAW,EAAE,kBAAkB;KAChC;IACD,SAAS,EAAE;QACT,KAAK,EAAE,OAAO;QACd,UAAU,EAAE,cAAc;QAC1B,YAAY,EAAE,YAAY;KAC3B;CACF,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAA4B;IAC5D,WAAW,EAAE,IAAI;IACjB,SAAS,EAAE,IAAI;IACf,WAAW,EAAE,IAAI;IACjB,YAAY,EAAE,IAAI;IAClB,eAAe,EAAE,IAAI;IACrB,aAAa,EAAE,IAAI;IACnB,gBAAgB,EAAE,IAAI;IACtB,wBAAwB,EAAE,IAAI;IAC9B,KAAK,EAAE,IAAI;IACX,SAAS,EAAE,IAAI;IACf,OAAO,EAAE,IAAI;CACd,CAAC","sourcesContent":["import type { TemplateResult } from 'lit';\nimport { msg } from '@lit/localize';\nimport type { MediaType } from '@internetarchive/field-parsers';\nimport {\n AggregationSortType,\n HitType,\n SearchReview,\n SearchResult,\n SortDirection,\n} from '@internetarchive/search-service';\nimport { collapseRepeatedQuotes } from './utils/collapse-repeated-quotes';\nimport { resolveMediatype } from './utils/resolve-mediatype';\n\nimport { loginRequiredIcon } from './assets/img/icons/login-required';\nimport { restrictedIcon } from './assets/img/icons/restricted';\n\n/**\n * Flags that can affect the visibility of content on a tile\n */\ninterface TileFlags {\n loginRequired: boolean;\n contentWarning: boolean;\n}\n\n/**\n * Different types of tile overlays, corresponding to the above flags.\n */\nexport type TileOverlayType = 'login-required' | 'content-warning';\n\nexport const TILE_OVERLAY_TEXT: Record<TileOverlayType, string> = {\n 'login-required': msg('Log in to view this item'),\n 'content-warning': msg('Content may be inappropriate'),\n};\n\nexport const TILE_OVERLAY_ICONS: Record<TileOverlayType, TemplateResult> = {\n 'login-required': loginRequiredIcon,\n 'content-warning': restrictedIcon,\n};\n\n/**\n * What type of request produced a given set of hits:\n * - `search_query`: Hits produced by an explicit user query and/or applied filters on any page\n * - `collection_members`: Hits produced for a collection page without any query or filters\n * - `profile_tab`: Hits produced for a tab of the profile page without any query or filters\n * - `unknown`: Hits produced via any other means\n */\nexport type HitRequestSource =\n | 'search_query'\n | 'collection_members'\n | 'profile_tab'\n | 'unknown';\n\n/**\n * Class for converting & storing raw search results in the correct format for UI tiles.\n */\nexport class TileModel {\n /** For TV hits. List of identifiers for any commercials contained. */\n adIds?: string[];\n\n averageRating?: number;\n\n /** For Web Archive hits on profile pages. List of capture dates for the current URL. */\n captureDates?: Date[];\n\n /** Whether this tile is currently checked for item management functions */\n checked: boolean;\n\n collectionIdentifier?: string;\n\n collectionName?: string;\n\n collectionFilesCount: number;\n\n collections: string[];\n\n collectionSize: number;\n\n commentCount: number;\n\n creator?: string;\n\n creators: string[];\n\n /** A string representation of the publication date, used strictly for passing preformatted dates to the parent */\n dateStr?: string;\n\n /** Date added to public search (software-defined) [from MD field: addeddate] */\n dateAdded?: Date;\n\n /** Date archived (software-defined) item created on archive.org [from MD field: publicdate] */\n dateArchived?: Date;\n\n /** Date work published in the world (user-defined) [from MD field: date] */\n datePublished?: Date;\n\n /** Date reviewed (user-created) most recent review [from MD field: reviewdate] */\n dateReviewed?: Date;\n\n description?: string;\n\n /** For TV hits. List of URLs for any fact-checks of the contained clips. */\n factChecks?: string[];\n\n favCount: number;\n\n hitRequestSource: HitRequestSource;\n\n hitType?: HitType;\n\n href?: string;\n\n identifier?: string;\n\n /** Whether this model represents a TV clip */\n isClip?: boolean;\n\n issue?: string;\n\n itemCount: number;\n\n mediatype: MediaType;\n\n review?: SearchReview;\n\n source?: string;\n\n snippets?: string[];\n\n subjects: string[];\n\n thumbnailUrl?: string;\n\n title: string;\n\n tvClipCount?: number;\n\n viewCount?: number;\n\n volume?: string;\n\n weeklyViewCount?: number;\n\n loginRequired: boolean;\n\n contentWarning: boolean;\n\n constructor(\n result: SearchResult,\n hitRequestSource: HitRequestSource = 'unknown',\n ) {\n const flags = this.getFlags(result);\n\n this.adIds = result.ad_id?.values;\n this.averageRating = result.avg_rating?.value;\n this.captureDates = result.capture_dates?.values;\n this.checked = false;\n this.collections = result.collection?.values ?? [];\n this.collectionFilesCount = result.collection_files_count?.value ?? 0;\n this.collectionSize = result.collection_size?.value ?? 0;\n this.commentCount = result.num_reviews?.value ?? 0;\n this.creator = result.creator?.value;\n this.creators = result.creator?.values ?? [];\n this.dateAdded = result.addeddate?.value;\n this.dateArchived = result.publicdate?.value;\n this.datePublished = result.date?.value;\n this.dateReviewed = result.reviewdate?.value;\n this.description = result.description?.values.join('\\n');\n this.factChecks = result.factcheck?.values;\n this.favCount = result.num_favorites?.value ?? 0;\n this.hitRequestSource = hitRequestSource;\n this.hitType = result.rawMetadata?.hit_type;\n this.href = collapseRepeatedQuotes(\n result.review?.__href__ ?? result.__href__?.value,\n );\n this.identifier = TileModel.cleanIdentifier(result.identifier);\n this.isClip = result.is_clip?.value;\n this.issue = result.issue?.value;\n this.itemCount = result.item_count?.value ?? 0;\n this.mediatype = resolveMediatype(result);\n this.review = result.review;\n this.snippets = result.highlight?.values ?? [];\n this.source = result.source?.value;\n this.subjects = result.subject?.values ?? [];\n this.thumbnailUrl = result.__img__?.value;\n this.title = result.title?.value ?? '';\n this.tvClipCount = result.num_clips?.value ?? 0;\n this.volume = result.volume?.value;\n this.viewCount = result.downloads?.value;\n this.weeklyViewCount = result.week?.value;\n this.loginRequired = flags.loginRequired;\n this.contentWarning = flags.contentWarning;\n }\n\n /**\n * Copies the contents of this TileModel onto a new instance\n */\n clone(): TileModel {\n const cloned = new TileModel({});\n cloned.adIds = this.adIds;\n cloned.averageRating = this.averageRating;\n cloned.captureDates = this.captureDates;\n cloned.checked = this.checked;\n cloned.collections = this.collections;\n cloned.collectionFilesCount = this.collectionFilesCount;\n cloned.collectionSize = this.collectionSize;\n cloned.commentCount = this.commentCount;\n cloned.creator = this.creator;\n cloned.creators = this.creators;\n cloned.dateStr = this.dateStr;\n cloned.dateAdded = this.dateAdded;\n cloned.dateArchived = this.dateArchived;\n cloned.datePublished = this.datePublished;\n cloned.dateReviewed = this.dateReviewed;\n cloned.description = this.description;\n cloned.factChecks = this.factChecks;\n cloned.favCount = this.favCount;\n cloned.hitRequestSource = this.hitRequestSource;\n cloned.hitType = this.hitType;\n cloned.href = this.href;\n cloned.identifier = this.identifier;\n cloned.isClip = this.isClip;\n cloned.issue = this.issue;\n cloned.itemCount = this.itemCount;\n cloned.mediatype = this.mediatype;\n cloned.snippets = this.snippets;\n cloned.source = this.source;\n cloned.subjects = this.subjects;\n cloned.thumbnailUrl = this.thumbnailUrl;\n cloned.title = this.title;\n cloned.tvClipCount = this.tvClipCount;\n cloned.volume = this.volume;\n cloned.viewCount = this.viewCount;\n cloned.weeklyViewCount = this.weeklyViewCount;\n cloned.loginRequired = this.loginRequired;\n cloned.contentWarning = this.contentWarning;\n return cloned;\n }\n\n /**\n * Whether this model represents the result of a TV search query.\n */\n get isTvSearchResult(): boolean {\n return (\n this.hitType === 'tv_clip' && this.hitRequestSource === 'search_query'\n );\n }\n\n /**\n * Determines the appropriate tile flags for the given search result\n * (login required and/or content warning)\n */\n private getFlags(result: SearchResult): TileFlags {\n const flags: TileFlags = {\n loginRequired: false,\n contentWarning: false,\n };\n\n // Check if item and item in \"modifying\" collection, setting above flags\n if (\n result.collection?.values.length &&\n result.mediatype?.value !== 'collection'\n ) {\n for (const collection of result.collection?.values ?? []) {\n if (collection === 'loggedin') {\n flags.loginRequired = true;\n if (flags.contentWarning) break;\n }\n if (collection === 'no-preview') {\n flags.contentWarning = true;\n if (flags.loginRequired) break;\n }\n }\n }\n\n return flags;\n }\n\n private static cleanIdentifier(\n identifier: string | undefined,\n ): string | undefined {\n // Some identifiers (e.g., from Whisper) represent documents rather than items, and\n // are suffixed with values that need to be stripped. Those values are separated\n // from the item identifier itself with '|'.\n const barIndex = identifier?.indexOf('|') ?? -1;\n const cleaned = barIndex > 0 ? identifier?.slice(0, barIndex) : identifier;\n return cleaned;\n }\n}\n\nexport type RequestKind = 'full' | 'hits' | 'aggregations';\n\nexport type CollectionDisplayMode = 'grid' | 'list-compact' | 'list-detail';\n\nexport type TileDisplayMode =\n | 'grid'\n | 'list-compact'\n | 'list-detail'\n | 'list-header';\n\n/**\n * This is mainly used to set the cookies for the collection display mode.\n *\n * It allows the user to set different modes for different contexts (collection page, search page, profile page etc).\n */\nexport type CollectionBrowserContext = 'collection' | 'search' | 'profile';\n\n/**\n * The sort fields shown in the sort filter bar\n */\nexport enum SortField {\n 'default' = 'default',\n 'unrecognized' = 'unrecognized',\n 'relevance' = 'relevance',\n 'alltimeview' = 'alltimeview',\n 'weeklyview' = 'weeklyview',\n 'title' = 'title',\n 'date' = 'date',\n 'datearchived' = 'datearchived',\n 'datereviewed' = 'datereviewed',\n 'dateadded' = 'dateadded',\n 'datefavorited' = 'datefavorited',\n 'creator' = 'creator',\n}\n\n/**\n * Views-related sort fields\n */\nexport const ALL_VIEWS_SORT_FIELDS = [\n SortField.weeklyview,\n SortField.alltimeview,\n] as const;\nexport type ViewsSortField = (typeof ALL_VIEWS_SORT_FIELDS)[number];\n\n/**\n * Date-related sort fields\n */\nexport const ALL_DATE_SORT_FIELDS = [\n SortField.datefavorited,\n SortField.date,\n SortField.datearchived,\n SortField.datereviewed,\n SortField.dateadded,\n] as const;\nexport type DateSortField = (typeof ALL_DATE_SORT_FIELDS)[number];\n\nexport interface SortOption {\n /**\n * The SortField enum member corresponding to this option.\n */\n field: SortField;\n\n /**\n * The default sort direction to apply when this sort option is first selected.\n */\n defaultSortDirection: SortDirection | null;\n\n /**\n * Whether this sort option allows its sort direction to be changed from the default.\n */\n canSetDirection: boolean;\n\n /**\n * Whether this sort option may appear in the sort bar.\n */\n shownInSortBar: boolean;\n\n /**\n * Whether this sort option should be saved to the URL.\n * If false, then no `sort` param will be added to the URL when this sort option\n * is selected.\n */\n shownInURL: boolean;\n\n /**\n * Whether this sort option is passed to the search service.\n * If false, then no sort param will be passed to the search service at all when\n * this sort option is selected.\n */\n handledBySearchService: boolean;\n\n /**\n * The string identifying this sort field to the search service & backend API.\n */\n searchServiceKey?: string;\n\n /**\n * The human-readable name to use for this option in the sort bar (if applicable).\n */\n displayName: string;\n\n /**\n * A list of URL param keys that should be mapped to this sort option.\n * E.g., both `title` and `titleSorter` in the URL map to the `SortField.title` option.\n */\n urlNames: (string | null | undefined)[];\n}\n\nexport const SORT_OPTIONS: Record<SortField, SortOption> = {\n // Default sort is the case where the user has not specified a sort option via the sort bar or URL.\n // In these cases, we defer to whatever sort the backend chooses.\n // For the search page, the default is always relevance sort.\n // For collection pages _without a query_, the default is usually weekly views, but this can be\n // overridden by the collection's `sort-by` metadata entry. If a query _is_ specified, then the\n // default is again relevance sort.\n // For fav-* collections only, the default is instead sorting by date favorited.\n [SortField.default]: {\n field: SortField.default,\n defaultSortDirection: null,\n canSetDirection: false,\n shownInSortBar: false,\n shownInURL: false,\n handledBySearchService: false, // We rely on the PPS default sort handling in these cases\n displayName: '',\n urlNames: ['', null, undefined], // Empty or nullish sort params result in default sorting\n },\n // Unrecognized sort is the case where the user has specified a sort in the URL, but it is not\n // one of the options listed in this map. We still want these unrecognized sorts to be applied\n // when searching, but they are not displayed in the sort bar and we do not actively manage\n // their URL param beyond flipping the direction as needed.\n [SortField.unrecognized]: {\n field: SortField.unrecognized,\n defaultSortDirection: null,\n canSetDirection: true,\n shownInSortBar: false,\n shownInURL: false,\n handledBySearchService: true, // The unrecognized sort param is passed along as-is\n displayName: '',\n urlNames: [],\n },\n // Relevance sort is unique in that it does not produce a URL param when it is set.\n // It is only available when there is a user-specified query that relevancy can be scored against.\n // Therefore, it does not appear as a sort bar option when browsing a collection with no query set.\n [SortField.relevance]: {\n field: SortField.relevance,\n defaultSortDirection: null,\n canSetDirection: false,\n shownInSortBar: true,\n shownInURL: false,\n handledBySearchService: false,\n displayName: 'Relevance',\n urlNames: ['_score'],\n },\n [SortField.alltimeview]: {\n field: SortField.alltimeview,\n defaultSortDirection: 'desc',\n canSetDirection: true,\n shownInSortBar: true,\n shownInURL: true,\n handledBySearchService: true,\n searchServiceKey: 'downloads',\n displayName: 'All-time views',\n urlNames: ['downloads'],\n },\n [SortField.weeklyview]: {\n field: SortField.weeklyview,\n defaultSortDirection: 'desc',\n canSetDirection: true,\n shownInSortBar: true,\n shownInURL: true,\n handledBySearchService: true,\n searchServiceKey: 'week',\n displayName: 'Weekly views',\n urlNames: ['week'],\n },\n [SortField.title]: {\n field: SortField.title,\n defaultSortDirection: 'asc',\n canSetDirection: true,\n shownInSortBar: true,\n shownInURL: true,\n handledBySearchService: true,\n searchServiceKey: 'titleSorter',\n displayName: 'Title',\n urlNames: ['title', 'titleSorter'],\n },\n [SortField.date]: {\n field: SortField.date,\n defaultSortDirection: 'desc',\n canSetDirection: true,\n shownInSortBar: true,\n shownInURL: true,\n handledBySearchService: true,\n searchServiceKey: 'date',\n displayName: 'Date published',\n urlNames: ['date'],\n },\n [SortField.datearchived]: {\n field: SortField.datearchived,\n defaultSortDirection: 'desc',\n canSetDirection: true,\n shownInSortBar: true,\n shownInURL: true,\n handledBySearchService: true,\n searchServiceKey: 'publicdate',\n displayName: 'Date archived',\n urlNames: ['publicdate'],\n },\n [SortField.datereviewed]: {\n field: SortField.datereviewed,\n defaultSortDirection: 'desc',\n canSetDirection: true,\n shownInSortBar: true,\n shownInURL: true,\n handledBySearchService: true,\n searchServiceKey: 'reviewdate',\n displayName: 'Date reviewed',\n urlNames: ['reviewdate'],\n },\n [SortField.dateadded]: {\n field: SortField.dateadded,\n defaultSortDirection: 'desc',\n canSetDirection: true,\n shownInSortBar: true,\n shownInURL: true,\n handledBySearchService: true,\n searchServiceKey: 'addeddate',\n displayName: 'Date added',\n urlNames: ['addeddate'],\n },\n [SortField.datefavorited]: {\n field: SortField.datefavorited,\n defaultSortDirection: 'desc',\n canSetDirection: false,\n shownInSortBar: true, // But only when viewing fav-* collections\n shownInURL: false,\n handledBySearchService: false,\n searchServiceKey: 'favoritedate',\n displayName: 'Date favorited',\n urlNames: ['favoritedate'],\n },\n [SortField.creator]: {\n field: SortField.creator,\n defaultSortDirection: 'asc',\n canSetDirection: true,\n shownInSortBar: true,\n shownInURL: true,\n handledBySearchService: true,\n searchServiceKey: 'creatorSorter',\n displayName: 'Creator',\n urlNames: ['creator', 'creatorSorter'],\n },\n};\n\n/**\n * Returns the SortOption corresponding to the given API sort name, or\n * the \"unrecognized\" SortOption if none matches.\n */\nexport function sortOptionFromAPIString(sortName?: string | null): SortOption {\n return (\n Object.values(SORT_OPTIONS).find(opt =>\n opt.urlNames.some(name => sortName === name),\n ) ?? SORT_OPTIONS[SortField.unrecognized]\n );\n}\n\nexport const defaultSortAvailability: Record<SortField, boolean> = {\n [SortField.relevance]: true,\n [SortField.weeklyview]: true,\n [SortField.alltimeview]: true,\n [SortField.title]: true,\n [SortField.datefavorited]: false,\n [SortField.date]: true,\n [SortField.datearchived]: true,\n [SortField.datereviewed]: true,\n [SortField.dateadded]: true,\n [SortField.creator]: true,\n [SortField.default]: false,\n [SortField.unrecognized]: false,\n};\n\nexport const favoritesSortAvailability: Record<SortField, boolean> = {\n ...defaultSortAvailability,\n [SortField.datefavorited]: true,\n};\n\nexport const tvSortAvailability: Record<SortField, boolean> = {\n ...defaultSortAvailability,\n [SortField.date]: false,\n [SortField.datereviewed]: false,\n [SortField.dateadded]: false,\n};\n\nexport const defaultProfileElementSorts: Record<\n string,\n Exclude<SortField, SortField.default>\n> = {\n uploads: SortField.datearchived,\n reviews: SortField.datereviewed,\n collections: SortField.datearchived,\n web_archives: SortField.datearchived,\n favorites: SortField.datefavorited,\n};\n\n/** A union of the fields that permit prefix filtering (e.g., alphabetical filtering) */\nexport type PrefixFilterType = 'title' | 'creator';\n\n/** A map from prefixes (e.g., initial letters) to the number of items matching that prefix */\nexport type PrefixFilterCounts = Record<string, number>;\n\n/**\n * A map from prefix filter types to the corresponding aggregation keys\n * that are needed to fetch the filter counts from the backend.\n */\nexport const prefixFilterAggregationKeys: Record<PrefixFilterType, string> = {\n title: 'firstTitle',\n creator: 'firstCreator',\n};\n\n/**\n * Different facet loading strategies that can be used with collection browser.\n * - `eager`: Facet data is always loaded as soon as a search is performed\n * - `lazy-mobile`: In the desktop layout, functions exactly as `eager`.\n * In the mobile layout, facet data will only be loaded once the \"Filters\" accordion is opened.\n * - `opt-in-or-login`: Same as `opt-in` for guest users not logged into an account, but same as `eager` for\n * any logged in user.\n * - `opt-in`: In the desktop layout, facet data will only be loaded after the user presses a \"Load Facets\" button.\n * In the mobile layout, functions exactly as `lazy-mobile`.\n * - `off`: Facet data will never be loaded, and a message will be displayed in place of facets\n * indicating that they are unavailable.\n */\nexport type FacetLoadStrategy =\n | 'eager'\n | 'lazy-mobile'\n | 'opt-in-or-login'\n | 'opt-in'\n | 'off';\n\n/**\n * Union of the facet types that are available in the sidebar.\n */\nexport type FacetOption =\n | 'subject'\n | 'lending'\n | 'mediatype'\n | 'language'\n | 'creator'\n | 'collection'\n | 'year'\n // TV-specific facet options:\n | 'clip_type'\n | 'program'\n | 'person'\n | 'sponsor';\n\nexport type SelectedFacetState = 'selected' | 'hidden';\n\nexport type FacetState = SelectedFacetState | 'none';\n\nexport interface FacetBucket {\n key: string;\n count: number;\n state: FacetState;\n // for some facets, we augment the key with a display value\n displayText?: string;\n // for TV channel facets, we add a parenthesized secondary name\n extraNote?: string;\n}\n\nexport interface FacetGroup {\n title: string;\n key: FacetOption;\n buckets: FacetBucket[];\n}\n\n/**\n * Information about a user interaction event on a facet.\n */\nexport type FacetEventDetails = {\n /**\n * The type of facet that was interacted with (e.g., 'mediatype', 'language', ...).\n */\n facetType: FacetOption;\n /**\n * The bucket corresponding to the facet that was interacted with, including the\n * updated state of the facet after the interaction.\n */\n bucket: FacetBucket;\n /**\n * Whether the interaction occurred on a negative facet.\n */\n negative: boolean;\n};\n\nexport type FacetValue = string;\n\nexport type SelectedFacets = Partial<\n Record<FacetOption, Record<FacetValue, FacetBucket>>\n>;\n\nexport const getDefaultSelectedFacets = (): Required<SelectedFacets> => ({\n subject: {},\n lending: {},\n mediatype: {},\n language: {},\n creator: {},\n collection: {},\n year: {},\n clip_type: {},\n program: {},\n person: {},\n sponsor: {},\n});\n\n/**\n * For TV search results, what types of TV clips to restrict the results to.\n */\nexport type TvClipFilterType = 'commercial' | 'fact check' | 'quote';\n\n/**\n * Map from allowed TV filtering parameters in the URL to their corresponding filter type\n */\nexport const tvClipURLParamsToFilters: Record<string, TvClipFilterType> = {\n only_commercials: 'commercial',\n only_factchecks: 'fact check',\n only_quotes: 'quote',\n};\n\n/**\n * Facet display order when presenting results for all search types *except* TV (see below).\n */\nexport const defaultFacetDisplayOrder: FacetOption[] = [\n 'mediatype',\n // 'lending', Commenting this out removes the lending facet from the sidebar for now\n 'year',\n 'subject',\n 'collection',\n 'creator',\n 'language',\n];\n\n/**\n * Specialized facet ordering when displaying TV search results\n */\nexport const tvFacetDisplayOrder: FacetOption[] = [\n 'program',\n 'creator',\n 'year',\n 'subject',\n // 'person', Omitting the Person facet group for now, though it may be re-added later with new semantics\n 'language',\n 'clip_type',\n];\n\n/**\n * Human-readable titles for each facet group.\n */\nexport const facetTitles: Record<FacetOption, string> = {\n subject: 'Subject',\n lending: 'Availability',\n mediatype: 'Media Type',\n language: 'Language',\n creator: 'Creator',\n collection: 'Collection',\n year: 'Year',\n clip_type: 'Clip Type',\n program: 'Program',\n person: 'Person',\n sponsor: 'Sponsor',\n};\n\n/**\n * Human-readable plural titles for each facet group, for referring to its values.\n */\nexport const facetPluralTitles: Record<FacetOption, string> = {\n subject: 'Subjects',\n lending: 'Availability',\n mediatype: 'Media Types',\n language: 'Languages',\n creator: 'Creators',\n collection: 'Collections',\n year: 'Years',\n clip_type: 'Clip Types',\n program: 'Programs',\n person: 'People',\n sponsor: 'Sponsors',\n};\n\n/**\n * The default sort type to use for each facet type\n */\nexport const defaultFacetSort: Record<FacetOption, AggregationSortType> = {\n subject: AggregationSortType.COUNT,\n lending: AggregationSortType.COUNT,\n mediatype: AggregationSortType.COUNT,\n language: AggregationSortType.COUNT,\n creator: AggregationSortType.COUNT,\n collection: AggregationSortType.COUNT,\n year: AggregationSortType.NUMERIC, // Year facets are ordered by their numeric value by default\n clip_type: AggregationSortType.COUNT,\n program: AggregationSortType.COUNT,\n person: AggregationSortType.COUNT,\n sponsor: AggregationSortType.COUNT,\n};\n\n/**\n * The default sort type to use for each facet type in TV search More... dialogs only\n */\nexport const tvMoreFacetSort: Record<FacetOption, AggregationSortType> = {\n ...defaultFacetSort,\n creator: AggregationSortType.ALPHABETICAL,\n program: AggregationSortType.ALPHABETICAL,\n};\n\n/**\n * The sort type corresponding to facet bucket values, for each facet type\n * (i.e., the opposite of \"sort by count\" for that type).\n */\nexport const valueFacetSort: Record<FacetOption, AggregationSortType> = {\n subject: AggregationSortType.ALPHABETICAL,\n lending: AggregationSortType.ALPHABETICAL,\n mediatype: AggregationSortType.ALPHABETICAL,\n language: AggregationSortType.ALPHABETICAL,\n creator: AggregationSortType.ALPHABETICAL,\n collection: AggregationSortType.ALPHABETICAL,\n year: AggregationSortType.NUMERIC, // Year facets' values should be compared numerically, not lexicographically (year 2001 > year 3)\n clip_type: AggregationSortType.ALPHABETICAL,\n program: AggregationSortType.ALPHABETICAL,\n person: AggregationSortType.ALPHABETICAL,\n sponsor: AggregationSortType.ALPHABETICAL,\n};\n\nexport type LendingFacetKey =\n | 'is_lendable'\n | 'is_borrowable'\n | 'available_to_borrow'\n | 'is_browsable'\n | 'available_to_browse'\n | 'is_readable'\n | 'available_to_waitlist';\n\n/**\n * Maps valid lending keys to whether they should be visible in the facet sidebar\n */\nexport const lendingFacetKeysVisibility: Record<LendingFacetKey, boolean> = {\n is_lendable: true,\n is_borrowable: false,\n available_to_borrow: true,\n is_browsable: false,\n available_to_browse: false,\n is_readable: true,\n available_to_waitlist: false,\n};\n\n/**\n * Most facet options allow any string as keys, while some others can only take on a\n * limited set of strings. This type just defines those restrictions for the specific\n * facet types where they apply.\n */\nexport type AllowedFacetKey<T extends FacetOption> = T extends 'lending'\n ? LendingFacetKey\n : T extends 'clip_type'\n ? TvClipFilterType\n : string;\n\n/**\n * A type mapping FacetOptions to objects that define custom display names for some\n * or all of their valid keys.\n */\nexport type FacetDisplayNameMap = {\n [K in FacetOption]?: Partial<Record<AllowedFacetKey<K>, string>>;\n};\n\nexport const customFacetDisplayNames: FacetDisplayNameMap = {\n lending: {\n is_lendable: 'Lending Library',\n available_to_borrow: 'Borrow 14 Days',\n is_readable: 'Always Available',\n },\n clip_type: {\n quote: 'Quote',\n commercial: 'Political Ad',\n 'fact check': 'Fact Check',\n },\n};\n\n/**\n * A record of which admin-only collections should be suppressed from being displayed\n * as facets or in an item's list of collections.\n */\nexport const suppressedCollections: Record<string, boolean> = {\n deemphasize: true,\n community: true,\n stream_only: true,\n samples_only: true,\n test_collection: true,\n printdisabled: true,\n 'openlibrary-ol': true,\n nationalemergencylibrary: true,\n china: true,\n americana: true,\n toronto: true,\n};\n\n/**\n * A record of manageable item\n */\nexport interface ManageableItem {\n identifier: string;\n title?: string;\n dateStr?: string;\n date?: string;\n}\n\n/**\n * Possible states for whether & how the user has overridden their user preference\n * for blurring behavior on tiles with sensitive content.\n * - `no-override`: The user has not overridden their user preference, so simply\n * respect the preference as given.\n * - `on`: The user has overridden their preference and wants tile blurring enabled.\n * - `off`: The user has overridden their preference and wants tile blurring disabled.\n */\nexport type TileBlurOverrideState = 'no-override' | 'on' | 'off';\n"]}
|
package/dist/src/utils/log.d.ts
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* console.log() utility -- production ignores 'log()' JS calls; dev invokes 'console.log()'
|
|
3
3
|
*/
|
|
4
|
-
export declare const log:
|
|
5
|
-
(...data: any[]): void;
|
|
6
|
-
(message?: any, ...optionalParams: any[]): void;
|
|
7
|
-
};
|
|
4
|
+
export declare const log: (...data: any[]) => void;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The forms of a piece of text that loose "contains" matching compares. See
|
|
3
|
+
* `normalizeFilterText`.
|
|
4
|
+
*/
|
|
5
|
+
export type NormalizedFilterText = {
|
|
6
|
+
/** With word-joining punctuation turned into spaces */
|
|
7
|
+
spaced: string;
|
|
8
|
+
/** With word-joining punctuation removed */
|
|
9
|
+
joined: string;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Reduces text to the forms used for loose "contains" matching: lowercased,
|
|
13
|
+
* with accents and punctuation removed and runs of whitespace collapsed.
|
|
14
|
+
* Apply it to both the filter term and the values being filtered, then
|
|
15
|
+
* compare them with `filterTextIncludes`.
|
|
16
|
+
*
|
|
17
|
+
* Punctuation that joins words goes both ways, since people type those words
|
|
18
|
+
* apart and together: `spaced` turns it into spaces, so `wc tv` matches
|
|
19
|
+
* `WC-TV`, and `joined` removes it, so `wctv` does too. Other punctuation is
|
|
20
|
+
* removed outright, so `aor` matches `A.O.R.` and `dr drew` matches
|
|
21
|
+
* `Dr. Drew`. The two forms only differ for text with word-joining
|
|
22
|
+
* punctuation.
|
|
23
|
+
*/
|
|
24
|
+
export declare function normalizeFilterText(text: string): NormalizedFilterText;
|
|
25
|
+
/**
|
|
26
|
+
* Whether normalized `text` contains the normalized `filter`, in either form
|
|
27
|
+
*/
|
|
28
|
+
export declare function filterTextIncludes(text: NormalizedFilterText, filter: NormalizedFilterText): boolean;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** Punctuation that joins words: hyphens and dashes, underscores, slashes */
|
|
2
|
+
const WORD_JOINERS = /[\p{Pd}\p{Pc}/]/gu;
|
|
3
|
+
/**
|
|
4
|
+
* Reduces text to the forms used for loose "contains" matching: lowercased,
|
|
5
|
+
* with accents and punctuation removed and runs of whitespace collapsed.
|
|
6
|
+
* Apply it to both the filter term and the values being filtered, then
|
|
7
|
+
* compare them with `filterTextIncludes`.
|
|
8
|
+
*
|
|
9
|
+
* Punctuation that joins words goes both ways, since people type those words
|
|
10
|
+
* apart and together: `spaced` turns it into spaces, so `wc tv` matches
|
|
11
|
+
* `WC-TV`, and `joined` removes it, so `wctv` does too. Other punctuation is
|
|
12
|
+
* removed outright, so `aor` matches `A.O.R.` and `dr drew` matches
|
|
13
|
+
* `Dr. Drew`. The two forms only differ for text with word-joining
|
|
14
|
+
* punctuation.
|
|
15
|
+
*/
|
|
16
|
+
export function normalizeFilterText(text) {
|
|
17
|
+
const base = text
|
|
18
|
+
.normalize('NFKD')
|
|
19
|
+
.replace(/\p{M}/gu, '')
|
|
20
|
+
.toLocaleLowerCase();
|
|
21
|
+
return {
|
|
22
|
+
spaced: removePunctuation(base.replace(WORD_JOINERS, ' ')),
|
|
23
|
+
joined: removePunctuation(base.replace(WORD_JOINERS, '')),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Whether normalized `text` contains the normalized `filter`, in either form
|
|
28
|
+
*/
|
|
29
|
+
export function filterTextIncludes(text, filter) {
|
|
30
|
+
return (text.spaced.includes(filter.spaced) || text.joined.includes(filter.joined));
|
|
31
|
+
}
|
|
32
|
+
function removePunctuation(text) {
|
|
33
|
+
return text.replace(/\p{P}/gu, '').replace(/\s+/g, ' ').trim();
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=normalize-filter-text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-filter-text.js","sourceRoot":"","sources":["../../../src/utils/normalize-filter-text.ts"],"names":[],"mappings":"AAYA,6EAA6E;AAC7E,MAAM,YAAY,GAAG,mBAAmB,CAAC;AAEzC;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,MAAM,IAAI,GAAG,IAAI;SACd,SAAS,CAAC,MAAM,CAAC;SACjB,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;SACtB,iBAAiB,EAAE,CAAC;IACvB,OAAO;QACL,MAAM,EAAE,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;QAC1D,MAAM,EAAE,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;KAC1D,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAA0B,EAC1B,MAA4B;IAE5B,OAAO,CACL,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAC3E,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY;IACrC,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AACjE,CAAC","sourcesContent":["/**\n * The forms of a piece of text that loose \"contains\" matching compares. See\n * `normalizeFilterText`.\n */\nexport type NormalizedFilterText = {\n /** With word-joining punctuation turned into spaces */\n spaced: string;\n\n /** With word-joining punctuation removed */\n joined: string;\n};\n\n/** Punctuation that joins words: hyphens and dashes, underscores, slashes */\nconst WORD_JOINERS = /[\\p{Pd}\\p{Pc}/]/gu;\n\n/**\n * Reduces text to the forms used for loose \"contains\" matching: lowercased,\n * with accents and punctuation removed and runs of whitespace collapsed.\n * Apply it to both the filter term and the values being filtered, then\n * compare them with `filterTextIncludes`.\n *\n * Punctuation that joins words goes both ways, since people type those words\n * apart and together: `spaced` turns it into spaces, so `wc tv` matches\n * `WC-TV`, and `joined` removes it, so `wctv` does too. Other punctuation is\n * removed outright, so `aor` matches `A.O.R.` and `dr drew` matches\n * `Dr. Drew`. The two forms only differ for text with word-joining\n * punctuation.\n */\nexport function normalizeFilterText(text: string): NormalizedFilterText {\n const base = text\n .normalize('NFKD')\n .replace(/\\p{M}/gu, '')\n .toLocaleLowerCase();\n return {\n spaced: removePunctuation(base.replace(WORD_JOINERS, ' ')),\n joined: removePunctuation(base.replace(WORD_JOINERS, '')),\n };\n}\n\n/**\n * Whether normalized `text` contains the normalized `filter`, in either form\n */\nexport function filterTextIncludes(\n text: NormalizedFilterText,\n filter: NormalizedFilterText,\n): boolean {\n return (\n text.spaced.includes(filter.spaced) || text.joined.includes(filter.joined)\n );\n}\n\nfunction removePunctuation(text: string): string {\n return text.replace(/\\p{P}/gu, '').replace(/\\s+/g, ' ').trim();\n}\n"]}
|