All files / virtual-keyboard/src keyProps.ts

100% Statements 5/5
100% Branches 2/2
100% Functions 3/3
100% Lines 5/5

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35                                    1505x                 1x 1x     1505x 1505x    
import type { ButtonHTMLAttributes } from "react";
import { isModifierAction, keyAccessibleName } from "./constants";
import type { ResolvedKey } from "./types";
 
/**
 * The single source of truth for a key `<button>`'s attributes — used by both
 * the hook's `getKeyProps` (for headless / `renderKey` consumers) and the
 * built-in `Key` component, so the two never diverge.
 *
 * Includes the roving-focus contract (`tabIndex={-1}` + `data-vk-key`) so any
 * key rendered from these props participates in arrow/D-pad navigation, and an
 * `onMouseDown` that prevents the default focus steal — a ref-bound input keeps
 * visible focus while the user types with the pointer.
 */
export function getKeyButtonProps(
  key: ResolvedKey,
  onPress: (key: ResolvedKey) => void
): ButtonHTMLAttributes<HTMLButtonElement> {
  const props: ButtonHTMLAttributes<HTMLButtonElement> = {
    type: "button",
    disabled: key.disabled,
    tabIndex: -1,
    "aria-label": keyAccessibleName(key, key.effectiveValue),
    "aria-pressed": isModifierAction(key.action)
      ? Boolean(key.active)
      : undefined,
    // Keep a ref-bound input focused during pointer typing.
    onMouseDown: (event) => event.preventDefault(),
    onClick: () => onPress(key),
  };
  // data-* keys are not part of the typed literal surface — attach after.
  (props as Record<string, unknown>)["data-vk-key"] = "";
  return props;
}