(null);\n const { languageProvider, history, onBlur, onRunQuery, initialValue, placeholder, onChange, datasource } = props;\n\n const lpRef = useLatest(languageProvider);\n const historyRef = useLatest(history);\n const onRunQueryRef = useLatest(onRunQuery);\n const onBlurRef = useLatest(onBlur);\n const onChangeRef = useLatest(onChange);\n\n const autocompleteDisposeFun = useRef<(() => void) | null>(null);\n\n const theme = useTheme2();\n const styles = getStyles(theme, placeholder);\n\n useEffect(() => {\n // when we unmount, we unregister the autocomplete-function, if it was registered\n return () => {\n autocompleteDisposeFun.current?.();\n };\n }, []);\n\n return (\n \n {\n ensurePromQL(monaco);\n }}\n onMount={(editor, monaco) => {\n const isEditorFocused = editor.createContextKey('isEditorFocused' + id, false);\n // we setup on-blur\n editor.onDidBlurEditorWidget(() => {\n isEditorFocused.set(false);\n onBlurRef.current(editor.getValue());\n });\n editor.onDidFocusEditorText(() => {\n isEditorFocused.set(true);\n });\n\n // we construct a DataProvider object\n const getHistory = () =>\n Promise.resolve(historyRef.current.map((h) => h.query.expr).filter((expr) => expr !== undefined));\n\n const getAllMetricNames = () => {\n const { metrics, metricsMetadata } = lpRef.current;\n const result = metrics.map((m) => {\n const metaItem = metricsMetadata?.[m];\n return {\n name: m,\n help: metaItem?.help ?? '',\n type: metaItem?.type ?? '',\n };\n });\n\n return Promise.resolve(result);\n };\n\n const getAllLabelNames = () => Promise.resolve(lpRef.current.getLabelKeys());\n\n const getLabelValues = (labelName: string) => lpRef.current.getLabelValues(labelName);\n\n const getSeriesValues = lpRef.current.getSeriesValues;\n\n const getSeriesLabels = lpRef.current.getSeriesLabels;\n\n const dataProvider = {\n getHistory,\n getAllMetricNames,\n getAllLabelNames,\n getLabelValues,\n getSeriesValues,\n getSeriesLabels,\n };\n const completionProvider = getCompletionProvider(monaco, dataProvider);\n\n // completion-providers in monaco are not registered directly to editor-instances,\n // they are registered to languages. this makes it hard for us to have\n // separate completion-providers for every query-field-instance\n // (but we need that, because they might connect to different datasources).\n // the trick we do is, we wrap the callback in a \"proxy\",\n // and in the proxy, the first thing is, we check if we are called from\n // \"our editor instance\", and if not, we just return nothing. if yes,\n // we call the completion-provider.\n const filteringCompletionProvider: monacoTypes.languages.CompletionItemProvider = {\n ...completionProvider,\n provideCompletionItems: (model, position, context, token) => {\n // if the model-id does not match, then this call is from a different editor-instance,\n // not \"our instance\", so return nothing\n if (editor.getModel()?.id !== model.id) {\n return { suggestions: [] };\n }\n return completionProvider.provideCompletionItems(model, position, context, token);\n },\n };\n\n const { dispose } = monaco.languages.registerCompletionItemProvider(\n PROMQL_LANG_ID,\n filteringCompletionProvider\n );\n\n autocompleteDisposeFun.current = dispose;\n // this code makes the editor resize itself so that the content fits\n // (it will grow taller when necessary)\n // FIXME: maybe move this functionality into CodeEditor, like:\n // \n const updateElementHeight = () => {\n const containerDiv = containerRef.current;\n if (containerDiv !== null) {\n const pixelHeight = editor.getContentHeight();\n containerDiv.style.height = `${pixelHeight + EDITOR_HEIGHT_OFFSET}px`;\n containerDiv.style.width = '100%';\n const pixelWidth = containerDiv.clientWidth;\n editor.layout({ width: pixelWidth, height: pixelHeight });\n }\n };\n\n editor.onDidContentSizeChange(updateElementHeight);\n updateElementHeight();\n\n // Whenever the editor changes, lets save the last value so the next query for this editor will be up-to-date.\n // This change is being introduced to fix a bug where you can submit a query via shift+enter:\n // If you clicked into another field and haven't un-blurred the active field,\n // then the query that is run will be stale, as the reference is only updated\n // with the value of the last blurred input.\n // This can run quite slowly, so we're debouncing this which should accomplish two things\n // 1. Should prevent this function from blocking the current call stack by pushing into the web API callback queue\n // 2. Should prevent a bunch of duplicates of this function being called as the user is typing\n const updateCurrentEditorValue = debounce(() => {\n const editorValue = editor.getValue();\n onChangeRef.current(editorValue);\n }, lpRef.current.datasource.getDebounceTimeInMilliseconds());\n\n editor.getModel()?.onDidChangeContent(() => {\n updateCurrentEditorValue();\n });\n\n // handle: shift + enter\n // FIXME: maybe move this functionality into CodeEditor?\n editor.addCommand(\n monaco.KeyMod.Shift | monaco.KeyCode.Enter,\n () => {\n onRunQueryRef.current(editor.getValue());\n },\n 'isEditorFocused' + id\n );\n\n /* Something in this configuration of monaco doesn't bubble up [mod]+K, which the\n command palette uses. Pass the event out of monaco manually\n */\n editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyK, function () {\n global.dispatchEvent(new KeyboardEvent('keydown', { key: 'k', metaKey: true }));\n });\n\n if (placeholder) {\n const placeholderDecorators = [\n {\n range: new monaco.Range(1, 1, 1, 1),\n options: {\n className: styles.placeholder,\n isWholeLine: true,\n },\n },\n ];\n\n let decorators: string[] = [];\n\n const checkDecorators: () => void = () => {\n const model = editor.getModel();\n\n if (!model) {\n return;\n }\n\n const newDecorators = model.getValueLength() === 0 ? placeholderDecorators : [];\n decorators = model.deltaDecorations(decorators, newDecorators);\n };\n\n checkDecorators();\n editor.onDidChangeModelContent(checkDecorators);\n\n editor.onDidChangeModelContent((e) => {\n const model = editor.getModel();\n if (!model) {\n return;\n }\n const query = model.getValue();\n const errors =\n validateQuery(\n query,\n datasource.interpolateString(query, placeHolderScopedVars),\n model.getLinesContent(),\n parser\n ) || [];\n\n const markers = errors.map(({ error, ...boundary }) => ({\n message: `${\n error ? `Error parsing \"${error}\"` : 'Parse error'\n }. The query appears to be incorrect and could fail to be executed.`,\n severity: monaco.MarkerSeverity.Error,\n ...boundary,\n }));\n\n monaco.editor.setModelMarkers(model, 'owner', markers);\n });\n }\n }}\n />\n
\n );\n};\n\n// we will lazy-load this module using React.lazy,\n// and that only supports default-exports,\n// so we have to default-export this, even if\n// it is against the style-guidelines.\n\nexport default MonacoQueryField;\n","import { useRef } from 'react';\nvar useLatest = function (value) {\n var ref = useRef(value);\n ref.current = value;\n return ref;\n};\nexport default useLatest;\n"],"names":["validateQuery","query","interpolatedQuery","queryLines","parser","interpolatedErrors","parseQuery","parseErrors","queryErrors","interpolatedError","queryError","parseError","findErrorBoundary","isErrorBoundary","nodeRef","node","isEmptyString","errorNode","error","startPos","endPos","line","boundary","placeHolderScopedVars","ErrorId","getLeftMostChild","cur","makeError","expr","getString","variableRegex","replaceVariables","match","var1","var2","fmt2","var3","fieldPath","fmt3","fmt","variable","varType","varTypeFunc","v","f","returnVariables","type","makeBinOp","opDef","numberNode","hasBool","params","getAllByType","values","pos","child","regexifyLabelValuesQueryString","promLanguageDefinition","makeStorageService","strings","data","key","scope","fallbackValue","val","value","target","reason","overrideServices","getOverrideServices","NeverCaseError","getAllMetricNamesCompletions","dataProvider","metric","FUNCTION_COMPLETIONS","getAllFunctionsAndMetricNamesCompletions","metricNames","DURATION_COMPLETIONS","text","getAllHistoryCompletions","makeSelector","metricName","labels","allLabels","label","getLabelNames","otherLabels","selector","getLabelNamesForCompletions","suffix","triggerOnInsert","getLabelNamesForSelectorCompletions","getLabelNamesForByCompletions","getLabelValues","labelName","getLabelValuesForMetricCompletions","betweenQuotes","getCompletions","situation","move","direction","walk","path","current","expectedType","getNodeText","parsePromQLStringLiteral","inside","isPathMatch","resolverPath","cursorPath","item","index","ERROR_NODE_NAME","RESOLVERS","resolveLabelKeysWithEquals","resolveTopLevel","resolveInFunction","resolveLabelMatcher","resolveDurations","resolveLabelsForGrouping","LABEL_OP_MAP","getLabelOp","opNode","opChild","getLabel","labelMatcherNode","nameNode","op","valueNode","name","getLabels","labelMatchersNode","listNode","matcherNode","getNodeChildren","children","getNodeInSubtree","typeId","n","aggrExpNode","bodyNode","metricIdNode","idNode","inStringNode","parent","labelNameNode","firstListNode","p","id","metricNameNode","subTreeHasError","getErrorNode","tree","getSituation","maybeErrorNode","currentNode","ids","resolver","getSuggestOptions","getMonacoCompletionItemKind","monaco","getCompletionProvider","model","position","word","range","positionClone","selectedText","offset","items","maxIndexDigits","options","EDITOR_HEIGHT_OFFSET","PROMQL_LANG_ID","PROMQL_SETUP_STARTED","ensurePromQL","aliases","extensions","mimetypes","loader","mod","getStyles","theme","placeholder","props","overrideServicesRef","containerRef","languageProvider","history","onBlur","onRunQuery","initialValue","onChange","datasource","lpRef","useLatest","historyRef","onRunQueryRef","onBlurRef","onChangeRef","autocompleteDisposeFun","styles","selectors","editor","isEditorFocused","getHistory","h","getAllMetricNames","metrics","metricsMetadata","result","m","metaItem","getAllLabelNames","getSeriesValues","getSeriesLabels","completionProvider","filteringCompletionProvider","context","token","dispose","updateElementHeight","containerDiv","pixelHeight","pixelWidth","updateCurrentEditorValue","editorValue","placeholderDecorators","decorators","checkDecorators","newDecorators","e","markers","ref"],"sourceRoot":""}