@internetarchive/collection-browser 3.5.1 → 3.5.2-alpha-webdev8164.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/src/app-root.js +606 -606
  2. package/dist/src/app-root.js.map +1 -1
  3. package/dist/src/collection-browser.js +764 -764
  4. package/dist/src/collection-browser.js.map +1 -1
  5. package/dist/src/collection-facets/facet-row.js +140 -140
  6. package/dist/src/collection-facets/facet-row.js.map +1 -1
  7. package/dist/src/collection-facets/facets-template.js +28 -23
  8. package/dist/src/collection-facets/facets-template.js.map +1 -1
  9. package/dist/src/collection-facets/more-facets-content.d.ts +34 -8
  10. package/dist/src/collection-facets/more-facets-content.js +358 -159
  11. package/dist/src/collection-facets/more-facets-content.js.map +1 -1
  12. package/dist/src/collection-facets.js +267 -267
  13. package/dist/src/collection-facets.js.map +1 -1
  14. package/dist/src/data-source/collection-browser-data-source-interface.js.map +1 -1
  15. package/dist/src/data-source/collection-browser-data-source.js.map +1 -1
  16. package/dist/src/data-source/collection-browser-query-state.js.map +1 -1
  17. package/dist/src/data-source/models.js.map +1 -1
  18. package/dist/src/models.js.map +1 -1
  19. package/dist/src/restoration-state-handler.js.map +1 -1
  20. package/dist/src/tiles/grid/collection-tile.js +77 -77
  21. package/dist/src/tiles/grid/collection-tile.js.map +1 -1
  22. package/dist/src/tiles/grid/item-tile.js +137 -137
  23. package/dist/src/tiles/grid/item-tile.js.map +1 -1
  24. package/dist/src/tiles/models.js.map +1 -1
  25. package/dist/src/tiles/tile-dispatcher.js +215 -215
  26. package/dist/src/tiles/tile-dispatcher.js.map +1 -1
  27. package/dist/test/collection-browser.test.js +189 -189
  28. package/dist/test/collection-browser.test.js.map +1 -1
  29. package/dist/test/collection-facets/more-facets-content.test.js +137 -31
  30. package/dist/test/collection-facets/more-facets-content.test.js.map +1 -1
  31. package/dist/test/restoration-state-handler.test.js.map +1 -1
  32. package/package.json +1 -1
  33. package/src/app-root.ts +1140 -1140
  34. package/src/collection-browser.ts +3075 -3075
  35. package/src/collection-facets/facet-row.ts +299 -299
  36. package/src/collection-facets/facets-template.ts +88 -83
  37. package/src/collection-facets/more-facets-content.ts +856 -642
  38. package/src/collection-facets.ts +1010 -1010
  39. package/src/data-source/collection-browser-data-source-interface.ts +345 -345
  40. package/src/data-source/collection-browser-data-source.ts +1441 -1441
  41. package/src/data-source/collection-browser-query-state.ts +59 -59
  42. package/src/data-source/models.ts +56 -56
  43. package/src/models.ts +864 -864
  44. package/src/restoration-state-handler.ts +546 -546
  45. package/src/tiles/grid/collection-tile.ts +163 -163
  46. package/src/tiles/grid/item-tile.ts +340 -340
  47. package/src/tiles/models.ts +1 -1
  48. package/src/tiles/tile-dispatcher.ts +517 -517
  49. package/test/collection-browser.test.ts +2413 -2413
  50. package/test/collection-facets/more-facets-content.test.ts +378 -231
  51. package/test/restoration-state-handler.test.ts +480 -480
  52. package/vite.config.ts +29 -29
@@ -32,8 +32,8 @@ let FacetRow = FacetRow_1 = class FacetRow extends LitElement {
32
32
  // For other facet types, we just have a static value to use.
33
33
  const bucketTextDisplay = facetType !== 'collection'
34
34
  ? html `${bucket.displayText ?? bucket.key} ${extraNoteSpan}`
35
- : html `<a href="/details/${bucket.key}">
36
- ${this.collectionTitles?.get(bucket.key) ?? bucket.key}
35
+ : html `<a href="/details/${bucket.key}">
36
+ ${this.collectionTitles?.get(bucket.key) ?? bucket.key}
37
37
  </a> `;
38
38
  const bucketCountText = bucket.count > 0 ? bucket.count.toLocaleString() : '';
39
39
  const facetHidden = bucket.state === 'hidden';
@@ -47,56 +47,56 @@ let FacetRow = FacetRow_1 = class FacetRow extends LitElement {
47
47
  const showHideText = facetHidden ? unhideText : hideText;
48
48
  const ariaLabel = `${titleText}, ${bucket.count} results`;
49
49
  // Added data-testid for Playwright testing
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}
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
57
  @click=${(e) => {
58
58
  this.facetClicked(e, false);
59
- }}
60
- .checked=${facetSelected}
61
- class="select-facet-checkbox"
62
- title=${onlyShowText}
63
- id=${showOnlyCheckboxId}
64
- data-testid=${showOnlyCheckboxId}
65
- />
66
- <div class="hide-facet-container">
67
- <input
68
- type="checkbox"
69
- id=${negativeCheckboxId}
70
- .name=${facetType}
71
- .value=${bucket.key}
59
+ }}
60
+ .checked=${facetSelected}
61
+ class="select-facet-checkbox"
62
+ title=${onlyShowText}
63
+ id=${showOnlyCheckboxId}
64
+ data-testid=${showOnlyCheckboxId}
65
+ />
66
+ <div class="hide-facet-container">
67
+ <input
68
+ type="checkbox"
69
+ id=${negativeCheckboxId}
70
+ .name=${facetType}
71
+ .value=${bucket.key}
72
72
  @click=${(e) => {
73
73
  this.facetClicked(e, true);
74
- }}
75
- .checked=${facetHidden}
76
- class="hide-facet-checkbox"
77
- />
78
- <label
79
- for=${negativeCheckboxId}
80
- class="hide-facet-icon${facetHidden ? ' active' : ''}"
81
- title=${showHideText}
82
- data-testid=${negativeCheckboxId}
83
- >
84
- <span class="sr-only">${showHideText}</span>
85
- <span class="eye eye-open">${eyeIcon}</span>
86
- <span class="eye eye-closed">${eyeClosedIcon}</span>
87
- </label>
88
- </div>
89
- </div>
90
- <label
91
- for=${showOnlyCheckboxId}
92
- class="facet-info-display"
93
- title=${onlyShowText}
94
- aria-label=${ariaLabel}
95
- >
96
- <div class="facet-title">${bucketTextDisplay}</div>
97
- <div class="facet-count">${bucketCountText}</div>
98
- </label>
99
- </div>
74
+ }}
75
+ .checked=${facetHidden}
76
+ class="hide-facet-checkbox"
77
+ />
78
+ <label
79
+ for=${negativeCheckboxId}
80
+ class="hide-facet-icon${facetHidden ? ' active' : ''}"
81
+ title=${showHideText}
82
+ data-testid=${negativeCheckboxId}
83
+ >
84
+ <span class="sr-only">${showHideText}</span>
85
+ <span class="eye eye-open">${eyeIcon}</span>
86
+ <span class="eye eye-closed">${eyeClosedIcon}</span>
87
+ </label>
88
+ </div>
89
+ </div>
90
+ <label
91
+ for=${showOnlyCheckboxId}
92
+ class="facet-info-display"
93
+ title=${onlyShowText}
94
+ aria-label=${ariaLabel}
95
+ >
96
+ <div class="facet-title">${bucketTextDisplay}</div>
97
+ <div class="facet-count">${bucketCountText}</div>
98
+ </label>
99
+ </div>
100
100
  `;
101
101
  }
102
102
  //
@@ -153,98 +153,98 @@ let FacetRow = FacetRow_1 = class FacetRow extends LitElement {
153
153
  const facetRowBorderTop = css `var(--facet-row-border-top, 1px solid transparent)`;
154
154
  const facetRowBorderBottom = css `var(--facet-row-border-bottom, 1px solid transparent)`;
155
155
  const checkboxHeight = css `15px`;
156
- const ownCss = css `
157
- .facet-checkboxes {
158
- margin: 0 5px 0 0;
159
- display: flex;
160
- height: ${checkboxHeight};
161
- }
162
- .facet-checkboxes input:first-child {
163
- margin-right: 5px;
164
- }
165
- .facet-checkboxes input {
166
- height: ${checkboxHeight};
167
- width: ${checkboxHeight};
168
- margin: 0;
169
- }
170
- .facet-row-container {
171
- display: flex;
172
- font-weight: 500;
173
- font-size: 1.2rem;
174
- margin: 0 auto;
175
- padding: 0.25rem 0;
176
- height: auto;
177
- border-top: ${facetRowBorderTop};
178
- border-bottom: ${facetRowBorderBottom};
179
- }
180
- .facet-info-display {
181
- display: flex;
182
- flex: 1 1 0%;
183
- cursor: pointer;
184
- flex-wrap: wrap;
185
- }
186
- .facet-title {
187
- word-break: break-word;
188
- display: inline-block;
189
- flex: 1 1 0%;
190
- }
191
- .facet-note {
192
- color: #bbb;
193
- }
194
- .facet-count {
195
- text-align: right;
196
- }
197
- .select-facet-checkbox {
198
- cursor: pointer;
199
- display: inline-block;
200
- }
201
- .hide-facet-checkbox {
202
- position: absolute;
203
- clip: rect(0, 0, 0, 0);
204
- pointer-events: none;
205
- }
206
- .hide-facet-checkbox:focus-visible + .hide-facet-icon {
207
- outline-style: auto;
208
- outline-offset: 2px;
209
- }
210
- .hide-facet-icon {
211
- width: ${checkboxHeight};
212
- height: ${checkboxHeight};
213
- cursor: pointer;
214
- display: flex;
215
- }
216
- .eye {
217
- width: ${checkboxHeight};
218
- height: ${checkboxHeight};
219
- opacity: 0.3;
220
- }
221
- .hide-facet-icon:hover .eye,
222
- .active .eye {
223
- opacity: 1;
224
- }
225
- .hide-facet-icon:hover .eye-open,
226
- .hide-facet-icon .eye-closed {
227
- display: none;
228
- }
229
- .hide-facet-icon:hover .eye-closed,
230
- .hide-facet-icon.active .eye-closed {
231
- display: inline;
232
- }
233
- .hide-facet-icon.active .eye-open {
234
- display: none;
235
- }
236
- .sorting-icon {
237
- cursor: pointer;
238
- }
239
-
240
- a:link,
241
- a:visited {
242
- text-decoration: none;
243
- color: var(--ia-theme-link-color, #4b64ff);
244
- }
245
- a:hover {
246
- text-decoration: underline;
247
- }
156
+ const ownCss = css `
157
+ .facet-checkboxes {
158
+ margin: 0 5px 0 0;
159
+ display: flex;
160
+ height: ${checkboxHeight};
161
+ }
162
+ .facet-checkboxes input:first-child {
163
+ margin-right: 5px;
164
+ }
165
+ .facet-checkboxes input {
166
+ height: ${checkboxHeight};
167
+ width: ${checkboxHeight};
168
+ margin: 0;
169
+ }
170
+ .facet-row-container {
171
+ display: flex;
172
+ font-weight: 500;
173
+ font-size: 1.2rem;
174
+ margin: 0 auto;
175
+ padding: 0.25rem 0;
176
+ height: auto;
177
+ border-top: ${facetRowBorderTop};
178
+ border-bottom: ${facetRowBorderBottom};
179
+ }
180
+ .facet-info-display {
181
+ display: flex;
182
+ flex: 1 1 0%;
183
+ cursor: pointer;
184
+ flex-wrap: wrap;
185
+ }
186
+ .facet-title {
187
+ word-break: break-word;
188
+ display: inline-block;
189
+ flex: 1 1 0%;
190
+ }
191
+ .facet-note {
192
+ color: #bbb;
193
+ }
194
+ .facet-count {
195
+ text-align: right;
196
+ }
197
+ .select-facet-checkbox {
198
+ cursor: pointer;
199
+ display: inline-block;
200
+ }
201
+ .hide-facet-checkbox {
202
+ position: absolute;
203
+ clip: rect(0, 0, 0, 0);
204
+ pointer-events: none;
205
+ }
206
+ .hide-facet-checkbox:focus-visible + .hide-facet-icon {
207
+ outline-style: auto;
208
+ outline-offset: 2px;
209
+ }
210
+ .hide-facet-icon {
211
+ width: ${checkboxHeight};
212
+ height: ${checkboxHeight};
213
+ cursor: pointer;
214
+ display: flex;
215
+ }
216
+ .eye {
217
+ width: ${checkboxHeight};
218
+ height: ${checkboxHeight};
219
+ opacity: 0.3;
220
+ }
221
+ .hide-facet-icon:hover .eye,
222
+ .active .eye {
223
+ opacity: 1;
224
+ }
225
+ .hide-facet-icon:hover .eye-open,
226
+ .hide-facet-icon .eye-closed {
227
+ display: none;
228
+ }
229
+ .hide-facet-icon:hover .eye-closed,
230
+ .hide-facet-icon.active .eye-closed {
231
+ display: inline;
232
+ }
233
+ .hide-facet-icon.active .eye-open {
234
+ display: none;
235
+ }
236
+ .sorting-icon {
237
+ cursor: pointer;
238
+ }
239
+
240
+ a:link,
241
+ a:visited {
242
+ text-decoration: none;
243
+ color: var(--ia-theme-link-color, #4b64ff);
244
+ }
245
+ a:hover {
246
+ text-decoration: underline;
247
+ }
248
248
  `;
249
249
  return [srOnlyStyle, ownCss];
250
250
  }
@@ -1 +1 @@
1
- {"version":3,"file":"facet-row.js","sourceRoot":"","sources":["../../../src/collection-facets/facet-row.ts"],"names":[],"mappings":";;AAAA,OAAO,EACL,GAAG,EACH,IAAI,EACJ,UAAU,EAGV,OAAO,GACR,MAAM,KAAK,CAAC;AACb,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,OAAO,MAAM,yBAAyB,CAAC;AAC9C,OAAO,aAAa,MAAM,gCAAgC,CAAC;AAQ3D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGzC,IAAM,QAAQ,gBAAd,MAAM,QAAS,SAAQ,UAAU;IAetC,EAAE;IACF,8BAA8B;IAC9B,EAAE;IAEF,MAAM;QACJ,OAAO,IAAI,CAAA,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;IACxC,CAAC;IAED,EAAE;IACF,mBAAmB;IACnB,EAAE;IAEF;;;OAGG;IACH,IAAY,gBAAgB;QAC1B,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;QACnC,IAAI,CAAC,MAAM,IAAI,CAAC,SAAS;YAAE,OAAO,OAAO,CAAC;QAE1C,MAAM,kBAAkB,GAAG,GAAG,SAAS,IAAI,MAAM,CAAC,GAAG,YAAY,CAAC;QAClE,MAAM,kBAAkB,GAAG,GAAG,SAAS,IAAI,MAAM,CAAC,GAAG,WAAW,CAAC;QAEjE,MAAM,aAAa,GAAG,MAAM,CAAC,SAAS;YACpC,CAAC,CAAC,IAAI,CAAA,4BAA4B,MAAM,CAAC,SAAS,SAAS;YAC3D,CAAC,CAAC,OAAO,CAAC;QAEZ,6DAA6D;QAC7D,6DAA6D;QAC7D,MAAM,iBAAiB,GACrB,SAAS,KAAK,YAAY;YACxB,CAAC,CAAC,IAAI,CAAA,GAAG,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,GAAG,IAAI,aAAa,EAAE;YAC5D,CAAC,CAAC,IAAI,CAAA,qBAAqB,MAAM,CAAC,GAAG;cAC/B,IAAI,CAAC,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG;gBAClD,CAAC;QAEb,MAAM,eAAe,GACnB,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAExD,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,KAAK,QAAQ,CAAC;QAC9C,MAAM,aAAa,GAAG,MAAM,CAAC,KAAK,KAAK,UAAU,CAAC;QAElD,MAAM,SAAS,GAAG,GAAG,SAAS,KAAK,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC;QACtE,MAAM,YAAY,GAAG,aAAa;YAChC,CAAC,CAAC,YAAY,SAAS,GAAG;YAC1B,CAAC,CAAC,aAAa,SAAS,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,QAAQ,SAAS,EAAE,CAAC;QACrC,MAAM,UAAU,GAAG,UAAU,SAAS,EAAE,CAAC;QACzC,MAAM,YAAY,GAAG,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC;QACzD,MAAM,SAAS,GAAG,GAAG,SAAS,KAAK,MAAM,CAAC,KAAK,UAAU,CAAC;QAE1D,2CAA2C;QAC3C,OAAO,IAAI,CAAA;;;;;oBAKK,SAAS;qBACR,MAAM,CAAC,GAAG;qBACV,CAAC,CAAQ,EAAE,EAAE;YACpB,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QAC9B,CAAC;uBACU,aAAa;;oBAEhB,YAAY;iBACf,kBAAkB;0BACT,kBAAkB;;;;;mBAKzB,kBAAkB;sBACf,SAAS;uBACR,MAAM,CAAC,GAAG;uBACV,CAAC,CAAQ,EAAE,EAAE;YACpB,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAC7B,CAAC;yBACU,WAAW;;;;oBAIhB,kBAAkB;sCACA,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;sBAC5C,YAAY;4BACN,kBAAkB;;sCAER,YAAY;2CACP,OAAO;6CACL,aAAa;;;;;gBAK1C,kBAAkB;;kBAEhB,YAAY;uBACP,SAAS;;qCAEK,iBAAiB;qCACjB,eAAe;;;KAG/C,CAAC;IACJ,CAAC;IAED,EAAE;IACF,+BAA+B;IAC/B,EAAE;IAEF;;OAEG;IACK,YAAY,CAAC,CAAQ,EAAE,QAAiB;QAC9C,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;QACnC,IAAI,CAAC,MAAM,IAAI,CAAC,SAAS;YAAE,OAAO;QAElC,MAAM,MAAM,GAAG,CAAC,CAAC,MAA0B,CAAC;QAC5C,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;QAC3B,IAAI,CAAC,MAAM,GAAG;YACZ,GAAG,MAAM;YACT,KAAK,EAAE,UAAQ,CAAC,aAAa,CAAC,OAAO,EAAE,QAAQ,CAAC;SACjD,CAAC;QAEF,IAAI,CAAC,uBAAuB,CAAC;YAC3B,SAAS;YACT,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,QAAQ;SACT,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,uBAAuB,CAAC,MAAyB;QACvD,MAAM,KAAK,GAAG,IAAI,WAAW,CAAoB,YAAY,EAAE;YAC7D,MAAM;SACP,CAAC,CAAC;QACH,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED,EAAE;IACF,gBAAgB;IAChB,EAAE;IAEF;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,OAAgB,EAAE,QAAiB;QACtD,IAAI,KAAiB,CAAC;QACtB,IAAI,OAAO,EAAE,CAAC;YACZ,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;QAC3C,CAAC;aAAM,CAAC;YACN,KAAK,GAAG,MAAM,CAAC;QACjB,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,EAAE;IACF,SAAS;IACT,EAAE;IAEF,MAAM,KAAK,MAAM;QACf,MAAM,iBAAiB,GAAG,GAAG,CAAA,oDAAoD,CAAC;QAClF,MAAM,oBAAoB,GAAG,GAAG,CAAA,uDAAuD,CAAC;QACxF,MAAM,cAAc,GAAG,GAAG,CAAA,MAAM,CAAC;QAEjC,MAAM,MAAM,GAAG,GAAG,CAAA;;;;kBAIJ,cAAc;;;;;;kBAMd,cAAc;iBACf,cAAc;;;;;;;;;;sBAUT,iBAAiB;yBACd,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiC5B,cAAc;kBACb,cAAc;;;;;iBAKf,cAAc;kBACb,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA8B3B,CAAC;QAEF,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAC/B,CAAC;CACF,CAAA;AA/Q6B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;2CAAyB;AAGxB;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;wCAAsB;AAIjD;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;kDACS;AAbzB,QAAQ;IADpB,aAAa,CAAC,WAAW,CAAC;GACd,QAAQ,CAqRpB","sourcesContent":["import {\r\n css,\r\n html,\r\n LitElement,\r\n TemplateResult,\r\n CSSResultGroup,\r\n nothing,\r\n} from 'lit';\r\nimport { customElement, property } from 'lit/decorators.js';\r\nimport eyeIcon from '../assets/img/icons/eye';\r\nimport eyeClosedIcon from '../assets/img/icons/eye-closed';\r\nimport type {\r\n FacetOption,\r\n FacetBucket,\r\n FacetEventDetails,\r\n FacetState,\r\n} from '../models';\r\nimport type { CollectionTitles } from '../data-source/models';\r\nimport { srOnlyStyle } from '../styles/sr-only';\r\n\r\n@customElement('facet-row')\r\nexport class FacetRow extends LitElement {\r\n //\r\n // UI STATE\r\n //\r\n\r\n /** The name of the facet group to which this facet belongs (e.g., \"mediatype\") */\r\n @property({ type: String }) facetType?: FacetOption;\r\n\r\n /** The facet bucket containing details about the state, count, and key for this row */\r\n @property({ type: Object }) bucket?: FacetBucket;\r\n\r\n /** The collection name cache for converting collection identifiers to titles */\r\n @property({ type: Object })\r\n collectionTitles?: CollectionTitles;\r\n\r\n //\r\n // COMPONENT LIFECYCLE METHODS\r\n //\r\n\r\n render() {\r\n return html`${this.facetRowTemplate}`;\r\n }\r\n\r\n //\r\n // TEMPLATE GETTERS\r\n //\r\n\r\n /**\r\n * Template for the full facet row, including the positive/negative checks,\r\n * the display name, and the count.\r\n */\r\n private get facetRowTemplate(): TemplateResult | typeof nothing {\r\n const { bucket, facetType } = this;\r\n if (!bucket || !facetType) return nothing;\r\n\r\n const showOnlyCheckboxId = `${facetType}:${bucket.key}-show-only`;\r\n const negativeCheckboxId = `${facetType}:${bucket.key}-negative`;\r\n\r\n const extraNoteSpan = bucket.extraNote\r\n ? html`<span class=\"facet-note\">${bucket.extraNote}</span>`\r\n : nothing;\r\n\r\n // For collections, we render the collection title as a link.\r\n // For other facet types, we just have a static value to use.\r\n const bucketTextDisplay =\r\n facetType !== 'collection'\r\n ? html`${bucket.displayText ?? bucket.key} ${extraNoteSpan}`\r\n : html`<a href=\"/details/${bucket.key}\">\r\n ${this.collectionTitles?.get(bucket.key) ?? bucket.key}\r\n </a> `;\r\n\r\n const bucketCountText =\r\n bucket.count > 0 ? bucket.count.toLocaleString() : '';\r\n\r\n const facetHidden = bucket.state === 'hidden';\r\n const facetSelected = bucket.state === 'selected';\r\n\r\n const titleText = `${facetType}: ${bucket.displayText ?? bucket.key}`;\r\n const onlyShowText = facetSelected\r\n ? `Show all ${facetType}s`\r\n : `Only show ${titleText}`;\r\n const hideText = `Hide ${titleText}`;\r\n const unhideText = `Unhide ${titleText}`;\r\n const showHideText = facetHidden ? unhideText : hideText;\r\n const ariaLabel = `${titleText}, ${bucket.count} results`;\r\n\r\n // Added data-testid for Playwright testing\r\n return html`\r\n <div class=\"facet-row-container\">\r\n <div class=\"facet-checkboxes\">\r\n <input\r\n type=\"checkbox\"\r\n .name=${facetType}\r\n .value=${bucket.key}\r\n @click=${(e: Event) => {\r\n this.facetClicked(e, false);\r\n }}\r\n .checked=${facetSelected}\r\n class=\"select-facet-checkbox\"\r\n title=${onlyShowText}\r\n id=${showOnlyCheckboxId}\r\n data-testid=${showOnlyCheckboxId}\r\n />\r\n <div class=\"hide-facet-container\">\r\n <input\r\n type=\"checkbox\"\r\n id=${negativeCheckboxId}\r\n .name=${facetType}\r\n .value=${bucket.key}\r\n @click=${(e: Event) => {\r\n this.facetClicked(e, true);\r\n }}\r\n .checked=${facetHidden}\r\n class=\"hide-facet-checkbox\"\r\n />\r\n <label\r\n for=${negativeCheckboxId}\r\n class=\"hide-facet-icon${facetHidden ? ' active' : ''}\"\r\n title=${showHideText}\r\n data-testid=${negativeCheckboxId}\r\n >\r\n <span class=\"sr-only\">${showHideText}</span>\r\n <span class=\"eye eye-open\">${eyeIcon}</span>\r\n <span class=\"eye eye-closed\">${eyeClosedIcon}</span>\r\n </label>\r\n </div>\r\n </div>\r\n <label\r\n for=${showOnlyCheckboxId}\r\n class=\"facet-info-display\"\r\n title=${onlyShowText}\r\n aria-label=${ariaLabel}\r\n >\r\n <div class=\"facet-title\">${bucketTextDisplay}</div>\r\n <div class=\"facet-count\">${bucketCountText}</div>\r\n </label>\r\n </div>\r\n `;\r\n }\r\n\r\n //\r\n // EVENT HANDLERS & DISPATCHERS\r\n //\r\n\r\n /**\r\n * Handler for whenever this facet is clicked & its state changes\r\n */\r\n private facetClicked(e: Event, negative: boolean) {\r\n const { bucket, facetType } = this;\r\n if (!bucket || !facetType) return;\r\n\r\n const target = e.target as HTMLInputElement;\r\n const { checked } = target;\r\n this.bucket = {\r\n ...bucket,\r\n state: FacetRow.getFacetState(checked, negative),\r\n };\r\n\r\n this.dispatchFacetClickEvent({\r\n facetType,\r\n bucket: this.bucket,\r\n negative,\r\n });\r\n }\r\n\r\n /**\r\n * Emits a `facetClick` event with details about this facet & its current state\r\n */\r\n private dispatchFacetClickEvent(detail: FacetEventDetails) {\r\n const event = new CustomEvent<FacetEventDetails>('facetClick', {\r\n detail,\r\n });\r\n this.dispatchEvent(event);\r\n }\r\n\r\n //\r\n // OTHER METHODS\r\n //\r\n\r\n /**\r\n * Returns the composed facet state corresponding to a positive or negative facet's checked state\r\n */\r\n static getFacetState(checked: boolean, negative: boolean): FacetState {\r\n let state: FacetState;\r\n if (checked) {\r\n state = negative ? 'hidden' : 'selected';\r\n } else {\r\n state = 'none';\r\n }\r\n return state;\r\n }\r\n\r\n //\r\n // STYLES\r\n //\r\n\r\n static get styles(): CSSResultGroup {\r\n const facetRowBorderTop = css`var(--facet-row-border-top, 1px solid transparent)`;\r\n const facetRowBorderBottom = css`var(--facet-row-border-bottom, 1px solid transparent)`;\r\n const checkboxHeight = css`15px`;\r\n\r\n const ownCss = css`\r\n .facet-checkboxes {\r\n margin: 0 5px 0 0;\r\n display: flex;\r\n height: ${checkboxHeight};\r\n }\r\n .facet-checkboxes input:first-child {\r\n margin-right: 5px;\r\n }\r\n .facet-checkboxes input {\r\n height: ${checkboxHeight};\r\n width: ${checkboxHeight};\r\n margin: 0;\r\n }\r\n .facet-row-container {\r\n display: flex;\r\n font-weight: 500;\r\n font-size: 1.2rem;\r\n margin: 0 auto;\r\n padding: 0.25rem 0;\r\n height: auto;\r\n border-top: ${facetRowBorderTop};\r\n border-bottom: ${facetRowBorderBottom};\r\n }\r\n .facet-info-display {\r\n display: flex;\r\n flex: 1 1 0%;\r\n cursor: pointer;\r\n flex-wrap: wrap;\r\n }\r\n .facet-title {\r\n word-break: break-word;\r\n display: inline-block;\r\n flex: 1 1 0%;\r\n }\r\n .facet-note {\r\n color: #bbb;\r\n }\r\n .facet-count {\r\n text-align: right;\r\n }\r\n .select-facet-checkbox {\r\n cursor: pointer;\r\n display: inline-block;\r\n }\r\n .hide-facet-checkbox {\r\n position: absolute;\r\n clip: rect(0, 0, 0, 0);\r\n pointer-events: none;\r\n }\r\n .hide-facet-checkbox:focus-visible + .hide-facet-icon {\r\n outline-style: auto;\r\n outline-offset: 2px;\r\n }\r\n .hide-facet-icon {\r\n width: ${checkboxHeight};\r\n height: ${checkboxHeight};\r\n cursor: pointer;\r\n display: flex;\r\n }\r\n .eye {\r\n width: ${checkboxHeight};\r\n height: ${checkboxHeight};\r\n opacity: 0.3;\r\n }\r\n .hide-facet-icon:hover .eye,\r\n .active .eye {\r\n opacity: 1;\r\n }\r\n .hide-facet-icon:hover .eye-open,\r\n .hide-facet-icon .eye-closed {\r\n display: none;\r\n }\r\n .hide-facet-icon:hover .eye-closed,\r\n .hide-facet-icon.active .eye-closed {\r\n display: inline;\r\n }\r\n .hide-facet-icon.active .eye-open {\r\n display: none;\r\n }\r\n .sorting-icon {\r\n cursor: pointer;\r\n }\r\n\r\n a:link,\r\n a:visited {\r\n text-decoration: none;\r\n color: var(--ia-theme-link-color, #4b64ff);\r\n }\r\n a:hover {\r\n text-decoration: underline;\r\n }\r\n `;\r\n\r\n return [srOnlyStyle, ownCss];\r\n }\r\n}\r\n"]}
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 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';\nimport type { CollectionTitles } from '../data-source/models';\nimport { srOnlyStyle } from '../styles/sr-only';\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 collectionTitles?: CollectionTitles;\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 const extraNoteSpan = bucket.extraNote\n ? html`<span class=\"facet-note\">${bucket.extraNote}</span>`\n : nothing;\n\n // For collections, we render the collection title as a link.\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} ${extraNoteSpan}`\n : html`<a href=\"/details/${bucket.key}\">\n ${this.collectionTitles?.get(bucket.key) ?? bucket.key}\n </a> `;\n\n const bucketCountText =\n bucket.count > 0 ? bucket.count.toLocaleString() : '';\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 // Added data-testid for Playwright testing\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 data-testid=${showOnlyCheckboxId}\n />\n <div class=\"hide-facet-container\">\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 data-testid=${negativeCheckboxId}\n >\n <span class=\"sr-only\">${showHideText}</span>\n <span class=\"eye eye-open\">${eyeIcon}</span>\n <span class=\"eye eye-closed\">${eyeClosedIcon}</span>\n </label>\n </div>\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\">${bucketCountText}</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 this.bucket = {\n ...bucket,\n state: FacetRow.getFacetState(checked, negative),\n };\n\n this.dispatchFacetClickEvent({\n facetType,\n bucket: this.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 const checkboxHeight = css`15px`;\n\n const ownCss = css`\n .facet-checkboxes {\n margin: 0 5px 0 0;\n display: flex;\n height: ${checkboxHeight};\n }\n .facet-checkboxes input:first-child {\n margin-right: 5px;\n }\n .facet-checkboxes input {\n height: ${checkboxHeight};\n width: ${checkboxHeight};\n margin: 0;\n }\n .facet-row-container {\n display: flex;\n font-weight: 500;\n font-size: 1.2rem;\n margin: 0 auto;\n padding: 0.25rem 0;\n height: auto;\n border-top: ${facetRowBorderTop};\n border-bottom: ${facetRowBorderBottom};\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-note {\n color: #bbb;\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 position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n }\n .hide-facet-checkbox:focus-visible + .hide-facet-icon {\n outline-style: auto;\n outline-offset: 2px;\n }\n .hide-facet-icon {\n width: ${checkboxHeight};\n height: ${checkboxHeight};\n cursor: pointer;\n display: flex;\n }\n .eye {\n width: ${checkboxHeight};\n height: ${checkboxHeight};\n opacity: 0.3;\n }\n .hide-facet-icon:hover .eye,\n .active .eye {\n opacity: 1;\n }\n .hide-facet-icon:hover .eye-open,\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-open {\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 return [srOnlyStyle, ownCss];\n }\n}\n"]}
@@ -21,15 +21,15 @@ let FacetsTemplate = class FacetsTemplate extends LitElement {
21
21
  const facetBuckets = facetGroup.buckets;
22
22
  // Added data-testid for Playwright testing
23
23
  // Using className and aria-labels is not ideal for Playwright locator
24
- return html `
25
- <div class="facet-rows" data-testid="facets-on-${facetGroup.key}">
26
- ${repeat(facetBuckets, bucket => `${facetGroup.key}:${bucket.key}`, bucket => html `<facet-row
27
- .facetType=${facetGroup.key}
28
- .bucket=${bucket}
29
- .collectionTitles=${this.collectionTitles}
30
- @facetClick=${this.facetClicked}
31
- ></facet-row>`)}
32
- </div>
24
+ return html `
25
+ <div class="facet-rows" data-testid="facets-on-${facetGroup.key}">
26
+ ${repeat(facetBuckets, bucket => `${facetGroup.key}:${bucket.key}`, bucket => html `<facet-row
27
+ .facetType=${facetGroup.key}
28
+ .bucket=${bucket}
29
+ .collectionTitles=${this.collectionTitles}
30
+ @facetClick=${this.facetClicked}
31
+ ></facet-row>`)}
32
+ </div>
33
33
  `;
34
34
  }
35
35
  render() {
@@ -38,20 +38,25 @@ let FacetsTemplate = class FacetsTemplate extends LitElement {
38
38
  static get styles() {
39
39
  const columnCount = css `var(--facetsColumnCount, 1)`;
40
40
  const columnGap = css `var(--facetsColumnGap, 15px)`;
41
- return css `
42
- .facet-rows {
43
- column-count: ${columnCount};
44
- column-gap: ${columnGap};
45
- }
46
-
47
- a:link,
48
- a:visited {
49
- text-decoration: none;
50
- color: var(--ia-theme-link-color, #4b64ff);
51
- }
52
- a:hover {
53
- text-decoration: underline;
54
- }
41
+ const columnWidth = css `var(--facetsColumnWidth, auto)`;
42
+ const maxHeight = css `var(--facetsMaxHeight, none)`;
43
+ return css `
44
+ .facet-rows {
45
+ column-count: ${columnCount};
46
+ column-gap: ${columnGap};
47
+ column-width: ${columnWidth};
48
+ max-height: ${maxHeight};
49
+ column-fill: auto;
50
+ }
51
+
52
+ a:link,
53
+ a:visited {
54
+ text-decoration: none;
55
+ color: var(--ia-theme-link-color, #4b64ff);
56
+ }
57
+ a:hover {
58
+ text-decoration: underline;
59
+ }
55
60
  `;
56
61
  }
57
62
  };
@@ -1 +1 @@
1
- {"version":3,"file":"facets-template.js","sourceRoot":"","sources":["../../../src/collection-facets/facets-template.ts"],"names":[],"mappings":";AAAA,OAAO,EACL,GAAG,EACH,IAAI,EACJ,UAAU,EAGV,OAAO,GACR,MAAM,KAAK,CAAC;AACb,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAGlD,OAAO,aAAa,CAAC;AAGd,IAAM,cAAc,GAApB,MAAM,cAAe,SAAQ,UAAU;IAMpC,YAAY,CAAC,CAAiC;QACpD,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IACzC,CAAC;IAEO,uBAAuB,CAAC,MAAyB;QACvD,MAAM,KAAK,GAAG,IAAI,WAAW,CAAoB,YAAY,EAAE;YAC7D,MAAM;YACN,QAAQ,EAAE,IAAI;SACf,CAAC,CAAC;QACH,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED,IAAY,cAAc;QACxB,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC,UAAU;YAAE,OAAO,OAAO,CAAC;QAEhC,MAAM,YAAY,GAAG,UAAU,CAAC,OAAwB,CAAC;QAEzD,2CAA2C;QAC3C,sEAAsE;QACtE,OAAO,IAAI,CAAA;uDACwC,UAAU,CAAC,GAAG;UAC3D,MAAM,CACN,YAAY,EACZ,MAAM,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,EAAE,EAC3C,MAAM,CAAC,EAAE,CACP,IAAI,CAAA;2BACW,UAAU,CAAC,GAAG;wBACjB,MAAM;kCACI,IAAI,CAAC,gBAAgB;4BAC3B,IAAI,CAAC,YAAY;0BACnB,CACjB;;KAEJ,CAAC;IACJ,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAA,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;IACtC,CAAC;IAED,MAAM,KAAK,MAAM;QACf,MAAM,WAAW,GAAG,GAAG,CAAA,6BAA6B,CAAC;QACrD,MAAM,SAAS,GAAG,GAAG,CAAA,8BAA8B,CAAC;QAEpD,OAAO,GAAG,CAAA;;wBAEU,WAAW;sBACb,SAAS;;;;;;;;;;;KAW1B,CAAC;IACJ,CAAC;CACF,CAAA;AAlE6B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;kDAAyB;AAGpD;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;wDACS;AAJzB,cAAc;IAD1B,aAAa,CAAC,iBAAiB,CAAC;GACpB,cAAc,CAmE1B","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 { repeat } from 'lit/directives/repeat.js';\nimport type { FacetGroup, FacetBucket, FacetEventDetails } from '../models';\nimport type { CollectionTitles } from '../data-source/models';\nimport './facet-row';\n\n@customElement('facets-template')\nexport class FacetsTemplate extends LitElement {\n @property({ type: Object }) facetGroup?: FacetGroup;\n\n @property({ type: Object })\n collectionTitles?: CollectionTitles;\n\n private facetClicked(e: CustomEvent<FacetEventDetails>) {\n this.dispatchFacetClickEvent(e.detail);\n }\n\n private dispatchFacetClickEvent(detail: FacetEventDetails) {\n const event = new CustomEvent<FacetEventDetails>('facetClick', {\n detail,\n composed: true,\n });\n this.dispatchEvent(event);\n }\n\n private get facetsTemplate(): TemplateResult | typeof nothing {\n const { facetGroup } = this;\n if (!facetGroup) return nothing;\n\n const facetBuckets = facetGroup.buckets as FacetBucket[];\n\n // Added data-testid for Playwright testing\n // Using className and aria-labels is not ideal for Playwright locator\n return html`\n <div class=\"facet-rows\" data-testid=\"facets-on-${facetGroup.key}\">\n ${repeat(\n facetBuckets,\n bucket => `${facetGroup.key}:${bucket.key}`,\n bucket =>\n html`<facet-row\n .facetType=${facetGroup.key}\n .bucket=${bucket}\n .collectionTitles=${this.collectionTitles}\n @facetClick=${this.facetClicked}\n ></facet-row>`,\n )}\n </div>\n `;\n }\n\n render() {\n return html`${this.facetsTemplate}`;\n }\n\n static get styles(): CSSResultGroup {\n const columnCount = css`var(--facetsColumnCount, 1)`;\n const columnGap = css`var(--facetsColumnGap, 15px)`;\n\n return css`\n .facet-rows {\n column-count: ${columnCount};\n column-gap: ${columnGap};\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"]}
1
+ {"version":3,"file":"facets-template.js","sourceRoot":"","sources":["../../../src/collection-facets/facets-template.ts"],"names":[],"mappings":";AAAA,OAAO,EACL,GAAG,EACH,IAAI,EACJ,UAAU,EAGV,OAAO,GACR,MAAM,KAAK,CAAC;AACb,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAGlD,OAAO,aAAa,CAAC;AAGd,IAAM,cAAc,GAApB,MAAM,cAAe,SAAQ,UAAU;IAMpC,YAAY,CAAC,CAAiC;QACpD,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IACzC,CAAC;IAEO,uBAAuB,CAAC,MAAyB;QACvD,MAAM,KAAK,GAAG,IAAI,WAAW,CAAoB,YAAY,EAAE;YAC7D,MAAM;YACN,QAAQ,EAAE,IAAI;SACf,CAAC,CAAC;QACH,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED,IAAY,cAAc;QACxB,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC,UAAU;YAAE,OAAO,OAAO,CAAC;QAEhC,MAAM,YAAY,GAAG,UAAU,CAAC,OAAwB,CAAC;QAEzD,2CAA2C;QAC3C,sEAAsE;QACtE,OAAO,IAAI,CAAA;uDACwC,UAAU,CAAC,GAAG;UAC3D,MAAM,CACN,YAAY,EACZ,MAAM,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,EAAE,EAC3C,MAAM,CAAC,EAAE,CACP,IAAI,CAAA;2BACW,UAAU,CAAC,GAAG;wBACjB,MAAM;kCACI,IAAI,CAAC,gBAAgB;4BAC3B,IAAI,CAAC,YAAY;0BACnB,CACjB;;KAEJ,CAAC;IACJ,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAA,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;IACtC,CAAC;IAED,MAAM,KAAK,MAAM;QACf,MAAM,WAAW,GAAG,GAAG,CAAA,6BAA6B,CAAC;QACrD,MAAM,SAAS,GAAG,GAAG,CAAA,8BAA8B,CAAC;QACpD,MAAM,WAAW,GAAG,GAAG,CAAA,gCAAgC,CAAC;QACxD,MAAM,SAAS,GAAG,GAAG,CAAA,8BAA8B,CAAC;QAEpD,OAAO,GAAG,CAAA;;wBAEU,WAAW;sBACb,SAAS;wBACP,WAAW;sBACb,SAAS;;;;;;;;;;;;KAY1B,CAAC;IACJ,CAAC;CACF,CAAA;AAvE6B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;kDAAyB;AAGpD;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;wDACS;AAJzB,cAAc;IAD1B,aAAa,CAAC,iBAAiB,CAAC;GACpB,cAAc,CAwE1B","sourcesContent":["import {\r\n css,\r\n html,\r\n LitElement,\r\n TemplateResult,\r\n CSSResultGroup,\r\n nothing,\r\n} from 'lit';\r\nimport { customElement, property } from 'lit/decorators.js';\r\nimport { repeat } from 'lit/directives/repeat.js';\r\nimport type { FacetGroup, FacetBucket, FacetEventDetails } from '../models';\r\nimport type { CollectionTitles } from '../data-source/models';\r\nimport './facet-row';\r\n\r\n@customElement('facets-template')\r\nexport class FacetsTemplate extends LitElement {\r\n @property({ type: Object }) facetGroup?: FacetGroup;\r\n\r\n @property({ type: Object })\r\n collectionTitles?: CollectionTitles;\r\n\r\n private facetClicked(e: CustomEvent<FacetEventDetails>) {\r\n this.dispatchFacetClickEvent(e.detail);\r\n }\r\n\r\n private dispatchFacetClickEvent(detail: FacetEventDetails) {\r\n const event = new CustomEvent<FacetEventDetails>('facetClick', {\r\n detail,\r\n composed: true,\r\n });\r\n this.dispatchEvent(event);\r\n }\r\n\r\n private get facetsTemplate(): TemplateResult | typeof nothing {\r\n const { facetGroup } = this;\r\n if (!facetGroup) return nothing;\r\n\r\n const facetBuckets = facetGroup.buckets as FacetBucket[];\r\n\r\n // Added data-testid for Playwright testing\r\n // Using className and aria-labels is not ideal for Playwright locator\r\n return html`\r\n <div class=\"facet-rows\" data-testid=\"facets-on-${facetGroup.key}\">\r\n ${repeat(\r\n facetBuckets,\r\n bucket => `${facetGroup.key}:${bucket.key}`,\r\n bucket =>\r\n html`<facet-row\r\n .facetType=${facetGroup.key}\r\n .bucket=${bucket}\r\n .collectionTitles=${this.collectionTitles}\r\n @facetClick=${this.facetClicked}\r\n ></facet-row>`,\r\n )}\r\n </div>\r\n `;\r\n }\r\n\r\n render() {\r\n return html`${this.facetsTemplate}`;\r\n }\r\n\r\n static get styles(): CSSResultGroup {\r\n const columnCount = css`var(--facetsColumnCount, 1)`;\r\n const columnGap = css`var(--facetsColumnGap, 15px)`;\r\n const columnWidth = css`var(--facetsColumnWidth, auto)`;\r\n const maxHeight = css`var(--facetsMaxHeight, none)`;\r\n\r\n return css`\r\n .facet-rows {\r\n column-count: ${columnCount};\r\n column-gap: ${columnGap};\r\n column-width: ${columnWidth};\r\n max-height: ${maxHeight};\r\n column-fill: auto;\r\n }\r\n\r\n a:link,\r\n a:visited {\r\n text-decoration: none;\r\n color: var(--ia-theme-link-color, #4b64ff);\r\n }\r\n a:hover {\r\n text-decoration: underline;\r\n }\r\n `;\r\n }\r\n}\r\n"]}
@@ -5,9 +5,9 @@ import type { AnalyticsManagerInterface } from '@internetarchive/analytics-manag
5
5
  import { SelectedFacets, FacetOption } from '../models';
6
6
  import type { CollectionTitles, PageSpecifierParams, TVChannelAliases } from '../data-source/models';
7
7
  import '@internetarchive/elements/ia-status-indicator/ia-status-indicator';
8
- import './more-facets-pagination';
9
8
  import './facets-template';
10
9
  import './toggle-switch';
10
+ import './more-facets-pagination';
11
11
  export declare class MoreFacetsContent extends LitElement {
12
12
  facetKey?: FacetOption;
13
13
  query?: string;
@@ -51,7 +51,12 @@ export declare class MoreFacetsContent extends LitElement {
51
51
  */
52
52
  private unappliedFacetChanges;
53
53
  /**
54
- * Which page of facets we are showing.
54
+ * Text entered by the user to filter facet buckets.
55
+ * Applied to bucket.key for case-insensitive matching.
56
+ */
57
+ private filterText;
58
+ /**
59
+ * Current page number for pagination (when facet count >= PAGINATION_THRESHOLD).
55
60
  */
56
61
  private pageNumber;
57
62
  willUpdate(changed: PropertyValues): void;
@@ -70,10 +75,6 @@ export declare class MoreFacetsContent extends LitElement {
70
75
  * - this.aggregations - hold result of search service and being used for further processing.
71
76
  */
72
77
  updateSpecificFacets(): Promise<void>;
73
- /**
74
- * Handler for page number changes from the pagination widget.
75
- */
76
- private pageNumberClicked;
77
78
  /**
78
79
  * Combines the selected facets with the aggregations to create a single list of facets
79
80
  */
@@ -89,18 +90,43 @@ export declare class MoreFacetsContent extends LitElement {
89
90
  */
90
91
  private get aggregationFacetGroup();
91
92
  /**
92
- * Returns a FacetGroup representing only the current page of facet buckets to show.
93
+ * Returns the facet group with buckets filtered by the current filter text.
94
+ * Filters are applied to the full bucket list before pagination.
95
+ */
96
+ private get filteredFacetGroup();
97
+ /**
98
+ * Determines whether to use pagination based on the number of filtered facets.
99
+ * Returns true if facet count >= PAGINATION_THRESHOLD, false otherwise.
100
+ */
101
+ private get usePagination();
102
+ /**
103
+ * Returns the facet group for the current page.
104
+ * If using pagination (>= 1000 facets), slices to show only the current page.
105
+ * Otherwise, returns all facets for horizontal scrolling.
93
106
  */
94
107
  private get facetGroupForCurrentPage();
95
108
  private get moreFacetsTemplate();
96
109
  private get loaderTemplate();
110
+ private get emptyFilterResultsTemplate();
97
111
  /**
98
- * How many pages of facets to show in the modal pagination widget
112
+ * Number of pages for pagination (only used when facet count >= PAGINATION_THRESHOLD).
99
113
  */
100
114
  private get paginationSize();
115
+ /**
116
+ * Template for pagination component (only shown when facet count >= PAGINATION_THRESHOLD).
117
+ */
101
118
  private get facetsPaginationTemplate();
102
119
  private get footerTemplate();
103
120
  private sortFacetAggregation;
121
+ /**
122
+ * Handler for filter input changes. Updates the filter text and triggers re-render.
123
+ */
124
+ private handleFilterInput;
125
+ /**
126
+ * Handler for pagination page number clicks.
127
+ * Only used when facet count >= PAGINATION_THRESHOLD.
128
+ */
129
+ private pageNumberClicked;
104
130
  private get modalHeaderTemplate();
105
131
  render(): TemplateResult<1>;
106
132
  private applySearchFacetsClicked;