noph-ui 0.17.12 → 0.18.0
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.
|
@@ -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,38 @@
|
|
|
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,
|
|
30
27
|
...attributes
|
|
31
28
|
}: AutoCompleteProps = $props()
|
|
32
29
|
|
|
33
30
|
const uid = $props.id()
|
|
34
|
-
let
|
|
31
|
+
let defaultOptionsFilter = (option: AutoCompleteOption) => {
|
|
32
|
+
return !value || option.label.includes(value)
|
|
33
|
+
}
|
|
34
|
+
let displayOptions = $derived(options.filter(optionsFilter || defaultOptionsFilter))
|
|
35
35
|
let useVirtualList = $derived(displayOptions.length > 4000)
|
|
36
36
|
let clientWidth = $state(0)
|
|
37
|
-
let menuOpen = $state(false)
|
|
38
37
|
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
|
-
})
|
|
38
|
+
let finalPopulated = $state(populated)
|
|
59
39
|
</script>
|
|
60
40
|
|
|
61
41
|
{#snippet item(option: AutoCompleteOption)}
|
|
62
42
|
<Item
|
|
63
|
-
onclick={() => {
|
|
43
|
+
onclick={(event) => {
|
|
44
|
+
event.preventDefault()
|
|
64
45
|
oncomplete(option)
|
|
65
46
|
element?.focus()
|
|
66
47
|
}}
|
|
@@ -78,44 +59,56 @@
|
|
|
78
59
|
oncomplete(option)
|
|
79
60
|
}
|
|
80
61
|
if (event.key === 'Tab') {
|
|
62
|
+
finalPopulated = populated
|
|
81
63
|
menuElement?.hidePopover()
|
|
82
64
|
}
|
|
83
65
|
}}
|
|
84
66
|
variant="button"
|
|
85
|
-
>{option.
|
|
67
|
+
>{option.label}
|
|
86
68
|
</Item>
|
|
87
69
|
{/snippet}
|
|
88
70
|
|
|
89
71
|
<TextField
|
|
90
72
|
{variant}
|
|
73
|
+
type="text"
|
|
74
|
+
populated={finalPopulated}
|
|
91
75
|
bind:clientWidth
|
|
92
76
|
bind:value
|
|
93
77
|
style="anchor-name:--{uid};"
|
|
94
|
-
onclick={
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
},
|
|
98
|
-
) => {
|
|
99
|
-
if (displayOptions.length) {
|
|
100
|
-
menuElement?.showPopover()
|
|
101
|
-
}
|
|
78
|
+
onclick={(event) => {
|
|
79
|
+
finalPopulated = true
|
|
80
|
+
menuElement?.showPopover()
|
|
102
81
|
onclick?.(event)
|
|
103
82
|
}}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
83
|
+
oninput={(event) => {
|
|
84
|
+
menuElement?.showPopover()
|
|
85
|
+
oninput?.(event)
|
|
86
|
+
}}
|
|
87
|
+
onkeydown={(event) => {
|
|
88
|
+
if (event.key === 'Tab' || event.key === 'Escape') {
|
|
89
|
+
menuElement?.hidePopover()
|
|
90
|
+
} else {
|
|
91
|
+
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
|
|
92
|
+
event.preventDefault()
|
|
93
|
+
finalPopulated = true
|
|
94
|
+
menuElement?.showPopover()
|
|
95
|
+
;(menuElement?.firstElementChild?.firstElementChild as HTMLElement)?.focus()
|
|
96
|
+
}
|
|
107
97
|
}
|
|
98
|
+
onkeydown?.(event)
|
|
108
99
|
}}
|
|
109
100
|
bind:reportValidity
|
|
110
101
|
bind:checkValidity
|
|
111
102
|
bind:element
|
|
112
|
-
{...attributes}
|
|
113
|
-
>
|
|
103
|
+
{...attributes}
|
|
104
|
+
>{@render children?.()}
|
|
105
|
+
</TextField>
|
|
114
106
|
<Menu
|
|
115
107
|
style="position-anchor:--{uid};{clampMenuWidth || useVirtualList
|
|
116
108
|
? 'width'
|
|
117
109
|
: 'min-width'}:{clientWidth}px"
|
|
118
110
|
role="listbox"
|
|
111
|
+
class={[!displayOptions.length && 'np-auto-complete-empty']}
|
|
119
112
|
--np-menu-justify-self="none"
|
|
120
113
|
--np-menu-position-area="bottom span-right"
|
|
121
114
|
--np-menu-margin="2px 0"
|
|
@@ -123,13 +116,6 @@
|
|
|
123
116
|
? 'var(--np-outlined-select-text-field-container-shape)'
|
|
124
117
|
: 'var(--np-filled-select-text-field-container-shape)'}
|
|
125
118
|
anchor={element}
|
|
126
|
-
ontoggle={({ newState }) => {
|
|
127
|
-
if (newState === 'open') {
|
|
128
|
-
menuOpen = true
|
|
129
|
-
} else {
|
|
130
|
-
menuOpen = false
|
|
131
|
-
}
|
|
132
|
-
}}
|
|
133
119
|
bind:element={menuElement}
|
|
134
120
|
>
|
|
135
121
|
{#if useVirtualList}
|
|
@@ -144,3 +130,10 @@
|
|
|
144
130
|
{/each}
|
|
145
131
|
{/if}
|
|
146
132
|
</Menu>
|
|
133
|
+
|
|
134
|
+
<style>
|
|
135
|
+
:global(.np-auto-complete-empty) {
|
|
136
|
+
display: none !important;
|
|
137
|
+
opacity: 0 !important;
|
|
138
|
+
}
|
|
139
|
+
</style>
|
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
|
|