@internetarchive/collection-browser 0.4.9-alpha.1 → 0.4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +29 -29
- package/.github/workflows/ci.yml +26 -26
- package/.github/workflows/gh-pages-main.yml +39 -39
- package/.github/workflows/npm-publish.yml +39 -39
- package/.github/workflows/pr-preview.yml +38 -38
- package/.husky/pre-commit +4 -4
- package/LICENSE +661 -661
- package/README.md +83 -83
- package/dist/index.d.ts +9 -9
- package/dist/index.js +9 -9
- package/dist/src/app-root.d.ts +50 -50
- package/dist/src/app-root.js +278 -278
- package/dist/src/assets/img/icons/arrow-left.d.ts +2 -2
- package/dist/src/assets/img/icons/arrow-left.js +2 -2
- package/dist/src/assets/img/icons/arrow-right.d.ts +2 -2
- package/dist/src/assets/img/icons/arrow-right.js +2 -2
- package/dist/src/assets/img/icons/chevron.d.ts +2 -2
- package/dist/src/assets/img/icons/chevron.js +2 -2
- package/dist/src/assets/img/icons/empty-query.d.ts +2 -2
- package/dist/src/assets/img/icons/empty-query.js +2 -2
- package/dist/src/assets/img/icons/eye-closed.d.ts +2 -2
- package/dist/src/assets/img/icons/eye-closed.js +2 -2
- package/dist/src/assets/img/icons/eye.d.ts +2 -2
- package/dist/src/assets/img/icons/eye.js +2 -2
- package/dist/src/assets/img/icons/favorite-filled.d.ts +1 -1
- package/dist/src/assets/img/icons/favorite-filled.js +2 -2
- package/dist/src/assets/img/icons/login-required.d.ts +1 -1
- package/dist/src/assets/img/icons/login-required.js +2 -2
- package/dist/src/assets/img/icons/mediatype/account.d.ts +1 -1
- package/dist/src/assets/img/icons/mediatype/account.js +2 -2
- package/dist/src/assets/img/icons/mediatype/audio.d.ts +1 -1
- package/dist/src/assets/img/icons/mediatype/audio.js +2 -2
- package/dist/src/assets/img/icons/mediatype/collection.d.ts +1 -1
- package/dist/src/assets/img/icons/mediatype/collection.js +2 -2
- package/dist/src/assets/img/icons/mediatype/data.d.ts +1 -1
- package/dist/src/assets/img/icons/mediatype/data.js +2 -2
- package/dist/src/assets/img/icons/mediatype/etree.d.ts +1 -1
- package/dist/src/assets/img/icons/mediatype/etree.js +2 -2
- package/dist/src/assets/img/icons/mediatype/film.d.ts +1 -1
- package/dist/src/assets/img/icons/mediatype/film.js +2 -2
- package/dist/src/assets/img/icons/mediatype/images.d.ts +1 -1
- package/dist/src/assets/img/icons/mediatype/images.js +2 -2
- package/dist/src/assets/img/icons/mediatype/radio.d.ts +1 -1
- package/dist/src/assets/img/icons/mediatype/radio.js +2 -2
- package/dist/src/assets/img/icons/mediatype/software.d.ts +1 -1
- package/dist/src/assets/img/icons/mediatype/software.js +2 -2
- package/dist/src/assets/img/icons/mediatype/texts.d.ts +1 -1
- package/dist/src/assets/img/icons/mediatype/texts.js +2 -2
- package/dist/src/assets/img/icons/mediatype/tv.d.ts +1 -1
- package/dist/src/assets/img/icons/mediatype/tv.js +2 -2
- package/dist/src/assets/img/icons/mediatype/video.d.ts +1 -1
- package/dist/src/assets/img/icons/mediatype/video.js +2 -2
- package/dist/src/assets/img/icons/mediatype/web.d.ts +1 -1
- package/dist/src/assets/img/icons/mediatype/web.js +2 -2
- package/dist/src/assets/img/icons/null-result.d.ts +2 -2
- package/dist/src/assets/img/icons/null-result.js +2 -2
- package/dist/src/assets/img/icons/restricted.d.ts +1 -1
- package/dist/src/assets/img/icons/restricted.js +2 -2
- package/dist/src/assets/img/icons/reviews.d.ts +1 -1
- package/dist/src/assets/img/icons/reviews.js +2 -2
- package/dist/src/assets/img/icons/upload.d.ts +1 -1
- package/dist/src/assets/img/icons/upload.js +2 -2
- package/dist/src/assets/img/icons/views.d.ts +1 -1
- package/dist/src/assets/img/icons/views.js +2 -2
- package/dist/src/circular-activity-indicator.d.ts +5 -5
- package/dist/src/circular-activity-indicator.js +17 -17
- package/dist/src/collection-browser.d.ts +281 -281
- package/dist/src/collection-browser.js +1204 -1200
- package/dist/src/collection-browser.js.map +1 -1
- package/dist/src/collection-facets/facet-tombstone-row.d.ts +5 -5
- package/dist/src/collection-facets/facet-tombstone-row.js +15 -15
- package/dist/src/collection-facets/facets-template.d.ts +16 -16
- package/dist/src/collection-facets/facets-template.js +125 -125
- package/dist/src/collection-facets/more-facets-content.d.ts +77 -77
- package/dist/src/collection-facets/more-facets-content.js +357 -357
- package/dist/src/collection-facets/more-facets-pagination.d.ts +36 -36
- package/dist/src/collection-facets/more-facets-pagination.js +192 -192
- package/dist/src/collection-facets.d.ts +83 -83
- package/dist/src/collection-facets.js +392 -392
- package/dist/src/collection-facets.js.map +1 -1
- package/dist/src/empty-placeholder.d.ts +11 -11
- package/dist/src/empty-placeholder.js +42 -42
- package/dist/src/language-code-handler/language-code-handler.d.ts +37 -37
- package/dist/src/language-code-handler/language-code-handler.js +26 -26
- package/dist/src/language-code-handler/language-code-mapping.d.ts +1 -1
- package/dist/src/language-code-handler/language-code-mapping.js +562 -562
- package/dist/src/mediatype/mediatype-config.d.ts +3 -3
- package/dist/src/mediatype/mediatype-config.js +85 -85
- package/dist/src/models.d.ts +115 -114
- package/dist/src/models.js +125 -125
- package/dist/src/models.js.map +1 -1
- package/dist/src/restoration-state-handler.d.ts +45 -45
- package/dist/src/restoration-state-handler.js +230 -230
- package/dist/src/sort-filter-bar/alpha-bar-tooltip.d.ts +6 -0
- package/dist/src/sort-filter-bar/alpha-bar-tooltip.js +61 -0
- package/dist/src/sort-filter-bar/alpha-bar-tooltip.js.map +1 -0
- package/dist/src/sort-filter-bar/alpha-bar.d.ts +20 -12
- package/dist/src/sort-filter-bar/alpha-bar.js +166 -58
- package/dist/src/sort-filter-bar/alpha-bar.js.map +1 -1
- package/dist/src/sort-filter-bar/img/compact.d.ts +1 -1
- package/dist/src/sort-filter-bar/img/compact.js +2 -2
- package/dist/src/sort-filter-bar/img/list.d.ts +1 -1
- package/dist/src/sort-filter-bar/img/list.js +2 -2
- package/dist/src/sort-filter-bar/img/sort-triangle.d.ts +1 -1
- package/dist/src/sort-filter-bar/img/sort-triangle.js +2 -2
- package/dist/src/sort-filter-bar/img/tile.d.ts +1 -1
- package/dist/src/sort-filter-bar/img/tile.js +2 -2
- package/dist/src/sort-filter-bar/sort-filter-bar.d.ts +108 -108
- package/dist/src/sort-filter-bar/sort-filter-bar.js +438 -438
- package/dist/src/styles/item-image-styles.d.ts +8 -8
- package/dist/src/styles/item-image-styles.js +9 -9
- package/dist/src/tiles/collection-browser-loading-tile.d.ts +5 -5
- package/dist/src/tiles/collection-browser-loading-tile.js +15 -15
- package/dist/src/tiles/grid/account-tile.d.ts +20 -17
- package/dist/src/tiles/grid/account-tile.js +68 -46
- package/dist/src/tiles/grid/account-tile.js.map +1 -1
- package/dist/src/tiles/grid/collection-tile.d.ts +17 -14
- package/dist/src/tiles/grid/collection-tile.js +75 -53
- package/dist/src/tiles/grid/collection-tile.js.map +1 -1
- package/dist/src/tiles/grid/item-tile.d.ts +32 -29
- package/dist/src/tiles/grid/item-tile.js +126 -108
- package/dist/src/tiles/grid/item-tile.js.map +1 -1
- package/dist/src/tiles/grid/styles/tile-grid-shared-styles.d.ts +1 -1
- package/dist/src/tiles/grid/styles/tile-grid-shared-styles.js +44 -8
- package/dist/src/tiles/grid/styles/tile-grid-shared-styles.js.map +1 -1
- package/dist/src/tiles/grid/tile-stats.d.ts +10 -10
- package/dist/src/tiles/grid/tile-stats.js +40 -40
- package/dist/src/tiles/hover/hover-pane-controller.d.ts +219 -197
- package/dist/src/tiles/hover/hover-pane-controller.js +352 -331
- package/dist/src/tiles/hover/hover-pane-controller.js.map +1 -1
- package/dist/src/tiles/hover/tile-hover-pane.d.ts +15 -15
- package/dist/src/tiles/hover/tile-hover-pane.js +38 -38
- package/dist/src/tiles/image-block.d.ts +17 -17
- package/dist/src/tiles/image-block.js +72 -72
- package/dist/src/tiles/item-image.d.ts +35 -35
- package/dist/src/tiles/item-image.js +117 -117
- package/dist/src/tiles/list/account-label.d.ts +1 -1
- package/dist/src/tiles/list/account-label.js +6 -6
- package/dist/src/tiles/list/date-label.d.ts +1 -1
- package/dist/src/tiles/list/date-label.js +12 -12
- package/dist/src/tiles/list/tile-list-compact-header.d.ts +12 -12
- package/dist/src/tiles/list/tile-list-compact-header.js +41 -41
- package/dist/src/tiles/list/tile-list-compact.d.ts +21 -21
- package/dist/src/tiles/list/tile-list-compact.js +99 -99
- package/dist/src/tiles/list/tile-list.d.ts +55 -55
- package/dist/src/tiles/list/tile-list.js +303 -297
- package/dist/src/tiles/list/tile-list.js.map +1 -1
- package/dist/src/tiles/mediatype-icon.d.ts +9 -9
- package/dist/src/tiles/mediatype-icon.js +47 -47
- package/dist/src/tiles/overlay/icon-overlay.d.ts +10 -10
- package/dist/src/tiles/overlay/icon-overlay.js +40 -40
- package/dist/src/tiles/overlay/icon-text-overlay.d.ts +9 -9
- package/dist/src/tiles/overlay/icon-text-overlay.js +38 -38
- package/dist/src/tiles/overlay/text-overlay.d.ts +10 -10
- package/dist/src/tiles/overlay/text-overlay.js +42 -42
- package/dist/src/tiles/text-snippet-block.d.ts +27 -27
- package/dist/src/tiles/text-snippet-block.js +73 -73
- package/dist/src/tiles/tile-dispatcher.d.ts +58 -55
- package/dist/src/tiles/tile-dispatcher.js +203 -179
- package/dist/src/tiles/tile-dispatcher.js.map +1 -1
- package/dist/src/utils/analytics-events.d.ts +22 -22
- package/dist/src/utils/analytics-events.js +24 -24
- package/dist/src/utils/format-count.d.ts +7 -7
- package/dist/src/utils/format-count.js +76 -76
- package/dist/src/utils/format-date.d.ts +2 -2
- package/dist/src/utils/format-date.js +23 -23
- package/dist/src/utils/format-unit-size.d.ts +2 -2
- package/dist/src/utils/format-unit-size.js +33 -33
- package/dist/test/collection-browser.test.d.ts +1 -1
- package/dist/test/collection-browser.test.js +584 -584
- package/dist/test/collection-facets/facets-template.test.d.ts +1 -1
- package/dist/test/collection-facets/facets-template.test.js +62 -62
- package/dist/test/collection-facets/more-facets-content.test.d.ts +1 -1
- package/dist/test/collection-facets/more-facets-content.test.js +114 -114
- package/dist/test/collection-facets/more-facets-pagination.test.d.ts +1 -1
- package/dist/test/collection-facets/more-facets-pagination.test.js +117 -117
- package/dist/test/collection-facets.test.d.ts +2 -2
- package/dist/test/collection-facets.test.js +508 -508
- package/dist/test/empty-placeholder.test.d.ts +1 -1
- package/dist/test/empty-placeholder.test.js +33 -33
- package/dist/test/icon-overlay.test.d.ts +1 -1
- package/dist/test/icon-overlay.test.js +24 -24
- package/dist/test/image-block.test.d.ts +1 -1
- package/dist/test/image-block.test.js +48 -48
- package/dist/test/item-image.test.d.ts +1 -1
- package/dist/test/item-image.test.js +84 -84
- package/dist/test/mediatype-config.test.d.ts +1 -1
- package/dist/test/mediatype-config.test.js +16 -16
- package/dist/test/mocks/mock-analytics-handler.d.ts +10 -10
- package/dist/test/mocks/mock-analytics-handler.js +15 -15
- package/dist/test/mocks/mock-collection-name-cache.d.ts +7 -7
- package/dist/test/mocks/mock-collection-name-cache.js +13 -13
- package/dist/test/mocks/mock-search-responses.d.ts +12 -12
- package/dist/test/mocks/mock-search-responses.js +341 -341
- package/dist/test/mocks/mock-search-service.d.ts +13 -13
- package/dist/test/mocks/mock-search-service.js +40 -40
- package/dist/test/restoration-state-handler.test.d.ts +1 -1
- package/dist/test/restoration-state-handler.test.js +125 -125
- package/dist/test/sort-filter-bar/alpha-bar-tooltip.test.d.ts +1 -0
- package/dist/test/sort-filter-bar/alpha-bar-tooltip.test.js +13 -0
- package/dist/test/sort-filter-bar/alpha-bar-tooltip.test.js.map +1 -0
- package/dist/test/sort-filter-bar/alpha-bar.test.d.ts +1 -1
- package/dist/test/sort-filter-bar/alpha-bar.test.js +73 -43
- package/dist/test/sort-filter-bar/alpha-bar.test.js.map +1 -1
- package/dist/test/sort-filter-bar/sort-filter-bar.test.d.ts +1 -1
- package/dist/test/sort-filter-bar/sort-filter-bar.test.js +197 -197
- package/dist/test/text-overlay.test.d.ts +1 -1
- package/dist/test/text-overlay.test.js +48 -48
- package/dist/test/text-snippet-block.test.d.ts +1 -1
- package/dist/test/text-snippet-block.test.js +57 -57
- package/dist/test/tile-stats.test.d.ts +1 -1
- package/dist/test/tile-stats.test.js +33 -33
- package/dist/test/tiles/grid/account-tile.test.d.ts +1 -1
- package/dist/test/tiles/grid/account-tile.test.js +81 -60
- package/dist/test/tiles/grid/account-tile.test.js.map +1 -1
- package/dist/test/tiles/grid/collection-tile.test.d.ts +1 -1
- package/dist/test/tiles/grid/collection-tile.test.js +81 -57
- package/dist/test/tiles/grid/collection-tile.test.js.map +1 -1
- package/dist/test/tiles/grid/item-tile.test.d.ts +1 -1
- package/dist/test/tiles/grid/item-tile.test.js +163 -142
- package/dist/test/tiles/grid/item-tile.test.js.map +1 -1
- package/dist/test/tiles/hover/hover-pane-controller.test.d.ts +1 -1
- package/dist/test/tiles/hover/hover-pane-controller.test.js +257 -257
- package/dist/test/tiles/hover/tile-hover-pane.test.d.ts +1 -1
- package/dist/test/tiles/hover/tile-hover-pane.test.js +13 -13
- package/dist/test/tiles/list/tile-list-compact.test.d.ts +1 -1
- package/dist/test/tiles/list/tile-list-compact.test.js +92 -92
- package/dist/test/tiles/list/tile-list.test.d.ts +1 -1
- package/dist/test/tiles/list/tile-list.test.js +163 -163
- package/dist/test/tiles/tile-dispatcher.test.d.ts +1 -0
- package/dist/test/tiles/tile-dispatcher.test.js +101 -0
- package/dist/test/tiles/tile-dispatcher.test.js.map +1 -0
- package/dist/test/utils/format-count.test.d.ts +1 -1
- package/dist/test/utils/format-count.test.js +23 -23
- package/dist/test/utils/format-date.test.d.ts +1 -1
- package/dist/test/utils/format-date.test.js +17 -17
- package/dist/test/utils/format-unit-size.test.d.ts +1 -1
- package/dist/test/utils/format-unit-size.test.js +17 -17
- package/local.archive.org.cert +86 -86
- package/local.archive.org.key +27 -27
- package/package.json +1 -1
- package/renovate.json +6 -6
- package/src/collection-browser.ts +4 -0
- package/src/collection-facets.ts +3 -5
- package/src/models.ts +1 -0
- package/src/sort-filter-bar/alpha-bar-tooltip.ts +54 -0
- package/src/sort-filter-bar/alpha-bar.ts +133 -9
- package/src/tiles/grid/account-tile.ts +23 -1
- package/src/tiles/grid/collection-tile.ts +31 -2
- package/src/tiles/grid/item-tile.ts +22 -2
- package/src/tiles/grid/styles/tile-grid-shared-styles.ts +37 -1
- package/src/tiles/hover/hover-pane-controller.ts +38 -1
- package/src/tiles/list/tile-list.ts +8 -1
- package/src/tiles/tile-dispatcher.ts +29 -2
- package/test/sort-filter-bar/alpha-bar-tooltip.test.ts +17 -0
- package/test/sort-filter-bar/alpha-bar.test.ts +46 -1
- package/test/tiles/grid/account-tile.test.ts +27 -0
- package/test/tiles/grid/collection-tile.test.ts +30 -0
- package/test/tiles/grid/item-tile.test.ts +27 -0
- package/test/tiles/tile-dispatcher.test.ts +122 -0
- package/tsconfig.json +21 -21
- package/web-dev-server.config.mjs +30 -30
- package/web-test-runner.config.mjs +41 -41
|
@@ -1,13 +1,27 @@
|
|
|
1
|
-
import { LitElement, html, css } from 'lit';
|
|
2
|
-
import { customElement, property } from 'lit/decorators.js';
|
|
1
|
+
import { LitElement, html, css, nothing, TemplateResult } from 'lit';
|
|
2
|
+
import { customElement, property, state, query } from 'lit/decorators.js';
|
|
3
3
|
import type { PrefixFilterCounts } from '../models';
|
|
4
4
|
|
|
5
|
+
import './alpha-bar-tooltip';
|
|
6
|
+
import type { AlphaBarTooltip } from './alpha-bar-tooltip';
|
|
7
|
+
|
|
5
8
|
@customElement('alpha-bar')
|
|
6
9
|
export class AlphaBar extends LitElement {
|
|
7
10
|
@property({ type: String }) selectedLetter: string | null = null;
|
|
8
11
|
|
|
9
12
|
@property({ type: Object }) letterCounts?: PrefixFilterCounts;
|
|
10
13
|
|
|
14
|
+
@state()
|
|
15
|
+
private tooltipShown: boolean = false;
|
|
16
|
+
|
|
17
|
+
@state()
|
|
18
|
+
private hoveredLetter?: string;
|
|
19
|
+
|
|
20
|
+
@query('alpha-bar-tooltip')
|
|
21
|
+
private tooltip?: AlphaBarTooltip;
|
|
22
|
+
|
|
23
|
+
private readonly alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
|
|
24
|
+
|
|
11
25
|
private get selectedUppercaseLetter(): string | undefined {
|
|
12
26
|
return this.selectedLetter?.toUpperCase();
|
|
13
27
|
}
|
|
@@ -22,11 +36,14 @@ export class AlphaBar extends LitElement {
|
|
|
22
36
|
<li
|
|
23
37
|
class=${letter === this.selectedUppercaseLetter
|
|
24
38
|
? 'selected'
|
|
25
|
-
:
|
|
39
|
+
: nothing}
|
|
40
|
+
@mousemove=${this.handleMouseMove}
|
|
41
|
+
@mouseleave=${this.handleMouseLeave}
|
|
26
42
|
>
|
|
27
43
|
${this.letterCounts?.[letter]
|
|
28
44
|
? this.letterLinkTemplate(letter)
|
|
29
45
|
: html`<span>${letter}</span>`}
|
|
46
|
+
${this.tooltipTemplate(letter)}
|
|
30
47
|
</li>
|
|
31
48
|
`
|
|
32
49
|
)}
|
|
@@ -49,6 +66,17 @@ export class AlphaBar extends LitElement {
|
|
|
49
66
|
`;
|
|
50
67
|
}
|
|
51
68
|
|
|
69
|
+
private tooltipTemplate(letter: string): TemplateResult | typeof nothing {
|
|
70
|
+
if (this.hoveredLetter !== letter) return nothing;
|
|
71
|
+
|
|
72
|
+
return this.tooltipShown
|
|
73
|
+
? html`<alpha-bar-tooltip
|
|
74
|
+
data-letter=${letter}
|
|
75
|
+
.numResults=${this.letterCounts?.[this.hoveredLetter] ?? 0}
|
|
76
|
+
></alpha-bar-tooltip>`
|
|
77
|
+
: nothing;
|
|
78
|
+
}
|
|
79
|
+
|
|
52
80
|
private letterClicked(letter: string) {
|
|
53
81
|
if (letter === this.selectedUppercaseLetter) {
|
|
54
82
|
this.selectedLetter = null;
|
|
@@ -62,7 +90,77 @@ export class AlphaBar extends LitElement {
|
|
|
62
90
|
);
|
|
63
91
|
}
|
|
64
92
|
|
|
65
|
-
private
|
|
93
|
+
private async handleMouseMove(e: MouseEvent) {
|
|
94
|
+
const target = e.target as HTMLLIElement;
|
|
95
|
+
if (target && !this.tooltipShown) {
|
|
96
|
+
const targetLetter = target.textContent?.trim() ?? undefined;
|
|
97
|
+
this.tooltipShown = true;
|
|
98
|
+
this.hoveredLetter = targetLetter;
|
|
99
|
+
|
|
100
|
+
await this.updateComplete;
|
|
101
|
+
await new Promise(resolve => {
|
|
102
|
+
setTimeout(resolve, 0);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
if (this.tooltip && this.tooltip.dataset.letter === targetLetter) {
|
|
106
|
+
this.positionTooltip(target);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private handleMouseLeave() {
|
|
112
|
+
this.tooltipShown = false;
|
|
113
|
+
this.hoveredLetter = undefined;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private positionTooltip(targetElmt: HTMLElement) {
|
|
117
|
+
if (!this.tooltip) return;
|
|
118
|
+
|
|
119
|
+
// Basic positioning is just to center the whole tooltip on the letter box.
|
|
120
|
+
const tooltipWidth = this.tooltip.clientWidth;
|
|
121
|
+
const letterWidth = targetElmt.clientWidth;
|
|
122
|
+
let left = letterWidth / 2 - tooltipWidth / 2;
|
|
123
|
+
|
|
124
|
+
// But we also need to ensure the tooltip doesn't flow outside the viewport.
|
|
125
|
+
// First, calculate the full width of the document body, including margins
|
|
126
|
+
// (but not including any scrollbar).
|
|
127
|
+
const bodyStyle = getComputedStyle(document.body);
|
|
128
|
+
const bodyMarginLeft = parseFloat(
|
|
129
|
+
bodyStyle.getPropertyValue('margin-left')
|
|
130
|
+
);
|
|
131
|
+
const bodyMarginRight = parseFloat(
|
|
132
|
+
bodyStyle.getPropertyValue('margin-right')
|
|
133
|
+
);
|
|
134
|
+
const bodyWidthWithMargin =
|
|
135
|
+
document.body.clientWidth + bodyMarginLeft + bodyMarginRight;
|
|
136
|
+
|
|
137
|
+
// Calculate the positions of the tooltip's left/right edges, and determine
|
|
138
|
+
// how much they overflow the viewport by (if at all).
|
|
139
|
+
const targetRect = targetElmt.getBoundingClientRect();
|
|
140
|
+
const tooltipLeft = targetRect.left + left;
|
|
141
|
+
const tooltipRight = tooltipLeft + tooltipWidth;
|
|
142
|
+
const offset = 1; // How many pixels the tooltip must be offset from the left/right edges
|
|
143
|
+
let overflowAmt;
|
|
144
|
+
if (tooltipLeft < offset) {
|
|
145
|
+
// Tooltip overflows left edge of viewport
|
|
146
|
+
overflowAmt = tooltipLeft - offset;
|
|
147
|
+
} else if (tooltipRight > bodyWidthWithMargin - offset) {
|
|
148
|
+
// Tooltip overflows right edge of viewport
|
|
149
|
+
overflowAmt = tooltipRight - bodyWidthWithMargin + offset;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Apply any needed adjustment to the tooltip and its arrow to keep it in the viewport
|
|
153
|
+
if (overflowAmt) {
|
|
154
|
+
left -= overflowAmt;
|
|
155
|
+
this.tooltip.style.setProperty(
|
|
156
|
+
'--tooltipArrowOffset',
|
|
157
|
+
`${overflowAmt}px`
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
this.tooltip.style.left = `${left}px`;
|
|
162
|
+
this.tooltip.classList.add('fade-in');
|
|
163
|
+
}
|
|
66
164
|
|
|
67
165
|
static styles = css`
|
|
68
166
|
h1 {
|
|
@@ -84,30 +182,56 @@ export class AlphaBar extends LitElement {
|
|
|
84
182
|
}
|
|
85
183
|
|
|
86
184
|
ul li {
|
|
185
|
+
position: relative;
|
|
87
186
|
flex: 1;
|
|
88
187
|
text-align: center;
|
|
89
188
|
max-width: 2.5rem;
|
|
189
|
+
border-radius: 4px;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
li:hover:not(.selected) a {
|
|
193
|
+
background-color: #c0c0c0;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
a,
|
|
197
|
+
span {
|
|
198
|
+
display: flex;
|
|
199
|
+
justify-content: center;
|
|
200
|
+
align-items: center;
|
|
201
|
+
aspect-ratio: 1 / 1;
|
|
90
202
|
}
|
|
91
203
|
|
|
92
204
|
a {
|
|
93
205
|
color: #333;
|
|
94
206
|
text-decoration: none;
|
|
95
|
-
|
|
96
|
-
display: block;
|
|
207
|
+
border-radius: 4px;
|
|
97
208
|
}
|
|
98
209
|
|
|
99
210
|
span {
|
|
100
211
|
color: #aaa;
|
|
101
|
-
|
|
102
|
-
display: block;
|
|
212
|
+
cursor: default;
|
|
103
213
|
}
|
|
104
214
|
|
|
105
215
|
.selected {
|
|
106
|
-
background-color:
|
|
216
|
+
background-color: #2c2c2c;
|
|
107
217
|
}
|
|
108
218
|
|
|
109
219
|
.selected a {
|
|
110
220
|
color: white;
|
|
111
221
|
}
|
|
222
|
+
|
|
223
|
+
alpha-bar-tooltip {
|
|
224
|
+
position: absolute;
|
|
225
|
+
top: 100%;
|
|
226
|
+
left: -9999px;
|
|
227
|
+
margin-top: 3px;
|
|
228
|
+
|
|
229
|
+
opacity: 0;
|
|
230
|
+
transition: opacity 0.2s ease;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
alpha-bar-tooltip.fade-in {
|
|
234
|
+
opacity: 1;
|
|
235
|
+
}
|
|
112
236
|
`;
|
|
113
237
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { css, html, LitElement, TemplateResult } from 'lit';
|
|
1
|
+
import { css, html, LitElement, nothing, TemplateResult } from 'lit';
|
|
2
2
|
import { customElement, property } from 'lit/decorators.js';
|
|
3
3
|
import type { TileModel } from '../../models';
|
|
4
4
|
|
|
@@ -12,9 +12,12 @@ export class AccountTile extends LitElement {
|
|
|
12
12
|
|
|
13
13
|
@property({ type: String }) baseImageUrl?: string;
|
|
14
14
|
|
|
15
|
+
@property({ type: Boolean }) showInfoButton = false;
|
|
16
|
+
|
|
15
17
|
render() {
|
|
16
18
|
return html`
|
|
17
19
|
<div class="container">
|
|
20
|
+
${this.infoButtonTemplate}
|
|
18
21
|
<div class="tile-details">
|
|
19
22
|
<div class="item-info">
|
|
20
23
|
${this.getAvatarTemplate} ${this.getTitleTemplate}
|
|
@@ -59,6 +62,25 @@ export class AccountTile extends LitElement {
|
|
|
59
62
|
</tile-stats>`;
|
|
60
63
|
}
|
|
61
64
|
|
|
65
|
+
private get infoButtonTemplate(): TemplateResult | typeof nothing {
|
|
66
|
+
// ⓘ is an information icon
|
|
67
|
+
return this.showInfoButton
|
|
68
|
+
? html`<button class="info-button" @click=${this.infoButtonPressed}>
|
|
69
|
+
ⓘ
|
|
70
|
+
<span class="sr-only">More info</span>
|
|
71
|
+
</button>`
|
|
72
|
+
: nothing;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private infoButtonPressed(e: PointerEvent) {
|
|
76
|
+
e.preventDefault();
|
|
77
|
+
const event = new CustomEvent<{ x: number; y: number }>(
|
|
78
|
+
'infoButtonPressed',
|
|
79
|
+
{ detail: { x: e.clientX, y: e.clientY } }
|
|
80
|
+
);
|
|
81
|
+
this.dispatchEvent(event);
|
|
82
|
+
}
|
|
83
|
+
|
|
62
84
|
/**
|
|
63
85
|
* CSS
|
|
64
86
|
*/
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
css,
|
|
3
|
+
CSSResultGroup,
|
|
4
|
+
html,
|
|
5
|
+
LitElement,
|
|
6
|
+
nothing,
|
|
7
|
+
TemplateResult,
|
|
8
|
+
} from 'lit';
|
|
2
9
|
import { customElement, property } from 'lit/decorators.js';
|
|
3
10
|
import { collectionIcon } from '../../assets/img/icons/mediatype/collection';
|
|
4
11
|
import type { TileModel } from '../../models';
|
|
@@ -12,9 +19,12 @@ export class CollectionTile extends LitElement {
|
|
|
12
19
|
|
|
13
20
|
@property({ type: String }) baseImageUrl?: string;
|
|
14
21
|
|
|
22
|
+
@property({ type: Boolean }) showInfoButton = false;
|
|
23
|
+
|
|
15
24
|
render() {
|
|
16
25
|
return html`
|
|
17
26
|
<div class="container">
|
|
27
|
+
${this.infoButtonTemplate}
|
|
18
28
|
<div class="tile-details">
|
|
19
29
|
<div class="item-info">
|
|
20
30
|
${this.getImageBlockTemplate} ${this.getTitleTemplate}
|
|
@@ -56,7 +66,7 @@ export class CollectionTile extends LitElement {
|
|
|
56
66
|
}
|
|
57
67
|
|
|
58
68
|
private get getItemsTemplate() {
|
|
59
|
-
const collectionItems = this.model?.itemCount
|
|
69
|
+
const collectionItems = this.model?.itemCount?.toLocaleString();
|
|
60
70
|
|
|
61
71
|
return html`<span id="item-count"
|
|
62
72
|
>${collectionItems} item${Number(collectionItems) !== 1 ? 's' : ''}</span
|
|
@@ -71,6 +81,25 @@ export class CollectionTile extends LitElement {
|
|
|
71
81
|
: ``;
|
|
72
82
|
}
|
|
73
83
|
|
|
84
|
+
private get infoButtonTemplate(): TemplateResult | typeof nothing {
|
|
85
|
+
// ⓘ is an information icon
|
|
86
|
+
return this.showInfoButton
|
|
87
|
+
? html`<button class="info-button" @click=${this.infoButtonPressed}>
|
|
88
|
+
ⓘ
|
|
89
|
+
<span class="sr-only">More info</span>
|
|
90
|
+
</button>`
|
|
91
|
+
: nothing;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private infoButtonPressed(e: PointerEvent) {
|
|
95
|
+
e.preventDefault();
|
|
96
|
+
const event = new CustomEvent<{ x: number; y: number }>(
|
|
97
|
+
'infoButtonPressed',
|
|
98
|
+
{ detail: { x: e.clientX, y: e.clientY } }
|
|
99
|
+
);
|
|
100
|
+
this.dispatchEvent(event);
|
|
101
|
+
}
|
|
102
|
+
|
|
74
103
|
static get styles(): CSSResultGroup {
|
|
75
104
|
const tileBorderColor = css`var(--tileBorderColor, #555555)`;
|
|
76
105
|
const tileBackgroundColor = css`var(--tileBackgroundColor, #666666)`;
|
|
@@ -31,11 +31,14 @@ export class ItemTile extends LitElement {
|
|
|
31
31
|
|
|
32
32
|
@property({ type: Object }) sortParam?: SortParam;
|
|
33
33
|
|
|
34
|
+
@property({ type: Boolean }) showInfoButton = false;
|
|
35
|
+
|
|
34
36
|
render() {
|
|
35
37
|
const itemTitle = this.model?.title;
|
|
36
38
|
|
|
37
39
|
return html`
|
|
38
40
|
<div class="container">
|
|
41
|
+
${this.infoButtonTemplate}
|
|
39
42
|
<div class="tile-details">
|
|
40
43
|
<div class="item-info">
|
|
41
44
|
${this.imageBlockTemplate}
|
|
@@ -96,8 +99,6 @@ export class ItemTile extends LitElement {
|
|
|
96
99
|
|
|
97
100
|
private get sortedDateInfoTemplate() {
|
|
98
101
|
let sortedValue;
|
|
99
|
-
|
|
100
|
-
// console.log('model: ', this.model)
|
|
101
102
|
switch (this.sortParam?.field) {
|
|
102
103
|
case 'date':
|
|
103
104
|
sortedValue = { field: 'published', value: this.model?.datePublished };
|
|
@@ -127,6 +128,16 @@ export class ItemTile extends LitElement {
|
|
|
127
128
|
`;
|
|
128
129
|
}
|
|
129
130
|
|
|
131
|
+
private get infoButtonTemplate(): TemplateResult | typeof nothing {
|
|
132
|
+
// ⓘ is an information icon
|
|
133
|
+
return this.showInfoButton
|
|
134
|
+
? html`<button class="info-button" @click=${this.infoButtonPressed}>
|
|
135
|
+
ⓘ
|
|
136
|
+
<span class="sr-only">More info</span>
|
|
137
|
+
</button>`
|
|
138
|
+
: nothing;
|
|
139
|
+
}
|
|
140
|
+
|
|
130
141
|
private get textSnippetsTemplate(): TemplateResult | typeof nothing {
|
|
131
142
|
if (!this.hasSnippets) return nothing;
|
|
132
143
|
|
|
@@ -158,6 +169,15 @@ export class ItemTile extends LitElement {
|
|
|
158
169
|
return !!this.model?.snippets?.length;
|
|
159
170
|
}
|
|
160
171
|
|
|
172
|
+
private infoButtonPressed(e: PointerEvent): void {
|
|
173
|
+
e.preventDefault();
|
|
174
|
+
const event = new CustomEvent<{ x: number; y: number }>(
|
|
175
|
+
'infoButtonPressed',
|
|
176
|
+
{ detail: { x: e.clientX, y: e.clientY } }
|
|
177
|
+
);
|
|
178
|
+
this.dispatchEvent(event);
|
|
179
|
+
}
|
|
180
|
+
|
|
161
181
|
/**
|
|
162
182
|
* CSS
|
|
163
183
|
*/
|
|
@@ -51,7 +51,7 @@ export const baseTileStyles = css`
|
|
|
51
51
|
.archivist-since {
|
|
52
52
|
display: flex;
|
|
53
53
|
justify-content: left;
|
|
54
|
-
align-items: flex-
|
|
54
|
+
align-items: flex-start;
|
|
55
55
|
padding: 0 5px;
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -97,7 +97,43 @@ export const baseTileStyles = css`
|
|
|
97
97
|
text-decoration: underline;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
.info-button {
|
|
101
|
+
position: absolute;
|
|
102
|
+
right: 10px;
|
|
103
|
+
top: 10px;
|
|
104
|
+
margin: 0;
|
|
105
|
+
padding: 0;
|
|
106
|
+
border: none;
|
|
107
|
+
border-radius: 50%;
|
|
108
|
+
display: flex;
|
|
109
|
+
justify-content: center;
|
|
110
|
+
align-items: center;
|
|
111
|
+
background: rgba(220, 220, 220, 0.5);
|
|
112
|
+
color: white;
|
|
113
|
+
font-size: 2rem;
|
|
114
|
+
font-weight: bold;
|
|
115
|
+
line-height: 1;
|
|
116
|
+
text-shadow: black 1px 1px 3px;
|
|
117
|
+
overflow: visible;
|
|
118
|
+
aspect-ratio: 1 / 1;
|
|
119
|
+
z-index: 1;
|
|
120
|
+
}
|
|
121
|
+
|
|
100
122
|
.hidden {
|
|
101
123
|
display: none;
|
|
102
124
|
}
|
|
125
|
+
|
|
126
|
+
.sr-only {
|
|
127
|
+
position: absolute !important;
|
|
128
|
+
width: 1px !important;
|
|
129
|
+
height: 1px !important;
|
|
130
|
+
margin: -1px !important;
|
|
131
|
+
padding: 0 !important;
|
|
132
|
+
border: 0 !important;
|
|
133
|
+
overflow: hidden !important;
|
|
134
|
+
white-space: nowrap !important;
|
|
135
|
+
clip: rect(1px, 1px, 1px, 1px) !important;
|
|
136
|
+
-webkit-clip-path: inset(50%) !important;
|
|
137
|
+
clip-path: inset(50%) !important;
|
|
138
|
+
}
|
|
103
139
|
`;
|
|
@@ -38,6 +38,11 @@ export interface HoverPaneProviderInterface {
|
|
|
38
38
|
getHoverPaneProps(): HoverPaneProperties;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
export interface ToggleHoverPaneOptions {
|
|
42
|
+
coords: { x: number; y: number };
|
|
43
|
+
enableTouchBackdrop?: boolean;
|
|
44
|
+
}
|
|
45
|
+
|
|
41
46
|
/**
|
|
42
47
|
* An interface for interacting with hover pane controllers (e.g.,
|
|
43
48
|
* to retrieve their current hover pane template).
|
|
@@ -49,6 +54,14 @@ export interface HoverPaneControllerInterface extends ReactiveController {
|
|
|
49
54
|
* pane should not currently be rendered.
|
|
50
55
|
*/
|
|
51
56
|
getTemplate(): HTMLTemplateResult | typeof nothing;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Requests to manually toggle the state of the hover pane.
|
|
60
|
+
* If the hover pane is already shown, it will begin fading out and then
|
|
61
|
+
* subsequently be hidden and removed. If the hover pane is already fading
|
|
62
|
+
* out or hidden, it will fade back in and be shown.
|
|
63
|
+
*/
|
|
64
|
+
toggleHoverPane(options: ToggleHoverPaneOptions): void;
|
|
52
65
|
}
|
|
53
66
|
|
|
54
67
|
const clamp = (val: number, min = -Infinity, max = Infinity) =>
|
|
@@ -123,6 +136,12 @@ export class HoverPaneController implements HoverPaneControllerInterface {
|
|
|
123
136
|
/** The timer ID for recognizing a long press event */
|
|
124
137
|
private longPressTimer?: number;
|
|
125
138
|
|
|
139
|
+
/**
|
|
140
|
+
* Whether the touch backdrop should currently be rendered irrespective of other touch
|
|
141
|
+
* interactions being enabled.
|
|
142
|
+
*/
|
|
143
|
+
private forceTouchBackdrop: boolean = false;
|
|
144
|
+
|
|
126
145
|
/** A record of the last mouse position on the host element, for positioning the hover pane */
|
|
127
146
|
private lastPointerClientPos = { x: 0, y: 0 };
|
|
128
147
|
|
|
@@ -173,6 +192,18 @@ export class HoverPaneController implements HoverPaneControllerInterface {
|
|
|
173
192
|
: nothing;
|
|
174
193
|
}
|
|
175
194
|
|
|
195
|
+
/** @inheritdoc */
|
|
196
|
+
toggleHoverPane(options: ToggleHoverPaneOptions): void {
|
|
197
|
+
if (this.hoverPaneState === 'shown') {
|
|
198
|
+
this.fadeOutHoverPane();
|
|
199
|
+
this.forceTouchBackdrop = false;
|
|
200
|
+
} else {
|
|
201
|
+
this.lastPointerClientPos = options.coords;
|
|
202
|
+
this.forceTouchBackdrop = options.enableTouchBackdrop ?? false;
|
|
203
|
+
this.showHoverPane();
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
176
207
|
/**
|
|
177
208
|
* Produces a template for the invisible touch capture backdrop that
|
|
178
209
|
* is used to cancel the hover pane on touch devices. We want any
|
|
@@ -181,7 +212,7 @@ export class HoverPaneController implements HoverPaneControllerInterface {
|
|
|
181
212
|
* affect the state of the hover pane (e.g., fading it back in).
|
|
182
213
|
*/
|
|
183
214
|
private get touchBackdropTemplate(): HTMLTemplateResult | typeof nothing {
|
|
184
|
-
return this.
|
|
215
|
+
return this.showTouchBackdrop
|
|
185
216
|
? html`<div
|
|
186
217
|
id="touch-backdrop"
|
|
187
218
|
@touchstart=${this.handleBackdropInteraction}
|
|
@@ -195,6 +226,12 @@ export class HoverPaneController implements HoverPaneControllerInterface {
|
|
|
195
226
|
: nothing;
|
|
196
227
|
}
|
|
197
228
|
|
|
229
|
+
private get showTouchBackdrop(): boolean {
|
|
230
|
+
return (
|
|
231
|
+
(this.isTouchEnabled && this.enableLongPress) || this.forceTouchBackdrop
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
198
235
|
/** Whether to use the mobile layout */
|
|
199
236
|
private get isMobileView(): boolean {
|
|
200
237
|
return !!this.mobileBreakpoint && window.innerWidth < this.mobileBreakpoint;
|
|
@@ -140,7 +140,14 @@ export class TileList extends LitElement {
|
|
|
140
140
|
if (!this.model?.title) {
|
|
141
141
|
return nothing;
|
|
142
142
|
}
|
|
143
|
-
|
|
143
|
+
|
|
144
|
+
// If the model has a server-specified href, use it
|
|
145
|
+
// Otherwise construct a details link using the identifier
|
|
146
|
+
return this.model?.href
|
|
147
|
+
? html`<a href="${this.baseNavigationUrl}${this.model.href}"
|
|
148
|
+
>${this.model.title ?? this.model.identifier}</a
|
|
149
|
+
>`
|
|
150
|
+
: this.detailsLink(this.model.identifier, this.model.title);
|
|
144
151
|
}
|
|
145
152
|
|
|
146
153
|
private get itemLineTemplate() {
|
|
@@ -122,7 +122,7 @@ export class TileDispatcher
|
|
|
122
122
|
private get linkTileTemplate() {
|
|
123
123
|
return html`
|
|
124
124
|
<a
|
|
125
|
-
href="${this.
|
|
125
|
+
href="${this.linkTileHref}"
|
|
126
126
|
title=${this.shouldPrepareHoverPane
|
|
127
127
|
? nothing // Don't show title tooltips when we have the tile info popups
|
|
128
128
|
: ifDefined(this.model?.title)}
|
|
@@ -136,6 +136,14 @@ export class TileDispatcher
|
|
|
136
136
|
`;
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
+
private get linkTileHref() {
|
|
140
|
+
// Use the server-specified href if available.
|
|
141
|
+
// Otherwise, construct a details page URL from the item identifier.
|
|
142
|
+
return this.model?.href
|
|
143
|
+
? `${this.baseNavigationUrl}${this.model?.href}`
|
|
144
|
+
: `${this.baseNavigationUrl}/details/${this.model?.identifier}`;
|
|
145
|
+
}
|
|
146
|
+
|
|
139
147
|
/**
|
|
140
148
|
* Whether hover pane behavior should be prepared for this tile
|
|
141
149
|
* (e.g., whether mouse listeners should be attached, etc.)
|
|
@@ -148,6 +156,10 @@ export class TileDispatcher
|
|
|
148
156
|
);
|
|
149
157
|
}
|
|
150
158
|
|
|
159
|
+
private get isHoverEnabled(): boolean {
|
|
160
|
+
return window.matchMedia('(hover: hover)').matches;
|
|
161
|
+
}
|
|
162
|
+
|
|
151
163
|
/** @inheritdoc */
|
|
152
164
|
getHoverPane(): TileHoverPane | undefined {
|
|
153
165
|
return this.hoverPane;
|
|
@@ -192,6 +204,15 @@ export class TileDispatcher
|
|
|
192
204
|
}
|
|
193
205
|
}
|
|
194
206
|
|
|
207
|
+
private tileInfoButtonPressed(
|
|
208
|
+
e: CustomEvent<{ x: number; y: number }>
|
|
209
|
+
): void {
|
|
210
|
+
this.hoverPaneController?.toggleHoverPane({
|
|
211
|
+
coords: e.detail,
|
|
212
|
+
enableTouchBackdrop: true,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
195
216
|
private get tile() {
|
|
196
217
|
const {
|
|
197
218
|
model,
|
|
@@ -213,6 +234,8 @@ export class TileDispatcher
|
|
|
213
234
|
.baseImageUrl=${this.baseImageUrl}
|
|
214
235
|
.currentWidth=${currentWidth}
|
|
215
236
|
.currentHeight=${currentHeight}
|
|
237
|
+
?showInfoButton=${!this.isHoverEnabled}
|
|
238
|
+
@infoButtonPressed=${this.tileInfoButtonPressed}
|
|
216
239
|
>
|
|
217
240
|
</collection-tile>`;
|
|
218
241
|
case 'account':
|
|
@@ -221,6 +244,8 @@ export class TileDispatcher
|
|
|
221
244
|
.baseImageUrl=${this.baseImageUrl}
|
|
222
245
|
.currentWidth=${currentWidth}
|
|
223
246
|
.currentHeight=${currentHeight}
|
|
247
|
+
?showInfoButton=${!this.isHoverEnabled}
|
|
248
|
+
@infoButtonPressed=${this.tileInfoButtonPressed}
|
|
224
249
|
>
|
|
225
250
|
</account-tile>`;
|
|
226
251
|
default:
|
|
@@ -232,6 +257,8 @@ export class TileDispatcher
|
|
|
232
257
|
.baseImageUrl=${this.baseImageUrl}
|
|
233
258
|
.sortParam=${sortParam}
|
|
234
259
|
.loggedIn=${this.loggedIn}
|
|
260
|
+
?showInfoButton=${!this.isHoverEnabled}
|
|
261
|
+
@infoButtonPressed=${this.tileInfoButtonPressed}
|
|
235
262
|
>
|
|
236
263
|
</item-tile>`;
|
|
237
264
|
}
|
|
@@ -318,7 +345,7 @@ export class TileDispatcher
|
|
|
318
345
|
height: 100vh;
|
|
319
346
|
top: 0;
|
|
320
347
|
left: 0;
|
|
321
|
-
z-index:
|
|
348
|
+
z-index: 2;
|
|
322
349
|
background: transparent;
|
|
323
350
|
}
|
|
324
351
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { expect, fixture } from '@open-wc/testing';
|
|
2
|
+
import { html } from 'lit';
|
|
3
|
+
import type { AlphaBarTooltip } from '../../src/sort-filter-bar/alpha-bar-tooltip';
|
|
4
|
+
|
|
5
|
+
import '../../src/sort-filter-bar/alpha-bar-tooltip';
|
|
6
|
+
|
|
7
|
+
describe('Alphabet Filter Bar Tooltips', () => {
|
|
8
|
+
it('renders component', async () => {
|
|
9
|
+
const el = await fixture<AlphaBarTooltip>(
|
|
10
|
+
html`<alpha-bar-tooltip .numResults=${42}></alpha-bar-tooltip>`
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
// Should render the number of results
|
|
14
|
+
const tooltipText = el.shadowRoot?.querySelector('#tooltip-text');
|
|
15
|
+
expect(tooltipText?.textContent?.trim()).to.equal('42 results');
|
|
16
|
+
});
|
|
17
|
+
});
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { expect, fixture } from '@open-wc/testing';
|
|
1
|
+
import { aTimeout, expect, fixture } from '@open-wc/testing';
|
|
2
2
|
import { html } from 'lit';
|
|
3
3
|
import type { AlphaBar } from '../../src/sort-filter-bar/alpha-bar';
|
|
4
4
|
|
|
5
5
|
import '../../src/sort-filter-bar/alpha-bar';
|
|
6
|
+
import type { AlphaBarTooltip } from '../../src/sort-filter-bar/alpha-bar-tooltip';
|
|
6
7
|
|
|
7
8
|
describe('Alphabetical Filter Bar', () => {
|
|
8
9
|
it('renders component', async () => {
|
|
@@ -49,4 +50,48 @@ describe('Alphabetical Filter Bar', () => {
|
|
|
49
50
|
expect(selectedLetter).to.exist;
|
|
50
51
|
expect(selectedLetter?.textContent?.trim()).to.equal('B');
|
|
51
52
|
});
|
|
53
|
+
|
|
54
|
+
it('renders a tooltip when hovered and removes it when un-hovered', async () => {
|
|
55
|
+
const el = await fixture<AlphaBar>(html`<alpha-bar></alpha-bar>`);
|
|
56
|
+
const firstLetter = el.shadowRoot?.querySelector('li') as HTMLLIElement;
|
|
57
|
+
expect(firstLetter).to.exist;
|
|
58
|
+
|
|
59
|
+
firstLetter.dispatchEvent(new MouseEvent('mousemove'));
|
|
60
|
+
await el.updateComplete;
|
|
61
|
+
|
|
62
|
+
const tooltip = el.shadowRoot?.querySelector(
|
|
63
|
+
'alpha-bar-tooltip'
|
|
64
|
+
) as AlphaBarTooltip;
|
|
65
|
+
expect(tooltip).to.exist;
|
|
66
|
+
|
|
67
|
+
// Should be positioned after next tick
|
|
68
|
+
await aTimeout(0);
|
|
69
|
+
expect(tooltip.style.left).to.exist;
|
|
70
|
+
|
|
71
|
+
firstLetter.dispatchEvent(new MouseEvent('mouseleave'));
|
|
72
|
+
await el.updateComplete;
|
|
73
|
+
|
|
74
|
+
expect(el.shadowRoot?.querySelector('alpha-bar-tooltip')).not.to.exist;
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('positions tooltip correctly when it would overflow viewport', async () => {
|
|
78
|
+
const el = await fixture<AlphaBar>(html`<alpha-bar></alpha-bar>`);
|
|
79
|
+
const letters = el.shadowRoot?.querySelectorAll('li');
|
|
80
|
+
const lastLetter = letters?.item(letters.length - 1) as HTMLLIElement;
|
|
81
|
+
expect(lastLetter).to.exist;
|
|
82
|
+
|
|
83
|
+
lastLetter.dispatchEvent(new MouseEvent('mousemove'));
|
|
84
|
+
await el.updateComplete;
|
|
85
|
+
|
|
86
|
+
const tooltip = el.shadowRoot?.querySelector(
|
|
87
|
+
'alpha-bar-tooltip'
|
|
88
|
+
) as AlphaBarTooltip;
|
|
89
|
+
expect(tooltip).to.exist;
|
|
90
|
+
|
|
91
|
+
// Should be positioned after next tick, but not off-screen
|
|
92
|
+
await aTimeout(0);
|
|
93
|
+
expect(tooltip.getBoundingClientRect().right).to.be.lessThan(
|
|
94
|
+
window.innerWidth
|
|
95
|
+
);
|
|
96
|
+
});
|
|
52
97
|
});
|