Skip to content

Commit 0443fbd

Browse files
committed
fix: Input component
1 parent a063fad commit 0443fbd

File tree

22 files changed

+368
-198
lines changed

22 files changed

+368
-198
lines changed

.changeset/clean-tables-grab.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte-5-ui-lib': patch
3+
---
4+
5+
fix: Input component

src/app.pcss

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,55 @@
195195
height: 1.5rem;
196196
width: 1.5rem;
197197
}
198+
/* input file */
199+
[type='file'] {
200+
background: unset;
201+
border-color: inherit;
202+
border-width: 0;
203+
border-radius: 0;
204+
padding: 0;
205+
font-size: unset;
206+
line-height: inherit;
207+
}
208+
209+
[type='file']:focus {
210+
outline: 1px auto inherit;
211+
}
212+
213+
input[type=file]::file-selector-button {
214+
color: white;
215+
background: #1F2937;
216+
border: 0;
217+
font-weight: 500;
218+
font-size: 0.875rem;
219+
cursor: pointer;
220+
padding-top: 0.625rem;
221+
padding-bottom: 0.625rem;
222+
padding-left: 2rem;
223+
padding-right: 1rem;
224+
-webkit-margin-start: -1rem;
225+
margin-inline-start: -1rem;
226+
-webkit-margin-end: 1rem;
227+
margin-inline-end: 1rem;
228+
}
229+
230+
input[type=file]::file-selector-button:hover {
231+
background: #374151;
232+
}
233+
234+
:is([dir=rtl]) input[type=file]::file-selector-button {
235+
padding-right: 2rem;
236+
padding-left: 1rem;
237+
}
238+
239+
.dark input[type=file]::file-selector-button {
240+
color: white;
241+
background: #4B5563;
242+
}
243+
244+
.dark input[type=file]::file-selector-button:hover {
245+
background: #6B7280;
246+
}
198247

199248
}
200249

src/lib/buttongroup/ButtonGroup.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
}: Props = $props();
1111
1212
let groupClass = $derived(buttonGroup({ size, className }));
13-
setContext('group', { size });
13+
setContext('group', size);
1414
</script>
1515

1616
<div {...attributes} class={groupClass} role="group">

src/lib/forms/checkbox/Checkbox.svelte

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
choices = [],
1515
checked = $bindable(false),
1616
spacing,
17-
groupLabelClass,
17+
classLabel,
1818
indeterminate,
1919
class: className,
2020
...attributes
@@ -26,7 +26,7 @@
2626
</script>
2727
{#if choices.length > 0}
2828
{#each choices as {value, checkboxLabel}, i}
29-
<Label class={label({ class: groupLabelClass })} for={`checkbox-${i}`}>
29+
<Label class={label({ class: classLabel })} for={`checkbox-${i}`}>
3030
{ checkboxLabel }
3131
<input id={`checkbox-${i}`} type="checkbox" value={ value } bind:group {...attributes}
3232
class={base({ class: className })}
@@ -37,7 +37,7 @@
3737
</Label>
3838
{/each}
3939
{:else}
40-
<Label class={label({ class: groupLabelClass })}>
40+
<Label class={label({ class: classLabel })}>
4141
<input
4242
type="checkbox"
4343
bind:checked
@@ -66,7 +66,7 @@
6666
@prop group = []
6767
@prop checked = $bindable(false)
6868
@prop spacing
69-
@prop groupLabelClass
69+
@prop classLabel
7070
@prop indeterminate
7171
@prop class: className
7272
@prop ...attributes

src/lib/forms/checkbox/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ interface CheckboxProps extends HTMLInputAttributes {
2424
choices?: CheckboxItem[];
2525
checked?: boolean | undefined | null;
2626
spacing?: string | undefined | null;
27-
groupLabelClass?: string | undefined;
27+
classLabel?: string | undefined;
2828
indeterminate?: boolean;
2929
class?: string | undefined | null;
3030
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<script lang="ts">
2+
import { type FileuploadProps as Props, fileupload } from '.'
3+
4+
let {
5+
files = $bindable(),
6+
value = $bindable(),
7+
size = 'md',
8+
class: className,
9+
...attributes
10+
}: Props = $props();
11+
const base = $derived(fileupload({ size, class: className }));
12+
</script>
13+
14+
<input type="file" bind:files {...attributes} class={base}/>
15+

src/lib/forms/fileupload/index.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import Fileupload from "./Fileupload.svelte";
2+
import type { HTMLInputAttributes } from "svelte/elements";
3+
import type { InputProps } from '$lib'
4+
import { fileupload } from './theme';
5+
6+
interface FileuploadProps extends Omit<HTMLInputAttributes, 'size'> {
7+
files?: FileList;
8+
value?: any;
9+
size?: InputProps['size'];
10+
color?: InputProps['color'];
11+
}
12+
13+
export { Fileupload, fileupload, type FileuploadProps }

src/lib/forms/fileupload/theme.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { tv } from 'tailwind-variants';
2+
3+
export const fileupload = tv({
4+
base: 'block w-full disabled:cursor-not-allowed disabled:opacity-50 rtl:text-right p-2.5 focus:border-primary-500 focus:ring-primary-500 dark:focus:border-primary-500 dark:focus:ring-primary-500 bg-gray-50 text-gray-900 dark:bg-gray-700 dark:placeholder-gray-400 border-gray-300 dark:border-gray-600 text-sm rounded-lg border !p-0 dark:text-gray-400',
5+
variants: {
6+
size: {
7+
sm: 'text-xs ps-9 pe-9 p-2',
8+
md: 'text-sm ps-10 pe-10 p-2.5',
9+
lg: 'sm:text-base ps-11 pe-11 p-3'
10+
}
11+
}
12+
});

src/lib/forms/input/Input.svelte

Lines changed: 61 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -7,30 +7,15 @@
77

88
<script lang="ts">
99
import { twMerge } from 'tailwind-merge';
10-
import { getContext, type Snippet } from 'svelte';
11-
import type { HTMLInputAttributes } from 'svelte/elements';
12-
13-
interface Props extends HTMLInputAttributes {
14-
children?: Snippet;
15-
left?: Snippet;
16-
right?: Snippet;
17-
inputSize?: FormSizeType;
18-
value?: any;
19-
defaultClass?: string | undefined | null;
20-
color?: 'base' | 'green' | 'red';
21-
floatClass?: string | undefined | null;
22-
classLeft?: string | undefined | null;
23-
classRight?: string | undefined | null;
24-
class?: string | undefined | null;
25-
show?: boolean;
26-
}
10+
import { getContext } from 'svelte';
11+
import { type InputProps as Props, input} from '.'
2712
2813
let {
2914
children,
3015
left,
3116
right,
3217
value = $bindable(),
33-
inputSize,
18+
size,
3419
defaultClass = 'block w-full disabled:cursor-not-allowed disabled:opacity-50 rtl:text-right',
3520
color = 'base',
3621
floatClass = 'flex absolute inset-y-0 items-center text-gray-500 dark:text-gray-400',
@@ -41,80 +26,88 @@
4126
...attributes
4227
}: Props = $props();
4328
44-
const borderClasses = {
45-
base: 'border border-gray-300 dark:border-gray-600',
46-
tinted: 'border border-gray-300 dark:border-gray-500',
47-
green: 'border border-green-500 dark:border-green-400',
48-
red: 'border border-red-500 dark:border-red-400'
49-
};
29+
// const borderClasses = {
30+
// base: 'border border-gray-300 dark:border-gray-600',
31+
// tinted: 'border border-gray-300 dark:border-gray-500',
32+
// green: 'border border-green-500 dark:border-green-400',
33+
// red: 'border border-red-500 dark:border-red-400'
34+
// };
5035
51-
const ringClasses = {
52-
base: 'focus:border-primary-500 focus:ring-primary-500 dark:focus:border-primary-500 dark:focus:ring-primary-500',
53-
green:
54-
'focus:ring-green-500 focus:border-green-500 dark:focus:border-green-500 dark:focus:ring-green-500',
55-
red: 'focus:ring-red-500 focus:border-red-500 dark:focus:ring-red-500 dark:focus:border-red-500'
56-
};
36+
// const ringClasses = {
37+
// base: 'focus:border-primary-500 focus:ring-primary-500 dark:focus:border-primary-500 dark:focus:ring-primary-500',
38+
// green:
39+
// 'focus:ring-green-500 focus:border-green-500 dark:focus:border-green-500 dark:focus:ring-green-500',
40+
// red: 'focus:ring-red-500 focus:border-red-500 dark:focus:ring-red-500 dark:focus:border-red-500'
41+
// };
5742
58-
const colorClasses = {
59-
base: 'bg-gray-50 text-gray-900 dark:bg-gray-700 dark:text-white dark:placeholder-gray-400',
60-
tinted:
61-
'bg-gray-50 text-gray-900 dark:bg-gray-600 dark:text-white dark:placeholder-gray-400',
62-
green:
63-
'bg-green-50 text-green-900 placeholder-green-700 dark:text-green-400 dark:placeholder-green-500 dark:bg-gray-700',
64-
red: 'bg-red-50 text-red-900 placeholder-red-700 dark:text-red-500 dark:placeholder-red-500 dark:bg-gray-700'
65-
};
43+
// const colorClasses = {
44+
// base: 'bg-gray-50 text-gray-900 dark:bg-gray-700 dark:text-white dark:placeholder-gray-400',
45+
// tinted:
46+
// 'bg-gray-50 text-gray-900 dark:bg-gray-600 dark:text-white dark:placeholder-gray-400',
47+
// green:
48+
// 'bg-green-50 text-green-900 placeholder-green-700 dark:text-green-400 dark:placeholder-green-500 dark:bg-gray-700',
49+
// red: 'bg-red-50 text-red-900 placeholder-red-700 dark:text-red-500 dark:placeholder-red-500 dark:bg-gray-700'
50+
// };
6651
6752
// tinted if put in component having its own background
6853
let background: boolean = getContext('background');
6954
7055
let group: { size: SizeType } = getContext('group');
71-
// console.log('group', group);
56+
let isGroup = !!group;
57+
// console.log('isGroup', isGroup);
7258
73-
const textSizes = { sm: 'sm:text-xs', md: 'text-sm', lg: 'sm:text-base' };
74-
const leftPadding = { sm: 'ps-9', md: 'ps-10', lg: 'ps-11' };
75-
const rightPadding = { sm: 'pe-9', md: 'pe-10', lg: 'pe-11' };
76-
const inputPadding = { sm: 'p-2', md: 'p-2.5', lg: 'p-3' };
59+
// const textSizes = { sm: 'sm:text-xs', md: 'text-sm', lg: 'sm:text-base' };
60+
// const leftPadding = { sm: 'ps-9', md: 'ps-10', lg: 'ps-11' };
61+
// const rightPadding = { sm: 'pe-9', md: 'pe-10', lg: 'pe-11' };
62+
// const inputPadding = { sm: 'p-2', md: 'p-2.5', lg: 'p-3' };
7763
78-
let _size = inputSize || clampSize(group?.size) || 'md';
64+
let _size = $derived(size || clampSize(group?.size) || 'md');
7965
const _color = $derived(color === 'base' && background ? 'tinted' : color);
80-
let inputClass = $derived(
81-
twMerge(
82-
defaultClass,
83-
inputPadding[_size],
84-
(left && leftPadding[_size]) || (right && rightPadding[_size]),
85-
ringClasses[color],
86-
colorClasses[_color],
87-
borderClasses[_color],
88-
textSizes[_size],
89-
group ? '' : 'rounded-lg',
90-
group && 'first:rounded-s-lg last:rounded-e-lg',
91-
group && '[&:not(:first-child)]:-ms-px',
92-
className
93-
)
94-
);
66+
67+
const { input:inputCls, left: leftCls, right: rightCls } = $derived(input({ size:_size, color:_color, group:isGroup, class: className }));
68+
// let inputClass = $derived(
69+
// twMerge(
70+
// defaultClass,
71+
// inputPadding[_size],
72+
// (left && leftPadding[_size]) || (right && rightPadding[_size]),
73+
// ringClasses[color],
74+
// colorClasses[_color],
75+
// borderClasses[_color],
76+
// textSizes[_size],
77+
// group ? '' : 'rounded-lg',
78+
// group && 'first:rounded-s-lg last:rounded-e-lg',
79+
// group && '[&:not(:first-child)]:-ms-px',
80+
// className
81+
// )
82+
// );
9583
</script>
9684

97-
<div class="relative w-full">
85+
{#snippet inputContent()}
9886
{#if left}
9987
<div
100-
class="{twMerge(
101-
floatClass,
102-
classLeft
103-
)} pointer-events-none start-0 ps-2.5"
88+
class={leftCls({ class: classLeft})}
10489
>
10590
{@render left()}
10691
</div>
10792
{/if}
108-
<input {...attributes} bind:value class={inputClass} />
93+
<input {...attributes} bind:value class={inputCls({ class: className })} />
10994
{#if children}
11095
{@render children()}
11196
{/if}
11297
{#if right}
113-
<div class="{twMerge(floatClass, classRight)} end-0 pe-2.5">
98+
<div class={rightCls({ class: classRight })}>
11499
{@render right()}
115100
</div>
116101
{/if}
117-
</div>
102+
{/snippet}
103+
104+
{#if group}
105+
{@render inputContent()}
106+
{:else}
107+
<div class="relative w-full">
108+
{@render inputContent()}
109+
</div>
110+
{/if}
118111

119112
<!--
120113
@component
@@ -124,7 +117,7 @@
124117
@prop left
125118
@prop right
126119
@prop value = $bindable()
127-
@prop inputSize
120+
@prop size
128121
@prop defaultClass = 'block w-full disabled:cursor-not-allowed disabled:opacity-50 rtl:text-right'
129122
@prop color = 'base'
130123
@prop floatClass = 'flex absolute inset-y-0 items-center text-gray-500 dark:text-gray-400'

src/lib/forms/input/index.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
11
import Input from './Input.svelte';
2+
import type { HTMLInputAttributes } from 'svelte/elements';
3+
import type { FormSizeType } from '$lib/types';
4+
import type { Snippet } from 'svelte';
5+
import { input } from './theme';
26

3-
export { Input };
7+
interface InputProps extends Omit<HTMLInputAttributes, 'size'> {
8+
children?: Snippet;
9+
left?: Snippet;
10+
right?: Snippet;
11+
size?: FormSizeType;
12+
value?: any;
13+
defaultClass?: string | undefined | null;
14+
color?: 'base' | 'green' | 'red';
15+
floatClass?: string | undefined | null;
16+
classLeft?: string | undefined | null;
17+
classRight?: string | undefined | null;
18+
class?: string | undefined | null;
19+
show?: boolean;
20+
}
21+
22+
export { Input, input, type InputProps };

0 commit comments

Comments
 (0)