@internetarchive/collection-browser 3.1.0 → 3.1.1-alpha-webdev6778.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/app-root.js +606 -606
- package/dist/src/app-root.js.map +1 -1
- package/dist/src/collection-browser.d.ts +9 -0
- package/dist/src/collection-browser.js +7 -0
- package/dist/src/collection-browser.js.map +1 -1
- package/dist/src/collection-facets/facet-row.js +140 -140
- package/dist/src/collection-facets/facet-row.js.map +1 -1
- package/dist/src/collection-facets/models.js.map +1 -1
- package/dist/src/collection-facets/more-facets-content.d.ts +1 -0
- package/dist/src/collection-facets/more-facets-content.js +122 -118
- package/dist/src/collection-facets/more-facets-content.js.map +1 -1
- package/dist/src/collection-facets/smart-facets/smart-facet-bar.js +75 -75
- package/dist/src/collection-facets/smart-facets/smart-facet-bar.js.map +1 -1
- package/dist/src/collection-facets/smart-facets/smart-facet-dropdown.js +54 -54
- package/dist/src/collection-facets/smart-facets/smart-facet-dropdown.js.map +1 -1
- package/dist/src/collection-facets.d.ts +1 -0
- package/dist/src/collection-facets.js +269 -265
- package/dist/src/collection-facets.js.map +1 -1
- package/dist/src/data-source/collection-browser-data-source-interface.js.map +1 -1
- package/dist/src/data-source/collection-browser-data-source.js +27 -13
- package/dist/src/data-source/collection-browser-data-source.js.map +1 -1
- package/dist/src/data-source/collection-browser-query-state.d.ts +1 -0
- package/dist/src/data-source/collection-browser-query-state.js.map +1 -1
- package/dist/src/data-source/models.d.ts +1 -1
- package/dist/src/data-source/models.js.map +1 -1
- package/dist/src/expanded-date-picker.js +52 -52
- package/dist/src/expanded-date-picker.js.map +1 -1
- package/dist/src/manage/manage-bar.js +77 -77
- package/dist/src/manage/manage-bar.js.map +1 -1
- package/dist/src/models.js.map +1 -1
- package/dist/src/sort-filter-bar/sort-filter-bar.js +376 -376
- package/dist/src/sort-filter-bar/sort-filter-bar.js.map +1 -1
- package/dist/src/tiles/grid/collection-tile.js +77 -77
- package/dist/src/tiles/grid/collection-tile.js.map +1 -1
- package/dist/src/tiles/grid/item-tile.js +139 -139
- package/dist/src/tiles/grid/item-tile.js.map +1 -1
- package/dist/src/tiles/grid/search-tile.js +42 -42
- package/dist/src/tiles/grid/search-tile.js.map +1 -1
- package/dist/src/tiles/grid/styles/tile-grid-shared-styles.js +119 -119
- package/dist/src/tiles/grid/styles/tile-grid-shared-styles.js.map +1 -1
- package/dist/src/tiles/list/tile-list.js +297 -297
- package/dist/src/tiles/list/tile-list.js.map +1 -1
- package/dist/src/tiles/tile-dispatcher.js +200 -200
- package/dist/src/tiles/tile-dispatcher.js.map +1 -1
- package/dist/src/utils/analytics-events.js.map +1 -1
- package/dist/test/collection-facets/facet-row.test.js +23 -23
- package/dist/test/collection-facets/facet-row.test.js.map +1 -1
- package/dist/test/collection-facets.test.js +20 -20
- package/dist/test/collection-facets.test.js.map +1 -1
- package/dist/test/sort-filter-bar/sort-filter-bar.test.js +37 -37
- package/dist/test/sort-filter-bar/sort-filter-bar.test.js.map +1 -1
- package/dist/test/tiles/list/tile-list.test.js +113 -113
- package/dist/test/tiles/list/tile-list.test.js.map +1 -1
- package/package.json +2 -2
- package/src/app-root.ts +1140 -1140
- package/src/collection-browser.ts +14 -0
- package/src/collection-facets/facet-row.ts +296 -296
- package/src/collection-facets/models.ts +10 -10
- package/src/collection-facets/more-facets-content.ts +639 -636
- package/src/collection-facets/smart-facets/smart-facet-bar.ts +437 -437
- package/src/collection-facets/smart-facets/smart-facet-dropdown.ts +185 -185
- package/src/collection-facets.ts +995 -992
- package/src/data-source/collection-browser-data-source-interface.ts +333 -333
- package/src/data-source/collection-browser-data-source.ts +21 -11
- package/src/data-source/collection-browser-query-state.ts +1 -0
- package/src/data-source/models.ts +1 -1
- package/src/expanded-date-picker.ts +191 -191
- package/src/manage/manage-bar.ts +247 -247
- package/src/models.ts +870 -870
- package/src/sort-filter-bar/sort-filter-bar.ts +1283 -1283
- package/src/tiles/grid/collection-tile.ts +162 -162
- package/src/tiles/grid/item-tile.ts +339 -339
- package/src/tiles/grid/search-tile.ts +90 -90
- package/src/tiles/grid/styles/tile-grid-shared-styles.ts +130 -130
- package/src/tiles/list/tile-list.ts +696 -696
- package/src/tiles/tile-dispatcher.ts +486 -486
- package/src/utils/analytics-events.ts +29 -29
- package/test/collection-facets/facet-row.test.ts +375 -375
- package/test/collection-facets.test.ts +928 -928
- package/test/sort-filter-bar/sort-filter-bar.test.ts +885 -885
- package/test/tiles/list/tile-list.test.ts +497 -497
|
@@ -125,6 +125,16 @@ export class CollectionBrowser
|
|
|
125
125
|
*/
|
|
126
126
|
@property({ type: String }) baseQuery?: string;
|
|
127
127
|
|
|
128
|
+
/**
|
|
129
|
+
* The base list of identifiers to fetch, if using the client_document_fetch feature
|
|
130
|
+
* of the search service.
|
|
131
|
+
*
|
|
132
|
+
* This approach allows many more identifiers to be retrieved than a query like
|
|
133
|
+
* `identifier:(foo OR bar OR ...)` would, but still may be more limited in what
|
|
134
|
+
* content is returned by the backend
|
|
135
|
+
*/
|
|
136
|
+
@property({ type: Array }) identifiers?: string[];
|
|
137
|
+
|
|
128
138
|
/**
|
|
129
139
|
* Which mode to display result tiles in (grid, extended list, or compact list)
|
|
130
140
|
*/
|
|
@@ -1278,6 +1288,7 @@ export class CollectionBrowser
|
|
|
1278
1288
|
.allowDatePickerMonths=${shouldUseTvInterface}
|
|
1279
1289
|
.contentWidth=${this.contentWidth}
|
|
1280
1290
|
.query=${this.baseQuery}
|
|
1291
|
+
.identifiers=${this.identifiers}
|
|
1281
1292
|
.filterMap=${this.dataSource.filterMap}
|
|
1282
1293
|
.isManageView=${this.isManageView}
|
|
1283
1294
|
.modalManager=${this.modalManager}
|
|
@@ -1525,6 +1536,7 @@ export class CollectionBrowser
|
|
|
1525
1536
|
|
|
1526
1537
|
if (
|
|
1527
1538
|
changed.has('baseQuery') ||
|
|
1539
|
+
changed.has('identifiers') ||
|
|
1528
1540
|
changed.has('searchType') ||
|
|
1529
1541
|
changed.has('withinCollection')
|
|
1530
1542
|
) {
|
|
@@ -1573,6 +1585,7 @@ export class CollectionBrowser
|
|
|
1573
1585
|
|
|
1574
1586
|
if (
|
|
1575
1587
|
changed.has('baseQuery') ||
|
|
1588
|
+
changed.has('identifiers') ||
|
|
1576
1589
|
changed.has('minSelectedDate') ||
|
|
1577
1590
|
changed.has('maxSelectedDate') ||
|
|
1578
1591
|
changed.has('selectedFacets') ||
|
|
@@ -1605,6 +1618,7 @@ export class CollectionBrowser
|
|
|
1605
1618
|
|
|
1606
1619
|
if (
|
|
1607
1620
|
changed.has('baseQuery') ||
|
|
1621
|
+
changed.has('identifiers') ||
|
|
1608
1622
|
changed.has('searchType') ||
|
|
1609
1623
|
changed.has('selectedTitleFilter') ||
|
|
1610
1624
|
changed.has('selectedCreatorFilter') ||
|
|
@@ -1,296 +1,296 @@
|
|
|
1
|
-
import {
|
|
2
|
-
css,
|
|
3
|
-
html,
|
|
4
|
-
LitElement,
|
|
5
|
-
TemplateResult,
|
|
6
|
-
CSSResultGroup,
|
|
7
|
-
nothing,
|
|
8
|
-
} from 'lit';
|
|
9
|
-
import { customElement, property } from 'lit/decorators.js';
|
|
10
|
-
import eyeIcon from '../assets/img/icons/eye';
|
|
11
|
-
import eyeClosedIcon from '../assets/img/icons/eye-closed';
|
|
12
|
-
import type {
|
|
13
|
-
FacetOption,
|
|
14
|
-
FacetBucket,
|
|
15
|
-
FacetEventDetails,
|
|
16
|
-
FacetState,
|
|
17
|
-
} from '../models';
|
|
18
|
-
import type { CollectionTitles } from '../data-source/models';
|
|
19
|
-
import { srOnlyStyle } from '../styles/sr-only';
|
|
20
|
-
|
|
21
|
-
@customElement('facet-row')
|
|
22
|
-
export class FacetRow extends LitElement {
|
|
23
|
-
//
|
|
24
|
-
// UI STATE
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
/** The name of the facet group to which this facet belongs (e.g., "mediatype") */
|
|
28
|
-
@property({ type: String }) facetType?: FacetOption;
|
|
29
|
-
|
|
30
|
-
/** The facet bucket containing details about the state, count, and key for this row */
|
|
31
|
-
@property({ type: Object }) bucket?: FacetBucket;
|
|
32
|
-
|
|
33
|
-
/** The collection name cache for converting collection identifiers to titles */
|
|
34
|
-
@property({ type: Object })
|
|
35
|
-
collectionTitles?: CollectionTitles;
|
|
36
|
-
|
|
37
|
-
//
|
|
38
|
-
// COMPONENT LIFECYCLE METHODS
|
|
39
|
-
//
|
|
40
|
-
|
|
41
|
-
render() {
|
|
42
|
-
return html`${this.facetRowTemplate}`;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
//
|
|
46
|
-
// TEMPLATE GETTERS
|
|
47
|
-
//
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Template for the full facet row, including the positive/negative checks,
|
|
51
|
-
* the display name, and the count.
|
|
52
|
-
*/
|
|
53
|
-
private get facetRowTemplate(): TemplateResult | typeof nothing {
|
|
54
|
-
const { bucket, facetType } = this;
|
|
55
|
-
if (!bucket || !facetType) return nothing;
|
|
56
|
-
|
|
57
|
-
const showOnlyCheckboxId = `${facetType}:${bucket.key}-show-only`;
|
|
58
|
-
const negativeCheckboxId = `${facetType}:${bucket.key}-negative`;
|
|
59
|
-
|
|
60
|
-
const extraNoteSpan = bucket.extraNote
|
|
61
|
-
? html`<span class="facet-note">${bucket.extraNote}</span>`
|
|
62
|
-
: nothing;
|
|
63
|
-
|
|
64
|
-
// For collections, we render the collection title as a link.
|
|
65
|
-
// For other facet types, we just have a static value to use.
|
|
66
|
-
const bucketTextDisplay =
|
|
67
|
-
facetType !== 'collection'
|
|
68
|
-
? html`${bucket.displayText ?? bucket.key} ${extraNoteSpan}`
|
|
69
|
-
: html`<a href="/details/${bucket.key}">
|
|
70
|
-
${this.collectionTitles?.get(bucket.key) ?? bucket.key}
|
|
71
|
-
</a> `;
|
|
72
|
-
|
|
73
|
-
const facetHidden = bucket.state === 'hidden';
|
|
74
|
-
const facetSelected = bucket.state === 'selected';
|
|
75
|
-
|
|
76
|
-
const titleText = `${facetType}: ${bucket.displayText ?? bucket.key}`;
|
|
77
|
-
const onlyShowText = facetSelected
|
|
78
|
-
? `Show all ${facetType}s`
|
|
79
|
-
: `Only show ${titleText}`;
|
|
80
|
-
const hideText = `Hide ${titleText}`;
|
|
81
|
-
const unhideText = `Unhide ${titleText}`;
|
|
82
|
-
const showHideText = facetHidden ? unhideText : hideText;
|
|
83
|
-
const ariaLabel = `${titleText}, ${bucket.count} results`;
|
|
84
|
-
|
|
85
|
-
// Added data-testid for Playwright testing
|
|
86
|
-
return html`
|
|
87
|
-
<div class="facet-row-container">
|
|
88
|
-
<div class="facet-checkboxes">
|
|
89
|
-
<input
|
|
90
|
-
type="checkbox"
|
|
91
|
-
.name=${facetType}
|
|
92
|
-
.value=${bucket.key}
|
|
93
|
-
@click=${(e: Event) => {
|
|
94
|
-
this.facetClicked(e, false);
|
|
95
|
-
}}
|
|
96
|
-
.checked=${facetSelected}
|
|
97
|
-
class="select-facet-checkbox"
|
|
98
|
-
title=${onlyShowText}
|
|
99
|
-
id=${showOnlyCheckboxId}
|
|
100
|
-
data-testid=${showOnlyCheckboxId}
|
|
101
|
-
/>
|
|
102
|
-
<div class="hide-facet-container">
|
|
103
|
-
<input
|
|
104
|
-
type="checkbox"
|
|
105
|
-
id=${negativeCheckboxId}
|
|
106
|
-
.name=${facetType}
|
|
107
|
-
.value=${bucket.key}
|
|
108
|
-
@click=${(e: Event) => {
|
|
109
|
-
this.facetClicked(e, true);
|
|
110
|
-
}}
|
|
111
|
-
.checked=${facetHidden}
|
|
112
|
-
class="hide-facet-checkbox"
|
|
113
|
-
/>
|
|
114
|
-
<label
|
|
115
|
-
for=${negativeCheckboxId}
|
|
116
|
-
class="hide-facet-icon${facetHidden ? ' active' : ''}"
|
|
117
|
-
title=${showHideText}
|
|
118
|
-
data-testid=${negativeCheckboxId}
|
|
119
|
-
>
|
|
120
|
-
<span class="sr-only">${showHideText}</span>
|
|
121
|
-
<span class="eye eye-open">${eyeIcon}</span>
|
|
122
|
-
<span class="eye eye-closed">${eyeClosedIcon}</span>
|
|
123
|
-
</label>
|
|
124
|
-
</div>
|
|
125
|
-
</div>
|
|
126
|
-
<label
|
|
127
|
-
for=${showOnlyCheckboxId}
|
|
128
|
-
class="facet-info-display"
|
|
129
|
-
title=${onlyShowText}
|
|
130
|
-
aria-label=${ariaLabel}
|
|
131
|
-
>
|
|
132
|
-
<div class="facet-title">${bucketTextDisplay}</div>
|
|
133
|
-
<div class="facet-count">${bucket.count.toLocaleString()}</div>
|
|
134
|
-
</label>
|
|
135
|
-
</div>
|
|
136
|
-
`;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
//
|
|
140
|
-
// EVENT HANDLERS & DISPATCHERS
|
|
141
|
-
//
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Handler for whenever this facet is clicked & its state changes
|
|
145
|
-
*/
|
|
146
|
-
private facetClicked(e: Event, negative: boolean) {
|
|
147
|
-
const { bucket, facetType } = this;
|
|
148
|
-
if (!bucket || !facetType) return;
|
|
149
|
-
|
|
150
|
-
const target = e.target as HTMLInputElement;
|
|
151
|
-
const { checked } = target;
|
|
152
|
-
this.bucket = {
|
|
153
|
-
...bucket,
|
|
154
|
-
state: FacetRow.getFacetState(checked, negative),
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
this.dispatchFacetClickEvent({
|
|
158
|
-
facetType,
|
|
159
|
-
bucket: this.bucket,
|
|
160
|
-
negative,
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Emits a `facetClick` event with details about this facet & its current state
|
|
166
|
-
*/
|
|
167
|
-
private dispatchFacetClickEvent(detail: FacetEventDetails) {
|
|
168
|
-
const event = new CustomEvent<FacetEventDetails>('facetClick', {
|
|
169
|
-
detail,
|
|
170
|
-
});
|
|
171
|
-
this.dispatchEvent(event);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
//
|
|
175
|
-
// OTHER METHODS
|
|
176
|
-
//
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Returns the composed facet state corresponding to a positive or negative facet's checked state
|
|
180
|
-
*/
|
|
181
|
-
static getFacetState(checked: boolean, negative: boolean): FacetState {
|
|
182
|
-
let state: FacetState;
|
|
183
|
-
if (checked) {
|
|
184
|
-
state = negative ? 'hidden' : 'selected';
|
|
185
|
-
} else {
|
|
186
|
-
state = 'none';
|
|
187
|
-
}
|
|
188
|
-
return state;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
//
|
|
192
|
-
// STYLES
|
|
193
|
-
//
|
|
194
|
-
|
|
195
|
-
static get styles(): CSSResultGroup {
|
|
196
|
-
const facetRowBorderTop = css`var(--facet-row-border-top, 1px solid transparent)`;
|
|
197
|
-
const facetRowBorderBottom = css`var(--facet-row-border-bottom, 1px solid transparent)`;
|
|
198
|
-
const checkboxHeight = css`15px`;
|
|
199
|
-
|
|
200
|
-
const ownCss = css`
|
|
201
|
-
.facet-checkboxes {
|
|
202
|
-
margin: 0 5px 0 0;
|
|
203
|
-
display: flex;
|
|
204
|
-
height: ${checkboxHeight};
|
|
205
|
-
}
|
|
206
|
-
.facet-checkboxes input:first-child {
|
|
207
|
-
margin-right: 5px;
|
|
208
|
-
}
|
|
209
|
-
.facet-checkboxes input {
|
|
210
|
-
height: ${checkboxHeight};
|
|
211
|
-
width: ${checkboxHeight};
|
|
212
|
-
margin: 0;
|
|
213
|
-
}
|
|
214
|
-
.facet-row-container {
|
|
215
|
-
display: flex;
|
|
216
|
-
font-weight: 500;
|
|
217
|
-
font-size: 1.2rem;
|
|
218
|
-
margin: 0 auto;
|
|
219
|
-
padding: 0.25rem 0;
|
|
220
|
-
height: auto;
|
|
221
|
-
border-top: ${facetRowBorderTop};
|
|
222
|
-
border-bottom: ${facetRowBorderBottom};
|
|
223
|
-
}
|
|
224
|
-
.facet-info-display {
|
|
225
|
-
display: flex;
|
|
226
|
-
flex: 1 1 0%;
|
|
227
|
-
cursor: pointer;
|
|
228
|
-
flex-wrap: wrap;
|
|
229
|
-
}
|
|
230
|
-
.facet-title {
|
|
231
|
-
word-break: break-word;
|
|
232
|
-
display: inline-block;
|
|
233
|
-
flex: 1 1 0%;
|
|
234
|
-
}
|
|
235
|
-
.facet-note {
|
|
236
|
-
color: #bbb;
|
|
237
|
-
}
|
|
238
|
-
.facet-count {
|
|
239
|
-
text-align: right;
|
|
240
|
-
}
|
|
241
|
-
.select-facet-checkbox {
|
|
242
|
-
cursor: pointer;
|
|
243
|
-
display: inline-block;
|
|
244
|
-
}
|
|
245
|
-
.hide-facet-checkbox {
|
|
246
|
-
position: absolute;
|
|
247
|
-
clip: rect(0, 0, 0, 0);
|
|
248
|
-
pointer-events: none;
|
|
249
|
-
}
|
|
250
|
-
.hide-facet-checkbox:focus-visible + .hide-facet-icon {
|
|
251
|
-
outline-style: auto;
|
|
252
|
-
outline-offset: 2px;
|
|
253
|
-
}
|
|
254
|
-
.hide-facet-icon {
|
|
255
|
-
width: ${checkboxHeight};
|
|
256
|
-
height: ${checkboxHeight};
|
|
257
|
-
cursor: pointer;
|
|
258
|
-
display: flex;
|
|
259
|
-
}
|
|
260
|
-
.eye {
|
|
261
|
-
width: ${checkboxHeight};
|
|
262
|
-
height: ${checkboxHeight};
|
|
263
|
-
opacity: 0.3;
|
|
264
|
-
}
|
|
265
|
-
.hide-facet-icon:hover .eye,
|
|
266
|
-
.active .eye {
|
|
267
|
-
opacity: 1;
|
|
268
|
-
}
|
|
269
|
-
.hide-facet-icon:hover .eye-open,
|
|
270
|
-
.hide-facet-icon .eye-closed {
|
|
271
|
-
display: none;
|
|
272
|
-
}
|
|
273
|
-
.hide-facet-icon:hover .eye-closed,
|
|
274
|
-
.hide-facet-icon.active .eye-closed {
|
|
275
|
-
display: inline;
|
|
276
|
-
}
|
|
277
|
-
.hide-facet-icon.active .eye-open {
|
|
278
|
-
display: none;
|
|
279
|
-
}
|
|
280
|
-
.sorting-icon {
|
|
281
|
-
cursor: pointer;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
a:link,
|
|
285
|
-
a:visited {
|
|
286
|
-
text-decoration: none;
|
|
287
|
-
color: var(--ia-theme-link-color, #4b64ff);
|
|
288
|
-
}
|
|
289
|
-
a:hover {
|
|
290
|
-
text-decoration: underline;
|
|
291
|
-
}
|
|
292
|
-
`;
|
|
293
|
-
|
|
294
|
-
return [srOnlyStyle, ownCss];
|
|
295
|
-
}
|
|
296
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
css,
|
|
3
|
+
html,
|
|
4
|
+
LitElement,
|
|
5
|
+
TemplateResult,
|
|
6
|
+
CSSResultGroup,
|
|
7
|
+
nothing,
|
|
8
|
+
} from 'lit';
|
|
9
|
+
import { customElement, property } from 'lit/decorators.js';
|
|
10
|
+
import eyeIcon from '../assets/img/icons/eye';
|
|
11
|
+
import eyeClosedIcon from '../assets/img/icons/eye-closed';
|
|
12
|
+
import type {
|
|
13
|
+
FacetOption,
|
|
14
|
+
FacetBucket,
|
|
15
|
+
FacetEventDetails,
|
|
16
|
+
FacetState,
|
|
17
|
+
} from '../models';
|
|
18
|
+
import type { CollectionTitles } from '../data-source/models';
|
|
19
|
+
import { srOnlyStyle } from '../styles/sr-only';
|
|
20
|
+
|
|
21
|
+
@customElement('facet-row')
|
|
22
|
+
export class FacetRow extends LitElement {
|
|
23
|
+
//
|
|
24
|
+
// UI STATE
|
|
25
|
+
//
|
|
26
|
+
|
|
27
|
+
/** The name of the facet group to which this facet belongs (e.g., "mediatype") */
|
|
28
|
+
@property({ type: String }) facetType?: FacetOption;
|
|
29
|
+
|
|
30
|
+
/** The facet bucket containing details about the state, count, and key for this row */
|
|
31
|
+
@property({ type: Object }) bucket?: FacetBucket;
|
|
32
|
+
|
|
33
|
+
/** The collection name cache for converting collection identifiers to titles */
|
|
34
|
+
@property({ type: Object })
|
|
35
|
+
collectionTitles?: CollectionTitles;
|
|
36
|
+
|
|
37
|
+
//
|
|
38
|
+
// COMPONENT LIFECYCLE METHODS
|
|
39
|
+
//
|
|
40
|
+
|
|
41
|
+
render() {
|
|
42
|
+
return html`${this.facetRowTemplate}`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
//
|
|
46
|
+
// TEMPLATE GETTERS
|
|
47
|
+
//
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Template for the full facet row, including the positive/negative checks,
|
|
51
|
+
* the display name, and the count.
|
|
52
|
+
*/
|
|
53
|
+
private get facetRowTemplate(): TemplateResult | typeof nothing {
|
|
54
|
+
const { bucket, facetType } = this;
|
|
55
|
+
if (!bucket || !facetType) return nothing;
|
|
56
|
+
|
|
57
|
+
const showOnlyCheckboxId = `${facetType}:${bucket.key}-show-only`;
|
|
58
|
+
const negativeCheckboxId = `${facetType}:${bucket.key}-negative`;
|
|
59
|
+
|
|
60
|
+
const extraNoteSpan = bucket.extraNote
|
|
61
|
+
? html`<span class="facet-note">${bucket.extraNote}</span>`
|
|
62
|
+
: nothing;
|
|
63
|
+
|
|
64
|
+
// For collections, we render the collection title as a link.
|
|
65
|
+
// For other facet types, we just have a static value to use.
|
|
66
|
+
const bucketTextDisplay =
|
|
67
|
+
facetType !== 'collection'
|
|
68
|
+
? html`${bucket.displayText ?? bucket.key} ${extraNoteSpan}`
|
|
69
|
+
: html`<a href="/details/${bucket.key}">
|
|
70
|
+
${this.collectionTitles?.get(bucket.key) ?? bucket.key}
|
|
71
|
+
</a> `;
|
|
72
|
+
|
|
73
|
+
const facetHidden = bucket.state === 'hidden';
|
|
74
|
+
const facetSelected = bucket.state === 'selected';
|
|
75
|
+
|
|
76
|
+
const titleText = `${facetType}: ${bucket.displayText ?? bucket.key}`;
|
|
77
|
+
const onlyShowText = facetSelected
|
|
78
|
+
? `Show all ${facetType}s`
|
|
79
|
+
: `Only show ${titleText}`;
|
|
80
|
+
const hideText = `Hide ${titleText}`;
|
|
81
|
+
const unhideText = `Unhide ${titleText}`;
|
|
82
|
+
const showHideText = facetHidden ? unhideText : hideText;
|
|
83
|
+
const ariaLabel = `${titleText}, ${bucket.count} results`;
|
|
84
|
+
|
|
85
|
+
// Added data-testid for Playwright testing
|
|
86
|
+
return html`
|
|
87
|
+
<div class="facet-row-container">
|
|
88
|
+
<div class="facet-checkboxes">
|
|
89
|
+
<input
|
|
90
|
+
type="checkbox"
|
|
91
|
+
.name=${facetType}
|
|
92
|
+
.value=${bucket.key}
|
|
93
|
+
@click=${(e: Event) => {
|
|
94
|
+
this.facetClicked(e, false);
|
|
95
|
+
}}
|
|
96
|
+
.checked=${facetSelected}
|
|
97
|
+
class="select-facet-checkbox"
|
|
98
|
+
title=${onlyShowText}
|
|
99
|
+
id=${showOnlyCheckboxId}
|
|
100
|
+
data-testid=${showOnlyCheckboxId}
|
|
101
|
+
/>
|
|
102
|
+
<div class="hide-facet-container">
|
|
103
|
+
<input
|
|
104
|
+
type="checkbox"
|
|
105
|
+
id=${negativeCheckboxId}
|
|
106
|
+
.name=${facetType}
|
|
107
|
+
.value=${bucket.key}
|
|
108
|
+
@click=${(e: Event) => {
|
|
109
|
+
this.facetClicked(e, true);
|
|
110
|
+
}}
|
|
111
|
+
.checked=${facetHidden}
|
|
112
|
+
class="hide-facet-checkbox"
|
|
113
|
+
/>
|
|
114
|
+
<label
|
|
115
|
+
for=${negativeCheckboxId}
|
|
116
|
+
class="hide-facet-icon${facetHidden ? ' active' : ''}"
|
|
117
|
+
title=${showHideText}
|
|
118
|
+
data-testid=${negativeCheckboxId}
|
|
119
|
+
>
|
|
120
|
+
<span class="sr-only">${showHideText}</span>
|
|
121
|
+
<span class="eye eye-open">${eyeIcon}</span>
|
|
122
|
+
<span class="eye eye-closed">${eyeClosedIcon}</span>
|
|
123
|
+
</label>
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
<label
|
|
127
|
+
for=${showOnlyCheckboxId}
|
|
128
|
+
class="facet-info-display"
|
|
129
|
+
title=${onlyShowText}
|
|
130
|
+
aria-label=${ariaLabel}
|
|
131
|
+
>
|
|
132
|
+
<div class="facet-title">${bucketTextDisplay}</div>
|
|
133
|
+
<div class="facet-count">${bucket.count.toLocaleString()}</div>
|
|
134
|
+
</label>
|
|
135
|
+
</div>
|
|
136
|
+
`;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
//
|
|
140
|
+
// EVENT HANDLERS & DISPATCHERS
|
|
141
|
+
//
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Handler for whenever this facet is clicked & its state changes
|
|
145
|
+
*/
|
|
146
|
+
private facetClicked(e: Event, negative: boolean) {
|
|
147
|
+
const { bucket, facetType } = this;
|
|
148
|
+
if (!bucket || !facetType) return;
|
|
149
|
+
|
|
150
|
+
const target = e.target as HTMLInputElement;
|
|
151
|
+
const { checked } = target;
|
|
152
|
+
this.bucket = {
|
|
153
|
+
...bucket,
|
|
154
|
+
state: FacetRow.getFacetState(checked, negative),
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
this.dispatchFacetClickEvent({
|
|
158
|
+
facetType,
|
|
159
|
+
bucket: this.bucket,
|
|
160
|
+
negative,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Emits a `facetClick` event with details about this facet & its current state
|
|
166
|
+
*/
|
|
167
|
+
private dispatchFacetClickEvent(detail: FacetEventDetails) {
|
|
168
|
+
const event = new CustomEvent<FacetEventDetails>('facetClick', {
|
|
169
|
+
detail,
|
|
170
|
+
});
|
|
171
|
+
this.dispatchEvent(event);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
//
|
|
175
|
+
// OTHER METHODS
|
|
176
|
+
//
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Returns the composed facet state corresponding to a positive or negative facet's checked state
|
|
180
|
+
*/
|
|
181
|
+
static getFacetState(checked: boolean, negative: boolean): FacetState {
|
|
182
|
+
let state: FacetState;
|
|
183
|
+
if (checked) {
|
|
184
|
+
state = negative ? 'hidden' : 'selected';
|
|
185
|
+
} else {
|
|
186
|
+
state = 'none';
|
|
187
|
+
}
|
|
188
|
+
return state;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
//
|
|
192
|
+
// STYLES
|
|
193
|
+
//
|
|
194
|
+
|
|
195
|
+
static get styles(): CSSResultGroup {
|
|
196
|
+
const facetRowBorderTop = css`var(--facet-row-border-top, 1px solid transparent)`;
|
|
197
|
+
const facetRowBorderBottom = css`var(--facet-row-border-bottom, 1px solid transparent)`;
|
|
198
|
+
const checkboxHeight = css`15px`;
|
|
199
|
+
|
|
200
|
+
const ownCss = css`
|
|
201
|
+
.facet-checkboxes {
|
|
202
|
+
margin: 0 5px 0 0;
|
|
203
|
+
display: flex;
|
|
204
|
+
height: ${checkboxHeight};
|
|
205
|
+
}
|
|
206
|
+
.facet-checkboxes input:first-child {
|
|
207
|
+
margin-right: 5px;
|
|
208
|
+
}
|
|
209
|
+
.facet-checkboxes input {
|
|
210
|
+
height: ${checkboxHeight};
|
|
211
|
+
width: ${checkboxHeight};
|
|
212
|
+
margin: 0;
|
|
213
|
+
}
|
|
214
|
+
.facet-row-container {
|
|
215
|
+
display: flex;
|
|
216
|
+
font-weight: 500;
|
|
217
|
+
font-size: 1.2rem;
|
|
218
|
+
margin: 0 auto;
|
|
219
|
+
padding: 0.25rem 0;
|
|
220
|
+
height: auto;
|
|
221
|
+
border-top: ${facetRowBorderTop};
|
|
222
|
+
border-bottom: ${facetRowBorderBottom};
|
|
223
|
+
}
|
|
224
|
+
.facet-info-display {
|
|
225
|
+
display: flex;
|
|
226
|
+
flex: 1 1 0%;
|
|
227
|
+
cursor: pointer;
|
|
228
|
+
flex-wrap: wrap;
|
|
229
|
+
}
|
|
230
|
+
.facet-title {
|
|
231
|
+
word-break: break-word;
|
|
232
|
+
display: inline-block;
|
|
233
|
+
flex: 1 1 0%;
|
|
234
|
+
}
|
|
235
|
+
.facet-note {
|
|
236
|
+
color: #bbb;
|
|
237
|
+
}
|
|
238
|
+
.facet-count {
|
|
239
|
+
text-align: right;
|
|
240
|
+
}
|
|
241
|
+
.select-facet-checkbox {
|
|
242
|
+
cursor: pointer;
|
|
243
|
+
display: inline-block;
|
|
244
|
+
}
|
|
245
|
+
.hide-facet-checkbox {
|
|
246
|
+
position: absolute;
|
|
247
|
+
clip: rect(0, 0, 0, 0);
|
|
248
|
+
pointer-events: none;
|
|
249
|
+
}
|
|
250
|
+
.hide-facet-checkbox:focus-visible + .hide-facet-icon {
|
|
251
|
+
outline-style: auto;
|
|
252
|
+
outline-offset: 2px;
|
|
253
|
+
}
|
|
254
|
+
.hide-facet-icon {
|
|
255
|
+
width: ${checkboxHeight};
|
|
256
|
+
height: ${checkboxHeight};
|
|
257
|
+
cursor: pointer;
|
|
258
|
+
display: flex;
|
|
259
|
+
}
|
|
260
|
+
.eye {
|
|
261
|
+
width: ${checkboxHeight};
|
|
262
|
+
height: ${checkboxHeight};
|
|
263
|
+
opacity: 0.3;
|
|
264
|
+
}
|
|
265
|
+
.hide-facet-icon:hover .eye,
|
|
266
|
+
.active .eye {
|
|
267
|
+
opacity: 1;
|
|
268
|
+
}
|
|
269
|
+
.hide-facet-icon:hover .eye-open,
|
|
270
|
+
.hide-facet-icon .eye-closed {
|
|
271
|
+
display: none;
|
|
272
|
+
}
|
|
273
|
+
.hide-facet-icon:hover .eye-closed,
|
|
274
|
+
.hide-facet-icon.active .eye-closed {
|
|
275
|
+
display: inline;
|
|
276
|
+
}
|
|
277
|
+
.hide-facet-icon.active .eye-open {
|
|
278
|
+
display: none;
|
|
279
|
+
}
|
|
280
|
+
.sorting-icon {
|
|
281
|
+
cursor: pointer;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
a:link,
|
|
285
|
+
a:visited {
|
|
286
|
+
text-decoration: none;
|
|
287
|
+
color: var(--ia-theme-link-color, #4b64ff);
|
|
288
|
+
}
|
|
289
|
+
a:hover {
|
|
290
|
+
text-decoration: underline;
|
|
291
|
+
}
|
|
292
|
+
`;
|
|
293
|
+
|
|
294
|
+
return [srOnlyStyle, ownCss];
|
|
295
|
+
}
|
|
296
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Maximum number of aggregations to include in the More... facet dialogs.
|
|
3
|
-
*/
|
|
4
|
-
export const MORE_FACETS__MAX_AGGREGATIONS = 10000;
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Default number of facets to show per page of the More... facet dialogs.
|
|
8
|
-
* Can be overridden via component property.
|
|
9
|
-
*/
|
|
10
|
-
export const MORE_FACETS__DEFAULT_PAGE_SIZE = 35;
|
|
1
|
+
/**
|
|
2
|
+
* Maximum number of aggregations to include in the More... facet dialogs.
|
|
3
|
+
*/
|
|
4
|
+
export const MORE_FACETS__MAX_AGGREGATIONS = 10000;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Default number of facets to show per page of the More... facet dialogs.
|
|
8
|
+
* Can be overridden via component property.
|
|
9
|
+
*/
|
|
10
|
+
export const MORE_FACETS__DEFAULT_PAGE_SIZE = 35;
|