@fluid-topics/ft-search-bar 0.2.14 → 0.2.17

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.
@@ -34,6 +34,7 @@ export const DEFAULT_LABELS = {
34
34
  clearInputButton: "Clear",
35
35
  clearFilterButton: "Clear",
36
36
  displayMoreFilterValuesButton: "More",
37
+ noFilterValuesAvailable: "No values available",
37
38
  searchButton: "Search",
38
39
  noSuggestions: "No results found…",
39
40
  clearFilters: "Clear filters",
@@ -57,12 +58,15 @@ export class SearchStateChangeEvent extends CustomEvent {
57
58
  super("change", { detail: request });
58
59
  }
59
60
  }
61
+ const doNothing = () => {
62
+ };
60
63
  export class FtSearchBar extends FtLitElement {
61
64
  constructor() {
62
65
  super(...arguments);
63
66
  this.dense = false;
64
67
  this.mode = "auto";
65
68
  this.forceMobileMenuOpen = false;
69
+ this.forceMenuOpen = false;
66
70
  this.baseUrl = "";
67
71
  this.apiIntegrationIdentifier = "ft-search-bar";
68
72
  this.availableContentLocales = [];
@@ -79,7 +83,7 @@ export class FtSearchBar extends FtLitElement {
79
83
  this.mobileMenuOpen = false;
80
84
  this.facets = [];
81
85
  this.facetsInitialized = false;
82
- this.knownFacetLabels = {};
86
+ this.knownFacetLabels = new Map();
83
87
  this.query = "";
84
88
  this.suggestions = [];
85
89
  this.suggestionsLoaded = true;
@@ -101,7 +105,7 @@ export class FtSearchBar extends FtLitElement {
101
105
  && a.filters.every(fa => b.filters.some(fb => this.compareFilters(fa, fb)));
102
106
  }
103
107
  get isMobileMenuOpen() {
104
- return this.forceMobileMenuOpen || this.mobileMenuOpen;
108
+ return this.isMobile && (this.forceMobileMenuOpen || this.forceMenuOpen || this.mobileMenuOpen);
105
109
  }
106
110
  get recentSearchesStorageKey() {
107
111
  return this.baseUrl + ":ft:recent-search-queries";
@@ -177,8 +181,9 @@ export class FtSearchBar extends FtLitElement {
177
181
  "ft-search-bar--dense": !this.isMobile && this.dense,
178
182
  "ft-search-bar--mobile": this.isMobile,
179
183
  "ft-search-bar--desktop": !this.isMobile,
180
- "ft-search-bar--floating-panel-open": !this.isMobile && this.displayFacets,
184
+ "ft-search-bar--floating-panel-open": !this.isMobile && this.displayFacets && !this.forceMenuOpen,
181
185
  "ft-search-bar--mobile-menu-open": this.isMobileMenuOpen,
186
+ "ft-search-bar--forced-open": this.forceMenuOpen || this.forceMobileMenuOpen,
182
187
  };
183
188
  return this.facetsInitialized && this.availableContentLocalesInitialized ? html `
184
189
  <div class="${classMap(rootClasses)}" part="container" tabindex="-1">
@@ -220,8 +225,9 @@ export class FtSearchBar extends FtLitElement {
220
225
  `;
221
226
  }
222
227
  renderMobileSearchBarButtons() {
223
- if (this.query || this.isMobileMenuOpen) {
224
- return html `
228
+ const displayClearButton = this.query || (this.isMobileMenuOpen && !this.forceMobileMenuOpen);
229
+ return html `
230
+ ${displayClearButton ? html `
225
231
  <div class="ft-search-bar--actions"
226
232
  part="search-bar-actions">
227
233
  <ft-button class="ft-search-bar--clear-query"
@@ -229,16 +235,15 @@ export class FtSearchBar extends FtLitElement {
229
235
  icon="close"
230
236
  round
231
237
  label="${this.labelResolver.resolve("clearInputButton")}"
238
+ tooltipPosition="left"
232
239
  @click=${() => {
233
- this.setQuery("");
234
- this.mobileMenuOpen = false;
235
- this.displayFacets = false;
236
- }}
240
+ this.setQuery("");
241
+ this.mobileMenuOpen = false;
242
+ this.displayFacets = false;
243
+ }}
237
244
  ></ft-button>
238
245
  </div>
239
- `;
240
- }
241
- return html `
246
+ ` : nothing}
242
247
  <div class="ft-search-bar--actions"
243
248
  part="search-bar-actions">
244
249
  <ft-button class="ft-search-bar--launch-search"
@@ -246,7 +251,8 @@ export class FtSearchBar extends FtLitElement {
246
251
  icon="search"
247
252
  round
248
253
  label="${this.labelResolver.resolve("searchButton")}"
249
- @click=${() => { var _a; return (_a = this.input) === null || _a === void 0 ? void 0 : _a.focus(); }}
254
+ tooltipPosition="left"
255
+ @click=${() => { var _a; return this.isMobileMenuOpen ? this.launchSearch() : (_a = this.input) === null || _a === void 0 ? void 0 : _a.focus(); }}
250
256
  ></ft-button>
251
257
  </div>
252
258
  `;
@@ -266,7 +272,8 @@ export class FtSearchBar extends FtLitElement {
266
272
  </ft-typography>
267
273
  </div>
268
274
  <ft-filter
269
- part="filters"
275
+ part="filters filter-ft-locale"
276
+ .exportpartsPrefixes=${["filter", "filter-ft-locale"]}
270
277
  class="ft-search-bar--content-locale"
271
278
  filterPlaceHolder="${this.labelResolver.resolve("filterInputPlaceHolder", this.labelResolver.resolve("contentLocaleSelector"))}"
272
279
  .options=${(this.contentLocalesAsFilterOptions())}
@@ -276,7 +283,8 @@ export class FtSearchBar extends FtLitElement {
276
283
  ` : null}
277
284
  ${repeat(this.facets, facet => facet.key, facet => {
278
285
  const filter = facetToFilter(facet);
279
- return html `
286
+ const keyWithNoColumn = facet.key.replace(":", "-");
287
+ return facet.rootNodes.length > 0 ? html `
280
288
  <ft-accordion-item data-facet-key="${facet.key}">
281
289
  <div class="ft-search-bar--filter-label" slot="toggle">
282
290
  <ft-typography variant="button">${facet.label}</ft-typography>
@@ -285,11 +293,13 @@ export class FtSearchBar extends FtLitElement {
285
293
  </ft-typography>
286
294
  </div>
287
295
  <ft-filter
288
- part="filters"
296
+ part="filters filter filter-${keyWithNoColumn}"
297
+ .exportpartsPrefixes=${["filter", "filter-" + keyWithNoColumn]}
289
298
  id="${filter.id}"
290
299
  filterPlaceHolder="${this.labelResolver.resolve("filterInputPlaceHolder", filter.label)}"
291
300
  clearButtonLabel="${this.labelResolver.resolve("clearFilterButton")}"
292
301
  moreValuesButtonLabel="${this.labelResolver.resolve("displayMoreFilterValuesButton")}"
302
+ noValuesLabel="${this.labelResolver.resolve("noFilterValuesAvailable")}"
293
303
  ?multivalued=${filter.multivalued}
294
304
  raiseSelectedOptions
295
305
  .options=${filter.options}
@@ -297,7 +307,7 @@ export class FtSearchBar extends FtLitElement {
297
307
  @change=${(e) => this.setFilter(filter.id, e.detail)}
298
308
  ></ft-filter>
299
309
  </ft-accordion-item>
300
- `;
310
+ ` : nothing;
301
311
  })}
302
312
  </ft-accordion>
303
313
  `;
@@ -327,25 +337,35 @@ export class FtSearchBar extends FtLitElement {
327
337
  ${this.renderSuggestions()}
328
338
  </div>
329
339
  ${this.renderDesktopSearchBarButtons()}
330
- <div class="ft-search-bar--floating-panel" @keyup=${this.onFloatingContainerKeyUp} tabindex="-1">
331
- ${this.renderFacetsActions()}
332
- ${this.renderDesktopFacets()}
333
- <div class="ft-search-bar--facets-actions">
334
- <ft-button class="ft-search-bar--launch-search"
335
- part="launch-search-in-panel"
336
- icon="search"
337
- @click=${this.launchSearch}>
338
- ${this.labelResolver.resolve("searchButton")}
339
- </ft-button>
340
- </div>
341
- </div>
340
+ ${this.forceMenuOpen ? nothing : html `
341
+ <div class="ft-search-bar--floating-panel" @keyup=${this.onFloatingContainerKeyUp}
342
+ tabindex="-1">
343
+ ${this.renderDesktopMenu()}
344
+ </div>`}
342
345
  </div>
343
- ${this.dense ? nothing : this.renderSelectedFacets()}
346
+ ${this.dense || this.forceMenuOpen ? (this.forceMenuOpen ? this.renderDesktopMenu() : nothing) : this.renderSelectedFacets()}
344
347
  `;
345
348
  }
349
+ renderDesktopMenu() {
350
+ return this.hasFacets ? html `
351
+ <div class="ft-search-bar--desktop-menu">
352
+ ${this.renderFacetsActions()}
353
+ ${this.renderDesktopFacets()}
354
+ <div class="ft-search-bar--facets-actions">
355
+ ${this.forceMenuOpen ? this.renderDesktopClearFilters() : nothing}
356
+ <ft-button class="ft-search-bar--launch-search"
357
+ part="launch-search-in-panel"
358
+ icon="search"
359
+ @click=${this.launchSearch}>
360
+ ${this.labelResolver.resolve("searchButton")}
361
+ </ft-button>
362
+ </div>
363
+ </div>
364
+ ` : nothing;
365
+ }
346
366
  renderSearchBarLeftAction() {
347
367
  if (this.hasFacets) {
348
- return html `
368
+ return this.forceMenuOpen ? nothing : html `
349
369
  <ft-button class="ft-search-bar--filters-opener ft-search-bar--left-action"
350
370
  part="filters-opener"
351
371
  trailingIcon
@@ -359,7 +379,7 @@ export class FtSearchBar extends FtLitElement {
359
379
  </ft-button>
360
380
  `;
361
381
  }
362
- if (this.hasLocaleSelector) {
382
+ else if (this.hasLocaleSelector) {
363
383
  return html `
364
384
  <ft-select outlined
365
385
  class="ft-search-bar--content-locale ft-search-bar--left-action"
@@ -419,16 +439,19 @@ export class FtSearchBar extends FtLitElement {
419
439
  `)}
420
440
  </ft-select>
421
441
  ` : nothing}
422
- ${this.searchFilters.length > 0 ? html `
423
- <ft-button part="facets-actions"
424
- @click=${this.clearFilters}>
425
- ${this.labelResolver.resolve("clearFilters")}
426
- </ft-button>
427
- ` : nothing}
428
442
  <slot name="facets-actions"></slot>
443
+ ${this.forceMenuOpen && !this.isMobile ? nothing : this.renderDesktopClearFilters()}
429
444
  </div>
430
445
  `;
431
446
  }
447
+ renderDesktopClearFilters() {
448
+ return this.searchFilters.length > 0 ? html `
449
+ <ft-button part="facets-actions"
450
+ @click=${this.clearFilters}>
451
+ ${this.labelResolver.resolve("clearFilters")}
452
+ </ft-button>
453
+ ` : nothing;
454
+ }
432
455
  renderDesktopFacets() {
433
456
  if (!this.hasFacets) {
434
457
  return nothing;
@@ -436,10 +459,12 @@ export class FtSearchBar extends FtLitElement {
436
459
  return html `
437
460
  <ft-snap-scroll horizontal limitSize controls
438
461
  class="ft-search-bar--filters-container"
439
- part="filters-container">
462
+ part="filters-container"
463
+ exportpartsPrefix="filters-container">
440
464
  ${this.hasLocaleSelector ? html `
441
- <ft-filter part="filters"
442
- class="ft-search-bar--content-locale"
465
+ <ft-filter class="ft-search-bar--content-locale"
466
+ part="filters filter-ft-locale"
467
+ .exportpartsPrefixes=${["filter", "filter-ft-locale"]}
443
468
  label="${this.labelResolver.resolve("contentLocaleSelector")}"
444
469
  filterPlaceHolder="${this.labelResolver.resolve("filterInputPlaceHolder", this.labelResolver.resolve("contentLocaleSelector"))}"
445
470
  .options=${(this.contentLocalesAsFilterOptions())}
@@ -449,15 +474,18 @@ export class FtSearchBar extends FtLitElement {
449
474
  ${repeat(this.facets, facet => facet.key, facet => {
450
475
  const filter = facetToFilter(facet);
451
476
  const hierachical = filter.options.some(o => { var _a, _b; return ((_b = (_a = o.subOptions) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0; });
477
+ const keyWithNoColumn = facet.key.replace(":", "-");
452
478
  return html `
453
479
  <ft-filter
454
480
  class="${hierachical ? "ft-search-bar--hierarchical-filter" : ""}"
455
- part="filters"
481
+ part="filters filter filter-${keyWithNoColumn}"
482
+ .exportpartsPrefixes=${["filter", "filter-" + keyWithNoColumn]}
456
483
  id="${filter.id}"
457
484
  label="${filter.label}"
458
485
  filterPlaceHolder="${this.labelResolver.resolve("filterInputPlaceHolder", filter.label)}"
459
486
  clearButtonLabel="${this.labelResolver.resolve("clearFilterButton")}"
460
487
  moreValuesButtonLabel="${this.labelResolver.resolve("displayMoreFilterValuesButton")}"
488
+ noValuesLabel="${this.labelResolver.resolve("noFilterValuesAvailable")}"
461
489
  ?multivalued=${filter.multivalued}
462
490
  raiseSelectedOptions
463
491
  .options=${filter.options}
@@ -476,7 +504,7 @@ export class FtSearchBar extends FtLitElement {
476
504
  const useSnapScroll = (!this.isMobile && this.dense) || (this.isMobile && this.isMobileMenuOpen);
477
505
  const filters = html `
478
506
  ${this.hasLocaleSelector && (this.hasFacets || this.isMobile) ? html `
479
- <ft-chip part="selected-filters"
507
+ <ft-chip part="selected-filters selected-filter-ft-locale"
480
508
  ?dense=${this.dense && !this.isMobile}
481
509
  ?clickable=${this.isMobile}
482
510
  @click=${() => this.openMobileFilters("ft:contentLocale")}>
@@ -487,9 +515,10 @@ export class FtSearchBar extends FtLitElement {
487
515
  const values = getSelectedValues(facet);
488
516
  return repeat(values, value => {
489
517
  let label = facet.label + ": " + getBreadcrumbFromValue(value);
518
+ const keyWithNoColumn = facet.key.replace(":", "-");
490
519
  const chip = html `
491
520
  <ft-chip
492
- part="selected-filters"
521
+ part="selected-filters selected-filter-${keyWithNoColumn}"
493
522
  ?dense=${this.dense && !this.isMobile}
494
523
  ?clickable=${this.isMobile}
495
524
  ?removable=${!this.isMobile}
@@ -509,7 +538,7 @@ export class FtSearchBar extends FtLitElement {
509
538
  });
510
539
  })}
511
540
  ${this.isMobile ? html `
512
- <ft-chip part="selected-filters"
541
+ <ft-chip part="selected-filters mobile-filters-opener"
513
542
  icon="add"
514
543
  clickable
515
544
  @click=${() => {
@@ -524,7 +553,8 @@ export class FtSearchBar extends FtLitElement {
524
553
  ? html `
525
554
  <ft-snap-scroll horizontal controls hideScrollbar limitSize
526
555
  class="ft-search-bar--selected-filters"
527
- part="selected-filters-container">
556
+ part="selected-filters-container"
557
+ exportpartsPrefix="selected-filters-container">
528
558
  ${filters}
529
559
  </ft-snap-scroll>
530
560
  `
@@ -554,6 +584,7 @@ export class FtSearchBar extends FtLitElement {
554
584
  part="remove-suggestion"
555
585
  ?dense=${!this.isMobile}
556
586
  label="${this.labelResolver.resolve("removeRecentSearch")}"
587
+ tooltipPosition="left"
557
588
  @click=${(e) => this.removeRecentSearch(e, query)}></ft-button>
558
589
  </a>
559
590
  `)}
@@ -640,6 +671,9 @@ export class FtSearchBar extends FtLitElement {
640
671
  this.setFiltersFromPreset(currentPreset);
641
672
  }
642
673
  }
674
+ if (props.has("contentLocale") && this.contentLocale != null) {
675
+ this.knownFacetLabels = new Map();
676
+ }
643
677
  if (["contentLocale", "searchFilters"].some(p => props.has(p))) {
644
678
  this.selectedPreset = (_f = ((_e = this.presets) !== null && _e !== void 0 ? _e : []).find(p => this.compareRequests(p, this.request))) === null || _f === void 0 ? void 0 : _f.name;
645
679
  }
@@ -694,9 +728,27 @@ export class FtSearchBar extends FtLitElement {
694
728
  if (this.facetsRequest.length > 0) {
695
729
  this.facetsLoaded = false;
696
730
  this.updateFacetsDebouncer.run(async () => {
697
- var _a, _b;
698
- this.facets = (_b = await ((_a = this.api) === null || _a === void 0 ? void 0 : _a.search({ ...this.request, query: "" }).then(r => r.facets).catch(() => []))) !== null && _b !== void 0 ? _b : [];
699
- this.facets.forEach(f => this.knownFacetLabels[f.key] = f.label);
731
+ var _a;
732
+ const retrievedFacets = new Map();
733
+ await ((_a = this.api) === null || _a === void 0 ? void 0 : _a.search({ ...this.request, query: "" }).then(r => r.facets.forEach(f => {
734
+ this.knownFacetLabels.set(f.key, f.label);
735
+ retrievedFacets.set(f.key, f);
736
+ })).catch(doNothing));
737
+ this.facets = [];
738
+ for (let r of this.facetsRequest) {
739
+ if (retrievedFacets.has(r.id)) {
740
+ this.facets.push(retrievedFacets.get(r.id));
741
+ }
742
+ else if (this.knownFacetLabels.has(r.id)) {
743
+ this.facets.push({
744
+ key: r.id,
745
+ label: this.knownFacetLabels.get(r.id),
746
+ rootNodes: [],
747
+ multiSelectionable: true,
748
+ hierarchical: false
749
+ });
750
+ }
751
+ }
700
752
  this.facetsLoaded = true;
701
753
  this.facetsInitialized = true;
702
754
  });
@@ -887,6 +939,9 @@ __decorate([
887
939
  __decorate([
888
940
  property({ type: Boolean })
889
941
  ], FtSearchBar.prototype, "forceMobileMenuOpen", void 0);
942
+ __decorate([
943
+ property({ type: Boolean })
944
+ ], FtSearchBar.prototype, "forceMenuOpen", void 0);
890
945
  __decorate([
891
946
  property()
892
947
  ], FtSearchBar.prototype, "baseUrl", void 0);