130 lines
3.4 KiB
Svelte
130 lines
3.4 KiB
Svelte
<script lang="ts">
|
|
import { IconSolid } 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 required = false;
|
|
export let disabled = false;
|
|
export let size: 'xs' | 'sm' | 'md' | 'lg' = 'md';
|
|
export let pickyWidth = true;
|
|
|
|
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={type === 'submit' && disabled ? 'cursor-not-allowed' : ''}>
|
|
{#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}
|
|
bind:this={inputElement}
|
|
autocomplete="off"
|
|
on:input={(e) => {
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
// @ts-ignore
|
|
value = e.target?.value;
|
|
input(e);
|
|
}}
|
|
on:click={click}
|
|
/>
|
|
{#if initialType === 'password'}
|
|
<button
|
|
class="absolute right-3"
|
|
type="button"
|
|
on:click={() => {
|
|
type = type === 'password' ? 'text' : 'password';
|
|
}}
|
|
>
|
|
{#if type === 'password'}
|
|
<IconSolid
|
|
name="eye-slash-solid"
|
|
width={passwordEyeSize[size]}
|
|
height={passwordEyeSize[size]}
|
|
/>
|
|
{:else}
|
|
<IconSolid
|
|
name="eye-solid"
|
|
width={passwordEyeSize[size]}
|
|
height={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>
|