noph-ui 0.17.13 → 0.18.1
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/autocomplete/AutoComplete.svelte +48 -53
- package/dist/autocomplete/AutoComplete.svelte.d.ts +1 -1
- package/dist/autocomplete/types.d.ts +2 -1
- package/dist/chip/types.d.ts +1 -1
- package/dist/tabs/Tab.svelte +15 -21
- package/dist/text-field/TextField.svelte +1 -1
- package/dist/text-field/TextField.svelte.d.ts +1 -1
- package/dist/text-field/types.d.ts +1 -0
- package/package.json +1 -1
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import Item from '../list/Item.svelte'
|
|
3
3
|
import Menu from '../menu/Menu.svelte'
|
|
4
4
|
import VirtualList from '../select/VirtualList.svelte'
|
|
5
|
-
import { tick } from 'svelte'
|
|
6
5
|
import type { AutoCompleteOption, AutoCompleteProps } from './types.ts'
|
|
7
6
|
import TextField from '../text-field/TextField.svelte'
|
|
8
7
|
|
|
@@ -11,56 +10,39 @@
|
|
|
11
10
|
value = $bindable(),
|
|
12
11
|
variant = 'filled',
|
|
13
12
|
element = $bindable(),
|
|
14
|
-
|
|
15
|
-
oninput,
|
|
13
|
+
populated,
|
|
16
14
|
reportValidity = $bindable(),
|
|
17
15
|
checkValidity = $bindable(),
|
|
18
16
|
clampMenuWidth = false,
|
|
19
17
|
children,
|
|
20
|
-
optionsFilter
|
|
21
|
-
return !value || option.value.includes(value)
|
|
22
|
-
},
|
|
18
|
+
optionsFilter,
|
|
23
19
|
oncomplete = (option) => {
|
|
24
|
-
value = option.
|
|
25
|
-
|
|
20
|
+
value = option.label
|
|
21
|
+
finalPopulated = populated
|
|
26
22
|
menuElement?.hidePopover()
|
|
27
23
|
},
|
|
28
|
-
|
|
24
|
+
onkeydown,
|
|
29
25
|
onclick,
|
|
26
|
+
oninput,
|
|
27
|
+
focused = $bindable(false),
|
|
30
28
|
...attributes
|
|
31
29
|
}: AutoCompleteProps = $props()
|
|
32
30
|
|
|
33
31
|
const uid = $props.id()
|
|
34
|
-
let
|
|
32
|
+
let defaultOptionsFilter = (option: AutoCompleteOption) => {
|
|
33
|
+
return !value || option.label.includes(value)
|
|
34
|
+
}
|
|
35
|
+
let displayOptions = $derived(options.filter(optionsFilter || defaultOptionsFilter))
|
|
35
36
|
let useVirtualList = $derived(displayOptions.length > 4000)
|
|
36
37
|
let clientWidth = $state(0)
|
|
37
|
-
let menuOpen = $state(false)
|
|
38
38
|
let menuElement: HTMLDivElement | undefined = $state()
|
|
39
|
-
|
|
40
|
-
const handleOptionSelect = (event: Event, option: AutoCompleteOption) => {
|
|
41
|
-
value = option.value
|
|
42
|
-
menuElement?.hidePopover()
|
|
43
|
-
event.preventDefault()
|
|
44
|
-
// tick().then(() => {
|
|
45
|
-
// if (checkValidity?.()) {
|
|
46
|
-
// errorRaw = error
|
|
47
|
-
// errorTextRaw = errorText
|
|
48
|
-
// }
|
|
49
|
-
// element?.dispatchEvent(new Event('change', { bubbles: true }))
|
|
50
|
-
// })
|
|
51
|
-
}
|
|
52
|
-
$effect(() => {
|
|
53
|
-
if (displayOptions.length) {
|
|
54
|
-
menuElement?.showPopover()
|
|
55
|
-
} else {
|
|
56
|
-
menuElement?.hidePopover()
|
|
57
|
-
}
|
|
58
|
-
})
|
|
39
|
+
let finalPopulated = $state(populated)
|
|
59
40
|
</script>
|
|
60
41
|
|
|
61
42
|
{#snippet item(option: AutoCompleteOption)}
|
|
62
43
|
<Item
|
|
63
|
-
onclick={() => {
|
|
44
|
+
onclick={(event) => {
|
|
45
|
+
event.preventDefault()
|
|
64
46
|
oncomplete(option)
|
|
65
47
|
element?.focus()
|
|
66
48
|
}}
|
|
@@ -78,44 +60,57 @@
|
|
|
78
60
|
oncomplete(option)
|
|
79
61
|
}
|
|
80
62
|
if (event.key === 'Tab') {
|
|
63
|
+
finalPopulated = populated
|
|
81
64
|
menuElement?.hidePopover()
|
|
82
65
|
}
|
|
83
66
|
}}
|
|
84
67
|
variant="button"
|
|
85
|
-
>{option.
|
|
68
|
+
>{option.label}
|
|
86
69
|
</Item>
|
|
87
70
|
{/snippet}
|
|
88
71
|
|
|
89
72
|
<TextField
|
|
90
73
|
{variant}
|
|
74
|
+
type="text"
|
|
75
|
+
populated={finalPopulated}
|
|
91
76
|
bind:clientWidth
|
|
92
77
|
bind:value
|
|
78
|
+
bind:focused
|
|
93
79
|
style="anchor-name:--{uid};"
|
|
94
|
-
onclick={
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
},
|
|
98
|
-
) => {
|
|
99
|
-
if (displayOptions.length) {
|
|
100
|
-
menuElement?.showPopover()
|
|
101
|
-
}
|
|
80
|
+
onclick={(event) => {
|
|
81
|
+
finalPopulated = true
|
|
82
|
+
menuElement?.showPopover()
|
|
102
83
|
onclick?.(event)
|
|
103
84
|
}}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
85
|
+
oninput={(event) => {
|
|
86
|
+
menuElement?.showPopover()
|
|
87
|
+
oninput?.(event)
|
|
88
|
+
}}
|
|
89
|
+
onkeydown={(event) => {
|
|
90
|
+
if (event.key === 'Tab' || event.key === 'Escape') {
|
|
91
|
+
menuElement?.hidePopover()
|
|
92
|
+
} else {
|
|
93
|
+
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
|
|
94
|
+
event.preventDefault()
|
|
95
|
+
finalPopulated = true
|
|
96
|
+
menuElement?.showPopover()
|
|
97
|
+
;(menuElement?.firstElementChild?.firstElementChild as HTMLElement)?.focus()
|
|
98
|
+
}
|
|
107
99
|
}
|
|
100
|
+
onkeydown?.(event)
|
|
108
101
|
}}
|
|
109
102
|
bind:reportValidity
|
|
110
103
|
bind:checkValidity
|
|
111
104
|
bind:element
|
|
112
|
-
{...attributes}
|
|
113
|
-
>
|
|
105
|
+
{...attributes}
|
|
106
|
+
>{@render children?.()}
|
|
107
|
+
</TextField>
|
|
114
108
|
<Menu
|
|
115
109
|
style="position-anchor:--{uid};{clampMenuWidth || useVirtualList
|
|
116
110
|
? 'width'
|
|
117
111
|
: 'min-width'}:{clientWidth}px"
|
|
118
112
|
role="listbox"
|
|
113
|
+
class={[!displayOptions.length && 'np-auto-complete-empty']}
|
|
119
114
|
--np-menu-justify-self="none"
|
|
120
115
|
--np-menu-position-area="bottom span-right"
|
|
121
116
|
--np-menu-margin="2px 0"
|
|
@@ -123,13 +118,6 @@
|
|
|
123
118
|
? 'var(--np-outlined-select-text-field-container-shape)'
|
|
124
119
|
: 'var(--np-filled-select-text-field-container-shape)'}
|
|
125
120
|
anchor={element}
|
|
126
|
-
ontoggle={({ newState }) => {
|
|
127
|
-
if (newState === 'open') {
|
|
128
|
-
menuOpen = true
|
|
129
|
-
} else {
|
|
130
|
-
menuOpen = false
|
|
131
|
-
}
|
|
132
|
-
}}
|
|
133
121
|
bind:element={menuElement}
|
|
134
122
|
>
|
|
135
123
|
{#if useVirtualList}
|
|
@@ -144,3 +132,10 @@
|
|
|
144
132
|
{/each}
|
|
145
133
|
{/if}
|
|
146
134
|
</Menu>
|
|
135
|
+
|
|
136
|
+
<style>
|
|
137
|
+
:global(.np-auto-complete-empty) {
|
|
138
|
+
display: none !important;
|
|
139
|
+
opacity: 0 !important;
|
|
140
|
+
}
|
|
141
|
+
</style>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { AutoCompleteProps } from './types.ts';
|
|
2
|
-
declare const AutoComplete: import("svelte").Component<AutoCompleteProps, {}, "element" | "value" | "reportValidity" | "checkValidity">;
|
|
2
|
+
declare const AutoComplete: import("svelte").Component<AutoCompleteProps, {}, "element" | "value" | "reportValidity" | "checkValidity" | "focused">;
|
|
3
3
|
type AutoComplete = ReturnType<typeof AutoComplete>;
|
|
4
4
|
export default AutoComplete;
|
package/dist/chip/types.d.ts
CHANGED
|
@@ -41,7 +41,7 @@ export interface InputChipProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
41
41
|
ariaLabelRemove?: string;
|
|
42
42
|
element?: HTMLDivElement;
|
|
43
43
|
name?: string;
|
|
44
|
-
value?: string;
|
|
44
|
+
value?: string | number;
|
|
45
45
|
onremove?: (event: MouseEvent & {
|
|
46
46
|
currentTarget: EventTarget & HTMLButtonElement;
|
|
47
47
|
}) => void;
|
package/dist/tabs/Tab.svelte
CHANGED
|
@@ -35,11 +35,16 @@
|
|
|
35
35
|
const oldIndicatorRect = oldIndicator?.getBoundingClientRect()
|
|
36
36
|
if (oldIndicatorRect) {
|
|
37
37
|
const newIndicator = el.querySelector<HTMLElement>('.np-indicator')
|
|
38
|
-
newIndicator
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
if (newIndicator) {
|
|
39
|
+
newIndicator.style.setProperty(
|
|
40
|
+
'--np-tab-indicator-start',
|
|
41
|
+
`${oldIndicatorRect.x - newIndicator.getBoundingClientRect().x}px`,
|
|
42
|
+
)
|
|
43
|
+
newIndicator.style.setProperty(
|
|
44
|
+
'--np-tab-indicator-scale',
|
|
45
|
+
`${oldIndicatorRect.width / newIndicator.clientWidth}`,
|
|
46
|
+
)
|
|
47
|
+
}
|
|
43
48
|
}
|
|
44
49
|
activeTab.value = value
|
|
45
50
|
activeTab.node = el
|
|
@@ -99,12 +104,7 @@
|
|
|
99
104
|
role="tab"
|
|
100
105
|
bind:this={element}
|
|
101
106
|
{href}
|
|
102
|
-
class={[
|
|
103
|
-
'np-tab',
|
|
104
|
-
variant === 'secondary' && 'np-tab-secondary',
|
|
105
|
-
isActive && 'np-tab-content-active',
|
|
106
|
-
attributes.class,
|
|
107
|
-
]}
|
|
107
|
+
class={['np-tab', isActive && 'np-tab-content-active', attributes.class]}
|
|
108
108
|
onclick={onClick}
|
|
109
109
|
onkeydown={onKeyDown}
|
|
110
110
|
>
|
|
@@ -117,12 +117,7 @@
|
|
|
117
117
|
tabindex={isActive ? 0 : -1}
|
|
118
118
|
role="tab"
|
|
119
119
|
bind:this={element}
|
|
120
|
-
class={[
|
|
121
|
-
'np-tab',
|
|
122
|
-
variant === 'secondary' && 'np-tab-secondary',
|
|
123
|
-
isActive && 'np-tab-content-active',
|
|
124
|
-
attributes.class,
|
|
125
|
-
]}
|
|
120
|
+
class={['np-tab', isActive && 'np-tab-content-active', attributes.class]}
|
|
126
121
|
onclick={onClick}
|
|
127
122
|
onkeydown={onKeyDown}
|
|
128
123
|
>
|
|
@@ -188,17 +183,16 @@
|
|
|
188
183
|
}
|
|
189
184
|
.np-tab-content-active .np-indicator {
|
|
190
185
|
opacity: 1;
|
|
186
|
+
transform-origin: left center;
|
|
191
187
|
animation: slide 0.3s ease-in-out;
|
|
192
188
|
}
|
|
193
189
|
|
|
194
190
|
@keyframes slide {
|
|
195
191
|
0% {
|
|
196
|
-
|
|
197
|
-
transform: translateX(var(--np-tab-indicator-start));
|
|
192
|
+
transform: translateX(var(--np-tab-indicator-start)) scaleX(var(--np-tab-indicator-scale, 1));
|
|
198
193
|
}
|
|
199
194
|
100% {
|
|
200
|
-
|
|
201
|
-
transform: translateX(0);
|
|
195
|
+
transform: translateX(0) scaleX(1);
|
|
202
196
|
}
|
|
203
197
|
}
|
|
204
198
|
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
children,
|
|
25
25
|
onfocus,
|
|
26
26
|
onblur,
|
|
27
|
+
focused = $bindable(false),
|
|
27
28
|
clientWidth = $bindable(),
|
|
28
29
|
clientHeight = $bindable(),
|
|
29
30
|
...attributes
|
|
@@ -33,7 +34,6 @@
|
|
|
33
34
|
let errorTextRaw: string = $state(errorText)
|
|
34
35
|
let focusOnInvalid = $state(true)
|
|
35
36
|
let doValidity = $state(false)
|
|
36
|
-
let focused = $state(false)
|
|
37
37
|
|
|
38
38
|
reportValidity = () => {
|
|
39
39
|
if (inputElement) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { TextFieldProps } from './types.ts';
|
|
2
|
-
declare const TextField: import("svelte").Component<TextFieldProps, {}, "element" | "value" | "reportValidity" | "checkValidity" | "inputElement" | "clientWidth" | "clientHeight">;
|
|
2
|
+
declare const TextField: import("svelte").Component<TextFieldProps, {}, "element" | "value" | "reportValidity" | "checkValidity" | "inputElement" | "clientWidth" | "clientHeight" | "focused">;
|
|
3
3
|
type TextField = ReturnType<typeof TextField>;
|
|
4
4
|
export default TextField;
|
|
@@ -18,6 +18,7 @@ interface FieldProps {
|
|
|
18
18
|
checkValidity?: () => boolean;
|
|
19
19
|
clientWidth?: number;
|
|
20
20
|
clientHeight?: number;
|
|
21
|
+
focused?: boolean;
|
|
21
22
|
}
|
|
22
23
|
export interface InputFieldProps extends HTMLInputAttributes, FieldProps {
|
|
23
24
|
type?: 'text' | 'password' | 'email' | 'number' | 'search' | 'tel' | 'url' | 'datetime-local';
|