One rule, two forms: useOrderItems (Top / Up / Down / Bottom rows of a row menu) and OrderButtons (four buttons with the place, or a compact Up / Down pair). A move that would go nowhere is shown off. - YouTube playlist rows: the four moves now come from useOrderItems. - Plex playlist rows: a block among the blocks, an episode within its show, off while a write is in flight; drag and menu share moveBlock/moveEpisode. - Saved views editor: the selected view's four buttons (owner: A), and the grip's keyboard pick-up (its instructions promised one it did not have). - Side panel groups in edit mode: an Up / Down pair (owner: A); a group the stored order does not hold yet moves too; the name wraps there. - The grip's touch-action: none is now test-held.
15 lines
827 B
TypeScript
15 lines
827 B
TypeScript
// The non-drag way to reorder a list (WCAG 2.5.7, docs/DESIGN.md "Reordering"): anything a grip can
|
|
// drag also moves by Top / Up / Down / Bottom — a menu's rows or a row of buttons, one rule for both.
|
|
|
|
export type MoveTo = "top" | "up" | "down" | "bottom";
|
|
|
|
export const MOVES: readonly MoveTo[] = ["top", "up", "down", "bottom"];
|
|
|
|
/** Where `to` sends the item at `from` in a list of `count`, or null when it would not move (the
|
|
* first item going up, the last going down, a stale index) — the caller shows that move as off. */
|
|
export function moveTarget(from: number, count: number, to: MoveTo): number | null {
|
|
if (from < 0 || from >= count) return null;
|
|
const at = to === "top" ? 0 : to === "bottom" ? count - 1 : to === "up" ? from - 1 : from + 1;
|
|
return at === from || at < 0 || at >= count ? null : at;
|
|
}
|