@internetarchive/collection-browser 4.3.1 → 4.3.2-alpha-webdev7939.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.
@@ -1,3 +1,4 @@
1
+ var CollectionBrowser_1;
1
2
  import { __decorate } from "tslib";
2
3
  import { html, css, LitElement, nothing, } from 'lit';
3
4
  import { customElement, property, query, state } from 'lit/decorators.js';
@@ -24,6 +25,7 @@ import './collection-facets';
24
25
  import './circular-activity-indicator';
25
26
  import './collection-facets/smart-facets/smart-facet-bar';
26
27
  let CollectionBrowser = class CollectionBrowser extends LitElement {
28
+ static { CollectionBrowser_1 = this; }
27
29
  constructor() {
28
30
  super();
29
31
  this.baseImageUrl = 'https://archive.org';
@@ -188,6 +190,7 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
188
190
  */
189
191
  this.dataSourceInstallInProgress = false;
190
192
  this.placeholderCellTemplate = html `<collection-browser-loading-tile></collection-browser-loading-tile>`;
193
+ this.deferredFetchTimer = 0;
191
194
  /**
192
195
  * Updates the height of the left column according to its position on the page.
193
196
  * Arrow function ensures proper `this` binding.
@@ -225,7 +228,7 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
225
228
  const model = this.dataSource.getTileModelAt(index);
226
229
  /**
227
230
  * If we encounter a model we don't have yet and we're not in the middle of an
228
- * automated scroll, fetch the page and just return undefined.
231
+ * automated scroll, schedule a fetch for the missing page and return undefined.
229
232
  * The datasource will be updated once the page is loaded and the cell will be rendered.
230
233
  *
231
234
  * We disable it during the automated scroll since we don't want to fetch pages for intervening cells the
@@ -233,10 +236,52 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
233
236
  */
234
237
  if (!model && !this.isScrollingToCell && this.dataSource.queryInitialized) {
235
238
  const pageNumber = Math.floor(index / this.pageSize) + 1;
236
- this.dataSource.fetchPage(pageNumber);
239
+ this.scheduleDeferredPageFetch(pageNumber);
237
240
  }
238
241
  return model;
239
242
  }
243
+ /**
244
+ * Debounce delay for page fetches initiated by new cells becoming visible.
245
+ * Tuned so quick scrolling through unloaded regions doesn't send rapid-fire
246
+ * search requests for every page we pass through, but to still feel responsive
247
+ * when the scroll ends.
248
+ */
249
+ static { this.DEFERRED_FETCH_DELAY_MS = 150; }
250
+ /**
251
+ * Schedules a fetch for the given page, debounced to ensure we don't
252
+ * rapid-fire fetches while scrolling through pages quickly.
253
+ *
254
+ * If there's no pending fetch timer yet, it will fire a fetch immediately.
255
+ * Otherwise, it will reset any existing timer. In either case, a deferred
256
+ * fetch for the visible pages is scheduled after a brief delay to account
257
+ * for whatever pages we land on after scrolling.
258
+ */
259
+ scheduleDeferredPageFetch(pageNumber) {
260
+ if (!this.deferredFetchTimer) {
261
+ this.dataSource.fetchPage(pageNumber);
262
+ }
263
+ else {
264
+ window.clearTimeout(this.deferredFetchTimer);
265
+ }
266
+ this.deferredFetchTimer = window.setTimeout(() => {
267
+ this.deferredFetchTimer = 0;
268
+ this.fetchVisiblePages();
269
+ }, CollectionBrowser_1.DEFERRED_FETCH_DELAY_MS);
270
+ }
271
+ /**
272
+ * Fetch each currently-visible page whose first cell still has no
273
+ * loaded model.
274
+ */
275
+ fetchVisiblePages() {
276
+ const visibleIndices = this.infiniteScroller?.getVisibleCellIndices() ?? [];
277
+ const visiblePages = new Set(visibleIndices.map(i => Math.floor(i / this.pageSize) + 1));
278
+ for (const page of visiblePages) {
279
+ const firstCellOfPage = (page - 1) * this.pageSize;
280
+ if (!this.dataSource.getTileModelAt(firstCellOfPage)) {
281
+ this.dataSource.fetchPage(page);
282
+ }
283
+ }
284
+ }
240
285
  // this is the total number of tiles we expect if
241
286
  // the data returned is a full page worth
242
287
  // this is useful for putting in placeholders for the expected number of tiles
@@ -406,32 +451,32 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
406
451
  }
407
452
  }
408
453
  render() {
409
- return html `
454
+ return html `
410
455
  ${this.showSmartFacetBar && this.placeholderType === null
411
- ? html `<smart-facet-bar
412
- .query=${this.baseQuery}
413
- .aggregations=${this.dataSource.aggregations}
414
- .selectedFacets=${this.selectedFacets}
415
- .collectionTitles=${this.dataSource.collectionTitles}
416
- .filterToggleShown=${!this.mobileView}
417
- .filterToggleActive=${this.facetPaneVisible}
418
- .label=${this.smartFacetBarLabel}
419
- @facetsChanged=${this.facetsChanged}
456
+ ? html `<smart-facet-bar
457
+ .query=${this.baseQuery}
458
+ .aggregations=${this.dataSource.aggregations}
459
+ .selectedFacets=${this.selectedFacets}
460
+ .collectionTitles=${this.dataSource.collectionTitles}
461
+ .filterToggleShown=${!this.mobileView}
462
+ .filterToggleActive=${this.facetPaneVisible}
463
+ .label=${this.smartFacetBarLabel}
464
+ @facetsChanged=${this.facetsChanged}
420
465
  @filtersToggled=${() => {
421
466
  this.facetPaneVisible = !this.facetPaneVisible;
422
467
  this.emitFacetPaneVisibilityChanged();
423
- }}
468
+ }}
424
469
  ></smart-facet-bar>`
425
- : nothing}
426
-
427
- <div
428
- id="content-container"
429
- class=${this.mobileView ? 'mobile' : 'desktop'}
430
- >
470
+ : nothing}
471
+
472
+ <div
473
+ id="content-container"
474
+ class=${this.mobileView ? 'mobile' : 'desktop'}
475
+ >
431
476
  ${this.placeholderType
432
477
  ? this.emptyPlaceholderTemplate
433
- : this.collectionBrowserTemplate}
434
- </div>
478
+ : this.collectionBrowserTemplate}
479
+ </div>
435
480
  `;
436
481
  }
437
482
  /**
@@ -475,23 +520,23 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
475
520
  * Template for the placeholder content to show when no results are available.
476
521
  */
477
522
  get emptyPlaceholderTemplate() {
478
- return html `
479
- <empty-placeholder
480
- .placeholderType=${this.placeholderType}
481
- ?isMobileView=${this.mobileView}
482
- ?isCollection=${!!this.withinCollection}
483
- .detailMessage=${this.dataSource.queryErrorMessage ?? ''}
484
- .baseNavigationUrl=${this.baseNavigationUrl}
485
- ></empty-placeholder>
523
+ return html `
524
+ <empty-placeholder
525
+ .placeholderType=${this.placeholderType}
526
+ ?isMobileView=${this.mobileView}
527
+ ?isCollection=${!!this.withinCollection}
528
+ .detailMessage=${this.dataSource.queryErrorMessage ?? ''}
529
+ .baseNavigationUrl=${this.baseNavigationUrl}
530
+ ></empty-placeholder>
486
531
  `;
487
532
  }
488
533
  /**
489
534
  * Top-level template for rendering the left (facets) and right (results) columns.
490
535
  */
491
536
  get collectionBrowserTemplate() {
492
- return html `
493
- <div id="left-column-scroll-sentinel"></div>
494
- ${this.leftColumnTemplate} ${this.rightColumnTemplate}
537
+ return html `
538
+ <div id="left-column-scroll-sentinel"></div>
539
+ ${this.leftColumnTemplate} ${this.rightColumnTemplate}
495
540
  `;
496
541
  }
497
542
  /**
@@ -510,33 +555,33 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
510
555
  * accordion-style facets.
511
556
  */
512
557
  get mobileLeftColumnTemplate() {
513
- return html `
514
- <div
515
- id="left-column"
516
- class="column${this.isResizeToMobile ? ' preload' : ''}"
517
- >
518
- ${this.facetTopViewSlot} ${this.resultsCountTemplate}
519
- <div id="facets-header-container">${this.mobileFacetsTemplate}</div>
520
- </div>
558
+ return html `
559
+ <div
560
+ id="left-column"
561
+ class="column${this.isResizeToMobile ? ' preload' : ''}"
562
+ >
563
+ ${this.facetTopViewSlot} ${this.resultsCountTemplate}
564
+ <div id="facets-header-container">${this.mobileFacetsTemplate}</div>
565
+ </div>
521
566
  `;
522
567
  }
523
568
  /**
524
569
  * Template for the desktop version of the left column, displaying the facets sidebar.
525
570
  */
526
571
  get desktopLeftColumnTemplate() {
527
- return html `
528
- <div id="left-column" class="column" ?hidden=${!this.facetPaneVisible}>
529
- ${this.facetTopViewSlot}
530
- <div id="facets-header-container">
531
- <h2 id="facets-header" class="sr-only">${msg('Filters')}</h2>
532
- ${this.resultsCountTemplate} ${this.clearFiltersBtnTemplate(false)}
533
- </div>
534
- <div id="facets-container" aria-labelledby="facets-header">
535
- ${this.facetsTemplate}
536
- <div id="facets-scroll-sentinel"></div>
537
- </div>
538
- <div id="facets-bottom-fade"></div>
539
- </div>
572
+ return html `
573
+ <div id="left-column" class="column" ?hidden=${!this.facetPaneVisible}>
574
+ ${this.facetTopViewSlot}
575
+ <div id="facets-header-container">
576
+ <h2 id="facets-header" class="sr-only">${msg('Filters')}</h2>
577
+ ${this.resultsCountTemplate} ${this.clearFiltersBtnTemplate(false)}
578
+ </div>
579
+ <div id="facets-container" aria-labelledby="facets-header">
580
+ ${this.facetsTemplate}
581
+ <div id="facets-scroll-sentinel"></div>
582
+ </div>
583
+ <div id="facets-bottom-fade"></div>
584
+ </div>
540
585
  `;
541
586
  }
542
587
  /**
@@ -544,8 +589,8 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
544
589
  * - mainly used to render userlists
545
590
  */
546
591
  get facetTopViewSlot() {
547
- return html `<div id="facet-top-view">
548
- <slot name="facet-top-slot"></slot>
592
+ return html `<div id="facet-top-view">
593
+ <slot name="facet-top-slot"></slot>
549
594
  </div>`;
550
595
  }
551
596
  /**
@@ -560,15 +605,15 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
560
605
  const resultsCount = this.totalResults?.toLocaleString();
561
606
  const resultsLabel = this.totalResults === 1 ? 'Result' : 'Results';
562
607
  // Added data-testid for Playwright testing
563
- return html `
564
- <div id="results-total" class=${classes} data-testid="results-total">
565
- <span id="big-results-count">
566
- ${shouldShowSearching ? html `Searching&hellip;` : resultsCount}
567
- </span>
568
- <span id="big-results-label">
569
- ${shouldShowSearching ? nothing : resultsLabel}
570
- </span>
571
- </div>
608
+ return html `
609
+ <div id="results-total" class=${classes} data-testid="results-total">
610
+ <span id="big-results-count">
611
+ ${shouldShowSearching ? html `Searching&hellip;` : resultsCount}
612
+ </span>
613
+ <span id="big-results-label">
614
+ ${shouldShowSearching ? nothing : resultsLabel}
615
+ </span>
616
+ </div>
572
617
  `;
573
618
  }
574
619
  /**
@@ -581,45 +626,46 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
581
626
  'full-width': !this.facetPaneVisible,
582
627
  'smart-results-spacing': !!this.showSmartResults,
583
628
  });
584
- return html `
585
- <div id="right-column" class=${rightColumnClasses}>
629
+ return html `
630
+ <div id="right-column" class=${rightColumnClasses}>
586
631
  ${this.showSmartResults
587
632
  ? html `<slot name="smart-results"></slot>`
588
- : nothing}
589
- <section id="results">
590
- <h2 class="results-section-heading">
591
- <slot name="results-heading"></slot>
592
- </h2>
593
- <div id="cb-top-view">
594
- <slot name="cb-top-slot"></slot>
595
- </div>
633
+ : nothing}
634
+ <section id="results">
635
+ <h2 class="results-section-heading">
636
+ <slot name="results-heading"></slot>
637
+ </h2>
638
+ <div id="cb-top-view">
639
+ <slot name="cb-top-slot"></slot>
640
+ </div>
596
641
  ${this.isManageView
597
642
  ? this.manageBarTemplate
598
- : this.sortFilterBarTemplate}
599
- <slot name="cb-results"></slot>
643
+ : this.sortFilterBarTemplate}
644
+ <slot name="cb-results"></slot>
600
645
  ${this.displayMode === `list-compact` && this.totalResults
601
646
  ? this.listHeaderTemplate
602
- : nothing}
603
- ${this.suppressResultTiles ? nothing : this.infiniteScrollerTemplate}
604
- </section>
605
- </div>
647
+ : nothing}
648
+ ${this.suppressResultTiles ? nothing : this.infiniteScrollerTemplate}
649
+ </section>
650
+ </div>
606
651
  `;
607
652
  }
608
653
  /**
609
654
  * Template for the infinite scroller widget that contains the result tiles.
610
655
  */
611
656
  get infiniteScrollerTemplate() {
612
- return html `<infinite-scroller
613
- class=${this.infiniteScrollerClasses}
614
- itemCount=${this.placeholderType ? 0 : nothing}
615
- ariaLandmarkLabel="Search results"
616
- .cellProvider=${this}
617
- .placeholderCellTemplate=${this.placeholderCellTemplate}
618
- @scrollThresholdReached=${this.scrollThresholdReached}
619
- @visibleCellsChanged=${this.visibleCellsChanged}
657
+ return html `<infinite-scroller
658
+ class=${this.infiniteScrollerClasses}
659
+ itemCount=${this.placeholderType ? 0 : nothing}
660
+ ariaLandmarkLabel="Search results"
661
+ .estimatedCellHeight=${this.estimatedTileHeight}
662
+ .cellProvider=${this}
663
+ .placeholderCellTemplate=${this.placeholderCellTemplate}
664
+ @scrollThresholdReached=${this.scrollThresholdReached}
665
+ @visibleCellsChanged=${this.visibleCellsChanged}
620
666
  >${this.displayMode === 'grid'
621
667
  ? html `<slot name="result-last-tile" slot="result-last-tile"></slot>`
622
- : nothing}
668
+ : nothing}
623
669
  </infinite-scroller>`;
624
670
  }
625
671
  /**
@@ -632,6 +678,24 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
632
678
  hidden: !!this.placeholderType,
633
679
  });
634
680
  }
681
+ /**
682
+ * Best-effort hint of how tall a single rendered tile is, by display mode.
683
+ * The scroller uses this to better estimate the size its initial scroll
684
+ * spacer and buffer position before real cell heights are measured.
685
+ * Should roughly match the placeholder heights since the initial render
686
+ * of a new page generally shows placeholders only anyway.
687
+ */
688
+ get estimatedTileHeight() {
689
+ switch (this.displayMode) {
690
+ case 'list-detail':
691
+ return 80;
692
+ case 'list-compact':
693
+ return 45;
694
+ case 'grid':
695
+ default:
696
+ return 225;
697
+ }
698
+ }
635
699
  /**
636
700
  * Template for the sort & filtering bar that appears atop the search results.
637
701
  */
@@ -653,29 +717,29 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
653
717
  }
654
718
  // We only show relevance sort if a search query is currently defined
655
719
  sortFieldAvailability.relevance = this.isRelevanceSortAvailable;
656
- return html `
657
- <sort-filter-bar
658
- .defaultSortField=${this.defaultSortField}
659
- .defaultSortDirection=${this.defaultSortDirection}
660
- .selectedSort=${this.selectedSort}
661
- .sortDirection=${this.sortDirection}
662
- .sortFieldAvailability=${sortFieldAvailability}
663
- .displayMode=${this.displayMode}
664
- .selectedTitleFilter=${this.selectedTitleFilter}
665
- .selectedCreatorFilter=${this.selectedCreatorFilter}
666
- .prefixFilterCountMap=${this.dataSource.prefixFilterCountMap}
667
- .enableSortOptionsSlot=${this.enableSortOptionsSlot}
668
- .suppressDisplayModes=${this.suppressDisplayModes}
669
- @sortChanged=${this.userChangedSort}
670
- @displayModeChanged=${this.displayModeChanged}
671
- @titleLetterChanged=${this.titleLetterSelected}
672
- @creatorLetterChanged=${this.creatorLetterSelected}
673
- >
674
- ${this.tileBlurCheckboxTemplate}
675
- <slot name="sort-options-left" slot="sort-options-left"></slot>
676
- <slot name="sort-options" slot="sort-options"></slot>
677
- <slot name="sort-options-right" slot="sort-options-right"></slot>
678
- </sort-filter-bar>
720
+ return html `
721
+ <sort-filter-bar
722
+ .defaultSortField=${this.defaultSortField}
723
+ .defaultSortDirection=${this.defaultSortDirection}
724
+ .selectedSort=${this.selectedSort}
725
+ .sortDirection=${this.sortDirection}
726
+ .sortFieldAvailability=${sortFieldAvailability}
727
+ .displayMode=${this.displayMode}
728
+ .selectedTitleFilter=${this.selectedTitleFilter}
729
+ .selectedCreatorFilter=${this.selectedCreatorFilter}
730
+ .prefixFilterCountMap=${this.dataSource.prefixFilterCountMap}
731
+ .enableSortOptionsSlot=${this.enableSortOptionsSlot}
732
+ .suppressDisplayModes=${this.suppressDisplayModes}
733
+ @sortChanged=${this.userChangedSort}
734
+ @displayModeChanged=${this.displayModeChanged}
735
+ @titleLetterChanged=${this.titleLetterSelected}
736
+ @creatorLetterChanged=${this.creatorLetterSelected}
737
+ >
738
+ ${this.tileBlurCheckboxTemplate}
739
+ <slot name="sort-options-left" slot="sort-options-left"></slot>
740
+ <slot name="sort-options" slot="sort-options"></slot>
741
+ <slot name="sort-options-right" slot="sort-options-right"></slot>
742
+ </sort-filter-bar>
679
743
  `;
680
744
  }
681
745
  /**
@@ -686,20 +750,20 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
686
750
  // Only show the checkbox for @archive.org users
687
751
  if (!this.dataSource.sessionContext?.is_archive_user)
688
752
  return nothing;
689
- return html `
690
- <label
691
- id="tile-blur-label"
692
- for="tile-blur-check"
693
- slot="sort-options-right"
694
- >
695
- ${msg('Blurring')}
696
- <input
697
- id="tile-blur-check"
698
- type="checkbox"
699
- ?checked=${!this.shouldSuppressTileBlurring}
700
- @change=${this.tileBlurCheckboxChanged}
701
- />
702
- </label>
753
+ return html `
754
+ <label
755
+ id="tile-blur-label"
756
+ for="tile-blur-check"
757
+ slot="sort-options-right"
758
+ >
759
+ ${msg('Blurring')}
760
+ <input
761
+ id="tile-blur-check"
762
+ type="checkbox"
763
+ ?checked=${!this.shouldSuppressTileBlurring}
764
+ @change=${this.tileBlurCheckboxChanged}
765
+ />
766
+ </label>
703
767
  `;
704
768
  }
705
769
  /**
@@ -707,27 +771,27 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
707
771
  * showing the management view. This generally replaces the sort bar when present.
708
772
  */
709
773
  get manageBarTemplate() {
710
- return html `
711
- <manage-bar
712
- .label=${this.manageViewLabel}
713
- .modalManager=${this.modalManager}
714
- .selectedItems=${this.dataSource.checkedTileModels}
715
- .profileElement=${this.profileElement}
716
- showSelectAll
717
- showUnselectAll
718
- ?showItemManageButton=${this.pageContext === 'search'}
719
- ?removeAllowed=${this.dataSource.checkedTileModels.length !== 0}
720
- @removeItems=${this.handleRemoveItems}
721
- @manageItems=${this.handleManageItems}
722
- @selectAll=${() => this.dataSource.checkAllTiles()}
723
- @unselectAll=${() => this.dataSource.uncheckAllTiles()}
774
+ return html `
775
+ <manage-bar
776
+ .label=${this.manageViewLabel}
777
+ .modalManager=${this.modalManager}
778
+ .selectedItems=${this.dataSource.checkedTileModels}
779
+ .profileElement=${this.profileElement}
780
+ showSelectAll
781
+ showUnselectAll
782
+ ?showItemManageButton=${this.pageContext === 'search'}
783
+ ?removeAllowed=${this.dataSource.checkedTileModels.length !== 0}
784
+ @removeItems=${this.handleRemoveItems}
785
+ @manageItems=${this.handleManageItems}
786
+ @selectAll=${() => this.dataSource.checkAllTiles()}
787
+ @unselectAll=${() => this.dataSource.uncheckAllTiles()}
724
788
  @cancel=${() => {
725
789
  this.isManageView = false;
726
790
  this.dataSource.uncheckAllTiles();
727
791
  if (this.searchResultsLoading)
728
792
  this.dataSource.resetPages();
729
- }}
730
- ></manage-bar>
793
+ }}
794
+ ></manage-bar>
731
795
  `;
732
796
  }
733
797
  /**
@@ -962,15 +1026,15 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
962
1026
  label: target.open ? 'open' : 'closed',
963
1027
  });
964
1028
  };
965
- return html `
966
- <details id="mobile-filter-collapse" @toggle=${toggleFacetsVisible}>
967
- <summary>
968
- <span class="collapser-icon">${chevronIcon}</span>
969
- <h2>${msg('Filters')}</h2>
970
- ${this.clearFiltersBtnTemplate(true)}
971
- </summary>
972
- ${this.facetsTemplate}
973
- </details>
1029
+ return html `
1030
+ <details id="mobile-filter-collapse" @toggle=${toggleFacetsVisible}>
1031
+ <summary>
1032
+ <span class="collapser-icon">${chevronIcon}</span>
1033
+ <h2>${msg('Filters')}</h2>
1034
+ ${this.clearFiltersBtnTemplate(true)}
1035
+ </summary>
1036
+ ${this.facetsTemplate}
1037
+ </details>
974
1038
  `;
975
1039
  }
976
1040
  /**
@@ -1054,50 +1118,50 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
1054
1118
  const filterByNetworkLabel = msg('Filter by Network');
1055
1119
  const filterByShowLabel = msg('Filter by Show');
1056
1120
  const shows = showEntries.map(([show]) => show);
1057
- const loadingIndicator = html `
1058
- <span slot="empty-options">
1059
- <img src="https://archive.org/images/loading.gif" />
1060
- </span>
1121
+ const loadingIndicator = html `
1122
+ <span slot="empty-options">
1123
+ <img src="https://archive.org/images/loading.gif" />
1124
+ </span>
1061
1125
  `;
1062
- const errorMessage = html `
1063
- <span slot="empty-options">
1064
- ${msg('Unable to fetch options, try again later')}
1065
- </span>
1126
+ const errorMessage = html `
1127
+ <span slot="empty-options">
1128
+ ${msg('Unable to fetch options, try again later')}
1129
+ </span>
1066
1130
  `;
1067
- return html `
1068
- <div id="tv-filters" slot="facets-top">
1069
- <ia-combo-box
1070
- id="tv-networks"
1071
- class="tv-filter-dropdown"
1072
- placeholder=${filterByNetworkLabel}
1073
- clearable
1074
- wrap-arrow-keys
1075
- sort
1076
- .options=${networks.map((n, i) => ({ id: `network-${i}`, text: n }))}
1077
- @toggle=${this.tvDropdownToggled}
1078
- @change=${this.networksDropdownChanged}
1079
- >
1080
- <span slot="label" class="sr-only">${filterByNetworkLabel}</span>
1081
- ${this.tvMapsLoading ? loadingIndicator : nothing}
1082
- ${this.tvMapsErrored ? errorMessage : nothing}
1083
- </ia-combo-box>
1084
- <ia-combo-box
1085
- id="tv-shows"
1086
- class="tv-filter-dropdown"
1087
- placeholder=${filterByShowLabel}
1088
- max-autocomplete-entries="500"
1089
- clearable
1090
- wrap-arrow-keys
1091
- sort
1092
- .options=${shows.map((s, i) => ({ id: `show-${i}`, text: s }))}
1093
- @toggle=${this.tvDropdownToggled}
1094
- @change=${this.showsDropdownChanged}
1095
- >
1096
- <span slot="label" class="sr-only">${filterByShowLabel}</span>
1097
- ${this.tvMapsLoading ? loadingIndicator : nothing}
1098
- ${this.tvMapsErrored ? errorMessage : nothing}
1099
- </ia-combo-box>
1100
- </div>
1131
+ return html `
1132
+ <div id="tv-filters" slot="facets-top">
1133
+ <ia-combo-box
1134
+ id="tv-networks"
1135
+ class="tv-filter-dropdown"
1136
+ placeholder=${filterByNetworkLabel}
1137
+ clearable
1138
+ wrap-arrow-keys
1139
+ sort
1140
+ .options=${networks.map((n, i) => ({ id: `network-${i}`, text: n }))}
1141
+ @toggle=${this.tvDropdownToggled}
1142
+ @change=${this.networksDropdownChanged}
1143
+ >
1144
+ <span slot="label" class="sr-only">${filterByNetworkLabel}</span>
1145
+ ${this.tvMapsLoading ? loadingIndicator : nothing}
1146
+ ${this.tvMapsErrored ? errorMessage : nothing}
1147
+ </ia-combo-box>
1148
+ <ia-combo-box
1149
+ id="tv-shows"
1150
+ class="tv-filter-dropdown"
1151
+ placeholder=${filterByShowLabel}
1152
+ max-autocomplete-entries="500"
1153
+ clearable
1154
+ wrap-arrow-keys
1155
+ sort
1156
+ .options=${shows.map((s, i) => ({ id: `show-${i}`, text: s }))}
1157
+ @toggle=${this.tvDropdownToggled}
1158
+ @change=${this.showsDropdownChanged}
1159
+ >
1160
+ <span slot="label" class="sr-only">${filterByShowLabel}</span>
1161
+ ${this.tvMapsLoading ? loadingIndicator : nothing}
1162
+ ${this.tvMapsErrored ? errorMessage : nothing}
1163
+ </ia-combo-box>
1164
+ </div>
1101
1165
  `;
1102
1166
  }
1103
1167
  /**
@@ -1107,10 +1171,10 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
1107
1171
  if (FACETLESS_PAGE_ELEMENTS.includes(this.profileElement))
1108
1172
  return nothing;
1109
1173
  if (this.facetLoadStrategy === 'off') {
1110
- return html `
1111
- <p class="facets-message">
1112
- ${msg('Facets are temporarily unavailable.')}
1113
- </p>
1174
+ return html `
1175
+ <p class="facets-message">
1176
+ ${msg('Facets are temporarily unavailable.')}
1177
+ </p>
1114
1178
  `;
1115
1179
  }
1116
1180
  // We switch to TV facet ordering & date picker if we are in a TV collection or showing TV search results
@@ -1119,46 +1183,46 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
1119
1183
  const facetDisplayOrder = shouldUseTvInterface
1120
1184
  ? tvFacetDisplayOrder
1121
1185
  : defaultFacetDisplayOrder;
1122
- const facets = html `
1123
- <collection-facets
1124
- .collectionPagePath=${this.collectionPagePath}
1125
- .parentCollections=${this.dataSource.parentCollections}
1126
- .pageSpecifierParams=${this.dataSource.pageSpecifierParams}
1127
- .searchService=${this.searchService}
1128
- .featureFeedbackService=${this.featureFeedbackService}
1129
- .recaptchaManager=${this.recaptchaManager}
1130
- .resizeObserver=${this.resizeObserver}
1131
- .searchType=${this.searchType}
1132
- .aggregations=${this.dataSource.aggregations}
1133
- .histogramAggregation=${this.dataSource.histogramAggregation}
1134
- .minSelectedDate=${this.minSelectedDate}
1135
- .maxSelectedDate=${this.maxSelectedDate}
1136
- .selectedFacets=${this.selectedFacets}
1137
- .baseNavigationUrl=${this.baseNavigationUrl}
1138
- .collectionTitles=${this.dataSource.collectionTitles}
1139
- .tvChannelAliases=${this.dataSource.tvChannelAliases}
1140
- .showHistogramDatePicker=${this.showHistogramDatePicker}
1141
- .allowExpandingDatePicker=${!this.mobileView}
1142
- .allowDatePickerMonths=${shouldUseTvInterface}
1143
- .contentWidth=${this.contentWidth}
1144
- .query=${this.baseQuery}
1145
- .identifiers=${this.identifiers}
1146
- .filterMap=${this.dataSource.filterMap}
1147
- .isManageView=${this.isManageView}
1148
- .modalManager=${this.modalManager}
1149
- .analyticsHandler=${this.analyticsHandler}
1150
- .facetDisplayOrder=${facetDisplayOrder}
1151
- .isTvSearch=${shouldUseTvInterface}
1152
- ?collapsableFacets=${this.mobileView}
1153
- ?facetsLoading=${this.facetsLoading}
1154
- ?histogramAggregationLoading=${this.facetsLoading}
1155
- ?suppressMediatypeFacets=${this.suppressMediatypeFacets}
1156
- @facetClick=${this.facetClickHandler}
1157
- @facetsChanged=${this.facetsChanged}
1158
- @histogramDateRangeUpdated=${this.histogramDateRangeUpdated}
1159
- >
1160
- ${this.tvDropdownFiltersTemplate}
1161
- </collection-facets>
1186
+ const facets = html `
1187
+ <collection-facets
1188
+ .collectionPagePath=${this.collectionPagePath}
1189
+ .parentCollections=${this.dataSource.parentCollections}
1190
+ .pageSpecifierParams=${this.dataSource.pageSpecifierParams}
1191
+ .searchService=${this.searchService}
1192
+ .featureFeedbackService=${this.featureFeedbackService}
1193
+ .recaptchaManager=${this.recaptchaManager}
1194
+ .resizeObserver=${this.resizeObserver}
1195
+ .searchType=${this.searchType}
1196
+ .aggregations=${this.dataSource.aggregations}
1197
+ .histogramAggregation=${this.dataSource.histogramAggregation}
1198
+ .minSelectedDate=${this.minSelectedDate}
1199
+ .maxSelectedDate=${this.maxSelectedDate}
1200
+ .selectedFacets=${this.selectedFacets}
1201
+ .baseNavigationUrl=${this.baseNavigationUrl}
1202
+ .collectionTitles=${this.dataSource.collectionTitles}
1203
+ .tvChannelAliases=${this.dataSource.tvChannelAliases}
1204
+ .showHistogramDatePicker=${this.showHistogramDatePicker}
1205
+ .allowExpandingDatePicker=${!this.mobileView}
1206
+ .allowDatePickerMonths=${shouldUseTvInterface}
1207
+ .contentWidth=${this.contentWidth}
1208
+ .query=${this.baseQuery}
1209
+ .identifiers=${this.identifiers}
1210
+ .filterMap=${this.dataSource.filterMap}
1211
+ .isManageView=${this.isManageView}
1212
+ .modalManager=${this.modalManager}
1213
+ .analyticsHandler=${this.analyticsHandler}
1214
+ .facetDisplayOrder=${facetDisplayOrder}
1215
+ .isTvSearch=${shouldUseTvInterface}
1216
+ ?collapsableFacets=${this.mobileView}
1217
+ ?facetsLoading=${this.facetsLoading}
1218
+ ?histogramAggregationLoading=${this.facetsLoading}
1219
+ ?suppressMediatypeFacets=${this.suppressMediatypeFacets}
1220
+ @facetClick=${this.facetClickHandler}
1221
+ @facetsChanged=${this.facetsChanged}
1222
+ @histogramDateRangeUpdated=${this.histogramDateRangeUpdated}
1223
+ >
1224
+ ${this.tvDropdownFiltersTemplate}
1225
+ </collection-facets>
1162
1226
  `;
1163
1227
  // If we are using one of the opt-in facet load strategies, we may need to wrap the
1164
1228
  // desktop view facets in a <details> widget so that patrons can opt into loading them.
@@ -1166,20 +1230,20 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
1166
1230
  const showDesktopOptInWidget = this.facetLoadStrategy === 'opt-in' ||
1167
1231
  (this.facetLoadStrategy === 'opt-in-or-login' && !this.loggedIn);
1168
1232
  if (showDesktopOptInWidget && !this.mobileView) {
1169
- return html `
1170
- <details
1171
- class="desktop-facets-dropdown"
1233
+ return html `
1234
+ <details
1235
+ class="desktop-facets-dropdown"
1172
1236
  @toggle=${(e) => {
1173
1237
  const target = e.target;
1174
1238
  this.collapsibleFacetsVisible = target.open;
1175
- }}
1176
- >
1177
- <summary>
1178
- <span class="collapser-icon">${chevronIcon}</span>
1179
- <h2>${msg('Filters')}</h2>
1180
- </summary>
1181
- ${facets}
1182
- </details>
1239
+ }}
1240
+ >
1241
+ <summary>
1242
+ <span class="collapser-icon">${chevronIcon}</span>
1243
+ <h2>${msg('Filters')}</h2>
1244
+ </summary>
1245
+ ${facets}
1246
+ </details>
1183
1247
  `;
1184
1248
  }
1185
1249
  // Otherwise, just render the facets component bare
@@ -1199,34 +1263,34 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
1199
1263
  mobile,
1200
1264
  });
1201
1265
  const buttonText = mobile ? 'Clear all' : 'Clear all filters';
1202
- return html `
1203
- <div class="clear-filters-btn-row">
1266
+ return html `
1267
+ <div class="clear-filters-btn-row">
1204
1268
  ${mobile
1205
1269
  ? html `<span class="clear-filters-btn-separator">&nbsp;</span>`
1206
- : nothing}
1207
- <button class=${buttonClasses} @click=${this.clearFilters}>
1208
- ${buttonText}
1209
- </button>
1210
- </div>
1270
+ : nothing}
1271
+ <button class=${buttonClasses} @click=${this.clearFilters}>
1272
+ ${buttonText}
1273
+ </button>
1274
+ </div>
1211
1275
  `;
1212
1276
  }
1213
1277
  /**
1214
1278
  * Template for the table header content that appears atop the compact list view.
1215
1279
  */
1216
1280
  get listHeaderTemplate() {
1217
- return html `
1218
- <div id="list-header">
1219
- <tile-dispatcher
1220
- .tileDisplayMode=${'list-header'}
1221
- .resizeObserver=${this.resizeObserver}
1222
- .sortParam=${this.sortParam}
1223
- .defaultSortParam=${this.defaultSortParam}
1224
- .mobileBreakpoint=${this.mobileBreakpoint}
1225
- .loggedIn=${this.loggedIn}
1226
- .suppressBlurring=${this.shouldSuppressTileBlurring}
1227
- >
1228
- </tile-dispatcher>
1229
- </div>
1281
+ return html `
1282
+ <div id="list-header">
1283
+ <tile-dispatcher
1284
+ .tileDisplayMode=${'list-header'}
1285
+ .resizeObserver=${this.resizeObserver}
1286
+ .sortParam=${this.sortParam}
1287
+ .defaultSortParam=${this.defaultSortParam}
1288
+ .mobileBreakpoint=${this.mobileBreakpoint}
1289
+ .loggedIn=${this.loggedIn}
1290
+ .suppressBlurring=${this.shouldSuppressTileBlurring}
1291
+ >
1292
+ </tile-dispatcher>
1293
+ </div>
1230
1294
  `;
1231
1295
  }
1232
1296
  /**
@@ -1457,6 +1521,10 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
1457
1521
  if (this.boundNavigationHandler) {
1458
1522
  window.removeEventListener('popstate', this.boundNavigationHandler);
1459
1523
  }
1524
+ if (this.deferredFetchTimer) {
1525
+ window.clearTimeout(this.deferredFetchTimer);
1526
+ this.deferredFetchTimer = 0;
1527
+ }
1460
1528
  this.leftColIntersectionObserver?.disconnect();
1461
1529
  this.facetsIntersectionObserver?.disconnect();
1462
1530
  window.removeEventListener('resize', this.updateLeftColumnHeight);
@@ -1794,25 +1862,31 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
1794
1862
  label: facetType,
1795
1863
  });
1796
1864
  }
1797
- scrollToPage(pageNumber) {
1798
- return new Promise(resolve => {
1799
- const cellIndexToScrollTo = this.pageSize * (pageNumber - 1);
1800
- // without this setTimeout, Safari just pauses until the `fetchPage` is complete
1801
- // then scrolls to the cell
1802
- setTimeout(() => {
1803
- this.isScrollingToCell = true;
1804
- this.infiniteScroller?.scrollToCell(cellIndexToScrollTo, true);
1805
- // This timeout is to give the scroll animation time to finish
1806
- // then updating the infinite scroller once we're done scrolling
1807
- // There's no scroll animation completion callback so we're
1808
- // giving it 0.5s to finish.
1809
- setTimeout(() => {
1810
- this.isScrollingToCell = false;
1811
- this.infiniteScroller?.refreshAllVisibleCells();
1812
- resolve();
1813
- }, 500);
1814
- }, 0);
1865
+ async scrollToPage(pageNumber) {
1866
+ const cellIndexToScrollTo = this.pageSize * (pageNumber - 1);
1867
+ // Wait for the infinite scroller be rendered before proceeding
1868
+ let waitAttempts = 0;
1869
+ while (!this.infiniteScroller && waitAttempts < 20) {
1870
+ await this.updateComplete;
1871
+ waitAttempts++;
1872
+ }
1873
+ if (!this.infiniteScroller)
1874
+ return;
1875
+ // The scroller have its default `itemCount=0`, so propagate our estimated
1876
+ // tile count before jumping to the desired page.
1877
+ if (this.infiniteScroller.itemCount < this.estimatedTileCount) {
1878
+ this.infiniteScroller.itemCount = this.estimatedTileCount;
1879
+ await this.updateComplete;
1880
+ }
1881
+ // Without this setTimeout(0), Safari just pauses until the `fetchPage`
1882
+ // is complete then scrolls to the cell.
1883
+ await new Promise(resolve => {
1884
+ setTimeout(resolve, 0);
1815
1885
  });
1886
+ this.isScrollingToCell = true;
1887
+ await this.infiniteScroller.scrollToCell(cellIndexToScrollTo, true);
1888
+ this.isScrollingToCell = false;
1889
+ this.infiniteScroller.refreshAllVisibleCells();
1816
1890
  }
1817
1891
  /**
1818
1892
  * Whether sorting by relevance makes sense for the current state.
@@ -1956,28 +2030,28 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
1956
2030
  const isRadioSearch = this.searchType === SearchType.RADIO;
1957
2031
  const { isTVCollection, isRadioCollection } = this;
1958
2032
  const shouldUseLocalTime = isTVSearch || isRadioSearch || isTVCollection || isRadioCollection;
1959
- return html `
1960
- <tile-dispatcher
1961
- .collectionPagePath=${this.collectionPagePath}
1962
- .baseNavigationUrl=${this.baseNavigationUrl}
1963
- .baseImageUrl=${this.baseImageUrl}
1964
- .model=${model}
1965
- .tileDisplayMode=${this.displayMode}
1966
- .resizeObserver=${this.resizeObserver}
1967
- .collectionTitles=${this.dataSource.collectionTitles}
1968
- .sortParam=${this.sortParam}
1969
- .defaultSortParam=${this.defaultSortParam}
1970
- .creatorFilter=${this.selectedCreatorFilter}
1971
- .mobileBreakpoint=${this.mobileBreakpoint}
1972
- .loggedIn=${this.loggedIn}
1973
- .suppressBlurring=${this.shouldSuppressTileBlurring}
1974
- .isManageView=${this.isManageView}
1975
- ?showTvClips=${isTVSearch || isTVCollection}
1976
- ?enableHoverPane=${true}
1977
- ?useLocalTime=${shouldUseLocalTime}
1978
- @resultSelected=${(e) => this.resultSelected(e)}
1979
- >
1980
- </tile-dispatcher>
2033
+ return html `
2034
+ <tile-dispatcher
2035
+ .collectionPagePath=${this.collectionPagePath}
2036
+ .baseNavigationUrl=${this.baseNavigationUrl}
2037
+ .baseImageUrl=${this.baseImageUrl}
2038
+ .model=${model}
2039
+ .tileDisplayMode=${this.displayMode}
2040
+ .resizeObserver=${this.resizeObserver}
2041
+ .collectionTitles=${this.dataSource.collectionTitles}
2042
+ .sortParam=${this.sortParam}
2043
+ .defaultSortParam=${this.defaultSortParam}
2044
+ .creatorFilter=${this.selectedCreatorFilter}
2045
+ .mobileBreakpoint=${this.mobileBreakpoint}
2046
+ .loggedIn=${this.loggedIn}
2047
+ .suppressBlurring=${this.shouldSuppressTileBlurring}
2048
+ .isManageView=${this.isManageView}
2049
+ ?showTvClips=${isTVSearch || isTVCollection}
2050
+ ?enableHoverPane=${true}
2051
+ ?useLocalTime=${shouldUseLocalTime}
2052
+ @resultSelected=${(e) => this.resultSelected(e)}
2053
+ >
2054
+ </tile-dispatcher>
1981
2055
  `;
1982
2056
  }
1983
2057
  /**
@@ -2012,479 +2086,479 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
2012
2086
  static get styles() {
2013
2087
  return [
2014
2088
  srOnlyStyle,
2015
- css `
2016
- :host {
2017
- display: block;
2018
- --leftColumnWidth: 18rem;
2019
- --leftColumnPaddingTop: 2rem;
2020
- --leftColumnPaddingRight: 2.5rem;
2021
- }
2022
-
2023
- #facet-top-view {
2024
- display: flex;
2025
- }
2026
-
2027
- /**
2028
- * When page width resizes from desktop to mobile, use this class to
2029
- * disable expand/collapse transition when loading.
2030
- */
2031
- .preload * {
2032
- transition: none !important;
2033
- -webkit-transition: none !important;
2034
- -moz-transition: none !important;
2035
- -ms-transition: none !important;
2036
- -o-transition: none !important;
2037
- }
2038
-
2039
- #content-container {
2040
- display: flex;
2041
- }
2042
-
2043
- empty-placeholder {
2044
- margin-top: var(--placeholderMarginTop, 0);
2045
- }
2046
-
2047
- .collapser-icon {
2048
- display: inline-block;
2049
- }
2050
-
2051
- .collapser-icon svg {
2052
- display: inline-block;
2053
- width: 12px;
2054
- height: 12px;
2055
- transition: transform 0.2s ease-out;
2056
- }
2057
-
2058
- #mobile-filter-collapse {
2059
- width: 100%;
2060
- }
2061
-
2062
- #mobile-filter-collapse > summary {
2063
- cursor: pointer;
2064
- list-style: none;
2065
- }
2066
-
2067
- #mobile-filter-collapse[open] > summary {
2068
- margin-bottom: 10px;
2069
- }
2070
-
2071
- #mobile-filter-collapse h2 {
2072
- display: inline-block;
2073
- margin: 0;
2074
- font-size: 2rem;
2075
- }
2076
-
2077
- #mobile-filter-collapse[open] svg {
2078
- transform: rotate(90deg);
2079
- }
2080
-
2081
- #content-container.mobile {
2082
- display: block;
2083
- }
2084
-
2085
- #right-column {
2086
- flex: 1;
2087
- position: relative;
2088
- min-height: 90vh;
2089
- border-right: 1px solid rgb(232, 232, 232);
2090
- margin-top: var(--rightColumnMarginTop, 0);
2091
- padding-top: var(--rightColumnPaddingTop, 2rem);
2092
- background: #fff;
2093
- }
2094
-
2095
- #left-column:not([hidden]) + #right-column {
2096
- border-left: 1px solid rgb(232, 232, 232);
2097
- }
2098
-
2099
- #right-column.smart-results-spacing {
2100
- padding-top: 0.5rem;
2101
- border-right: none;
2102
- background: transparent;
2103
- min-width: 0;
2104
- }
2105
-
2106
- #results {
2107
- background: #fff;
2108
- padding-left: 1rem;
2109
- padding-right: 1rem;
2110
- }
2111
-
2112
- #right-column.smart-results-spacing #results {
2113
- border-radius: 10px 10px 0px 0px;
2114
- padding-top: 0.5rem;
2115
- margin-top: 1rem;
2116
- }
2117
-
2118
- .mobile #right-column {
2119
- border-left: none;
2120
- }
2121
-
2122
- .mobile #results {
2123
- padding: 5px 5px 0;
2124
- }
2125
-
2126
- #left-column {
2127
- width: var(--leftColumnWidth, 18rem);
2128
- /* Prevents Safari from shrinking col at first draw */
2129
- min-width: var(--leftColumnWidth, 18rem);
2130
- padding-top: var(--leftColumnPaddingTop, 2rem);
2131
- /* Reduced padding by 0.2rem to add the invisible border in the rule below */
2132
- padding-right: calc(var(--leftColumnPaddingRight, 2.5rem) - 0.2rem);
2133
- border-right: 0.2rem solid transparent; /* Pads to the right of the scrollbar a bit */
2134
- z-index: 1;
2135
- }
2136
-
2137
- .desktop #left-column {
2138
- top: 0;
2139
- position: sticky;
2140
- height: calc(100vh - 2rem);
2141
- max-height: calc(100vh - 2rem);
2142
- overflow-x: hidden;
2143
- overflow-y: scroll;
2144
-
2145
- /*
2146
- * Firefox doesn't support any of the -webkit-scrollbar stuff below, but
2147
- * does at least give us a tiny bit of control over width & color.
2148
- */
2149
- scrollbar-width: thin;
2150
- scrollbar-color: transparent transparent;
2151
- }
2152
- .desktop #left-column:hover {
2153
- scrollbar-color: auto;
2154
- }
2155
- .desktop #left-column::-webkit-scrollbar {
2156
- appearance: none;
2157
- width: 6px;
2158
- }
2159
- .desktop #left-column::-webkit-scrollbar-button {
2160
- height: 3px;
2161
- background: transparent;
2162
- }
2163
- .desktop #left-column::-webkit-scrollbar-corner {
2164
- background: transparent;
2165
- }
2166
- .desktop #left-column::-webkit-scrollbar-thumb {
2167
- border-radius: 4px;
2168
- }
2169
- .desktop #left-column:hover::-webkit-scrollbar-thumb {
2170
- background: rgba(0, 0, 0, 0.15);
2171
- }
2172
- .desktop #left-column:hover::-webkit-scrollbar-thumb:hover {
2173
- background: rgba(0, 0, 0, 0.2);
2174
- }
2175
- .desktop #left-column:hover::-webkit-scrollbar-thumb:active {
2176
- background: rgba(0, 0, 0, 0.3);
2177
- }
2178
-
2179
- #facets-bottom-fade {
2180
- background: linear-gradient(
2181
- to bottom,
2182
- #fbfbfd00 0%,
2183
- #fbfbfdc0 50%,
2184
- #fbfbfd 80%,
2185
- #fbfbfd 100%
2186
- );
2187
- position: fixed;
2188
- bottom: 0;
2189
- height: 50px;
2190
- /* Wide enough to cover the content, but leave the scrollbar uncovered */
2191
- width: calc(
2192
- var(--leftColumnWidth) + var(--leftColumnPaddingRight) - 10px
2193
- );
2194
- z-index: 2;
2195
- pointer-events: none;
2196
- transition: height 0.1s ease;
2197
- }
2198
- #facets-bottom-fade.hidden {
2199
- height: 0;
2200
- }
2201
-
2202
- .facets-message {
2203
- font-size: 1.4rem;
2204
- }
2205
-
2206
- .desktop-facets-dropdown > summary {
2207
- cursor: pointer;
2208
- list-style: none;
2209
- }
2210
-
2211
- .desktop-facets-dropdown h2 {
2212
- display: inline-block;
2213
- margin: 0;
2214
- font-size: 1.6rem;
2215
- }
2216
-
2217
- .desktop-facets-dropdown[open] > summary {
2218
- margin-bottom: 10px;
2219
- }
2220
-
2221
- .desktop-facets-dropdown[open] svg {
2222
- transform: rotate(90deg);
2223
- }
2224
-
2225
- .desktop #left-column-scroll-sentinel {
2226
- width: 1px;
2227
- height: 100vh;
2228
- background: transparent;
2229
- }
2230
-
2231
- .desktop #facets-scroll-sentinel {
2232
- width: 1px;
2233
- height: 1px;
2234
- background: transparent;
2235
- }
2236
-
2237
- #facets-header-container {
2238
- display: flex;
2239
- justify-content: space-between;
2240
- align-items: flex-start;
2241
- clear: both;
2242
- }
2243
-
2244
- .desktop #facets-header-container {
2245
- flex-wrap: wrap;
2246
- }
2247
-
2248
- .mobile #left-column {
2249
- width: 100%;
2250
- min-width: 0;
2251
- padding: 5px 0;
2252
- border: 0;
2253
- }
2254
-
2255
- .clear-filters-btn-row {
2256
- display: inline-block;
2257
- }
2258
-
2259
- .desktop .clear-filters-btn-row {
2260
- width: 100%;
2261
- }
2262
-
2263
- .clear-filters-btn {
2264
- display: inline-block;
2265
- appearance: none;
2266
- margin: 0;
2267
- padding: 0;
2268
- border: 0;
2269
- background: none;
2270
- color: var(--ia-theme-link-color);
2271
- font-size: 1.4rem;
2272
- font-family: inherit;
2273
- cursor: pointer;
2274
- }
2275
-
2276
- .clear-filters-btn:hover {
2277
- text-decoration: underline;
2278
- }
2279
-
2280
- .clear-filters-btn-separator {
2281
- display: inline-block;
2282
- margin-left: 5px;
2283
- border-left: 1px solid #2c2c2c;
2284
- font-size: 1.4rem;
2285
- line-height: 1.3rem;
2286
- }
2287
-
2288
- #tv-filters {
2289
- margin-bottom: 15px;
2290
- }
2291
-
2292
- #tv-shows {
2293
- --comboBoxListWidth: 300px;
2294
- }
2295
-
2296
- .tv-filter-dropdown {
2297
- display: block;
2298
- font-size: 14px;
2299
- margin-left: 1px;
2300
- margin-bottom: 5px;
2301
- }
2302
-
2303
- .tv-filter-dropdown::part(combo-box) {
2304
- outline-offset: 1px;
2305
- }
2306
-
2307
- .tv-filter-dropdown::part(option) {
2308
- line-height: 1.1;
2309
- padding: 7px;
2310
- }
2311
-
2312
- .tv-filter-dropdown::part(clear-button) {
2313
- flex: 0 0 26px;
2314
- --combo-box-clear-icon-size: 14px;
2315
- }
2316
-
2317
- .tv-filter-dropdown::part(icon) {
2318
- width: 1.4rem;
2319
- height: 1.4rem;
2320
- }
2321
-
2322
- #facets-container {
2323
- position: relative;
2324
- max-height: 0;
2325
- transition: max-height 0.2s ease-in-out;
2326
- z-index: 1;
2327
- margin-top: var(--facetsContainerMarginTop, 3rem);
2328
- padding-bottom: 2rem;
2329
- }
2330
-
2331
- .desktop #facets-container {
2332
- width: 18rem;
2333
- }
2334
-
2335
- .mobile #facets-container {
2336
- overflow: hidden;
2337
- padding-bottom: 0;
2338
- padding-left: 10px;
2339
- padding-right: 10px;
2340
- }
2341
-
2342
- #facets-container.expanded {
2343
- max-height: 2000px;
2344
- }
2345
-
2346
- .results-section-heading {
2347
- margin: 0.5rem 0.3rem;
2348
- font-size: 2rem;
2349
- line-height: 25px;
2350
- }
2351
-
2352
- #results-total {
2353
- display: flex;
2354
- align-items: baseline;
2355
- }
2356
-
2357
- #results-total:not(.filtered) {
2358
- padding-bottom: 2rem;
2359
- }
2360
-
2361
- .mobile #results-total {
2362
- position: absolute;
2363
- right: 10px;
2364
- }
2365
-
2366
- #big-results-count {
2367
- font-size: 2.4rem;
2368
- font-weight: 500;
2369
- margin-right: 5px;
2370
- }
2371
-
2372
- .mobile #big-results-count {
2373
- font-size: 2rem;
2374
- }
2375
-
2376
- #big-results-label {
2377
- font-size: 1.4rem;
2378
- font-weight: 200;
2379
- }
2380
-
2381
- #list-header {
2382
- max-height: 4.2rem;
2383
- }
2384
-
2385
- .loading-cover {
2386
- position: absolute;
2387
- top: 0;
2388
- left: 0;
2389
- width: 100%;
2390
- height: 100%;
2391
- display: flex;
2392
- justify-content: center;
2393
- z-index: 1;
2394
- padding-top: 50px;
2395
- }
2396
-
2397
- #tile-blur-label {
2398
- display: flex;
2399
- align-items: center;
2400
- column-gap: 5px;
2401
- }
2402
-
2403
- #tile-blur-check {
2404
- margin: 0 5px 0 0;
2405
- width: 15px;
2406
- }
2407
-
2408
- circular-activity-indicator {
2409
- width: 30px;
2410
- height: 30px;
2411
- }
2412
-
2413
- sort-filter-bar {
2414
- display: block;
2415
- margin-bottom: 4rem;
2416
- }
2417
-
2418
- infinite-scroller {
2419
- display: block;
2420
- --infiniteScrollerRowGap: var(--collectionBrowserRowGap, 1.7rem);
2421
- --infiniteScrollerColGap: var(--collectionBrowserColGap, 1.7rem);
2422
- }
2423
-
2424
- infinite-scroller.list-compact {
2425
- --infiniteScrollerCellMinWidth: var(
2426
- --collectionBrowserCellMinWidth,
2427
- 100%
2428
- );
2429
- --infiniteScrollerCellMinHeight: 45px; /* override infinite scroller component */
2430
- --infiniteScrollerCellMaxHeight: 56px;
2431
- --infiniteScrollerRowGap: 10px;
2432
- }
2433
-
2434
- infinite-scroller.list-detail {
2435
- --infiniteScrollerCellMinWidth: var(
2436
- --collectionBrowserCellMinWidth,
2437
- 100%
2438
- );
2439
- --infiniteScrollerCellMinHeight: var(
2440
- --collectionBrowserCellMinHeight,
2441
- 5rem
2442
- );
2443
- /*
2444
- 30px in spec, compensating for a -4px margin
2445
- to align title with top of item image
2446
- src/tiles/list/tile-list.ts
2447
- */
2448
- --infiniteScrollerRowGap: 34px;
2449
- }
2450
-
2451
- .mobile infinite-scroller.list-detail {
2452
- --infiniteScrollerRowGap: 24px;
2453
- }
2454
-
2455
- infinite-scroller.grid {
2456
- --infiniteScrollerCellMinWidth: var(
2457
- --collectionBrowserCellMinWidth,
2458
- 17rem
2459
- );
2460
- --infiniteScrollerCellMaxWidth: var(
2461
- --collectionBrowserCellMaxWidth,
2462
- 1fr
2463
- );
2464
- }
2465
-
2466
- /* Allow tiles to shrink a bit further at smaller viewport widths */
2467
- @media screen and (max-width: 880px) {
2468
- infinite-scroller.grid {
2469
- --infiniteScrollerCellMinWidth: var(
2470
- --collectionBrowserCellMinWidth,
2471
- 15rem
2472
- );
2473
- }
2474
- }
2475
- /* At very small widths, maintain a 2-tile layout as far as it can reasonably go */
2476
- @media screen and (max-width: 360px) {
2477
- infinite-scroller.grid {
2478
- --infiniteScrollerCellMinWidth: var(
2479
- --collectionBrowserCellMinWidth,
2480
- 12rem
2481
- );
2482
- }
2483
- }
2484
-
2485
- infinite-scroller.hidden {
2486
- display: none;
2487
- }
2089
+ css `
2090
+ :host {
2091
+ display: block;
2092
+ --leftColumnWidth: 18rem;
2093
+ --leftColumnPaddingTop: 2rem;
2094
+ --leftColumnPaddingRight: 2.5rem;
2095
+ }
2096
+
2097
+ #facet-top-view {
2098
+ display: flex;
2099
+ }
2100
+
2101
+ /**
2102
+ * When page width resizes from desktop to mobile, use this class to
2103
+ * disable expand/collapse transition when loading.
2104
+ */
2105
+ .preload * {
2106
+ transition: none !important;
2107
+ -webkit-transition: none !important;
2108
+ -moz-transition: none !important;
2109
+ -ms-transition: none !important;
2110
+ -o-transition: none !important;
2111
+ }
2112
+
2113
+ #content-container {
2114
+ display: flex;
2115
+ }
2116
+
2117
+ empty-placeholder {
2118
+ margin-top: var(--placeholderMarginTop, 0);
2119
+ }
2120
+
2121
+ .collapser-icon {
2122
+ display: inline-block;
2123
+ }
2124
+
2125
+ .collapser-icon svg {
2126
+ display: inline-block;
2127
+ width: 12px;
2128
+ height: 12px;
2129
+ transition: transform 0.2s ease-out;
2130
+ }
2131
+
2132
+ #mobile-filter-collapse {
2133
+ width: 100%;
2134
+ }
2135
+
2136
+ #mobile-filter-collapse > summary {
2137
+ cursor: pointer;
2138
+ list-style: none;
2139
+ }
2140
+
2141
+ #mobile-filter-collapse[open] > summary {
2142
+ margin-bottom: 10px;
2143
+ }
2144
+
2145
+ #mobile-filter-collapse h2 {
2146
+ display: inline-block;
2147
+ margin: 0;
2148
+ font-size: 2rem;
2149
+ }
2150
+
2151
+ #mobile-filter-collapse[open] svg {
2152
+ transform: rotate(90deg);
2153
+ }
2154
+
2155
+ #content-container.mobile {
2156
+ display: block;
2157
+ }
2158
+
2159
+ #right-column {
2160
+ flex: 1;
2161
+ position: relative;
2162
+ min-height: 90vh;
2163
+ border-right: 1px solid rgb(232, 232, 232);
2164
+ margin-top: var(--rightColumnMarginTop, 0);
2165
+ padding-top: var(--rightColumnPaddingTop, 2rem);
2166
+ background: #fff;
2167
+ }
2168
+
2169
+ #left-column:not([hidden]) + #right-column {
2170
+ border-left: 1px solid rgb(232, 232, 232);
2171
+ }
2172
+
2173
+ #right-column.smart-results-spacing {
2174
+ padding-top: 0.5rem;
2175
+ border-right: none;
2176
+ background: transparent;
2177
+ min-width: 0;
2178
+ }
2179
+
2180
+ #results {
2181
+ background: #fff;
2182
+ padding-left: 1rem;
2183
+ padding-right: 1rem;
2184
+ }
2185
+
2186
+ #right-column.smart-results-spacing #results {
2187
+ border-radius: 10px 10px 0px 0px;
2188
+ padding-top: 0.5rem;
2189
+ margin-top: 1rem;
2190
+ }
2191
+
2192
+ .mobile #right-column {
2193
+ border-left: none;
2194
+ }
2195
+
2196
+ .mobile #results {
2197
+ padding: 5px 5px 0;
2198
+ }
2199
+
2200
+ #left-column {
2201
+ width: var(--leftColumnWidth, 18rem);
2202
+ /* Prevents Safari from shrinking col at first draw */
2203
+ min-width: var(--leftColumnWidth, 18rem);
2204
+ padding-top: var(--leftColumnPaddingTop, 2rem);
2205
+ /* Reduced padding by 0.2rem to add the invisible border in the rule below */
2206
+ padding-right: calc(var(--leftColumnPaddingRight, 2.5rem) - 0.2rem);
2207
+ border-right: 0.2rem solid transparent; /* Pads to the right of the scrollbar a bit */
2208
+ z-index: 1;
2209
+ }
2210
+
2211
+ .desktop #left-column {
2212
+ top: 0;
2213
+ position: sticky;
2214
+ height: calc(100vh - 2rem);
2215
+ max-height: calc(100vh - 2rem);
2216
+ overflow-x: hidden;
2217
+ overflow-y: scroll;
2218
+
2219
+ /*
2220
+ * Firefox doesn't support any of the -webkit-scrollbar stuff below, but
2221
+ * does at least give us a tiny bit of control over width & color.
2222
+ */
2223
+ scrollbar-width: thin;
2224
+ scrollbar-color: transparent transparent;
2225
+ }
2226
+ .desktop #left-column:hover {
2227
+ scrollbar-color: auto;
2228
+ }
2229
+ .desktop #left-column::-webkit-scrollbar {
2230
+ appearance: none;
2231
+ width: 6px;
2232
+ }
2233
+ .desktop #left-column::-webkit-scrollbar-button {
2234
+ height: 3px;
2235
+ background: transparent;
2236
+ }
2237
+ .desktop #left-column::-webkit-scrollbar-corner {
2238
+ background: transparent;
2239
+ }
2240
+ .desktop #left-column::-webkit-scrollbar-thumb {
2241
+ border-radius: 4px;
2242
+ }
2243
+ .desktop #left-column:hover::-webkit-scrollbar-thumb {
2244
+ background: rgba(0, 0, 0, 0.15);
2245
+ }
2246
+ .desktop #left-column:hover::-webkit-scrollbar-thumb:hover {
2247
+ background: rgba(0, 0, 0, 0.2);
2248
+ }
2249
+ .desktop #left-column:hover::-webkit-scrollbar-thumb:active {
2250
+ background: rgba(0, 0, 0, 0.3);
2251
+ }
2252
+
2253
+ #facets-bottom-fade {
2254
+ background: linear-gradient(
2255
+ to bottom,
2256
+ #fbfbfd00 0%,
2257
+ #fbfbfdc0 50%,
2258
+ #fbfbfd 80%,
2259
+ #fbfbfd 100%
2260
+ );
2261
+ position: fixed;
2262
+ bottom: 0;
2263
+ height: 50px;
2264
+ /* Wide enough to cover the content, but leave the scrollbar uncovered */
2265
+ width: calc(
2266
+ var(--leftColumnWidth) + var(--leftColumnPaddingRight) - 10px
2267
+ );
2268
+ z-index: 2;
2269
+ pointer-events: none;
2270
+ transition: height 0.1s ease;
2271
+ }
2272
+ #facets-bottom-fade.hidden {
2273
+ height: 0;
2274
+ }
2275
+
2276
+ .facets-message {
2277
+ font-size: 1.4rem;
2278
+ }
2279
+
2280
+ .desktop-facets-dropdown > summary {
2281
+ cursor: pointer;
2282
+ list-style: none;
2283
+ }
2284
+
2285
+ .desktop-facets-dropdown h2 {
2286
+ display: inline-block;
2287
+ margin: 0;
2288
+ font-size: 1.6rem;
2289
+ }
2290
+
2291
+ .desktop-facets-dropdown[open] > summary {
2292
+ margin-bottom: 10px;
2293
+ }
2294
+
2295
+ .desktop-facets-dropdown[open] svg {
2296
+ transform: rotate(90deg);
2297
+ }
2298
+
2299
+ .desktop #left-column-scroll-sentinel {
2300
+ width: 1px;
2301
+ height: 100vh;
2302
+ background: transparent;
2303
+ }
2304
+
2305
+ .desktop #facets-scroll-sentinel {
2306
+ width: 1px;
2307
+ height: 1px;
2308
+ background: transparent;
2309
+ }
2310
+
2311
+ #facets-header-container {
2312
+ display: flex;
2313
+ justify-content: space-between;
2314
+ align-items: flex-start;
2315
+ clear: both;
2316
+ }
2317
+
2318
+ .desktop #facets-header-container {
2319
+ flex-wrap: wrap;
2320
+ }
2321
+
2322
+ .mobile #left-column {
2323
+ width: 100%;
2324
+ min-width: 0;
2325
+ padding: 5px 0;
2326
+ border: 0;
2327
+ }
2328
+
2329
+ .clear-filters-btn-row {
2330
+ display: inline-block;
2331
+ }
2332
+
2333
+ .desktop .clear-filters-btn-row {
2334
+ width: 100%;
2335
+ }
2336
+
2337
+ .clear-filters-btn {
2338
+ display: inline-block;
2339
+ appearance: none;
2340
+ margin: 0;
2341
+ padding: 0;
2342
+ border: 0;
2343
+ background: none;
2344
+ color: var(--ia-theme-link-color);
2345
+ font-size: 1.4rem;
2346
+ font-family: inherit;
2347
+ cursor: pointer;
2348
+ }
2349
+
2350
+ .clear-filters-btn:hover {
2351
+ text-decoration: underline;
2352
+ }
2353
+
2354
+ .clear-filters-btn-separator {
2355
+ display: inline-block;
2356
+ margin-left: 5px;
2357
+ border-left: 1px solid #2c2c2c;
2358
+ font-size: 1.4rem;
2359
+ line-height: 1.3rem;
2360
+ }
2361
+
2362
+ #tv-filters {
2363
+ margin-bottom: 15px;
2364
+ }
2365
+
2366
+ #tv-shows {
2367
+ --comboBoxListWidth: 300px;
2368
+ }
2369
+
2370
+ .tv-filter-dropdown {
2371
+ display: block;
2372
+ font-size: 14px;
2373
+ margin-left: 1px;
2374
+ margin-bottom: 5px;
2375
+ }
2376
+
2377
+ .tv-filter-dropdown::part(combo-box) {
2378
+ outline-offset: 1px;
2379
+ }
2380
+
2381
+ .tv-filter-dropdown::part(option) {
2382
+ line-height: 1.1;
2383
+ padding: 7px;
2384
+ }
2385
+
2386
+ .tv-filter-dropdown::part(clear-button) {
2387
+ flex: 0 0 26px;
2388
+ --combo-box-clear-icon-size: 14px;
2389
+ }
2390
+
2391
+ .tv-filter-dropdown::part(icon) {
2392
+ width: 1.4rem;
2393
+ height: 1.4rem;
2394
+ }
2395
+
2396
+ #facets-container {
2397
+ position: relative;
2398
+ max-height: 0;
2399
+ transition: max-height 0.2s ease-in-out;
2400
+ z-index: 1;
2401
+ margin-top: var(--facetsContainerMarginTop, 3rem);
2402
+ padding-bottom: 2rem;
2403
+ }
2404
+
2405
+ .desktop #facets-container {
2406
+ width: 18rem;
2407
+ }
2408
+
2409
+ .mobile #facets-container {
2410
+ overflow: hidden;
2411
+ padding-bottom: 0;
2412
+ padding-left: 10px;
2413
+ padding-right: 10px;
2414
+ }
2415
+
2416
+ #facets-container.expanded {
2417
+ max-height: 2000px;
2418
+ }
2419
+
2420
+ .results-section-heading {
2421
+ margin: 0.5rem 0.3rem;
2422
+ font-size: 2rem;
2423
+ line-height: 25px;
2424
+ }
2425
+
2426
+ #results-total {
2427
+ display: flex;
2428
+ align-items: baseline;
2429
+ }
2430
+
2431
+ #results-total:not(.filtered) {
2432
+ padding-bottom: 2rem;
2433
+ }
2434
+
2435
+ .mobile #results-total {
2436
+ position: absolute;
2437
+ right: 10px;
2438
+ }
2439
+
2440
+ #big-results-count {
2441
+ font-size: 2.4rem;
2442
+ font-weight: 500;
2443
+ margin-right: 5px;
2444
+ }
2445
+
2446
+ .mobile #big-results-count {
2447
+ font-size: 2rem;
2448
+ }
2449
+
2450
+ #big-results-label {
2451
+ font-size: 1.4rem;
2452
+ font-weight: 200;
2453
+ }
2454
+
2455
+ #list-header {
2456
+ max-height: 4.2rem;
2457
+ }
2458
+
2459
+ .loading-cover {
2460
+ position: absolute;
2461
+ top: 0;
2462
+ left: 0;
2463
+ width: 100%;
2464
+ height: 100%;
2465
+ display: flex;
2466
+ justify-content: center;
2467
+ z-index: 1;
2468
+ padding-top: 50px;
2469
+ }
2470
+
2471
+ #tile-blur-label {
2472
+ display: flex;
2473
+ align-items: center;
2474
+ column-gap: 5px;
2475
+ }
2476
+
2477
+ #tile-blur-check {
2478
+ margin: 0 5px 0 0;
2479
+ width: 15px;
2480
+ }
2481
+
2482
+ circular-activity-indicator {
2483
+ width: 30px;
2484
+ height: 30px;
2485
+ }
2486
+
2487
+ sort-filter-bar {
2488
+ display: block;
2489
+ margin-bottom: 4rem;
2490
+ }
2491
+
2492
+ infinite-scroller {
2493
+ display: block;
2494
+ --infiniteScrollerRowGap: var(--collectionBrowserRowGap, 1.7rem);
2495
+ --infiniteScrollerColGap: var(--collectionBrowserColGap, 1.7rem);
2496
+ }
2497
+
2498
+ infinite-scroller.list-compact {
2499
+ --infiniteScrollerCellMinWidth: var(
2500
+ --collectionBrowserCellMinWidth,
2501
+ 100%
2502
+ );
2503
+ --infiniteScrollerCellMinHeight: 45px; /* override infinite scroller component */
2504
+ --infiniteScrollerCellMaxHeight: 56px;
2505
+ --infiniteScrollerRowGap: 10px;
2506
+ }
2507
+
2508
+ infinite-scroller.list-detail {
2509
+ --infiniteScrollerCellMinWidth: var(
2510
+ --collectionBrowserCellMinWidth,
2511
+ 100%
2512
+ );
2513
+ --infiniteScrollerCellMinHeight: var(
2514
+ --collectionBrowserCellMinHeight,
2515
+ 5rem
2516
+ );
2517
+ /*
2518
+ 30px in spec, compensating for a -4px margin
2519
+ to align title with top of item image
2520
+ src/tiles/list/tile-list.ts
2521
+ */
2522
+ --infiniteScrollerRowGap: 34px;
2523
+ }
2524
+
2525
+ .mobile infinite-scroller.list-detail {
2526
+ --infiniteScrollerRowGap: 24px;
2527
+ }
2528
+
2529
+ infinite-scroller.grid {
2530
+ --infiniteScrollerCellMinWidth: var(
2531
+ --collectionBrowserCellMinWidth,
2532
+ 17rem
2533
+ );
2534
+ --infiniteScrollerCellMaxWidth: var(
2535
+ --collectionBrowserCellMaxWidth,
2536
+ 1fr
2537
+ );
2538
+ }
2539
+
2540
+ /* Allow tiles to shrink a bit further at smaller viewport widths */
2541
+ @media screen and (max-width: 880px) {
2542
+ infinite-scroller.grid {
2543
+ --infiniteScrollerCellMinWidth: var(
2544
+ --collectionBrowserCellMinWidth,
2545
+ 15rem
2546
+ );
2547
+ }
2548
+ }
2549
+ /* At very small widths, maintain a 2-tile layout as far as it can reasonably go */
2550
+ @media screen and (max-width: 360px) {
2551
+ infinite-scroller.grid {
2552
+ --infiniteScrollerCellMinWidth: var(
2553
+ --collectionBrowserCellMinWidth,
2554
+ 12rem
2555
+ );
2556
+ }
2557
+ }
2558
+
2559
+ infinite-scroller.hidden {
2560
+ display: none;
2561
+ }
2488
2562
  `,
2489
2563
  ];
2490
2564
  }
@@ -2717,7 +2791,7 @@ __decorate([
2717
2791
  __decorate([
2718
2792
  query('infinite-scroller')
2719
2793
  ], CollectionBrowser.prototype, "infiniteScroller", void 0);
2720
- CollectionBrowser = __decorate([
2794
+ CollectionBrowser = CollectionBrowser_1 = __decorate([
2721
2795
  customElement('collection-browser')
2722
2796
  ], CollectionBrowser);
2723
2797
  export { CollectionBrowser };