@internetarchive/collection-browser 4.3.1-alpha-webdev8257.0 → 4.3.2-alpha-webdev7939.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/index.d.ts +0 -1
  2. package/dist/index.js.map +1 -1
  3. package/dist/src/app-root.d.ts +0 -8
  4. package/dist/src/app-root.js +672 -698
  5. package/dist/src/app-root.js.map +1 -1
  6. package/dist/src/collection-browser.d.ts +8 -8
  7. package/dist/src/collection-browser.js +44 -36
  8. package/dist/src/collection-browser.js.map +1 -1
  9. package/dist/src/tiles/base-tile-component.d.ts +1 -17
  10. package/dist/src/tiles/base-tile-component.js +1 -48
  11. package/dist/src/tiles/base-tile-component.js.map +1 -1
  12. package/dist/src/tiles/grid/item-tile.js +138 -139
  13. package/dist/src/tiles/grid/item-tile.js.map +1 -1
  14. package/dist/src/tiles/list/tile-list-compact-header.js +46 -66
  15. package/dist/src/tiles/list/tile-list-compact-header.js.map +1 -1
  16. package/dist/src/tiles/list/tile-list-compact.d.ts +1 -1
  17. package/dist/src/tiles/list/tile-list-compact.js +100 -132
  18. package/dist/src/tiles/list/tile-list-compact.js.map +1 -1
  19. package/dist/src/tiles/list/tile-list.d.ts +1 -1
  20. package/dist/src/tiles/list/tile-list.js +298 -316
  21. package/dist/src/tiles/list/tile-list.js.map +1 -1
  22. package/dist/src/tiles/models.d.ts +0 -14
  23. package/dist/src/tiles/models.js.map +1 -1
  24. package/dist/src/tiles/tile-dispatcher.d.ts +0 -14
  25. package/dist/src/tiles/tile-dispatcher.js +216 -319
  26. package/dist/src/tiles/tile-dispatcher.js.map +1 -1
  27. package/index.ts +28 -29
  28. package/package.json +3 -3
  29. package/src/app-root.ts +1251 -1281
  30. package/src/collection-browser.ts +48 -33
  31. package/src/tiles/base-tile-component.ts +65 -121
  32. package/src/tiles/grid/item-tile.ts +346 -347
  33. package/src/tiles/list/tile-list-compact-header.ts +86 -106
  34. package/src/tiles/list/tile-list-compact.ts +239 -273
  35. package/src/tiles/list/tile-list.ts +700 -718
  36. package/src/tiles/models.ts +8 -24
  37. package/src/tiles/tile-dispatcher.ts +527 -637
  38. package/dist/src/styles/tile-action-styles.d.ts +0 -14
  39. package/dist/src/styles/tile-action-styles.js +0 -52
  40. package/dist/src/styles/tile-action-styles.js.map +0 -1
  41. package/src/styles/tile-action-styles.ts +0 -52
@@ -78,7 +78,6 @@ import { sha1 } from './utils/sha1';
78
78
  import type { PlaceholderType } from './empty-placeholder';
79
79
  import type { ManageBar } from './manage/manage-bar';
80
80
  import type { SmartFacetBar } from './collection-facets/smart-facets/smart-facet-bar';
81
- import type { LayoutType, TileAction } from './tiles/models';
82
81
 
83
82
  import '@internetarchive/elements/ia-combo-box/ia-combo-box';
84
83
  import './empty-placeholder';
@@ -298,15 +297,6 @@ export class CollectionBrowser
298
297
  */
299
298
  @property({ type: Boolean }) isManageView = false;
300
299
 
301
- /** Action buttons to display on each tile */
302
- @property({ type: Array }) tileActions: TileAction[] = [];
303
-
304
- /**
305
- * The simplified layout to apply to grid-mode tiles, if any. See
306
- * `LayoutType` for available options. Has no effect on list display modes.
307
- */
308
- @property({ type: String }) tileLayoutType: LayoutType = 'default';
309
-
310
300
  @property({ type: String }) manageViewLabel = 'Select items to remove';
311
301
 
312
302
  /** Whether to replace the default sort options with a slot for customization (default: false) */
@@ -876,6 +866,7 @@ export class CollectionBrowser
876
866
  class=${this.infiniteScrollerClasses}
877
867
  itemCount=${this.placeholderType ? 0 : nothing}
878
868
  ariaLandmarkLabel="Search results"
869
+ .estimatedCellHeight=${this.estimatedTileHeight}
879
870
  .cellProvider=${this}
880
871
  .placeholderCellTemplate=${this.placeholderCellTemplate}
881
872
  @scrollThresholdReached=${this.scrollThresholdReached}
@@ -897,6 +888,25 @@ export class CollectionBrowser
897
888
  });
898
889
  }
899
890
 
891
+ /**
892
+ * Best-effort hint of how tall a single rendered tile is, by display mode.
893
+ * The scroller uses this to better estimate the size its initial scroll
894
+ * spacer and buffer position before real cell heights are measured.
895
+ * Should roughly match the placeholder heights since the initial render
896
+ * of a new page generally shows placeholders only anyway.
897
+ */
898
+ private get estimatedTileHeight(): number {
899
+ switch (this.displayMode) {
900
+ case 'list-detail':
901
+ return 80;
902
+ case 'list-compact':
903
+ return 45;
904
+ case 'grid':
905
+ default:
906
+ return 225;
907
+ }
908
+ }
909
+
900
910
  /**
901
911
  * Template for the sort & filtering bar that appears atop the search results.
902
912
  */
@@ -1591,7 +1601,6 @@ export class CollectionBrowser
1591
1601
  .mobileBreakpoint=${this.mobileBreakpoint}
1592
1602
  .loggedIn=${this.loggedIn}
1593
1603
  .suppressBlurring=${this.shouldSuppressTileBlurring}
1594
- .tileActions=${this.tileActions}
1595
1604
  >
1596
1605
  </tile-dispatcher>
1597
1606
  </div>
@@ -1741,8 +1750,7 @@ export class CollectionBrowser
1741
1750
  changed.has('displayMode') ||
1742
1751
  changed.has('baseNavigationUrl') ||
1743
1752
  changed.has('baseImageUrl') ||
1744
- changed.has('loggedIn') ||
1745
- changed.has('tileActions')
1753
+ changed.has('loggedIn')
1746
1754
  ) {
1747
1755
  this.infiniteScroller?.reload();
1748
1756
  }
@@ -2335,25 +2343,34 @@ export class CollectionBrowser
2335
2343
  });
2336
2344
  }
2337
2345
 
2338
- private scrollToPage(pageNumber: number): Promise<void> {
2339
- return new Promise(resolve => {
2340
- const cellIndexToScrollTo = this.pageSize * (pageNumber - 1);
2341
- // without this setTimeout, Safari just pauses until the `fetchPage` is complete
2342
- // then scrolls to the cell
2343
- setTimeout(() => {
2344
- this.isScrollingToCell = true;
2345
- this.infiniteScroller?.scrollToCell(cellIndexToScrollTo, true);
2346
- // This timeout is to give the scroll animation time to finish
2347
- // then updating the infinite scroller once we're done scrolling
2348
- // There's no scroll animation completion callback so we're
2349
- // giving it 0.5s to finish.
2350
- setTimeout(() => {
2351
- this.isScrollingToCell = false;
2352
- this.infiniteScroller?.refreshAllVisibleCells();
2353
- resolve();
2354
- }, 500);
2355
- }, 0);
2346
+ private async scrollToPage(pageNumber: number): Promise<void> {
2347
+ const cellIndexToScrollTo = this.pageSize * (pageNumber - 1);
2348
+
2349
+ // Wait for the infinite scroller be rendered before proceeding
2350
+ let waitAttempts = 0;
2351
+ while (!this.infiniteScroller && waitAttempts < 20) {
2352
+ await this.updateComplete;
2353
+ waitAttempts++;
2354
+ }
2355
+ if (!this.infiniteScroller) return;
2356
+
2357
+ // The scroller have its default `itemCount=0`, so propagate our estimated
2358
+ // tile count before jumping to the desired page.
2359
+ if (this.infiniteScroller.itemCount < this.estimatedTileCount) {
2360
+ this.infiniteScroller.itemCount = this.estimatedTileCount;
2361
+ await this.updateComplete;
2362
+ }
2363
+
2364
+ // Without this setTimeout(0), Safari just pauses until the `fetchPage`
2365
+ // is complete then scrolls to the cell.
2366
+ await new Promise<void>(resolve => {
2367
+ setTimeout(resolve, 0);
2356
2368
  });
2369
+
2370
+ this.isScrollingToCell = true;
2371
+ await this.infiniteScroller.scrollToCell(cellIndexToScrollTo, true);
2372
+ this.isScrollingToCell = false;
2373
+ this.infiniteScroller.refreshAllVisibleCells();
2357
2374
  }
2358
2375
 
2359
2376
  /**
@@ -2535,8 +2552,6 @@ export class CollectionBrowser
2535
2552
  .loggedIn=${this.loggedIn}
2536
2553
  .suppressBlurring=${this.shouldSuppressTileBlurring}
2537
2554
  .isManageView=${this.isManageView}
2538
- .tileActions=${this.tileActions}
2539
- .layoutType=${this.tileLayoutType}
2540
2555
  ?showTvClips=${isTVSearch || isTVCollection}
2541
2556
  ?enableHoverPane=${true}
2542
2557
  ?useLocalTime=${shouldUseLocalTime}
@@ -1,121 +1,65 @@
1
- import { html, LitElement, nothing, PropertyValues, TemplateResult } from 'lit';
2
- import { property } from 'lit/decorators.js';
3
- import type { SortParam } from '@internetarchive/search-service';
4
- import { TileDisplayValueProvider } from './tile-display-value-provider';
5
- import type { TileModel } from '../models';
6
- import { DateFormat, formatDate } from '../utils/format-date';
7
- import type { TileAction } from './models';
8
-
9
- export abstract class BaseTileComponent extends LitElement {
10
- @property({ type: Object }) model?: TileModel;
11
-
12
- /** Action buttons to display on this tile (rendered by subclasses) */
13
- @property({ type: Array }) tileActions: TileAction[] = [];
14
-
15
- @property({ type: Number }) currentWidth?: number;
16
-
17
- @property({ type: Number }) currentHeight?: number;
18
-
19
- @property({ type: String }) baseNavigationUrl?: string;
20
-
21
- @property({ type: String }) baseImageUrl?: string;
22
-
23
- @property({ type: String }) collectionPagePath?: string;
24
-
25
- @property({ type: Object }) sortParam: SortParam | null = null;
26
-
27
- @property({ type: Object }) defaultSortParam: SortParam | null = null;
28
-
29
- @property({ type: String }) creatorFilter?: string;
30
-
31
- @property({ type: Number }) mobileBreakpoint?: number;
32
-
33
- @property({ type: Boolean }) loggedIn = false;
34
-
35
- @property({ type: Boolean }) suppressBlurring = false;
36
-
37
- @property({ type: Boolean }) useLocalTime = false;
38
-
39
- protected displayValueProvider = new TileDisplayValueProvider();
40
-
41
- protected willUpdate(changed: PropertyValues<this>) {
42
- // Ensure the TileDisplayValueProvider stays up-to-date as properties change
43
- if (
44
- changed.has('model') ||
45
- changed.has('baseNavigationUrl') ||
46
- changed.has('collectionPagePath') ||
47
- changed.has('sortParam') ||
48
- changed.has('defaultSortParam') ||
49
- changed.has('creatorFilter')
50
- ) {
51
- this.displayValueProvider = new TileDisplayValueProvider({
52
- model: this.model,
53
- baseNavigationUrl: this.baseNavigationUrl,
54
- collectionPagePath: this.collectionPagePath,
55
- sortParam: this.sortParam ?? this.defaultSortParam ?? undefined,
56
- creatorFilter: this.creatorFilter,
57
- });
58
- }
59
- }
60
-
61
- /**
62
- * The formatted date string for given date and format type, taking into
63
- * account whether this tile component should be using local time or UTC.
64
- */
65
- protected getFormattedDate(date?: Date, format?: DateFormat): string {
66
- const { useLocalTime } = this;
67
- return formatDate(date, format, { useLocalTime });
68
- }
69
-
70
- /**
71
- * Renders the action buttons configured for this tile, or `nothing` if
72
- * there are none. Optional `extraClass` is appended to the container's
73
- * class list so subclasses can target their own layout tweaks.
74
- */
75
- protected renderTileActions(
76
- extraClass: string = '',
77
- ): TemplateResult | typeof nothing {
78
- if (!this.tileActions.length) return nothing;
79
-
80
- const containerClass = extraClass
81
- ? `tile-actions ${extraClass}`
82
- : 'tile-actions';
83
- return html`
84
- <div class=${containerClass}>
85
- ${this.tileActions.map(
86
- action => html`
87
- <button
88
- class="tile-action-btn"
89
- @click=${(e: Event) => this.handleTileActionClick(e, action)}
90
- >
91
- ${action.label}
92
- </button>
93
- `,
94
- )}
95
- </div>
96
- `;
97
- }
98
-
99
- /**
100
- * Click handler for tile action buttons. Stops propagation so the click
101
- * doesn't activate a wrapping tile link, and dispatches a
102
- * `tileActionClicked` event (bubbling + composed) carrying the action ID
103
- * and the tile model.
104
- */
105
- protected handleTileActionClick(e: Event, action: TileAction): void {
106
- e.preventDefault();
107
- e.stopPropagation();
108
- // Pre-set the hover pane controller's clicking flag so that focus
109
- // restoration after a consumer-opened modal won't trigger the hover pane.
110
- this.dispatchEvent(
111
- new PointerEvent('pointerdown', { bubbles: true, composed: true }),
112
- );
113
- this.dispatchEvent(
114
- new CustomEvent('tileActionClicked', {
115
- detail: { actionId: action.id, model: this.model },
116
- bubbles: true,
117
- composed: true,
118
- }),
119
- );
120
- }
121
- }
1
+ import { LitElement, PropertyValues } from 'lit';
2
+ import { property } from 'lit/decorators.js';
3
+ import type { SortParam } from '@internetarchive/search-service';
4
+ import { TileDisplayValueProvider } from './tile-display-value-provider';
5
+ import type { TileModel } from '../models';
6
+ import { DateFormat, formatDate } from '../utils/format-date';
7
+
8
+ export abstract class BaseTileComponent extends LitElement {
9
+ @property({ type: Object }) model?: TileModel;
10
+
11
+ @property({ type: Number }) currentWidth?: number;
12
+
13
+ @property({ type: Number }) currentHeight?: number;
14
+
15
+ @property({ type: String }) baseNavigationUrl?: string;
16
+
17
+ @property({ type: String }) baseImageUrl?: string;
18
+
19
+ @property({ type: String }) collectionPagePath?: string;
20
+
21
+ @property({ type: Object }) sortParam: SortParam | null = null;
22
+
23
+ @property({ type: Object }) defaultSortParam: SortParam | null = null;
24
+
25
+ @property({ type: String }) creatorFilter?: string;
26
+
27
+ @property({ type: Number }) mobileBreakpoint?: number;
28
+
29
+ @property({ type: Boolean }) loggedIn = false;
30
+
31
+ @property({ type: Boolean }) suppressBlurring = false;
32
+
33
+ @property({ type: Boolean }) useLocalTime = false;
34
+
35
+ protected displayValueProvider = new TileDisplayValueProvider();
36
+
37
+ protected willUpdate(changed: PropertyValues<this>) {
38
+ // Ensure the TileDisplayValueProvider stays up-to-date as properties change
39
+ if (
40
+ changed.has('model') ||
41
+ changed.has('baseNavigationUrl') ||
42
+ changed.has('collectionPagePath') ||
43
+ changed.has('sortParam') ||
44
+ changed.has('defaultSortParam') ||
45
+ changed.has('creatorFilter')
46
+ ) {
47
+ this.displayValueProvider = new TileDisplayValueProvider({
48
+ model: this.model,
49
+ baseNavigationUrl: this.baseNavigationUrl,
50
+ collectionPagePath: this.collectionPagePath,
51
+ sortParam: this.sortParam ?? this.defaultSortParam ?? undefined,
52
+ creatorFilter: this.creatorFilter,
53
+ });
54
+ }
55
+ }
56
+
57
+ /**
58
+ * The formatted date string for given date and format type, taking into
59
+ * account whether this tile component should be using local time or UTC.
60
+ */
61
+ protected getFormattedDate(date?: Date, format?: DateFormat): string {
62
+ const { useLocalTime } = this;
63
+ return formatDate(date, format, { useLocalTime });
64
+ }
65
+ }