UNPKG

@grafana/ui

Version:
1 lines 10.3 kB
{"version":3,"file":"KeyboardPlugin.mjs","sources":["../../../../../src/components/uPlot/plugins/KeyboardPlugin.tsx"],"sourcesContent":["import { clamp } from 'lodash';\nimport { useLayoutEffect } from 'react';\nimport uPlot from 'uplot';\n\nimport { UPlotConfigBuilder } from '../config/UPlotConfigBuilder';\n\ninterface KeyboardPluginProps {\n config: UPlotConfigBuilder; // onkeypress, onkeyup, onkeydown (triggered by vizlayout handlers)\n}\n\nconst PIXELS_PER_MS = 0.1 as const;\nconst SHIFT_MULTIPLIER = 2 as const;\nconst KNOWN_KEYS = new Set(['ArrowRight', 'ArrowLeft', 'ArrowUp', 'ArrowDown', 'Shift', ' ']);\n\nconst initHook = (u: uPlot) => {\n let parentWithFocus: HTMLElement | null = u.root;\n let pressedKeys = new Set<string>();\n let dragStartX: number | null = null;\n let keysLastHandledAt: number | null = null;\n\n if (!parentWithFocus) {\n return;\n }\n // Make Graph area focusable. Setting this in Viz* components will make focus available on panels that do not yet have keyboard support\n parentWithFocus.tabIndex = 0;\n\n const moveCursor = (dx: number, dy: number) => {\n const { cursor } = u;\n if (cursor.left === undefined || cursor.top === undefined) {\n return;\n }\n\n const { width, height } = u.over.style;\n const [maxX, maxY] = [Math.floor(parseFloat(width)), Math.floor(parseFloat(height))];\n\n u.setCursor({\n left: clamp(cursor.left + dx, 0, maxX),\n top: clamp(cursor.top + dy, 0, maxY),\n });\n };\n\n const handlePressedKeys = (time: number) => {\n const nothingPressed = pressedKeys.size === 0;\n if (nothingPressed || !u) {\n keysLastHandledAt = null;\n return;\n }\n\n const dt = time - (keysLastHandledAt ?? time);\n const dx = dt * PIXELS_PER_MS;\n let horValue = 0;\n let vertValue = 0;\n\n if (pressedKeys.has('ArrowUp')) {\n vertValue -= dx;\n }\n if (pressedKeys.has('ArrowDown')) {\n vertValue += dx;\n }\n if (pressedKeys.has('ArrowLeft')) {\n horValue -= dx;\n }\n if (pressedKeys.has('ArrowRight')) {\n horValue += dx;\n }\n if (pressedKeys.has('Shift')) {\n horValue *= SHIFT_MULTIPLIER;\n vertValue *= SHIFT_MULTIPLIER;\n }\n\n moveCursor(horValue, vertValue);\n\n const { cursor } = u;\n if (pressedKeys.has(' ') && cursor) {\n const drawHeight = Number(u.over.style.height.slice(0, -2));\n\n u.setSelect(\n {\n left: cursor.left! < dragStartX! ? cursor.left! : dragStartX!,\n top: 0,\n width: Math.abs(cursor.left! - (dragStartX ?? cursor.left!)),\n height: drawHeight,\n },\n false\n );\n }\n\n keysLastHandledAt = time;\n window.requestAnimationFrame(handlePressedKeys);\n };\n\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Tab') {\n // Hide the cursor if the user tabs away\n u.setCursor({ left: -5, top: -5 });\n return;\n }\n\n if (!KNOWN_KEYS.has(e.key)) {\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n\n const newKey = !pressedKeys.has(e.key);\n if (newKey) {\n const initiateAnimationLoop = pressedKeys.size === 0;\n pressedKeys.add(e.key);\n\n dragStartX = e.key === ' ' && dragStartX === null ? u.cursor.left! : dragStartX;\n\n if (initiateAnimationLoop) {\n window.requestAnimationFrame(handlePressedKeys);\n }\n }\n };\n\n const onKeyUp = (e: KeyboardEvent) => {\n if (!KNOWN_KEYS.has(e.key)) {\n return;\n }\n\n pressedKeys.delete(e.key);\n\n if (e.key === ' ') {\n e.preventDefault();\n e.stopPropagation();\n\n // We do this so setSelect hooks get fired, zooming the plot\n u.setSelect(u.select);\n dragStartX = null;\n }\n };\n\n const onFocus = () => {\n // We only want to initialize the cursor if the user is using keyboard controls\n if (!parentWithFocus?.matches(':focus-visible')) {\n return;\n }\n\n // Is there a more idiomatic way to do this?\n const drawWidth = parseFloat(u.over.style.width);\n const drawHeight = parseFloat(u.over.style.height);\n u.setCursor({ left: drawWidth / 2, top: drawHeight / 2 });\n };\n\n const onBlur = () => {\n keysLastHandledAt = null;\n dragStartX = null;\n pressedKeys.clear();\n u.setSelect({ left: 0, top: 0, width: 0, height: 0 }, false);\n };\n\n parentWithFocus.addEventListener('keydown', onKeyDown);\n parentWithFocus.addEventListener('keyup', onKeyUp);\n parentWithFocus.addEventListener('focus', onFocus);\n parentWithFocus.addEventListener('blur', onBlur);\n\n const onDestroy = () => {\n parentWithFocus?.removeEventListener('keydown', onKeyDown);\n parentWithFocus?.removeEventListener('keyup', onKeyUp);\n parentWithFocus?.removeEventListener('focus', onFocus);\n parentWithFocus?.removeEventListener('blur', onBlur);\n parentWithFocus = null;\n };\n\n (u.hooks.destroy ??= []).push(onDestroy);\n};\n\n/**\n * @alpha\n */\nexport const KeyboardPlugin = ({ config }: KeyboardPluginProps) => {\n useLayoutEffect(() => config.addHook('init', initHook), [config]);\n\n return null;\n};\n"],"names":[],"mappings":";;;;AAUA,MAAM,aAAA,GAAgB,GAAA;AACtB,MAAM,gBAAA,GAAmB,CAAA;AACzB,MAAM,UAAA,mBAAa,IAAI,GAAA,CAAI,CAAC,YAAA,EAAc,aAAa,SAAA,EAAW,WAAA,EAAa,OAAA,EAAS,GAAG,CAAC,CAAA;AAE5F,MAAM,QAAA,GAAW,CAAC,CAAA,KAAa;AAd/B,EAAA,IAAA,EAAA,EAAA,EAAA;AAeE,EAAA,IAAI,kBAAsC,CAAA,CAAE,IAAA;AAC5C,EAAA,IAAI,WAAA,uBAAkB,GAAA,EAAY;AAClC,EAAA,IAAI,UAAA,GAA4B,IAAA;AAChC,EAAA,IAAI,iBAAA,GAAmC,IAAA;AAEvC,EAAA,IAAI,CAAC,eAAA,EAAiB;AACpB,IAAA;AAAA,EACF;AAEA,EAAA,eAAA,CAAgB,QAAA,GAAW,CAAA;AAE3B,EAAA,MAAM,UAAA,GAAa,CAAC,EAAA,EAAY,EAAA,KAAe;AAC7C,IAAA,MAAM,EAAE,QAAO,GAAI,CAAA;AACnB,IAAA,IAAI,MAAA,CAAO,IAAA,KAAS,KAAA,CAAA,IAAa,MAAA,CAAO,QAAQ,KAAA,CAAA,EAAW;AACzD,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,EAAE,KAAA,EAAO,MAAA,EAAO,GAAI,EAAE,IAAA,CAAK,KAAA;AACjC,IAAA,MAAM,CAAC,IAAA,EAAM,IAAI,CAAA,GAAI,CAAC,KAAK,KAAA,CAAM,UAAA,CAAW,KAAK,CAAC,GAAG,IAAA,CAAK,KAAA,CAAM,UAAA,CAAW,MAAM,CAAC,CAAC,CAAA;AAEnF,IAAA,CAAA,CAAE,SAAA,CAAU;AAAA,MACV,MAAM,KAAA,CAAM,MAAA,CAAO,IAAA,GAAO,EAAA,EAAI,GAAG,IAAI,CAAA;AAAA,MACrC,KAAK,KAAA,CAAM,MAAA,CAAO,GAAA,GAAM,EAAA,EAAI,GAAG,IAAI;AAAA,KACpC,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,MAAM,iBAAA,GAAoB,CAAC,IAAA,KAAiB;AAC1C,IAAA,MAAM,cAAA,GAAiB,YAAY,IAAA,KAAS,CAAA;AAC5C,IAAA,IAAI,cAAA,IAAkB,CAAC,CAAA,EAAG;AACxB,MAAA,iBAAA,GAAoB,IAAA;AACpB,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,EAAA,GAAK,QAAQ,iBAAA,IAAA,IAAA,GAAA,iBAAA,GAAqB,IAAA,CAAA;AACxC,IAAA,MAAM,KAAK,EAAA,GAAK,aAAA;AAChB,IAAA,IAAI,QAAA,GAAW,CAAA;AACf,IAAA,IAAI,SAAA,GAAY,CAAA;AAEhB,IAAA,IAAI,WAAA,CAAY,GAAA,CAAI,SAAS,CAAA,EAAG;AAC9B,MAAA,SAAA,IAAa,EAAA;AAAA,IACf;AACA,IAAA,IAAI,WAAA,CAAY,GAAA,CAAI,WAAW,CAAA,EAAG;AAChC,MAAA,SAAA,IAAa,EAAA;AAAA,IACf;AACA,IAAA,IAAI,WAAA,CAAY,GAAA,CAAI,WAAW,CAAA,EAAG;AAChC,MAAA,QAAA,IAAY,EAAA;AAAA,IACd;AACA,IAAA,IAAI,WAAA,CAAY,GAAA,CAAI,YAAY,CAAA,EAAG;AACjC,MAAA,QAAA,IAAY,EAAA;AAAA,IACd;AACA,IAAA,IAAI,WAAA,CAAY,GAAA,CAAI,OAAO,CAAA,EAAG;AAC5B,MAAA,QAAA,IAAY,gBAAA;AACZ,MAAA,SAAA,IAAa,gBAAA;AAAA,IACf;AAEA,IAAA,UAAA,CAAW,UAAU,SAAS,CAAA;AAE9B,IAAA,MAAM,EAAE,QAAO,GAAI,CAAA;AACnB,IAAA,IAAI,WAAA,CAAY,GAAA,CAAI,GAAG,CAAA,IAAK,MAAA,EAAQ;AAClC,MAAA,MAAM,UAAA,GAAa,OAAO,CAAA,CAAE,IAAA,CAAK,MAAM,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,CAAA,CAAE,CAAC,CAAA;AAE1D,MAAA,CAAA,CAAE,SAAA;AAAA,QACA;AAAA,UACE,IAAA,EAAM,MAAA,CAAO,IAAA,GAAQ,UAAA,GAAc,OAAO,IAAA,GAAQ,UAAA;AAAA,UAClD,GAAA,EAAK,CAAA;AAAA,UACL,OAAO,IAAA,CAAK,GAAA,CAAI,OAAO,IAAA,IAAS,UAAA,IAAA,IAAA,GAAA,UAAA,GAAc,OAAO,IAAA,CAAM,CAAA;AAAA,UAC3D,MAAA,EAAQ;AAAA,SACV;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAEA,IAAA,iBAAA,GAAoB,IAAA;AACpB,IAAA,MAAA,CAAO,sBAAsB,iBAAiB,CAAA;AAAA,EAChD,CAAA;AAEA,EAAA,MAAM,SAAA,GAAY,CAAC,CAAA,KAAqB;AACtC,IAAA,IAAI,CAAA,CAAE,QAAQ,KAAA,EAAO;AAEnB,MAAA,CAAA,CAAE,UAAU,EAAE,IAAA,EAAM,CAAA,CAAA,EAAI,GAAA,EAAK,IAAI,CAAA;AACjC,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,UAAA,CAAW,GAAA,CAAI,CAAA,CAAE,GAAG,CAAA,EAAG;AAC1B,MAAA;AAAA,IACF;AAEA,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,CAAA,CAAE,eAAA,EAAgB;AAElB,IAAA,MAAM,MAAA,GAAS,CAAC,WAAA,CAAY,GAAA,CAAI,EAAE,GAAG,CAAA;AACrC,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAM,qBAAA,GAAwB,YAAY,IAAA,KAAS,CAAA;AACnD,MAAA,WAAA,CAAY,GAAA,CAAI,EAAE,GAAG,CAAA;AAErB,MAAA,UAAA,GAAa,EAAE,GAAA,KAAQ,GAAA,IAAO,eAAe,IAAA,GAAO,CAAA,CAAE,OAAO,IAAA,GAAQ,UAAA;AAErE,MAAA,IAAI,qBAAA,EAAuB;AACzB,QAAA,MAAA,CAAO,sBAAsB,iBAAiB,CAAA;AAAA,MAChD;AAAA,IACF;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,OAAA,GAAU,CAAC,CAAA,KAAqB;AACpC,IAAA,IAAI,CAAC,UAAA,CAAW,GAAA,CAAI,CAAA,CAAE,GAAG,CAAA,EAAG;AAC1B,MAAA;AAAA,IACF;AAEA,IAAA,WAAA,CAAY,MAAA,CAAO,EAAE,GAAG,CAAA;AAExB,IAAA,IAAI,CAAA,CAAE,QAAQ,GAAA,EAAK;AACjB,MAAA,CAAA,CAAE,cAAA,EAAe;AACjB,MAAA,CAAA,CAAE,eAAA,EAAgB;AAGlB,MAAA,CAAA,CAAE,SAAA,CAAU,EAAE,MAAM,CAAA;AACpB,MAAA,UAAA,GAAa,IAAA;AAAA,IACf;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,UAAU,MAAM;AAEpB,IAAA,IAAI,EAAC,eAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,eAAA,CAAiB,OAAA,CAAQ,gBAAA,CAAA,CAAA,EAAmB;AAC/C,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,SAAA,GAAY,UAAA,CAAW,CAAA,CAAE,IAAA,CAAK,MAAM,KAAK,CAAA;AAC/C,IAAA,MAAM,UAAA,GAAa,UAAA,CAAW,CAAA,CAAE,IAAA,CAAK,MAAM,MAAM,CAAA;AACjD,IAAA,CAAA,CAAE,SAAA,CAAU,EAAE,IAAA,EAAM,SAAA,GAAY,GAAG,GAAA,EAAK,UAAA,GAAa,GAAG,CAAA;AAAA,EAC1D,CAAA;AAEA,EAAA,MAAM,SAAS,MAAM;AACnB,IAAA,iBAAA,GAAoB,IAAA;AACpB,IAAA,UAAA,GAAa,IAAA;AACb,IAAA,WAAA,CAAY,KAAA,EAAM;AAClB,IAAA,CAAA,CAAE,SAAA,CAAU,EAAE,IAAA,EAAM,CAAA,EAAG,GAAA,EAAK,CAAA,EAAG,KAAA,EAAO,CAAA,EAAG,MAAA,EAAQ,CAAA,EAAE,EAAG,KAAK,CAAA;AAAA,EAC7D,CAAA;AAEA,EAAA,eAAA,CAAgB,gBAAA,CAAiB,WAAW,SAAS,CAAA;AACrD,EAAA,eAAA,CAAgB,gBAAA,CAAiB,SAAS,OAAO,CAAA;AACjD,EAAA,eAAA,CAAgB,gBAAA,CAAiB,SAAS,OAAO,CAAA;AACjD,EAAA,eAAA,CAAgB,gBAAA,CAAiB,QAAQ,MAAM,CAAA;AAE/C,EAAA,MAAM,YAAY,MAAM;AACtB,IAAA,eAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,eAAA,CAAiB,oBAAoB,SAAA,EAAW,SAAA,CAAA;AAChD,IAAA,eAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,eAAA,CAAiB,oBAAoB,OAAA,EAAS,OAAA,CAAA;AAC9C,IAAA,eAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,eAAA,CAAiB,oBAAoB,OAAA,EAAS,OAAA,CAAA;AAC9C,IAAA,eAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,eAAA,CAAiB,oBAAoB,MAAA,EAAQ,MAAA,CAAA;AAC7C,IAAA,eAAA,GAAkB,IAAA;AAAA,EACpB,CAAA;AAEA,EAAA,CAAA,CAAC,EAAA,GAAA,CAAA,EAAA,GAAA,CAAA,CAAE,OAAM,OAAA,KAAR,IAAA,GAAA,EAAA,GAAA,EAAA,CAAQ,UAAY,EAAC,EAAG,KAAK,SAAS,CAAA;AACzC,CAAA;AAKO,MAAM,cAAA,GAAiB,CAAC,EAAE,MAAA,EAAO,KAA2B;AACjE,EAAA,eAAA,CAAgB,MAAM,OAAO,OAAA,CAAQ,MAAA,EAAQ,QAAQ,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAEhE,EAAA,OAAO,IAAA;AACT;;;;"}