class AIChatButton extends HTMLElement {
#root = null;
#dialog = null;
constructor() {
super();
this.#root = this.attachShadow({mode: 'open'});
this.#root.innerHTML = `
`;
this.#root.appendChild(this.getStyle());
this.#dialog = this.#root.querySelector('dialog');
const toggleButtons = this.#root.querySelectorAll('button.toggle');
toggleButtons.forEach(function (button) {
button.addEventListener('click', this.toggleDialog.bind(this))
}.bind(this));
this.#dialog.querySelector('button.fs').addEventListener('click', function() {
this.#dialog.classList.toggle('fullscreen');
}.bind(this));
}
/**
* Called when the DOM has been connected
*
* We initialize the attribute based states here
*/
connectedCallback() {
this.#root.querySelector('button.start').title = this.getAttribute('label') || 'AI Chat';
this.#dialog.querySelector('header h1').textContent = this.getAttribute('label') || 'AI Chat';
// make title attributes translatable
for (const elem of this.#root.querySelectorAll('[title]')) {
elem.title = this.getAttribute('title-'+elem.title) || elem.title;
}
this.#root.querySelector('button.start').animate({
opacity: [0, 0.5, 1],
transform: ['scale(0.5)', 'scale(1.1)', 'scale(1)'],
easing: ["ease-in", "ease-out"],
}, 1000);
}
/**
* Define the web component's internal styles
*
* @returns {HTMLStyleElement}
*/
getStyle() {
const style = document.createElement('style');
style.textContent = `
:host {
--color-chat-icon: #4881bf;
--color-link: #4881bf;
--icon-size: 2em;
}
button {
background: none;
border: none;
cursor: pointer;
}
:host > button svg {
fill: var(--color-chat-icon);
filter: drop-shadow(0.2em 0.2em 0.2em rgb(0 0 0 / 0.4));
}
svg {
width: 2em;
height: 2em;
}
button.start svg {
width: var(--icon-size);
height: var(--icon-size);
}
dialog {
width: 500px;
max-width: 90vw;
height: 800px;
max-height: 90vh;
position: fixed;
top: 1em;
right: 1em;
left: auto;
z-index: 9999;
padding: 0.5em;
box-shadow: 0 0.2em 0.2em rgb(0 0 0 / 0.4);
border-radius: 8px;
border: 1px solid #fff;
}
dialog.fullscreen {
width: 100%;
height: 100%;
left: 1em;
right: 1em;
}
dialog > div {
display: flex;
flex-direction: column;
height: 100%;
}
dialog header {
display: flex;
justify-content: space-between;
align-items: flex-start;
}
dialog header button svg {
fill: var(--color-link);
}
dialog main {
overflow: auto;
flex-grow: 1;
}
`;
return style;
}
toggleDialog() {
if (this.#dialog.open) {
this.#dialog.close();
} else {
this.#dialog.show();
}
}
}
window.customElements.define('aichat-button', AIChatButton);