{"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/lib/usePrevious';\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';\nimport { useStyles2 } from '../../themes';\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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsBA,MAAM,MAAA,GAAS,CAAC,CAAW,EAAA,CAAA,KAAc,IAAI,CAAI,GAAA,IAAA,CAAK,KAAM,CAAA,CAAA,GAAI,CAAC,CAAA;AASjE,MAAM,eAA2B,GAAA;AAAA,EAC/B,eAAiB,EAAA;AAAA,IACf,OAAS,EAAA;AAAA;AAEb,CAAA;AAEA,MAAM,OAAU,GAAA;AAAA,EACd,UAAA;AAAA,IACE;AAAA,MACE,QAAQ,CAAC,IAAA,KAAS,MAAU,IAAA,IAAA,IAAQ,KAAK,IAAS,KAAA,YAAA;AAAA,MAClD,WAAW,MAAM;AAAA,KACnB;AAAA,IACA,EAAE,GAAI,KAAM,CAAA,SAAA,EAA2B,OAAO,eAAgB;AAAA;AAElE,CAAA;AAEA,MAAM,SAAA,GAAY,CAAC,KAA0B,MAAA;AAAA,EAC3C,OAAO,cAAe,CAAA,EAAE,OAAO,OAAS,EAAA,KAAA,EAAO,CAAE,CAAA,KAAA;AAAA,EACjD,QAAQ,GAAI,CAAA;AAAA,IACV,wBAA0B,EAAA;AAAA,MACxB,KAAA,EAAO,KAAM,CAAA,MAAA,CAAO,OAAQ,CAAA;AAAA,KAC9B;AAAA,IACA,iBAAmB,EAAA;AAAA,MACjB,KAAA,EAAO,KAAM,CAAA,MAAA,CAAO,OAAQ,CAAA;AAAA;AAC9B,GACD,CAAA;AAAA,EACD,oBAAoB,GAAI,CAAA;AAAA,IACtB,SAAA,EAAW,MAAM,OAAQ,CAAA;AAAA,GAC1B,CAAA;AAAA;AAAA;AAAA,EAGD,kBAAkB,GAAI,CAAA;AAAA,IACpB,KAAO,EAAA,MAAA;AAAA,IACP,+BAAiC,EAAA;AAAA,MAC/B,OAAS,EAAA,CAAA;AAAA,MACT,eAAiB,EAAA,aAAA;AAAA,MACjB,MAAQ,EAAA;AAAA;AACV,GACD;AACH,CAAA,CAAA;AAIO,MAAM,aAAgB,GAAA,IAAA;AAAA,EAC3B,CAAC;AAAA,IACC,KAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAA;AAAA,IACA,WAAc,GAAA;AAAA,GACU,KAAA;AACxB,IAAM,MAAA,SAAA,GAAY,OAAe,IAAI,CAAA;AACrC,IAAM,MAAA,MAAA,GAAS,WAAW,SAAS,CAAA;AACnC,IAAA,MAAM,CAAC,kBAAA,EAAoB,qBAAqB,CAAA,GAAI,SAAS,KAAK,CAAA;AAClE,IAAA,MAAM,CAAC,gBAAA,EAAkB,mBAAmB,CAAA,GAAI,SAAS,CAAC,CAAA;AAC1D,IAAA,MAAM,CAAC,OAAS,EAAA,UAAU,IAAI,QAAgB,CAAA,SAAA,CAAU,KAAK,CAAC,CAAA;AAC9D,IAAM,MAAA,WAAA,GAAc,YAAmB,OAAO,CAAA;AAC9C,IAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAS,CAAC,CAAA;AAC5C,IAAM,MAAA,SAAA,GAAY,OAAuB,IAAI,CAAA;AAE7C,IAAA,SAAA,CAAU,MAAM;AA1FpB,MAAA,IAAA,EAAA;AA2FM,MAAU,CAAA,EAAA,GAAA,SAAA,CAAA,OAAA,KAAV,IAAmB,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,QAAA,CAAS,CAAG,EAAA,SAAA,CAAA;AAAA,KACjC,EAAG,CAAC,SAAS,CAAC,CAAA;AAGd,IAAA,MAAM,UAAa,GAAA;AAAA,MACjB,MAAO,CAAA,CAAC,EAAE,KAAA,EAAa,MAAA;AAAA,QACrB,aAAA,EAAe,MAAM,SAAU,CAAA;AAAA,OAC/B,CAAA,CAAA;AAAA,MACF,IAAK,CAAA;AAAA,QACH,yBAA2B,EAAA,OAAA;AAAA;AAAA,QAE3B,SAAW,EAAA,KAAA;AAAA,QACX,UAAU,QAAS,CAAA;AAAA,OACpB,CAAA;AAAA,MACD,KAAM;AAAA,KACR;AAEA,IAAA,MAAM,EAAE,IAAA,EAAM,cAAe,EAAA,GAAI,WAAY,CAAA;AAAA,MAC3C,IAAM,EAAA,kBAAA;AAAA,MACN,SAAW,EAAA,cAAA;AAAA,MACX,YAAc,EAAA,qBAAA;AAAA,MACd,UAAA;AAAA,MACA,oBAAsB,EAAA,UAAA;AAAA,MACtB,QAAU,EAAA;AAAA,KACX,CAAA;AAGD,IAAM,MAAA,QAAA,GAAW,OAAO,EAAE,kBAAA,EAAoB,aAAa,gBAAkB,EAAA,OAAA,EAAS,UAAU,CAAA;AAChG,IAAA,QAAA,CAAS,UAAU,EAAE,kBAAA,EAAoB,WAAa,EAAA,gBAAA,EAAkB,SAAS,QAAS,EAAA;AAG1F,IAAM,MAAA,SAAA,GAAY,OAAuB,IAAI,CAAA;AAC7C,IAAA,SAAA,CAAU,MAAM;AACd,MAAA,YAAA,CAAa,kBAAmB,CAAA,SAAA,CAAU,OAAS,EAAA,gBAAgB,CAAC,CAAA;AAAA,KACtE,EAAG,CAAC,gBAAgB,CAAC,CAAA;AAErB,IAAA,MAAM,SAAY,GAAA,KAAA,CAAM,WAAY,CAAA,CAAC,OAA4B,IAAqB,KAAA;AACpF,MAAI,IAAA,CAAC,QAAS,CAAA,OAAA,CAAQ,kBAAoB,EAAA;AACxC,QAAI,IAAA,KAAA,CAAM,GAAQ,KAAA,GAAA,IAAO,KAAM,CAAA,GAAA,KAAQ,OAAQ,KAAM,CAAA,OAAA,KAAY,EAAM,IAAA,KAAA,CAAM,OAAU,EAAA;AACrF,UAAM,MAAA,YAAA,GAAe,IAAI,kBAAmB,EAAA;AAC5C,UAAA,IAAA,CAAK,aAAa,YAAY,CAAA;AAC9B,UAAA,OAAO,sBAAsB,IAAI,CAAA;AAAA;AAEnC,QAAA,OAAO,IAAK,EAAA;AAAA;AAGd,MAAA,QAAQ,MAAM,GAAK;AAAA,QACjB,KAAK,WAAA;AACH,UAAA,IAAI,SAAS,OAAQ,CAAA,OAAA,CAAQ,UAAU,OAAQ,EAAA,CAAE,WAAW,CAAG,EAAA;AAC7D,YAAK,IAAA,EAAA;AAAA;AACP,QACF,KAAK,QAAA;AACH,UAAA,qBAAA,CAAsB,KAAK,CAAA;AAC3B,UAAA,OAAO,oBAAoB,CAAC,CAAA;AAAA,QAE9B,KAAK,OAAA;AACH,UAAA,KAAA,CAAM,cAAe,EAAA;AACrB,UAAA,OAAO,iBAAiB,QAAS,CAAA,OAAA,CAAQ,YAAY,QAAS,CAAA,OAAA,CAAQ,gBAAgB,CAAC,CAAA;AAAA,QAEzF,KAAK,WAAA;AAAA,QACL,KAAK,SAAA;AACH,UAAA,KAAA,CAAM,cAAe,EAAA;AACrB,UAAA,MAAM,SAAY,GAAA,KAAA,CAAM,GAAQ,KAAA,WAAA,GAAc,CAAI,GAAA,CAAA,CAAA;AAClD,UAAO,OAAA,mBAAA,CAAoB,CAAC,KAAA,KAAU,MAAO,CAAA,KAAA,GAAQ,WAAW,QAAS,CAAA,OAAA,CAAQ,WAAY,CAAA,MAAM,CAAC,CAAA;AAAA,QACtG;AACE,UAAA,OAAO,IAAK,EAAA;AAAA;AAChB,KAEF,EAAG,EAAE,CAAA;AAEL,IAAA,SAAA,CAAU,MAAM;AAId,MAAA,IAAI,eAAe,WAAY,CAAA,SAAA,CAAU,aAAa,CAAC,OAAA,CAAQ,UAAU,SAAW,EAAA;AAClF,QAAA,QAAA,CAAS,OAAQ,CAAA,QAAA,CAAS,KAAM,CAAA,SAAA,CAAU,OAAO,CAAC,CAAA;AAAA;AACpD,KACC,EAAA,CAAC,OAAS,EAAA,WAAW,CAAC,CAAA;AAEzB,IAAA,MAAM,cAAc,KAAM,CAAA,WAAA,CAAY,CAAC,EAAE,KAAA,EAAAA,QAA8B,KAAA;AACrE,MAAA,UAAA,CAAWA,MAAK,CAAA;AAAA,KAClB,EAAG,EAAE,CAAA;AAEL,IAAA,MAAM,gBAAmB,GAAA,CAAC,IAA0B,EAAA,MAAA,GAAS,UAAU,OAAa,KAAA;AAClF,MAAA,MAAM,gBAAwB,wBAAyB,EAAA;AACvD,MAAA,MAAM,kBAAkB,aAAkB,KAAA,GAAA;AAC1C,MAAA,IAAI,KAAK,MAAW,KAAA,cAAA,CAAe,YAAY,IAAK,CAAA,KAAA,KAAU,oBAAoB,WAAa,EAAA;AAC7F,QAAO,MAAA,CAAA,UAAA,CAAW,GAAG,eAAkB,GAAA,EAAA,GAAK,GAAG,CAAK,CAAA,EAAA,IAAA,CAAK,KAAK,CAAG,CAAA,CAAA,CAAA;AAAA,OAC5D,MAAA;AACL,QAAO,MAAA,CAAA,UAAA,CAAW,GAAG,eAAkB,GAAA,EAAA,GAAK,GAAG,CAAK,CAAA,EAAA,IAAA,CAAK,KAAK,CAAc,YAAA,CAAA,CAAA;AAAA;AAG9E,MAAA,UAAA,CAAW,OAAO,KAAK,CAAA;AACvB,MAAA,qBAAA,CAAsB,KAAK,CAAA;AAE3B,MAAA,mBAAA,CAAoB,CAAC,CAAA;AACrB,MAAA,QAAA,CAAS,QAAQ,QAAS,CAAA,KAAA,CAAM,SAAU,CAAA,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,KACzD;AAEA,IAAA,MAAM,2BAA2B,MAAM;AACrC,MAAM,MAAA,KAAA,GAAgC,QAAS,CAAA,cAAA,CAAe,iBAAiB,CAAA;AAC/E,MAAI,IAAA,aAAA,GAAgB,IAClB,GACA,EAAA,KAAA;AACF,MAAA,IAAI,OAAO,YAAc,EAAA;AACvB,QAAA,GAAA,GAAM,OAAO,YAAa,EAAA;AAC1B,QAAI,IAAA,GAAA,IAAO,GAAI,CAAA,UAAA,GAAa,CAAG,EAAA;AAC7B,UAAA,KAAA,GAAQ,GAAI,CAAA,UAAA,CAAW,CAAC,CAAA,CAAE,UAAW,EAAA;AAErC,UAAA,KAAA,CAAM,SAAS,IAAI,CAAA;AACnB,UAAM,KAAA,CAAA,QAAA,CAAS,OAAO,CAAC,CAAA;AACvB,UAAA,aAAA,GAAgB,KAAM,CAAA,QAAA,EAAW,CAAA,KAAA,CAAM,CAAE,CAAA,CAAA;AAAA;AAC3C;AAEF,MAAO,OAAA,aAAA;AAAA,KACT;AAEA,IAAA,uBACG,GAAA,CAAA,KAAA,EAAA,EAAI,SAAW,EAAA,MAAA,CAAO,kBACrB,QAAC,kBAAA,GAAA,CAAA,KAAA,EAAA,EAAI,SAAU,EAAA,4BAAA,EACb,QAAC,kBAAA,IAAA,CAAA,KAAA,EAAA,EAAI,EAAG,EAAA,iBAAA,EAAkB,WAAU,mBACjC,EAAA,QAAA,EAAA;AAAA,MACC,kBAAA,oBAAA,GAAA,CAAC,UACC,QAAC,kBAAA,GAAA,CAAA,KAAA,EAAA,EAAI,KAAK,IAAK,CAAA,WAAA,EAAa,OAAO,cACjC,EAAA,QAAA,kBAAA,GAAA;AAAA,QAAC,eAAA;AAAA,QAAA;AAAA,UACC,SAAU,EAAA,OAAA;AAAA,UACV,GAAK,EAAA,SAAA;AAAA,UACL,UAAU,CAAC,KAAA,KAAU,YAAa,CAAA,KAAA,CAAM,cAAc,SAAS,CAAA;AAAA,UAE/D,QAAA,kBAAA,GAAA;AAAA,YAAC,mBAAA;AAAA,YAAA;AAAA,cACC,SAAA;AAAA,cACA,WAAA,EAAa,SAAS,OAAQ,CAAA,WAAA;AAAA,cAC9B,kBAAoB,EAAA,gBAAA;AAAA,cACpB,OAAA,EAAS,MAAM,qBAAA,CAAsB,KAAK,CAAA;AAAA,cAC1C,WAAa,EAAA;AAAA;AAAA;AACf;AAAA,SAEJ,CACF,EAAA,CAAA;AAAA,sBAEF,GAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,MAAQ,EAAA,MAAA;AAAA,UACR,GAAK,EAAA,SAAA;AAAA,UACL,WAAA;AAAA,UACA,KAAA,EAAO,SAAS,OAAQ,CAAA,OAAA;AAAA,UACxB,QAAU,EAAA,WAAA;AAAA,UACV,WAAW,CAAC,KAAA,EAAO,SAAS,IAAS,KAAA,SAAA,CAAU,OAAO,IAAI,CAAA;AAAA,UAC1D,OAAA;AAAA,UACA,SAAW,EAAA,EAAA;AAAA,YACT,MAAO,CAAA,MAAA;AAAA,YACP,MAAO,CAAA,KAAA;AAAA,YACP,GAAI,CAAA;AAAA,cACF,OAAS,EAAA;AAAA,aACV;AAAA;AACH;AAAA;AACF,KAAA,EACF,GACF,CACF,EAAA,CAAA;AAAA;AAGN;AAEA,aAAA,CAAc,WAAc,GAAA,eAAA;AAE5B,SAAS,kBAAA,CAAmB,mBAAuC,WAAqB,EAAA;AAhQxF,EAAA,IAAA,EAAA;AAiQE,EAAQ,OAAA,CAAA,CAAA,EAAA,GAAA,iBAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,iBAAA,CAAmB,YAAnB,KAAA,IAAA,GAAA,EAAA,GAAmC,CAAK,IAAA,WAAA;AAClD;;;;"}