| 
									
										
										
										
											2023-03-30 04:51:56 +02:00
										 |  |  | <script lang="ts"> | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |   import { UIEventSource } from "../../Logic/UIEventSource" | 
					
						
							|  |  |  |   import type { ValidatorType } from "./Validators" | 
					
						
							|  |  |  |   import Validators from "./Validators" | 
					
						
							|  |  |  |   import { ExclamationIcon } from "@rgossiaux/svelte-heroicons/solid" | 
					
						
							|  |  |  |   import { Translation } from "../i18n/Translation" | 
					
						
							|  |  |  |   import { createEventDispatcher, onDestroy } from "svelte" | 
					
						
							|  |  |  |   import { Validator } from "./Validator" | 
					
						
							|  |  |  |   import { Unit } from "../../Models/Unit" | 
					
						
							|  |  |  |   import UnitInput from "../Popup/UnitInput.svelte" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   export let type: ValidatorType | 
					
						
							|  |  |  |   export let feedback: UIEventSource<Translation> | undefined = undefined | 
					
						
							|  |  |  |   export let getCountry: () => string | undefined | 
					
						
							|  |  |  |   export let placeholder: string | Translation | undefined | 
					
						
							|  |  |  |   export let unit: Unit = undefined | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   export let value: UIEventSource<string> | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * Internal state bound to the input element. | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * This is only copied to 'value' when appropriate so that no invalid values leak outside; | 
					
						
							|  |  |  |    * Additionally, the unit is added when copying | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   let _value = new UIEventSource(value.data ?? "") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   let validator: Validator = Validators.get(type ?? "string") | 
					
						
							|  |  |  |   let selectedUnit: UIEventSource<string> = new UIEventSource<string>(undefined) | 
					
						
							|  |  |  |   let _placeholder = placeholder ?? validator?.getPlaceholder() ?? type | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function initValueAndDenom() { | 
					
						
							|  |  |  |     if (unit && value.data) { | 
					
						
							|  |  |  |       const [v, denom] = unit?.findDenomination(value.data, getCountry) | 
					
						
							|  |  |  |       if (denom) { | 
					
						
							|  |  |  |         _value.setData(v) | 
					
						
							|  |  |  |         selectedUnit.setData(denom.canonical) | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         _value.setData(value.data ?? "") | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       _value.setData(value.data ?? "") | 
					
						
							| 
									
										
										
										
											2023-03-30 04:51:56 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-03-30 04:51:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |   initValueAndDenom() | 
					
						
							| 
									
										
										
										
											2023-06-11 01:32:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |   $: { | 
					
						
							|  |  |  |     // The type changed -> reset some values | 
					
						
							|  |  |  |     validator = Validators.get(type ?? "string") | 
					
						
							|  |  |  |     _placeholder = placeholder ?? validator?.getPlaceholder() ?? type | 
					
						
							|  |  |  |     feedback = feedback?.setData(validator?.getFeedback(_value.data, getCountry)) | 
					
						
							| 
									
										
										
										
											2023-06-11 01:32:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |     initValueAndDenom() | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function setValues() { | 
					
						
							|  |  |  |     // Update the value stores | 
					
						
							|  |  |  |     const v = _value.data | 
					
						
							|  |  |  |     if (!validator.isValid(v, getCountry) || v === "") { | 
					
						
							|  |  |  |       value.setData(undefined) | 
					
						
							|  |  |  |       feedback?.setData(validator.getFeedback(v, getCountry)) | 
					
						
							|  |  |  |       return | 
					
						
							| 
									
										
										
										
											2023-06-11 01:32:30 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-03-30 04:51:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |     if (unit && isNaN(Number(v))) { | 
					
						
							|  |  |  |       value.setData(undefined) | 
					
						
							|  |  |  |       return | 
					
						
							| 
									
										
										
										
											2023-06-11 01:32:30 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |     feedback?.setData(undefined) | 
					
						
							|  |  |  |     value.setData(v + (selectedUnit.data ?? "")) | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onDestroy(_value.addCallbackAndRun((_) => setValues())) | 
					
						
							|  |  |  |   onDestroy(selectedUnit.addCallback((_) => setValues())) | 
					
						
							|  |  |  |   if (validator === undefined) { | 
					
						
							|  |  |  |     throw "Not a valid type for a validator:" + type | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-06-11 01:32:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |   const isValid = _value.map((v) => validator.isValid(v, getCountry)) | 
					
						
							| 
									
										
										
										
											2023-06-11 01:32:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |   let htmlElem: HTMLInputElement | 
					
						
							| 
									
										
										
										
											2023-06-11 01:32:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |   let dispatch = createEventDispatcher<{ selected }>() | 
					
						
							|  |  |  |   $: { | 
					
						
							|  |  |  |     if (htmlElem !== undefined) { | 
					
						
							|  |  |  |       htmlElem.onfocus = () => dispatch("selected") | 
					
						
							| 
									
										
										
										
											2023-03-31 03:28:11 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-03-30 04:51:56 +02:00
										 |  |  | </script> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | {#if validator.textArea} | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |   <textarea | 
					
						
							|  |  |  |     class="w-full" | 
					
						
							|  |  |  |     bind:value={$_value} | 
					
						
							|  |  |  |     inputmode={validator.inputmode ?? "text"} | 
					
						
							|  |  |  |     placeholder={_placeholder} | 
					
						
							|  |  |  |   /> | 
					
						
							|  |  |  | {:else} | 
					
						
							| 
									
										
										
										
											2023-04-16 03:42:26 +02:00
										 |  |  |   <span class="inline-flex"> | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |     <input | 
					
						
							|  |  |  |       bind:this={htmlElem} | 
					
						
							|  |  |  |       bind:value={$_value} | 
					
						
							|  |  |  |       class="w-full" | 
					
						
							|  |  |  |       inputmode={validator.inputmode ?? "text"} | 
					
						
							|  |  |  |       placeholder={_placeholder} | 
					
						
							|  |  |  |     /> | 
					
						
							|  |  |  |     {#if !$isValid} | 
					
						
							| 
									
										
										
										
											2023-06-14 20:44:01 +02:00
										 |  |  |       <ExclamationIcon class="-ml-6 h-6 w-6" /> | 
					
						
							| 
									
										
										
										
											2023-03-30 04:51:56 +02:00
										 |  |  |     {/if} | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-11 01:32:30 +02:00
										 |  |  |     {#if unit !== undefined} | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |       <UnitInput {unit} {selectedUnit} textValue={_value} upstreamValue={value} /> | 
					
						
							| 
									
										
										
										
											2023-06-11 01:32:30 +02:00
										 |  |  |     {/if} | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  |   </span> | 
					
						
							| 
									
										
										
										
											2023-03-30 04:51:56 +02:00
										 |  |  | {/if} |