forked from MapComplete/MapComplete
		
	
		
			
				
	
	
		
			56 lines
		
	
	
	
		
			1.8 KiB
		
	
	
	
		
			Svelte
		
	
	
	
	
	
			
		
		
	
	
			56 lines
		
	
	
	
		
			1.8 KiB
		
	
	
	
		
			Svelte
		
	
	
	
	
	
<script lang="ts">
 | 
						|
 | 
						|
  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";
 | 
						|
 | 
						|
  export let value: UIEventSource<string>;
 | 
						|
  // Internal state, only copied to 'value' so that no invalid values leak outside
 | 
						|
  let _value = new UIEventSource(value.data ?? "");
 | 
						|
  onDestroy(value.addCallbackAndRun(v => _value.setData(v ?? "")));
 | 
						|
  export let type: ValidatorType;
 | 
						|
  let validator = Validators.get(type);
 | 
						|
  export let feedback: UIEventSource<Translation> | undefined = undefined;
 | 
						|
  onDestroy(_value.addCallbackAndRun(v => {
 | 
						|
    if (validator.isValid(v)) {
 | 
						|
      feedback?.setData(undefined);
 | 
						|
      value.setData(v);
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    value.setData(undefined);
 | 
						|
    feedback?.setData(validator.getFeedback(v));
 | 
						|
  }))
 | 
						|
 | 
						|
  if (validator === undefined) {
 | 
						|
    throw "Not a valid type for a validator:" + type;
 | 
						|
  }
 | 
						|
 | 
						|
  const isValid = _value.map(v => validator.isValid(v));
 | 
						|
 | 
						|
  let htmlElem: HTMLInputElement;
 | 
						|
 | 
						|
  let dispatch = createEventDispatcher<{ selected }>();
 | 
						|
  $: {
 | 
						|
    console.log(htmlElem);
 | 
						|
    if (htmlElem !== undefined) {
 | 
						|
      htmlElem.onfocus = () => {
 | 
						|
        console.log("Dispatching selected event");
 | 
						|
        return dispatch("selected");
 | 
						|
      };
 | 
						|
    }
 | 
						|
  }
 | 
						|
</script>
 | 
						|
 | 
						|
{#if validator.textArea}
 | 
						|
  <textarea class="w-full" bind:value={$_value} inputmode={validator.inputmode ?? "text"}></textarea>
 | 
						|
{:else }
 | 
						|
  <span class="inline-flex">
 | 
						|
    <input bind:this={htmlElem} bind:value={$_value} inputmode={validator.inputmode ?? "text"}>
 | 
						|
    {#if !$isValid}
 | 
						|
      <ExclamationIcon class="h-6 w-6 -ml-6"></ExclamationIcon>
 | 
						|
    {/if}
 | 
						|
  </span>
 | 
						|
{/if}
 |