68 lines
2.3 KiB
JavaScript
68 lines
2.3 KiB
JavaScript
/**
|
|
* ZoneItemGroup web component
|
|
*
|
|
* Progressive enhancement for zone-grouped item cards in the outfit view.
|
|
* Replaces baseline Show/Hide buttons with radio-button behavior:
|
|
* - Clicking a closeted item's label selects its radio and submits the Show form
|
|
* - Clicking a worn item's label submits the Hide form (un-wears it)
|
|
* - Arrow keys navigate between items via native radio behavior, triggering
|
|
* a `change` event that submits the newly-selected item's Show form
|
|
*/
|
|
class ZoneItemGroup extends HTMLElement {
|
|
connectedCallback() {
|
|
this.addEventListener("click", this.#handleClick);
|
|
this.addEventListener("keydown", this.#handleKeydown);
|
|
this.addEventListener("change", this.#handleChange);
|
|
}
|
|
|
|
#handleClick = (e) => {
|
|
// Only handle clicks on labels (the item card click target)
|
|
const label = e.target.closest(".item-card-label");
|
|
if (!label) return;
|
|
|
|
const radio = label.querySelector("input[type=radio]");
|
|
if (!radio) return;
|
|
|
|
const card = label.closest(".item-card");
|
|
if (!card) return;
|
|
|
|
// If this item is worn (radio was already checked), un-wear it
|
|
if (card.dataset.isWorn != null) {
|
|
// Prevent the default label behavior (which would keep radio checked)
|
|
e.preventDefault();
|
|
const hideButton = card.querySelector(".item-hide-button");
|
|
if (hideButton) hideButton.closest("form").requestSubmit();
|
|
}
|
|
// If closeted, let the default label click proceed—it checks the radio,
|
|
// which fires the `change` event handled below
|
|
};
|
|
|
|
#handleKeydown = (e) => {
|
|
// Spacebar on an already-checked radio: un-wear the item
|
|
if (e.key !== " ") return;
|
|
|
|
const radio = e.target;
|
|
if (radio.type !== "radio" || !radio.checked) return;
|
|
|
|
const card = radio.closest(".item-card");
|
|
if (!card || card.dataset.isWorn == null) return;
|
|
|
|
e.preventDefault();
|
|
const hideButton = card.querySelector(".item-hide-button");
|
|
if (hideButton) hideButton.closest("form").requestSubmit();
|
|
};
|
|
|
|
#handleChange = (e) => {
|
|
const radio = e.target;
|
|
if (radio.type !== "radio" || !radio.checked) return;
|
|
|
|
const card = radio.closest(".item-card");
|
|
if (!card) return;
|
|
|
|
// Submit the Show form to wear this item
|
|
const showButton = card.querySelector(".item-show-button");
|
|
if (showButton) showButton.closest("form").requestSubmit();
|
|
};
|
|
}
|
|
|
|
customElements.define("zone-item-group", ZoneItemGroup);
|