website/src/lib/components/Input/Input.svelte
bytedream 60f031aa7b
All checks were successful
delpoy / build-and-deploy (push) Successful in 1m5s
update input disabled style
2024-12-20 19:10:52 +01:00

156 lines
3.8 KiB
Svelte

<script lang="ts">
import { Eye, EyeSlash } from 'svelte-heros-v2';
import type { Snippet } from 'svelte';
let {
label,
notice,
id,
name,
type = 'text',
value = $bindable(),
placeholder,
pattern,
required = false,
disabled = false,
readonly = false,
checked = $bindable(false),
size = 'md',
pickyWidth = true,
containerClass = '',
inputElement = $bindable(),
oninput,
onclick
}: {
label?: Snippet;
notice?: Snippet;
id?: string;
name?: string;
type?: string;
value?: string;
placeholder?: string;
pattern?: RegExp;
required?: boolean;
disabled?: boolean;
readonly?: boolean;
checked?: boolean;
size?: 'xs' | 'sm' | 'md' | 'lg';
pickyWidth?: boolean;
containerClass?: string;
inputElement?: HTMLInputElement;
oninput?: (e: Event & { currentTarget: EventTarget & HTMLInputElement }) => void;
onclick?: (e: Event) => void;
} = $props();
let initialType = type;
let passwordEyeSize = {
xs: '14',
sm: '18',
md: '24',
lg: '30'
};
</script>
<!-- the cursor-not-allowed class must be set here because a disabled button does not respect the 'cursor' css property -->
<div class={containerClass} class:cursor-not-allowed={type === 'submit' && disabled}>
{#if type === 'submit'}
<input
class="btn"
class:btn-xs={size === 'xs'}
class:btn-sm={size === 'sm'}
class:btn-md={size === 'md'}
class:btn-lg={size === 'lg'}
{id}
type="submit"
{disabled}
bind:value
bind:this={inputElement}
{oninput}
{onclick}
/>
{:else}
<div>
{#if label}
<label class="label" for={id}>
<span class="label-text">
{@render label()}
{#if required}
<span class="text-red-700">*</span>
{/if}
</span>
</label>
{/if}
<div
class="relative flex items-center"
class:sm:max-w-[16rem]={type !== 'checkbox' && pickyWidth}
>
<input
class:checkbox={type === 'checkbox'}
class:checkbox-xs={type === 'checkbox' && size === 'xs'}
class:checkbox-sm={type === 'checkbox' && size === 'sm'}
class:checkbox-md={type === 'checkbox' && size === 'md'}
class:checkbox-lg={type === 'checkbox' && size === 'lg'}
class:input,w-full={type !== 'checkbox'}
class:input-xs={type !== 'checkbox' && size === 'xs'}
class:input-sm={type !== 'checkbox' && size === 'sm'}
class:input-md={type !== 'checkbox' && size === 'md'}
class:input-lg={type !== 'checkbox' && size === 'lg'}
class:input-bordered={type !== 'checkbox'}
class:pr-11={initialType === 'password'}
class:!border-none,!text-inherit={disabled}
{id}
{name}
{type}
{value}
{checked}
{placeholder}
{required}
{disabled}
{readonly}
bind:this={inputElement}
autocomplete="off"
onchange={() => {
if (type === 'checkbox') {
checked = !checked;
}
}}
oninput={(e: Event & { currentTarget: EventTarget & HTMLInputElement }) => {
value = e.currentTarget.value;
if (pattern && !pattern.test(value)) return;
oninput?.(e);
}}
onpaste={(e) => {
if (pattern && e.clipboardData && !pattern.test(e.clipboardData.getData('text'))) {
e.preventDefault();
}
}}
{onclick}
/>
{#if initialType === 'password'}
<button
class="absolute right-3"
type="button"
onclick={() => {
type = type === 'password' ? 'text' : 'password';
}}
>
{#if type === 'password'}
<EyeSlash variation="solid" size={passwordEyeSize[size]} />
{:else}
<Eye variation="solid" size={passwordEyeSize[size]} />
{/if}
</button>
{/if}
</div>
{#if notice}
<label class="label" for={id}>
<span class="label-text-alt">
{@render notice()}
</span>
</label>
{/if}
</div>
{/if}
</div>