@grafana/ui
Version:
Grafana Components Library
1 lines • 16.2 kB
Source Map (JSON)
{"version":3,"file":"DataLinkInput.mjs","sources":["../../../../src/components/DataLinks/DataLinkInput.tsx"],"sourcesContent":["import { css, cx } from '@emotion/css';\nimport { autoUpdate, flip, offset, shift, 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 { 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 flip({\n fallbackAxisSideDirection: 'start',\n // see https://floating-ui.com/docs/flip#combining-with-shift\n crossAxis: false,\n boundary: document.body,\n }),\n shift(),\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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"}