Coves frontend - a photon fork
at main 132 lines 3.3 kB view raw
1<script module lang="ts"> 2 import { Label } from 'mono-svelte' 3 import type { HTMLInputAttributes } from 'svelte/elements' 4 import { generateID } from './helper' 5 6 export type Size = keyof typeof sizeClass 7 export type Shadow = keyof typeof shadowClass 8 9 export const sizeClass = { 10 sm: 'px-3 py-1', 11 md: 'px-3.5 py-1.5', 12 lg: 'px-5 py-3', 13 } 14 15 export const shadowClass = { 16 sm: 'shadow-xs', 17 none: 'shadow-none', 18 } 19 20 interface Props extends Omit<HTMLInputAttributes, 'size' | 'prefix'> { 21 label?: string | undefined 22 placeholder?: string 23 disabled?: boolean 24 required?: boolean 25 size?: Size 26 id?: string 27 inlineAffixes?: boolean 28 shadow?: Shadow 29 element?: HTMLInputElement | undefined 30 class?: string 31 customLabel?: import('svelte').Snippet 32 prefix?: import('svelte').Snippet 33 suffix?: import('svelte').Snippet 34 children?: import('svelte').Snippet 35 } 36 37 export type { Props as TextInputProps } 38</script> 39 40<script lang="ts"> 41 const borderClass = `border border-slate-200 border-b-slate-300 dark:border-zinc-800` 42 43 let { 44 label = undefined, 45 value = $bindable(), 46 placeholder = '', 47 disabled = false, 48 required = false, 49 size = 'md', 50 id = generateID(), 51 inlineAffixes = false, 52 shadow = 'sm', 53 element = $bindable(), 54 class: clazz = '', 55 customLabel: passedCustomLabel, 56 prefix, 57 suffix, 58 children, 59 ...rest 60 }: Props = $props() 61</script> 62 63<div class="flex flex-col gap-1 {clazz}"> 64 {#if passedCustomLabel || label} 65 <Label 66 for={id} 67 text={label} 68 class={[ 69 'peer-invalid:text-red-500 relative', 70 required && "after:content-['*'] after:text-red-500 after:ml-1", 71 ]} 72 > 73 {@render passedCustomLabel?.()} 74 </Label> 75 {/if} 76 <div 77 class={[ 78 shadowClass[shadow], 79 borderClass, 80 `border focus-within:border-primary-900 dark:focus-within:border-primary-100 focus-within:ring-2 81 ring-slate-300 dark:ring-zinc-700 82 transition-colors 83 rounded-xl flex flex-row items-center text-sm`, 84 clazz, 85 ]} 86 > 87 {#if prefix} 88 <div 89 class={[ 90 'rounded-xl rounded-r-none text-slate-600 dark:text-zinc-400', 91 inlineAffixes && 'bg-white dark:bg-zinc-900 pr-0 w-8', 92 sizeClass[size], 93 ]} 94 > 95 {@render prefix?.()} 96 </div> 97 {/if} 98 <input 99 type="text" 100 {id} 101 {placeholder} 102 {disabled} 103 bind:value 104 bind:this={element} 105 {required} 106 {...rest} 107 class={[ 108 sizeClass[size], 109 `bg-white dark:bg-zinc-900 110 focus:outline-hidden rounded-xl text-sm w-full disabled:bg-slate-100 111 disabled:cursor-not-allowed dark:disabled:bg-zinc-800 invalid:border-red-500! 112 peer invalid:text-red-500 z-10`, 113 prefix && 'rounded-l-none', 114 prefix && inlineAffixes && 'border-l-0', 115 suffix && 'rounded-r-none', 116 suffix && inlineAffixes && 'border-r-0', 117 clazz, 118 ]} 119 /> 120 {#if suffix} 121 <div 122 class={[ 123 'rounded-xl rounded-l-none text-slate-600 dark:text-zinc-400 h-full', 124 inlineAffixes && 'bg-white dark:bg-zinc-900 pl-0', 125 ]} 126 > 127 {@render suffix?.()} 128 </div> 129 {/if} 130 </div> 131 {@render children?.()} 132</div>