Files
sui/src/lib/TextInput.svelte
Elijah Duffy 90ff836061 text input: change default asterisk behaviour
asterisk now shown by default if field is required.
2026-02-04 14:53:14 -08:00

69 lines
1.5 KiB
Svelte

<script lang="ts">
import Label from './Label.svelte';
import StyledRawInput from './StyledRawInput.svelte';
import { generateIdentifier } from './util';
import type { ClassValue } from 'svelte/elements';
import type { ComponentProps } from 'svelte';
interface Props extends ComponentProps<typeof StyledRawInput> {
id?: string;
label?: string;
value?: string;
invalidMessage?: string | null;
ref?: HTMLInputElement | null;
asterisk?: boolean | null;
class?: ClassValue | null | undefined;
}
let {
id = generateIdentifier('text-input'),
label,
value = $bindable(''),
invalidMessage = 'Field is required',
ref = $bindable<HTMLInputElement | null>(null),
asterisk = null,
class: classValue,
forceInvalid = false,
...others
}: Props = $props();
let valid: boolean = $state(true);
let displayAsterisk = $derived(
asterisk === true || (asterisk !== false && others.validate && others.validate.required)
);
export const focus = () => {
if (ref) ref.focus();
};
</script>
<div class={['w-full', classValue]}>
{#if label}
<Label for={id}>
{label}
{#if displayAsterisk}
<span class="text-red-500">*</span>
{/if}
</Label>
{/if}
<StyledRawInput
{id}
bind:value
bind:ref
onvalidate={(e) => {
valid = e.detail.valid;
}}
{forceInvalid}
{...others}
/>
{#if others.validate && invalidMessage !== null}
<div class={['opacity-0 transition-opacity', (!valid || forceInvalid) && 'opacity-100']}>
<Label for={id} error>
{invalidMessage}
</Label>
</div>
{/if}
</div>