// Adapted from Astryx Kbd (MIT). See THIRD_PARTY_NOTICES.md. "use client"; import { useSyncExternalStore, type ComponentProps } from "react"; const displays: Record = { ctrl: "⌃", alt: "⌥", shift: "⇧", enter: "↵", backspace: "⌫", escape: "Esc", tab: "⇥", space: "Space", up: "↑", down: "↓", left: "←", right: "→", plus: "+", }; const labels: Record = { ctrl: "Control", alt: "Alt", shift: "Shift", enter: "Enter", backspace: "Backspace", escape: "Escape", tab: "Tab", space: "Space", up: "Up arrow", down: "Down arrow", left: "Left arrow", right: "Right arrow", plus: "Plus", }; const aliases: Record = { esc: "escape", return: "enter" }; const subscribe = () => () => {}; const getServerSnapshot = () => false; const getPlatformSnapshot = () => typeof navigator !== "undefined" && /Mac|iPhone|iPad|iPod/.test(navigator.platform); export interface KbdProps extends ComponentProps<"span"> { keys: string; } export function Kbd({ keys, className = "", ...props }: KbdProps) { const isApple = useSyncExternalStore( subscribe, getPlatformSnapshot, getServerSnapshot, ); const occurrences = new Map(); const parts = keys .split("+") .map((key) => key.trim().toLowerCase()) .filter(Boolean) .map((source) => { const occurrence = occurrences.get(source) ?? 0; occurrences.set(source, occurrence + 1); return { key: aliases[source] ?? source, reactKey: `${source}:${occurrence}`, }; }); const keyLabel = (key: string) => key === "mod" ? isApple ? "Command" : "Control" : (labels[key] ?? key.toUpperCase()); const keyDisplay = (key: string) => key === "mod" ? isApple ? "⌘" : "Ctrl" : (displays[key] ?? key.toUpperCase()); return ( keyLabel(key)).join(" + ")} className={`ynr-kbd${className ? ` ${className}` : ""}`} > {parts.map(({ key, reactKey }) => ( ))} ); }