sveltacular 1.0.5 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/forms/index.d.ts +6 -2
- package/dist/forms/index.js +6 -3
- package/dist/forms/number-range-box/number-range-box.svelte +218 -0
- package/dist/forms/number-range-box/number-range-box.svelte.d.ts +21 -0
- package/dist/forms/tag-input-box/tag-input-box.svelte +203 -0
- package/dist/forms/tag-input-box/tag-input-box.svelte.d.ts +17 -0
- package/dist/generic/avatar/avatar.svelte +1 -0
- package/dist/generic/chip/chip.svelte +1 -0
- package/dist/navigation/context-menu/README.md +1 -0
- package/dist/navigation/context-menu/context-menu-divider.svelte +1 -0
- package/package.json +1 -1
package/dist/forms/index.d.ts
CHANGED
|
@@ -7,8 +7,14 @@ export { default as InfoBox } from './info-box/info-box.svelte';
|
|
|
7
7
|
export { default as MoneyBox } from './money-box/money-box.svelte';
|
|
8
8
|
export { default as NewOrExistingCombo } from './combo/new-or-existing-combo.svelte';
|
|
9
9
|
export { default as NumberBox } from './number-box/number-box.svelte';
|
|
10
|
+
export { default as NumberRangeBox } from './number-range-box/number-range-box.svelte';
|
|
11
|
+
export { default as PhoneBox } from './phone-box/phone-box.svelte';
|
|
12
|
+
export { default as Slider } from './slider/slider.svelte';
|
|
13
|
+
export { default as SwitchBox } from './switch-box/switch-box.svelte';
|
|
14
|
+
export { default as TagInputBox } from './tag-input-box/tag-input-box.svelte';
|
|
10
15
|
export { default as TextArea } from './text-area/text-area.svelte';
|
|
11
16
|
export { default as TextBox } from './text-box/text-box.svelte';
|
|
17
|
+
export { default as TimeBox } from './time-box/time-box.svelte';
|
|
12
18
|
export { default as UrlBox } from './url-box/url-box.svelte';
|
|
13
19
|
export * from './check-box/index.js';
|
|
14
20
|
export * from './list-box/index.js';
|
|
@@ -21,6 +27,4 @@ export { default as FormHeader } from './form-header.svelte';
|
|
|
21
27
|
export { default as FormLabel } from './form-label/form-label.svelte';
|
|
22
28
|
export { default as FormSection } from './form-section/form-section.svelte';
|
|
23
29
|
export { default as FormRow } from './form-row/form-row.svelte';
|
|
24
|
-
export { default as Slider } from './slider/slider.svelte';
|
|
25
|
-
export { default as TimeBox } from './time-box/time-box.svelte';
|
|
26
30
|
export * from './validation.js';
|
package/dist/forms/index.js
CHANGED
|
@@ -8,8 +8,14 @@ export { default as InfoBox } from './info-box/info-box.svelte';
|
|
|
8
8
|
export { default as MoneyBox } from './money-box/money-box.svelte';
|
|
9
9
|
export { default as NewOrExistingCombo } from './combo/new-or-existing-combo.svelte';
|
|
10
10
|
export { default as NumberBox } from './number-box/number-box.svelte';
|
|
11
|
+
export { default as NumberRangeBox } from './number-range-box/number-range-box.svelte';
|
|
12
|
+
export { default as PhoneBox } from './phone-box/phone-box.svelte';
|
|
13
|
+
export { default as Slider } from './slider/slider.svelte';
|
|
14
|
+
export { default as SwitchBox } from './switch-box/switch-box.svelte';
|
|
15
|
+
export { default as TagInputBox } from './tag-input-box/tag-input-box.svelte';
|
|
11
16
|
export { default as TextArea } from './text-area/text-area.svelte';
|
|
12
17
|
export { default as TextBox } from './text-box/text-box.svelte';
|
|
18
|
+
export { default as TimeBox } from './time-box/time-box.svelte';
|
|
13
19
|
export { default as UrlBox } from './url-box/url-box.svelte';
|
|
14
20
|
// Form components with barrel files
|
|
15
21
|
export * from './check-box/index.js';
|
|
@@ -24,8 +30,5 @@ export { default as FormHeader } from './form-header.svelte';
|
|
|
24
30
|
export { default as FormLabel } from './form-label/form-label.svelte';
|
|
25
31
|
export { default as FormSection } from './form-section/form-section.svelte';
|
|
26
32
|
export { default as FormRow } from './form-row/form-row.svelte';
|
|
27
|
-
// New form components
|
|
28
|
-
export { default as Slider } from './slider/slider.svelte';
|
|
29
|
-
export { default as TimeBox } from './time-box/time-box.svelte';
|
|
30
33
|
// Validation utilities
|
|
31
34
|
export * from './validation.js';
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { roundToDecimals } from '../../helpers/round-to-decimals.js';
|
|
3
|
+
import { uniqueId } from '../../helpers/unique-id.js';
|
|
4
|
+
import FormField from '../form-field/form-field.svelte';
|
|
5
|
+
import type { FormFieldSizeOptions } from '../../types/form.js';
|
|
6
|
+
|
|
7
|
+
const minId = uniqueId();
|
|
8
|
+
const maxId = uniqueId();
|
|
9
|
+
|
|
10
|
+
let {
|
|
11
|
+
minValue = $bindable(null as number | null),
|
|
12
|
+
maxValue = $bindable(null as number | null),
|
|
13
|
+
minAllowed = 0,
|
|
14
|
+
maxAllowed = 99999,
|
|
15
|
+
step = 1,
|
|
16
|
+
allowDecimals = false,
|
|
17
|
+
minPlaceholder = '0',
|
|
18
|
+
maxPlaceholder = 'No limit',
|
|
19
|
+
prefix = null as string | null,
|
|
20
|
+
suffix = null as string | null,
|
|
21
|
+
stickyEnd = false,
|
|
22
|
+
required = false,
|
|
23
|
+
size = 'full' as FormFieldSizeOptions,
|
|
24
|
+
label = undefined as string | undefined,
|
|
25
|
+
onChange = undefined as ((minValue: number | null, maxValue: number | null) => void) | undefined
|
|
26
|
+
}: {
|
|
27
|
+
minValue?: number | null;
|
|
28
|
+
maxValue?: number | null;
|
|
29
|
+
minAllowed?: number;
|
|
30
|
+
maxAllowed?: number;
|
|
31
|
+
step?: number;
|
|
32
|
+
allowDecimals?: boolean;
|
|
33
|
+
minPlaceholder?: string;
|
|
34
|
+
maxPlaceholder?: string;
|
|
35
|
+
prefix?: string | null;
|
|
36
|
+
suffix?: string | null;
|
|
37
|
+
stickyEnd?: boolean;
|
|
38
|
+
required?: boolean;
|
|
39
|
+
size?: FormFieldSizeOptions;
|
|
40
|
+
label?: string;
|
|
41
|
+
onChange?: ((minValue: number | null, maxValue: number | null) => void) | undefined;
|
|
42
|
+
} = $props();
|
|
43
|
+
|
|
44
|
+
const handleChange = () => {
|
|
45
|
+
// Calculate decimal places from step (e.g., step 0.1 = 1 decimal, step 0.01 = 2 decimals)
|
|
46
|
+
const decimalPlaces = step < 1 ? Math.abs(Math.log10(step)) : 0;
|
|
47
|
+
|
|
48
|
+
// If no decimals, must round to integer
|
|
49
|
+
if (!allowDecimals) {
|
|
50
|
+
if (minValue !== null) minValue = Math.round(minValue);
|
|
51
|
+
if (maxValue !== null) maxValue = Math.round(maxValue);
|
|
52
|
+
}
|
|
53
|
+
// If decimals, must round to step precision
|
|
54
|
+
else {
|
|
55
|
+
if (minValue !== null) minValue = roundToDecimals(minValue, decimalPlaces);
|
|
56
|
+
if (maxValue !== null) maxValue = roundToDecimals(maxValue, decimalPlaces);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Ensure min value is not less than minAllowed
|
|
60
|
+
if (minValue !== null && minValue < minAllowed) {
|
|
61
|
+
minValue = minAllowed;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Ensure max value is not greater than maxAllowed
|
|
65
|
+
if (maxValue !== null && maxValue > maxAllowed) {
|
|
66
|
+
maxValue = maxAllowed;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Ensure max value is greater than or equal to min value
|
|
70
|
+
if (minValue !== null && maxValue !== null && minValue > maxValue) {
|
|
71
|
+
maxValue = minValue;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
onChange?.(minValue, maxValue);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const handleMinChange = () => {
|
|
78
|
+
if (stickyEnd) {
|
|
79
|
+
maxValue = minValue;
|
|
80
|
+
}
|
|
81
|
+
handleChange();
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const onInput = (e: Event, isMin: boolean) => {
|
|
85
|
+
const input = e.target as HTMLInputElement;
|
|
86
|
+
const newValue = parseFloat(input.value);
|
|
87
|
+
if (isNaN(newValue)) {
|
|
88
|
+
if (isMin) minValue = null;
|
|
89
|
+
else maxValue = null;
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (isMin) minValue = newValue;
|
|
93
|
+
else maxValue = newValue;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// Don't allow certain characters to be typed into the input
|
|
97
|
+
const onKeyPress = (e: KeyboardEvent, isMin: boolean) => {
|
|
98
|
+
const isNumber = !isNaN(Number(e.key));
|
|
99
|
+
const isDecimal = e.key === '.';
|
|
100
|
+
const isAllowed =
|
|
101
|
+
isNumber ||
|
|
102
|
+
isDecimal ||
|
|
103
|
+
['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Tab', '-'].includes(e.key);
|
|
104
|
+
if (!isAllowed) return e.preventDefault();
|
|
105
|
+
if (isDecimal && !allowDecimals) return e.preventDefault();
|
|
106
|
+
};
|
|
107
|
+
</script>
|
|
108
|
+
|
|
109
|
+
<FormField {size} {label} id={minId} {required}>
|
|
110
|
+
<div class="number-range-inputs">
|
|
111
|
+
<div class="input-group">
|
|
112
|
+
<div class="input">
|
|
113
|
+
{#if prefix}
|
|
114
|
+
<span class="prefix">{prefix}</span>
|
|
115
|
+
{/if}
|
|
116
|
+
<input
|
|
117
|
+
id={minId}
|
|
118
|
+
type="number"
|
|
119
|
+
placeholder={minPlaceholder}
|
|
120
|
+
min={minAllowed}
|
|
121
|
+
max={maxAllowed}
|
|
122
|
+
{step}
|
|
123
|
+
bind:value={minValue}
|
|
124
|
+
onchange={handleMinChange}
|
|
125
|
+
oninput={(e) => onInput(e, true)}
|
|
126
|
+
onkeypress={(e) => onKeyPress(e, true)}
|
|
127
|
+
{required}
|
|
128
|
+
/>
|
|
129
|
+
{#if suffix}
|
|
130
|
+
<span class="suffix">{suffix}</span>
|
|
131
|
+
{/if}
|
|
132
|
+
</div>
|
|
133
|
+
</div>
|
|
134
|
+
<div class="input-group">
|
|
135
|
+
<div class="input">
|
|
136
|
+
{#if prefix}
|
|
137
|
+
<span class="prefix">{prefix}</span>
|
|
138
|
+
{/if}
|
|
139
|
+
<input
|
|
140
|
+
id={maxId}
|
|
141
|
+
type="number"
|
|
142
|
+
placeholder={maxPlaceholder}
|
|
143
|
+
min={minAllowed}
|
|
144
|
+
max={maxAllowed}
|
|
145
|
+
{step}
|
|
146
|
+
bind:value={maxValue}
|
|
147
|
+
onchange={handleChange}
|
|
148
|
+
oninput={(e) => onInput(e, false)}
|
|
149
|
+
onkeypress={(e) => onKeyPress(e, false)}
|
|
150
|
+
{required}
|
|
151
|
+
/>
|
|
152
|
+
{#if suffix}
|
|
153
|
+
<span class="suffix">{suffix}</span>
|
|
154
|
+
{/if}
|
|
155
|
+
</div>
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
</FormField>
|
|
159
|
+
|
|
160
|
+
<style>.number-range-inputs {
|
|
161
|
+
display: flex;
|
|
162
|
+
gap: var(--spacing-md);
|
|
163
|
+
width: 100%;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.input-group {
|
|
167
|
+
flex: 1;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.input {
|
|
171
|
+
display: flex;
|
|
172
|
+
align-items: center;
|
|
173
|
+
justify-content: flex-start;
|
|
174
|
+
position: relative;
|
|
175
|
+
width: 100%;
|
|
176
|
+
height: 100%;
|
|
177
|
+
border-radius: var(--radius-md);
|
|
178
|
+
border: var(--border-thin) solid var(--form-input-border);
|
|
179
|
+
background-color: var(--form-input-bg);
|
|
180
|
+
color: var(--form-input-fg);
|
|
181
|
+
font-size: var(--font-md);
|
|
182
|
+
font-weight: 500;
|
|
183
|
+
line-height: 2rem;
|
|
184
|
+
transition: background-color var(--transition-base) var(--ease-in-out), border-color var(--transition-base) var(--ease-in-out), color var(--transition-base) var(--ease-in-out), fill var(--transition-base) var(--ease-in-out), stroke var(--transition-base) var(--ease-in-out);
|
|
185
|
+
user-select: none;
|
|
186
|
+
white-space: nowrap;
|
|
187
|
+
}
|
|
188
|
+
.input input {
|
|
189
|
+
background-color: transparent;
|
|
190
|
+
border: none;
|
|
191
|
+
line-height: 2rem;
|
|
192
|
+
font-size: var(--font-md);
|
|
193
|
+
width: 100%;
|
|
194
|
+
flex-grow: 1;
|
|
195
|
+
padding-left: var(--spacing-base);
|
|
196
|
+
padding-right: var(--spacing-base);
|
|
197
|
+
}
|
|
198
|
+
.input input:focus {
|
|
199
|
+
outline: none;
|
|
200
|
+
}
|
|
201
|
+
.input input::placeholder {
|
|
202
|
+
color: var(--form-input-placeholder);
|
|
203
|
+
}
|
|
204
|
+
.input .prefix,
|
|
205
|
+
.input .suffix {
|
|
206
|
+
font-size: var(--font-md);
|
|
207
|
+
line-height: 2rem;
|
|
208
|
+
padding-left: var(--spacing-base);
|
|
209
|
+
padding-right: var(--spacing-base);
|
|
210
|
+
background-color: var(--form-input-accent-bg);
|
|
211
|
+
color: var(--form-input-accent-fg);
|
|
212
|
+
}
|
|
213
|
+
.input .prefix {
|
|
214
|
+
border-right: var(--border-thin) solid var(--form-input-border);
|
|
215
|
+
}
|
|
216
|
+
.input .suffix {
|
|
217
|
+
border-left: var(--border-thin) solid var(--form-input-border);
|
|
218
|
+
}</style>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { FormFieldSizeOptions } from '../../types/form.js';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
minValue?: number | null;
|
|
4
|
+
maxValue?: number | null;
|
|
5
|
+
minAllowed?: number;
|
|
6
|
+
maxAllowed?: number;
|
|
7
|
+
step?: number;
|
|
8
|
+
allowDecimals?: boolean;
|
|
9
|
+
minPlaceholder?: string;
|
|
10
|
+
maxPlaceholder?: string;
|
|
11
|
+
prefix?: string | null;
|
|
12
|
+
suffix?: string | null;
|
|
13
|
+
stickyEnd?: boolean;
|
|
14
|
+
required?: boolean;
|
|
15
|
+
size?: FormFieldSizeOptions;
|
|
16
|
+
label?: string;
|
|
17
|
+
onChange?: ((minValue: number | null, maxValue: number | null) => void) | undefined;
|
|
18
|
+
};
|
|
19
|
+
declare const NumberRangeBox: import("svelte").Component<$$ComponentProps, {}, "minValue" | "maxValue">;
|
|
20
|
+
type NumberRangeBox = ReturnType<typeof NumberRangeBox>;
|
|
21
|
+
export default NumberRangeBox;
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { uniqueId } from '../../helpers/unique-id.js';
|
|
3
|
+
import FormField from '../form-field/form-field.svelte';
|
|
4
|
+
import Chip from '../../generic/chip/chip.svelte';
|
|
5
|
+
import type { FormFieldSizeOptions } from '../../types/form.js';
|
|
6
|
+
|
|
7
|
+
const id = uniqueId();
|
|
8
|
+
const datalistId = uniqueId();
|
|
9
|
+
|
|
10
|
+
let {
|
|
11
|
+
value = $bindable([] as string[]),
|
|
12
|
+
placeholder = 'Add a tag...',
|
|
13
|
+
required = false,
|
|
14
|
+
disabled = false,
|
|
15
|
+
autocomplete = [] as string[],
|
|
16
|
+
separators = [',', ';'] as string[],
|
|
17
|
+
size = 'full' as FormFieldSizeOptions,
|
|
18
|
+
label = undefined as string | undefined,
|
|
19
|
+
helperText = undefined as string | undefined,
|
|
20
|
+
errorText = undefined as string | undefined,
|
|
21
|
+
onChange = undefined as ((value: string[]) => void) | undefined
|
|
22
|
+
}: {
|
|
23
|
+
value?: string[];
|
|
24
|
+
placeholder?: string;
|
|
25
|
+
required?: boolean;
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
autocomplete?: string[];
|
|
28
|
+
separators?: string[];
|
|
29
|
+
size?: FormFieldSizeOptions;
|
|
30
|
+
label?: string;
|
|
31
|
+
helperText?: string;
|
|
32
|
+
errorText?: string;
|
|
33
|
+
onChange?: ((value: string[]) => void) | undefined;
|
|
34
|
+
} = $props();
|
|
35
|
+
|
|
36
|
+
let newTag = $state('');
|
|
37
|
+
|
|
38
|
+
function addTag(tagToAdd?: string) {
|
|
39
|
+
const tag = tagToAdd || newTag.trim();
|
|
40
|
+
if (tag && !value.includes(tag)) {
|
|
41
|
+
value = [...value, tag];
|
|
42
|
+
newTag = '';
|
|
43
|
+
onChange?.(value);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function removeTag(tagToRemove: string) {
|
|
48
|
+
value = value.filter((tag) => tag !== tagToRemove);
|
|
49
|
+
onChange?.(value);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function handleKeydown(event: KeyboardEvent) {
|
|
53
|
+
if (event.key === 'Enter') {
|
|
54
|
+
event.preventDefault();
|
|
55
|
+
addTag();
|
|
56
|
+
} else if (event.key === 'Backspace' && newTag === '' && value.length > 0) {
|
|
57
|
+
removeTag(value[value.length - 1]);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function handleInput(event: Event) {
|
|
62
|
+
const input = event.target as HTMLInputElement;
|
|
63
|
+
const inputValue = input.value;
|
|
64
|
+
|
|
65
|
+
// Check if the last character is a separator
|
|
66
|
+
if (inputValue.length > 0) {
|
|
67
|
+
const lastChar = inputValue[inputValue.length - 1];
|
|
68
|
+
if (separators.includes(lastChar)) {
|
|
69
|
+
// Extract the tag before the separator
|
|
70
|
+
const tagBeforeSeparator = inputValue.slice(0, -1).trim();
|
|
71
|
+
if (tagBeforeSeparator) {
|
|
72
|
+
// Prevent the separator from being added
|
|
73
|
+
newTag = tagBeforeSeparator;
|
|
74
|
+
// Add the tag
|
|
75
|
+
addTag(tagBeforeSeparator);
|
|
76
|
+
} else {
|
|
77
|
+
// If there's no text before the separator, just clear it
|
|
78
|
+
newTag = '';
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
</script>
|
|
84
|
+
|
|
85
|
+
<FormField {size} {label} {id} {required} {disabled} {helperText} {errorText}>
|
|
86
|
+
<div class="tag-input">
|
|
87
|
+
<div class="input-container">
|
|
88
|
+
<div class="input-wrapper">
|
|
89
|
+
<input
|
|
90
|
+
{id}
|
|
91
|
+
type="text"
|
|
92
|
+
bind:value={newTag}
|
|
93
|
+
{placeholder}
|
|
94
|
+
onkeydown={handleKeydown}
|
|
95
|
+
oninput={handleInput}
|
|
96
|
+
{disabled}
|
|
97
|
+
{required}
|
|
98
|
+
list={autocomplete.length > 0 ? datalistId : undefined}
|
|
99
|
+
aria-label="Tag input"
|
|
100
|
+
class="tag-input-field"
|
|
101
|
+
/>
|
|
102
|
+
{#if autocomplete.length > 0}
|
|
103
|
+
<datalist id={datalistId}>
|
|
104
|
+
{#each autocomplete as option}
|
|
105
|
+
<option value={option}></option>
|
|
106
|
+
{/each}
|
|
107
|
+
</datalist>
|
|
108
|
+
{/if}
|
|
109
|
+
</div>
|
|
110
|
+
<button
|
|
111
|
+
type="button"
|
|
112
|
+
class="add-button"
|
|
113
|
+
onclick={() => addTag()}
|
|
114
|
+
disabled={disabled || !newTag.trim()}
|
|
115
|
+
aria-label="Add tag"
|
|
116
|
+
>
|
|
117
|
+
Add
|
|
118
|
+
</button>
|
|
119
|
+
</div>
|
|
120
|
+
|
|
121
|
+
{#if value.length > 0}
|
|
122
|
+
<div class="tags">
|
|
123
|
+
{#each value as tag}
|
|
124
|
+
<Chip label={tag} removable={true} onRemove={() => removeTag(tag)} />
|
|
125
|
+
{/each}
|
|
126
|
+
</div>
|
|
127
|
+
{/if}
|
|
128
|
+
</div>
|
|
129
|
+
</FormField>
|
|
130
|
+
|
|
131
|
+
<style>.tag-input {
|
|
132
|
+
display: flex;
|
|
133
|
+
flex-direction: column;
|
|
134
|
+
gap: var(--spacing-sm);
|
|
135
|
+
width: 100%;
|
|
136
|
+
}
|
|
137
|
+
.tag-input .input-container {
|
|
138
|
+
display: flex;
|
|
139
|
+
gap: var(--spacing-sm);
|
|
140
|
+
align-items: flex-end;
|
|
141
|
+
}
|
|
142
|
+
.tag-input .input-container .input-wrapper {
|
|
143
|
+
flex: 1;
|
|
144
|
+
position: relative;
|
|
145
|
+
}
|
|
146
|
+
.tag-input .input-container .tag-input-field {
|
|
147
|
+
width: 100%;
|
|
148
|
+
height: 2.5rem;
|
|
149
|
+
padding: 0 var(--spacing-base);
|
|
150
|
+
border: var(--border-thin) solid var(--form-input-border);
|
|
151
|
+
border-radius: var(--radius-md);
|
|
152
|
+
background-color: var(--form-input-bg);
|
|
153
|
+
color: var(--form-input-fg);
|
|
154
|
+
font-size: var(--font-md);
|
|
155
|
+
font-weight: 500;
|
|
156
|
+
line-height: 2rem;
|
|
157
|
+
transition: background-color var(--transition-base) var(--ease-in-out), border-color var(--transition-base) var(--ease-in-out), color var(--transition-base) var(--ease-in-out);
|
|
158
|
+
}
|
|
159
|
+
.tag-input .input-container .tag-input-field:focus {
|
|
160
|
+
outline: none;
|
|
161
|
+
border-color: var(--form-input-border-focus);
|
|
162
|
+
background-color: var(--form-input-bg);
|
|
163
|
+
}
|
|
164
|
+
.tag-input .input-container .tag-input-field:disabled {
|
|
165
|
+
opacity: 0.6;
|
|
166
|
+
cursor: not-allowed;
|
|
167
|
+
}
|
|
168
|
+
.tag-input .input-container .tag-input-field::placeholder {
|
|
169
|
+
color: var(--form-input-placeholder);
|
|
170
|
+
}
|
|
171
|
+
.tag-input .input-container .add-button {
|
|
172
|
+
padding: var(--spacing-sm) var(--spacing-base);
|
|
173
|
+
background-color: var(--button-primary-bg);
|
|
174
|
+
color: var(--button-primary-fg);
|
|
175
|
+
border: var(--border-thin) solid var(--button-primary-border);
|
|
176
|
+
border-radius: var(--radius-md);
|
|
177
|
+
font-size: var(--font-sm);
|
|
178
|
+
font-weight: 500;
|
|
179
|
+
cursor: pointer;
|
|
180
|
+
transition: background-color var(--transition-base) var(--ease-in-out), border-color var(--transition-base) var(--ease-in-out), color var(--transition-base) var(--ease-in-out);
|
|
181
|
+
white-space: nowrap;
|
|
182
|
+
height: fit-content;
|
|
183
|
+
min-height: 2.5rem;
|
|
184
|
+
}
|
|
185
|
+
.tag-input .input-container .add-button:hover:not(:disabled) {
|
|
186
|
+
background-color: var(--button-primary-hover-bg);
|
|
187
|
+
color: var(--button-primary-hover-fg);
|
|
188
|
+
}
|
|
189
|
+
.tag-input .input-container .add-button:disabled {
|
|
190
|
+
background-color: var(--gray-400);
|
|
191
|
+
border-color: var(--gray-400);
|
|
192
|
+
color: var(--gray-600);
|
|
193
|
+
cursor: not-allowed;
|
|
194
|
+
opacity: 0.6;
|
|
195
|
+
}
|
|
196
|
+
.tag-input .input-container .add-button:active:not(:disabled) {
|
|
197
|
+
transform: scale(0.98);
|
|
198
|
+
}
|
|
199
|
+
.tag-input .tags {
|
|
200
|
+
display: flex;
|
|
201
|
+
flex-wrap: wrap;
|
|
202
|
+
gap: var(--spacing-sm);
|
|
203
|
+
}</style>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { FormFieldSizeOptions } from '../../types/form.js';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
value?: string[];
|
|
4
|
+
placeholder?: string;
|
|
5
|
+
required?: boolean;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
autocomplete?: string[];
|
|
8
|
+
separators?: string[];
|
|
9
|
+
size?: FormFieldSizeOptions;
|
|
10
|
+
label?: string;
|
|
11
|
+
helperText?: string;
|
|
12
|
+
errorText?: string;
|
|
13
|
+
onChange?: ((value: string[]) => void) | undefined;
|
|
14
|
+
};
|
|
15
|
+
declare const TagInputBox: import("svelte").Component<$$ComponentProps, {}, "value">;
|
|
16
|
+
type TagInputBox = ReturnType<typeof TagInputBox>;
|
|
17
|
+
export default TagInputBox;
|