This commit is contained in:
sairaj mote 2022-08-08 00:20:10 +05:30
parent c8e5f8c4f6
commit 8107ae7999
4 changed files with 225 additions and 4 deletions

View File

@ -528,7 +528,6 @@ strip-select {
strip-option {
font-weight: 500;
--border-radius: 0.3rem;
--active-option-color: var(--accent-color);
}
sm-menu {

2
css/main.min.css vendored

File diff suppressed because one or more lines are too long

View File

@ -498,7 +498,6 @@ strip-select {
strip-option {
font-weight: 500;
--border-radius: 0.3rem;
--active-option-color: var(--accent-color);
}
sm-menu {
--background: var(--foreground-color);

View File

@ -3100,4 +3100,227 @@ customElements.define('sm-option', class extends HTMLElement {
this.setAttribute('role', 'option')
this.setAttribute('tabindex', '0')
}
})
})
const tagsInput = document.createElement('template')
tagsInput.innerHTML = `
<style>
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
:host{
--danger-color: red;
--border-radius: 0.3rem;
--background: rgba(var(--text-color,(17,17,17)), 0.06);
}
.hide{
display: none !important;
}
.tags-wrapper{
position: relative;
display: flex;
cursor: text;
flex-wrap: wrap;
justify-items: flex-start;
align-items: center;
padding: 0.5rem 0.5rem 0 0.5rem;
border-radius: var(--border-radius);
background: var(--background);
}
.tags-wrapper:focus-within{
box-shadow: 0 0 0 0.1rem var(--accent-color,teal) inset !important;
}
.tag {
overflow-wrap: anywhere;
cursor: pointer;
user-select: none;
align-items: center;
display: inline-flex;
border-radius: 0.3rem;
padding: 0.3rem 0.5rem;
margin: 0 0.5rem 0.5rem 0;
background-color: rgba(var(--text-color,(17,17,17)), 0.06);
}
.icon {
height: 1.2rem;
width: 1.2rem;
margin-left: 0.3rem;
fill: rgba(var(--text-color,(17,17,17)), 0.8);
}
input,
input:focus {
outline: none;
border: none;
}
input {
display: inline-flex;
width: auto;
color: inherit;
max-width: inherit;
font-size: inherit;
font-family: inherit;
padding: 0.4rem 0.5rem;
margin: 0 0.5rem 0.5rem 0;
background-color: transparent;
}
.placeholder{
position: absolute;
padding: 0 0.5rem;
top: 50%;
font-weight: 500;
transform: translateY(-50%);
color: rgba(var(--text-color,(17,17,17)), 0.6);
}
</style>
<div class="tags-wrapper">
<input type="text" size="3"/>
<p class="placeholder"></p>
</div>
`
customElements.define('tags-input', class extends HTMLElement {
constructor() {
super()
this.attachShadow({
mode: 'open'
}).append(tagsInput.content.cloneNode(true))
this.input = this.shadowRoot.querySelector('input')
this.tagsWrapper = this.shadowRoot.querySelector('.tags-wrapper')
this.placeholder = this.shadowRoot.querySelector('.placeholder')
this.reflectedAttributes = ['placeholder', 'limit']
this.limit = undefined
this.tags = new Set()
this.reset = this.reset.bind(this)
this.handleInput = this.handleInput.bind(this)
this.addTag = this.addTag.bind(this)
this.handleKeydown = this.handleKeydown.bind(this)
this.handleClick = this.handleClick.bind(this)
this.removeTag = this.removeTag.bind(this)
}
static get observedAttributes() {
return ['placeholder', 'limit']
}
get value() {
return [...this.tags].filter(v => v !== undefined)
}
set value(arr) {
this.reset();
[...new Set(arr.filter(v => v !== undefined))].forEach(tag => this.addTag(tag))
}
get isValid() {
return this.tags.size
}
focusIn() {
this.input.focus()
}
reset() {
this.input.value = ''
this.tags.clear()
while (this.input.previousElementSibling) {
this.input.previousElementSibling.remove()
}
}
addTag(tagValue) {
const tag = document.createElement('span')
tag.dataset.value = tagValue
tag.className = 'tag'
tag.innerHTML = `
<span class="tag-text">${tagValue}</span>
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z"/></svg>
`
this.input.before(tag)
this.tags.add(tagValue)
}
handleInput(e) {
const inputValueLength = e.target.value.trim().length
e.target.setAttribute('size', inputValueLength ? inputValueLength : '3')
if (inputValueLength) {
this.placeholder.classList.add('hide')
}
else if (!inputValueLength && !this.tags.size) {
this.placeholder.classList.remove('hide')
}
}
handleKeydown(e) {
if (e.key === ',' || e.key === '/') {
e.preventDefault()
}
if (e.target.value.trim() !== '') {
if (e.key === 'Enter' || e.key === ',' || e.key === '/') {
const tagValue = e.target.value.trim()
if (this.tags.has(tagValue)) {
this.tagsWrapper.querySelector(`[data-value="${tagValue}"]`).animate([
{
backgroundColor: 'initial'
},
{
backgroundColor: 'var(--accent-color,teal)'
},
{
backgroundColor: 'initial'
},
], {
duration: 300,
easing: 'ease'
})
} else {
this.addTag(tagValue)
}
e.target.value = ''
e.target.setAttribute('size', '3')
if (this.limit && this.limit < this.tags.size + 1) {
this.input.readOnly = true
return
}
}
}
else {
if (e.key === 'Backspace' && this.input.previousElementSibling) {
this.removeTag(this.input.previousElementSibling)
}
if (this.limit && this.limit > this.tags.size) {
this.input.readOnly = false
}
}
}
handleClick(e) {
if (e.target.closest('.tag')) {
this.removeTag(e.target.closest('.tag'))
}
else {
this.input.focus()
}
}
removeTag(tag) {
this.tags.delete(tag.dataset.value)
tag.remove()
if (!this.tags.size) {
this.placeholder.classList.remove('hide')
}
}
connectedCallback() {
this.input.addEventListener('input', this.handleInput)
this.input.addEventListener('keydown', this.handleKeydown)
this.tagsWrapper.addEventListener('click', this.handleClick)
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'placeholder') {
this.placeholder.textContent = newValue
}
if (name === 'limit') {
this.limit = parseInt(newValue)
}
}
disconnectedCallback() {
this.input.removeEventListener('input', this.handleInput)
this.input.removeEventListener('keydown', this.handleKeydown)
this.tagsWrapper.removeEventListener('click', this.handleClick)
}
})