Files
website/src/lib/components/Input/Input.svelte
bytedream d5ad9a7890
All checks were successful
delpoy / build-and-deploy (push) Successful in 40s
fix unwanted phone number field clearing
2023-11-30 21:16:38 +01:00

138 lines
3.7 KiB
Svelte

<script lang="ts">
import { Eye, EyeSlash } from 'svelte-heros-v2';
import { createEventDispatcher } from 'svelte';
export let id: string | null = null;
export let name: string | null = null;
export let type = 'text';
export let value: string | null = null;
export let placeholder: string | null = null;
export let pattern: RegExp | null = null;
export let required = false;
export let disabled = false;
export let readonly = false;
export let size: 'xs' | 'sm' | 'md' | 'lg' = 'md';
export let pickyWidth = true;
export let containerClass = '';
export let inputElement: HTMLInputElement | undefined = undefined;
const dispatch = createEventDispatcher();
function input(e: Event & { currentTarget: EventTarget & HTMLInputElement }) {
dispatch('input', e);
}
function click(e: Event) {
dispatch('click', e);
}
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}
on:input={input}
on:click={click}
/>
{:else}
<div>
{#if $$slots.label}
<label class="label" for={id}>
<span class="label-text">
<slot name="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'}
{id}
{name}
{type}
{value}
{placeholder}
{required}
{disabled}
{readonly}
bind:this={inputElement}
autocomplete="off"
on:input={(e) => {
value = e.target?.value;
if (pattern && !pattern.test(e.target?.value)) {
if (inputElement?.value.endsWith(e.data)) {
value = e.target?.value.substring(0, e.target?.value.length - e.data.length);
}
return;
}
return input(e);
}}
on:paste={(e) => {
if (
pattern &&
!pattern.test((e.clipboardData || window.clipboardData).getData('text'))
) {
e.preventDefault();
}
}}
on:click={click}
/>
{#if initialType === 'password'}
<button
class="absolute right-3"
type="button"
on:click={() => {
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 $$slots.notice}
<label class="label" for={id}>
<span class="label-text-alt"><slot name="notice" /></span>
</label>
{/if}
</div>
{/if}
</div>