@neovici/cosmoz-autocomplete 5.3.2 → 6.1.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.
Files changed (43) hide show
  1. package/dist/autocomplete/autocomplete.d.ts +16 -0
  2. package/dist/autocomplete/autocomplete.js +79 -0
  3. package/dist/autocomplete/index.d.ts +1 -0
  4. package/dist/autocomplete/index.js +19 -0
  5. package/dist/autocomplete/selection.d.ts +11 -0
  6. package/dist/autocomplete/selection.js +58 -0
  7. package/dist/autocomplete/styles.css.d.ts +2 -0
  8. package/{lib/autocomplete.css.js → dist/autocomplete/styles.css.js} +1 -2
  9. package/dist/autocomplete/use-autocomplete.d.ts +41 -0
  10. package/dist/autocomplete/use-autocomplete.js +74 -0
  11. package/dist/autocomplete/use-keys.d.ts +10 -0
  12. package/dist/autocomplete/use-keys.js +29 -0
  13. package/dist/autocomplete/util.d.ts +4 -0
  14. package/dist/autocomplete/util.js +25 -0
  15. package/dist/index.d.ts +1 -0
  16. package/dist/index.js +1 -0
  17. package/dist/listbox/index.d.ts +20 -0
  18. package/dist/listbox/index.js +41 -0
  19. package/dist/listbox/item-renderer.d.ts +25 -0
  20. package/dist/listbox/item-renderer.js +21 -0
  21. package/dist/listbox/style.css.d.ts +7 -0
  22. package/dist/listbox/style.css.js +104 -0
  23. package/dist/listbox/use-items.d.ts +14 -0
  24. package/dist/listbox/use-items.js +26 -0
  25. package/dist/listbox/use-keyboard.d.ts +8 -0
  26. package/dist/listbox/use-keyboard.js +32 -0
  27. package/dist/listbox/use-listbox.d.ts +28 -0
  28. package/dist/listbox/use-listbox.js +54 -0
  29. package/dist/listbox/use-render-item.d.ts +5 -0
  30. package/dist/listbox/use-render-item.js +7 -0
  31. package/dist/listbox/util.d.ts +2 -0
  32. package/dist/listbox/util.js +24 -0
  33. package/package.json +16 -12
  34. package/cosmoz-autocomplete.js +0 -21
  35. package/cosmoz-listbox.js +0 -145
  36. package/lib/autocomplete.js +0 -190
  37. package/lib/item-renderer.js +0 -26
  38. package/lib/on-scrolled.js +0 -37
  39. package/lib/use-autocomplete.js +0 -102
  40. package/lib/use-keyboard.js +0 -35
  41. package/lib/use-keys.js +0 -39
  42. package/lib/use-listbox.js +0 -123
  43. package/lib/utils.js +0 -62
@@ -1,102 +0,0 @@
1
- import {
2
- useCallback, useMemo
3
- } from 'haunted';
4
- import {
5
- without, search, strProp, prop, array
6
- } from './utils';
7
- import { useHost } from '@neovici/cosmoz-utils/hooks/use-host';
8
- import { useMeta } from '@neovici/cosmoz-utils/hooks/use-meta';
9
- import { useFocus } from '@neovici/cosmoz-dropdown/src/use-focus.js';
10
- import { useKeys } from './use-keys';
11
-
12
- const
13
- EMPTY = [],
14
- EMPTY$ = Promise.resolve(EMPTY),
15
- notify = (host, name, detail) => host.dispatchEvent(new CustomEvent(name, { detail })),
16
- useNotify = (host, fn, name) => useCallback(val => {
17
- fn?.(val);
18
- notify(host, name, val);
19
- }, [fn]),
20
- useAutocomplete = ({
21
- value,
22
- text,
23
- onChange: _onChange,
24
- onText: _onText,
25
- onSelect,
26
- limit,
27
- source,
28
- textProperty,
29
- valueProperty,
30
- external,
31
- hideEmpty,
32
- keepQuery,
33
- keepOpened,
34
- ...thru
35
- }) => {
36
- const
37
- textual = useMemo(() => strProp(textProperty), [textProperty]),
38
- { active, onFocus, setClosed } = useFocus(thru),
39
- empty = !text,
40
- query = useMemo(() => text?.trim().toLowerCase(), [text]),
41
- host = useHost(),
42
- onText = useNotify(host, _onText, 'text'),
43
- onChange = useCallback(val => {
44
- _onChange?.(val, () => setClosed(true));
45
- notify(host, 'value', val);
46
- }, [_onChange]),
47
- source$ = useMemo(() => Promise.resolve(typeof source === 'function'
48
- ? source({ query, active })
49
- : source
50
- ), [source, active, query]),
51
- values$ = useMemo(() => source$.then(source => [...array(value), ...without(value, prop(valueProperty))(source)]), [source$, value, valueProperty]);
52
-
53
- useKeys({
54
- active,
55
- empty,
56
- limit,
57
- value,
58
- hideEmpty,
59
- onChange,
60
- onText
61
- });
62
-
63
- const meta = useMeta({ onText, onChange, value, limit, keepQuery, keepOpened, setClosed, onSelect });
64
-
65
- return {
66
- query,
67
- textual,
68
- values$,
69
- items$: useMemo(() => {
70
- if (!active || hideEmpty && empty) {
71
- return EMPTY$;
72
- }
73
- return query && !external
74
- ? values$.then(values => search(values, query, textual))
75
- : values$;
76
- }, [values$, active, query, textual, external, hideEmpty, empty]),
77
- onClick: useCallback(() => setClosed(false), []),
78
- onFocus,
79
- onText: useCallback(e => {
80
- onText(e.target.value);
81
- setClosed(false);
82
- }, [onText, text, setClosed]),
83
- onSelect: useCallback(newVal => {
84
- const { onSelect} = meta;
85
- if(onSelect) {
86
- return onSelect(newVal, meta);
87
- }
88
- const { onChange, onText, limit, value: val, keepQuery, keepOpened, setClosed } = meta;
89
- if (!keepQuery) {
90
- onText('');
91
- }
92
- if (!keepOpened) {
93
- setClosed(true);
94
- }
95
- const value = array(val);
96
- onChange((value.includes(newVal) ? without(newVal)(value) : [...value, newVal]).slice(-limit));
97
- }, [meta]),
98
- onDeselect: useCallback(val => meta.onChange(without(val)(meta.value)), [meta])
99
- };
100
- };
101
-
102
- export { useAutocomplete };
@@ -1,35 +0,0 @@
1
- import { useEffect } from 'haunted';
2
- import { useMeta } from '@neovici/cosmoz-utils/hooks/use-meta';
3
-
4
- export const useKeyboard = handlers => {
5
- const listeners = useMeta(handlers);
6
-
7
- useEffect(() => {
8
- const handler = e => {
9
- if (e.ctrlKey && e.altKey || e.defaultPrevented) {
10
- return;
11
- }
12
- switch (e.key) {
13
- case 'Up':
14
- case 'ArrowUp':
15
- e.preventDefault();
16
- listeners.onUp();
17
- break;
18
- case 'Down':
19
- case 'ArrowDown':
20
- e.preventDefault();
21
- listeners.onDown();
22
- break;
23
- case 'Enter':
24
- e.preventDefault();
25
- listeners.onEnter();
26
- break;
27
- default:
28
- break;
29
- }
30
- };
31
-
32
- document.addEventListener('keydown', handler, true);
33
- return () => document.removeEventListener('keydown', handler, true);
34
- }, [listeners]);
35
- };
package/lib/use-keys.js DELETED
@@ -1,39 +0,0 @@
1
- import { useEffect } from 'haunted';
2
- import { array } from './utils';
3
- import { useMeta } from '@neovici/cosmoz-utils/hooks/use-meta';
4
-
5
- const useKeys = ({
6
- active,
7
- empty,
8
- ...info
9
- }) => {
10
- const enabled = active && empty,
11
- meta = useMeta(info);
12
- useEffect(() => {
13
- if (!enabled) {
14
- return;
15
- }
16
- const handler = e => {
17
- if (e.defaultPrevented) {
18
- return;
19
- }
20
- const { key } = e,
21
- values = array(meta.value),
22
- isOne = meta.limit == 1; //eslint-disable-line eqeqeq
23
-
24
- if (values.length > 0 && (key === 'Backspace' || isOne && key.length === 1)) {
25
- return meta.onChange(values.slice(0, -1));
26
- } else if (meta.hideEmpty && values.length < 1 && ['Up', 'ArrowUp', 'Down', 'ArrowDown'].includes(key)) {
27
- meta.onText(' ');
28
- e.preventDefault();
29
- }
30
- };
31
-
32
- document.addEventListener('keydown', handler, true);
33
- return () => document.removeEventListener('keydown', handler, true);
34
-
35
- }, [enabled, meta]);
36
- };
37
-
38
- export { useKeys };
39
-
@@ -1,123 +0,0 @@
1
- import { useCallback, useEffect, useState, useMemo } from 'haunted';
2
- import { useMeta } from '@neovici/cosmoz-utils/hooks/use-meta';
3
- import { usePosition } from '@neovici/cosmoz-dropdown/src/use-position.js';
4
- import { useKeyboard } from './use-keyboard';
5
- import defaultItemRenderer from './item-renderer';
6
- import { byValue } from './utils';
7
-
8
- const useItems = ({ items, onSelect, defaultIndex = 0 }) => {
9
- const [position, setPosition] = useState({
10
- index: defaultIndex,
11
- }),
12
- { index } = position,
13
- { length } = items;
14
-
15
- useEffect(() => {
16
- setPosition({ index: defaultIndex, scroll: true });
17
- }, [items, defaultIndex]);
18
-
19
- useKeyboard({
20
- onUp: useCallback(
21
- () =>
22
- setPosition(({ index }) => ({
23
- index: index > 0 ? index - 1 : length - 1,
24
- scroll: true,
25
- })),
26
- [length]
27
- ),
28
- onDown: useCallback(
29
- () =>
30
- setPosition(({ index }) => ({
31
- index: index < length - 1 ? index + 1 : 0,
32
- scroll: true,
33
- })),
34
- [length]
35
- ),
36
- onEnter: useCallback(
37
- () => index > -1 && index < length && onSelect?.(items[index], index),
38
- [index, items, onSelect]
39
- ),
40
- });
41
-
42
- return {
43
- position,
44
- highlight: useCallback((index) => setPosition({ index }), []),
45
- select: useCallback((item) => onSelect?.(item), [onSelect]),
46
- };
47
- },
48
- useRenderItem = ({ itemRenderer, ...meta }) => {
49
- const info = useMeta(meta);
50
- return useCallback(
51
- (item, i) => (itemRenderer || defaultItemRenderer)(item, i, info),
52
- [info, itemRenderer]
53
- );
54
- },
55
- useListbox = (host) => {
56
- const {
57
- value,
58
- valueProperty,
59
- items: _items,
60
- onSelect,
61
- defaultIndex,
62
- query,
63
- textual,
64
- itemRenderer,
65
- itemHeight = 40,
66
- itemLimit = 5,
67
- anchor,
68
- confinement,
69
- placement,
70
- } = host,
71
- isSelected = useMemo(
72
- () => byValue(value, valueProperty),
73
- [value, valueProperty]
74
- ),
75
- items = useMemo(() => _items.slice(), [_items, isSelected]),
76
- { position, highlight, select } = useItems({
77
- items,
78
- onSelect,
79
- defaultIndex: isNaN(defaultIndex) ? undefined : Number(defaultIndex),
80
- });
81
-
82
- usePosition({
83
- anchor,
84
- host,
85
- confinement,
86
- placement,
87
- limit: true,
88
- });
89
-
90
- return {
91
- position,
92
- items,
93
- height: Math.min(itemLimit, items.length) * itemHeight,
94
- highlight,
95
- select,
96
- itemHeight,
97
- renderItem: useRenderItem({
98
- itemRenderer,
99
- highlight,
100
- select,
101
- textual,
102
- query,
103
- isSelected,
104
- }),
105
- };
106
- },
107
- properties = [
108
- 'query',
109
- 'items',
110
- 'onSelect',
111
- 'textual',
112
- 'anchor',
113
- 'confinement',
114
- 'placement',
115
- 'itemHeight',
116
- 'itemLimit',
117
- 'itemRenderer',
118
- 'defaultIndex',
119
- 'value',
120
- 'styles',
121
- ];
122
-
123
- export { useListbox, useRenderItem, properties };
package/lib/utils.js DELETED
@@ -1,62 +0,0 @@
1
- import { html } from 'lit-html';
2
-
3
- import { identity } from '@neovici/cosmoz-utils/function';
4
- import { array, without } from '@neovici/cosmoz-utils/array';
5
- import { prop, strProp } from '@neovici/cosmoz-utils/object';
6
-
7
- const mark = (text, query) => {
8
- if (!query || !text) {
9
- return text;
10
- }
11
- const i = text.toLowerCase().indexOf(query.toLowerCase());
12
- if (i < 0) {
13
- return text;
14
- }
15
- const end = i + query.length;
16
- return [
17
- text.slice(0, i),
18
- html`<mark>${ text.slice(i, end) }</mark>`,
19
- text.slice(end)
20
- ];
21
- },
22
- search = (source, query, textual) => {
23
- const matches = [];
24
- for (const item of source) {
25
- const index = textual(item).toLowerCase().indexOf(query);
26
- if (index < 0) {
27
- continue;
28
- }
29
- matches.push({
30
- item,
31
- index
32
- });
33
- }
34
- return matches
35
- .sort((a, b) => {
36
- return a.index - b.index;
37
- })
38
- .map(({ item }) => item);
39
- },
40
- scrollIntoViewIfNeeded = (el, parent) => {
41
- if (el == null) {
42
- return;
43
- }
44
- if (el.scrollIntoViewIfNeeded) {
45
- el.scrollIntoViewIfNeeded();
46
- return;
47
- }
48
- const ebox = el.getBoundingClientRect(),
49
- pbox = parent.getBoundingClientRect();
50
- if (ebox.top >= pbox.top && ebox.top + ebox.height < pbox.top + pbox.height) {
51
- return;
52
- }
53
- el.scrollIntoView();
54
- },
55
- byValue = (value, valueProperty) => {
56
- const valuation = prop(valueProperty);
57
- return item => array(value).find(value => valuation(value) === valuation(item));
58
- };
59
-
60
- export {
61
- array, identity, mark, prop, search, without, strProp, scrollIntoViewIfNeeded, byValue
62
- };