feat(playlists): select rows with a box, Shift for a range, x and Esc

A box first in every row and one over the column for the rows shown, the
selected row tinted. A filter keeps what it hides selected; another list
starts over; a row that left the list drops out. Watch later has none.

A box no longer counts as a typing target: a click on one left the focus
there and the page's keys went dead.
This commit is contained in:
2026-11-01 20:49:59 +01:00
parent cd773e8f33
commit 8cf8c4139c
20 changed files with 710 additions and 29 deletions
+23
View File
@@ -93,6 +93,24 @@ describe("isTypingTarget", () => {
it("is false on ordinary content", () => {
expect(isTypingTarget(press({ key: "a" }))).toBe(false);
});
it("is false on a box, where no letter types: the page's keys go on working after a tick", () => {
for (const type of ["checkbox", "radio"]) {
const el = document.createElement("input");
el.type = type;
document.body.append(el);
expect(isTypingTarget(press({ key: "a" }, el))).toBe(false);
el.remove();
}
});
it("stays true on a slider, whose arrows are its own", () => {
const el = document.createElement("input");
el.type = "range";
document.body.append(el);
expect(isTypingTarget(press({ key: "ArrowLeft" }, el))).toBe(true);
el.remove();
});
});
describe("isActivationTarget", () => {
@@ -101,6 +119,11 @@ describe("isActivationTarget", () => {
document.body.append(btn);
expect(isActivationTarget(press({ key: " " }, btn))).toBe(true);
btn.remove();
const box = document.createElement("input");
box.type = "checkbox";
document.body.append(box);
expect(isActivationTarget(press({ key: " " }, box))).toBe(true);
box.remove();
expect(isActivationTarget(press({ key: " " }))).toBe(false);
});
});