@internetarchive/collection-browser 4.8.0 → 4.8.1-webdev-9227.1
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/README.md +33 -0
- package/dist/src/collection-browser.d.ts +2 -1
- package/dist/src/collection-browser.js +3 -3
- package/dist/src/collection-browser.js.map +1 -1
- package/dist/src/collection-facets/more-facets-content.js +3 -2
- package/dist/src/collection-facets/more-facets-content.js.map +1 -1
- package/dist/src/collection-facets/more-facets-scroller.js +3 -2
- package/dist/src/collection-facets/more-facets-scroller.js.map +1 -1
- package/dist/src/collection-facets.js +3 -2
- package/dist/src/collection-facets.js.map +1 -1
- package/dist/src/empty-placeholder.d.ts +7 -7
- package/dist/src/empty-placeholder.js +29 -15
- package/dist/src/empty-placeholder.js.map +1 -1
- package/dist/src/expanded-date-picker.js +3 -2
- package/dist/src/expanded-date-picker.js.map +1 -1
- package/dist/src/locales/es.d.ts +94 -0
- package/dist/src/locales/es.js +109 -0
- package/dist/src/locales/es.js.map +1 -0
- package/dist/src/manage/manage-bar.d.ts +3 -2
- package/dist/src/manage/manage-bar.js +6 -7
- package/dist/src/manage/manage-bar.js.map +1 -1
- package/dist/src/manage/remove-items-modal-content.js +3 -2
- package/dist/src/manage/remove-items-modal-content.js.map +1 -1
- package/dist/src/models.js +6 -2
- package/dist/src/models.js.map +1 -1
- package/dist/src/sort-filter-bar/sort-filter-bar.js +3 -2
- package/dist/src/sort-filter-bar/sort-filter-bar.js.map +1 -1
- package/dist/src/tiles/grid/account-tile.js +3 -2
- package/dist/src/tiles/grid/account-tile.js.map +1 -1
- package/dist/src/tiles/grid/collection-tile.js +3 -2
- package/dist/src/tiles/grid/collection-tile.js.map +1 -1
- package/dist/src/tiles/grid/item-tile.js +3 -2
- package/dist/src/tiles/grid/item-tile.js.map +1 -1
- package/dist/src/tiles/grid/tile-stats.js +3 -2
- package/dist/src/tiles/grid/tile-stats.js.map +1 -1
- package/dist/src/tiles/list/tile-list-compact-header.js +3 -2
- package/dist/src/tiles/list/tile-list-compact-header.js.map +1 -1
- package/dist/src/tiles/list/tile-list-compact.js +3 -1
- package/dist/src/tiles/list/tile-list-compact.js.map +1 -1
- package/dist/src/tiles/list/tile-list.js +3 -2
- package/dist/src/tiles/list/tile-list.js.map +1 -1
- package/dist/src/tiles/overlay/text-overlay.js +3 -1
- package/dist/src/tiles/overlay/text-overlay.js.map +1 -1
- package/dist/src/tiles/review-block.js +3 -2
- package/dist/src/tiles/review-block.js.map +1 -1
- package/dist/src/tiles/tile-dispatcher.d.ts +2 -1
- package/dist/src/tiles/tile-dispatcher.js +5 -4
- package/dist/src/tiles/tile-dispatcher.js.map +1 -1
- package/locales/es.d.ts +1 -0
- package/locales/es.js +1 -0
- package/package.json +13 -1
- package/.editorconfig +0 -29
- package/.github/workflows/ci.yml +0 -29
- package/.github/workflows/gh-pages-main.yml +0 -41
- package/.github/workflows/npm-publish.yml +0 -42
- package/.github/workflows/pr-preview.yml +0 -40
- package/.husky/pre-commit +0 -1
- package/.prettierignore +0 -1
- package/dist/test/collection-browser.test.d.ts +0 -1
- package/dist/test/collection-browser.test.js +0 -1815
- package/dist/test/collection-browser.test.js.map +0 -1
- package/dist/test/collection-facets/facet-row.test.d.ts +0 -1
- package/dist/test/collection-facets/facet-row.test.js +0 -291
- package/dist/test/collection-facets/facet-row.test.js.map +0 -1
- package/dist/test/collection-facets/facets-template.test.d.ts +0 -1
- package/dist/test/collection-facets/facets-template.test.js +0 -95
- package/dist/test/collection-facets/facets-template.test.js.map +0 -1
- package/dist/test/collection-facets/more-facets-content.test.d.ts +0 -1
- package/dist/test/collection-facets/more-facets-content.test.js +0 -509
- package/dist/test/collection-facets/more-facets-content.test.js.map +0 -1
- package/dist/test/collection-facets/more-facets-scroller.test.d.ts +0 -1
- package/dist/test/collection-facets/more-facets-scroller.test.js +0 -288
- package/dist/test/collection-facets/more-facets-scroller.test.js.map +0 -1
- package/dist/test/collection-facets/page-window.test.d.ts +0 -1
- package/dist/test/collection-facets/page-window.test.js +0 -175
- package/dist/test/collection-facets/page-window.test.js.map +0 -1
- package/dist/test/collection-facets/toggle-switch.test.d.ts +0 -1
- package/dist/test/collection-facets/toggle-switch.test.js +0 -99
- package/dist/test/collection-facets/toggle-switch.test.js.map +0 -1
- package/dist/test/collection-facets.test.d.ts +0 -2
- package/dist/test/collection-facets.test.js +0 -728
- package/dist/test/collection-facets.test.js.map +0 -1
- package/dist/test/data-source/collection-browser-data-source.test.d.ts +0 -1
- package/dist/test/data-source/collection-browser-data-source.test.js +0 -154
- package/dist/test/data-source/collection-browser-data-source.test.js.map +0 -1
- package/dist/test/empty-placeholder.test.d.ts +0 -1
- package/dist/test/empty-placeholder.test.js +0 -57
- package/dist/test/empty-placeholder.test.js.map +0 -1
- package/dist/test/expanded-date-picker.test.d.ts +0 -1
- package/dist/test/expanded-date-picker.test.js +0 -124
- package/dist/test/expanded-date-picker.test.js.map +0 -1
- package/dist/test/icon-overlay.test.d.ts +0 -1
- package/dist/test/icon-overlay.test.js +0 -31
- package/dist/test/icon-overlay.test.js.map +0 -1
- package/dist/test/image-block.test.d.ts +0 -1
- package/dist/test/image-block.test.js +0 -208
- package/dist/test/image-block.test.js.map +0 -1
- package/dist/test/item-image.test.d.ts +0 -1
- package/dist/test/item-image.test.js +0 -187
- package/dist/test/item-image.test.js.map +0 -1
- package/dist/test/manage/manage-bar.test.d.ts +0 -3
- package/dist/test/manage/manage-bar.test.js +0 -216
- package/dist/test/manage/manage-bar.test.js.map +0 -1
- package/dist/test/manage/remove-items-modal-content.test.d.ts +0 -1
- package/dist/test/manage/remove-items-modal-content.test.js +0 -60
- package/dist/test/manage/remove-items-modal-content.test.js.map +0 -1
- package/dist/test/mediatype-config.test.d.ts +0 -1
- package/dist/test/mediatype-config.test.js +0 -11
- package/dist/test/mediatype-config.test.js.map +0 -1
- package/dist/test/mocks/mock-analytics-handler.d.ts +0 -10
- package/dist/test/mocks/mock-analytics-handler.js +0 -16
- package/dist/test/mocks/mock-analytics-handler.js.map +0 -1
- package/dist/test/mocks/mock-search-responses.d.ts +0 -37
- package/dist/test/mocks/mock-search-responses.js +0 -1293
- package/dist/test/mocks/mock-search-responses.js.map +0 -1
- package/dist/test/mocks/mock-search-service.d.ts +0 -16
- package/dist/test/mocks/mock-search-service.js +0 -65
- package/dist/test/mocks/mock-search-service.js.map +0 -1
- package/dist/test/restoration-state-handler.test.d.ts +0 -1
- package/dist/test/restoration-state-handler.test.js +0 -335
- package/dist/test/restoration-state-handler.test.js.map +0 -1
- package/dist/test/review-block.test.d.ts +0 -1
- package/dist/test/review-block.test.js +0 -46
- package/dist/test/review-block.test.js.map +0 -1
- package/dist/test/sort-filter-bar/alpha-bar-tooltip.test.d.ts +0 -1
- package/dist/test/sort-filter-bar/alpha-bar-tooltip.test.js +0 -12
- package/dist/test/sort-filter-bar/alpha-bar-tooltip.test.js.map +0 -1
- package/dist/test/sort-filter-bar/alpha-bar.test.d.ts +0 -1
- package/dist/test/sort-filter-bar/alpha-bar.test.js +0 -68
- package/dist/test/sort-filter-bar/alpha-bar.test.js.map +0 -1
- package/dist/test/sort-filter-bar/sort-filter-bar.test.d.ts +0 -1
- package/dist/test/sort-filter-bar/sort-filter-bar.test.js +0 -304
- package/dist/test/sort-filter-bar/sort-filter-bar.test.js.map +0 -1
- package/dist/test/text-overlay.test.d.ts +0 -1
- package/dist/test/text-overlay.test.js +0 -43
- package/dist/test/text-overlay.test.js.map +0 -1
- package/dist/test/text-snippet-block.test.d.ts +0 -1
- package/dist/test/text-snippet-block.test.js +0 -58
- package/dist/test/text-snippet-block.test.js.map +0 -1
- package/dist/test/tile-stats.test.d.ts +0 -1
- package/dist/test/tile-stats.test.js +0 -167
- package/dist/test/tile-stats.test.js.map +0 -1
- package/dist/test/tiles/grid/account-tile.test.d.ts +0 -1
- package/dist/test/tiles/grid/account-tile.test.js +0 -96
- package/dist/test/tiles/grid/account-tile.test.js.map +0 -1
- package/dist/test/tiles/grid/collection-tile.test.d.ts +0 -1
- package/dist/test/tiles/grid/collection-tile.test.js +0 -90
- package/dist/test/tiles/grid/collection-tile.test.js.map +0 -1
- package/dist/test/tiles/grid/item-tile.test.d.ts +0 -1
- package/dist/test/tiles/grid/item-tile.test.js +0 -400
- package/dist/test/tiles/grid/item-tile.test.js.map +0 -1
- package/dist/test/tiles/grid/search-tile.test.d.ts +0 -1
- package/dist/test/tiles/grid/search-tile.test.js +0 -62
- package/dist/test/tiles/grid/search-tile.test.js.map +0 -1
- package/dist/test/tiles/hover/hover-pane-controller.test.d.ts +0 -1
- package/dist/test/tiles/hover/hover-pane-controller.test.js +0 -351
- package/dist/test/tiles/hover/hover-pane-controller.test.js.map +0 -1
- package/dist/test/tiles/hover/tile-hover-pane.test.d.ts +0 -1
- package/dist/test/tiles/hover/tile-hover-pane.test.js +0 -53
- package/dist/test/tiles/hover/tile-hover-pane.test.js.map +0 -1
- package/dist/test/tiles/list/tile-list-compact-header.test.d.ts +0 -1
- package/dist/test/tiles/list/tile-list-compact-header.test.js +0 -36
- package/dist/test/tiles/list/tile-list-compact-header.test.js.map +0 -1
- package/dist/test/tiles/list/tile-list-compact.test.d.ts +0 -1
- package/dist/test/tiles/list/tile-list-compact.test.js +0 -237
- package/dist/test/tiles/list/tile-list-compact.test.js.map +0 -1
- package/dist/test/tiles/list/tile-list.test.d.ts +0 -1
- package/dist/test/tiles/list/tile-list.test.js +0 -460
- package/dist/test/tiles/list/tile-list.test.js.map +0 -1
- package/dist/test/tiles/tile-dispatcher.test.d.ts +0 -1
- package/dist/test/tiles/tile-dispatcher.test.js +0 -246
- package/dist/test/tiles/tile-dispatcher.test.js.map +0 -1
- package/dist/test/tiles/tile-display-value-provider.test.d.ts +0 -1
- package/dist/test/tiles/tile-display-value-provider.test.js +0 -142
- package/dist/test/tiles/tile-display-value-provider.test.js.map +0 -1
- package/dist/test/tiles/tile-mediatype-icon.test.d.ts +0 -1
- package/dist/test/tiles/tile-mediatype-icon.test.js +0 -133
- package/dist/test/tiles/tile-mediatype-icon.test.js.map +0 -1
- package/dist/test/utils/array-equals.test.d.ts +0 -1
- package/dist/test/utils/array-equals.test.js +0 -27
- package/dist/test/utils/array-equals.test.js.map +0 -1
- package/dist/test/utils/format-count.test.d.ts +0 -1
- package/dist/test/utils/format-count.test.js +0 -24
- package/dist/test/utils/format-count.test.js.map +0 -1
- package/dist/test/utils/format-date.test.d.ts +0 -1
- package/dist/test/utils/format-date.test.js +0 -61
- package/dist/test/utils/format-date.test.js.map +0 -1
- package/dist/test/utils/format-unit-size.test.d.ts +0 -1
- package/dist/test/utils/format-unit-size.test.js +0 -18
- package/dist/test/utils/format-unit-size.test.js.map +0 -1
- package/dist/test/utils/local-date-from-utc.test.d.ts +0 -1
- package/dist/test/utils/local-date-from-utc.test.js +0 -27
- package/dist/test/utils/local-date-from-utc.test.js.map +0 -1
- package/dist/test/utils/normalize-filter-text.test.d.ts +0 -1
- package/dist/test/utils/normalize-filter-text.test.js +0 -69
- package/dist/test/utils/normalize-filter-text.test.js.map +0 -1
- package/docs/design/column-virtualization.md +0 -214
- package/eslint.config.mjs +0 -53
- package/index.html +0 -24
- package/index.ts +0 -29
- package/local.archive.org.cert +0 -86
- package/local.archive.org.key +0 -27
- package/pnpm-workspace.yaml +0 -30
- package/renovate.json +0 -6
- package/src/app-root.ts +0 -1282
- package/src/assets/img/icons/arrow-left.ts +0 -10
- package/src/assets/img/icons/arrow-right.ts +0 -10
- package/src/assets/img/icons/check.ts +0 -5
- package/src/assets/img/icons/chevron.ts +0 -4
- package/src/assets/img/icons/close-circle-dark.ts +0 -5
- package/src/assets/img/icons/contract.ts +0 -9
- package/src/assets/img/icons/empty-query.ts +0 -5
- package/src/assets/img/icons/expand.ts +0 -9
- package/src/assets/img/icons/eye-closed.ts +0 -5
- package/src/assets/img/icons/eye.ts +0 -5
- package/src/assets/img/icons/favorite-filled.ts +0 -10
- package/src/assets/img/icons/favorite-unfilled.ts +0 -9
- package/src/assets/img/icons/filter.ts +0 -10
- package/src/assets/img/icons/login-required.ts +0 -18
- package/src/assets/img/icons/mediatype/account.ts +0 -14
- package/src/assets/img/icons/mediatype/audio.ts +0 -14
- package/src/assets/img/icons/mediatype/collection.ts +0 -12
- package/src/assets/img/icons/mediatype/data.ts +0 -15
- package/src/assets/img/icons/mediatype/etree.ts +0 -14
- package/src/assets/img/icons/mediatype/film.ts +0 -14
- package/src/assets/img/icons/mediatype/images.ts +0 -13
- package/src/assets/img/icons/mediatype/radio.ts +0 -15
- package/src/assets/img/icons/mediatype/search.ts +0 -14
- package/src/assets/img/icons/mediatype/software.ts +0 -13
- package/src/assets/img/icons/mediatype/texts.ts +0 -13
- package/src/assets/img/icons/mediatype/tv-commercial.ts +0 -12
- package/src/assets/img/icons/mediatype/tv-fact-check.ts +0 -12
- package/src/assets/img/icons/mediatype/tv-quote.ts +0 -12
- package/src/assets/img/icons/mediatype/tv.ts +0 -14
- package/src/assets/img/icons/mediatype/video.ts +0 -14
- package/src/assets/img/icons/mediatype/web.ts +0 -13
- package/src/assets/img/icons/null-result.ts +0 -5
- package/src/assets/img/icons/quote.ts +0 -7
- package/src/assets/img/icons/restricted.ts +0 -13
- package/src/assets/img/icons/reviews.ts +0 -11
- package/src/assets/img/icons/upload.ts +0 -12
- package/src/assets/img/icons/views.ts +0 -11
- package/src/circular-activity-indicator.ts +0 -64
- package/src/collection-browser.ts +0 -3165
- package/src/collection-facets/facet-row-template.ts +0 -242
- package/src/collection-facets/facet-row.ts +0 -122
- package/src/collection-facets/facet-tombstone-row.ts +0 -40
- package/src/collection-facets/facets-template.ts +0 -85
- package/src/collection-facets/models.ts +0 -16
- package/src/collection-facets/more-facets-content.ts +0 -951
- package/src/collection-facets/more-facets-scroller.ts +0 -485
- package/src/collection-facets/page-window.ts +0 -247
- package/src/collection-facets/smart-facets/dedupe.ts +0 -44
- package/src/collection-facets/smart-facets/heuristics/browser-language/browser-language-heuristic.ts +0 -27
- package/src/collection-facets/smart-facets/heuristics/index.ts +0 -3
- package/src/collection-facets/smart-facets/heuristics/query-keywords/query-keywords-heuristic.ts +0 -17
- package/src/collection-facets/smart-facets/heuristics/query-keywords/query-keywords-map.ts +0 -70
- package/src/collection-facets/smart-facets/heuristics/wikidata/wikidata-entity-map.ts +0 -79
- package/src/collection-facets/smart-facets/heuristics/wikidata/wikidata-heuristic.ts +0 -93
- package/src/collection-facets/smart-facets/models.ts +0 -36
- package/src/collection-facets/smart-facets/smart-facet-bar.ts +0 -437
- package/src/collection-facets/smart-facets/smart-facet-button.ts +0 -145
- package/src/collection-facets/smart-facets/smart-facet-dropdown.ts +0 -185
- package/src/collection-facets/smart-facets/smart-facet-equals.ts +0 -16
- package/src/collection-facets/smart-facets/smart-facet-heuristics.ts +0 -26
- package/src/collection-facets/toggle-switch.ts +0 -175
- package/src/collection-facets.ts +0 -1013
- package/src/data-source/collection-browser-data-source-interface.ts +0 -351
- package/src/data-source/collection-browser-data-source.ts +0 -1474
- package/src/data-source/collection-browser-query-state.ts +0 -60
- package/src/data-source/models.ts +0 -56
- package/src/empty-placeholder.ts +0 -192
- package/src/expanded-date-picker.ts +0 -191
- package/src/language-code-handler/language-code-handler.ts +0 -64
- package/src/language-code-handler/language-code-mapping.ts +0 -564
- package/src/manage/manage-bar.ts +0 -276
- package/src/manage/remove-items-modal-content.ts +0 -102
- package/src/mediatype/mediatype-config.ts +0 -146
- package/src/models.ts +0 -912
- package/src/restoration-state-handler.ts +0 -550
- package/src/sort-filter-bar/alpha-bar-tooltip.ts +0 -53
- package/src/sort-filter-bar/alpha-bar.ts +0 -252
- package/src/sort-filter-bar/img/compact.ts +0 -5
- package/src/sort-filter-bar/img/list.ts +0 -5
- package/src/sort-filter-bar/img/sort-toggle-disabled.ts +0 -15
- package/src/sort-filter-bar/img/sort-toggle-down.ts +0 -17
- package/src/sort-filter-bar/img/sort-toggle-up.ts +0 -17
- package/src/sort-filter-bar/img/sort-triangle.ts +0 -5
- package/src/sort-filter-bar/img/tile.ts +0 -5
- package/src/sort-filter-bar/sort-filter-bar.ts +0 -733
- package/src/styles/ia-button.ts +0 -139
- package/src/styles/item-image-styles.ts +0 -124
- package/src/styles/sr-only.ts +0 -18
- package/src/styles/tile-action-styles.ts +0 -59
- package/src/tiles/base-tile-component.ts +0 -124
- package/src/tiles/collection-browser-loading-tile.ts +0 -26
- package/src/tiles/grid/account-tile.ts +0 -113
- package/src/tiles/grid/collection-tile.ts +0 -184
- package/src/tiles/grid/item-tile.ts +0 -347
- package/src/tiles/grid/search-tile.ts +0 -90
- package/src/tiles/grid/styles/tile-grid-shared-styles.ts +0 -130
- package/src/tiles/grid/tile-stats.ts +0 -211
- package/src/tiles/hover/hover-pane-controller.ts +0 -638
- package/src/tiles/hover/tile-hover-pane.ts +0 -184
- package/src/tiles/image-block.ts +0 -162
- package/src/tiles/item-image.ts +0 -214
- package/src/tiles/list/tile-list-compact-header.ts +0 -112
- package/src/tiles/list/tile-list-compact.ts +0 -278
- package/src/tiles/list/tile-list.ts +0 -718
- package/src/tiles/models.ts +0 -21
- package/src/tiles/overlay/icon-overlay.ts +0 -57
- package/src/tiles/overlay/text-overlay.ts +0 -79
- package/src/tiles/review-block.ts +0 -130
- package/src/tiles/text-snippet-block.ts +0 -132
- package/src/tiles/tile-dispatcher.ts +0 -637
- package/src/tiles/tile-display-value-provider.ts +0 -133
- package/src/tiles/tile-mediatype-icon.ts +0 -133
- package/src/utils/analytics-events.ts +0 -29
- package/src/utils/array-equals.ts +0 -8
- package/src/utils/collapse-repeated-quotes.ts +0 -13
- package/src/utils/date-filter-field.ts +0 -11
- package/src/utils/facet-utils.ts +0 -183
- package/src/utils/format-count.ts +0 -95
- package/src/utils/format-date.ts +0 -62
- package/src/utils/format-unit-size.ts +0 -43
- package/src/utils/local-date-from-utc.ts +0 -15
- package/src/utils/log.ts +0 -14
- package/src/utils/normalize-filter-text.ts +0 -54
- package/src/utils/resolve-mediatype.ts +0 -26
- package/src/utils/sha1.ts +0 -9
- package/test/collection-browser.test.ts +0 -2639
- package/test/collection-facets/facet-row.test.ts +0 -421
- package/test/collection-facets/facets-template.test.ts +0 -139
- package/test/collection-facets/more-facets-content.test.ts +0 -716
- package/test/collection-facets/more-facets-scroller.test.ts +0 -401
- package/test/collection-facets/page-window.test.ts +0 -208
- package/test/collection-facets/toggle-switch.test.ts +0 -164
- package/test/collection-facets.test.ts +0 -928
- package/test/data-source/collection-browser-data-source.test.ts +0 -193
- package/test/empty-placeholder.test.ts +0 -88
- package/test/expanded-date-picker.test.ts +0 -201
- package/test/icon-overlay.test.ts +0 -38
- package/test/image-block.test.ts +0 -247
- package/test/item-image.test.ts +0 -220
- package/test/manage/manage-bar.test.ts +0 -347
- package/test/manage/remove-items-modal-content.test.ts +0 -81
- package/test/mediatype-config.test.ts +0 -11
- package/test/mocks/mock-analytics-handler.ts +0 -30
- package/test/mocks/mock-search-responses.ts +0 -1420
- package/test/mocks/mock-search-service.ts +0 -136
- package/test/restoration-state-handler.test.ts +0 -480
- package/test/review-block.test.ts +0 -62
- package/test/sort-filter-bar/alpha-bar-tooltip.test.ts +0 -17
- package/test/sort-filter-bar/alpha-bar.test.ts +0 -101
- package/test/sort-filter-bar/sort-filter-bar.test.ts +0 -443
- package/test/text-overlay.test.ts +0 -55
- package/test/text-snippet-block.test.ts +0 -85
- package/test/tile-stats.test.ts +0 -191
- package/test/tiles/grid/account-tile.test.ts +0 -121
- package/test/tiles/grid/collection-tile.test.ts +0 -114
- package/test/tiles/grid/item-tile.test.ts +0 -520
- package/test/tiles/grid/search-tile.test.ts +0 -75
- package/test/tiles/hover/hover-pane-controller.test.ts +0 -482
- package/test/tiles/hover/tile-hover-pane.test.ts +0 -80
- package/test/tiles/list/tile-list-compact-header.test.ts +0 -43
- package/test/tiles/list/tile-list-compact.test.ts +0 -282
- package/test/tiles/list/tile-list.test.ts +0 -576
- package/test/tiles/tile-dispatcher.test.ts +0 -320
- package/test/tiles/tile-display-value-provider.test.ts +0 -172
- package/test/tiles/tile-mediatype-icon.test.ts +0 -160
- package/test/utils/array-equals.test.ts +0 -31
- package/test/utils/format-count.test.ts +0 -32
- package/test/utils/format-date.test.ts +0 -89
- package/test/utils/format-unit-size.test.ts +0 -21
- package/test/utils/local-date-from-utc.test.ts +0 -37
- package/test/utils/normalize-filter-text.test.ts +0 -87
- package/tsconfig.json +0 -25
- package/types/dompurify.d.ts +0 -1
- package/vite.config.ts +0 -29
- package/web-dev-server.config.mjs +0 -30
- package/web-test-runner.config.mjs +0 -57
|
@@ -1,247 +0,0 @@
|
|
|
1
|
-
import type { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
2
|
-
|
|
3
|
-
export type PageWindowConfig = {
|
|
4
|
-
/** Width in px of every column. Columns are uniform. */
|
|
5
|
-
colWidth: number;
|
|
6
|
-
|
|
7
|
-
/** Total number of columns in the dataset. */
|
|
8
|
-
total: number;
|
|
9
|
-
|
|
10
|
-
/** Pages kept mounted on each side of the visible ones. Defaults to 1. */
|
|
11
|
-
buffer?: number;
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Called each time the scroller comes to rest (or is re-laid out), with the
|
|
15
|
-
* page it rests on. Fires even when that page hasn't changed.
|
|
16
|
-
*/
|
|
17
|
-
onRest?: (page: number) => void;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const supportsScrollEnd = 'onscrollend' in window;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Windowing controller for a horizontal scroller of fixed-width columns that
|
|
24
|
-
* snaps to page boundaries. Tracks which pages should be in the DOM (`first`
|
|
25
|
-
* through `last`) and which page the scroller last came to rest on.
|
|
26
|
-
*
|
|
27
|
-
* All positions are arithmetic on `colWidth`; the only measurement is the
|
|
28
|
-
* scroller's width, which comes from a ResizeObserver.
|
|
29
|
-
*
|
|
30
|
-
* See docs/design/column-virtualization.md before changing this, especially
|
|
31
|
-
* its invariants.
|
|
32
|
-
*/
|
|
33
|
-
export class PageWindow implements ReactiveController {
|
|
34
|
-
/** Index of the first mounted page. */
|
|
35
|
-
first = 0;
|
|
36
|
-
|
|
37
|
-
/** Index of the last mounted page, or -1 when nothing is mounted. */
|
|
38
|
-
last = -1;
|
|
39
|
-
|
|
40
|
-
/** How many columns fit in the scroller, derived from its measured width. */
|
|
41
|
-
colsPerPage = 1;
|
|
42
|
-
|
|
43
|
-
/** The page the scroller last came to rest on. */
|
|
44
|
-
currentPage = 0;
|
|
45
|
-
|
|
46
|
-
private scroller?: HTMLElement;
|
|
47
|
-
|
|
48
|
-
private viewportW = 0;
|
|
49
|
-
|
|
50
|
-
private frame = 0;
|
|
51
|
-
|
|
52
|
-
private landFrame = 0;
|
|
53
|
-
|
|
54
|
-
private endTimer = 0;
|
|
55
|
-
|
|
56
|
-
private ro?: ResizeObserver;
|
|
57
|
-
|
|
58
|
-
/** Page to realign to once the host has re-rendered at a new page width. */
|
|
59
|
-
private realignTo?: number;
|
|
60
|
-
|
|
61
|
-
/** Whether to re-check the resting page once the host has re-rendered. */
|
|
62
|
-
private relandAfterUpdate = false;
|
|
63
|
-
|
|
64
|
-
constructor(
|
|
65
|
-
private host: ReactiveControllerHost,
|
|
66
|
-
private cfg: PageWindowConfig,
|
|
67
|
-
) {
|
|
68
|
-
host.addController(this);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
get pageWidth(): number {
|
|
72
|
-
return this.cfg.colWidth * this.colsPerPage;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
get pageCount(): number {
|
|
76
|
-
return Math.ceil(this.cfg.total / this.colsPerPage);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
get totalWidth(): number {
|
|
80
|
-
return this.cfg.colWidth * this.cfg.total;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Width of page `i`. Every page is `pageWidth` except a partial last page,
|
|
85
|
-
* which is trimmed so that nothing extends the scroll area past `totalWidth`.
|
|
86
|
-
*/
|
|
87
|
-
pageSpan(i: number): number {
|
|
88
|
-
return Math.min(this.pageWidth, this.totalWidth - i * this.pageWidth);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/** Updates the number of columns, e.g. when the dataset is filtered. */
|
|
92
|
-
setTotal(total: number): void {
|
|
93
|
-
if (total === this.cfg.total) return;
|
|
94
|
-
this.cfg.total = total;
|
|
95
|
-
this.recompute(true);
|
|
96
|
-
// The sizer hasn't resized yet, so wait for the host to render before
|
|
97
|
-
// reading where the scroller rests.
|
|
98
|
-
this.relandAfterUpdate = true;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/** Scrolls so that `page` sits at the start of the viewport. */
|
|
102
|
-
scrollToPage(page: number, behavior: ScrollBehavior = 'auto'): void {
|
|
103
|
-
const target = Math.max(0, Math.min(page, this.pageCount - 1));
|
|
104
|
-
this.scroller?.scrollTo({ left: target * this.pageWidth, behavior });
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/** Ref callback for the scroll container. */
|
|
108
|
-
attach = (el?: Element): void => {
|
|
109
|
-
const next = el instanceof HTMLElement ? el : undefined;
|
|
110
|
-
if (next === this.scroller) return;
|
|
111
|
-
this.detach();
|
|
112
|
-
if (!next) return;
|
|
113
|
-
|
|
114
|
-
this.scroller = next;
|
|
115
|
-
next.addEventListener('scroll', this.onScroll, { passive: true });
|
|
116
|
-
if (supportsScrollEnd) {
|
|
117
|
-
next.addEventListener('scrollend', this.onScrollEnd);
|
|
118
|
-
} else {
|
|
119
|
-
next.addEventListener('scroll', this.onScrollIdle, { passive: true });
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
this.ro = new ResizeObserver(([e]) => this.onResize(e.contentRect.width));
|
|
123
|
-
this.ro.observe(next);
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
hostUpdated(): void {
|
|
127
|
-
const el = this.scroller;
|
|
128
|
-
if (!el) return;
|
|
129
|
-
// A resize changed the page width. The host has now moved the snap stubs,
|
|
130
|
-
// so put the page that held the anchor column back at the start.
|
|
131
|
-
if (this.realignTo !== undefined) {
|
|
132
|
-
const target = this.realignTo * this.pageWidth;
|
|
133
|
-
// After a layout change WebKit re-snaps to the snap point with the same
|
|
134
|
-
// index as before, which is now a different column. Assigning the
|
|
135
|
-
// position the scroller already has is a no-op that doesn't update that
|
|
136
|
-
// index, so nudge it first.
|
|
137
|
-
if (el.scrollLeft === target) el.scrollLeft = target + 1;
|
|
138
|
-
el.scrollLeft = target;
|
|
139
|
-
this.realignTo = undefined;
|
|
140
|
-
this.relandAfterUpdate = true;
|
|
141
|
-
}
|
|
142
|
-
if (this.relandAfterUpdate && !this.landFrame) {
|
|
143
|
-
this.relandAfterUpdate = false;
|
|
144
|
-
// Next frame, so as not to update the host again from inside its update
|
|
145
|
-
this.landFrame = requestAnimationFrame(() => {
|
|
146
|
-
this.landFrame = 0;
|
|
147
|
-
this.land();
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
hostDisconnected(): void {
|
|
153
|
-
this.detach();
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
private detach(): void {
|
|
157
|
-
const el = this.scroller;
|
|
158
|
-
if (!el) return;
|
|
159
|
-
el.removeEventListener('scroll', this.onScroll);
|
|
160
|
-
el.removeEventListener('scroll', this.onScrollIdle);
|
|
161
|
-
el.removeEventListener('scrollend', this.onScrollEnd);
|
|
162
|
-
this.ro?.disconnect();
|
|
163
|
-
this.ro = undefined;
|
|
164
|
-
if (this.frame) cancelAnimationFrame(this.frame);
|
|
165
|
-
if (this.landFrame) cancelAnimationFrame(this.landFrame);
|
|
166
|
-
this.frame = 0;
|
|
167
|
-
this.landFrame = 0;
|
|
168
|
-
clearTimeout(this.endTimer);
|
|
169
|
-
this.scroller = undefined;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
private onResize(width: number): void {
|
|
173
|
-
const el = this.scroller;
|
|
174
|
-
if (!el) return;
|
|
175
|
-
this.viewportW = width;
|
|
176
|
-
|
|
177
|
-
const colsPerPage = Math.max(1, Math.floor(width / this.cfg.colWidth));
|
|
178
|
-
if (colsPerPage === this.colsPerPage) {
|
|
179
|
-
this.recompute();
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// Columns never move (column c always starts at c * colWidth); only the
|
|
184
|
-
// page boundaries do. Keep the leftmost visible column on screen by
|
|
185
|
-
// realigning to whichever new page contains it.
|
|
186
|
-
const anchorCol = Math.round(el.scrollLeft / this.cfg.colWidth);
|
|
187
|
-
this.colsPerPage = colsPerPage;
|
|
188
|
-
this.realignTo = Math.floor(anchorCol / colsPerPage);
|
|
189
|
-
this.recompute(true);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
private onScroll = (): void => {
|
|
193
|
-
if (this.frame) return;
|
|
194
|
-
this.frame = requestAnimationFrame(() => {
|
|
195
|
-
this.frame = 0;
|
|
196
|
-
this.recompute();
|
|
197
|
-
});
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
/** Fallback for browsers without `scrollend`: treat 120ms of quiet as rest. */
|
|
201
|
-
private onScrollIdle = (): void => {
|
|
202
|
-
clearTimeout(this.endTimer);
|
|
203
|
-
this.endTimer = window.setTimeout(this.onScrollEnd, 120);
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
private onScrollEnd = (): void => {
|
|
207
|
-
this.land();
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
private recompute(force = false): void {
|
|
211
|
-
const el = this.scroller;
|
|
212
|
-
if (!el) return;
|
|
213
|
-
const pw = this.pageWidth;
|
|
214
|
-
const buf = this.cfg.buffer ?? 1;
|
|
215
|
-
const left = el.scrollLeft;
|
|
216
|
-
const first = Math.max(0, Math.floor(left / pw) - buf);
|
|
217
|
-
// Floor on both edges, so that first and last shift together at each page
|
|
218
|
-
// boundary rather than one just before it and one just after.
|
|
219
|
-
const last = Math.min(
|
|
220
|
-
this.pageCount - 1,
|
|
221
|
-
Math.floor((left + this.viewportW) / pw) + buf,
|
|
222
|
-
);
|
|
223
|
-
// Most scroll events end here: the window only changes at page boundaries
|
|
224
|
-
if (!force && first === this.first && last === this.last) return;
|
|
225
|
-
this.first = first;
|
|
226
|
-
this.last = last;
|
|
227
|
-
this.host.requestUpdate();
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/** Records which page the scroller is resting on. */
|
|
231
|
-
private land(): void {
|
|
232
|
-
const el = this.scroller;
|
|
233
|
-
if (!el) return;
|
|
234
|
-
const left = el.scrollLeft;
|
|
235
|
-
const maxLeft = this.totalWidth - this.viewportW;
|
|
236
|
-
// A partial last page can't reach its own snap point, so resting at the
|
|
237
|
-
// far end counts as landing on the last page.
|
|
238
|
-
const atEnd = left >= maxLeft - 1;
|
|
239
|
-
const page = atEnd ? this.pageCount - 1 : Math.round(left / this.pageWidth);
|
|
240
|
-
const clamped = Math.max(0, Math.min(page, this.pageCount - 1));
|
|
241
|
-
if (clamped !== this.currentPage) {
|
|
242
|
-
this.currentPage = clamped;
|
|
243
|
-
this.host.requestUpdate();
|
|
244
|
-
}
|
|
245
|
-
this.cfg.onRest?.(clamped);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import type { SmartFacet } from './models';
|
|
2
|
-
import { smartFacetEquals } from './smart-facet-equals';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Removes any duplicated smart facets from the given array.
|
|
6
|
-
* Smart facets are equal if they have the same `label` and same
|
|
7
|
-
* set of facet refs. Only the first occurrence of a given smart
|
|
8
|
-
* facet is kept.
|
|
9
|
-
* @param facets The array of smart facets to deduplicate
|
|
10
|
-
* @returns A new array containing the deduplicated set of facets
|
|
11
|
-
*/
|
|
12
|
-
export function dedupe<T extends SmartFacet[] | SmartFacet[][]>(facets: T): T {
|
|
13
|
-
if (!Array.isArray(facets[0])) {
|
|
14
|
-
const facetsUnnested = facets as SmartFacet[];
|
|
15
|
-
|
|
16
|
-
let result: SmartFacet[] = [...facetsUnnested];
|
|
17
|
-
for (let i = 0; i < result.length; i++) {
|
|
18
|
-
const curFacet = result[i];
|
|
19
|
-
result = result.filter(
|
|
20
|
-
sf => curFacet === sf || !smartFacetEquals(curFacet, sf),
|
|
21
|
-
);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return result as T;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const facetsNested = facets as SmartFacet[][];
|
|
28
|
-
|
|
29
|
-
const result: SmartFacet[][] = [];
|
|
30
|
-
for (const curFacetArray of facetsNested) {
|
|
31
|
-
const subresult: SmartFacet[] = [];
|
|
32
|
-
for (const curFacet of curFacetArray) {
|
|
33
|
-
const existing = result.find(sfa =>
|
|
34
|
-
sfa.find(sf => smartFacetEquals(curFacet, sf)),
|
|
35
|
-
);
|
|
36
|
-
if (!existing) subresult.push(curFacet);
|
|
37
|
-
}
|
|
38
|
-
if (subresult.length > 0) {
|
|
39
|
-
result.push(subresult);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return result as T;
|
|
44
|
-
}
|
package/src/collection-facets/smart-facets/heuristics/browser-language/browser-language-heuristic.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import type { SmartQueryHeuristic, SmartFacet } from '../../models';
|
|
2
|
-
|
|
3
|
-
export class BrowserLanguageHeuristic implements SmartQueryHeuristic {
|
|
4
|
-
async getRecommendedFacets(): Promise<SmartFacet[]> {
|
|
5
|
-
const browserLanguageCode = navigator.language;
|
|
6
|
-
const languageName =
|
|
7
|
-
BrowserLanguageHeuristic.getLanguageDisplayName(browserLanguageCode);
|
|
8
|
-
if (!languageName) return [];
|
|
9
|
-
|
|
10
|
-
return [
|
|
11
|
-
{
|
|
12
|
-
facets: [
|
|
13
|
-
{
|
|
14
|
-
facetType: 'language',
|
|
15
|
-
bucketKey: languageName,
|
|
16
|
-
},
|
|
17
|
-
],
|
|
18
|
-
},
|
|
19
|
-
];
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
private static getLanguageDisplayName(langCode: string): string | undefined {
|
|
23
|
-
// Strip off any script/region/variant codes for greater generality
|
|
24
|
-
const languageOnly = langCode.split('-')[0];
|
|
25
|
-
return new Intl.DisplayNames(['en'], { type: 'language' }).of(languageOnly);
|
|
26
|
-
}
|
|
27
|
-
}
|
package/src/collection-facets/smart-facets/heuristics/query-keywords/query-keywords-heuristic.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { SmartQueryHeuristic, SmartFacet } from '../../models';
|
|
2
|
-
import { QUERY_KEYWORDS } from './query-keywords-map';
|
|
3
|
-
|
|
4
|
-
// If the query contains X keyword but Y facet isn't selected, recommend facet Y
|
|
5
|
-
export class QueryKeywordsHeuristic implements SmartQueryHeuristic {
|
|
6
|
-
async getRecommendedFacets(query: string): Promise<SmartFacet[]> {
|
|
7
|
-
const recommendations: SmartFacet[] = [];
|
|
8
|
-
|
|
9
|
-
for (const [keyword, facets] of Object.entries(QUERY_KEYWORDS)) {
|
|
10
|
-
if (query.includes(keyword)) {
|
|
11
|
-
recommendations.push(...facets);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
return recommendations;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import type { KeywordFacetMap, SmartFacet } from '../../models';
|
|
2
|
-
|
|
3
|
-
const TEXTS: SmartFacet = {
|
|
4
|
-
facets: [{ facetType: 'mediatype', bucketKey: 'texts' }],
|
|
5
|
-
};
|
|
6
|
-
const AUDIO: SmartFacet = {
|
|
7
|
-
facets: [{ facetType: 'mediatype', bucketKey: 'audio' }],
|
|
8
|
-
};
|
|
9
|
-
const MOVIES: SmartFacet = {
|
|
10
|
-
facets: [{ facetType: 'mediatype', bucketKey: 'movies' }],
|
|
11
|
-
};
|
|
12
|
-
const IMAGE: SmartFacet = {
|
|
13
|
-
facets: [{ facetType: 'mediatype', bucketKey: 'image' }],
|
|
14
|
-
};
|
|
15
|
-
const SOFTWARE: SmartFacet = {
|
|
16
|
-
facets: [{ facetType: 'mediatype', bucketKey: 'software' }],
|
|
17
|
-
};
|
|
18
|
-
const ETREE: SmartFacet = {
|
|
19
|
-
facets: [{ facetType: 'mediatype', bucketKey: 'etree' }],
|
|
20
|
-
};
|
|
21
|
-
const WEB: SmartFacet = {
|
|
22
|
-
facets: [{ facetType: 'mediatype', bucketKey: 'web' }],
|
|
23
|
-
};
|
|
24
|
-
const DATA: SmartFacet = {
|
|
25
|
-
facets: [{ facetType: 'mediatype', bucketKey: 'data' }],
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Map from keywords found in the search query to an array of
|
|
30
|
-
* likely-relevant "smart facets" for those keywords.
|
|
31
|
-
*/
|
|
32
|
-
export const QUERY_KEYWORDS: Readonly<KeywordFacetMap> = {
|
|
33
|
-
text: [TEXTS],
|
|
34
|
-
book: [TEXTS],
|
|
35
|
-
novel: [TEXTS],
|
|
36
|
-
magazine: [TEXTS],
|
|
37
|
-
newspaper: [TEXTS],
|
|
38
|
-
pdf: [TEXTS],
|
|
39
|
-
epub: [TEXTS],
|
|
40
|
-
audio: [AUDIO],
|
|
41
|
-
song: [AUDIO],
|
|
42
|
-
music: [AUDIO],
|
|
43
|
-
listen: [AUDIO],
|
|
44
|
-
podcast: [AUDIO],
|
|
45
|
-
radio: [AUDIO],
|
|
46
|
-
stream: [AUDIO, MOVIES],
|
|
47
|
-
video: [MOVIES],
|
|
48
|
-
movie: [MOVIES],
|
|
49
|
-
film: [MOVIES],
|
|
50
|
-
animation: [MOVIES],
|
|
51
|
-
youtube: [MOVIES],
|
|
52
|
-
image: [IMAGE],
|
|
53
|
-
photo: [IMAGE],
|
|
54
|
-
picture: [IMAGE],
|
|
55
|
-
painting: [IMAGE],
|
|
56
|
-
jpg: [IMAGE],
|
|
57
|
-
jpeg: [IMAGE],
|
|
58
|
-
png: [IMAGE],
|
|
59
|
-
gif: [IMAGE],
|
|
60
|
-
software: [SOFTWARE],
|
|
61
|
-
app: [SOFTWARE],
|
|
62
|
-
program: [SOFTWARE],
|
|
63
|
-
game: [SOFTWARE],
|
|
64
|
-
arcade: [SOFTWARE],
|
|
65
|
-
etree: [ETREE],
|
|
66
|
-
concert: [ETREE],
|
|
67
|
-
'live music': [ETREE],
|
|
68
|
-
'web crawl': [WEB],
|
|
69
|
-
dataset: [DATA],
|
|
70
|
-
};
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import type { KeywordFacetMap, SmartFacet } from '../../models';
|
|
2
|
-
|
|
3
|
-
const WRITTEN_WORK_SMART_FACETS: SmartFacet[] = [
|
|
4
|
-
{ facets: [{ facetType: 'mediatype', bucketKey: 'texts' }] },
|
|
5
|
-
];
|
|
6
|
-
|
|
7
|
-
const FILMMAKER_SMART_FACETS: SmartFacet[] = [
|
|
8
|
-
{
|
|
9
|
-
label: 'Films by __QUERY',
|
|
10
|
-
facets: [
|
|
11
|
-
{ facetType: 'mediatype', bucketKey: 'movies' },
|
|
12
|
-
{ facetType: 'creator', bucketKey: '__QUERY' },
|
|
13
|
-
],
|
|
14
|
-
},
|
|
15
|
-
];
|
|
16
|
-
|
|
17
|
-
const AUTHOR_SMART_FACETS: SmartFacet[] = [
|
|
18
|
-
{
|
|
19
|
-
label: 'Writing by __QUERY',
|
|
20
|
-
facets: [
|
|
21
|
-
{ facetType: 'mediatype', bucketKey: 'texts' },
|
|
22
|
-
{ facetType: 'creator', bucketKey: '__QUERY' },
|
|
23
|
-
],
|
|
24
|
-
},
|
|
25
|
-
];
|
|
26
|
-
|
|
27
|
-
const VISUAL_ARTIST_SMART_FACETS: SmartFacet[] = [
|
|
28
|
-
{
|
|
29
|
-
label: 'Images by __QUERY',
|
|
30
|
-
facets: [
|
|
31
|
-
{ facetType: 'mediatype', bucketKey: 'image' },
|
|
32
|
-
{ facetType: 'creator', bucketKey: '__QUERY' },
|
|
33
|
-
],
|
|
34
|
-
},
|
|
35
|
-
];
|
|
36
|
-
|
|
37
|
-
const MUSICIAN_SMART_FACETS: SmartFacet[] = [
|
|
38
|
-
{
|
|
39
|
-
label: 'Music by __QUERY',
|
|
40
|
-
facets: [
|
|
41
|
-
{ facetType: 'mediatype', bucketKey: 'audio' },
|
|
42
|
-
{ facetType: 'creator', bucketKey: '__QUERY' },
|
|
43
|
-
],
|
|
44
|
-
},
|
|
45
|
-
];
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Map from Wikidata description keywords for a given entity to a
|
|
49
|
-
* set of likely-relevant "smart facets" for that query.
|
|
50
|
-
*
|
|
51
|
-
* The placeholder string "__QUERY" should be substituted for the actual
|
|
52
|
-
* queried entity when generating facet values.
|
|
53
|
-
*/
|
|
54
|
-
export const WIKIDATA_ENTITIES: Readonly<KeywordFacetMap> = {
|
|
55
|
-
'written work': WRITTEN_WORK_SMART_FACETS,
|
|
56
|
-
literature: WRITTEN_WORK_SMART_FACETS,
|
|
57
|
-
book: WRITTEN_WORK_SMART_FACETS,
|
|
58
|
-
novel: WRITTEN_WORK_SMART_FACETS,
|
|
59
|
-
|
|
60
|
-
filmmaker: FILMMAKER_SMART_FACETS,
|
|
61
|
-
director: FILMMAKER_SMART_FACETS,
|
|
62
|
-
|
|
63
|
-
author: AUTHOR_SMART_FACETS,
|
|
64
|
-
writer: AUTHOR_SMART_FACETS,
|
|
65
|
-
novelist: AUTHOR_SMART_FACETS,
|
|
66
|
-
essayist: AUTHOR_SMART_FACETS,
|
|
67
|
-
poet: AUTHOR_SMART_FACETS,
|
|
68
|
-
|
|
69
|
-
'visual artist': VISUAL_ARTIST_SMART_FACETS,
|
|
70
|
-
'graphic artist': VISUAL_ARTIST_SMART_FACETS,
|
|
71
|
-
photographer: VISUAL_ARTIST_SMART_FACETS,
|
|
72
|
-
painter: VISUAL_ARTIST_SMART_FACETS,
|
|
73
|
-
|
|
74
|
-
singer: MUSICIAN_SMART_FACETS,
|
|
75
|
-
songwriter: MUSICIAN_SMART_FACETS,
|
|
76
|
-
musician: MUSICIAN_SMART_FACETS,
|
|
77
|
-
composer: MUSICIAN_SMART_FACETS,
|
|
78
|
-
pianist: MUSICIAN_SMART_FACETS,
|
|
79
|
-
};
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import type { SmartQueryHeuristic, SmartFacet } from '../../models';
|
|
2
|
-
import { WIKIDATA_ENTITIES } from './wikidata-entity-map';
|
|
3
|
-
|
|
4
|
-
// If wikidata describes the top query result as X, recommend facet Y, e.g.:
|
|
5
|
-
// X Y
|
|
6
|
-
// written work mt:texts
|
|
7
|
-
// film mt:movies
|
|
8
|
-
// author mt:texts and creator:<query>
|
|
9
|
-
// filmmaker mt:movies and creator:<query>
|
|
10
|
-
// photographer mt:image and creator:<query>
|
|
11
|
-
// visual artist mt:image and creator:<query>
|
|
12
|
-
// etc.
|
|
13
|
-
export class WikidataHeuristic implements SmartQueryHeuristic {
|
|
14
|
-
private readonly WIKIDATA_BASE_URL = 'https://www.wikidata.org/w/api.php';
|
|
15
|
-
|
|
16
|
-
private readonly WIKIDATA_DEFAULT_ARGS =
|
|
17
|
-
'?action=wbsearchentities&format=json&language=en&uselang=en&origin=*&type=item&limit=5';
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Returns the full URL for a Wikidata search for the given query
|
|
21
|
-
* @param query The query to search for
|
|
22
|
-
*/
|
|
23
|
-
private getWikidataURL(query: string): string {
|
|
24
|
-
const urlQuery = encodeURIComponent(query);
|
|
25
|
-
return `${this.WIKIDATA_BASE_URL}${this.WIKIDATA_DEFAULT_ARGS}&search=${urlQuery}`;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Replaces query placeholders with an actual query string, within a collection of smart facets
|
|
30
|
-
* @param smartFacets The array of smart facets
|
|
31
|
-
* @param query The query string to replace placeholders with
|
|
32
|
-
* @returns A new array of smart facets with all query placeholders replaced
|
|
33
|
-
*/
|
|
34
|
-
private replaceQueryPlaceholders(
|
|
35
|
-
smartFacets: SmartFacet[],
|
|
36
|
-
query: string,
|
|
37
|
-
): SmartFacet[] {
|
|
38
|
-
return smartFacets.map(
|
|
39
|
-
smartFacet =>
|
|
40
|
-
({
|
|
41
|
-
// Replace placeholders within the smart facet label
|
|
42
|
-
label: smartFacet.label?.replace('__QUERY', query),
|
|
43
|
-
// Replace placeholders within the facets themselves (buckets & display text)
|
|
44
|
-
facets: smartFacet.facets.map(facet => {
|
|
45
|
-
const replaced = {
|
|
46
|
-
...facet,
|
|
47
|
-
bucketKey: facet.bucketKey.replace(
|
|
48
|
-
'__QUERY',
|
|
49
|
-
query.toLowerCase(),
|
|
50
|
-
),
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
if (facet.displayText) {
|
|
54
|
-
replaced.displayText = replaced.displayText?.replace(
|
|
55
|
-
'__QUERY',
|
|
56
|
-
query,
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return replaced;
|
|
61
|
-
}),
|
|
62
|
-
}) as SmartFacet,
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* @inheritdoc
|
|
68
|
-
*/
|
|
69
|
-
async getRecommendedFacets(query: string): Promise<SmartFacet[]> {
|
|
70
|
-
const recommendations: SmartFacet[] = [];
|
|
71
|
-
|
|
72
|
-
try {
|
|
73
|
-
const wikidataURL = this.getWikidataURL(query);
|
|
74
|
-
const wikidataResponse = await fetch(wikidataURL);
|
|
75
|
-
const searchResults = await wikidataResponse.json();
|
|
76
|
-
|
|
77
|
-
for (const [keyword, facets] of Object.entries(WIKIDATA_ENTITIES)) {
|
|
78
|
-
const keywordRegex = new RegExp(`\\b${keyword}\\b`);
|
|
79
|
-
if (keywordRegex.test(searchResults.search[0]?.description)) {
|
|
80
|
-
const entityName = searchResults.search[0].label;
|
|
81
|
-
recommendations.push(
|
|
82
|
-
...this.replaceQueryPlaceholders(facets, entityName),
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return recommendations;
|
|
88
|
-
} catch (err) {
|
|
89
|
-
console.warn(err);
|
|
90
|
-
return [];
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import type { FacetEventDetails, FacetOption } from '../../models';
|
|
2
|
-
|
|
3
|
-
export interface FacetRef {
|
|
4
|
-
facetType: FacetOption;
|
|
5
|
-
bucketKey: string;
|
|
6
|
-
displayText?: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
interface LabeledSmartFacet {
|
|
10
|
-
label: string;
|
|
11
|
-
facets: FacetRef[];
|
|
12
|
-
selected?: boolean;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
interface UnlabeledSmartFacet {
|
|
16
|
-
label?: string;
|
|
17
|
-
facets: [FacetRef];
|
|
18
|
-
selected?: boolean;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export type SmartFacet = LabeledSmartFacet | UnlabeledSmartFacet;
|
|
22
|
-
|
|
23
|
-
export interface SmartFacetEvent {
|
|
24
|
-
smartFacet: SmartFacet;
|
|
25
|
-
details: FacetEventDetails[];
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export type KeywordFacetMap = Record<string, SmartFacet[]>;
|
|
29
|
-
|
|
30
|
-
export interface SmartQueryHeuristic {
|
|
31
|
-
/**
|
|
32
|
-
* Resolves to a recommended set of facets to apply for the given query
|
|
33
|
-
* @param query The search query to recommend facets for
|
|
34
|
-
*/
|
|
35
|
-
getRecommendedFacets(query: string): Promise<SmartFacet[]>;
|
|
36
|
-
}
|