|
4 | 4 |
|
5 | 5 | interface IInputProps extends HTMLInputAttributes { |
6 | 6 | type: HTMLInputTypeAttribute; |
| 7 | + selected?: string; |
| 8 | + name?: string; |
7 | 9 | } |
8 | 10 |
|
9 | 11 | let { |
10 | 12 | type = 'text', |
11 | 13 | value = $bindable(), |
| 14 | + selected = $bindable(), |
| 15 | + name = '', |
12 | 16 | placeholder = '', |
13 | 17 | ...restProps |
14 | 18 | }: IInputProps = $props(); |
15 | 19 |
|
16 | | - const cbase = $derived( |
17 | | - 'w-full bg-grey py-3.5 px-6 text-[15px] text-black-800 font-geist font-normal placeholder:text-black-600 rounded-4xl outline-0 border border-transparent invalid:border-red invalid:text-red focus:invalid:text-black-800 focus:invalid:border-transparent' |
18 | | - ); |
| 20 | + let radioElement: HTMLInputElement | null = $state(null); |
| 21 | +
|
| 22 | + const typeClasses: Record<string, string> = { |
| 23 | + radio: 'opacity-100' |
| 24 | + }; |
| 25 | +
|
| 26 | + const cbase = $derived({ |
| 27 | + common: 'w-full bg-grey py-3.5 px-6 text-[15px] text-black-800 font-geist font-normal placeholder:text-black-600 rounded-4xl outline-0 border border-transparent invalid:border-red invalid:text-red focus:invalid:text-black-800 focus:invalid:border-transparent', |
| 28 | + type: typeClasses[type] |
| 29 | + }); |
| 30 | +
|
| 31 | + const radioCustomStyles = $derived({ |
| 32 | + common: "before:h-4.5 before:w-4.5 before:border-brand-burnt-orange before:-left-0.75 before:-bottom-0.25 relative before:absolute before:rounded-full before:border-2 before:bg-white before:content-['']", |
| 33 | + selected: |
| 34 | + 'after:h-2.5 after:w-2.5 after:bg-brand-burnt-orange after:absolute after:bottom-0.75 after:left-0.25 after:rounded-full' |
| 35 | + }); |
19 | 36 | </script> |
20 | 37 |
|
21 | | -<input |
22 | | - {...restProps} |
23 | | - {type} |
24 | | - {placeholder} |
25 | | - bind:value |
26 | | - class={cn([cbase, restProps.class].join(' '))} |
27 | | - tabindex="0" |
28 | | -/> |
| 38 | +{#if type === 'radio'} |
| 39 | + <div |
| 40 | + class={cn( |
| 41 | + [radioCustomStyles.common, selected === value ? radioCustomStyles.selected : ''].join( |
| 42 | + ' ' |
| 43 | + ) |
| 44 | + )} |
| 45 | + aria-checked={selected === value} |
| 46 | + role="radio" |
| 47 | + tabindex="0" |
| 48 | + onclick={() => radioElement?.click()} |
| 49 | + onkeypress={() => radioElement?.click()} |
| 50 | + > |
| 51 | + <input |
| 52 | + {...restProps} |
| 53 | + type="radio" |
| 54 | + {value} |
| 55 | + bind:group={selected} |
| 56 | + bind:this={radioElement} |
| 57 | + {name} |
| 58 | + checked={selected === value} |
| 59 | + class={cn([cbase.common, cbase.type, restProps.class].join(' '))} |
| 60 | + tabindex="0" |
| 61 | + /> |
| 62 | + </div> |
| 63 | +{:else} |
| 64 | + <input |
| 65 | + {...restProps} |
| 66 | + {type} |
| 67 | + {placeholder} |
| 68 | + bind:value |
| 69 | + class={cn([cbase.common, cbase.type, restProps.class].join(' '))} |
| 70 | + tabindex="0" |
| 71 | + /> |
| 72 | +{/if} |
0 commit comments