@internetarchive/collection-browser 4.1.0 → 4.1.1-alpha-webdev8185.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.
Files changed (30) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.js +1 -1
  3. package/dist/index.js.map +1 -1
  4. package/dist/src/collection-browser.d.ts +9 -18
  5. package/dist/src/collection-browser.js +779 -838
  6. package/dist/src/collection-browser.js.map +1 -1
  7. package/dist/src/data-source/collection-browser-data-source.js +2 -3
  8. package/dist/src/data-source/collection-browser-data-source.js.map +1 -1
  9. package/dist/src/data-source/collection-browser-query-state.d.ts +5 -3
  10. package/dist/src/data-source/collection-browser-query-state.js.map +1 -1
  11. package/dist/src/models.d.ts +27 -2
  12. package/dist/src/models.js +36 -0
  13. package/dist/src/models.js.map +1 -1
  14. package/dist/src/sort-filter-bar/sort-filter-bar.d.ts +2 -2
  15. package/dist/src/sort-filter-bar/sort-filter-bar.js +280 -280
  16. package/dist/src/sort-filter-bar/sort-filter-bar.js.map +1 -1
  17. package/dist/test/collection-browser.test.js +204 -206
  18. package/dist/test/collection-browser.test.js.map +1 -1
  19. package/dist/test/sort-filter-bar/sort-filter-bar.test.js +22 -22
  20. package/dist/test/sort-filter-bar/sort-filter-bar.test.js.map +1 -1
  21. package/index.ts +5 -0
  22. package/package.json +1 -1
  23. package/src/collection-browser.ts +3001 -3070
  24. package/src/data-source/collection-browser-data-source.ts +1443 -1444
  25. package/src/data-source/collection-browser-query-state.ts +69 -60
  26. package/src/models.ts +53 -4
  27. package/src/sort-filter-bar/sort-filter-bar.ts +732 -733
  28. package/test/collection-browser.test.ts +2400 -2402
  29. package/test/sort-filter-bar/sort-filter-bar.test.ts +443 -443
  30. package/.claude/settings.local.json +0 -8
@@ -5,7 +5,7 @@ import { classMap } from 'lit/directives/class-map.js';
5
5
  import { msg } from '@lit/localize';
6
6
  import { SearchType, } from '@internetarchive/search-service';
7
7
  import '@internetarchive/infinite-scroller';
8
- import { SortField, getDefaultSelectedFacets, sortOptionFromAPIString, SORT_OPTIONS, defaultProfileElementSorts, defaultFacetDisplayOrder, tvFacetDisplayOrder, defaultSortAvailability, favoritesSortAvailability, tvSortAvailability, } from './models';
8
+ import { SortField, getDefaultSelectedFacets, SORT_OPTIONS, defaultFacetDisplayOrder, tvFacetDisplayOrder, defaultSortAvailability, favoritesSortAvailability, tvSortAvailability, } from './models';
9
9
  import { RestorationStateHandler, } from './restoration-state-handler';
10
10
  import { CollectionBrowserDataSource } from './data-source/collection-browser-data-source';
11
11
  import { FACETLESS_PAGE_ELEMENTS } from './data-source/models';
@@ -373,37 +373,34 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
373
373
  }
374
374
  willUpdate(changed) {
375
375
  this.setPlaceholderType();
376
- if (changed.has('searchType') && this.searchType === SearchType.TV) {
377
- this.applyDefaultTVSearchSort();
378
- }
379
376
  }
380
377
  render() {
381
- return html `
378
+ return html `
382
379
  ${this.showSmartFacetBar && this.placeholderType === null
383
- ? html `<smart-facet-bar
384
- .query=${this.baseQuery}
385
- .aggregations=${this.dataSource.aggregations}
386
- .selectedFacets=${this.selectedFacets}
387
- .collectionTitles=${this.dataSource.collectionTitles}
388
- .filterToggleShown=${!this.mobileView}
389
- .filterToggleActive=${this.facetPaneVisible}
390
- .label=${this.smartFacetBarLabel}
391
- @facetsChanged=${this.facetsChanged}
380
+ ? html `<smart-facet-bar
381
+ .query=${this.baseQuery}
382
+ .aggregations=${this.dataSource.aggregations}
383
+ .selectedFacets=${this.selectedFacets}
384
+ .collectionTitles=${this.dataSource.collectionTitles}
385
+ .filterToggleShown=${!this.mobileView}
386
+ .filterToggleActive=${this.facetPaneVisible}
387
+ .label=${this.smartFacetBarLabel}
388
+ @facetsChanged=${this.facetsChanged}
392
389
  @filtersToggled=${() => {
393
390
  this.facetPaneVisible = !this.facetPaneVisible;
394
391
  this.emitFacetPaneVisibilityChanged();
395
- }}
392
+ }}
396
393
  ></smart-facet-bar>`
397
- : nothing}
398
-
399
- <div
400
- id="content-container"
401
- class=${this.mobileView ? 'mobile' : 'desktop'}
402
- >
394
+ : nothing}
395
+
396
+ <div
397
+ id="content-container"
398
+ class=${this.mobileView ? 'mobile' : 'desktop'}
399
+ >
403
400
  ${this.placeholderType
404
401
  ? this.emptyPlaceholderTemplate
405
- : this.collectionBrowserTemplate}
406
- </div>
402
+ : this.collectionBrowserTemplate}
403
+ </div>
407
404
  `;
408
405
  }
409
406
  /**
@@ -447,23 +444,23 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
447
444
  * Template for the placeholder content to show when no results are available.
448
445
  */
449
446
  get emptyPlaceholderTemplate() {
450
- return html `
451
- <empty-placeholder
452
- .placeholderType=${this.placeholderType}
453
- ?isMobileView=${this.mobileView}
454
- ?isCollection=${!!this.withinCollection}
455
- .detailMessage=${this.dataSource.queryErrorMessage ?? ''}
456
- .baseNavigationUrl=${this.baseNavigationUrl}
457
- ></empty-placeholder>
447
+ return html `
448
+ <empty-placeholder
449
+ .placeholderType=${this.placeholderType}
450
+ ?isMobileView=${this.mobileView}
451
+ ?isCollection=${!!this.withinCollection}
452
+ .detailMessage=${this.dataSource.queryErrorMessage ?? ''}
453
+ .baseNavigationUrl=${this.baseNavigationUrl}
454
+ ></empty-placeholder>
458
455
  `;
459
456
  }
460
457
  /**
461
458
  * Top-level template for rendering the left (facets) and right (results) columns.
462
459
  */
463
460
  get collectionBrowserTemplate() {
464
- return html `
465
- <div id="left-column-scroll-sentinel"></div>
466
- ${this.leftColumnTemplate} ${this.rightColumnTemplate}
461
+ return html `
462
+ <div id="left-column-scroll-sentinel"></div>
463
+ ${this.leftColumnTemplate} ${this.rightColumnTemplate}
467
464
  `;
468
465
  }
469
466
  /**
@@ -482,33 +479,33 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
482
479
  * accordion-style facets.
483
480
  */
484
481
  get mobileLeftColumnTemplate() {
485
- return html `
486
- <div
487
- id="left-column"
488
- class="column${this.isResizeToMobile ? ' preload' : ''}"
489
- >
490
- ${this.facetTopViewSlot} ${this.resultsCountTemplate}
491
- <div id="facets-header-container">${this.mobileFacetsTemplate}</div>
492
- </div>
482
+ return html `
483
+ <div
484
+ id="left-column"
485
+ class="column${this.isResizeToMobile ? ' preload' : ''}"
486
+ >
487
+ ${this.facetTopViewSlot} ${this.resultsCountTemplate}
488
+ <div id="facets-header-container">${this.mobileFacetsTemplate}</div>
489
+ </div>
493
490
  `;
494
491
  }
495
492
  /**
496
493
  * Template for the desktop version of the left column, displaying the facets sidebar.
497
494
  */
498
495
  get desktopLeftColumnTemplate() {
499
- return html `
500
- <div id="left-column" class="column" ?hidden=${!this.facetPaneVisible}>
501
- ${this.facetTopViewSlot}
502
- <div id="facets-header-container">
503
- <h2 id="facets-header" class="sr-only">${msg('Filters')}</h2>
504
- ${this.resultsCountTemplate} ${this.clearFiltersBtnTemplate(false)}
505
- </div>
506
- <div id="facets-container" aria-labelledby="facets-header">
507
- ${this.facetsTemplate}
508
- <div id="facets-scroll-sentinel"></div>
509
- </div>
510
- <div id="facets-bottom-fade"></div>
511
- </div>
496
+ return html `
497
+ <div id="left-column" class="column" ?hidden=${!this.facetPaneVisible}>
498
+ ${this.facetTopViewSlot}
499
+ <div id="facets-header-container">
500
+ <h2 id="facets-header" class="sr-only">${msg('Filters')}</h2>
501
+ ${this.resultsCountTemplate} ${this.clearFiltersBtnTemplate(false)}
502
+ </div>
503
+ <div id="facets-container" aria-labelledby="facets-header">
504
+ ${this.facetsTemplate}
505
+ <div id="facets-scroll-sentinel"></div>
506
+ </div>
507
+ <div id="facets-bottom-fade"></div>
508
+ </div>
512
509
  `;
513
510
  }
514
511
  /**
@@ -516,8 +513,8 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
516
513
  * - mainly used to render userlists
517
514
  */
518
515
  get facetTopViewSlot() {
519
- return html `<div id="facet-top-view">
520
- <slot name="facet-top-slot"></slot>
516
+ return html `<div id="facet-top-view">
517
+ <slot name="facet-top-slot"></slot>
521
518
  </div>`;
522
519
  }
523
520
  /**
@@ -532,15 +529,15 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
532
529
  const resultsCount = this.totalResults?.toLocaleString();
533
530
  const resultsLabel = this.totalResults === 1 ? 'Result' : 'Results';
534
531
  // Added data-testid for Playwright testing
535
- return html `
536
- <div id="results-total" class=${classes} data-testid="results-total">
537
- <span id="big-results-count">
538
- ${shouldShowSearching ? html `Searching&hellip;` : resultsCount}
539
- </span>
540
- <span id="big-results-label">
541
- ${shouldShowSearching ? nothing : resultsLabel}
542
- </span>
543
- </div>
532
+ return html `
533
+ <div id="results-total" class=${classes} data-testid="results-total">
534
+ <span id="big-results-count">
535
+ ${shouldShowSearching ? html `Searching&hellip;` : resultsCount}
536
+ </span>
537
+ <span id="big-results-label">
538
+ ${shouldShowSearching ? nothing : resultsLabel}
539
+ </span>
540
+ </div>
544
541
  `;
545
542
  }
546
543
  /**
@@ -553,45 +550,45 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
553
550
  'full-width': !this.facetPaneVisible,
554
551
  'smart-results-spacing': !!this.showSmartResults,
555
552
  });
556
- return html `
557
- <div id="right-column" class=${rightColumnClasses}>
553
+ return html `
554
+ <div id="right-column" class=${rightColumnClasses}>
558
555
  ${this.showSmartResults
559
556
  ? html `<slot name="smart-results"></slot>`
560
- : nothing}
561
- <section id="results">
562
- <h2 class="results-section-heading">
563
- <slot name="results-heading"></slot>
564
- </h2>
565
- <div id="cb-top-view">
566
- <slot name="cb-top-slot"></slot>
567
- </div>
557
+ : nothing}
558
+ <section id="results">
559
+ <h2 class="results-section-heading">
560
+ <slot name="results-heading"></slot>
561
+ </h2>
562
+ <div id="cb-top-view">
563
+ <slot name="cb-top-slot"></slot>
564
+ </div>
568
565
  ${this.isManageView
569
566
  ? this.manageBarTemplate
570
- : this.sortFilterBarTemplate}
571
- <slot name="cb-results"></slot>
567
+ : this.sortFilterBarTemplate}
568
+ <slot name="cb-results"></slot>
572
569
  ${this.displayMode === `list-compact` && this.totalResults
573
570
  ? this.listHeaderTemplate
574
- : nothing}
575
- ${this.suppressResultTiles ? nothing : this.infiniteScrollerTemplate}
576
- </section>
577
- </div>
571
+ : nothing}
572
+ ${this.suppressResultTiles ? nothing : this.infiniteScrollerTemplate}
573
+ </section>
574
+ </div>
578
575
  `;
579
576
  }
580
577
  /**
581
578
  * Template for the infinite scroller widget that contains the result tiles.
582
579
  */
583
580
  get infiniteScrollerTemplate() {
584
- return html `<infinite-scroller
585
- class=${this.infiniteScrollerClasses}
586
- itemCount=${this.placeholderType ? 0 : nothing}
587
- ariaLandmarkLabel="Search results"
588
- .cellProvider=${this}
589
- .placeholderCellTemplate=${this.placeholderCellTemplate}
590
- @scrollThresholdReached=${this.scrollThresholdReached}
591
- @visibleCellsChanged=${this.visibleCellsChanged}
581
+ return html `<infinite-scroller
582
+ class=${this.infiniteScrollerClasses}
583
+ itemCount=${this.placeholderType ? 0 : nothing}
584
+ ariaLandmarkLabel="Search results"
585
+ .cellProvider=${this}
586
+ .placeholderCellTemplate=${this.placeholderCellTemplate}
587
+ @scrollThresholdReached=${this.scrollThresholdReached}
588
+ @visibleCellsChanged=${this.visibleCellsChanged}
592
589
  >${this.displayMode === 'grid'
593
590
  ? html `<slot name="result-last-tile" slot="result-last-tile"></slot>`
594
- : nothing}
591
+ : nothing}
595
592
  </infinite-scroller>`;
596
593
  }
597
594
  /**
@@ -623,29 +620,29 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
623
620
  }
624
621
  // We only show relevance sort if a search query is currently defined
625
622
  sortFieldAvailability.relevance = this.isRelevanceSortAvailable;
626
- return html `
627
- <sort-filter-bar
628
- .defaultSortField=${this.defaultSortField}
629
- .defaultSortDirection=${this.defaultSortDirection}
630
- .selectedSort=${this.selectedSort}
631
- .sortDirection=${this.sortDirection}
632
- .sortFieldAvailability=${sortFieldAvailability}
633
- .displayMode=${this.displayMode}
634
- .selectedTitleFilter=${this.selectedTitleFilter}
635
- .selectedCreatorFilter=${this.selectedCreatorFilter}
636
- .prefixFilterCountMap=${this.dataSource.prefixFilterCountMap}
637
- .enableSortOptionsSlot=${this.enableSortOptionsSlot}
638
- .suppressDisplayModes=${this.suppressDisplayModes}
639
- @sortChanged=${this.userChangedSort}
640
- @displayModeChanged=${this.displayModeChanged}
641
- @titleLetterChanged=${this.titleLetterSelected}
642
- @creatorLetterChanged=${this.creatorLetterSelected}
643
- >
644
- ${this.tileBlurCheckboxTemplate}
645
- <slot name="sort-options-left" slot="sort-options-left"></slot>
646
- <slot name="sort-options" slot="sort-options"></slot>
647
- <slot name="sort-options-right" slot="sort-options-right"></slot>
648
- </sort-filter-bar>
623
+ return html `
624
+ <sort-filter-bar
625
+ .defaultSortField=${this.defaultSortField}
626
+ .defaultSortDirection=${this.defaultSortDirection}
627
+ .selectedSort=${this.selectedSort}
628
+ .sortDirection=${this.sortDirection}
629
+ .sortFieldAvailability=${sortFieldAvailability}
630
+ .displayMode=${this.displayMode}
631
+ .selectedTitleFilter=${this.selectedTitleFilter}
632
+ .selectedCreatorFilter=${this.selectedCreatorFilter}
633
+ .prefixFilterCountMap=${this.dataSource.prefixFilterCountMap}
634
+ .enableSortOptionsSlot=${this.enableSortOptionsSlot}
635
+ .suppressDisplayModes=${this.suppressDisplayModes}
636
+ @sortChanged=${this.userChangedSort}
637
+ @displayModeChanged=${this.displayModeChanged}
638
+ @titleLetterChanged=${this.titleLetterSelected}
639
+ @creatorLetterChanged=${this.creatorLetterSelected}
640
+ >
641
+ ${this.tileBlurCheckboxTemplate}
642
+ <slot name="sort-options-left" slot="sort-options-left"></slot>
643
+ <slot name="sort-options" slot="sort-options"></slot>
644
+ <slot name="sort-options-right" slot="sort-options-right"></slot>
645
+ </sort-filter-bar>
649
646
  `;
650
647
  }
651
648
  /**
@@ -656,20 +653,20 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
656
653
  // Only show the checkbox for @archive.org users
657
654
  if (!this.dataSource.sessionContext?.is_archive_user)
658
655
  return nothing;
659
- return html `
660
- <label
661
- id="tile-blur-label"
662
- for="tile-blur-check"
663
- slot="sort-options-right"
664
- >
665
- ${msg('Blurring')}
666
- <input
667
- id="tile-blur-check"
668
- type="checkbox"
669
- ?checked=${!this.shouldSuppressTileBlurring}
670
- @change=${this.tileBlurCheckboxChanged}
671
- />
672
- </label>
656
+ return html `
657
+ <label
658
+ id="tile-blur-label"
659
+ for="tile-blur-check"
660
+ slot="sort-options-right"
661
+ >
662
+ ${msg('Blurring')}
663
+ <input
664
+ id="tile-blur-check"
665
+ type="checkbox"
666
+ ?checked=${!this.shouldSuppressTileBlurring}
667
+ @change=${this.tileBlurCheckboxChanged}
668
+ />
669
+ </label>
673
670
  `;
674
671
  }
675
672
  /**
@@ -695,27 +692,27 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
695
692
  * showing the management view. This generally replaces the sort bar when present.
696
693
  */
697
694
  get manageBarTemplate() {
698
- return html `
699
- <manage-bar
700
- .label=${this.manageViewLabel}
701
- .modalManager=${this.modalManager}
702
- .selectedItems=${this.dataSource.checkedTileModels}
703
- .manageViewModalMsg=${this.manageViewModalMsg}
704
- showSelectAll
705
- showUnselectAll
706
- ?showItemManageButton=${this.pageContext === 'search'}
707
- ?removeAllowed=${this.dataSource.checkedTileModels.length !== 0}
708
- @removeItems=${this.handleRemoveItems}
709
- @manageItems=${this.handleManageItems}
710
- @selectAll=${() => this.dataSource.checkAllTiles()}
711
- @unselectAll=${() => this.dataSource.uncheckAllTiles()}
695
+ return html `
696
+ <manage-bar
697
+ .label=${this.manageViewLabel}
698
+ .modalManager=${this.modalManager}
699
+ .selectedItems=${this.dataSource.checkedTileModels}
700
+ .manageViewModalMsg=${this.manageViewModalMsg}
701
+ showSelectAll
702
+ showUnselectAll
703
+ ?showItemManageButton=${this.pageContext === 'search'}
704
+ ?removeAllowed=${this.dataSource.checkedTileModels.length !== 0}
705
+ @removeItems=${this.handleRemoveItems}
706
+ @manageItems=${this.handleManageItems}
707
+ @selectAll=${() => this.dataSource.checkAllTiles()}
708
+ @unselectAll=${() => this.dataSource.uncheckAllTiles()}
712
709
  @cancel=${() => {
713
710
  this.isManageView = false;
714
711
  this.dataSource.uncheckAllTiles();
715
712
  if (this.searchResultsLoading)
716
713
  this.dataSource.resetPages();
717
- }}
718
- ></manage-bar>
714
+ }}
715
+ ></manage-bar>
719
716
  `;
720
717
  }
721
718
  /**
@@ -950,15 +947,15 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
950
947
  label: target.open ? 'open' : 'closed',
951
948
  });
952
949
  };
953
- return html `
954
- <details id="mobile-filter-collapse" @toggle=${toggleFacetsVisible}>
955
- <summary>
956
- <span class="collapser-icon">${chevronIcon}</span>
957
- <h2>${msg('Filters')}</h2>
958
- ${this.clearFiltersBtnTemplate(true)}
959
- </summary>
960
- ${this.facetsTemplate}
961
- </details>
950
+ return html `
951
+ <details id="mobile-filter-collapse" @toggle=${toggleFacetsVisible}>
952
+ <summary>
953
+ <span class="collapser-icon">${chevronIcon}</span>
954
+ <h2>${msg('Filters')}</h2>
955
+ ${this.clearFiltersBtnTemplate(true)}
956
+ </summary>
957
+ ${this.facetsTemplate}
958
+ </details>
962
959
  `;
963
960
  }
964
961
  /**
@@ -1042,50 +1039,50 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
1042
1039
  const filterByNetworkLabel = msg('Filter by Network');
1043
1040
  const filterByShowLabel = msg('Filter by Show');
1044
1041
  const shows = showEntries.map(([show]) => show);
1045
- const loadingIndicator = html `
1046
- <span slot="empty-options">
1047
- <img src="https://archive.org/images/loading.gif" />
1048
- </span>
1042
+ const loadingIndicator = html `
1043
+ <span slot="empty-options">
1044
+ <img src="https://archive.org/images/loading.gif" />
1045
+ </span>
1049
1046
  `;
1050
- const errorMessage = html `
1051
- <span slot="empty-options">
1052
- ${msg('Unable to fetch options, try again later')}
1053
- </span>
1047
+ const errorMessage = html `
1048
+ <span slot="empty-options">
1049
+ ${msg('Unable to fetch options, try again later')}
1050
+ </span>
1054
1051
  `;
1055
- return html `
1056
- <div id="tv-filters" slot="facets-top">
1057
- <ia-combo-box
1058
- id="tv-networks"
1059
- class="tv-filter-dropdown"
1060
- placeholder=${filterByNetworkLabel}
1061
- clearable
1062
- wrap-arrow-keys
1063
- sort
1064
- .options=${networks.map((n, i) => ({ id: `network-${i}`, text: n }))}
1065
- @toggle=${this.tvDropdownToggled}
1066
- @change=${this.networksDropdownChanged}
1067
- >
1068
- <span slot="label" class="sr-only">${filterByNetworkLabel}</span>
1069
- ${this.tvMapsLoading ? loadingIndicator : nothing}
1070
- ${this.tvMapsErrored ? errorMessage : nothing}
1071
- </ia-combo-box>
1072
- <ia-combo-box
1073
- id="tv-shows"
1074
- class="tv-filter-dropdown"
1075
- placeholder=${filterByShowLabel}
1076
- max-autocomplete-entries="500"
1077
- clearable
1078
- wrap-arrow-keys
1079
- sort
1080
- .options=${shows.map((s, i) => ({ id: `show-${i}`, text: s }))}
1081
- @toggle=${this.tvDropdownToggled}
1082
- @change=${this.showsDropdownChanged}
1083
- >
1084
- <span slot="label" class="sr-only">${filterByShowLabel}</span>
1085
- ${this.tvMapsLoading ? loadingIndicator : nothing}
1086
- ${this.tvMapsErrored ? errorMessage : nothing}
1087
- </ia-combo-box>
1088
- </div>
1052
+ return html `
1053
+ <div id="tv-filters" slot="facets-top">
1054
+ <ia-combo-box
1055
+ id="tv-networks"
1056
+ class="tv-filter-dropdown"
1057
+ placeholder=${filterByNetworkLabel}
1058
+ clearable
1059
+ wrap-arrow-keys
1060
+ sort
1061
+ .options=${networks.map((n, i) => ({ id: `network-${i}`, text: n }))}
1062
+ @toggle=${this.tvDropdownToggled}
1063
+ @change=${this.networksDropdownChanged}
1064
+ >
1065
+ <span slot="label" class="sr-only">${filterByNetworkLabel}</span>
1066
+ ${this.tvMapsLoading ? loadingIndicator : nothing}
1067
+ ${this.tvMapsErrored ? errorMessage : nothing}
1068
+ </ia-combo-box>
1069
+ <ia-combo-box
1070
+ id="tv-shows"
1071
+ class="tv-filter-dropdown"
1072
+ placeholder=${filterByShowLabel}
1073
+ max-autocomplete-entries="500"
1074
+ clearable
1075
+ wrap-arrow-keys
1076
+ sort
1077
+ .options=${shows.map((s, i) => ({ id: `show-${i}`, text: s }))}
1078
+ @toggle=${this.tvDropdownToggled}
1079
+ @change=${this.showsDropdownChanged}
1080
+ >
1081
+ <span slot="label" class="sr-only">${filterByShowLabel}</span>
1082
+ ${this.tvMapsLoading ? loadingIndicator : nothing}
1083
+ ${this.tvMapsErrored ? errorMessage : nothing}
1084
+ </ia-combo-box>
1085
+ </div>
1089
1086
  `;
1090
1087
  }
1091
1088
  /**
@@ -1095,10 +1092,10 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
1095
1092
  if (FACETLESS_PAGE_ELEMENTS.includes(this.profileElement))
1096
1093
  return nothing;
1097
1094
  if (this.facetLoadStrategy === 'off') {
1098
- return html `
1099
- <p class="facets-message">
1100
- ${msg('Facets are temporarily unavailable.')}
1101
- </p>
1095
+ return html `
1096
+ <p class="facets-message">
1097
+ ${msg('Facets are temporarily unavailable.')}
1098
+ </p>
1102
1099
  `;
1103
1100
  }
1104
1101
  // We switch to TV facet ordering & date picker if we are in a TV collection or showing TV search results
@@ -1107,46 +1104,46 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
1107
1104
  const facetDisplayOrder = shouldUseTvInterface
1108
1105
  ? tvFacetDisplayOrder
1109
1106
  : defaultFacetDisplayOrder;
1110
- const facets = html `
1111
- <collection-facets
1112
- .collectionPagePath=${this.collectionPagePath}
1113
- .parentCollections=${this.dataSource.parentCollections}
1114
- .pageSpecifierParams=${this.dataSource.pageSpecifierParams}
1115
- .searchService=${this.searchService}
1116
- .featureFeedbackService=${this.featureFeedbackService}
1117
- .recaptchaManager=${this.recaptchaManager}
1118
- .resizeObserver=${this.resizeObserver}
1119
- .searchType=${this.searchType}
1120
- .aggregations=${this.dataSource.aggregations}
1121
- .histogramAggregation=${this.dataSource.histogramAggregation}
1122
- .minSelectedDate=${this.minSelectedDate}
1123
- .maxSelectedDate=${this.maxSelectedDate}
1124
- .selectedFacets=${this.selectedFacets}
1125
- .baseNavigationUrl=${this.baseNavigationUrl}
1126
- .collectionTitles=${this.dataSource.collectionTitles}
1127
- .tvChannelAliases=${this.dataSource.tvChannelAliases}
1128
- .showHistogramDatePicker=${this.showHistogramDatePicker}
1129
- .allowExpandingDatePicker=${!this.mobileView}
1130
- .allowDatePickerMonths=${shouldUseTvInterface}
1131
- .contentWidth=${this.contentWidth}
1132
- .query=${this.baseQuery}
1133
- .identifiers=${this.identifiers}
1134
- .filterMap=${this.dataSource.filterMap}
1135
- .isManageView=${this.isManageView}
1136
- .modalManager=${this.modalManager}
1137
- .analyticsHandler=${this.analyticsHandler}
1138
- .facetDisplayOrder=${facetDisplayOrder}
1139
- .isTvSearch=${shouldUseTvInterface}
1140
- ?collapsableFacets=${this.mobileView}
1141
- ?facetsLoading=${this.facetsLoading}
1142
- ?histogramAggregationLoading=${this.facetsLoading}
1143
- ?suppressMediatypeFacets=${this.suppressMediatypeFacets}
1144
- @facetClick=${this.facetClickHandler}
1145
- @facetsChanged=${this.facetsChanged}
1146
- @histogramDateRangeUpdated=${this.histogramDateRangeUpdated}
1147
- >
1148
- ${this.tvDropdownFiltersTemplate}
1149
- </collection-facets>
1107
+ const facets = html `
1108
+ <collection-facets
1109
+ .collectionPagePath=${this.collectionPagePath}
1110
+ .parentCollections=${this.dataSource.parentCollections}
1111
+ .pageSpecifierParams=${this.dataSource.pageSpecifierParams}
1112
+ .searchService=${this.searchService}
1113
+ .featureFeedbackService=${this.featureFeedbackService}
1114
+ .recaptchaManager=${this.recaptchaManager}
1115
+ .resizeObserver=${this.resizeObserver}
1116
+ .searchType=${this.searchType}
1117
+ .aggregations=${this.dataSource.aggregations}
1118
+ .histogramAggregation=${this.dataSource.histogramAggregation}
1119
+ .minSelectedDate=${this.minSelectedDate}
1120
+ .maxSelectedDate=${this.maxSelectedDate}
1121
+ .selectedFacets=${this.selectedFacets}
1122
+ .baseNavigationUrl=${this.baseNavigationUrl}
1123
+ .collectionTitles=${this.dataSource.collectionTitles}
1124
+ .tvChannelAliases=${this.dataSource.tvChannelAliases}
1125
+ .showHistogramDatePicker=${this.showHistogramDatePicker}
1126
+ .allowExpandingDatePicker=${!this.mobileView}
1127
+ .allowDatePickerMonths=${shouldUseTvInterface}
1128
+ .contentWidth=${this.contentWidth}
1129
+ .query=${this.baseQuery}
1130
+ .identifiers=${this.identifiers}
1131
+ .filterMap=${this.dataSource.filterMap}
1132
+ .isManageView=${this.isManageView}
1133
+ .modalManager=${this.modalManager}
1134
+ .analyticsHandler=${this.analyticsHandler}
1135
+ .facetDisplayOrder=${facetDisplayOrder}
1136
+ .isTvSearch=${shouldUseTvInterface}
1137
+ ?collapsableFacets=${this.mobileView}
1138
+ ?facetsLoading=${this.facetsLoading}
1139
+ ?histogramAggregationLoading=${this.facetsLoading}
1140
+ ?suppressMediatypeFacets=${this.suppressMediatypeFacets}
1141
+ @facetClick=${this.facetClickHandler}
1142
+ @facetsChanged=${this.facetsChanged}
1143
+ @histogramDateRangeUpdated=${this.histogramDateRangeUpdated}
1144
+ >
1145
+ ${this.tvDropdownFiltersTemplate}
1146
+ </collection-facets>
1150
1147
  `;
1151
1148
  // If we are using one of the opt-in facet load strategies, we may need to wrap the
1152
1149
  // desktop view facets in a <details> widget so that patrons can opt into loading them.
@@ -1154,20 +1151,20 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
1154
1151
  const showDesktopOptInWidget = this.facetLoadStrategy === 'opt-in' ||
1155
1152
  (this.facetLoadStrategy === 'opt-in-or-login' && !this.loggedIn);
1156
1153
  if (showDesktopOptInWidget && !this.mobileView) {
1157
- return html `
1158
- <details
1159
- class="desktop-facets-dropdown"
1154
+ return html `
1155
+ <details
1156
+ class="desktop-facets-dropdown"
1160
1157
  @toggle=${(e) => {
1161
1158
  const target = e.target;
1162
1159
  this.collapsibleFacetsVisible = target.open;
1163
- }}
1164
- >
1165
- <summary>
1166
- <span class="collapser-icon">${chevronIcon}</span>
1167
- <h2>${msg('Filters')}</h2>
1168
- </summary>
1169
- ${facets}
1170
- </details>
1160
+ }}
1161
+ >
1162
+ <summary>
1163
+ <span class="collapser-icon">${chevronIcon}</span>
1164
+ <h2>${msg('Filters')}</h2>
1165
+ </summary>
1166
+ ${facets}
1167
+ </details>
1171
1168
  `;
1172
1169
  }
1173
1170
  // Otherwise, just render the facets component bare
@@ -1187,34 +1184,34 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
1187
1184
  mobile,
1188
1185
  });
1189
1186
  const buttonText = mobile ? 'Clear all' : 'Clear all filters';
1190
- return html `
1191
- <div class="clear-filters-btn-row">
1187
+ return html `
1188
+ <div class="clear-filters-btn-row">
1192
1189
  ${mobile
1193
1190
  ? html `<span class="clear-filters-btn-separator">&nbsp;</span>`
1194
- : nothing}
1195
- <button class=${buttonClasses} @click=${this.clearFilters}>
1196
- ${buttonText}
1197
- </button>
1198
- </div>
1191
+ : nothing}
1192
+ <button class=${buttonClasses} @click=${this.clearFilters}>
1193
+ ${buttonText}
1194
+ </button>
1195
+ </div>
1199
1196
  `;
1200
1197
  }
1201
1198
  /**
1202
1199
  * Template for the table header content that appears atop the compact list view.
1203
1200
  */
1204
1201
  get listHeaderTemplate() {
1205
- return html `
1206
- <div id="list-header">
1207
- <tile-dispatcher
1208
- .tileDisplayMode=${'list-header'}
1209
- .resizeObserver=${this.resizeObserver}
1210
- .sortParam=${this.sortParam}
1211
- .defaultSortParam=${this.defaultSortParam}
1212
- .mobileBreakpoint=${this.mobileBreakpoint}
1213
- .loggedIn=${this.loggedIn}
1214
- .suppressBlurring=${this.shouldSuppressTileBlurring}
1215
- >
1216
- </tile-dispatcher>
1217
- </div>
1202
+ return html `
1203
+ <div id="list-header">
1204
+ <tile-dispatcher
1205
+ .tileDisplayMode=${'list-header'}
1206
+ .resizeObserver=${this.resizeObserver}
1207
+ .sortParam=${this.sortParam}
1208
+ .defaultSortParam=${this.defaultSortParam}
1209
+ .mobileBreakpoint=${this.mobileBreakpoint}
1210
+ .loggedIn=${this.loggedIn}
1211
+ .suppressBlurring=${this.shouldSuppressTileBlurring}
1212
+ >
1213
+ </tile-dispatcher>
1214
+ </div>
1218
1215
  `;
1219
1216
  }
1220
1217
  /**
@@ -1274,6 +1271,12 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
1274
1271
  this.maxSelectedDate = queryState.maxSelectedDate;
1275
1272
  this.selectedSort = queryState.selectedSort ?? SortField.default;
1276
1273
  this.sortDirection = queryState.sortDirection;
1274
+ if (queryState.defaultSortField) {
1275
+ this.defaultSortField = queryState.defaultSortField;
1276
+ }
1277
+ if (queryState.defaultSortDirection !== undefined) {
1278
+ this.defaultSortDirection = queryState.defaultSortDirection;
1279
+ }
1277
1280
  this.selectedTitleFilter = queryState.selectedTitleFilter;
1278
1281
  this.selectedCreatorFilter = queryState.selectedCreatorFilter;
1279
1282
  this.pagesToRender = this.initialPageNumber;
@@ -1362,19 +1365,6 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
1362
1365
  });
1363
1366
  }
1364
1367
  }
1365
- if (changed.has('profileElement')) {
1366
- this.applyDefaultProfileSort();
1367
- }
1368
- if (changed.has('withinCollection') && this.withinCollection) {
1369
- // Set a sensible default collection sort while we load results, which we will later
1370
- // adjust based on any sort-by metadata once the response arrives.
1371
- if (!this.baseQuery) {
1372
- this.defaultSortField = this.withinCollection.startsWith('fav-')
1373
- ? SortField.datefavorited
1374
- : SortField.weeklyview;
1375
- this.defaultSortDirection = 'desc';
1376
- }
1377
- }
1378
1368
  if (changed.has('baseQuery')) {
1379
1369
  this.emitBaseQueryChanged();
1380
1370
  }
@@ -1589,6 +1579,17 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
1589
1579
  detail: this.dataSource.queryErrorMessage,
1590
1580
  }));
1591
1581
  }
1582
+ /**
1583
+ * Emits a `collectionExtraInfoLoaded` event when the data source has received
1584
+ * collection metadata from the backend. This allows parent components to react
1585
+ * to the metadata (e.g., to update their default sort based on the collection's
1586
+ * `sort-by` metadata field).
1587
+ */
1588
+ emitCollectionExtraInfoLoaded(collectionExtraInfo) {
1589
+ this.dispatchEvent(new CustomEvent('collectionExtraInfoLoaded', {
1590
+ detail: collectionExtraInfo,
1591
+ }));
1592
+ }
1592
1593
  /**
1593
1594
  * Emits a `queryStateChanged` event indicating that one or more of this component's
1594
1595
  * properties have changed in a way that could affect the set of search results.
@@ -1842,66 +1843,6 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
1842
1843
  this.infiniteScroller.itemCount = count;
1843
1844
  }
1844
1845
  }
1845
- /**
1846
- * Applies the default sort options for the TV search results page
1847
- */
1848
- applyDefaultTVSearchSort() {
1849
- this.defaultSortField = SortField.datearchived;
1850
- this.defaultSortDirection = 'desc';
1851
- }
1852
- /**
1853
- * Applies any default sort option for the current collection, by checking
1854
- * for one in the collection's metadata. If none is found, defaults to sorting
1855
- * descending by:
1856
- * - Date Favorited for fav-* collections
1857
- * - Weekly views for all other collections
1858
- */
1859
- applyDefaultCollectionSort(collectionInfo) {
1860
- if (this.baseQuery) {
1861
- // If there's a query set, then we default to relevance sorting regardless of
1862
- // the collection metadata-specified sort.
1863
- this.defaultSortField = SortField.relevance;
1864
- this.defaultSortDirection = null;
1865
- return;
1866
- }
1867
- // Favorite collections sort on Date Favorited by default.
1868
- // Other collections fall back to sorting on weekly views.
1869
- const baseDefaultSort = collectionInfo?.public_metadata?.identifier?.startsWith('fav-')
1870
- ? '-favoritedate'
1871
- : '-week';
1872
- // The collection metadata may override the default sorting with something else
1873
- const metadataSort = collectionInfo?.public_metadata?.['sort-by'];
1874
- // Prefer the metadata-specified sort if one exists
1875
- const defaultSortToApply = metadataSort ?? baseDefaultSort;
1876
- // Account for both -field and field:dir formats
1877
- let [field, dir] = defaultSortToApply.split(':');
1878
- if (field.startsWith('-')) {
1879
- field = field.slice(1);
1880
- dir = 'desc';
1881
- }
1882
- else if (!['asc', 'desc'].includes(dir)) {
1883
- dir = 'asc';
1884
- }
1885
- const sortOption = sortOptionFromAPIString(field);
1886
- const sortField = sortOption.field;
1887
- if (sortField && sortField !== SortField.default) {
1888
- this.defaultSortField = sortField;
1889
- this.defaultSortDirection = dir;
1890
- }
1891
- }
1892
- /**
1893
- * Applies the default sort option for the current profile element
1894
- */
1895
- applyDefaultProfileSort() {
1896
- if (this.profileElement) {
1897
- const defaultSortField = defaultProfileElementSorts[this.profileElement];
1898
- this.defaultSortField = defaultSortField ?? SortField.weeklyview;
1899
- }
1900
- else {
1901
- this.defaultSortField = SortField.weeklyview;
1902
- }
1903
- this.defaultSortDirection = 'desc';
1904
- }
1905
1846
  /**
1906
1847
  * This is useful for determining whether we need to reload the scroller.
1907
1848
  *
@@ -1969,28 +1910,28 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
1969
1910
  const isRadioSearch = this.searchType === SearchType.RADIO;
1970
1911
  const { isTVCollection, isRadioCollection } = this;
1971
1912
  const shouldUseLocalTime = isTVSearch || isRadioSearch || isTVCollection || isRadioCollection;
1972
- return html `
1973
- <tile-dispatcher
1974
- .collectionPagePath=${this.collectionPagePath}
1975
- .baseNavigationUrl=${this.baseNavigationUrl}
1976
- .baseImageUrl=${this.baseImageUrl}
1977
- .model=${model}
1978
- .tileDisplayMode=${this.displayMode}
1979
- .resizeObserver=${this.resizeObserver}
1980
- .collectionTitles=${this.dataSource.collectionTitles}
1981
- .sortParam=${this.sortParam}
1982
- .defaultSortParam=${this.defaultSortParam}
1983
- .creatorFilter=${this.selectedCreatorFilter}
1984
- .mobileBreakpoint=${this.mobileBreakpoint}
1985
- .loggedIn=${this.loggedIn}
1986
- .suppressBlurring=${this.shouldSuppressTileBlurring}
1987
- .isManageView=${this.isManageView}
1988
- ?showTvClips=${isTVSearch || isTVCollection}
1989
- ?enableHoverPane=${true}
1990
- ?useLocalTime=${shouldUseLocalTime}
1991
- @resultSelected=${(e) => this.resultSelected(e)}
1992
- >
1993
- </tile-dispatcher>
1913
+ return html `
1914
+ <tile-dispatcher
1915
+ .collectionPagePath=${this.collectionPagePath}
1916
+ .baseNavigationUrl=${this.baseNavigationUrl}
1917
+ .baseImageUrl=${this.baseImageUrl}
1918
+ .model=${model}
1919
+ .tileDisplayMode=${this.displayMode}
1920
+ .resizeObserver=${this.resizeObserver}
1921
+ .collectionTitles=${this.dataSource.collectionTitles}
1922
+ .sortParam=${this.sortParam}
1923
+ .defaultSortParam=${this.defaultSortParam}
1924
+ .creatorFilter=${this.selectedCreatorFilter}
1925
+ .mobileBreakpoint=${this.mobileBreakpoint}
1926
+ .loggedIn=${this.loggedIn}
1927
+ .suppressBlurring=${this.shouldSuppressTileBlurring}
1928
+ .isManageView=${this.isManageView}
1929
+ ?showTvClips=${isTVSearch || isTVCollection}
1930
+ ?enableHoverPane=${true}
1931
+ ?useLocalTime=${shouldUseLocalTime}
1932
+ @resultSelected=${(e) => this.resultSelected(e)}
1933
+ >
1934
+ </tile-dispatcher>
1994
1935
  `;
1995
1936
  }
1996
1937
  /**
@@ -2025,479 +1966,479 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
2025
1966
  static get styles() {
2026
1967
  return [
2027
1968
  srOnlyStyle,
2028
- css `
2029
- :host {
2030
- display: block;
2031
- --leftColumnWidth: 18rem;
2032
- --leftColumnPaddingTop: 2rem;
2033
- --leftColumnPaddingRight: 2.5rem;
2034
- }
2035
-
2036
- #facet-top-view {
2037
- display: flex;
2038
- }
2039
-
2040
- /**
2041
- * When page width resizes from desktop to mobile, use this class to
2042
- * disable expand/collapse transition when loading.
2043
- */
2044
- .preload * {
2045
- transition: none !important;
2046
- -webkit-transition: none !important;
2047
- -moz-transition: none !important;
2048
- -ms-transition: none !important;
2049
- -o-transition: none !important;
2050
- }
2051
-
2052
- #content-container {
2053
- display: flex;
2054
- }
2055
-
2056
- empty-placeholder {
2057
- margin-top: var(--placeholderMarginTop, 0);
2058
- }
2059
-
2060
- .collapser-icon {
2061
- display: inline-block;
2062
- }
2063
-
2064
- .collapser-icon svg {
2065
- display: inline-block;
2066
- width: 12px;
2067
- height: 12px;
2068
- transition: transform 0.2s ease-out;
2069
- }
2070
-
2071
- #mobile-filter-collapse {
2072
- width: 100%;
2073
- }
2074
-
2075
- #mobile-filter-collapse > summary {
2076
- cursor: pointer;
2077
- list-style: none;
2078
- }
2079
-
2080
- #mobile-filter-collapse[open] > summary {
2081
- margin-bottom: 10px;
2082
- }
2083
-
2084
- #mobile-filter-collapse h2 {
2085
- display: inline-block;
2086
- margin: 0;
2087
- font-size: 2rem;
2088
- }
2089
-
2090
- #mobile-filter-collapse[open] svg {
2091
- transform: rotate(90deg);
2092
- }
2093
-
2094
- #content-container.mobile {
2095
- display: block;
2096
- }
2097
-
2098
- #right-column {
2099
- flex: 1;
2100
- position: relative;
2101
- min-height: 90vh;
2102
- border-right: 1px solid rgb(232, 232, 232);
2103
- margin-top: var(--rightColumnMarginTop, 0);
2104
- padding-top: var(--rightColumnPaddingTop, 2rem);
2105
- background: #fff;
2106
- }
2107
-
2108
- #left-column:not([hidden]) + #right-column {
2109
- border-left: 1px solid rgb(232, 232, 232);
2110
- }
2111
-
2112
- #right-column.smart-results-spacing {
2113
- padding-top: 0.5rem;
2114
- border-right: none;
2115
- background: transparent;
2116
- min-width: 0;
2117
- }
2118
-
2119
- #results {
2120
- background: #fff;
2121
- padding-left: 1rem;
2122
- padding-right: 1rem;
2123
- }
2124
-
2125
- #right-column.smart-results-spacing #results {
2126
- border-radius: 10px 10px 0px 0px;
2127
- padding-top: 0.5rem;
2128
- margin-top: 1rem;
2129
- }
2130
-
2131
- .mobile #right-column {
2132
- border-left: none;
2133
- }
2134
-
2135
- .mobile #results {
2136
- padding: 5px 5px 0;
2137
- }
2138
-
2139
- #left-column {
2140
- width: var(--leftColumnWidth, 18rem);
2141
- /* Prevents Safari from shrinking col at first draw */
2142
- min-width: var(--leftColumnWidth, 18rem);
2143
- padding-top: var(--leftColumnPaddingTop, 2rem);
2144
- /* Reduced padding by 0.2rem to add the invisible border in the rule below */
2145
- padding-right: calc(var(--leftColumnPaddingRight, 2.5rem) - 0.2rem);
2146
- border-right: 0.2rem solid transparent; /* Pads to the right of the scrollbar a bit */
2147
- z-index: 1;
2148
- }
2149
-
2150
- .desktop #left-column {
2151
- top: 0;
2152
- position: sticky;
2153
- height: calc(100vh - 2rem);
2154
- max-height: calc(100vh - 2rem);
2155
- overflow-x: hidden;
2156
- overflow-y: scroll;
2157
-
2158
- /*
2159
- * Firefox doesn't support any of the -webkit-scrollbar stuff below, but
2160
- * does at least give us a tiny bit of control over width & color.
2161
- */
2162
- scrollbar-width: thin;
2163
- scrollbar-color: transparent transparent;
2164
- }
2165
- .desktop #left-column:hover {
2166
- scrollbar-color: auto;
2167
- }
2168
- .desktop #left-column::-webkit-scrollbar {
2169
- appearance: none;
2170
- width: 6px;
2171
- }
2172
- .desktop #left-column::-webkit-scrollbar-button {
2173
- height: 3px;
2174
- background: transparent;
2175
- }
2176
- .desktop #left-column::-webkit-scrollbar-corner {
2177
- background: transparent;
2178
- }
2179
- .desktop #left-column::-webkit-scrollbar-thumb {
2180
- border-radius: 4px;
2181
- }
2182
- .desktop #left-column:hover::-webkit-scrollbar-thumb {
2183
- background: rgba(0, 0, 0, 0.15);
2184
- }
2185
- .desktop #left-column:hover::-webkit-scrollbar-thumb:hover {
2186
- background: rgba(0, 0, 0, 0.2);
2187
- }
2188
- .desktop #left-column:hover::-webkit-scrollbar-thumb:active {
2189
- background: rgba(0, 0, 0, 0.3);
2190
- }
2191
-
2192
- #facets-bottom-fade {
2193
- background: linear-gradient(
2194
- to bottom,
2195
- #fbfbfd00 0%,
2196
- #fbfbfdc0 50%,
2197
- #fbfbfd 80%,
2198
- #fbfbfd 100%
2199
- );
2200
- position: fixed;
2201
- bottom: 0;
2202
- height: 50px;
2203
- /* Wide enough to cover the content, but leave the scrollbar uncovered */
2204
- width: calc(
2205
- var(--leftColumnWidth) + var(--leftColumnPaddingRight) - 10px
2206
- );
2207
- z-index: 2;
2208
- pointer-events: none;
2209
- transition: height 0.1s ease;
2210
- }
2211
- #facets-bottom-fade.hidden {
2212
- height: 0;
2213
- }
2214
-
2215
- .facets-message {
2216
- font-size: 1.4rem;
2217
- }
2218
-
2219
- .desktop-facets-dropdown > summary {
2220
- cursor: pointer;
2221
- list-style: none;
2222
- }
2223
-
2224
- .desktop-facets-dropdown h2 {
2225
- display: inline-block;
2226
- margin: 0;
2227
- font-size: 1.6rem;
2228
- }
2229
-
2230
- .desktop-facets-dropdown[open] > summary {
2231
- margin-bottom: 10px;
2232
- }
2233
-
2234
- .desktop-facets-dropdown[open] svg {
2235
- transform: rotate(90deg);
2236
- }
2237
-
2238
- .desktop #left-column-scroll-sentinel {
2239
- width: 1px;
2240
- height: 100vh;
2241
- background: transparent;
2242
- }
2243
-
2244
- .desktop #facets-scroll-sentinel {
2245
- width: 1px;
2246
- height: 1px;
2247
- background: transparent;
2248
- }
2249
-
2250
- #facets-header-container {
2251
- display: flex;
2252
- justify-content: space-between;
2253
- align-items: flex-start;
2254
- clear: both;
2255
- }
2256
-
2257
- .desktop #facets-header-container {
2258
- flex-wrap: wrap;
2259
- }
2260
-
2261
- .mobile #left-column {
2262
- width: 100%;
2263
- min-width: 0;
2264
- padding: 5px 0;
2265
- border: 0;
2266
- }
2267
-
2268
- .clear-filters-btn-row {
2269
- display: inline-block;
2270
- }
2271
-
2272
- .desktop .clear-filters-btn-row {
2273
- width: 100%;
2274
- }
2275
-
2276
- .clear-filters-btn {
2277
- display: inline-block;
2278
- appearance: none;
2279
- margin: 0;
2280
- padding: 0;
2281
- border: 0;
2282
- background: none;
2283
- color: var(--ia-theme-link-color);
2284
- font-size: 1.4rem;
2285
- font-family: inherit;
2286
- cursor: pointer;
2287
- }
2288
-
2289
- .clear-filters-btn:hover {
2290
- text-decoration: underline;
2291
- }
2292
-
2293
- .clear-filters-btn-separator {
2294
- display: inline-block;
2295
- margin-left: 5px;
2296
- border-left: 1px solid #2c2c2c;
2297
- font-size: 1.4rem;
2298
- line-height: 1.3rem;
2299
- }
2300
-
2301
- #tv-filters {
2302
- margin-bottom: 15px;
2303
- }
2304
-
2305
- #tv-shows {
2306
- --comboBoxListWidth: 300px;
2307
- }
2308
-
2309
- .tv-filter-dropdown {
2310
- display: block;
2311
- font-size: 14px;
2312
- margin-left: 1px;
2313
- margin-bottom: 5px;
2314
- }
2315
-
2316
- .tv-filter-dropdown::part(combo-box) {
2317
- outline-offset: 1px;
2318
- }
2319
-
2320
- .tv-filter-dropdown::part(option) {
2321
- line-height: 1.1;
2322
- padding: 7px;
2323
- }
2324
-
2325
- .tv-filter-dropdown::part(clear-button) {
2326
- flex: 0 0 26px;
2327
- --combo-box-clear-icon-size: 14px;
2328
- }
2329
-
2330
- .tv-filter-dropdown::part(icon) {
2331
- width: 1.4rem;
2332
- height: 1.4rem;
2333
- }
2334
-
2335
- #facets-container {
2336
- position: relative;
2337
- max-height: 0;
2338
- transition: max-height 0.2s ease-in-out;
2339
- z-index: 1;
2340
- margin-top: var(--facetsContainerMarginTop, 3rem);
2341
- padding-bottom: 2rem;
2342
- }
2343
-
2344
- .desktop #facets-container {
2345
- width: 18rem;
2346
- }
2347
-
2348
- .mobile #facets-container {
2349
- overflow: hidden;
2350
- padding-bottom: 0;
2351
- padding-left: 10px;
2352
- padding-right: 10px;
2353
- }
2354
-
2355
- #facets-container.expanded {
2356
- max-height: 2000px;
2357
- }
2358
-
2359
- .results-section-heading {
2360
- margin: 0.5rem 0.3rem;
2361
- font-size: 2rem;
2362
- line-height: 25px;
2363
- }
2364
-
2365
- #results-total {
2366
- display: flex;
2367
- align-items: baseline;
2368
- }
2369
-
2370
- #results-total:not(.filtered) {
2371
- padding-bottom: 2rem;
2372
- }
2373
-
2374
- .mobile #results-total {
2375
- position: absolute;
2376
- right: 10px;
2377
- }
2378
-
2379
- #big-results-count {
2380
- font-size: 2.4rem;
2381
- font-weight: 500;
2382
- margin-right: 5px;
2383
- }
2384
-
2385
- .mobile #big-results-count {
2386
- font-size: 2rem;
2387
- }
2388
-
2389
- #big-results-label {
2390
- font-size: 1.4rem;
2391
- font-weight: 200;
2392
- }
2393
-
2394
- #list-header {
2395
- max-height: 4.2rem;
2396
- }
2397
-
2398
- .loading-cover {
2399
- position: absolute;
2400
- top: 0;
2401
- left: 0;
2402
- width: 100%;
2403
- height: 100%;
2404
- display: flex;
2405
- justify-content: center;
2406
- z-index: 1;
2407
- padding-top: 50px;
2408
- }
2409
-
2410
- #tile-blur-label {
2411
- display: flex;
2412
- align-items: center;
2413
- column-gap: 5px;
2414
- }
2415
-
2416
- #tile-blur-check {
2417
- margin: 0 5px 0 0;
2418
- width: 15px;
2419
- }
2420
-
2421
- circular-activity-indicator {
2422
- width: 30px;
2423
- height: 30px;
2424
- }
2425
-
2426
- sort-filter-bar {
2427
- display: block;
2428
- margin-bottom: 4rem;
2429
- }
2430
-
2431
- infinite-scroller {
2432
- display: block;
2433
- --infiniteScrollerRowGap: var(--collectionBrowserRowGap, 1.7rem);
2434
- --infiniteScrollerColGap: var(--collectionBrowserColGap, 1.7rem);
2435
- }
2436
-
2437
- infinite-scroller.list-compact {
2438
- --infiniteScrollerCellMinWidth: var(
2439
- --collectionBrowserCellMinWidth,
2440
- 100%
2441
- );
2442
- --infiniteScrollerCellMinHeight: 45px; /* override infinite scroller component */
2443
- --infiniteScrollerCellMaxHeight: 56px;
2444
- --infiniteScrollerRowGap: 10px;
2445
- }
2446
-
2447
- infinite-scroller.list-detail {
2448
- --infiniteScrollerCellMinWidth: var(
2449
- --collectionBrowserCellMinWidth,
2450
- 100%
2451
- );
2452
- --infiniteScrollerCellMinHeight: var(
2453
- --collectionBrowserCellMinHeight,
2454
- 5rem
2455
- );
2456
- /*
2457
- 30px in spec, compensating for a -4px margin
2458
- to align title with top of item image
2459
- src/tiles/list/tile-list.ts
2460
- */
2461
- --infiniteScrollerRowGap: 34px;
2462
- }
2463
-
2464
- .mobile infinite-scroller.list-detail {
2465
- --infiniteScrollerRowGap: 24px;
2466
- }
2467
-
2468
- infinite-scroller.grid {
2469
- --infiniteScrollerCellMinWidth: var(
2470
- --collectionBrowserCellMinWidth,
2471
- 17rem
2472
- );
2473
- --infiniteScrollerCellMaxWidth: var(
2474
- --collectionBrowserCellMaxWidth,
2475
- 1fr
2476
- );
2477
- }
2478
-
2479
- /* Allow tiles to shrink a bit further at smaller viewport widths */
2480
- @media screen and (max-width: 880px) {
2481
- infinite-scroller.grid {
2482
- --infiniteScrollerCellMinWidth: var(
2483
- --collectionBrowserCellMinWidth,
2484
- 15rem
2485
- );
2486
- }
2487
- }
2488
- /* At very small widths, maintain a 2-tile layout as far as it can reasonably go */
2489
- @media screen and (max-width: 360px) {
2490
- infinite-scroller.grid {
2491
- --infiniteScrollerCellMinWidth: var(
2492
- --collectionBrowserCellMinWidth,
2493
- 12rem
2494
- );
2495
- }
2496
- }
2497
-
2498
- infinite-scroller.hidden {
2499
- display: none;
2500
- }
1969
+ css `
1970
+ :host {
1971
+ display: block;
1972
+ --leftColumnWidth: 18rem;
1973
+ --leftColumnPaddingTop: 2rem;
1974
+ --leftColumnPaddingRight: 2.5rem;
1975
+ }
1976
+
1977
+ #facet-top-view {
1978
+ display: flex;
1979
+ }
1980
+
1981
+ /**
1982
+ * When page width resizes from desktop to mobile, use this class to
1983
+ * disable expand/collapse transition when loading.
1984
+ */
1985
+ .preload * {
1986
+ transition: none !important;
1987
+ -webkit-transition: none !important;
1988
+ -moz-transition: none !important;
1989
+ -ms-transition: none !important;
1990
+ -o-transition: none !important;
1991
+ }
1992
+
1993
+ #content-container {
1994
+ display: flex;
1995
+ }
1996
+
1997
+ empty-placeholder {
1998
+ margin-top: var(--placeholderMarginTop, 0);
1999
+ }
2000
+
2001
+ .collapser-icon {
2002
+ display: inline-block;
2003
+ }
2004
+
2005
+ .collapser-icon svg {
2006
+ display: inline-block;
2007
+ width: 12px;
2008
+ height: 12px;
2009
+ transition: transform 0.2s ease-out;
2010
+ }
2011
+
2012
+ #mobile-filter-collapse {
2013
+ width: 100%;
2014
+ }
2015
+
2016
+ #mobile-filter-collapse > summary {
2017
+ cursor: pointer;
2018
+ list-style: none;
2019
+ }
2020
+
2021
+ #mobile-filter-collapse[open] > summary {
2022
+ margin-bottom: 10px;
2023
+ }
2024
+
2025
+ #mobile-filter-collapse h2 {
2026
+ display: inline-block;
2027
+ margin: 0;
2028
+ font-size: 2rem;
2029
+ }
2030
+
2031
+ #mobile-filter-collapse[open] svg {
2032
+ transform: rotate(90deg);
2033
+ }
2034
+
2035
+ #content-container.mobile {
2036
+ display: block;
2037
+ }
2038
+
2039
+ #right-column {
2040
+ flex: 1;
2041
+ position: relative;
2042
+ min-height: 90vh;
2043
+ border-right: 1px solid rgb(232, 232, 232);
2044
+ margin-top: var(--rightColumnMarginTop, 0);
2045
+ padding-top: var(--rightColumnPaddingTop, 2rem);
2046
+ background: #fff;
2047
+ }
2048
+
2049
+ #left-column:not([hidden]) + #right-column {
2050
+ border-left: 1px solid rgb(232, 232, 232);
2051
+ }
2052
+
2053
+ #right-column.smart-results-spacing {
2054
+ padding-top: 0.5rem;
2055
+ border-right: none;
2056
+ background: transparent;
2057
+ min-width: 0;
2058
+ }
2059
+
2060
+ #results {
2061
+ background: #fff;
2062
+ padding-left: 1rem;
2063
+ padding-right: 1rem;
2064
+ }
2065
+
2066
+ #right-column.smart-results-spacing #results {
2067
+ border-radius: 10px 10px 0px 0px;
2068
+ padding-top: 0.5rem;
2069
+ margin-top: 1rem;
2070
+ }
2071
+
2072
+ .mobile #right-column {
2073
+ border-left: none;
2074
+ }
2075
+
2076
+ .mobile #results {
2077
+ padding: 5px 5px 0;
2078
+ }
2079
+
2080
+ #left-column {
2081
+ width: var(--leftColumnWidth, 18rem);
2082
+ /* Prevents Safari from shrinking col at first draw */
2083
+ min-width: var(--leftColumnWidth, 18rem);
2084
+ padding-top: var(--leftColumnPaddingTop, 2rem);
2085
+ /* Reduced padding by 0.2rem to add the invisible border in the rule below */
2086
+ padding-right: calc(var(--leftColumnPaddingRight, 2.5rem) - 0.2rem);
2087
+ border-right: 0.2rem solid transparent; /* Pads to the right of the scrollbar a bit */
2088
+ z-index: 1;
2089
+ }
2090
+
2091
+ .desktop #left-column {
2092
+ top: 0;
2093
+ position: sticky;
2094
+ height: calc(100vh - 2rem);
2095
+ max-height: calc(100vh - 2rem);
2096
+ overflow-x: hidden;
2097
+ overflow-y: scroll;
2098
+
2099
+ /*
2100
+ * Firefox doesn't support any of the -webkit-scrollbar stuff below, but
2101
+ * does at least give us a tiny bit of control over width & color.
2102
+ */
2103
+ scrollbar-width: thin;
2104
+ scrollbar-color: transparent transparent;
2105
+ }
2106
+ .desktop #left-column:hover {
2107
+ scrollbar-color: auto;
2108
+ }
2109
+ .desktop #left-column::-webkit-scrollbar {
2110
+ appearance: none;
2111
+ width: 6px;
2112
+ }
2113
+ .desktop #left-column::-webkit-scrollbar-button {
2114
+ height: 3px;
2115
+ background: transparent;
2116
+ }
2117
+ .desktop #left-column::-webkit-scrollbar-corner {
2118
+ background: transparent;
2119
+ }
2120
+ .desktop #left-column::-webkit-scrollbar-thumb {
2121
+ border-radius: 4px;
2122
+ }
2123
+ .desktop #left-column:hover::-webkit-scrollbar-thumb {
2124
+ background: rgba(0, 0, 0, 0.15);
2125
+ }
2126
+ .desktop #left-column:hover::-webkit-scrollbar-thumb:hover {
2127
+ background: rgba(0, 0, 0, 0.2);
2128
+ }
2129
+ .desktop #left-column:hover::-webkit-scrollbar-thumb:active {
2130
+ background: rgba(0, 0, 0, 0.3);
2131
+ }
2132
+
2133
+ #facets-bottom-fade {
2134
+ background: linear-gradient(
2135
+ to bottom,
2136
+ #fbfbfd00 0%,
2137
+ #fbfbfdc0 50%,
2138
+ #fbfbfd 80%,
2139
+ #fbfbfd 100%
2140
+ );
2141
+ position: fixed;
2142
+ bottom: 0;
2143
+ height: 50px;
2144
+ /* Wide enough to cover the content, but leave the scrollbar uncovered */
2145
+ width: calc(
2146
+ var(--leftColumnWidth) + var(--leftColumnPaddingRight) - 10px
2147
+ );
2148
+ z-index: 2;
2149
+ pointer-events: none;
2150
+ transition: height 0.1s ease;
2151
+ }
2152
+ #facets-bottom-fade.hidden {
2153
+ height: 0;
2154
+ }
2155
+
2156
+ .facets-message {
2157
+ font-size: 1.4rem;
2158
+ }
2159
+
2160
+ .desktop-facets-dropdown > summary {
2161
+ cursor: pointer;
2162
+ list-style: none;
2163
+ }
2164
+
2165
+ .desktop-facets-dropdown h2 {
2166
+ display: inline-block;
2167
+ margin: 0;
2168
+ font-size: 1.6rem;
2169
+ }
2170
+
2171
+ .desktop-facets-dropdown[open] > summary {
2172
+ margin-bottom: 10px;
2173
+ }
2174
+
2175
+ .desktop-facets-dropdown[open] svg {
2176
+ transform: rotate(90deg);
2177
+ }
2178
+
2179
+ .desktop #left-column-scroll-sentinel {
2180
+ width: 1px;
2181
+ height: 100vh;
2182
+ background: transparent;
2183
+ }
2184
+
2185
+ .desktop #facets-scroll-sentinel {
2186
+ width: 1px;
2187
+ height: 1px;
2188
+ background: transparent;
2189
+ }
2190
+
2191
+ #facets-header-container {
2192
+ display: flex;
2193
+ justify-content: space-between;
2194
+ align-items: flex-start;
2195
+ clear: both;
2196
+ }
2197
+
2198
+ .desktop #facets-header-container {
2199
+ flex-wrap: wrap;
2200
+ }
2201
+
2202
+ .mobile #left-column {
2203
+ width: 100%;
2204
+ min-width: 0;
2205
+ padding: 5px 0;
2206
+ border: 0;
2207
+ }
2208
+
2209
+ .clear-filters-btn-row {
2210
+ display: inline-block;
2211
+ }
2212
+
2213
+ .desktop .clear-filters-btn-row {
2214
+ width: 100%;
2215
+ }
2216
+
2217
+ .clear-filters-btn {
2218
+ display: inline-block;
2219
+ appearance: none;
2220
+ margin: 0;
2221
+ padding: 0;
2222
+ border: 0;
2223
+ background: none;
2224
+ color: var(--ia-theme-link-color);
2225
+ font-size: 1.4rem;
2226
+ font-family: inherit;
2227
+ cursor: pointer;
2228
+ }
2229
+
2230
+ .clear-filters-btn:hover {
2231
+ text-decoration: underline;
2232
+ }
2233
+
2234
+ .clear-filters-btn-separator {
2235
+ display: inline-block;
2236
+ margin-left: 5px;
2237
+ border-left: 1px solid #2c2c2c;
2238
+ font-size: 1.4rem;
2239
+ line-height: 1.3rem;
2240
+ }
2241
+
2242
+ #tv-filters {
2243
+ margin-bottom: 15px;
2244
+ }
2245
+
2246
+ #tv-shows {
2247
+ --comboBoxListWidth: 300px;
2248
+ }
2249
+
2250
+ .tv-filter-dropdown {
2251
+ display: block;
2252
+ font-size: 14px;
2253
+ margin-left: 1px;
2254
+ margin-bottom: 5px;
2255
+ }
2256
+
2257
+ .tv-filter-dropdown::part(combo-box) {
2258
+ outline-offset: 1px;
2259
+ }
2260
+
2261
+ .tv-filter-dropdown::part(option) {
2262
+ line-height: 1.1;
2263
+ padding: 7px;
2264
+ }
2265
+
2266
+ .tv-filter-dropdown::part(clear-button) {
2267
+ flex: 0 0 26px;
2268
+ --combo-box-clear-icon-size: 14px;
2269
+ }
2270
+
2271
+ .tv-filter-dropdown::part(icon) {
2272
+ width: 1.4rem;
2273
+ height: 1.4rem;
2274
+ }
2275
+
2276
+ #facets-container {
2277
+ position: relative;
2278
+ max-height: 0;
2279
+ transition: max-height 0.2s ease-in-out;
2280
+ z-index: 1;
2281
+ margin-top: var(--facetsContainerMarginTop, 3rem);
2282
+ padding-bottom: 2rem;
2283
+ }
2284
+
2285
+ .desktop #facets-container {
2286
+ width: 18rem;
2287
+ }
2288
+
2289
+ .mobile #facets-container {
2290
+ overflow: hidden;
2291
+ padding-bottom: 0;
2292
+ padding-left: 10px;
2293
+ padding-right: 10px;
2294
+ }
2295
+
2296
+ #facets-container.expanded {
2297
+ max-height: 2000px;
2298
+ }
2299
+
2300
+ .results-section-heading {
2301
+ margin: 0.5rem 0.3rem;
2302
+ font-size: 2rem;
2303
+ line-height: 25px;
2304
+ }
2305
+
2306
+ #results-total {
2307
+ display: flex;
2308
+ align-items: baseline;
2309
+ }
2310
+
2311
+ #results-total:not(.filtered) {
2312
+ padding-bottom: 2rem;
2313
+ }
2314
+
2315
+ .mobile #results-total {
2316
+ position: absolute;
2317
+ right: 10px;
2318
+ }
2319
+
2320
+ #big-results-count {
2321
+ font-size: 2.4rem;
2322
+ font-weight: 500;
2323
+ margin-right: 5px;
2324
+ }
2325
+
2326
+ .mobile #big-results-count {
2327
+ font-size: 2rem;
2328
+ }
2329
+
2330
+ #big-results-label {
2331
+ font-size: 1.4rem;
2332
+ font-weight: 200;
2333
+ }
2334
+
2335
+ #list-header {
2336
+ max-height: 4.2rem;
2337
+ }
2338
+
2339
+ .loading-cover {
2340
+ position: absolute;
2341
+ top: 0;
2342
+ left: 0;
2343
+ width: 100%;
2344
+ height: 100%;
2345
+ display: flex;
2346
+ justify-content: center;
2347
+ z-index: 1;
2348
+ padding-top: 50px;
2349
+ }
2350
+
2351
+ #tile-blur-label {
2352
+ display: flex;
2353
+ align-items: center;
2354
+ column-gap: 5px;
2355
+ }
2356
+
2357
+ #tile-blur-check {
2358
+ margin: 0 5px 0 0;
2359
+ width: 15px;
2360
+ }
2361
+
2362
+ circular-activity-indicator {
2363
+ width: 30px;
2364
+ height: 30px;
2365
+ }
2366
+
2367
+ sort-filter-bar {
2368
+ display: block;
2369
+ margin-bottom: 4rem;
2370
+ }
2371
+
2372
+ infinite-scroller {
2373
+ display: block;
2374
+ --infiniteScrollerRowGap: var(--collectionBrowserRowGap, 1.7rem);
2375
+ --infiniteScrollerColGap: var(--collectionBrowserColGap, 1.7rem);
2376
+ }
2377
+
2378
+ infinite-scroller.list-compact {
2379
+ --infiniteScrollerCellMinWidth: var(
2380
+ --collectionBrowserCellMinWidth,
2381
+ 100%
2382
+ );
2383
+ --infiniteScrollerCellMinHeight: 45px; /* override infinite scroller component */
2384
+ --infiniteScrollerCellMaxHeight: 56px;
2385
+ --infiniteScrollerRowGap: 10px;
2386
+ }
2387
+
2388
+ infinite-scroller.list-detail {
2389
+ --infiniteScrollerCellMinWidth: var(
2390
+ --collectionBrowserCellMinWidth,
2391
+ 100%
2392
+ );
2393
+ --infiniteScrollerCellMinHeight: var(
2394
+ --collectionBrowserCellMinHeight,
2395
+ 5rem
2396
+ );
2397
+ /*
2398
+ 30px in spec, compensating for a -4px margin
2399
+ to align title with top of item image
2400
+ src/tiles/list/tile-list.ts
2401
+ */
2402
+ --infiniteScrollerRowGap: 34px;
2403
+ }
2404
+
2405
+ .mobile infinite-scroller.list-detail {
2406
+ --infiniteScrollerRowGap: 24px;
2407
+ }
2408
+
2409
+ infinite-scroller.grid {
2410
+ --infiniteScrollerCellMinWidth: var(
2411
+ --collectionBrowserCellMinWidth,
2412
+ 17rem
2413
+ );
2414
+ --infiniteScrollerCellMaxWidth: var(
2415
+ --collectionBrowserCellMaxWidth,
2416
+ 1fr
2417
+ );
2418
+ }
2419
+
2420
+ /* Allow tiles to shrink a bit further at smaller viewport widths */
2421
+ @media screen and (max-width: 880px) {
2422
+ infinite-scroller.grid {
2423
+ --infiniteScrollerCellMinWidth: var(
2424
+ --collectionBrowserCellMinWidth,
2425
+ 15rem
2426
+ );
2427
+ }
2428
+ }
2429
+ /* At very small widths, maintain a 2-tile layout as far as it can reasonably go */
2430
+ @media screen and (max-width: 360px) {
2431
+ infinite-scroller.grid {
2432
+ --infiniteScrollerCellMinWidth: var(
2433
+ --collectionBrowserCellMinWidth,
2434
+ 12rem
2435
+ );
2436
+ }
2437
+ }
2438
+
2439
+ infinite-scroller.hidden {
2440
+ display: none;
2441
+ }
2501
2442
  `,
2502
2443
  ];
2503
2444
  }