123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- // https://github.com/siddharthkp/show-keys/blob/main/index.js
- const prettyMap = {
- ArrowUp: "↑",
- ArrowRight: "→",
- ArrowDown: "↓",
- ArrowLeft: "←",
- Shift: "⇧",
- Meta: "⌘",
- Alt: "⌥",
- Control: "^",
- Escape: "esc",
- Backspace: "⌫",
- Enter: "⏎",
- 32: "space",
- CapsLock: "caps lock",
- Tab: "tab",
- }
- let keys = []
- let appearedAt = null
- const handler = (event) => {
- if (
- window.SHOW_KEYS_SKIP_INPUTS &&
- ["INPUT", "TEXTAREA"].includes(event.target.tagName)
- ) {
- return
- }
- const key =
- prettyMap[event.key] || prettyMap[event.which] || event.key.toUpperCase()
- const modifiers = {
- Meta: event.metaKey,
- Shift: event.shiftKey,
- Alt: event.altKey,
- Control: event.ctrlKey,
- }
- const newKeys = []
- Object.keys(modifiers)
- .filter((modifier) => modifiers[modifier])
- .forEach((modifier) => newKeys.push(prettyMap[modifier]))
- if (!Object.keys(modifiers).includes(event.key)) newKeys.push(key)
- const dismissAfterTimeout = () => {
- // TODO: Should probably clear this timeout
- window.setTimeout(() => {
- if (new Date() - appearedAt < 1000) dismissAfterTimeout()
- else {
- keys = []
- render()
- }
- }, 1000)
- }
- keys = newKeys
- appearedAt = new Date()
- render()
- dismissAfterTimeout()
- }
- const css = `
- [data-keys] {
- display: flex;
- background: rgba(0, 0, 0, 0.75);
- border-radius: 8px;
- position: fixed;
- bottom: 64px;
- left: 32px;
- padding: 8px 8px 12px;
- font-size: 24px;
- font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
- Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
- animation: keys-zoom-in 50ms;
- z-index: 99999;
- }
- [data-keys][data-children="0"] {
- opacity: 0;
- }
- [data-keys] [data-key] + [data-key] {
- margin-left: 8px;
- }
- [data-keys] [data-key] {
- height: 46px;
- min-width: 32px;
- padding: 16px;
- display: flex;
- justify-content: center;
- align-items: center;
- color: #2e2e2e;
- background: linear-gradient(#fff, #dadada);
- border-radius: 8px;
- border-top: 1px solid #f5f5f5;
- box-shadow: inset 0 0 25px #e8e8e8, 0 1px 0 #c3c3c3, 0 4px 0 #c9c9c9;
- text-shadow: 0px 1px 0px #f5f5f5;
- }
- @keyframes keys-zoom-in {
- from {
- transform: scale(0.9);
- }
- 100% {
- }
- }
- `
- const insertCSS = () => {
- const cssExists = document.head.querySelector("#keyscss")
- if (!cssExists) {
- const cssContainer = document.createElement("style")
- cssContainer.id = "keyscss"
- document.head.append(cssContainer)
- cssContainer.append(css)
- }
- }
- const ensureContainer = () => {
- let container = document.querySelector("[data-keys]")
- if (!container) {
- container = document.createElement("div")
- container.setAttribute("data-keys", "")
- document.body.append(container)
- return container
- } else {
- return container
- }
- }
- const render = () => {
- const container = ensureContainer()
- if (keys.length === 0) container.outerHTML = ``
- else {
- container.outerHTML = `
- <div data-keys>
- ${keys.map((key) => `<div data-key>${key}</div>`)}
- </div>
- `
- }
- }
- if (typeof window !== "undefined") {
- window.addEventListener("keydown", handler)
- insertCSS()
- }
|