forked from MapComplete/MapComplete
		
	ToSvelte will now bind directly to svelte in the case that a SvelteUIElement is passed. This helps with cleaning up MapLibre maps, which should help with #2024
This commit is contained in:
		
							parent
							
								
									7038fcc6f6
								
							
						
					
					
						commit
						7d678d95c7
					
				
					 4 changed files with 54 additions and 18 deletions
				
			
		|  | @ -11,7 +11,7 @@ export default class SvelteUIElement< | |||
|     Events extends Record<string, any> = any, | ||||
|     Slots extends Record<string, any> = any | ||||
| > extends BaseUIElement { | ||||
|     private readonly _svelteComponent: { | ||||
|     public readonly _svelteComponent: { | ||||
|         new (args: { | ||||
|             target: HTMLElement | ||||
|             props: Props | ||||
|  | @ -19,10 +19,11 @@ export default class SvelteUIElement< | |||
|             slots?: Slots | ||||
|         }): SvelteComponentTyped<Props, Events, Slots> | ||||
|     } | ||||
|     private readonly _props: Props | ||||
|     private readonly _events: Events | ||||
|     private readonly _slots: Slots | ||||
|     public readonly _props: Props | ||||
|     public readonly _events: Events | ||||
|     public readonly _slots: Slots | ||||
|     private tag: "div" | "span" = "div" | ||||
|     public readonly isSvelte = true | ||||
| 
 | ||||
|     constructor(svelteElement, props?: Props, events?: Events, slots?: Slots) { | ||||
|         super() | ||||
|  | @ -47,4 +48,18 @@ export default class SvelteUIElement< | |||
|         }) | ||||
|         return el | ||||
|     } | ||||
| 
 | ||||
|     public getClass(){ | ||||
|         if(this.clss.size === 0){ | ||||
|             return undefined | ||||
|         } | ||||
|         return this.clss | ||||
|     } | ||||
| 
 | ||||
|     public getStyle(){ | ||||
|         if(this.style === ""){ | ||||
|             return undefined | ||||
|         } | ||||
|         return this.style | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -1,13 +1,24 @@ | |||
| <script lang="ts"> | ||||
|   import BaseUIElement from "../BaseUIElement.js" | ||||
|   import { onDestroy, onMount } from "svelte" | ||||
|   import SvelteUIElement from "./SvelteUIElement" | ||||
| 
 | ||||
|   export let construct: BaseUIElement | (() => BaseUIElement) | ||||
|   let elem: HTMLElement | ||||
|   let html: HTMLElement | ||||
|   let isSvelte = false | ||||
|   let uiElement : BaseUIElement | SvelteUIElement | undefined | ||||
|   let svelteElem: SvelteUIElement | ||||
|   onMount(() => { | ||||
|     const uiElem = typeof construct === "function" ? construct() : construct | ||||
|     html = uiElem?.ConstructElement() | ||||
|     uiElement = typeof construct === "function" ? construct() : construct | ||||
| 
 | ||||
|     if (uiElement?.["isSvelte"]) { | ||||
|       isSvelte = true | ||||
|       svelteElem = <SvelteUIElement> uiElement | ||||
|       return | ||||
|     } | ||||
| 
 | ||||
|     html = uiElement?.ConstructElement() | ||||
| 
 | ||||
|     if (html !== undefined) { | ||||
|       elem?.replaceWith(html) | ||||
|  | @ -16,7 +27,12 @@ | |||
| 
 | ||||
|   onDestroy(() => { | ||||
|     html?.remove() | ||||
|     uiElement?.Destroy() | ||||
|   }) | ||||
| </script> | ||||
| 
 | ||||
| <span bind:this={elem} /> | ||||
| {#if isSvelte} | ||||
|   <svelte:component this={svelteElem?._svelteComponent} {...svelteElem._props} class={svelteElem.getClass()} style={svelteElem.getStyle()}/> | ||||
| {:else} | ||||
|   <span bind:this={elem} /> | ||||
| {/if} | ||||
|  |  | |||
|  | @ -63,7 +63,7 @@ export default abstract class BaseUIElement { | |||
|     /** | ||||
|      * Adds all the relevant classes, space separated | ||||
|      */ | ||||
|     public SetClass(clss: string) { | ||||
|     public SetClass(clss: string): this { | ||||
|         if (clss == undefined) { | ||||
|             return this | ||||
|         } | ||||
|  | @ -101,7 +101,7 @@ export default abstract class BaseUIElement { | |||
|         return this.clss.has(clss) | ||||
|     } | ||||
| 
 | ||||
|     public SetStyle(style: string): BaseUIElement { | ||||
|     public SetStyle(style: string): this { | ||||
|         this.style = style | ||||
|         if (this._constructedHtmlElement !== undefined) { | ||||
|             this._constructedHtmlElement.style.cssText = style | ||||
|  |  | |||
|  | @ -50,13 +50,13 @@ | |||
|       center: { lng: lon, lat }, | ||||
|       maxZoom: 24, | ||||
|       interactive: true, | ||||
|       attributionControl: false, | ||||
|       attributionControl: false | ||||
|     } | ||||
|     _map = new maplibre.Map(options) | ||||
|     window.requestAnimationFrame(() => { | ||||
|       _map.resize() | ||||
|     }) | ||||
|     _map.on("load", function () { | ||||
|     _map.on("load", function() { | ||||
|       _map.resize() | ||||
|       const canvas = _map.getCanvas() | ||||
|       if (interactive) { | ||||
|  | @ -71,13 +71,18 @@ | |||
|     map.set(_map) | ||||
|   }) | ||||
|   onDestroy(async () => { | ||||
|     await Utils.waitFor(250) | ||||
|     try { | ||||
|       if (_map) _map.remove() | ||||
|       map = null | ||||
|     } catch (e) { | ||||
|       console.error("Could not destroy map") | ||||
|     } | ||||
|     await Utils.waitFor(100) | ||||
|     requestAnimationFrame( | ||||
|       () => { | ||||
|         try { | ||||
|           _map?.remove() | ||||
|           console.log("Removed map") | ||||
|           map = null | ||||
|         } catch (e) { | ||||
|           console.error("Could not destroy map") | ||||
|         } | ||||
|       } | ||||
|     ) | ||||
|   }) | ||||
| </script> | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue