noph-ui 0.16.3 → 0.16.5
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/chip/ChipSet.svelte +2 -4
- package/dist/chip/FilterChip.svelte +9 -4
- package/dist/chip/InputChip.svelte +72 -83
- package/dist/chip/InputChip.svelte.d.ts +1 -1
- package/dist/chip/types.d.ts +0 -2
- package/dist/list/Item.svelte +26 -4
- package/dist/select/Select.svelte +1 -1
- package/dist/text-field/TextField.svelte +84 -49
- package/dist/text-field/types.d.ts +1 -0
- package/package.json +10 -10
package/dist/chip/ChipSet.svelte
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
</script>
|
|
6
6
|
|
|
7
7
|
{#if children}
|
|
8
|
-
<div class={['np-chip-set', attributes.class]} role="toolbar">
|
|
8
|
+
<div class={['np-chip-set', attributes.class]} style={attributes.style} role="toolbar">
|
|
9
9
|
{@render children()}
|
|
10
10
|
</div>
|
|
11
11
|
{/if}
|
|
@@ -14,9 +14,7 @@
|
|
|
14
14
|
.np-chip-set {
|
|
15
15
|
display: flex;
|
|
16
16
|
flex-wrap: wrap;
|
|
17
|
-
padding-top: 2px;
|
|
18
|
-
padding-bottom: 2px;
|
|
19
|
-
padding-right: 2px;
|
|
20
17
|
gap: 0.5rem;
|
|
18
|
+
align-items: center;
|
|
21
19
|
}
|
|
22
20
|
</style>
|
|
@@ -148,6 +148,10 @@
|
|
|
148
148
|
color: var(--np-color-primary);
|
|
149
149
|
display: flex;
|
|
150
150
|
}
|
|
151
|
+
|
|
152
|
+
.np-filter-chip-disabled .np-chip-icon {
|
|
153
|
+
color: var(--np-color-on-surface);
|
|
154
|
+
}
|
|
151
155
|
.np-filter-chip:has(input:checked) .np-filter-chip-label,
|
|
152
156
|
.np-filter-chip-icon .np-filter-chip-label {
|
|
153
157
|
padding-left: 0.5rem;
|
|
@@ -172,7 +176,6 @@
|
|
|
172
176
|
inset: 0;
|
|
173
177
|
border-radius: inherit;
|
|
174
178
|
pointer-events: none;
|
|
175
|
-
background-color: var(--np-color-surface-container-low);
|
|
176
179
|
}
|
|
177
180
|
.np-filter-chip-default::before {
|
|
178
181
|
border-width: 1px;
|
|
@@ -184,9 +187,11 @@
|
|
|
184
187
|
background-color: var(--np-color-secondary-container);
|
|
185
188
|
}
|
|
186
189
|
.np-filter-chip-elevated {
|
|
187
|
-
border-width: 0;
|
|
188
190
|
box-shadow: var(--np-elevation-1);
|
|
189
191
|
}
|
|
192
|
+
.np-filter-chip-elevated::before {
|
|
193
|
+
background-color: var(--np-color-surface-container-low);
|
|
194
|
+
}
|
|
190
195
|
.np-filter-chip:has(input:checked) {
|
|
191
196
|
--np-icon-button-icon-color: var(--np-color-on-secondary-container);
|
|
192
197
|
}
|
|
@@ -217,7 +222,7 @@
|
|
|
217
222
|
|
|
218
223
|
.np-filter-chip-disabled .np-filter-chip-label {
|
|
219
224
|
cursor: default;
|
|
220
|
-
color: var(--np-color-on-surface);
|
|
225
|
+
color: var(--np-color-on-surface) !important;
|
|
221
226
|
opacity: 0.38;
|
|
222
227
|
}
|
|
223
228
|
.np-filter-chip-disabled.np-filter-chip-elevated {
|
|
@@ -238,7 +243,7 @@
|
|
|
238
243
|
opacity: 0.12;
|
|
239
244
|
}
|
|
240
245
|
.np-filter-chip-disabled::before {
|
|
241
|
-
background-color: var(--np-color-on-surface);
|
|
246
|
+
background-color: var(--np-color-on-surface) !important;
|
|
242
247
|
opacity: 0.12;
|
|
243
248
|
border-width: 0;
|
|
244
249
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import IconButton from '../button/IconButton.svelte'
|
|
3
3
|
import CloseIcon from '../icons/CloseIcon.svelte'
|
|
4
4
|
import Ripple from '../ripple/Ripple.svelte'
|
|
5
|
+
import { onMount } from 'svelte'
|
|
5
6
|
import type { InputChipProps } from './types.ts'
|
|
6
7
|
|
|
7
8
|
let {
|
|
@@ -14,106 +15,97 @@
|
|
|
14
15
|
onremove,
|
|
15
16
|
name,
|
|
16
17
|
value,
|
|
17
|
-
group = $bindable(),
|
|
18
|
-
defaultSelected,
|
|
19
18
|
...attributes
|
|
20
19
|
}: InputChipProps = $props()
|
|
21
20
|
|
|
22
|
-
let chipLabel:
|
|
21
|
+
let chipLabel: HTMLDivElement | undefined = $state()
|
|
22
|
+
let visible = $state(false)
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
$effect(() => {
|
|
31
|
-
if (value && group) {
|
|
32
|
-
const index = group.indexOf(value)
|
|
33
|
-
if (selected) {
|
|
34
|
-
if (index < 0) {
|
|
35
|
-
group?.push(value)
|
|
36
|
-
group = group
|
|
24
|
+
onMount(() => {
|
|
25
|
+
const observer = new IntersectionObserver((entries) => {
|
|
26
|
+
entries.forEach((entry) => {
|
|
27
|
+
if (entry.isIntersecting) {
|
|
28
|
+
visible = true
|
|
29
|
+
observer.disconnect()
|
|
37
30
|
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
31
|
+
})
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
if (element) {
|
|
35
|
+
observer.observe(element)
|
|
44
36
|
}
|
|
37
|
+
|
|
38
|
+
return () => observer.disconnect()
|
|
45
39
|
})
|
|
46
40
|
</script>
|
|
47
41
|
|
|
48
42
|
<div
|
|
49
43
|
{...attributes}
|
|
50
44
|
bind:this={element}
|
|
45
|
+
tabindex={disabled ? -1 : 0}
|
|
46
|
+
aria-disabled={disabled}
|
|
47
|
+
role="button"
|
|
51
48
|
class={[
|
|
52
|
-
'np-
|
|
53
|
-
icon ? 'np-
|
|
54
|
-
disabled ? 'np-
|
|
49
|
+
'np-input-chip',
|
|
50
|
+
icon ? 'np-input-chip-icon' : '',
|
|
51
|
+
disabled ? 'np-input-chip-disabled' : '',
|
|
52
|
+
selected ? 'np-input-chip-selected' : '',
|
|
55
53
|
attributes.class,
|
|
56
54
|
]}
|
|
57
55
|
>
|
|
58
|
-
|
|
59
|
-
{
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
56
|
+
{#if visible}
|
|
57
|
+
<div bind:this={chipLabel} class={['np-input-chip-label']}>
|
|
58
|
+
{#if icon}
|
|
59
|
+
<div class="np-chip-icon">
|
|
60
|
+
{@render icon()}
|
|
61
|
+
</div>
|
|
62
|
+
{/if}
|
|
63
|
+
<div class="np-chip-label">{label || value}</div>
|
|
64
|
+
<input type="hidden" {value} {name} {disabled} />
|
|
65
|
+
</div>
|
|
66
|
+
{#if !disabled}
|
|
67
|
+
<Ripple forElement={chipLabel} />
|
|
63
68
|
{/if}
|
|
64
|
-
<
|
|
65
|
-
<input
|
|
66
|
-
type="checkbox"
|
|
67
|
-
bind:checked={selected}
|
|
68
|
-
onclick={(e) => e.preventDefault()}
|
|
69
|
-
{value}
|
|
70
|
-
{name}
|
|
69
|
+
<IconButton
|
|
71
70
|
{disabled}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
71
|
+
type="button"
|
|
72
|
+
--np-icon-button-container-height="1.75rem"
|
|
73
|
+
--np-icon-button-container-width="1.75rem"
|
|
74
|
+
--np-icon-button-icon-size="1.125rem"
|
|
75
|
+
aria-label={ariaLabelRemove}
|
|
76
|
+
onclick={(
|
|
77
|
+
event: MouseEvent & {
|
|
78
|
+
currentTarget: EventTarget & HTMLButtonElement
|
|
79
|
+
},
|
|
80
|
+
) => {
|
|
81
|
+
if (element === undefined) {
|
|
82
|
+
return
|
|
83
|
+
}
|
|
84
|
+
onremove?.(event)
|
|
85
|
+
}}
|
|
86
|
+
>
|
|
87
|
+
<CloseIcon />
|
|
88
|
+
</IconButton>
|
|
77
89
|
{/if}
|
|
78
|
-
<IconButton
|
|
79
|
-
{disabled}
|
|
80
|
-
type="button"
|
|
81
|
-
--np-icon-button-container-height="1.75rem"
|
|
82
|
-
--np-icon-button-container-width="1.75rem"
|
|
83
|
-
--np-icon-button-icon-size="1.125rem"
|
|
84
|
-
aria-label={ariaLabelRemove}
|
|
85
|
-
onclick={(
|
|
86
|
-
event: MouseEvent & {
|
|
87
|
-
currentTarget: EventTarget & HTMLButtonElement
|
|
88
|
-
},
|
|
89
|
-
) => {
|
|
90
|
-
if (element === undefined) {
|
|
91
|
-
return
|
|
92
|
-
}
|
|
93
|
-
onremove?.(event)
|
|
94
|
-
}}
|
|
95
|
-
>
|
|
96
|
-
<CloseIcon />
|
|
97
|
-
</IconButton>
|
|
98
90
|
</div>
|
|
99
91
|
|
|
100
92
|
<style>
|
|
101
|
-
.np-
|
|
93
|
+
.np-input-chip {
|
|
102
94
|
position: relative;
|
|
103
95
|
display: inline-flex;
|
|
104
96
|
align-items: center;
|
|
105
97
|
user-select: none;
|
|
106
|
-
border-radius: var(--np-
|
|
98
|
+
border-radius: var(--np-input-chip-container-shape, var(--np-shape-corner-small));
|
|
107
99
|
--np-icon-button-icon-color: var(--np-color-on-surface-variant);
|
|
108
100
|
--np-icon-size: 1.125rem;
|
|
109
101
|
padding-right: 2px;
|
|
110
102
|
}
|
|
111
|
-
.np-
|
|
103
|
+
.np-input-chip-label input {
|
|
112
104
|
opacity: 0;
|
|
113
105
|
position: absolute;
|
|
114
106
|
pointer-events: none;
|
|
115
107
|
}
|
|
116
|
-
.np-
|
|
108
|
+
.np-input-chip-label {
|
|
117
109
|
cursor: pointer;
|
|
118
110
|
display: inline-flex;
|
|
119
111
|
align-items: center;
|
|
@@ -131,7 +123,7 @@
|
|
|
131
123
|
color: var(--np-color-primary);
|
|
132
124
|
display: flex;
|
|
133
125
|
}
|
|
134
|
-
.np-
|
|
126
|
+
.np-input-chip-icon .np-input-chip-label {
|
|
135
127
|
padding-left: 0.5rem;
|
|
136
128
|
}
|
|
137
129
|
.np-chip-label {
|
|
@@ -143,31 +135,27 @@
|
|
|
143
135
|
overflow: hidden;
|
|
144
136
|
text-overflow: ellipsis;
|
|
145
137
|
}
|
|
146
|
-
.np-
|
|
138
|
+
.np-input-chip::before {
|
|
147
139
|
content: '';
|
|
148
140
|
position: absolute;
|
|
149
141
|
inset: 0;
|
|
150
142
|
border-radius: inherit;
|
|
151
143
|
pointer-events: none;
|
|
152
|
-
background-color: var(--np-color-surface-container-low);
|
|
153
144
|
border-width: 1px;
|
|
154
145
|
border-style: solid;
|
|
155
|
-
border-color: var(--np-
|
|
146
|
+
border-color: var(--np-input-chip-outline-color, var(--np-color-outline-variant));
|
|
156
147
|
}
|
|
157
|
-
.np-
|
|
148
|
+
.np-input-chip-selected::before {
|
|
158
149
|
border-width: 0;
|
|
159
150
|
background-color: var(--np-color-secondary-container);
|
|
160
151
|
}
|
|
161
|
-
.np-
|
|
152
|
+
.np-input-chip-selected {
|
|
162
153
|
--np-icon-button-icon-color: var(--np-color-on-secondary-container);
|
|
163
154
|
}
|
|
164
|
-
.np-
|
|
155
|
+
.np-input-chip-selected .np-input-chip-label {
|
|
165
156
|
color: var(--np-color-on-secondary-container);
|
|
166
157
|
}
|
|
167
|
-
.np-
|
|
168
|
-
outline-width: 0;
|
|
169
|
-
}
|
|
170
|
-
.np-filter-chip:has(input:focus-visible) {
|
|
158
|
+
.np-input-chip:focus-visible {
|
|
171
159
|
outline-style: solid;
|
|
172
160
|
outline-color: var(--np-color-primary);
|
|
173
161
|
outline-width: 3px;
|
|
@@ -186,15 +174,15 @@
|
|
|
186
174
|
}
|
|
187
175
|
}
|
|
188
176
|
|
|
189
|
-
.np-
|
|
177
|
+
.np-input-chip-disabled .np-input-chip-label {
|
|
190
178
|
cursor: default;
|
|
191
179
|
color: var(--np-color-on-surface);
|
|
192
180
|
opacity: 0.38;
|
|
193
181
|
}
|
|
194
|
-
.np-
|
|
182
|
+
.np-input-chip-disabled.np-input-chip-selected::before {
|
|
195
183
|
opacity: 0.12;
|
|
196
184
|
}
|
|
197
|
-
.np-
|
|
185
|
+
.np-input-chip-disabled:not(.np-input-chip-selected).np-input-chip::after {
|
|
198
186
|
content: '';
|
|
199
187
|
position: absolute;
|
|
200
188
|
inset: 0;
|
|
@@ -205,9 +193,10 @@
|
|
|
205
193
|
border-color: var(--np-color-on-surface);
|
|
206
194
|
opacity: 0.12;
|
|
207
195
|
}
|
|
208
|
-
.np-
|
|
209
|
-
background-color: var(--np-color-on-surface);
|
|
196
|
+
.np-input-chip-disabled::before {
|
|
210
197
|
opacity: 0.12;
|
|
211
|
-
|
|
198
|
+
}
|
|
199
|
+
.np-input-chip-selected.np-input-chip-disabled::before {
|
|
200
|
+
background-color: var(--np-color-on-surface);
|
|
212
201
|
}
|
|
213
202
|
</style>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { InputChipProps } from './types.ts';
|
|
2
|
-
declare const InputChip: import("svelte").Component<InputChipProps, {}, "element" | "
|
|
2
|
+
declare const InputChip: import("svelte").Component<InputChipProps, {}, "element" | "selected">;
|
|
3
3
|
type InputChip = ReturnType<typeof InputChip>;
|
|
4
4
|
export default InputChip;
|
package/dist/chip/types.d.ts
CHANGED
|
@@ -42,8 +42,6 @@ export interface InputChipProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
42
42
|
element?: HTMLDivElement;
|
|
43
43
|
name?: string;
|
|
44
44
|
value?: string;
|
|
45
|
-
group?: (string | number)[] | null;
|
|
46
|
-
defaultSelected?: boolean | null;
|
|
47
45
|
onremove?: (event: MouseEvent & {
|
|
48
46
|
currentTarget: EventTarget & HTMLButtonElement;
|
|
49
47
|
}) => void;
|
package/dist/list/Item.svelte
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import Ripple from '../ripple/Ripple.svelte'
|
|
3
3
|
import type { FocusEventHandler } from 'svelte/elements'
|
|
4
4
|
import type { ItemProps } from './types.ts'
|
|
5
|
+
import { onMount } from 'svelte'
|
|
5
6
|
|
|
6
7
|
let {
|
|
7
8
|
selected = false,
|
|
@@ -16,7 +17,24 @@
|
|
|
16
17
|
}: ItemProps = $props()
|
|
17
18
|
|
|
18
19
|
let focused = $state(false)
|
|
20
|
+
let visible = $state(false)
|
|
19
21
|
let element: HTMLButtonElement | HTMLAnchorElement | undefined = $state()
|
|
22
|
+
onMount(() => {
|
|
23
|
+
const observer = new IntersectionObserver((entries) => {
|
|
24
|
+
entries.forEach((entry) => {
|
|
25
|
+
if (entry.isIntersecting) {
|
|
26
|
+
visible = true
|
|
27
|
+
observer.disconnect()
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
if (element) {
|
|
33
|
+
observer.observe(element)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return () => observer.disconnect()
|
|
37
|
+
})
|
|
20
38
|
</script>
|
|
21
39
|
|
|
22
40
|
{#snippet content()}
|
|
@@ -67,8 +85,10 @@
|
|
|
67
85
|
class={['np-item', selected && 'selected', attributes.class]}
|
|
68
86
|
bind:this={element}
|
|
69
87
|
>
|
|
70
|
-
{
|
|
71
|
-
|
|
88
|
+
{#if visible}
|
|
89
|
+
{@render content()}
|
|
90
|
+
<Ripple forceHover={focused} />
|
|
91
|
+
{/if}
|
|
72
92
|
</button>
|
|
73
93
|
{:else if attributes.variant === 'link'}
|
|
74
94
|
<a
|
|
@@ -84,8 +104,10 @@
|
|
|
84
104
|
class={['np-item', selected && 'selected', attributes.class]}
|
|
85
105
|
bind:this={element}
|
|
86
106
|
>
|
|
87
|
-
{
|
|
88
|
-
|
|
107
|
+
{#if visible}
|
|
108
|
+
{@render content()}
|
|
109
|
+
<Ripple forceHover={focused} />
|
|
110
|
+
{/if}
|
|
89
111
|
</a>
|
|
90
112
|
{/if}
|
|
91
113
|
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
}
|
|
45
45
|
let selectedOption = $state(options.filter((option) => option.selected))
|
|
46
46
|
|
|
47
|
-
let useVirtualList = $derived(options.length >
|
|
47
|
+
let useVirtualList = $derived(options.length > 4000)
|
|
48
48
|
|
|
49
49
|
let errorTextRaw: string = $state(errorText)
|
|
50
50
|
let errorRaw = $state(error)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { isFirstInvalidControlInForm } from './report-validity.js'
|
|
3
|
+
import type { FocusEventHandler } from 'svelte/elements'
|
|
3
4
|
import type { TextFieldProps } from './types.ts'
|
|
4
5
|
|
|
5
6
|
let {
|
|
@@ -15,11 +16,14 @@
|
|
|
15
16
|
style,
|
|
16
17
|
noAsterisk = false,
|
|
17
18
|
variant = 'filled',
|
|
18
|
-
placeholder = ' ',
|
|
19
19
|
element = $bindable(),
|
|
20
|
+
populated = false,
|
|
20
21
|
inputElement = $bindable(),
|
|
21
22
|
reportValidity = $bindable(),
|
|
22
23
|
checkValidity = $bindable(),
|
|
24
|
+
children,
|
|
25
|
+
onfocus,
|
|
26
|
+
onblur,
|
|
23
27
|
...attributes
|
|
24
28
|
}: TextFieldProps = $props()
|
|
25
29
|
|
|
@@ -27,6 +31,7 @@
|
|
|
27
31
|
let errorTextRaw: string = $state(errorText)
|
|
28
32
|
let focusOnInvalid = $state(true)
|
|
29
33
|
let doValidity = $state(false)
|
|
34
|
+
let focused = $state(false)
|
|
30
35
|
|
|
31
36
|
reportValidity = () => {
|
|
32
37
|
if (inputElement) {
|
|
@@ -89,14 +94,26 @@
|
|
|
89
94
|
})
|
|
90
95
|
</script>
|
|
91
96
|
|
|
92
|
-
<
|
|
97
|
+
<div
|
|
93
98
|
style={(variant === 'outlined'
|
|
94
99
|
? '--_label-text-color:var(--np-outlined-text-field-label-text-color);--top-space:1rem;--bottom-space:1rem;--floating-label-top:-0.5rem;--floating-label-left:-2.25rem;--_focus-outline-width:3px;'
|
|
95
100
|
: !label?.length
|
|
96
|
-
? '--_label-text-color:var(--np-filled-text-field-label-text-color);--top-space:1rem;--bottom-space:1rem; '
|
|
97
|
-
: '--_label-text-color:var(--np-filled-text-field-label-text-color); '
|
|
101
|
+
? '--_label-text-color:var(--np-filled-text-field-label-text-color);--np-input-chip-outline-color:var(--np-color-outline);--top-space:1rem;--bottom-space:1rem; '
|
|
102
|
+
: '--_label-text-color:var(--np-filled-text-field-label-text-color);--np-input-chip-outline-color:var(--np-color-outline); ' +
|
|
103
|
+
(children ? '--top-space:2rem;--bottom-space:1rem;' : '')) + style}
|
|
98
104
|
class={['text-field', attributes.class]}
|
|
99
105
|
bind:this={element}
|
|
106
|
+
role="button"
|
|
107
|
+
tabindex="-1"
|
|
108
|
+
onfocus={() => {
|
|
109
|
+
inputElement?.focus()
|
|
110
|
+
}}
|
|
111
|
+
onkeydown={(event) => {
|
|
112
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
113
|
+
event.preventDefault()
|
|
114
|
+
inputElement?.focus()
|
|
115
|
+
}
|
|
116
|
+
}}
|
|
100
117
|
>
|
|
101
118
|
<div
|
|
102
119
|
class="field"
|
|
@@ -106,6 +123,8 @@
|
|
|
106
123
|
class:with-start={start}
|
|
107
124
|
class:with-end={end}
|
|
108
125
|
class:disabled={attributes.disabled}
|
|
126
|
+
class:populated={(value !== '' && value !== undefined && value !== null) || populated}
|
|
127
|
+
class:focused
|
|
109
128
|
class:outlined={variant === 'outlined'}
|
|
110
129
|
>
|
|
111
130
|
<div class="container-overflow">
|
|
@@ -119,7 +138,9 @@
|
|
|
119
138
|
<div class="outline-start"></div>
|
|
120
139
|
{#if label?.length}
|
|
121
140
|
<div class="label-wrapper">
|
|
122
|
-
<span class="label"
|
|
141
|
+
<span class="label" aria-disabled={attributes.disabled}
|
|
142
|
+
>{label}{noAsterisk || !attributes.required ? '' : '*'}
|
|
143
|
+
</span>
|
|
123
144
|
</div>
|
|
124
145
|
<div class="outline-notch">
|
|
125
146
|
<span class="notch np-hidden" aria-hidden="true"
|
|
@@ -140,7 +161,9 @@
|
|
|
140
161
|
{#if variant === 'filled'}
|
|
141
162
|
<div class="label-wrapper">
|
|
142
163
|
{#if label?.length}
|
|
143
|
-
<span class="label"
|
|
164
|
+
<span class="label" aria-disabled={attributes.disabled}
|
|
165
|
+
>{label}{noAsterisk || !attributes.required ? '' : '*'}
|
|
166
|
+
</span>
|
|
144
167
|
{/if}
|
|
145
168
|
</div>
|
|
146
169
|
{/if}
|
|
@@ -149,10 +172,17 @@
|
|
|
149
172
|
<textarea
|
|
150
173
|
aria-label={label}
|
|
151
174
|
{...attributes}
|
|
175
|
+
onfocus={(event) => {
|
|
176
|
+
focused = true
|
|
177
|
+
;(onfocus as FocusEventHandler<HTMLTextAreaElement>)?.(event)
|
|
178
|
+
}}
|
|
179
|
+
onblur={(event) => {
|
|
180
|
+
focused = false
|
|
181
|
+
;(onblur as FocusEventHandler<HTMLTextAreaElement>)?.(event)
|
|
182
|
+
}}
|
|
152
183
|
bind:value
|
|
153
184
|
bind:this={inputElement}
|
|
154
185
|
class="input"
|
|
155
|
-
{placeholder}
|
|
156
186
|
rows={attributes.rows || 2}
|
|
157
187
|
></textarea>
|
|
158
188
|
{:else}
|
|
@@ -162,13 +192,21 @@
|
|
|
162
192
|
{prefixText}
|
|
163
193
|
</span>
|
|
164
194
|
{/if}
|
|
195
|
+
{@render children?.()}
|
|
165
196
|
<input
|
|
166
197
|
aria-label={label}
|
|
167
198
|
{...attributes}
|
|
168
199
|
bind:value
|
|
169
200
|
bind:this={inputElement}
|
|
201
|
+
onfocus={(event) => {
|
|
202
|
+
focused = true
|
|
203
|
+
;(onfocus as FocusEventHandler<HTMLInputElement>)?.(event)
|
|
204
|
+
}}
|
|
205
|
+
onblur={(event) => {
|
|
206
|
+
focused = false
|
|
207
|
+
;(onblur as FocusEventHandler<HTMLInputElement>)?.(event)
|
|
208
|
+
}}
|
|
170
209
|
class="input"
|
|
171
|
-
{placeholder}
|
|
172
210
|
aria-invalid={errorRaw}
|
|
173
211
|
/>
|
|
174
212
|
{#if suffixText}
|
|
@@ -198,7 +236,7 @@
|
|
|
198
236
|
</div>
|
|
199
237
|
{/if}
|
|
200
238
|
</div>
|
|
201
|
-
</
|
|
239
|
+
</div>
|
|
202
240
|
|
|
203
241
|
<style>
|
|
204
242
|
.active-indicator {
|
|
@@ -356,6 +394,7 @@
|
|
|
356
394
|
top: var(--_focus-outline-width, 3px);
|
|
357
395
|
inset-inline-start: var(--_focus-outline-width, 0);
|
|
358
396
|
}
|
|
397
|
+
|
|
359
398
|
.content * {
|
|
360
399
|
all: unset;
|
|
361
400
|
color: currentColor;
|
|
@@ -366,6 +405,17 @@
|
|
|
366
405
|
white-space: revert;
|
|
367
406
|
}
|
|
368
407
|
|
|
408
|
+
.input-wrapper {
|
|
409
|
+
display: flex;
|
|
410
|
+
flex-wrap: wrap;
|
|
411
|
+
align-items: baseline;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
.input-wrapper > * {
|
|
415
|
+
all: inherit;
|
|
416
|
+
padding: 0;
|
|
417
|
+
}
|
|
418
|
+
|
|
369
419
|
.middle {
|
|
370
420
|
align-items: stretch;
|
|
371
421
|
align-self: baseline;
|
|
@@ -376,6 +426,7 @@
|
|
|
376
426
|
caret-color: var(--np-color-primary);
|
|
377
427
|
overflow-x: hidden;
|
|
378
428
|
text-align: inherit;
|
|
429
|
+
flex: 1;
|
|
379
430
|
|
|
380
431
|
&::placeholder {
|
|
381
432
|
color: currentColor;
|
|
@@ -399,8 +450,7 @@
|
|
|
399
450
|
.no-label .content,
|
|
400
451
|
.field:has(input:focus-visible) .content,
|
|
401
452
|
.field:has(textarea:focus-visible) .content,
|
|
402
|
-
.field
|
|
403
|
-
.field:has(textarea:not(:placeholder-shown)) .content {
|
|
453
|
+
.field.populated .content {
|
|
404
454
|
opacity: 1;
|
|
405
455
|
}
|
|
406
456
|
|
|
@@ -429,18 +479,18 @@
|
|
|
429
479
|
margin-bottom: var(--bottom-space, 0.5rem);
|
|
430
480
|
}
|
|
431
481
|
|
|
432
|
-
.input-wrapper
|
|
433
|
-
|
|
482
|
+
.content .input-wrapper .input,
|
|
483
|
+
.content .input-wrapper .prefix,
|
|
484
|
+
.content .input-wrapper .suffix {
|
|
485
|
+
margin-top: var(--top-space, 1.5rem);
|
|
486
|
+
margin-bottom: var(--bottom-space, 0.5rem);
|
|
434
487
|
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
all: inherit;
|
|
438
|
-
padding: 0;
|
|
488
|
+
.content .input-wrapper .input {
|
|
489
|
+
min-width: 100px;
|
|
439
490
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
padding-bottom: var(--bottom-space, 0.5rem);
|
|
491
|
+
:global(.content .input-wrapper .np-chip-set) {
|
|
492
|
+
margin-top: calc(var(--top-space, 1.5rem) - 4px);
|
|
493
|
+
margin-right: 0.5rem;
|
|
444
494
|
}
|
|
445
495
|
|
|
446
496
|
.prefix {
|
|
@@ -456,6 +506,8 @@
|
|
|
456
506
|
user-select: none;
|
|
457
507
|
text-wrap: nowrap;
|
|
458
508
|
width: min-content;
|
|
509
|
+
display: flex;
|
|
510
|
+
align-items: center;
|
|
459
511
|
}
|
|
460
512
|
.start {
|
|
461
513
|
color: var(--np-color-on-surface-variant);
|
|
@@ -520,21 +572,13 @@
|
|
|
520
572
|
.with-end .np-outline .label-wrapper {
|
|
521
573
|
margin-inline-end: 3.25rem;
|
|
522
574
|
}
|
|
523
|
-
.with-start:has(input:focus-visible
|
|
524
|
-
.with-start:has(
|
|
525
|
-
.with-start:has(input:not(:placeholder-shown)) .label-wrapper,
|
|
526
|
-
.with-start:has(textarea:focus-visible:not(:placeholder-shown)) .label-wrapper,
|
|
527
|
-
.with-start:has(textarea:focus-visible) .label-wrapper,
|
|
528
|
-
.with-start:has(textarea:not(:placeholder-shown)) .label-wrapper {
|
|
575
|
+
.with-start.populated .with-start:has(input:focus-visible) .label-wrapper,
|
|
576
|
+
.with-start:has(textarea:focus-visible) .label-wrapper {
|
|
529
577
|
right: -2.25rem;
|
|
530
578
|
}
|
|
531
579
|
|
|
532
|
-
.with-end:has(input:focus-visible
|
|
533
|
-
.with-end:has(
|
|
534
|
-
.with-end:has(input:not(:placeholder-shown)) .label-wrapper,
|
|
535
|
-
.with-end:has(textarea:focus-visible:not(:placeholder-shown)) .label-wrapper,
|
|
536
|
-
.with-end:has(textarea:focus-visible) .label-wrapper,
|
|
537
|
-
.with-end:has(textarea:not(:placeholder-shown)) .label-wrapper {
|
|
580
|
+
.with-end.populated .with-end:has(input:focus-visible) .label-wrapper,
|
|
581
|
+
.with-end:has(textarea:focus-visible) .label-wrapper {
|
|
538
582
|
margin-inline-end: 1rem;
|
|
539
583
|
}
|
|
540
584
|
.notch {
|
|
@@ -549,30 +593,23 @@
|
|
|
549
593
|
opacity: 0;
|
|
550
594
|
}
|
|
551
595
|
|
|
552
|
-
.field:
|
|
553
|
-
.field:has(textarea:not(:focus-visible):placeholder-shown) .label {
|
|
596
|
+
.field:not(.populated) .label {
|
|
554
597
|
position: absolute;
|
|
555
598
|
top: 1rem;
|
|
556
599
|
left: 0rem;
|
|
557
600
|
}
|
|
558
|
-
.field
|
|
601
|
+
.field.populated .label,
|
|
559
602
|
.field:has(input:focus-visible) .label,
|
|
560
|
-
.field:has(
|
|
561
|
-
.field:has(textarea:focus-visible:not(:placeholder-shown)) .label,
|
|
562
|
-
.field:has(textarea:focus-visible) .label,
|
|
563
|
-
.field:has(textarea:not(:placeholder-shown)) .label {
|
|
603
|
+
.field:has(textarea:focus-visible) .label {
|
|
564
604
|
font-size: 0.75rem;
|
|
565
605
|
line-height: 1rem;
|
|
566
606
|
transform-origin: top left;
|
|
567
607
|
position: absolute;
|
|
568
608
|
top: var(--floating-label-top, 0.5rem);
|
|
569
609
|
}
|
|
570
|
-
.with-start
|
|
610
|
+
.with-start.populated .label,
|
|
571
611
|
.with-start:has(input:focus-visible) .label,
|
|
572
|
-
.with-start:has(
|
|
573
|
-
.with-start:has(textarea:focus-visible:not(:placeholder-shown)) .label,
|
|
574
|
-
.with-start:has(textarea:focus-visible) .label,
|
|
575
|
-
.with-start:has(textarea:not(:placeholder-shown)) .label {
|
|
612
|
+
.with-start:has(textarea:focus-visible) .label {
|
|
576
613
|
left: var(--floating-label-left, 0);
|
|
577
614
|
}
|
|
578
615
|
.label {
|
|
@@ -610,8 +647,7 @@
|
|
|
610
647
|
overflow: hidden;
|
|
611
648
|
}
|
|
612
649
|
.disabled.no-label .content,
|
|
613
|
-
.disabled
|
|
614
|
-
.disabled:has(textarea:not(:placeholder-shown)) .content {
|
|
650
|
+
.disabled.populated .content {
|
|
615
651
|
opacity: 0.38;
|
|
616
652
|
}
|
|
617
653
|
.field,
|
|
@@ -687,8 +723,7 @@
|
|
|
687
723
|
}
|
|
688
724
|
.field:has(input:focus-visible) .outline-notch::before,
|
|
689
725
|
.field:has(textarea:focus-visible) .outline-notch::before,
|
|
690
|
-
.field
|
|
691
|
-
.field:has(textarea:not(:placeholder-shown)) .outline-notch::before {
|
|
726
|
+
.field.populated .outline-notch::before {
|
|
692
727
|
border-top-style: none;
|
|
693
728
|
}
|
|
694
729
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "noph-ui",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.5",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"homepage": "https://noph.dev",
|
|
6
6
|
"repository": {
|
|
@@ -52,27 +52,27 @@
|
|
|
52
52
|
"svelte": "^5.20.0"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@eslint/js": "^9.
|
|
55
|
+
"@eslint/js": "^9.23.0",
|
|
56
56
|
"@material/material-color-utilities": "^0.3.0",
|
|
57
|
-
"@playwright/test": "^1.51.
|
|
57
|
+
"@playwright/test": "^1.51.1",
|
|
58
58
|
"@sveltejs/adapter-vercel": "^5.6.3",
|
|
59
|
-
"@sveltejs/kit": "^2.
|
|
59
|
+
"@sveltejs/kit": "^2.20.2",
|
|
60
60
|
"@sveltejs/package": "^2.3.10",
|
|
61
61
|
"@sveltejs/vite-plugin-svelte": "^5.0.3",
|
|
62
62
|
"@types/eslint": "^9.6.1",
|
|
63
|
-
"eslint": "^9.
|
|
63
|
+
"eslint": "^9.23.0",
|
|
64
64
|
"eslint-config-prettier": "^10.1.1",
|
|
65
|
-
"eslint-plugin-svelte": "^3.
|
|
65
|
+
"eslint-plugin-svelte": "^3.3.3",
|
|
66
66
|
"globals": "^16.0.0",
|
|
67
67
|
"prettier": "^3.5.3",
|
|
68
68
|
"prettier-plugin-svelte": "^3.3.3",
|
|
69
69
|
"publint": "^0.3.9",
|
|
70
|
-
"svelte": "^5.
|
|
70
|
+
"svelte": "^5.25.3",
|
|
71
71
|
"svelte-check": "^4.1.5",
|
|
72
72
|
"typescript": "^5.8.2",
|
|
73
|
-
"typescript-eslint": "^8.
|
|
74
|
-
"vite": "^6.2.
|
|
75
|
-
"vitest": "^3.0.
|
|
73
|
+
"typescript-eslint": "^8.27.0",
|
|
74
|
+
"vite": "^6.2.2",
|
|
75
|
+
"vitest": "^3.0.9"
|
|
76
76
|
},
|
|
77
77
|
"svelte": "./dist/index.js",
|
|
78
78
|
"types": "./dist/index.d.ts",
|