feat(kanban): prove accessible local reorder
req: client_local/013\nreq: accessibility/002\nreq: accessibility/003\nreq: accessibility/004\nreq: accessibility/006\nreq: milestone/001
This commit is contained in:
+37
-11
@@ -256,7 +256,7 @@
|
||||
const wire = await handler(
|
||||
1,
|
||||
event.type,
|
||||
"value" in el ? String(el.value) : undefined,
|
||||
dragKeys.get(root) || el.getAttribute("data-card-id") || ("value" in el ? String(el.value) : undefined),
|
||||
"checked" in el ? Boolean(el.checked) : undefined,
|
||||
event.key || undefined,
|
||||
stateVersion,
|
||||
@@ -265,6 +265,14 @@
|
||||
if (!(wire instanceof Uint8Array)) throw new Error(`client-local hemx handler ${name} returned an invalid effect batch`);
|
||||
if (!active()) return;
|
||||
applyBatch(wire, root);
|
||||
if (name === "reorder_card") {
|
||||
const key = dragKeys.get(root) || el.getAttribute("data-card-id");
|
||||
const moved = key ? firstElement(root, (node) => node.getAttribute("data-key") === key) : null;
|
||||
const focus = moved && (firstElement(moved, (node) => node.tagName === "BUTTON") || moved);
|
||||
if (focus && typeof focus.focus === "function") focus.focus();
|
||||
if (matchMedia("(prefers-reduced-motion: reduce)").matches) root.setAttribute("data-hemx-reduced-motion", "");
|
||||
else root.removeAttribute("data-hemx-reduced-motion");
|
||||
}
|
||||
} catch (error) {
|
||||
if (!active()) return;
|
||||
const fallback = el.hasAttribute("data-hemx-client-fallback");
|
||||
@@ -677,14 +685,23 @@
|
||||
}
|
||||
|
||||
function defaultEvent(el) {
|
||||
if (el.getAttribute("data-hemx-on")) return el.getAttribute("data-hemx-on");
|
||||
if (el.getAttribute("data-hemx-on")) return el.getAttribute("data-hemx-on").trim().split(/\s+/)[0];
|
||||
if (el.tagName === "FORM") return "submit";
|
||||
return "click";
|
||||
}
|
||||
|
||||
function handlesEvent(el, name) {
|
||||
const declared = el.getAttribute("data-hemx-on");
|
||||
return declared ? declared.trim().split(/\s+/).includes(name) : defaultEvent(el) === name;
|
||||
}
|
||||
|
||||
function bindRoot(root) {
|
||||
["click", "submit", "input", "change", "dragstart", "dragover", "drop"].forEach((name) => {
|
||||
["click", "submit", "input", "change", "keydown", "dragstart", "dragover", "drop"].forEach((name) => {
|
||||
root.addEventListener(name, (event) => {
|
||||
if (name === "keydown") {
|
||||
const direct = closestInRoot(event.target, root, (el) => el.hasAttribute("data-hemx-client"));
|
||||
if (direct && !["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown"].includes(event.key)) return;
|
||||
}
|
||||
if (name === "dragstart") {
|
||||
const item = closestInRoot(event.target, root, (el) => el.hasAttribute("data-key"));
|
||||
if (item) {
|
||||
@@ -709,16 +726,17 @@
|
||||
}
|
||||
if (name === "click") {
|
||||
const direct = closestInRoot(event.target, root, (el) => el.hasAttribute(HID));
|
||||
if (direct && defaultEvent(direct) === "click") {
|
||||
const active = direct || closestInRoot(event.target, root, (el) => el.hasAttribute("data-hemx-client"));
|
||||
if (active && handlesEvent(active, "click")) {
|
||||
event.preventDefault();
|
||||
if (direct.hasAttribute("data-hemx-client")) {
|
||||
runClient(direct, event).catch((error) => emit(root, "hemx:client-error", {
|
||||
handler: direct.getAttribute("data-hemx-client"),
|
||||
if (active.hasAttribute("data-hemx-client")) {
|
||||
runClient(active, event).catch((error) => emit(root, "hemx:client-error", {
|
||||
handler: active.getAttribute("data-hemx-client"),
|
||||
message: String(error),
|
||||
fallback: false,
|
||||
}));
|
||||
} else {
|
||||
schedule(direct, name);
|
||||
schedule(active, name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -737,13 +755,21 @@
|
||||
}
|
||||
}
|
||||
let el = closestInRoot(event.target, root, (node) =>
|
||||
node.hasAttribute(HID) ||
|
||||
node.hasAttribute(HID) || node.hasAttribute("data-hemx-client") ||
|
||||
(node.tagName === "FORM" && (pageFormHistoryMode(event.submitter || node, node) || boostRoot(node)))
|
||||
);
|
||||
if (name === "submit" && !el && event.target && event.target.tagName === "FORM" && (formHandleId(event.target) || pageFormHistoryMode(event.submitter || event.target, event.target))) el = event.target;
|
||||
if (!el || defaultEvent(el) !== name) return;
|
||||
if (!el || !handlesEvent(el, name)) return;
|
||||
event.preventDefault();
|
||||
schedule(el, name, event.submitter || el);
|
||||
if (el.hasAttribute("data-hemx-client")) {
|
||||
runClient(el, event).catch((error) => emit(root, "hemx:client-error", {
|
||||
handler: el.getAttribute("data-hemx-client"),
|
||||
message: String(error),
|
||||
fallback: false,
|
||||
}));
|
||||
} else {
|
||||
schedule(el, name, event.submitter || el);
|
||||
}
|
||||
});
|
||||
});
|
||||
bindPolling(root);
|
||||
|
||||
Reference in New Issue
Block a user