@neovici/cosmoz-autocomplete 8.9.2 → 9.0.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.d.ts +4 -3
- package/dist/autocomplete/autocomplete.js +20 -21
- package/dist/autocomplete/chip.js +6 -1
- package/dist/autocomplete/skeleton-span.d.ts +1 -0
- package/dist/autocomplete/skeleton-span.js +31 -0
- package/dist/autocomplete/styles.css.js +0 -22
- package/dist/autocomplete/use-autocomplete.d.ts +3 -5
- package/dist/autocomplete/use-autocomplete.js +23 -19
- package/dist/autocomplete/use-keys.d.ts +1 -2
- package/dist/autocomplete/use-keys.js +2 -8
- package/dist/autocomplete/util.d.ts +1 -1
- package/dist/autocomplete/util.js +4 -6
- package/dist/listbox/index.d.ts +1 -1
- package/dist/listbox/index.js +11 -11
- package/dist/listbox/item-renderer.js +1 -1
- package/dist/listbox/style.css.js +3 -3
- package/dist/listbox/use-items.js +4 -1
- package/dist/listbox/use-listbox.js +1 -0
- package/package.json +2 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import '@neovici/cosmoz-input';
|
|
2
|
-
import
|
|
2
|
+
import './skeleton-span';
|
|
3
3
|
import style from './styles.css';
|
|
4
|
+
import { Props as Base, RProps } from './use-autocomplete';
|
|
4
5
|
export interface Props<I> extends Base<I> {
|
|
5
6
|
invalid?: boolean;
|
|
6
7
|
errorMessage?: string;
|
|
@@ -17,5 +18,5 @@ export interface Props<I> extends Base<I> {
|
|
|
17
18
|
type AProps<I> = Omit<Props<I>, keyof RProps<I>> & RProps<I> & {
|
|
18
19
|
onInputRef?: (el?: Element) => void;
|
|
19
20
|
};
|
|
20
|
-
declare const autocomplete: <I>(props: AProps<I>) => import("lit-html").TemplateResult<1>, Autocomplete: <I>(props: Props<I>) => import("lit-html").TemplateResult<1>, observedAttributes: readonly ["disabled", "invalid", "no-label-float", "always-float-label", "text-property", "value-property", "limit", "min", "show-single", "preserve-order", "keep-opened", "keep-query", "
|
|
21
|
-
export {
|
|
21
|
+
declare const autocomplete: <I>(props: AProps<I>) => import("lit-html").TemplateResult<1>, Autocomplete: <I>(props: Props<I>) => import("lit-html").TemplateResult<1>, observedAttributes: readonly ["disabled", "invalid", "no-label-float", "always-float-label", "text-property", "value-property", "limit", "min", "show-single", "preserve-order", "keep-opened", "keep-query", "default-index", "item-height", "item-limit", "wrap"];
|
|
22
|
+
export { Autocomplete, autocomplete, observedAttributes, style };
|
|
@@ -1,34 +1,30 @@
|
|
|
1
|
+
import '@neovici/cosmoz-input';
|
|
2
|
+
import './skeleton-span';
|
|
3
|
+
import { useHost } from '@neovici/cosmoz-utils/hooks/use-host';
|
|
4
|
+
import { useImperativeApi } from '@neovici/cosmoz-utils/hooks/use-imperative-api';
|
|
5
|
+
import { useCallback } from '@pionjs/pion';
|
|
1
6
|
import { html, nothing } from 'lit-html'; // eslint-disable-line object-curly-newline
|
|
2
7
|
import { live } from 'lit-html/directives/live.js';
|
|
3
8
|
import { until } from 'lit-html/directives/until.js';
|
|
4
9
|
import { when } from 'lit-html/directives/when.js';
|
|
5
|
-
import { useCallback } from '@pionjs/pion';
|
|
6
|
-
import { useHost } from '@neovici/cosmoz-utils/hooks/use-host';
|
|
7
|
-
import { useImperativeApi } from '@neovici/cosmoz-utils/hooks/use-imperative-api';
|
|
8
|
-
import '@neovici/cosmoz-input';
|
|
9
|
-
import { useAutocomplete } from './use-autocomplete';
|
|
10
10
|
import { listbox } from '../listbox';
|
|
11
|
-
import style from './styles.css';
|
|
12
11
|
import { selection } from './selection';
|
|
12
|
+
import style from './styles.css';
|
|
13
|
+
import { useAutocomplete } from './use-autocomplete';
|
|
13
14
|
import { useOverflow } from './use-overflow';
|
|
14
|
-
const blank = () => nothing;
|
|
15
15
|
const inputParts = ['input', 'control', 'label', 'line', 'error', 'wrap']
|
|
16
16
|
.map((part) => `${part}: input-${part}`)
|
|
17
17
|
.join();
|
|
18
|
+
const blank = () => nothing;
|
|
18
19
|
const autocomplete = (props) => {
|
|
19
|
-
const { invalid, errorMessage, label, placeholder, disabled, noLabelFloat, alwaysFloatLabel, textual, text, onText, onFocus, onClick, onDeselect, value, limit, min, showSingle, items
|
|
20
|
+
const { active, invalid, errorMessage, label, placeholder, disabled, noLabelFloat, alwaysFloatLabel, textual, text, onText, onFocus, onClick, onDeselect, value, limit, min, showSingle, items, source$, } = props, host = useHost(), isOne = limit == 1, // eslint-disable-line eqeqeq
|
|
20
21
|
isSingle = isOne && value?.[0] != null,
|
|
21
22
|
// TODO: Refactor with ref or a state callback
|
|
22
|
-
anchor = useCallback(() => host.shadowRoot.querySelector('#input'), [host, value])
|
|
23
|
-
...props,
|
|
24
|
-
anchor,
|
|
25
|
-
items,
|
|
26
|
-
multi: !isOne,
|
|
27
|
-
}))));
|
|
23
|
+
anchor = useCallback(() => host.shadowRoot.querySelector('#input'), [host, value]);
|
|
28
24
|
useImperativeApi({
|
|
29
25
|
focus: () => host.shadowRoot?.querySelector('#input')?.focus(),
|
|
30
26
|
}, []);
|
|
31
|
-
return html
|
|
27
|
+
return html `<cosmoz-input
|
|
32
28
|
id="input"
|
|
33
29
|
part="input"
|
|
34
30
|
.label=${label}
|
|
@@ -37,8 +33,8 @@ const autocomplete = (props) => {
|
|
|
37
33
|
?always-float-label=${value?.length > 0 || alwaysFloatLabel}
|
|
38
34
|
?readonly=${isSingle}
|
|
39
35
|
?disabled=${disabled}
|
|
40
|
-
?invalid=${until(
|
|
41
|
-
.errorMessage=${until(
|
|
36
|
+
?invalid=${until(source$.then(() => invalid, () => true), invalid)}
|
|
37
|
+
.errorMessage=${until(source$.then(() => errorMessage, (e) => e.message), errorMessage)}
|
|
42
38
|
.value=${live(text)}
|
|
43
39
|
@value-changed=${onText}
|
|
44
40
|
@focusin=${onFocus}
|
|
@@ -59,10 +55,14 @@ const autocomplete = (props) => {
|
|
|
59
55
|
textual,
|
|
60
56
|
disabled,
|
|
61
57
|
})}
|
|
62
|
-
${until(values$.then(blank, blank), html `<div slot="suffix" class="spinner"></div>`)}
|
|
63
58
|
</cosmoz-input>
|
|
64
59
|
|
|
65
|
-
${
|
|
60
|
+
${when(active && !(isSingle && !showSingle), () => listbox({
|
|
61
|
+
...props,
|
|
62
|
+
anchor,
|
|
63
|
+
items,
|
|
64
|
+
multi: !isOne,
|
|
65
|
+
}, when(items.length < 5, () => until(source$.then(blank, blank), html `<cosmoz-autocomplete-skeleton-span></cosmoz-autocomplete-skeleton-span>`))))}`;
|
|
66
66
|
}, Autocomplete = (props) => {
|
|
67
67
|
const thru = {
|
|
68
68
|
...props,
|
|
@@ -83,10 +83,9 @@ const autocomplete = (props) => {
|
|
|
83
83
|
'preserve-order',
|
|
84
84
|
'keep-opened',
|
|
85
85
|
'keep-query',
|
|
86
|
-
'hide-empty',
|
|
87
86
|
'default-index',
|
|
88
87
|
'item-height',
|
|
89
88
|
'item-limit',
|
|
90
89
|
'wrap',
|
|
91
90
|
];
|
|
92
|
-
export {
|
|
91
|
+
export { Autocomplete, autocomplete, observedAttributes, style };
|
|
@@ -29,7 +29,12 @@ const clear = html `
|
|
|
29
29
|
`;
|
|
30
30
|
export const Chip = ({ onClear, disabled }) => html `
|
|
31
31
|
<div class="content" part="content chip-text"><slot></slot></div>
|
|
32
|
-
${when(onClear && !disabled, () => html
|
|
32
|
+
${when(onClear && !disabled, () => html `<span
|
|
33
|
+
class="clear"
|
|
34
|
+
part="clear chip-clear"
|
|
35
|
+
@mousedown=${(ev) => ev.preventDefault()}
|
|
36
|
+
@click=${onClear}
|
|
37
|
+
>
|
|
33
38
|
${clear}
|
|
34
39
|
</span>`)}
|
|
35
40
|
`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { component, css } from '@pionjs/pion';
|
|
2
|
+
import { nothing } from 'lit-html';
|
|
3
|
+
const style = css `
|
|
4
|
+
:host {
|
|
5
|
+
display: inline-block;
|
|
6
|
+
vertical-align: middle;
|
|
7
|
+
background-image: linear-gradient(90deg, #e0e0e0, #f5f5f5, #e0e0e0);
|
|
8
|
+
background-size: 1000%;
|
|
9
|
+
background-position: right;
|
|
10
|
+
animation: sweep 1.5s cubic-bezier(0.3, 1, 0.3, 1) infinite;
|
|
11
|
+
border-radius: 3px;
|
|
12
|
+
width: calc(100% - 20px);
|
|
13
|
+
max-width: 150px;
|
|
14
|
+
height: 20px;
|
|
15
|
+
margin: 10px;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
:host-context([show-single]) {
|
|
19
|
+
margin-left: 20px;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@keyframes sweep {
|
|
23
|
+
0% {
|
|
24
|
+
background-position: right;
|
|
25
|
+
}
|
|
26
|
+
100% {
|
|
27
|
+
background-position: left;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
`;
|
|
31
|
+
customElements.define('cosmoz-autocomplete-skeleton-span', component(() => nothing, { styleSheets: [style] }));
|
|
@@ -52,26 +52,4 @@ export default css `
|
|
|
52
52
|
slot {
|
|
53
53
|
display: contents !important;
|
|
54
54
|
}
|
|
55
|
-
|
|
56
|
-
@keyframes rotateAnimation {
|
|
57
|
-
from {
|
|
58
|
-
transform: rotate(0deg);
|
|
59
|
-
}
|
|
60
|
-
to {
|
|
61
|
-
transform: rotate(360deg);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
.spinner {
|
|
66
|
-
border-radius: 50%;
|
|
67
|
-
width: 22px;
|
|
68
|
-
height: 22px;
|
|
69
|
-
border: 2px solid rgba(0, 0, 0, 0.1);
|
|
70
|
-
border-top: 2px solid #5f5a92;
|
|
71
|
-
animation: rotateAnimation 1.2s infinite
|
|
72
|
-
cubic-bezier(0.785, 0.135, 0.15, 0.86);
|
|
73
|
-
box-sizing: border-box;
|
|
74
|
-
margin-top: -3px;
|
|
75
|
-
flex: none;
|
|
76
|
-
}
|
|
77
55
|
`;
|
|
@@ -22,19 +22,17 @@ export interface Props<I> extends Base<I> {
|
|
|
22
22
|
textProperty?: string;
|
|
23
23
|
textual?: (prop?: string) => (i: I) => string;
|
|
24
24
|
valueProperty?: string;
|
|
25
|
-
external?: boolean;
|
|
26
|
-
hideEmpty?: boolean;
|
|
27
25
|
disabled?: boolean;
|
|
28
26
|
onFocus?: (focused?: boolean) => void;
|
|
29
27
|
preserveOrder?: boolean;
|
|
30
28
|
}
|
|
31
|
-
export declare const useAutocomplete: <I>({ value: _value, text, onChange: _onChange, onText: _onText, onSelect, limit, min, source, textProperty, textual: _textual, valueProperty,
|
|
29
|
+
export declare const useAutocomplete: <I>({ value: _value, text, onChange: _onChange, onText: _onText, onSelect, limit, min, source, textProperty, textual: _textual, valueProperty, keepOpened, keepQuery, preserveOrder, ...thru }: Props<I>) => {
|
|
32
30
|
active: boolean | undefined;
|
|
33
31
|
query: string;
|
|
34
32
|
textual: (i: I) => string;
|
|
35
33
|
value: I[];
|
|
36
|
-
|
|
37
|
-
items
|
|
34
|
+
source$: Promise<I[]>;
|
|
35
|
+
items: I[];
|
|
38
36
|
onClick: () => void;
|
|
39
37
|
onFocus: (e: FocusEvent) => void;
|
|
40
38
|
onText: (e: InputEvent) => void;
|
|
@@ -1,27 +1,22 @@
|
|
|
1
|
-
import { useCallback, useMemo, useEffect } from '@pionjs/pion';
|
|
1
|
+
import { useCallback, useMemo, useEffect, useState } from '@pionjs/pion';
|
|
2
2
|
import { without, array } from '@neovici/cosmoz-utils/array';
|
|
3
3
|
import { prop, strProp } from '@neovici/cosmoz-utils/object';
|
|
4
4
|
import { useHost } from '@neovici/cosmoz-utils/hooks/use-host';
|
|
5
5
|
import { useMeta } from '@neovici/cosmoz-utils/hooks/use-meta';
|
|
6
6
|
import { useFocus } from '@neovici/cosmoz-dropdown/use-focus';
|
|
7
7
|
import { useKeys } from './use-keys';
|
|
8
|
-
import { search, normalize, notify, useNotify, EMPTY
|
|
9
|
-
export const useAutocomplete = ({ value: _value, text, onChange: _onChange, onText: _onText, onSelect, limit, min, source, textProperty, textual: _textual, valueProperty,
|
|
8
|
+
import { search, normalize, notify, useNotify, EMPTY } from './util';
|
|
9
|
+
export const useAutocomplete = ({ value: _value, text, onChange: _onChange, onText: _onText, onSelect, limit, min, source, textProperty, textual: _textual, valueProperty, keepOpened, keepQuery, preserveOrder, ...thru }) => {
|
|
10
10
|
const textual = useMemo(() => (_textual ?? strProp)(textProperty), [_textual, textProperty]), { active, focused, onFocus, setClosed } = useFocus(thru), empty = !text, query = useMemo(() => text?.trim(), [text]), host = useHost(), onText = useNotify(host, _onText, 'text'), onChange = useCallback((val) => {
|
|
11
11
|
_onChange?.(val, () => setClosed(true));
|
|
12
12
|
notify(host, 'value', val);
|
|
13
|
-
}, [_onChange]), source$ = useMemo(() => Promise.resolve(typeof source === 'function' ? source({ query, active }) : source), [source, active, query]), value = useMemo(() => array(_value), [_value])
|
|
14
|
-
|
|
15
|
-
: [
|
|
16
|
-
...value,
|
|
17
|
-
...without(value, prop(valueProperty))(normalize(source)),
|
|
18
|
-
]), [source$, value, valueProperty]);
|
|
13
|
+
}, [_onChange]), [options, setOptions] = useState([]), source$ = useMemo(() => Promise.resolve(typeof source === 'function' ? source({ query, active }) : source).then(normalize), [source, active, query]), value = useMemo(() => array(_value), [_value]);
|
|
14
|
+
useEffect(() => source$.then(setOptions), [source$]);
|
|
19
15
|
useKeys({
|
|
20
16
|
focused,
|
|
21
17
|
empty,
|
|
22
18
|
limit,
|
|
23
19
|
value,
|
|
24
|
-
hideEmpty,
|
|
25
20
|
onChange,
|
|
26
21
|
onText,
|
|
27
22
|
});
|
|
@@ -45,15 +40,24 @@ export const useAutocomplete = ({ value: _value, text, onChange: _onChange, onTe
|
|
|
45
40
|
query,
|
|
46
41
|
textual,
|
|
47
42
|
value,
|
|
48
|
-
|
|
49
|
-
items
|
|
50
|
-
if (!active
|
|
51
|
-
return EMPTY
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}, [
|
|
43
|
+
source$,
|
|
44
|
+
items: useMemo(() => {
|
|
45
|
+
if (!active)
|
|
46
|
+
return EMPTY;
|
|
47
|
+
const items = preserveOrder
|
|
48
|
+
? options
|
|
49
|
+
: [...value, ...without(value, prop(valueProperty))(options)];
|
|
50
|
+
return search(items, query, textual);
|
|
51
|
+
}, [
|
|
52
|
+
options,
|
|
53
|
+
active,
|
|
54
|
+
query,
|
|
55
|
+
textual,
|
|
56
|
+
empty,
|
|
57
|
+
value,
|
|
58
|
+
preserveOrder,
|
|
59
|
+
valueProperty,
|
|
60
|
+
]),
|
|
57
61
|
onClick: useCallback(() => setClosed(false), []),
|
|
58
62
|
onFocus,
|
|
59
63
|
onText: useCallback((e) => {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
export interface Props<I> {
|
|
2
2
|
focused?: boolean;
|
|
3
3
|
empty?: boolean;
|
|
4
|
-
hideEmpty?: boolean;
|
|
5
4
|
value: I | I[];
|
|
6
5
|
limit?: number;
|
|
7
6
|
onChange: (v: I[]) => void;
|
|
8
7
|
onText: (s: string) => void;
|
|
9
8
|
}
|
|
10
|
-
export declare const useKeys: <I>({ focused, empty, ...
|
|
9
|
+
export declare const useKeys: <I>({ focused, empty, ...rest }: Props<I>) => void;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useEffect } from '@pionjs/pion';
|
|
2
2
|
import { array } from '@neovici/cosmoz-utils/array';
|
|
3
3
|
import { useMeta } from '@neovici/cosmoz-utils/hooks/use-meta';
|
|
4
|
-
export const useKeys = ({ focused, empty, ...
|
|
5
|
-
const enabled = focused && empty, meta = useMeta(
|
|
4
|
+
export const useKeys = ({ focused, empty, ...rest }) => {
|
|
5
|
+
const enabled = focused && empty, meta = useMeta(rest);
|
|
6
6
|
useEffect(() => {
|
|
7
7
|
if (!enabled) {
|
|
8
8
|
return;
|
|
@@ -16,12 +16,6 @@ export const useKeys = ({ focused, empty, ...info }) => {
|
|
|
16
16
|
(key === 'Backspace' || (isOne && key.length === 1))) {
|
|
17
17
|
return meta.onChange(values.slice(0, -1));
|
|
18
18
|
}
|
|
19
|
-
else if (meta.hideEmpty &&
|
|
20
|
-
values.length < 1 &&
|
|
21
|
-
['Up', 'ArrowUp', 'Down', 'ArrowDown'].includes(key)) {
|
|
22
|
-
meta.onText(' ');
|
|
23
|
-
e.preventDefault();
|
|
24
|
-
}
|
|
25
19
|
};
|
|
26
20
|
document.addEventListener('keydown', handler, true);
|
|
27
21
|
return () => document.removeEventListener('keydown', handler, true);
|
|
@@ -2,7 +2,7 @@ export declare const search: <I>(source: I[], query: string, textual: (i: I) =>
|
|
|
2
2
|
export declare const normalize: <I>(source: I[] | false | null) => I[];
|
|
3
3
|
export declare const notify: <T>(host: EventTarget, name: string, detail: T) => boolean;
|
|
4
4
|
export declare const useNotify: <V>(host: EventTarget, fn: undefined | ((v: V) => void), name: string) => (val: V) => void;
|
|
5
|
-
export declare const EMPTY: never[]
|
|
5
|
+
export declare const EMPTY: never[];
|
|
6
6
|
type Arr = unknown[];
|
|
7
7
|
type ArrFn<T extends Arr> = (...args: T) => void;
|
|
8
8
|
export declare const raf: <A extends Arr, F extends ArrFn<A> = ArrFn<A>>(fn: F) => (...args: A) => () => void;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { useCallback } from '@pionjs/pion';
|
|
2
2
|
export const search = (source, query, textual) => {
|
|
3
|
+
if (!query)
|
|
4
|
+
return source;
|
|
3
5
|
const qry = query.toLowerCase();
|
|
4
6
|
const matches = [];
|
|
5
7
|
for (const item of source) {
|
|
@@ -12,11 +14,7 @@ export const search = (source, query, textual) => {
|
|
|
12
14
|
index,
|
|
13
15
|
});
|
|
14
16
|
}
|
|
15
|
-
return matches
|
|
16
|
-
.sort((a, b) => {
|
|
17
|
-
return a.index - b.index;
|
|
18
|
-
})
|
|
19
|
-
.map(({ item }) => item);
|
|
17
|
+
return matches.sort((a, b) => a.index - b.index).map(({ item }) => item);
|
|
20
18
|
};
|
|
21
19
|
export const normalize = (source) => {
|
|
22
20
|
if (source === false || source == null)
|
|
@@ -28,7 +26,7 @@ export const useNotify = (host, fn, name) => useCallback((val) => {
|
|
|
28
26
|
fn?.(val);
|
|
29
27
|
notify(host, name, val);
|
|
30
28
|
}, [fn]);
|
|
31
|
-
export const EMPTY = []
|
|
29
|
+
export const EMPTY = [];
|
|
32
30
|
export const raf = (fn) => (...args) => {
|
|
33
31
|
let id;
|
|
34
32
|
const cleanup = () => {
|
package/dist/listbox/index.d.ts
CHANGED
package/dist/listbox/index.js
CHANGED
|
@@ -23,18 +23,19 @@ const Listbox = (props) => {
|
|
|
23
23
|
_itemSize: { height: itemHeight - 0.00001 },
|
|
24
24
|
}), [itemHeight]);
|
|
25
25
|
return html `<div
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
class="items"
|
|
27
|
+
${ref((el) => (listRef.current = el))}
|
|
28
|
+
style="min-height: ${height}px"
|
|
29
|
+
>
|
|
30
|
+
<div virtualizer-sizer></div>
|
|
31
|
+
${virtualize({
|
|
32
32
|
items,
|
|
33
33
|
renderItem,
|
|
34
34
|
scroller: true,
|
|
35
35
|
layout,
|
|
36
36
|
})}
|
|
37
|
-
|
|
37
|
+
</div>
|
|
38
|
+
<slot></slot>`;
|
|
38
39
|
};
|
|
39
40
|
const supportsPopover = () => {
|
|
40
41
|
// eslint-disable-next-line no-prototype-builtins
|
|
@@ -49,12 +50,11 @@ const showPopover = (popover) => {
|
|
|
49
50
|
}
|
|
50
51
|
};
|
|
51
52
|
customElements.define('cosmoz-listbox', component(Listbox, { styleSheets: [sheet(style)] }));
|
|
52
|
-
export const listbox = ({ multi, ...thru }) =>
|
|
53
|
-
return html `<cosmoz-listbox
|
|
53
|
+
export const listbox = ({ multi, ...thru }, content) => html `<cosmoz-listbox
|
|
54
54
|
${ref(showPopover)}
|
|
55
55
|
popover="manual"
|
|
56
56
|
part="listbox"
|
|
57
57
|
?multi=${multi}
|
|
58
58
|
...=${spreadProps(props(properties)(thru))}
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
>${content}</cosmoz-listbox
|
|
60
|
+
>`;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { html } from 'lit-html';
|
|
2
1
|
import { identity } from '@neovici/cosmoz-utils/function';
|
|
2
|
+
import { html } from 'lit-html';
|
|
3
3
|
import { mark } from './util';
|
|
4
4
|
export const itemRenderer = (render = identity) => (item, i, { highlight, select, textual = identity, query, isSelected, }) => {
|
|
5
5
|
const text = textual(item), content = mark(text, query), rendered = render(content, item, i);
|
|
@@ -16,6 +16,7 @@ const style = css `
|
|
|
16
16
|
0 1px 8px 0 rgba(0, 0, 0, 0.12),
|
|
17
17
|
0 3px 3px -2px rgba(0, 0, 0, 0.4);
|
|
18
18
|
text-transform: var(--cosmoz-autocomplete-listbox-text-transform, initial);
|
|
19
|
+
overflow: hidden;
|
|
19
20
|
}
|
|
20
21
|
:host(:popover-open) {
|
|
21
22
|
box-sizing: border-box;
|
|
@@ -30,7 +31,6 @@ const style = css `
|
|
|
30
31
|
position: relative;
|
|
31
32
|
overflow-y: auto;
|
|
32
33
|
contain: layout paint !important;
|
|
33
|
-
height: 100%;
|
|
34
34
|
}
|
|
35
35
|
.item {
|
|
36
36
|
font-size: 14px;
|
|
@@ -100,8 +100,8 @@ const style = css `
|
|
|
100
100
|
export default style;
|
|
101
101
|
export const styles = ({ index, height, itemHeight, }) => css `
|
|
102
102
|
:host {
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
xmin-height: ${itemHeight}px;
|
|
104
|
+
xheight: ${height}px;
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
.item {
|
|
@@ -5,7 +5,10 @@ export const useItems = ({ items, onSelect, defaultIndex = 0, }) => {
|
|
|
5
5
|
index: defaultIndex,
|
|
6
6
|
}), { index } = position, { length } = items;
|
|
7
7
|
useEffect(() => {
|
|
8
|
-
setPosition({
|
|
8
|
+
setPosition({
|
|
9
|
+
index: Math.min(position.index, items.length - 1),
|
|
10
|
+
scroll: true,
|
|
11
|
+
});
|
|
9
12
|
}, [items, defaultIndex]);
|
|
10
13
|
useKeyboard({
|
|
11
14
|
onUp: useCallback(() => setPosition((p) => ({
|
|
@@ -18,6 +18,7 @@ export const properties = [
|
|
|
18
18
|
'defaultIndex',
|
|
19
19
|
'value',
|
|
20
20
|
'valueProperty',
|
|
21
|
+
'loading',
|
|
21
22
|
];
|
|
22
23
|
export const useListbox = ({ value, valueProperty, items: _items, onSelect, defaultIndex, query, textual, itemRenderer, itemHeight = 40, itemLimit = 5, ...thru }) => {
|
|
23
24
|
const isSelected = useMemo(() => byValue(value, valueProperty), [value, valueProperty]),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neovici/cosmoz-autocomplete",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.1",
|
|
4
4
|
"description": "A autocomplete input web component",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"lit-html",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"@neovici/cosmoz-dropdown": "^4.4.0",
|
|
75
75
|
"@neovici/cosmoz-input": "^5.0.2",
|
|
76
76
|
"@neovici/cosmoz-utils": "^6.0.0",
|
|
77
|
-
"@pionjs/pion": "^2.
|
|
77
|
+
"@pionjs/pion": "^2.7.1",
|
|
78
78
|
"lit-html": "^2.0.0 || ^3.0.0"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|