const smChips = document.createElement('template');
smChips.innerHTML = `
`;
customElements.define('sm-chips', class extends HTMLElement {
constructor() {
super();
this.attachShadow({
mode: 'open'
}).append(smChips.content.cloneNode(true));
this.chipsWrapper = this.shadowRoot.querySelector('.sm-chips');
this.coverLeft = this.shadowRoot.querySelector('.cover--left');
this.coverRight = this.shadowRoot.querySelector('.cover--right');
this.navButtonLeft = this.shadowRoot.querySelector('.nav-button--left');
this.navButtonRight = this.shadowRoot.querySelector('.nav-button--right');
this.slottedOptions = undefined;
this._value = undefined;
this.scrollDistance = 0;
this.assignedElements = [];
this.scrollLeft = this.scrollLeft.bind(this);
this.scrollRight = this.scrollRight.bind(this);
this.fireEvent = this.fireEvent.bind(this);
this.setSelectedOption = this.setSelectedOption.bind(this);
}
get value() {
return this._value;
}
set value(val) {
this.setSelectedOption(val);
}
scrollLeft() {
this.chipsWrapper.scrollBy({
left: -this.scrollDistance,
behavior: 'smooth'
});
}
scrollRight() {
this.chipsWrapper.scrollBy({
left: this.scrollDistance,
behavior: 'smooth'
});
}
setSelectedOption(value) {
if (this._value === value) return
this._value = value;
this.assignedElements.forEach(elem => {
if (elem.value == value) {
elem.setAttribute('selected', '');
elem.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "center" });
}
else
elem.removeAttribute('selected')
});
}
fireEvent() {
this.dispatchEvent(
new CustomEvent("change", {
bubbles: true,
composed: true,
detail: {
value: this._value
}
})
);
}
connectedCallback() {
this.setAttribute('role', 'listbox');
const slot = this.shadowRoot.querySelector('slot');
slot.addEventListener('slotchange', e => {
firstOptionObserver.disconnect();
lastOptionObserver.disconnect();
this.observeSelf.disconnect();
// debounce to wait for all elements to be assigned
clearTimeout(this.slotChangeTimeout);
this.slotChangeTimeout = setTimeout(() => {
this.assignedElements = slot.assignedElements();
this.assignedElements.forEach(elem => {
if (elem.hasAttribute('selected')) {
this._value = elem.value;
}
});
this.observeSelf.observe(this);
}, 0);
});
const resObs = new ResizeObserver(entries => {
entries.forEach(entry => {
if (entry.contentBoxSize) {
// Firefox implements `contentBoxSize` as a single content rect, rather than an array
const contentBoxSize = Array.isArray(entry.contentBoxSize) ? entry.contentBoxSize[0] : entry.contentBoxSize;
this.scrollDistance = contentBoxSize.inlineSize * 0.6;
} else {
this.scrollDistance = entry.contentRect.width * 0.6;
}
});
});
resObs.observe(this);
this.observeSelf = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting && !this.hasAttribute('multiline') && this.assignedElements.length > 0) {
firstOptionObserver.observe(this.assignedElements[0]);
lastOptionObserver.observe(this.assignedElements[this.assignedElements.length - 1]);
observer.unobserve(this);
}
});
}, {
threshold: 1,
});
this.chipsWrapper.addEventListener('option-clicked', e => {
if (this._value !== e.target.value) {
this.setSelectedOption(e.target.value);
this.fireEvent();
}
});
const firstOptionObserver = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
this.navButtonLeft.classList.add('hide');
this.coverLeft.classList.add('hide');
} else {
this.navButtonLeft.classList.remove('hide');
this.coverLeft.classList.remove('hide');
}
});
},
{
threshold: 1,
root: this
});
const lastOptionObserver = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
this.navButtonRight.classList.add('hide');
this.coverRight.classList.add('hide');
} else {
this.navButtonRight.classList.remove('hide');
this.coverRight.classList.remove('hide');
}
});
},
{
threshold: 1,
root: this
});
this.navButtonLeft.addEventListener('click', this.scrollLeft);
this.navButtonRight.addEventListener('click', this.scrollRight);
}
disconnectedCallback() {
this.navButtonLeft.removeEventListener('click', this.scrollLeft);
this.navButtonRight.removeEventListener('click', this.scrollRight);
}
});
const smChip = document.createElement('template');
smChip.innerHTML = `
`;
customElements.define('sm-chip', class extends HTMLElement {
constructor() {
super();
this.attachShadow({
mode: 'open'
}).append(smChip.content.cloneNode(true));
this._value = undefined;
this.radioButton = this.shadowRoot.querySelector('input');
this.fireEvent = this.fireEvent.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
}
get value() {
return this._value;
}
fireEvent() {
this.dispatchEvent(
new CustomEvent("option-clicked", {
bubbles: true,
composed: true,
detail: {
value: this._value
}
})
);
}
handleKeyDown(e) {
if (e.key === 'Enter' || e.key === 'Space') {
this.fireEvent();
}
}
connectedCallback() {
this.setAttribute('role', 'option');
this.setAttribute('tabindex', '0');
this._value = this.getAttribute('value');
this.addEventListener('click', this.fireEvent);
this.addEventListener('keydown', this.handleKeyDown);
}
disconnectedCallback() {
this.removeEventListener('click', this.fireEvent);
this.removeEventListener('keydown', this.handleKeyDown);
}
});