UNPKG

@grafana/ui

Version:
1 lines 16 kB
{"version":3,"file":"DataLinkInput.mjs","sources":["../../../../src/components/DataLinks/DataLinkInput.tsx"],"sourcesContent":["import { css, cx } from '@emotion/css';\nimport { autoUpdate, offset, useFloating } from '@floating-ui/react';\nimport Prism, { Grammar, LanguageMap } from 'prismjs';\nimport { memo, useEffect, useRef, useState } from 'react';\nimport * as React from 'react';\nimport { usePrevious } from 'react-use';\nimport { Value } from 'slate';\nimport Plain from 'slate-plain-serializer';\nimport { Editor } from 'slate-react';\n\nimport { DataLinkBuiltInVars, GrafanaTheme2, VariableOrigin, VariableSuggestion } from '@grafana/data';\n\nimport { SlatePrism } from '../../slate-plugins/slate-prism';\nimport { useStyles2 } from '../../themes/ThemeContext';\nimport { getPositioningMiddleware } from '../../utils/floating';\nimport { SCHEMA, makeValue } from '../../utils/slate';\nimport { getInputStyles } from '../Input/Input';\nimport { Portal } from '../Portal/Portal';\nimport { ScrollContainer } from '../ScrollContainer/ScrollContainer';\n\nimport { DataLinkSuggestions } from './DataLinkSuggestions';\nimport { SelectionReference } from './SelectionReference';\n\nconst modulo = (a: number, n: number) => a - n * Math.floor(a / n);\n\ninterface DataLinkInputProps {\n value: string;\n onChange: (url: string, callback?: () => void) => void;\n suggestions: VariableSuggestion[];\n placeholder?: string;\n}\n\nconst datalinksSyntax: Grammar = {\n builtInVariable: {\n pattern: /(\\${\\S+?})/,\n },\n};\n\nconst plugins = [\n SlatePrism(\n {\n onlyIn: (node) => 'type' in node && node.type === 'code_block',\n getSyntax: () => 'links',\n },\n { ...(Prism.languages as LanguageMap), links: datalinksSyntax }\n ),\n];\n\nconst getStyles = (theme: GrafanaTheme2) => ({\n input: getInputStyles({ theme, invalid: false }).input,\n editor: css({\n '.token.builtInVariable': {\n color: theme.colors.success.text,\n },\n '.token.variable': {\n color: theme.colors.primary.text,\n },\n }),\n suggestionsWrapper: css({\n boxShadow: theme.shadows.z2,\n }),\n // Wrapper with child selector needed.\n // When classnames are applied to the same element as the wrapper, it causes the suggestions to stop working\n wrapperOverrides: css({\n width: '100%',\n '> .slate-query-field__wrapper': {\n padding: 0,\n backgroundColor: 'transparent',\n border: 'none',\n },\n }),\n});\n\n// This memoised also because rerendering the slate editor grabs focus which created problem in some cases this\n// was used and changes to different state were propagated here.\nexport const DataLinkInput = memo(\n ({\n value,\n onChange,\n suggestions,\n placeholder = 'http://your-grafana.com/d/000000010/annotations',\n }: DataLinkInputProps) => {\n const editorRef = useRef<Editor>(null);\n const styles = useStyles2(getStyles);\n const [showingSuggestions, setShowingSuggestions] = useState(false);\n const [suggestionsIndex, setSuggestionsIndex] = useState(0);\n const [linkUrl, setLinkUrl] = useState<Value>(makeValue(value));\n const prevLinkUrl = usePrevious<Value>(linkUrl);\n const [scrollTop, setScrollTop] = useState(0);\n const scrollRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n scrollRef.current?.scrollTo(0, scrollTop);\n }, [scrollTop]);\n\n // the order of middleware is important!\n const middleware = [\n offset(({ rects }) => ({\n alignmentAxis: rects.reference.width,\n })),\n ...getPositioningMiddleware(),\n ];\n\n const { refs, floatingStyles } = useFloating({\n open: showingSuggestions,\n placement: 'bottom-start',\n onOpenChange: setShowingSuggestions,\n middleware,\n whileElementsMounted: autoUpdate,\n strategy: 'fixed',\n });\n\n // Workaround for https://github.com/ianstormtaylor/slate/issues/2927\n const stateRef = useRef({ showingSuggestions, suggestions, suggestionsIndex, linkUrl, onChange });\n stateRef.current = { showingSuggestions, suggestions, suggestionsIndex, linkUrl, onChange };\n\n // Used to get the height of the suggestion elements in order to scroll to them.\n const activeRef = useRef<HTMLDivElement>(null);\n useEffect(() => {\n setScrollTop(getElementPosition(activeRef.current, suggestionsIndex));\n }, [suggestionsIndex]);\n\n const onKeyDown = React.useCallback((event: React.KeyboardEvent, next: () => void) => {\n if (!stateRef.current.showingSuggestions) {\n if (event.key === '=' || event.key === '$' || (event.keyCode === 32 && event.ctrlKey)) {\n const selectionRef = new SelectionReference();\n refs.setReference(selectionRef);\n return setShowingSuggestions(true);\n }\n return next();\n }\n\n switch (event.key) {\n case 'Backspace':\n if (stateRef.current.linkUrl.focusText.getText().length === 1) {\n next();\n }\n case 'Escape':\n setShowingSuggestions(false);\n return setSuggestionsIndex(0);\n\n case 'Enter':\n event.preventDefault();\n return onVariableSelect(stateRef.current.suggestions[stateRef.current.suggestionsIndex]);\n\n case 'ArrowDown':\n case 'ArrowUp':\n event.preventDefault();\n const direction = event.key === 'ArrowDown' ? 1 : -1;\n return setSuggestionsIndex((index) => modulo(index + direction, stateRef.current.suggestions.length));\n default:\n return next();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n useEffect(() => {\n // Update the state of the link in the parent. This is basically done on blur but we need to do it after\n // our state have been updated. The duplicity of state is done for perf reasons and also because local\n // state also contains things like selection and formating.\n if (prevLinkUrl && prevLinkUrl.selection.isFocused && !linkUrl.selection.isFocused) {\n stateRef.current.onChange(Plain.serialize(linkUrl));\n }\n }, [linkUrl, prevLinkUrl]);\n\n const onUrlChange = React.useCallback(({ value }: { value: Value }) => {\n setLinkUrl(value);\n }, []);\n\n const onVariableSelect = (item: VariableSuggestion, editor = editorRef.current!) => {\n const precedingChar: string = getCharactersAroundCaret();\n const precedingDollar = precedingChar === '$';\n if (item.origin !== VariableOrigin.Template || item.value === DataLinkBuiltInVars.includeVars) {\n editor.insertText(`${precedingDollar ? '' : '$'}\\{${item.value}}`);\n } else {\n editor.insertText(`${precedingDollar ? '' : '$'}\\{${item.value}:queryparam}`);\n }\n\n setLinkUrl(editor.value);\n setShowingSuggestions(false);\n\n setSuggestionsIndex(0);\n stateRef.current.onChange(Plain.serialize(editor.value));\n };\n\n const getCharactersAroundCaret = () => {\n const input: HTMLSpanElement | null = document.getElementById('data-link-input')!;\n let precedingChar = '',\n sel: Selection | null,\n range: Range;\n if (window.getSelection) {\n sel = window.getSelection();\n if (sel && sel.rangeCount > 0) {\n range = sel.getRangeAt(0).cloneRange();\n // Collapse to the start of the range\n range.collapse(true);\n range.setStart(input, 0);\n precedingChar = range.toString().slice(-1);\n }\n }\n return precedingChar;\n };\n\n return (\n <div className={styles.wrapperOverrides}>\n <div className=\"slate-query-field__wrapper\">\n <div id=\"data-link-input\" className=\"slate-query-field\">\n {showingSuggestions && (\n <Portal>\n <div ref={refs.setFloating} style={floatingStyles}>\n <ScrollContainer\n maxHeight=\"300px\"\n ref={scrollRef}\n onScroll={(event) => setScrollTop(event.currentTarget.scrollTop)}\n >\n <DataLinkSuggestions\n activeRef={activeRef}\n suggestions={stateRef.current.suggestions}\n onSuggestionSelect={onVariableSelect}\n onClose={() => setShowingSuggestions(false)}\n activeIndex={suggestionsIndex}\n />\n </ScrollContainer>\n </div>\n </Portal>\n )}\n <Editor\n schema={SCHEMA}\n ref={editorRef}\n placeholder={placeholder}\n value={stateRef.current.linkUrl}\n onChange={onUrlChange}\n onKeyDown={(event, _editor, next) => onKeyDown(event, next)}\n plugins={plugins}\n className={cx(\n styles.editor,\n styles.input,\n css({\n padding: '3px 8px',\n })\n )}\n />\n </div>\n </div>\n </div>\n );\n }\n);\n\nDataLinkInput.displayName = 'DataLinkInput';\n\nfunction getElementPosition(suggestionElement: HTMLElement | null, activeIndex: number) {\n return (suggestionElement?.clientHeight ?? 0) * activeIndex;\n}\n"],"names":["value"],"mappings":"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"}