<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}
/>
