@neovici/cosmoz-autocomplete 5.0.0 → 5.1.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/cosmoz-listbox.js CHANGED
@@ -42,7 +42,7 @@ const svg =
42
42
  color: var(--cosmoz-listbox-color, #101010);
43
43
  }
44
44
 
45
- .item[data-index="${index || '0'}"] {
45
+ .item[data-index='${index || '0'}'] {
46
46
  background: var(
47
47
  --cosmoz-listbox-active-color,
48
48
  var(--cosmoz-selection-color, rgba(58, 145, 226, 0.1))
@@ -87,6 +87,15 @@ const svg =
87
87
  :host([multi]) .sizer {
88
88
  padding-left: 33px;
89
89
  }
90
+ .swatch {
91
+ width: 18px;
92
+ height: 18px;
93
+ display: inline-block;
94
+ box-sizing: border-box;
95
+ vertical-align: middle;
96
+ border-radius: 50%;
97
+ border: 2px solid #eee;
98
+ }
90
99
  `,
91
100
  Listbox = (host) => {
92
101
  const { index, items, renderItem, height, itemHeight } = useListbox(host);
@@ -1,6 +1,7 @@
1
1
  import { html, nothing } from 'lit-html'; // eslint-disable-line object-curly-newline
2
2
  import { live } from 'lit-html/directives/live.js';
3
3
  import { until } from 'lit-html/directives/until.js';
4
+ import { when } from 'lit-html/directives/when.js';
4
5
  import { useCallback } from 'haunted';
5
6
  import { useHost } from '@neovici/cosmoz-utils/hooks/use-host';
6
7
  import { array } from '@neovici/cosmoz-utils/array';
@@ -43,33 +44,36 @@ const blank = () => nothing,
43
44
  ?data-one=${isOne}
44
45
  >
45
46
  <span class="chip-text" part="chip-text">${text}</span>
46
- ${(!disabled &&
47
- html` <span class="chip-clear" part="chip-clear" @click=${onClear}>
48
- ${clear}
49
- </span>`) ||
50
- nothing}
47
+ ${when(
48
+ !disabled,
49
+ () =>
50
+ html` <span class="chip-clear" part="chip-clear" @click=${onClear}>
51
+ ${clear}
52
+ </span>`
53
+ )}
51
54
  </div>
52
55
  `,
53
56
  renderBadge = ({ value, onDeselect }) => {
54
57
  const len = value?.length;
55
- return len > 0
56
- ? html`<div class="badge" slot="suffix" part="badge">
57
- ${len}
58
- <span
59
- class="badge-clear"
60
- part="chip-clear"
61
- @click=${() => onDeselect(value)}
62
- >${clear}</span
63
- >
64
- </div>`
65
- : nothing;
58
+ return when(
59
+ len > 0,
60
+ () => html`<div class="badge" slot="suffix" part="badge">
61
+ ${len}
62
+ <span
63
+ class="badge-clear"
64
+ part="chip-clear"
65
+ @click=${() => onDeselect(value)}
66
+ >${clear}</span
67
+ >
68
+ </div>`
69
+ );
66
70
  },
67
71
  renderSelection = (value, isOne, onDeselect, textual, disabled) => {
68
72
  if (isOne || value.length === 1) {
69
73
  const val = value[0];
70
- return val
71
- ? renderChip(textual(val), () => onDeselect(val), disabled, isOne)
72
- : nothing;
74
+ return when(val, () =>
75
+ renderChip(textual(val), () => onDeselect(val), disabled, isOne)
76
+ );
73
77
  }
74
78
  return renderBadge({ value, onDeselect });
75
79
  },
@@ -105,17 +109,15 @@ const blank = () => nothing,
105
109
  [host, value]
106
110
  ),
107
111
  suggestions = until(
108
- items$.then(
109
- (items) =>
110
- ((!isSingle || showSingle) &&
111
- items.length &&
112
- listbox({
113
- ...props,
114
- anchor,
115
- items,
116
- multi: !isOne,
117
- })) ||
118
- nothing
112
+ items$.then((items) =>
113
+ when((!isSingle || showSingle) && items.length, () =>
114
+ listbox({
115
+ ...props,
116
+ anchor,
117
+ items,
118
+ multi: !isOne,
119
+ })
120
+ )
119
121
  )
120
122
  );
121
123
 
@@ -1,27 +1,25 @@
1
1
  import { html } from 'haunted';
2
2
  import { mark, identity } from './utils';
3
- export default (
4
- item,
5
- i,
6
- {
7
- highlight,
8
- select,
9
- textual = identity,
10
- query,
11
- isSelected
12
- }
13
- ) => {
14
- const text = textual(item),
15
- content = mark(text, query);
3
+ export const itemRenderer =
4
+ (render = identity) =>
5
+ (item, i, { highlight, select, textual = identity, query, isSelected }) => {
6
+ const text = textual(item),
7
+ content = mark(text, query);
16
8
 
17
- return html`
18
- <div class="item"
19
- role="option" part="option" ?aria-selected=${ isSelected(item) }
20
- data-index=${ i }
21
- @mouseenter=${ () => highlight(i) }
22
- @click=${ () => select(item) }
23
- @mousedown=${ e => e.preventDefault() }
24
- title=${ text }
25
- >${ content }</div>
26
- <div class="sizer" virtualizer-sizer>${ content }</div>`;
27
- };
9
+ return html` <div
10
+ class="item"
11
+ role="option"
12
+ part="option"
13
+ ?aria-selected=${isSelected(item)}
14
+ data-index=${i}
15
+ @mouseenter=${() => highlight(i)}
16
+ @click=${() => select(item)}
17
+ @mousedown=${(e) => e.preventDefault()}
18
+ title=${text}
19
+ >
20
+ ${render(content, item, i)}
21
+ </div>
22
+ <div class="sizer" virtualizer-sizer>${content}</div>`;
23
+ };
24
+
25
+ export default itemRenderer();
@@ -30,6 +30,7 @@ const
30
30
  external,
31
31
  hideEmpty,
32
32
  keepQuery,
33
+ keepOpened,
33
34
  ...thru
34
35
  }) => {
35
36
  const
@@ -59,7 +60,7 @@ const
59
60
  onText
60
61
  });
61
62
 
62
- const meta = useMeta({ onText, onChange, value, limit, keepQuery, setClosed, onSelect });
63
+ const meta = useMeta({ onText, onChange, value, limit, keepQuery, keepOpened, setClosed, onSelect });
63
64
 
64
65
  return {
65
66
  query,
@@ -5,11 +5,7 @@ import { useKeyboard } from './use-keyboard';
5
5
  import defaultItemRenderer from './item-renderer';
6
6
  import { byValue } from './utils';
7
7
 
8
- const useItems = ({
9
- items,
10
- onSelect,
11
- defaultIndex = 0
12
- }) => {
8
+ const useItems = ({ items, onSelect, defaultIndex = 0 }) => {
13
9
  const [index, setIndex] = useState(defaultIndex),
14
10
  { length } = items;
15
11
 
@@ -18,29 +14,34 @@ const useItems = ({
18
14
  }, [items, defaultIndex]);
19
15
 
20
16
  useKeyboard({
21
- onUp: useCallback(() => setIndex(index => index > 0 ? index - 1 : length - 1), [length]),
22
- onDown: useCallback(() => setIndex(index => index < length - 1 ? index + 1 : 0), [length]),
23
- onEnter: useCallback(() => index > -1 && index < length && onSelect?.(items[index], index), [
24
- index,
25
- items,
26
- onSelect
27
- ])
17
+ onUp: useCallback(
18
+ () => setIndex((index) => (index > 0 ? index - 1 : length - 1)),
19
+ [length]
20
+ ),
21
+ onDown: useCallback(
22
+ () => setIndex((index) => (index < length - 1 ? index + 1 : 0)),
23
+ [length]
24
+ ),
25
+ onEnter: useCallback(
26
+ () => index > -1 && index < length && onSelect?.(items[index], index),
27
+ [index, items, onSelect]
28
+ ),
28
29
  });
29
30
 
30
31
  return {
31
32
  index,
32
33
  highlight: setIndex,
33
- select: useCallback(item => onSelect?.(item), [onSelect])
34
+ select: useCallback((item) => onSelect?.(item), [onSelect]),
34
35
  };
35
36
  },
36
-
37
- useRenderItem = ({ itemRenderer = defaultItemRenderer, ...meta }) => {
37
+ useRenderItem = ({ itemRenderer, ...meta }) => {
38
38
  const info = useMeta(meta);
39
- return useCallback((item, i) => itemRenderer(item, i, info), [info, itemRenderer]);
39
+ return useCallback(
40
+ (item, i) => (itemRenderer || defaultItemRenderer)(item, i, info),
41
+ [info, itemRenderer]
42
+ );
40
43
  },
41
-
42
-
43
- useListbox = host => {
44
+ useListbox = (host) => {
44
45
  const {
45
46
  value,
46
47
  valueProperty,
@@ -54,18 +55,17 @@ const useItems = ({
54
55
  itemLimit = 5,
55
56
  anchor,
56
57
  confinement,
57
- placement
58
+ placement,
58
59
  } = host,
59
- isSelected = useMemo(() => byValue(value, valueProperty), [value, valueProperty]),
60
+ isSelected = useMemo(
61
+ () => byValue(value, valueProperty),
62
+ [value, valueProperty]
63
+ ),
60
64
  items = useMemo(() => _items.slice(), [_items, isSelected]),
61
- {
62
- index,
63
- highlight,
64
- select
65
- } = useItems({
65
+ { index, highlight, select } = useItems({
66
66
  items,
67
67
  onSelect,
68
- defaultIndex: isNaN(defaultIndex) ? undefined : Number(defaultIndex)
68
+ defaultIndex: isNaN(defaultIndex) ? undefined : Number(defaultIndex),
69
69
  });
70
70
 
71
71
  usePosition({
@@ -73,7 +73,7 @@ const useItems = ({
73
73
  host,
74
74
  confinement,
75
75
  placement,
76
- limit: true
76
+ limit: true,
77
77
  });
78
78
 
79
79
  return {
@@ -89,14 +89,24 @@ const useItems = ({
89
89
  select,
90
90
  textual,
91
91
  query,
92
- isSelected
93
- })
92
+ isSelected,
93
+ }),
94
94
  };
95
95
  },
96
- properties = ['query', 'items', 'onSelect', 'textual', 'anchor', 'confinement', 'placement', 'itemHeight', 'itemLimit', 'defaultIndex', 'value', 'styles'];
96
+ properties = [
97
+ 'query',
98
+ 'items',
99
+ 'onSelect',
100
+ 'textual',
101
+ 'anchor',
102
+ 'confinement',
103
+ 'placement',
104
+ 'itemHeight',
105
+ 'itemLimit',
106
+ 'itemRenderer',
107
+ 'defaultIndex',
108
+ 'value',
109
+ 'styles',
110
+ ];
97
111
 
98
- export {
99
- useListbox,
100
- useRenderItem,
101
- properties
102
- };
112
+ export { useListbox, useRenderItem, properties };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neovici/cosmoz-autocomplete",
3
- "version": "5.0.0",
3
+ "version": "5.1.1",
4
4
  "description": "A autocomplete input web component",
5
5
  "keywords": [
6
6
  "lit-html",
@@ -81,7 +81,7 @@
81
81
  "@web/dev-server-storybook": "^0.5.1",
82
82
  "husky": "^8.0.0",
83
83
  "semantic-release": "^19.0.0",
84
- "sinon": "^14.0.0",
84
+ "sinon": "^15.0.0",
85
85
  "typescript": "^4.6.0"
86
86
  }
87
87
  }