From defbc03a623feeaddd664d30b54a9b7f9f3dcdba Mon Sep 17 00:00:00 2001
From: Olivia Guyot <olivia.guyot@camptocamp.com>
Date: Fri, 20 Oct 2023 15:34:35 +0200
Subject: [PATCH 1/7] feat(wc): implement a general cdk overlay for all web
 components

This will work with any webcomponent by creating an overlay at the root of each
webcomponent

Changed the name of the custom OverlayContainer for clarity
---
 .../src/app/AppOverlayContainer.ts            | 41 -------------------
 .../src/app/components/base.component.ts      | 17 +++++++-
 .../gn-search-input.component.html            |  4 +-
 .../src/app/webcomponent-overlay-container.ts | 32 +++++++++++++++
 .../src/app/webcomponents.module.ts           | 14 ++-----
 apps/webcomponents/src/styles.css             |  4 +-
 6 files changed, 55 insertions(+), 57 deletions(-)
 delete mode 100644 apps/webcomponents/src/app/AppOverlayContainer.ts
 create mode 100644 apps/webcomponents/src/app/webcomponent-overlay-container.ts

diff --git a/apps/webcomponents/src/app/AppOverlayContainer.ts b/apps/webcomponents/src/app/AppOverlayContainer.ts
deleted file mode 100644
index 73c6f3249f..0000000000
--- a/apps/webcomponents/src/app/AppOverlayContainer.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import { OverlayContainer } from '@angular/cdk/overlay'
-import { Platform } from '@angular/cdk/platform'
-import { DOCUMENT } from '@angular/common'
-import { Inject, Injectable, OnDestroy } from '@angular/core'
-
-@Injectable()
-export class AppOverlayContainer extends OverlayContainer implements OnDestroy {
-  private selector: string
-
-  constructor(
-    @Inject(DOCUMENT) private document: Document,
-    platform: Platform
-  ) {
-    super(document, platform)
-  }
-
-  setSelector(selector: string) {
-    this.selector = selector
-  }
-  ngOnDestroy() {
-    super.ngOnDestroy()
-  }
-
-  protected _createContainer(): void {
-    const container: HTMLDivElement = this.document.createElement('div')
-    container.classList.add('app-overlay-container')
-    const element: Element | null = this.document
-      .querySelector(this.selector)
-      .shadowRoot.querySelector('#angular-app-root')
-    if (element !== null) {
-      element.appendChild(container)
-      this._containerElement = container
-    } else {
-      console.error(
-        'Material CDK Overlay creation failed ! ' +
-          'It can work only with gn-search-input webcomponent. ' +
-          'You have to add an element with id="angular-app-root" (in the shadowDOM) to which the overlay will be appended.'
-      )
-    }
-  }
-}
diff --git a/apps/webcomponents/src/app/components/base.component.ts b/apps/webcomponents/src/app/components/base.component.ts
index 0c3a3b63e7..f31461387a 100644
--- a/apps/webcomponents/src/app/components/base.component.ts
+++ b/apps/webcomponents/src/app/components/base.component.ts
@@ -1,4 +1,11 @@
-import { Component, Injector, Input, OnChanges, OnInit } from '@angular/core'
+import {
+  Component,
+  ElementRef,
+  Injector,
+  Input,
+  OnChanges,
+  OnInit,
+} from '@angular/core'
 import {
   LinkClassifierService,
   LinkUsage,
@@ -10,6 +17,8 @@ import { TranslateService } from '@ngx-translate/core'
 import { firstValueFrom } from 'rxjs'
 import { DatasetDistribution } from '@geonetwork-ui/common/domain/record'
 import { RecordsRepositoryInterface } from '@geonetwork-ui/common/domain/records-repository.interface'
+import { OverlayContainer } from '@angular/cdk/overlay'
+import { WebcomponentOverlayContainer } from '../webcomponent-overlay-container'
 
 export const apiConfiguration = new Configuration()
 
@@ -40,6 +49,12 @@ export class BaseComponent implements OnChanges, OnInit {
     this.searchService = injector.get(SearchApiService)
     this.recordsRepository = injector.get(RecordsRepositoryInterface)
     this.linkClassifier = injector.get(LinkClassifierService)
+
+    const elementRef = injector.get(ElementRef)
+    const overlayContainer = injector.get(
+      OverlayContainer
+    ) as WebcomponentOverlayContainer
+    overlayContainer.setRoot(elementRef.nativeElement.shadowRoot)
   }
 
   ngOnInit() {
diff --git a/apps/webcomponents/src/app/components/gn-search-input/gn-search-input.component.html b/apps/webcomponents/src/app/components/gn-search-input/gn-search-input.component.html
index 4abf44b912..1b159ba380 100644
--- a/apps/webcomponents/src/app/components/gn-search-input/gn-search-input.component.html
+++ b/apps/webcomponents/src/app/components/gn-search-input/gn-search-input.component.html
@@ -1,3 +1 @@
-<div id="angular-app-root">
-  <gn-ui-fuzzy-search #searchInput class="text-[18px]"></gn-ui-fuzzy-search>
-</div>
+<gn-ui-fuzzy-search #searchInput class="text-[18px]"></gn-ui-fuzzy-search>
diff --git a/apps/webcomponents/src/app/webcomponent-overlay-container.ts b/apps/webcomponents/src/app/webcomponent-overlay-container.ts
new file mode 100644
index 0000000000..6a2415c7ac
--- /dev/null
+++ b/apps/webcomponents/src/app/webcomponent-overlay-container.ts
@@ -0,0 +1,32 @@
+import { OverlayContainer } from '@angular/cdk/overlay'
+import { Platform } from '@angular/cdk/platform'
+import { DOCUMENT } from '@angular/common'
+import { Inject, Injectable } from '@angular/core'
+
+@Injectable()
+export class WebcomponentOverlayContainer extends OverlayContainer {
+  private componentRoot: HTMLElement
+
+  constructor(
+    @Inject(DOCUMENT) private document: Document,
+    platform: Platform
+  ) {
+    super(document, platform)
+  }
+
+  setRoot(componentRoot: HTMLElement) {
+    this.componentRoot = componentRoot
+  }
+
+  protected _createContainer(): void {
+    const container: HTMLDivElement = this.document.createElement('div')
+    container.classList.add('gn-ui-overlay-container')
+    if (!this.componentRoot) {
+      throw new Error(
+        'Angular CDK OverlayContainer was used without proper initialization.'
+      )
+    }
+    this.componentRoot.appendChild(container)
+    this._containerElement = container
+  }
+}
diff --git a/apps/webcomponents/src/app/webcomponents.module.ts b/apps/webcomponents/src/app/webcomponents.module.ts
index 452151d851..fa0f1cf47e 100644
--- a/apps/webcomponents/src/app/webcomponents.module.ts
+++ b/apps/webcomponents/src/app/webcomponents.module.ts
@@ -1,6 +1,5 @@
 import { OverlayContainer } from '@angular/cdk/overlay'
-import { Platform } from '@angular/cdk/platform'
-import { CommonModule, DOCUMENT } from '@angular/common'
+import { CommonModule } from '@angular/common'
 import { CUSTOM_ELEMENTS_SCHEMA, Injector, NgModule } from '@angular/core'
 import { createCustomElement } from '@angular/elements'
 import { MatIconModule } from '@angular/material/icon'
@@ -12,6 +11,7 @@ import { UiElementsModule } from '@geonetwork-ui/ui/elements'
 import { UiInputsModule } from '@geonetwork-ui/ui/inputs'
 import { UiSearchModule } from '@geonetwork-ui/ui/search'
 import {
+  EmbeddedTranslateLoader,
   TRANSLATE_DEFAULT_CONFIG,
   UtilI18nModule,
 } from '@geonetwork-ui/util/i18n'
@@ -20,7 +20,7 @@ import { StoreModule } from '@ngrx/store'
 import { StoreDevtoolsModule } from '@ngrx/store-devtools'
 import { TranslateLoader, TranslateModule } from '@ngx-translate/core'
 import { AppComponent } from './app.component'
-import { AppOverlayContainer } from './AppOverlayContainer'
+import { WebcomponentOverlayContainer } from './webcomponent-overlay-container'
 import { apiConfiguration, BaseComponent } from './components/base.component'
 import { GnAggregatedRecordsComponent } from './components/gn-aggregated-records/gn-aggregated-records.component'
 import { GnFacetsComponent } from './components/gn-facets/gn-facets.component'
@@ -31,7 +31,6 @@ import { GnMapViewerComponent } from './components/gn-map-viewer/gn-map-viewer.c
 import { FeatureMapModule } from '@geonetwork-ui/feature/map'
 import { GnDatasetViewChartComponent } from './components/gn-dataset-view-chart/gn-dataset-view-chart.component'
 import { FeatureDatavizModule } from '@geonetwork-ui/feature/dataviz'
-import { EmbeddedTranslateLoader } from '@geonetwork-ui/util/i18n'
 import { FeatureAuthModule } from '@geonetwork-ui/feature/auth'
 import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
 
@@ -90,12 +89,7 @@ const CUSTOM_ELEMENTS: [new (...args) => BaseComponent, string][] = [
     },
     {
       provide: OverlayContainer,
-      useFactory: (document: Document, platform: Platform) => {
-        const container = new AppOverlayContainer(document, platform)
-        container.setSelector('gn-search-input')
-        return container
-      },
-      deps: [DOCUMENT, Platform],
+      useClass: WebcomponentOverlayContainer,
     },
   ],
   schemas: [CUSTOM_ELEMENTS_SCHEMA],
diff --git a/apps/webcomponents/src/styles.css b/apps/webcomponents/src/styles.css
index 4814c8c96c..e614fc4a34 100644
--- a/apps/webcomponents/src/styles.css
+++ b/apps/webcomponents/src/styles.css
@@ -51,7 +51,7 @@
   min-width: 1px;
   min-height: 1px;
 }
-.app-overlay-container {
+.gn-ui-overlay-container {
   position: absolute;
   z-index: 1000;
   pointer-events: none;
@@ -60,7 +60,7 @@
   height: 100%;
   width: 100%;
 }
-.app-overlay-container:empty {
+.gn-ui-overlay-container:empty {
   display: none;
 }
 

From 449147263cb6cef119300987d382f7758c19b646 Mon Sep 17 00:00:00 2001
From: Olivia Guyot <olivia.guyot@camptocamp.com>
Date: Fri, 20 Oct 2023 15:35:37 +0200
Subject: [PATCH 2/7] chore(wc): fix font url for material icons

---
 apps/webcomponents/src/styles.css | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/apps/webcomponents/src/styles.css b/apps/webcomponents/src/styles.css
index e614fc4a34..2e69e7cea4 100644
--- a/apps/webcomponents/src/styles.css
+++ b/apps/webcomponents/src/styles.css
@@ -13,7 +13,7 @@
   font-family: 'Material Symbols Outlined';
   font-style: normal;
   font-weight: 400;
-  src: url(https://fonts.gstatic.com/s/materialiconsoutlined/v108/gok-H7zzDkdnRel8-DQ6KAXJ69wP1tGnf4ZGhUce.woff2)
+  src: url(https://fonts.gstatic.com/s/materialsymbolsoutlined/v138/kJEhBvYX7BgnkSrUwT8OhrdQw4oELdPIeeII9v6oFsLjBuVY.woff2)
     format('woff2');
 }
 .material-symbols-outlined {

From 697802f9c176408efd43300f098a075c3f2b4fcb Mon Sep 17 00:00:00 2001
From: Olivia Guyot <olivia.guyot@camptocamp.com>
Date: Fri, 20 Oct 2023 16:02:43 +0200
Subject: [PATCH 3/7] feat(inputs): use outsideClick instead of backdropClick
 to close overlays

---
 .../dropdown-multiselect/dropdown-multiselect.component.html    | 2 +-
 .../src/lib/dropdown-selector/dropdown-selector.component.html  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/libs/ui/inputs/src/lib/dropdown-multiselect/dropdown-multiselect.component.html b/libs/ui/inputs/src/lib/dropdown-multiselect/dropdown-multiselect.component.html
index c938fe3cc1..439d197378 100644
--- a/libs/ui/inputs/src/lib/dropdown-multiselect/dropdown-multiselect.component.html
+++ b/libs/ui/inputs/src/lib/dropdown-multiselect/dropdown-multiselect.component.html
@@ -43,7 +43,7 @@
   [cdkConnectedOverlayPositions]="overlayPositions"
   [cdkConnectedOverlayScrollStrategy]="scrollStrategy"
   [cdkConnectedOverlayFlexibleDimensions]="true"
-  (backdropClick)="closeOverlay()"
+  (overlayOutsideClick)="closeOverlay()"
   (detach)="closeOverlay()"
 >
   <div
diff --git a/libs/ui/inputs/src/lib/dropdown-selector/dropdown-selector.component.html b/libs/ui/inputs/src/lib/dropdown-selector/dropdown-selector.component.html
index 972dd747f9..54a3ba7987 100644
--- a/libs/ui/inputs/src/lib/dropdown-selector/dropdown-selector.component.html
+++ b/libs/ui/inputs/src/lib/dropdown-selector/dropdown-selector.component.html
@@ -37,7 +37,7 @@
   [cdkConnectedOverlayOpen]="overlayOpen"
   [cdkConnectedOverlayPositions]="overlayPositions"
   [cdkConnectedOverlayFlexibleDimensions]="true"
-  (backdropClick)="closeOverlay()"
+  (overlayOutsideClick)="closeOverlay()"
   (detach)="closeOverlay()"
 >
   <div

From 865d47fb7f2de015481ca9e066d18cad7a29e5b5 Mon Sep 17 00:00:00 2001
From: Olivia Guyot <olivia.guyot@camptocamp.com>
Date: Fri, 20 Oct 2023 20:02:01 +0200
Subject: [PATCH 4/7] feat(search): do not emit inputSubmitted if only clearing
 the search field

---
 .../fuzzy-search/fuzzy-search.component.html  |  1 +
 .../fuzzy-search.component.spec.ts            | 23 ++++++++++++++++---
 .../fuzzy-search/fuzzy-search.component.ts    |  4 ++++
 .../autocomplete.component.spec.ts            | 20 +++++++++-------
 .../autocomplete/autocomplete.component.ts    |  3 ++-
 5 files changed, 39 insertions(+), 12 deletions(-)

diff --git a/libs/feature/search/src/lib/fuzzy-search/fuzzy-search.component.html b/libs/feature/search/src/lib/fuzzy-search/fuzzy-search.component.html
index ea7fcafe9e..0ce3113a7f 100644
--- a/libs/feature/search/src/lib/fuzzy-search/fuzzy-search.component.html
+++ b/libs/feature/search/src/lib/fuzzy-search/fuzzy-search.component.html
@@ -4,6 +4,7 @@
   [action]="autoCompleteAction"
   (itemSelected)="handleItemSelection($event)"
   (inputSubmitted)="handleInputSubmission($event)"
+  (inputCleared)="handleInputCleared()"
   [value]="searchInputValue$ | async"
   [clearOnSelection]="true"
 ></gn-ui-autocomplete>
diff --git a/libs/feature/search/src/lib/fuzzy-search/fuzzy-search.component.spec.ts b/libs/feature/search/src/lib/fuzzy-search/fuzzy-search.component.spec.ts
index 39328db8d9..b4f31ca72a 100644
--- a/libs/feature/search/src/lib/fuzzy-search/fuzzy-search.component.spec.ts
+++ b/libs/feature/search/src/lib/fuzzy-search/fuzzy-search.component.spec.ts
@@ -109,7 +109,6 @@ describe('FuzzySearchComponent', () => {
   })
 
   describe('search enter key press', () => {
-    let outputValue
     describe('when no output defined', () => {
       beforeEach(() => {
         component.handleInputSubmission('blarg')
@@ -123,8 +122,7 @@ describe('FuzzySearchComponent', () => {
     describe('when output is defined', () => {
       beforeEach(() => {
         jest.resetAllMocks()
-        outputValue = null
-        component.inputSubmitted.subscribe((event) => (outputValue = event))
+        component.inputSubmitted.subscribe()
         jest.spyOn(component.inputSubmitted, 'emit')
         component.handleInputSubmission('blarg')
       })
@@ -139,6 +137,25 @@ describe('FuzzySearchComponent', () => {
     })
   })
 
+  describe('search input clear', () => {
+    describe('when output is defined', () => {
+      beforeEach(() => {
+        jest.resetAllMocks()
+        component.inputSubmitted.subscribe()
+        jest.spyOn(component.inputSubmitted, 'emit')
+        component.handleInputCleared()
+      })
+      it('clears the search filters', () => {
+        expect(searchService.updateFilters).toHaveBeenCalledWith({
+          any: '',
+        })
+      })
+      it('does not emit inputSubmitted', () => {
+        expect(component.inputSubmitted.emit).not.toHaveBeenCalled()
+      })
+    })
+  })
+
   describe('search suggestion selection', () => {
     describe('when no output defined', () => {
       beforeEach(() => {
diff --git a/libs/feature/search/src/lib/fuzzy-search/fuzzy-search.component.ts b/libs/feature/search/src/lib/fuzzy-search/fuzzy-search.component.ts
index b13e99b905..2e80a32aec 100644
--- a/libs/feature/search/src/lib/fuzzy-search/fuzzy-search.component.ts
+++ b/libs/feature/search/src/lib/fuzzy-search/fuzzy-search.component.ts
@@ -72,4 +72,8 @@ export class FuzzySearchComponent implements OnInit {
       this.searchService.updateFilters({ any })
     }
   }
+
+  handleInputCleared() {
+    this.searchService.updateFilters({ any: '' })
+  }
 }
diff --git a/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.spec.ts b/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.spec.ts
index be2eb5d4b1..7c11ac9daa 100644
--- a/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.spec.ts
+++ b/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.spec.ts
@@ -111,34 +111,38 @@ describe('AutocompleteComponent', () => {
       })
     })
     describe('when input is not empty', () => {
-      let anyEmitted
+      let anyEmitted: boolean
+      let clearEmitted: boolean
       let button
       beforeEach(() => {
+        anyEmitted = false
+        clearEmitted = false
         component.inputRef.nativeElement.value = 'blar'
         component.inputRef.nativeElement.dispatchEvent(new InputEvent('input'))
         component.triggerRef.closePanel = jest.fn()
-        component.inputSubmitted.subscribe((event) => (anyEmitted = event))
+        component.inputSubmitted.subscribe(() => (anyEmitted = true))
+        component.inputCleared.subscribe(() => (clearEmitted = true))
         fixture.detectChanges()
         button = fixture.debugElement.query(By.css('.clear-btn'))
+        button.nativeElement.click()
       })
       it('is visible', () => {
         expect(button).not.toBeNull()
       })
       it('resets the text input', () => {
-        button.nativeElement.click()
         expect(component.inputRef.nativeElement.value).toBe('')
       })
       it('sets the text input of the focus', () => {
-        button.nativeElement.click()
         expect(document.activeElement).toBe(component.inputRef.nativeElement)
       })
       it('closes the autocomplete panel', () => {
-        button.nativeElement.click()
         expect(component.triggerRef.closePanel).toHaveBeenCalled()
       })
-      it('clears search result by emitting empty string', () => {
-        button.nativeElement.click()
-        expect(anyEmitted).toEqual('')
+      it('does not emit an inputSubmitted event', () => {
+        expect(anyEmitted).toEqual(false)
+      })
+      it('emits an inputCleared event', () => {
+        expect(clearEmitted).toEqual(true)
       })
     })
   })
diff --git a/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.ts b/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.ts
index d8c9c25441..2442fe4c83 100644
--- a/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.ts
+++ b/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.ts
@@ -49,6 +49,7 @@ export class AutocompleteComponent
   @Input() clearOnSelection = false
   @Output() itemSelected = new EventEmitter<AutocompleteItem>()
   @Output() inputSubmitted = new EventEmitter<string>()
+  @Output() inputCleared = new EventEmitter<void>()
   @ViewChild(MatAutocompleteTrigger) triggerRef: MatAutocompleteTrigger
   @ViewChild(MatAutocomplete) autocomplete: MatAutocomplete
   @ViewChild('searchInput') inputRef: ElementRef<HTMLInputElement>
@@ -126,7 +127,7 @@ export class AutocompleteComponent
 
   clear(): void {
     this.inputRef.nativeElement.value = ''
-    this.inputSubmitted.emit('')
+    this.inputCleared.emit()
     this.selectionSubject
       .pipe(take(1))
       .subscribe((selection) => selection && selection.option.deselect())

From c3d7ceccac87ef3005e11d34516b1f71efe26796 Mon Sep 17 00:00:00 2001
From: Olivia Guyot <olivia.guyot@camptocamp.com>
Date: Fri, 20 Oct 2023 20:23:37 +0200
Subject: [PATCH 5/7] fix(wc): do not include icons font in samples; this
 shouldn't be needed

---
 .../gn-dataset-view-chart/gn-dataset-view-chart.sample.html   | 4 ----
 .../gn-dataset-view-table/gn-dataset-view-table.sample.html   | 4 ----
 .../src/app/components/gn-facets/gn-facets.sample.html        | 4 ----
 .../app/components/gn-map-viewer/gn-map-viewer.sample.html    | 4 ----
 .../gn-results-list/gn-results-list-multiple.sample.html      | 4 ----
 .../components/gn-results-list/gn-results-list.sample.html    | 4 ----
 .../gn-search-input/gn-search-input-and-results.sample.html   | 4 ----
 .../components/gn-search-input/gn-search-input.sample.html    | 4 ----
 8 files changed, 32 deletions(-)

diff --git a/apps/webcomponents/src/app/components/gn-dataset-view-chart/gn-dataset-view-chart.sample.html b/apps/webcomponents/src/app/components/gn-dataset-view-chart/gn-dataset-view-chart.sample.html
index d875ef9b79..aa88dcf175 100644
--- a/apps/webcomponents/src/app/components/gn-dataset-view-chart/gn-dataset-view-chart.sample.html
+++ b/apps/webcomponents/src/app/components/gn-dataset-view-chart/gn-dataset-view-chart.sample.html
@@ -7,10 +7,6 @@
     <meta name="viewport" content="width=device-width, initial-scale=1" />
     <link rel="preconnect" href="https://fonts.googleapis.com" />
     <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
-    <link
-      rel="stylesheet"
-      href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200"
-    />
     <link
       href="https://fonts.googleapis.com/css2?family=DM+Serif+Display&amp;family=Inter:wght@200;300;400;500;600;700&amp;display=swap"
       rel="stylesheet"
diff --git a/apps/webcomponents/src/app/components/gn-dataset-view-table/gn-dataset-view-table.sample.html b/apps/webcomponents/src/app/components/gn-dataset-view-table/gn-dataset-view-table.sample.html
index 4562243244..1b198f115a 100644
--- a/apps/webcomponents/src/app/components/gn-dataset-view-table/gn-dataset-view-table.sample.html
+++ b/apps/webcomponents/src/app/components/gn-dataset-view-table/gn-dataset-view-table.sample.html
@@ -7,10 +7,6 @@
     <meta name="viewport" content="width=device-width, initial-scale=1" />
     <link rel="preconnect" href="https://fonts.googleapis.com" />
     <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
-    <link
-      rel="stylesheet"
-      href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200"
-    />
     <link
       href="https://fonts.googleapis.com/css2?family=DM+Serif+Display&amp;family=Inter:wght@200;300;400;500;600;700&amp;display=swap"
       rel="stylesheet"
diff --git a/apps/webcomponents/src/app/components/gn-facets/gn-facets.sample.html b/apps/webcomponents/src/app/components/gn-facets/gn-facets.sample.html
index 71745a04e1..45bc3b676e 100644
--- a/apps/webcomponents/src/app/components/gn-facets/gn-facets.sample.html
+++ b/apps/webcomponents/src/app/components/gn-facets/gn-facets.sample.html
@@ -7,10 +7,6 @@
     <meta name="viewport" content="width=device-width, initial-scale=1" />
     <link rel="preconnect" href="https://fonts.googleapis.com" />
     <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
-    <link
-      rel="stylesheet"
-      href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200"
-    />
     <link
       href="https://fonts.googleapis.com/css2?family=DM+Serif+Display&amp;family=Inter:wght@200;300;400;500;600;700&amp;display=swap"
       rel="stylesheet"
diff --git a/apps/webcomponents/src/app/components/gn-map-viewer/gn-map-viewer.sample.html b/apps/webcomponents/src/app/components/gn-map-viewer/gn-map-viewer.sample.html
index f5dc23a59d..050d960d98 100644
--- a/apps/webcomponents/src/app/components/gn-map-viewer/gn-map-viewer.sample.html
+++ b/apps/webcomponents/src/app/components/gn-map-viewer/gn-map-viewer.sample.html
@@ -7,10 +7,6 @@
     <meta name="viewport" content="width=device-width, initial-scale=1" />
     <link rel="preconnect" href="https://fonts.googleapis.com" />
     <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
-    <link
-      rel="stylesheet"
-      href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200"
-    />
     <link
       href="https://fonts.googleapis.com/css2?family=DM+Serif+Display&amp;family=Inter:wght@200;300;400;500;600;700&amp;display=swap"
       rel="stylesheet"
diff --git a/apps/webcomponents/src/app/components/gn-results-list/gn-results-list-multiple.sample.html b/apps/webcomponents/src/app/components/gn-results-list/gn-results-list-multiple.sample.html
index 75d5c0ff47..f2db0710be 100644
--- a/apps/webcomponents/src/app/components/gn-results-list/gn-results-list-multiple.sample.html
+++ b/apps/webcomponents/src/app/components/gn-results-list/gn-results-list-multiple.sample.html
@@ -7,10 +7,6 @@
     <meta name="viewport" content="width=device-width, initial-scale=1" />
     <link rel="preconnect" href="https://fonts.googleapis.com" />
     <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
-    <link
-      rel="stylesheet"
-      href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200"
-    />
     <link
       href="https://fonts.googleapis.com/css2?family=Roboto:wght@200;300;400;500;600;700&amp;display=swap"
       rel="stylesheet"
diff --git a/apps/webcomponents/src/app/components/gn-results-list/gn-results-list.sample.html b/apps/webcomponents/src/app/components/gn-results-list/gn-results-list.sample.html
index 18222c366b..12cc77e0b3 100644
--- a/apps/webcomponents/src/app/components/gn-results-list/gn-results-list.sample.html
+++ b/apps/webcomponents/src/app/components/gn-results-list/gn-results-list.sample.html
@@ -7,10 +7,6 @@
     <meta name="viewport" content="width=device-width, initial-scale=1" />
     <link rel="preconnect" href="https://fonts.googleapis.com" />
     <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
-    <link
-      rel="stylesheet"
-      href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200"
-    />
     <link
       href="https://fonts.googleapis.com/css2?family=DM+Serif+Display&amp;family=Inter:wght@200;300;400;500;600;700&amp;display=swap"
       rel="stylesheet"
diff --git a/apps/webcomponents/src/app/components/gn-search-input/gn-search-input-and-results.sample.html b/apps/webcomponents/src/app/components/gn-search-input/gn-search-input-and-results.sample.html
index d9343b1480..c0f7fb7007 100644
--- a/apps/webcomponents/src/app/components/gn-search-input/gn-search-input-and-results.sample.html
+++ b/apps/webcomponents/src/app/components/gn-search-input/gn-search-input-and-results.sample.html
@@ -7,10 +7,6 @@
     <meta name="viewport" content="width=device-width, initial-scale=1" />
     <link rel="preconnect" href="https://fonts.googleapis.com" />
     <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
-    <link
-      rel="stylesheet"
-      href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200"
-    />
     <link
       href="https://fonts.googleapis.com/css2?family=DM+Serif+Display&amp;family=Inter:wght@200;300;400;500;600;700&amp;display=swap"
       rel="stylesheet"
diff --git a/apps/webcomponents/src/app/components/gn-search-input/gn-search-input.sample.html b/apps/webcomponents/src/app/components/gn-search-input/gn-search-input.sample.html
index a9669e8fa7..2ac92548fa 100644
--- a/apps/webcomponents/src/app/components/gn-search-input/gn-search-input.sample.html
+++ b/apps/webcomponents/src/app/components/gn-search-input/gn-search-input.sample.html
@@ -7,10 +7,6 @@
     <meta name="viewport" content="width=device-width, initial-scale=1" />
     <link rel="preconnect" href="https://fonts.googleapis.com" />
     <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
-    <link
-      rel="stylesheet"
-      href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200"
-    />
     <link
       href="https://fonts.googleapis.com/css2?family=DM+Serif+Display&amp;family=Inter:wght@200;300;400;500;600;700&amp;display=swap"
       rel="stylesheet"

From ba50d704275b076fd40ea3da8c60665c7880c1ba Mon Sep 17 00:00:00 2001
From: Olivia Guyot <olivia.guyot@camptocamp.com>
Date: Sat, 21 Oct 2023 15:24:18 +0200
Subject: [PATCH 6/7] feat(wc): copy fontface definitions to document on init

this will make icons and fonts appear in web components
---
 .../src/app/components/base.component.ts      | 22 +++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/apps/webcomponents/src/app/components/base.component.ts b/apps/webcomponents/src/app/components/base.component.ts
index f31461387a..59394945c8 100644
--- a/apps/webcomponents/src/app/components/base.component.ts
+++ b/apps/webcomponents/src/app/components/base.component.ts
@@ -83,6 +83,7 @@ export class BaseComponent implements OnChanges, OnInit {
       this.titleFont
     )
     this.facade.init(this.searchId)
+    this.copyFontFacesToDocument()
     this.isInitialized = true
   }
 
@@ -90,6 +91,27 @@ export class BaseComponent implements OnChanges, OnInit {
     // to override
   }
 
+  private copyFontFacesToDocument() {
+    // get the list of font face definitions in the Shadow DOM
+    const root = this.injector.get(ElementRef).nativeElement as HTMLElement
+    const styles = root.shadowRoot.styleSheets
+    const fontFaces = Array.from(styles).reduce(
+      (prev, curr) => [
+        ...prev,
+        ...Array.from(curr.cssRules)
+          .filter((rule) => rule.cssText.startsWith('@font-face'))
+          .map((rule) => rule.cssText),
+      ],
+      []
+    )
+
+    // all font faces are then copied to the document
+    const style = document.createElement('style')
+    const cssText = fontFaces.join('\n')
+    style.appendChild(document.createTextNode(cssText))
+    document.head.appendChild(style)
+  }
+
   async getRecordLink(
     uuid: string,
     usages: LinkUsage[]

From 6291baa357503a0bb5335e1495931b3b08a25361 Mon Sep 17 00:00:00 2001
From: Olivia Guyot <olivia.guyot@camptocamp.com>
Date: Mon, 23 Oct 2023 18:50:35 +0200
Subject: [PATCH 7/7] feat(wc): extract css classes from the metariel theme for
 overlay backdrop

This makes the overlay correctly close with WC as well
---
 apps/webcomponents/src/styles.css | 27 +++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/apps/webcomponents/src/styles.css b/apps/webcomponents/src/styles.css
index 2e69e7cea4..799b8b6c3e 100644
--- a/apps/webcomponents/src/styles.css
+++ b/apps/webcomponents/src/styles.css
@@ -32,7 +32,7 @@
   -webkit-font-smoothing: antialiased;
 }
 
-/* Material Theme */
+/* These classes were extracted from the full Material theme to save size */
 .cdk-overlay-pane {
   position: absolute;
   pointer-events: auto;
@@ -42,7 +42,6 @@
   max-width: 100%;
   max-height: 100%;
 }
-
 .cdk-overlay-connected-position-bounding-box {
   position: absolute;
   z-index: 1000;
@@ -51,6 +50,30 @@
   min-width: 1px;
   min-height: 1px;
 }
+.cdk-overlay-backdrop {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  z-index: 1000;
+  pointer-events: auto;
+  transition: opacity 400ms cubic-bezier(0.25, 0.8, 0.25, 1);
+  opacity: 0;
+}
+.cdk-overlay-backdrop.cdk-overlay-backdrop-showing {
+  opacity: 1;
+}
+.cdk-overlay-transparent-backdrop {
+  transition: visibility 1ms linear, opacity 1ms linear;
+  visibility: hidden;
+  opacity: 1;
+}
+.cdk-overlay-transparent-backdrop.cdk-overlay-backdrop-showing {
+  opacity: 0;
+  visibility: visible;
+}
+
 .gn-ui-overlay-container {
   position: absolute;
   z-index: 1000;