Files
reiverr/src/lib/components/TextField.svelte
2024-05-28 23:57:19 +03:00

75 lines
1.8 KiB
Svelte

<script lang="ts">
import Container from '../../Container.svelte';
import type { FormEventHandler, HTMLInputTypeAttribute } from 'svelte/elements';
import { type ComponentType, createEventDispatcher } from 'svelte';
import { PLATFORM_TV } from '../constants';
import classNames from 'classnames';
import Spinner from './Utils/Spinner.svelte';
import { Check, Cross1 } from 'radix-icons-svelte';
export let value = '';
export let type: HTMLInputTypeAttribute = 'text';
export let isValid: Promise<boolean> | boolean | undefined = undefined;
let icon: ComponentType | undefined = undefined;
$: {
if (isValid instanceof Promise) {
icon = Spinner;
isValid.then((valid) => {
icon = valid ? Check : Cross1;
});
} else if (isValid === false) {
icon = Cross1;
} else if (isValid === true) {
icon = Check;
} else {
icon = undefined;
}
}
const dispatch = createEventDispatcher<{
change: string;
}>();
let input: HTMLInputElement;
const handleChange = (e: Event) => {
// @ts-ignore
value = e.target?.value;
// @ts-ignore
dispatch('change', e.target?.value);
};
</script>
<Container
on:enter={(e) => {
if (!PLATFORM_TV) {
e.detail.options.setFocusedElement = input;
}
}}
on:clickOrSelect={() => input?.focus()}
class={classNames('flex flex-col', $$restProps.class)}
let:hasFocus
focusOnClick
>
<label class="text-secondary-300 font-medium tracking-wide text-sm mb-1">
<slot>Label</slot>
</label>
<div class="relative flex flex-col">
<input
class={classNames('bg-primary-900 px-6 py-2 rounded-lg', {
selected: hasFocus,
unselected: !hasFocus
})}
{type}
{value}
on:input={handleChange}
bind:this={input}
/>
{#if icon}
<div class="absolute inset-y-0 right-4 flex items-center justify-center">
<svelte:component this={icon} size={19} />
</div>
{/if}
</div>
</Container>