impress/app/assets/javascripts/pose-picker.js

53 lines
1.4 KiB
JavaScript

/**
* PosePicker web component
*
* Progressive enhancement for pose picker forms:
* - Auto-submits the form when a pose is selected (if JS is enabled)
* - Shows a submit button as fallback (if JS is disabled or slow to load)
* - Uses Custom Element internals API to communicate state to CSS
*/
class PosePickerPopover extends HTMLElement {
#internals;
#styleListObserver;
constructor() {
super();
this.#internals = this.attachInternals();
}
connectedCallback() {
// Listen for changes to auto-submit the form, then tell CSS about it!
this.addEventListener("change", this.#handleChange);
this.#internals.states.add("auto-loading");
// When the style picker list becomes visible (e.g. tab switch or
// popover open), scroll the selected style into view.
const styleList = this.querySelector(".style-picker-list");
if (styleList) {
this.#styleListObserver = new IntersectionObserver(([entry]) => {
if (entry.isIntersecting) {
const checked = styleList.querySelector("input:checked");
checked
?.closest("label")
?.scrollIntoView({ block: "nearest" });
}
});
this.#styleListObserver.observe(styleList);
}
}
disconnectedCallback() {
this.#styleListObserver?.disconnect();
}
#handleChange(e) {
// Only auto-submit if a radio button was changed
if (e.target.type === "radio") {
e.target.closest("form").requestSubmit();
}
}
}
customElements.define("pose-picker-popover", PosePickerPopover);