import Component from 'https://fancy-pants.js.org/min/component.js';
import { confineTabbing, releaseTabbing } from 'https://tritarget.org/cdn/tabbing.js';
const uniqueId = (() => {
let lastId = 0;
return () => lastId++;
})();
class SimpleModal extends Component {
releaseKeyboard = () => {};
modalResolver = { resolve() {}, reject() {} };
constructor() {
super();
this.id = this.id || `simple-model${uniqueId()}`;
}
connectedCallback() {
super.connectedCallback();
this.dialog = this.querySelector('dialog');
this.addEventListener('click', (e) => this.handleAction(e));
this.addEventListener('close', () => this.cancel());
}
handleAction(event) {
event.stopPropagation();
let { action } = event.target.dataset;
if (['cancel', 'confirm', 'reject', 'error'].includes(action)) {
this[action]();
} else if (event.target === this) {
this.cancel();
}
}
open() {
return new Promise((resolve, reject) => {
this.modalResolver = { resolve, reject };
this.dialog.showModal();
}).finally(() => this.dialog.close());
}
cancel(value) {
this.modalResolver.resolve({ reason: 'cancelled', value });
}
confirm(value) {
this.modalResolver.resolve({ reason: 'confirmed', value });
}
reject(value) {
this.modalResolver.resolve({ reason: 'rejected', value });
}
error(error) {
this.modalResolver.reject(error);
}
render() {
let ariaLabelId = `${this.id}-title`;
this.dialog.querySelector('header h1').id = ariaLabelId;
this.dialog.setAttribute('aria-labelledby', ariaLabelId);
}
static get observedAttributes() {
return ['open'];
}
static get template() {
return `
<dialog>
<header>
<button type="button" aria-label="dismiss" data-action="cancel">✗</button>
<h1><slot name="header"></slot></h1>
</header>
<section><slot name="content"></slot></section>
<footer><slot name="footer"></slot></footer>
</dialog>
`;
}
}
SimpleModal.register();