49 lines
958 B
Svelte
49 lines
958 B
Svelte
<script lang="ts">
|
|
import Label from './Label.svelte';
|
|
import StyledRawInput from './StyledRawInput.svelte';
|
|
import { type ValidatorOptions } from '@repo/validate';
|
|
|
|
let {
|
|
name,
|
|
label,
|
|
value = $bindable(''),
|
|
placeholder,
|
|
type,
|
|
validate: validateOpts,
|
|
invalidMessage
|
|
}: {
|
|
name: string;
|
|
label?: string;
|
|
value?: string;
|
|
placeholder?: string;
|
|
type?: HTMLInputElement['type'];
|
|
validate?: ValidatorOptions;
|
|
invalidMessage?: string;
|
|
} = $props();
|
|
|
|
let valid: boolean = $state(true);
|
|
</script>
|
|
|
|
<div>
|
|
{#if label}
|
|
<Label for={name}>{label}</Label>
|
|
{/if}
|
|
|
|
<StyledRawInput
|
|
{placeholder}
|
|
{name}
|
|
{type}
|
|
bind:value
|
|
validate={validateOpts}
|
|
onvalidate={(e) => {
|
|
valid = e.detail.valid;
|
|
}}
|
|
/>
|
|
|
|
<div class={['opacity-0 transition-opacity', !valid && 'opacity-100']}>
|
|
<Label for={name} error>
|
|
{invalidMessage !== undefined && invalidMessage != '' ? invalidMessage : 'Field is required'}
|
|
</Label>
|
|
</div>
|
|
</div>
|