87 lines
2.2 KiB
Svelte
87 lines
2.2 KiB
Svelte
<script lang="ts">
|
|
import type { HTMLInputAttributes } from 'svelte/elements';
|
|
import {
|
|
validate,
|
|
type InputValidatorEvent,
|
|
type ValidatorOptions
|
|
} from '@svelte-toolkit/validate';
|
|
import { generateIdentifier } from './util';
|
|
import { onMount } from 'svelte';
|
|
|
|
type $Props = Omit<HTMLInputAttributes, 'name' | 'value'> & {
|
|
name?: string;
|
|
value?: string;
|
|
validate?: ValidatorOptions;
|
|
focus?: boolean;
|
|
compact?: boolean;
|
|
use?: (node: HTMLInputElement) => void;
|
|
ref?: HTMLInputElement | null;
|
|
onvalidate?: (e: InputValidatorEvent) => void;
|
|
};
|
|
|
|
let {
|
|
id = generateIdentifier('styled-raw-input'),
|
|
name,
|
|
value = $bindable(''),
|
|
placeholder,
|
|
validate: validateOpts,
|
|
disabled = false,
|
|
focus: focusOnMount = false,
|
|
compact = false,
|
|
use,
|
|
ref = $bindable<HTMLInputElement | null>(null),
|
|
onvalidate,
|
|
class: classValue,
|
|
...others
|
|
}: $Props = $props();
|
|
|
|
let valid: boolean = $state(true);
|
|
|
|
export const focus = () => {
|
|
if (ref) ref.focus();
|
|
};
|
|
|
|
const conditionalUse = $derived(use ? use : () => {});
|
|
|
|
$effect(() => {
|
|
// default autovalOnInvalid to true unless explicitly set to false
|
|
if (validateOpts !== undefined && validateOpts.autovalOnInvalid === undefined) {
|
|
validateOpts.autovalOnInvalid = true;
|
|
}
|
|
});
|
|
|
|
onMount(() => {
|
|
if (focusOnMount && ref) {
|
|
ref.focus();
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<input
|
|
{id}
|
|
{name}
|
|
{placeholder}
|
|
aria-label={placeholder}
|
|
{...others}
|
|
bind:value
|
|
class={[
|
|
'border-sui-accent w-full rounded-sm border bg-white font-normal transition-colors',
|
|
'text-sui-text placeholder:text-sui-text/60 dark:border-sui-accent/50 dark:bg-sui-text-800 placeholder:font-normal',
|
|
'dark:text-sui-background dark:placeholder:text-sui-background/60 dark:sm:bg-slate-800',
|
|
'ring-sui-primary ring-offset-1 placeholder-shown:text-ellipsis focus:ring-2',
|
|
!compact ? 'px-[1.125rem] py-3.5' : 'px-[0.75rem] py-2',
|
|
!valid && 'border-red-500!',
|
|
disabled &&
|
|
'border-sui-accent/20 text-sui-text/60 dark:text-sui-background/60 cursor-not-allowed',
|
|
classValue
|
|
]}
|
|
{disabled}
|
|
use:validate={validateOpts}
|
|
use:conditionalUse
|
|
onvalidate={(e) => {
|
|
valid = e.detail.valid;
|
|
if (onvalidate) onvalidate(e);
|
|
}}
|
|
bind:this={ref}
|
|
/>
|