@internetarchive/collection-browser 1.14.9-alpha1 → 1.14.9-alpha10
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.d.ts +1 -0
- package/dist/src/app-root.js +154 -82
- package/dist/src/app-root.js.map +1 -1
- package/dist/src/collection-browser.d.ts +2 -2
- package/dist/src/collection-browser.js +23 -18
- package/dist/src/collection-browser.js.map +1 -1
- package/dist/src/collection-facets/facet-row.d.ts +30 -0
- package/dist/src/collection-facets/facet-row.js +245 -0
- package/dist/src/collection-facets/facet-row.js.map +1 -0
- package/dist/src/collection-facets/facets-template.d.ts +1 -4
- package/dist/src/collection-facets/facets-template.js +40 -182
- package/dist/src/collection-facets/facets-template.js.map +1 -1
- package/dist/src/models.d.ts +18 -2
- package/dist/src/models.js.map +1 -1
- package/dist/test/collection-browser.test.js +36 -4
- package/dist/test/collection-browser.test.js.map +1 -1
- package/dist/test/collection-facets/facet-row.test.d.ts +1 -0
- package/dist/test/collection-facets/facet-row.test.js +235 -0
- package/dist/test/collection-facets/facet-row.test.js.map +1 -0
- package/dist/test/collection-facets/facets-template.test.js +65 -96
- package/dist/test/collection-facets/facets-template.test.js.map +1 -1
- package/dist/test/collection-facets.test.js +39 -70
- package/dist/test/collection-facets.test.js.map +1 -1
- package/package.json +2 -2
- package/src/app-root.ts +159 -82
- package/src/collection-browser.ts +23 -20
- package/src/collection-facets/facet-row.ts +274 -0
- package/src/collection-facets/facets-template.ts +49 -196
- package/src/models.ts +18 -2
- package/test/collection-browser.test.ts +36 -4
- package/test/collection-facets/facet-row.test.ts +328 -0
- package/test/collection-facets/facets-template.test.ts +72 -110
- package/test/collection-facets.test.ts +69 -101
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { LitElement, TemplateResult, CSSResultGroup } from 'lit';
|
|
2
|
+
import type { CollectionNameCacheInterface } from '@internetarchive/collection-name-cache';
|
|
3
|
+
import type { FacetOption, FacetBucket, FacetState } from '../models';
|
|
4
|
+
export declare class FacetRow extends LitElement {
|
|
5
|
+
/** The name of the facet group to which this facet belongs (e.g., "mediatype") */
|
|
6
|
+
facetType?: FacetOption;
|
|
7
|
+
/** The facet bucket containing details about the state, count, and key for this row */
|
|
8
|
+
bucket?: FacetBucket;
|
|
9
|
+
/** The collection name cache for converting collection identifiers to titles */
|
|
10
|
+
collectionNameCache?: CollectionNameCacheInterface;
|
|
11
|
+
render(): TemplateResult<1>;
|
|
12
|
+
/**
|
|
13
|
+
* Template for the full facet row, including the positive/negative checks,
|
|
14
|
+
* the display name, and the count.
|
|
15
|
+
*/
|
|
16
|
+
private get facetRowTemplate();
|
|
17
|
+
/**
|
|
18
|
+
* Handler for whenever this facet is clicked & its state changes
|
|
19
|
+
*/
|
|
20
|
+
private facetClicked;
|
|
21
|
+
/**
|
|
22
|
+
* Emits a `facetClick` event with details about this facet & its current state
|
|
23
|
+
*/
|
|
24
|
+
private dispatchFacetClickEvent;
|
|
25
|
+
/**
|
|
26
|
+
* Returns the composed facet state corresponding to a positive or negative facet's checked state
|
|
27
|
+
*/
|
|
28
|
+
static getFacetState(checked: boolean, negative: boolean): FacetState;
|
|
29
|
+
static get styles(): CSSResultGroup;
|
|
30
|
+
}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
var FacetRow_1;
|
|
2
|
+
import { __decorate } from "tslib";
|
|
3
|
+
import { css, html, LitElement, nothing, } from 'lit';
|
|
4
|
+
import { customElement, property } from 'lit/decorators.js';
|
|
5
|
+
import eyeIcon from '../assets/img/icons/eye';
|
|
6
|
+
import eyeClosedIcon from '../assets/img/icons/eye-closed';
|
|
7
|
+
let FacetRow = FacetRow_1 = class FacetRow extends LitElement {
|
|
8
|
+
//
|
|
9
|
+
// COMPONENT LIFECYCLE METHODS
|
|
10
|
+
//
|
|
11
|
+
render() {
|
|
12
|
+
return html `${this.facetRowTemplate}`;
|
|
13
|
+
}
|
|
14
|
+
//
|
|
15
|
+
// TEMPLATE GETTERS
|
|
16
|
+
//
|
|
17
|
+
/**
|
|
18
|
+
* Template for the full facet row, including the positive/negative checks,
|
|
19
|
+
* the display name, and the count.
|
|
20
|
+
*/
|
|
21
|
+
get facetRowTemplate() {
|
|
22
|
+
var _a, _b;
|
|
23
|
+
const { bucket, facetType } = this;
|
|
24
|
+
if (!bucket || !facetType)
|
|
25
|
+
return nothing;
|
|
26
|
+
const showOnlyCheckboxId = `${facetType}:${bucket.key}-show-only`;
|
|
27
|
+
const negativeCheckboxId = `${facetType}:${bucket.key}-negative`;
|
|
28
|
+
// For collections, we need to asynchronously load the collection name
|
|
29
|
+
// so we use the `async-collection-name` widget.
|
|
30
|
+
// For other facet types, we just have a static value to use.
|
|
31
|
+
const bucketTextDisplay = facetType !== 'collection'
|
|
32
|
+
? html `${(_a = bucket.displayText) !== null && _a !== void 0 ? _a : bucket.key}`
|
|
33
|
+
: html `<a href="/details/${bucket.key}">
|
|
34
|
+
<async-collection-name
|
|
35
|
+
.collectionNameCache=${this.collectionNameCache}
|
|
36
|
+
.identifier=${bucket.key}
|
|
37
|
+
placeholder="-"
|
|
38
|
+
></async-collection-name>
|
|
39
|
+
</a> `;
|
|
40
|
+
const facetHidden = bucket.state === 'hidden';
|
|
41
|
+
const facetSelected = bucket.state === 'selected';
|
|
42
|
+
const titleText = `${facetType}: ${(_b = bucket.displayText) !== null && _b !== void 0 ? _b : bucket.key}`;
|
|
43
|
+
const onlyShowText = facetSelected
|
|
44
|
+
? `Show all ${facetType}s`
|
|
45
|
+
: `Only show ${titleText}`;
|
|
46
|
+
const hideText = `Hide ${titleText}`;
|
|
47
|
+
const unhideText = `Unhide ${titleText}`;
|
|
48
|
+
const showHideText = facetHidden ? unhideText : hideText;
|
|
49
|
+
const ariaLabel = `${titleText}, ${bucket.count} results`;
|
|
50
|
+
return html `
|
|
51
|
+
<div class="facet-row-container">
|
|
52
|
+
<div class="facet-checkboxes">
|
|
53
|
+
<input
|
|
54
|
+
type="checkbox"
|
|
55
|
+
.name=${facetType}
|
|
56
|
+
.value=${bucket.key}
|
|
57
|
+
@click=${(e) => {
|
|
58
|
+
this.facetClicked(e, false);
|
|
59
|
+
}}
|
|
60
|
+
.checked=${facetSelected}
|
|
61
|
+
class="select-facet-checkbox"
|
|
62
|
+
title=${onlyShowText}
|
|
63
|
+
id=${showOnlyCheckboxId}
|
|
64
|
+
/>
|
|
65
|
+
<input
|
|
66
|
+
type="checkbox"
|
|
67
|
+
id=${negativeCheckboxId}
|
|
68
|
+
.name=${facetType}
|
|
69
|
+
.value=${bucket.key}
|
|
70
|
+
@click=${(e) => {
|
|
71
|
+
this.facetClicked(e, true);
|
|
72
|
+
}}
|
|
73
|
+
.checked=${facetHidden}
|
|
74
|
+
class="hide-facet-checkbox"
|
|
75
|
+
/>
|
|
76
|
+
<label
|
|
77
|
+
for=${negativeCheckboxId}
|
|
78
|
+
class="hide-facet-icon${facetHidden ? ' active' : ''}"
|
|
79
|
+
title=${showHideText}
|
|
80
|
+
>
|
|
81
|
+
<span class="eye">${eyeIcon}</span>
|
|
82
|
+
<span class="eye-closed">${eyeClosedIcon}</span>
|
|
83
|
+
</label>
|
|
84
|
+
</div>
|
|
85
|
+
<label
|
|
86
|
+
for=${showOnlyCheckboxId}
|
|
87
|
+
class="facet-info-display"
|
|
88
|
+
title=${onlyShowText}
|
|
89
|
+
aria-label=${ariaLabel}
|
|
90
|
+
>
|
|
91
|
+
<div class="facet-title">${bucketTextDisplay}</div>
|
|
92
|
+
<div class="facet-count">${bucket.count.toLocaleString()}</div>
|
|
93
|
+
</label>
|
|
94
|
+
</div>
|
|
95
|
+
`;
|
|
96
|
+
}
|
|
97
|
+
//
|
|
98
|
+
// EVENT HANDLERS & DISPATCHERS
|
|
99
|
+
//
|
|
100
|
+
/**
|
|
101
|
+
* Handler for whenever this facet is clicked & its state changes
|
|
102
|
+
*/
|
|
103
|
+
facetClicked(e, negative) {
|
|
104
|
+
const { bucket, facetType } = this;
|
|
105
|
+
if (!bucket || !facetType)
|
|
106
|
+
return;
|
|
107
|
+
const target = e.target;
|
|
108
|
+
const { checked } = target;
|
|
109
|
+
bucket.state = FacetRow_1.getFacetState(checked, negative);
|
|
110
|
+
this.dispatchFacetClickEvent({
|
|
111
|
+
facetType,
|
|
112
|
+
bucket,
|
|
113
|
+
negative,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Emits a `facetClick` event with details about this facet & its current state
|
|
118
|
+
*/
|
|
119
|
+
dispatchFacetClickEvent(detail) {
|
|
120
|
+
const event = new CustomEvent('facetClick', {
|
|
121
|
+
detail,
|
|
122
|
+
});
|
|
123
|
+
this.dispatchEvent(event);
|
|
124
|
+
}
|
|
125
|
+
//
|
|
126
|
+
// OTHER METHODS
|
|
127
|
+
//
|
|
128
|
+
/**
|
|
129
|
+
* Returns the composed facet state corresponding to a positive or negative facet's checked state
|
|
130
|
+
*/
|
|
131
|
+
static getFacetState(checked, negative) {
|
|
132
|
+
let state;
|
|
133
|
+
if (checked) {
|
|
134
|
+
state = negative ? 'hidden' : 'selected';
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
state = 'none';
|
|
138
|
+
}
|
|
139
|
+
return state;
|
|
140
|
+
}
|
|
141
|
+
//
|
|
142
|
+
// STYLES
|
|
143
|
+
//
|
|
144
|
+
static get styles() {
|
|
145
|
+
const facetRowBorderTop = css `var(--facet-row-border-top, 1px solid transparent)`;
|
|
146
|
+
const facetRowBorderBottom = css `var(--facet-row-border-bottom, 1px solid transparent)`;
|
|
147
|
+
return css `
|
|
148
|
+
async-collection-name {
|
|
149
|
+
display: contents;
|
|
150
|
+
}
|
|
151
|
+
.facet-checkboxes {
|
|
152
|
+
margin: 0 5px 0 0;
|
|
153
|
+
display: flex;
|
|
154
|
+
height: 15px;
|
|
155
|
+
}
|
|
156
|
+
.facet-checkboxes input:first-child {
|
|
157
|
+
margin-right: 5px;
|
|
158
|
+
}
|
|
159
|
+
.facet-checkboxes input {
|
|
160
|
+
height: 15px;
|
|
161
|
+
width: 15px;
|
|
162
|
+
margin: 0;
|
|
163
|
+
}
|
|
164
|
+
.facet-row-container {
|
|
165
|
+
display: flex;
|
|
166
|
+
font-weight: 500;
|
|
167
|
+
font-size: 1.2rem;
|
|
168
|
+
margin: 2.5px auto;
|
|
169
|
+
height: auto;
|
|
170
|
+
border-top: ${facetRowBorderTop};
|
|
171
|
+
border-bottom: ${facetRowBorderBottom};
|
|
172
|
+
overflow: hidden;
|
|
173
|
+
}
|
|
174
|
+
.facet-info-display {
|
|
175
|
+
display: flex;
|
|
176
|
+
flex: 1 1 0%;
|
|
177
|
+
cursor: pointer;
|
|
178
|
+
flex-wrap: wrap;
|
|
179
|
+
}
|
|
180
|
+
.facet-title {
|
|
181
|
+
word-break: break-word;
|
|
182
|
+
display: inline-block;
|
|
183
|
+
flex: 1 1 0%;
|
|
184
|
+
}
|
|
185
|
+
.facet-count {
|
|
186
|
+
text-align: right;
|
|
187
|
+
}
|
|
188
|
+
.select-facet-checkbox {
|
|
189
|
+
cursor: pointer;
|
|
190
|
+
display: inline-block;
|
|
191
|
+
}
|
|
192
|
+
.hide-facet-checkbox {
|
|
193
|
+
display: none;
|
|
194
|
+
}
|
|
195
|
+
.hide-facet-icon {
|
|
196
|
+
width: 15px;
|
|
197
|
+
height: 15px;
|
|
198
|
+
cursor: pointer;
|
|
199
|
+
opacity: 0.3;
|
|
200
|
+
display: inline-block;
|
|
201
|
+
}
|
|
202
|
+
.hide-facet-icon:hover,
|
|
203
|
+
.active {
|
|
204
|
+
opacity: 1;
|
|
205
|
+
}
|
|
206
|
+
.hide-facet-icon:hover .eye,
|
|
207
|
+
.hide-facet-icon .eye-closed {
|
|
208
|
+
display: none;
|
|
209
|
+
}
|
|
210
|
+
.hide-facet-icon:hover .eye-closed,
|
|
211
|
+
.hide-facet-icon.active .eye-closed {
|
|
212
|
+
display: inline;
|
|
213
|
+
}
|
|
214
|
+
.hide-facet-icon.active .eye {
|
|
215
|
+
display: none;
|
|
216
|
+
}
|
|
217
|
+
.sorting-icon {
|
|
218
|
+
cursor: pointer;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
a:link,
|
|
222
|
+
a:visited {
|
|
223
|
+
text-decoration: none;
|
|
224
|
+
color: var(--ia-theme-link-color, #4b64ff);
|
|
225
|
+
}
|
|
226
|
+
a:hover {
|
|
227
|
+
text-decoration: underline;
|
|
228
|
+
}
|
|
229
|
+
`;
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
__decorate([
|
|
233
|
+
property({ type: String })
|
|
234
|
+
], FacetRow.prototype, "facetType", void 0);
|
|
235
|
+
__decorate([
|
|
236
|
+
property({ type: Object })
|
|
237
|
+
], FacetRow.prototype, "bucket", void 0);
|
|
238
|
+
__decorate([
|
|
239
|
+
property({ type: Object })
|
|
240
|
+
], FacetRow.prototype, "collectionNameCache", void 0);
|
|
241
|
+
FacetRow = FacetRow_1 = __decorate([
|
|
242
|
+
customElement('facet-row')
|
|
243
|
+
], FacetRow);
|
|
244
|
+
export { FacetRow };
|
|
245
|
+
//# sourceMappingURL=facet-row.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"facet-row.js","sourceRoot":"","sources":["../../../src/collection-facets/facet-row.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n css,\n html,\n LitElement,\n TemplateResult,\n CSSResultGroup,\n nothing,\n} from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport type { CollectionNameCacheInterface } from '@internetarchive/collection-name-cache';\nimport eyeIcon from '../assets/img/icons/eye';\nimport eyeClosedIcon from '../assets/img/icons/eye-closed';\nimport type {\n FacetOption,\n FacetBucket,\n FacetEventDetails,\n FacetState,\n} from '../models';\n\n@customElement('facet-row')\nexport class FacetRow extends LitElement {\n //\n // UI STATE\n //\n\n /** The name of the facet group to which this facet belongs (e.g., \"mediatype\") */\n @property({ type: String }) facetType?: FacetOption;\n\n /** The facet bucket containing details about the state, count, and key for this row */\n @property({ type: Object }) bucket?: FacetBucket;\n\n /** The collection name cache for converting collection identifiers to titles */\n @property({ type: Object })\n collectionNameCache?: CollectionNameCacheInterface;\n\n //\n // COMPONENT LIFECYCLE METHODS\n //\n\n render() {\n return html`${this.facetRowTemplate}`;\n }\n\n //\n // TEMPLATE GETTERS\n //\n\n /**\n * Template for the full facet row, including the positive/negative checks,\n * the display name, and the count.\n */\n private get facetRowTemplate(): TemplateResult | typeof nothing {\n const { bucket, facetType } = this;\n if (!bucket || !facetType) return nothing;\n\n const showOnlyCheckboxId = `${facetType}:${bucket.key}-show-only`;\n const negativeCheckboxId = `${facetType}:${bucket.key}-negative`;\n\n // For collections, we need to asynchronously load the collection name\n // so we use the `async-collection-name` widget.\n // For other facet types, we just have a static value to use.\n const bucketTextDisplay =\n facetType !== 'collection'\n ? html`${bucket.displayText ?? bucket.key}`\n : html`<a href=\"/details/${bucket.key}\">\n <async-collection-name\n .collectionNameCache=${this.collectionNameCache}\n .identifier=${bucket.key}\n placeholder=\"-\"\n ></async-collection-name>\n </a> `;\n\n const facetHidden = bucket.state === 'hidden';\n const facetSelected = bucket.state === 'selected';\n\n const titleText = `${facetType}: ${bucket.displayText ?? bucket.key}`;\n const onlyShowText = facetSelected\n ? `Show all ${facetType}s`\n : `Only show ${titleText}`;\n const hideText = `Hide ${titleText}`;\n const unhideText = `Unhide ${titleText}`;\n const showHideText = facetHidden ? unhideText : hideText;\n const ariaLabel = `${titleText}, ${bucket.count} results`;\n\n return html`\n <div class=\"facet-row-container\">\n <div class=\"facet-checkboxes\">\n <input\n type=\"checkbox\"\n .name=${facetType}\n .value=${bucket.key}\n @click=${(e: Event) => {\n this.facetClicked(e, false);\n }}\n .checked=${facetSelected}\n class=\"select-facet-checkbox\"\n title=${onlyShowText}\n id=${showOnlyCheckboxId}\n />\n <input\n type=\"checkbox\"\n id=${negativeCheckboxId}\n .name=${facetType}\n .value=${bucket.key}\n @click=${(e: Event) => {\n this.facetClicked(e, true);\n }}\n .checked=${facetHidden}\n class=\"hide-facet-checkbox\"\n />\n <label\n for=${negativeCheckboxId}\n class=\"hide-facet-icon${facetHidden ? ' active' : ''}\"\n title=${showHideText}\n >\n <span class=\"eye\">${eyeIcon}</span>\n <span class=\"eye-closed\">${eyeClosedIcon}</span>\n </label>\n </div>\n <label\n for=${showOnlyCheckboxId}\n class=\"facet-info-display\"\n title=${onlyShowText}\n aria-label=${ariaLabel}\n >\n <div class=\"facet-title\">${bucketTextDisplay}</div>\n <div class=\"facet-count\">${bucket.count.toLocaleString()}</div>\n </label>\n </div>\n `;\n }\n\n //\n // EVENT HANDLERS & DISPATCHERS\n //\n\n /**\n * Handler for whenever this facet is clicked & its state changes\n */\n private facetClicked(e: Event, negative: boolean) {\n const { bucket, facetType } = this;\n if (!bucket || !facetType) return;\n\n const target = e.target as HTMLInputElement;\n const { checked } = target;\n bucket.state = FacetRow.getFacetState(checked, negative);\n\n this.dispatchFacetClickEvent({\n facetType,\n bucket,\n negative,\n });\n }\n\n /**\n * Emits a `facetClick` event with details about this facet & its current state\n */\n private dispatchFacetClickEvent(detail: FacetEventDetails) {\n const event = new CustomEvent<FacetEventDetails>('facetClick', {\n detail,\n });\n this.dispatchEvent(event);\n }\n\n //\n // OTHER METHODS\n //\n\n /**\n * Returns the composed facet state corresponding to a positive or negative facet's checked state\n */\n static getFacetState(checked: boolean, negative: boolean): FacetState {\n let state: FacetState;\n if (checked) {\n state = negative ? 'hidden' : 'selected';\n } else {\n state = 'none';\n }\n return state;\n }\n\n //\n // STYLES\n //\n\n static get styles(): CSSResultGroup {\n const facetRowBorderTop = css`var(--facet-row-border-top, 1px solid transparent)`;\n const facetRowBorderBottom = css`var(--facet-row-border-bottom, 1px solid transparent)`;\n\n return css`\n async-collection-name {\n display: contents;\n }\n .facet-checkboxes {\n margin: 0 5px 0 0;\n display: flex;\n height: 15px;\n }\n .facet-checkboxes input:first-child {\n margin-right: 5px;\n }\n .facet-checkboxes input {\n height: 15px;\n width: 15px;\n margin: 0;\n }\n .facet-row-container {\n display: flex;\n font-weight: 500;\n font-size: 1.2rem;\n margin: 2.5px auto;\n height: auto;\n border-top: ${facetRowBorderTop};\n border-bottom: ${facetRowBorderBottom};\n overflow: hidden;\n }\n .facet-info-display {\n display: flex;\n flex: 1 1 0%;\n cursor: pointer;\n flex-wrap: wrap;\n }\n .facet-title {\n word-break: break-word;\n display: inline-block;\n flex: 1 1 0%;\n }\n .facet-count {\n text-align: right;\n }\n .select-facet-checkbox {\n cursor: pointer;\n display: inline-block;\n }\n .hide-facet-checkbox {\n display: none;\n }\n .hide-facet-icon {\n width: 15px;\n height: 15px;\n cursor: pointer;\n opacity: 0.3;\n display: inline-block;\n }\n .hide-facet-icon:hover,\n .active {\n opacity: 1;\n }\n .hide-facet-icon:hover .eye,\n .hide-facet-icon .eye-closed {\n display: none;\n }\n .hide-facet-icon:hover .eye-closed,\n .hide-facet-icon.active .eye-closed {\n display: inline;\n }\n .hide-facet-icon.active .eye {\n display: none;\n }\n .sorting-icon {\n cursor: pointer;\n }\n\n a:link,\n a:visited {\n text-decoration: none;\n color: var(--ia-theme-link-color, #4b64ff);\n }\n a:hover {\n text-decoration: underline;\n }\n `;\n }\n}\n"]}
|
|
@@ -5,16 +5,13 @@ export declare class FacetsTemplate extends LitElement {
|
|
|
5
5
|
facetGroup?: FacetGroup;
|
|
6
6
|
selectedFacets?: SelectedFacets;
|
|
7
7
|
renderOn?: string;
|
|
8
|
-
collectionPagePath: string;
|
|
9
8
|
collectionNameCache?: CollectionNameCacheInterface;
|
|
10
9
|
private facetClicked;
|
|
11
10
|
private facetChecked;
|
|
12
11
|
private facetUnchecked;
|
|
13
|
-
/** Returns the composed facet state corresponding to a positive or negative facet's checked state */
|
|
14
|
-
private getFacetState;
|
|
15
12
|
private dispatchFacetClickEvent;
|
|
16
13
|
private dispatchSelectedFacetsChanged;
|
|
17
|
-
private
|
|
14
|
+
private get facetsTemplate();
|
|
18
15
|
render(): TemplateResult<1>;
|
|
19
16
|
static get styles(): CSSResultGroup;
|
|
20
17
|
}
|
|
@@ -1,28 +1,24 @@
|
|
|
1
1
|
import { __decorate } from "tslib";
|
|
2
|
-
import { css, html, LitElement } from 'lit';
|
|
2
|
+
import { css, html, LitElement, nothing, } from 'lit';
|
|
3
3
|
import { customElement, property } from 'lit/decorators.js';
|
|
4
4
|
import { repeat } from 'lit/directives/repeat.js';
|
|
5
|
-
import eyeIcon from '../assets/img/icons/eye';
|
|
6
|
-
import eyeClosedIcon from '../assets/img/icons/eye-closed';
|
|
7
5
|
import { getDefaultSelectedFacets, } from '../models';
|
|
6
|
+
import { FacetRow } from './facet-row';
|
|
8
7
|
let FacetsTemplate = class FacetsTemplate extends LitElement {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
facetClicked(e, count, negative) {
|
|
14
|
-
const target = e.target;
|
|
15
|
-
const { checked, name, value } = target;
|
|
16
|
-
if (checked) {
|
|
17
|
-
this.facetChecked(name, value, count, negative);
|
|
8
|
+
facetClicked(e) {
|
|
9
|
+
const { bucket, negative } = e.detail;
|
|
10
|
+
if (bucket.state === 'none') {
|
|
11
|
+
this.facetUnchecked(bucket);
|
|
18
12
|
}
|
|
19
13
|
else {
|
|
20
|
-
this.
|
|
14
|
+
this.facetChecked(bucket, negative);
|
|
21
15
|
}
|
|
22
|
-
this.dispatchFacetClickEvent(
|
|
16
|
+
this.dispatchFacetClickEvent(e.detail);
|
|
23
17
|
}
|
|
24
|
-
facetChecked(
|
|
25
|
-
const { selectedFacets } = this;
|
|
18
|
+
facetChecked(bucket, negative) {
|
|
19
|
+
const { facetGroup, selectedFacets } = this;
|
|
20
|
+
if (!facetGroup)
|
|
21
|
+
return;
|
|
26
22
|
let newFacets;
|
|
27
23
|
if (selectedFacets) {
|
|
28
24
|
newFacets = {
|
|
@@ -32,15 +28,17 @@ let FacetsTemplate = class FacetsTemplate extends LitElement {
|
|
|
32
28
|
else {
|
|
33
29
|
newFacets = getDefaultSelectedFacets();
|
|
34
30
|
}
|
|
35
|
-
newFacets[key][
|
|
36
|
-
|
|
37
|
-
|
|
31
|
+
newFacets[facetGroup.key][bucket.key] = {
|
|
32
|
+
...bucket,
|
|
33
|
+
state: FacetRow.getFacetState(true, negative),
|
|
38
34
|
};
|
|
39
35
|
this.selectedFacets = newFacets;
|
|
40
36
|
this.dispatchSelectedFacetsChanged();
|
|
41
37
|
}
|
|
42
|
-
facetUnchecked(
|
|
43
|
-
const { selectedFacets } = this;
|
|
38
|
+
facetUnchecked(bucket) {
|
|
39
|
+
const { facetGroup, selectedFacets } = this;
|
|
40
|
+
if (!facetGroup)
|
|
41
|
+
return;
|
|
44
42
|
let newFacets;
|
|
45
43
|
if (selectedFacets) {
|
|
46
44
|
newFacets = {
|
|
@@ -50,24 +48,13 @@ let FacetsTemplate = class FacetsTemplate extends LitElement {
|
|
|
50
48
|
else {
|
|
51
49
|
newFacets = getDefaultSelectedFacets();
|
|
52
50
|
}
|
|
53
|
-
delete newFacets[key][
|
|
51
|
+
delete newFacets[facetGroup.key][bucket.key];
|
|
54
52
|
this.selectedFacets = newFacets;
|
|
55
53
|
this.dispatchSelectedFacetsChanged();
|
|
56
54
|
}
|
|
57
|
-
|
|
58
|
-
getFacetState(checked, negative) {
|
|
59
|
-
let state;
|
|
60
|
-
if (checked) {
|
|
61
|
-
state = negative ? 'hidden' : 'selected';
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
state = 'none';
|
|
65
|
-
}
|
|
66
|
-
return state;
|
|
67
|
-
}
|
|
68
|
-
dispatchFacetClickEvent(key, state, negative) {
|
|
55
|
+
dispatchFacetClickEvent(detail) {
|
|
69
56
|
const event = new CustomEvent('facetClick', {
|
|
70
|
-
detail
|
|
57
|
+
detail,
|
|
71
58
|
composed: true,
|
|
72
59
|
});
|
|
73
60
|
this.dispatchEvent(event);
|
|
@@ -80,105 +67,39 @@ let FacetsTemplate = class FacetsTemplate extends LitElement {
|
|
|
80
67
|
});
|
|
81
68
|
this.dispatchEvent(event);
|
|
82
69
|
}
|
|
83
|
-
|
|
84
|
-
|
|
70
|
+
get facetsTemplate() {
|
|
71
|
+
const { facetGroup } = this;
|
|
72
|
+
if (!facetGroup)
|
|
73
|
+
return nothing;
|
|
74
|
+
let facetBuckets = facetGroup.buckets;
|
|
85
75
|
/**
|
|
86
76
|
* sorting FacetBucket before render page / modal
|
|
87
77
|
* - first, selected items should be at top having sorted
|
|
88
78
|
* - second, suppressed/hidden items should be after selected having sorted
|
|
89
79
|
* - and then no-selected / not suppressed items should render having sorted
|
|
90
80
|
*/
|
|
91
|
-
|
|
92
|
-
...
|
|
81
|
+
facetBuckets = [
|
|
82
|
+
...facetBuckets
|
|
93
83
|
.filter(x => x.state === 'selected')
|
|
94
84
|
.sort((a, b) => (a.count < b.count ? 1 : -1)),
|
|
95
|
-
...
|
|
85
|
+
...facetBuckets
|
|
96
86
|
.filter(x => x.state === 'hidden')
|
|
97
87
|
.sort((a, b) => (a.count < b.count ? 1 : -1)),
|
|
98
|
-
...
|
|
88
|
+
...facetBuckets.filter(x => x.state === 'none'),
|
|
99
89
|
];
|
|
100
90
|
return html `
|
|
101
91
|
<div class="facets-on-${this.renderOn}">
|
|
102
|
-
${repeat(
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
// a static value to use
|
|
109
|
-
const bucketTextDisplay = facetGroup.key !== 'collection'
|
|
110
|
-
? html `${(_a = bucket.displayText) !== null && _a !== void 0 ? _a : bucket.key}`
|
|
111
|
-
: html `<a href="${this.collectionPagePath}${bucket.key}">
|
|
112
|
-
<async-collection-name
|
|
113
|
-
.collectionNameCache=${this.collectionNameCache}
|
|
114
|
-
.identifier=${bucket.key}
|
|
115
|
-
placeholder="-"
|
|
116
|
-
></async-collection-name>
|
|
117
|
-
</a> `;
|
|
118
|
-
const facetHidden = bucket.state === 'hidden';
|
|
119
|
-
const facetSelected = bucket.state === 'selected';
|
|
120
|
-
const titleText = `${facetGroup.key}: ${(_b = bucket.displayText) !== null && _b !== void 0 ? _b : bucket.key}`;
|
|
121
|
-
const onlyShowText = facetSelected
|
|
122
|
-
? `Show all ${facetGroup.key}s`
|
|
123
|
-
: `Only show ${titleText}`;
|
|
124
|
-
const hideText = `Hide ${titleText}`;
|
|
125
|
-
const unhideText = `Unhide ${titleText}`;
|
|
126
|
-
const showHideText = facetHidden ? unhideText : hideText;
|
|
127
|
-
const ariaLabel = `${titleText}, ${bucket.count} results`;
|
|
128
|
-
return html `
|
|
129
|
-
<div class="facet-row">
|
|
130
|
-
<div class="facet-checkbox">
|
|
131
|
-
<input
|
|
132
|
-
type="checkbox"
|
|
133
|
-
.name=${facetGroup.key}
|
|
134
|
-
.value=${bucket.key}
|
|
135
|
-
@click=${(e) => {
|
|
136
|
-
this.facetClicked(e, bucket.count, false);
|
|
137
|
-
}}
|
|
138
|
-
.checked=${facetSelected}
|
|
139
|
-
class="select-facet-checkbox"
|
|
140
|
-
title=${onlyShowText}
|
|
141
|
-
id=${showOnlyCheckboxId}
|
|
142
|
-
/>
|
|
143
|
-
<input
|
|
144
|
-
type="checkbox"
|
|
145
|
-
id=${negativeCheckboxId}
|
|
146
|
-
.name=${facetGroup.key}
|
|
147
|
-
.value=${bucket.key}
|
|
148
|
-
@click=${(e) => {
|
|
149
|
-
this.facetClicked(e, bucket.count, true);
|
|
150
|
-
}}
|
|
151
|
-
.checked=${facetHidden}
|
|
152
|
-
class="hide-facet-checkbox"
|
|
153
|
-
/>
|
|
154
|
-
<label
|
|
155
|
-
for=${negativeCheckboxId}
|
|
156
|
-
class="hide-facet-icon${facetHidden ? ' active' : ''}"
|
|
157
|
-
title=${showHideText}
|
|
158
|
-
>
|
|
159
|
-
<span class="eye">${eyeIcon}</span>
|
|
160
|
-
<span class="eye-closed">${eyeClosedIcon}</span>
|
|
161
|
-
</label>
|
|
162
|
-
</div>
|
|
163
|
-
<label
|
|
164
|
-
for=${showOnlyCheckboxId}
|
|
165
|
-
class="facet-info-display"
|
|
166
|
-
title=${onlyShowText}
|
|
167
|
-
aria-label=${ariaLabel}
|
|
168
|
-
>
|
|
169
|
-
<div class="facet-title">${bucketTextDisplay}</div>
|
|
170
|
-
<div class="facet-count">
|
|
171
|
-
${bucket.count.toLocaleString()}
|
|
172
|
-
</div>
|
|
173
|
-
</label>
|
|
174
|
-
</div>
|
|
175
|
-
`;
|
|
176
|
-
})}
|
|
92
|
+
${repeat(facetBuckets, bucket => `${facetGroup.key}:${bucket.key}`, bucket => html `<facet-row
|
|
93
|
+
.facetType=${facetGroup.key}
|
|
94
|
+
.bucket=${bucket}
|
|
95
|
+
.collectionNameCache=${this.collectionNameCache}
|
|
96
|
+
@facetClick=${this.facetClicked}
|
|
97
|
+
></facet-row>`)}
|
|
177
98
|
</div>
|
|
178
99
|
`;
|
|
179
100
|
}
|
|
180
101
|
render() {
|
|
181
|
-
return html `${this.
|
|
102
|
+
return html `${this.facetsTemplate}`;
|
|
182
103
|
}
|
|
183
104
|
static get styles() {
|
|
184
105
|
return css `
|
|
@@ -191,9 +112,7 @@ let FacetsTemplate = class FacetsTemplate extends LitElement {
|
|
|
191
112
|
column-gap: 15px;
|
|
192
113
|
column-count: 3;
|
|
193
114
|
}
|
|
194
|
-
|
|
195
|
-
display: contents;
|
|
196
|
-
}
|
|
115
|
+
|
|
197
116
|
ul.facet-list {
|
|
198
117
|
list-style: none;
|
|
199
118
|
margin: 0;
|
|
@@ -203,19 +122,7 @@ let FacetsTemplate = class FacetsTemplate extends LitElement {
|
|
|
203
122
|
margin-bottom: 0.2rem;
|
|
204
123
|
display: grid;
|
|
205
124
|
}
|
|
206
|
-
|
|
207
|
-
margin: 0 5px 0 0;
|
|
208
|
-
display: flex;
|
|
209
|
-
height: 15px;
|
|
210
|
-
}
|
|
211
|
-
.facet-checkbox input:first-child {
|
|
212
|
-
margin-right: 5px;
|
|
213
|
-
}
|
|
214
|
-
.facet-checkbox input {
|
|
215
|
-
height: 15px;
|
|
216
|
-
width: 15px;
|
|
217
|
-
margin: 0;
|
|
218
|
-
}
|
|
125
|
+
|
|
219
126
|
.facet-row {
|
|
220
127
|
display: flex;
|
|
221
128
|
font-weight: 500;
|
|
@@ -226,52 +133,6 @@ let FacetsTemplate = class FacetsTemplate extends LitElement {
|
|
|
226
133
|
border-bottom: var(--facet-row-border-bottom, 1px solid transparent);
|
|
227
134
|
overflow: hidden;
|
|
228
135
|
}
|
|
229
|
-
.facet-info-display {
|
|
230
|
-
display: flex;
|
|
231
|
-
flex: 1 1 0%;
|
|
232
|
-
cursor: pointer;
|
|
233
|
-
flex-wrap: wrap;
|
|
234
|
-
}
|
|
235
|
-
.facet-title {
|
|
236
|
-
word-break: break-word;
|
|
237
|
-
display: inline-block;
|
|
238
|
-
flex: 1 1 0%;
|
|
239
|
-
}
|
|
240
|
-
.facet-count {
|
|
241
|
-
text-align: right;
|
|
242
|
-
}
|
|
243
|
-
.select-facet-checkbox {
|
|
244
|
-
cursor: pointer;
|
|
245
|
-
display: inline-block;
|
|
246
|
-
}
|
|
247
|
-
.hide-facet-checkbox {
|
|
248
|
-
display: none;
|
|
249
|
-
}
|
|
250
|
-
.hide-facet-icon {
|
|
251
|
-
width: 15px;
|
|
252
|
-
height: 15px;
|
|
253
|
-
cursor: pointer;
|
|
254
|
-
opacity: 0.3;
|
|
255
|
-
display: inline-block;
|
|
256
|
-
}
|
|
257
|
-
.hide-facet-icon:hover,
|
|
258
|
-
.active {
|
|
259
|
-
opacity: 1;
|
|
260
|
-
}
|
|
261
|
-
.hide-facet-icon:hover .eye,
|
|
262
|
-
.hide-facet-icon .eye-closed {
|
|
263
|
-
display: none;
|
|
264
|
-
}
|
|
265
|
-
.hide-facet-icon:hover .eye-closed,
|
|
266
|
-
.hide-facet-icon.active .eye-closed {
|
|
267
|
-
display: inline;
|
|
268
|
-
}
|
|
269
|
-
.hide-facet-icon.active .eye {
|
|
270
|
-
display: none;
|
|
271
|
-
}
|
|
272
|
-
.sorting-icon {
|
|
273
|
-
cursor: pointer;
|
|
274
|
-
}
|
|
275
136
|
|
|
276
137
|
a:link,
|
|
277
138
|
a:visited {
|
|
@@ -293,9 +154,6 @@ __decorate([
|
|
|
293
154
|
__decorate([
|
|
294
155
|
property({ type: String })
|
|
295
156
|
], FacetsTemplate.prototype, "renderOn", void 0);
|
|
296
|
-
__decorate([
|
|
297
|
-
property({ type: String })
|
|
298
|
-
], FacetsTemplate.prototype, "collectionPagePath", void 0);
|
|
299
157
|
__decorate([
|
|
300
158
|
property({ type: Object })
|
|
301
159
|
], FacetsTemplate.prototype, "collectionNameCache", void 0);
|