@neovici/cosmoz-autocomplete
Advanced tools
Comparing version 3.1.1 to 3.2.0
@@ -43,3 +43,3 @@ import { tagged as css } from '@neovici/cosmoz-utils'; | ||
margin: 2px 4px 2px -6px; | ||
background-color: var(--cosmoz-autocomplete-chip-clear-bg-color, #81899B); | ||
background-color: var(--cosmoz-autocomplete-chip-clear-bg-color, #81899b); | ||
border-radius: 500px; | ||
@@ -52,3 +52,5 @@ cursor: pointer; | ||
} | ||
.chip-clear svg { | ||
.chip-clear svg, | ||
.badge-clear svg { | ||
display: block; | ||
@@ -64,8 +66,21 @@ transform: translate(3.5px, 3.5px); | ||
line-height: 22px; | ||
padding: 0 2px; | ||
padding: 0 4px 0 6px; | ||
gap: 4px; | ||
border-radius: 90px; | ||
text-align: center; | ||
box-sizing: border-box; | ||
/* fallback for unsupported min-content FF, Safari */ | ||
flex: 0.01 2 30px; | ||
flex: 0 2 min-content; | ||
display: flex; | ||
align-items: center; | ||
} | ||
.badge-clear { | ||
background-color: var(--cosmoz-autocomplete-chip-clear-bg-color, #81899b); | ||
border-radius: 500px; | ||
cursor: pointer; | ||
width: 16px; | ||
height: 16px; | ||
stroke: var(--cosmoz-autocomplete-chip-bg-color, #cbcfdb); | ||
display: block; | ||
} | ||
@@ -72,0 +87,0 @@ |
@@ -12,29 +12,71 @@ import { html, nothing } from 'lit-html'; // eslint-disable-line object-curly-newline | ||
const | ||
blank = () => nothing, | ||
const blank = () => nothing, | ||
clear = html` | ||
<svg | ||
width="9" | ||
height="8" | ||
viewBox="0 0 9 8" | ||
fill="none" | ||
xmlns="http://www.w3.org/2000/svg" | ||
> | ||
<line | ||
x1="7.53033" | ||
y1="0.994808" | ||
x2="1.16637" | ||
y2="7.35877" | ||
stroke-width="1.5" | ||
/> | ||
<line | ||
x1="7.46967" | ||
y1="7.35882" | ||
x2="1.10571" | ||
y2="0.99486" | ||
stroke-width="1.5" | ||
/> | ||
</svg> | ||
`, | ||
renderChip = (text, onClear, disabled, isOne) => html` | ||
<div class="chip" part="chip" slot="suffix" title=${ text } ?data-one=${isOne}> | ||
<span class="chip-text" part="chip-text">${ text }</span> | ||
${ !disabled && html` | ||
<span class="chip-clear" part="chip-clear" @click=${ onClear }> | ||
<svg width="9" height="8" viewBox="0 0 9 8" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||
<line x1="7.53033" y1="0.994808" x2="1.16637" y2="7.35877" stroke-width="1.5"/> | ||
<line x1="7.46967" y1="7.35882" x2="1.10571" y2="0.99486" stroke-width="1.5"/> | ||
</svg> | ||
</span>` || nothing } | ||
<div | ||
class="chip" | ||
part="chip" | ||
slot="suffix" | ||
title=${text} | ||
?data-one=${isOne} | ||
> | ||
<span class="chip-text" part="chip-text">${text}</span> | ||
${(!disabled && | ||
html` <span class="chip-clear" part="chip-clear" @click=${onClear}> | ||
${clear} | ||
</span>`) || | ||
nothing} | ||
</div> | ||
`, | ||
renderBadge = len => len > 0 ? html`<div class="badge" slot="suffix" part="badge">${ len }</div>` : nothing, | ||
renderBadge = ({ value, onDeselect }) => { | ||
const len = value?.length; | ||
return len > 0 | ||
? html`<div class="badge" slot="suffix" part="badge"> | ||
${len} | ||
<span | ||
class="badge-clear" | ||
part="chip-clear" | ||
@click=${() => onDeselect(value)} | ||
>${clear}</span | ||
> | ||
</div>` | ||
: nothing; | ||
}, | ||
renderSelection = (value, isOne, onDeselect, textual, disabled) => { | ||
if (isOne || value.length === 1) { | ||
const val = value[0]; | ||
return val ? renderChip(textual(val), () => onDeselect(val), disabled, isOne) : nothing; | ||
return val | ||
? renderChip(textual(val), () => onDeselect(val), disabled, isOne) | ||
: nothing; | ||
} | ||
return renderBadge(value.length); | ||
return renderBadge({ value, onDeselect }); | ||
}, | ||
inputParts = ['input', 'label', 'line', 'error'].map(part => `${ part }: input-${ part }`).join(), | ||
autocomplete = props => { | ||
const | ||
{ | ||
inputParts = ['input', 'label', 'line', 'error'] | ||
.map((part) => `${part}: input-${part}`) | ||
.join(), | ||
autocomplete = (props) => { | ||
const { | ||
invalid, | ||
@@ -60,44 +102,73 @@ errorMessage, | ||
host = useHost(), | ||
isOne = limit == 1, // eslint-disable-line eqeqeq | ||
isSingle = isOne && array(value)?.[0] != null, | ||
anchor = useCallback(() => host.shadowRoot.querySelector('#input'), [host, value]), | ||
suggestions = until(items$.then(items => (!isSingle || showSingle) && items.length && listbox({ | ||
...props, | ||
anchor, | ||
items, | ||
multi: !isOne, | ||
}) || nothing)); | ||
anchor = useCallback( | ||
() => host.shadowRoot.querySelector('#input'), | ||
[host, value] | ||
), | ||
suggestions = until( | ||
items$.then( | ||
(items) => | ||
((!isSingle || showSingle) && | ||
items.length && | ||
listbox({ | ||
...props, | ||
anchor, | ||
items, | ||
multi: !isOne, | ||
})) || | ||
nothing | ||
) | ||
); | ||
return html` | ||
<style>${ style }</style> | ||
return html` <style> | ||
${style} | ||
</style> | ||
<cosmoz-input | ||
id="input" part="input" | ||
.label=${ label } | ||
.placeholder=${ placeholder } | ||
?no-label-float=${ noLabelFloat } | ||
?always-float-label=${ isSingle || alwaysFloatLabel } | ||
?readonly=${ isSingle } | ||
?disabled=${ disabled } | ||
?invalid=${ until(values$.then(() => invalid, () => true), invalid) } | ||
.errorMessage=${ until(values$.then(() => errorMessage, e => e.message), errorMessage) } | ||
.value=${ live(text) } | ||
@value-changed=${ onText } | ||
@focusin=${ onFocus } @focusout=${ onFocus } | ||
@click=${ onClick } | ||
id="input" | ||
part="input" | ||
.label=${label} | ||
.placeholder=${placeholder} | ||
?no-label-float=${noLabelFloat} | ||
?always-float-label=${isSingle || alwaysFloatLabel} | ||
?readonly=${isSingle} | ||
?disabled=${disabled} | ||
?invalid=${until( | ||
values$.then( | ||
() => invalid, | ||
() => true | ||
), | ||
invalid | ||
)} | ||
.errorMessage=${until( | ||
values$.then( | ||
() => errorMessage, | ||
(e) => e.message | ||
), | ||
errorMessage | ||
)} | ||
.value=${live(text)} | ||
@value-changed=${onText} | ||
@focusin=${onFocus} | ||
@focusout=${onFocus} | ||
@click=${onClick} | ||
autocomplete="off" | ||
exportparts=${ inputParts } | ||
exportparts=${inputParts} | ||
> | ||
<slot name="prefix" slot="prefix"></slot> | ||
<slot name="suffix" slot="suffix"></slot> | ||
${ renderSelection(array(value), isOne, onDeselect, textual, disabled) } | ||
${ until(values$.then(blank, blank), html`<div slot="suffix" class="spinner"></div>`) } | ||
${renderSelection(array(value), isOne, onDeselect, textual, disabled)} | ||
${until( | ||
values$.then(blank, blank), | ||
html`<div slot="suffix" class="spinner"></div>` | ||
)} | ||
</cosmoz-input> | ||
${ suggestions }`; | ||
${suggestions}`; | ||
}, | ||
Autocomplete = props => autocomplete({ | ||
...props, | ||
...useAutocomplete(props) | ||
}), | ||
Autocomplete = (props) => | ||
autocomplete({ | ||
...props, | ||
...useAutocomplete(props), | ||
}), | ||
observedAttributes = [ | ||
@@ -116,9 +187,5 @@ 'disabled', | ||
'item-height', | ||
'item-limit' | ||
'item-limit', | ||
]; | ||
export { | ||
autocomplete, | ||
Autocomplete, | ||
observedAttributes | ||
}; | ||
export { autocomplete, Autocomplete, observedAttributes }; |
{ | ||
"name": "@neovici/cosmoz-autocomplete", | ||
"version": "3.1.1", | ||
"version": "3.2.0", | ||
"description": "A autocomplete input web component", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
23568
784