@grafana/ui
Version:
Grafana Components Library
1 lines • 19.3 kB
Source Map (JSON)
{"version":3,"file":"suggestions.mjs","sources":["../../../src/slate-plugins/suggestions.tsx"],"sourcesContent":["import { debounce, sortBy } from 'lodash';\nimport { Editor, Plugin as SlatePlugin } from 'slate-react';\n\nimport { BootData } from '@grafana/data';\n\nimport { Typeahead } from '../components/Typeahead/Typeahead';\nimport { CompletionItem, SuggestionsState, TypeaheadInput, TypeaheadOutput } from '../types/completion';\nimport { SearchFunctionType, SearchFunctionMap } from '../utils/searchFunctions';\nimport { makeFragment } from '../utils/slate';\n\nimport TOKEN_MARK from './slate-prism/TOKEN_MARK';\n\nexport const TYPEAHEAD_DEBOUNCE = 250;\n\ndeclare global {\n interface Window {\n grafanaBootData?: BootData;\n }\n}\n\n// Commands added to the editor by this plugin.\ninterface SuggestionsPluginCommands {\n selectSuggestion: (suggestion: CompletionItem) => Editor;\n applyTypeahead: (suggestion: CompletionItem) => Editor;\n}\n\nexport function SuggestionsPlugin({\n onTypeahead,\n cleanText,\n onWillApplySuggestion,\n portalOrigin,\n}: {\n onTypeahead?: (typeahead: TypeaheadInput) => Promise<TypeaheadOutput>;\n cleanText?: (text: string) => string;\n onWillApplySuggestion?: (suggestion: string, state: SuggestionsState) => string;\n portalOrigin: string;\n}): SlatePlugin {\n let typeaheadRef: Typeahead;\n let state: SuggestionsState = {\n groupedItems: [],\n typeaheadPrefix: '',\n typeaheadContext: '',\n typeaheadText: '',\n };\n const handleTypeaheadDebounced = debounce(handleTypeahead, TYPEAHEAD_DEBOUNCE);\n\n const setState = (update: Partial<SuggestionsState>) => {\n state = {\n ...state,\n ...update,\n };\n };\n\n return {\n onBlur: (event, editor, next) => {\n state = {\n ...state,\n groupedItems: [],\n };\n\n return next();\n },\n\n onClick: (event, editor, next) => {\n state = {\n ...state,\n groupedItems: [],\n };\n\n return next();\n },\n\n onKeyDown: (event, editor, next) => {\n const currentSuggestions = state.groupedItems;\n\n const hasSuggestions = currentSuggestions.length;\n\n switch (event.key) {\n case 'Escape': {\n if (hasSuggestions) {\n event.preventDefault();\n\n state = {\n ...state,\n groupedItems: [],\n };\n\n // Bogus edit to re-render editor\n return editor.insertText('');\n }\n\n break;\n }\n\n case 'ArrowDown':\n case 'ArrowUp':\n if (hasSuggestions) {\n event.preventDefault();\n typeaheadRef.moveMenuIndex(event.key === 'ArrowDown' ? 1 : -1);\n return;\n }\n\n break;\n\n case 'Enter': {\n if (!(event.shiftKey || event.ctrlKey) && hasSuggestions) {\n event.preventDefault();\n return typeaheadRef.insertSuggestion();\n }\n\n break;\n }\n\n case 'Tab': {\n if (hasSuggestions) {\n event.preventDefault();\n return typeaheadRef.insertSuggestion();\n }\n\n break;\n }\n\n default: {\n // Don't react on meta keys\n if (event.key.length === 1) {\n handleTypeaheadDebounced(editor, setState, onTypeahead, cleanText);\n }\n break;\n }\n }\n\n return next();\n },\n\n commands: {\n selectSuggestion: (editor, suggestion: CompletionItem): Editor => {\n const suggestions = state.groupedItems;\n if (!suggestions || !suggestions.length) {\n return editor;\n }\n\n // @ts-ignore\n const ed = editor.applyTypeahead(suggestion);\n handleTypeaheadDebounced(editor, setState, onTypeahead, cleanText);\n return ed;\n },\n\n applyTypeahead: (editor, suggestion: CompletionItem) => {\n let suggestionText = suggestion.insertText || suggestion.label;\n\n const preserveSuffix = suggestion.kind === 'function';\n const move = suggestion.move || 0;\n const moveForward = move > 0 ? move : 0;\n const moveBackward = move < 0 ? -move : 0;\n\n const { typeaheadPrefix, typeaheadText, typeaheadContext } = state;\n\n if (onWillApplySuggestion) {\n suggestionText = onWillApplySuggestion(suggestionText, {\n groupedItems: state.groupedItems,\n typeaheadContext,\n typeaheadPrefix,\n typeaheadText,\n });\n }\n\n const { forward, backward } = getNumCharsToDelete(\n suggestionText,\n typeaheadPrefix,\n typeaheadText,\n preserveSuffix,\n suggestion.deleteBackwards,\n cleanText\n );\n\n // If new-lines, apply suggestion as block\n if (suggestionText.match(/\\n/)) {\n const fragment = makeFragment(suggestionText);\n editor.deleteBackward(backward).deleteForward(forward).insertFragment(fragment).focus();\n return editor;\n }\n\n state = {\n ...state,\n groupedItems: [],\n };\n\n editor\n .snapshotSelection()\n .deleteBackward(backward)\n .deleteForward(forward)\n .insertText(suggestionText)\n .moveForward(moveForward)\n .moveBackward(moveBackward)\n .focus();\n\n return editor;\n },\n },\n\n renderEditor(props, editor, next) {\n if (editor.value.selection.isExpanded) {\n return next();\n }\n\n const children = next();\n\n return (\n <>\n {children}\n <Typeahead\n menuRef={(menu: Typeahead) => (typeaheadRef = menu)}\n origin={portalOrigin}\n prefix={state.typeaheadPrefix}\n isOpen={!!state.groupedItems.length}\n groupedItems={state.groupedItems}\n onSelectSuggestion={(editor as Editor & SuggestionsPluginCommands).selectSuggestion}\n />\n </>\n );\n },\n };\n}\n\nconst handleTypeahead = async (\n editor: Editor,\n onStateChange: (state: Partial<SuggestionsState>) => void,\n onTypeahead?: (typeahead: TypeaheadInput) => Promise<TypeaheadOutput>,\n cleanText?: (text: string) => string\n): Promise<void> => {\n if (!onTypeahead) {\n return;\n }\n\n const { value } = editor;\n const { selection } = value;\n\n // Get decorations associated with the current line\n const parentBlock = value.document.getClosestBlock(value.focusBlock.key);\n const selectionStartOffset = value.selection.start.offset - 1;\n const decorations = parentBlock && parentBlock.getDecorations(editor as any);\n\n const filteredDecorations = decorations\n ? decorations\n .filter(\n (decoration) =>\n decoration!.start.offset <= selectionStartOffset &&\n decoration!.end.offset > selectionStartOffset &&\n decoration!.type === TOKEN_MARK\n )\n .toArray()\n : [];\n\n // Find the first label key to the left of the cursor\n const labelKeyDec =\n decorations &&\n decorations\n .filter(\n (decoration) =>\n decoration!.end.offset <= selectionStartOffset &&\n decoration!.type === TOKEN_MARK &&\n decoration!.data.get('className').includes('label-key')\n )\n .last();\n\n const labelKey = labelKeyDec && value.focusText.text.slice(labelKeyDec.start.offset, labelKeyDec.end.offset);\n\n const wrapperClasses = filteredDecorations\n .map((decoration) => decoration.data.get('className'))\n .join(' ')\n .split(' ')\n .filter((className) => className.length);\n\n let text = value.focusText.text;\n let prefix = text.slice(0, selection.focus.offset);\n\n if (filteredDecorations.length) {\n text = value.focusText.text.slice(filteredDecorations[0].start.offset, filteredDecorations[0].end.offset);\n prefix = value.focusText.text.slice(filteredDecorations[0].start.offset, selection.focus.offset);\n }\n\n // Label values could have valid characters erased if `cleanText()` is\n // blindly applied, which would undesirably interfere with suggestions\n const labelValueMatch = prefix.match(/(?:!?=~?\"?|\")(.*)/);\n if (labelValueMatch) {\n prefix = labelValueMatch[1];\n } else if (cleanText) {\n prefix = cleanText(prefix);\n }\n\n const { suggestions, context } = await onTypeahead({\n prefix,\n text,\n value,\n wrapperClasses,\n labelKey: labelKey || undefined,\n editor,\n });\n\n const filteredSuggestions = suggestions\n .map((group) => {\n if (!group.items) {\n return group;\n }\n // Falling back to deprecated prefixMatch to support backwards compatibility with plugins using this property\n const searchFunctionType =\n group.searchFunctionType || (group.prefixMatch ? SearchFunctionType.Prefix : SearchFunctionType.Word);\n const searchFunction = SearchFunctionMap[searchFunctionType];\n let newGroup = { ...group };\n if (prefix) {\n // Filter groups based on prefix\n if (!group.skipFilter) {\n newGroup.items = newGroup.items.filter((c) => (c.filterText || c.label).length >= prefix.length);\n newGroup.items = searchFunction(newGroup.items, prefix);\n }\n\n // Filter out the already typed value (prefix) unless it inserts custom text not matching the prefix\n newGroup.items = newGroup.items.filter(\n (c) => !(c.insertText === prefix || (c.filterText ?? c.label) === prefix)\n );\n }\n\n if (!group.skipSort) {\n newGroup.items = sortBy(newGroup.items, (item: CompletionItem) => {\n if (item.sortText === undefined) {\n return item.sortValue !== undefined ? item.sortValue : item.label;\n } else {\n // Falling back to deprecated sortText to support backwards compatibility with plugins using this property\n return item.sortText || item.label;\n }\n });\n }\n\n return newGroup;\n })\n .filter((gr) => gr.items && gr.items.length); // Filter out empty groups\n\n onStateChange({\n groupedItems: filteredSuggestions,\n typeaheadPrefix: prefix,\n typeaheadContext: context,\n typeaheadText: text,\n });\n\n // Bogus edit to force re-render\n editor.blur().focus();\n};\n\nexport function getNumCharsToDelete(\n suggestionText: string,\n typeaheadPrefix: string,\n typeaheadText: string,\n preserveSuffix: boolean,\n deleteBackwards?: number,\n cleanText?: (text: string) => string\n) {\n // remove the current, incomplete text and replace it with the selected suggestion\n const backward = deleteBackwards || typeaheadPrefix.length;\n const text = cleanText ? cleanText(typeaheadText) : typeaheadText;\n const offset = typeaheadText.indexOf(typeaheadPrefix);\n\n const suffixLength =\n offset > -1 ? text.length - offset - typeaheadPrefix.length : text.length - typeaheadPrefix.length;\n const midWord = Boolean((typeaheadPrefix && suffixLength > 0) || suggestionText === typeaheadText);\n const forward = midWord && !preserveSuffix ? suffixLength + offset : 0;\n\n return {\n forward,\n backward,\n };\n}\n"],"names":[],"mappings":";;;;;;;AAYO,MAAM,kBAAqB,GAAA;AAc3B,SAAS,iBAAkB,CAAA;AAAA,EAChC,WAAA;AAAA,EACA,SAAA;AAAA,EACA,qBAAA;AAAA,EACA;AACF,CAKgB,EAAA;AACd,EAAI,IAAA,YAAA;AACJ,EAAA,IAAI,KAA0B,GAAA;AAAA,IAC5B,cAAc,EAAC;AAAA,IACf,eAAiB,EAAA,EAAA;AAAA,IACjB,gBAAkB,EAAA,EAAA;AAAA,IAClB,aAAe,EAAA;AAAA,GACjB;AACA,EAAM,MAAA,wBAAA,GAA2B,QAAS,CAAA,eAAA,EAAiB,kBAAkB,CAAA;AAE7E,EAAM,MAAA,QAAA,GAAW,CAAC,MAAsC,KAAA;AACtD,IAAQ,KAAA,GAAA;AAAA,MACN,GAAG,KAAA;AAAA,MACH,GAAG;AAAA,KACL;AAAA,GACF;AAEA,EAAO,OAAA;AAAA,IACL,MAAQ,EAAA,CAAC,KAAO,EAAA,MAAA,EAAQ,IAAS,KAAA;AAC/B,MAAQ,KAAA,GAAA;AAAA,QACN,GAAG,KAAA;AAAA,QACH,cAAc;AAAC,OACjB;AAEA,MAAA,OAAO,IAAK,EAAA;AAAA,KACd;AAAA,IAEA,OAAS,EAAA,CAAC,KAAO,EAAA,MAAA,EAAQ,IAAS,KAAA;AAChC,MAAQ,KAAA,GAAA;AAAA,QACN,GAAG,KAAA;AAAA,QACH,cAAc;AAAC,OACjB;AAEA,MAAA,OAAO,IAAK,EAAA;AAAA,KACd;AAAA,IAEA,SAAW,EAAA,CAAC,KAAO,EAAA,MAAA,EAAQ,IAAS,KAAA;AAClC,MAAA,MAAM,qBAAqB,KAAM,CAAA,YAAA;AAEjC,MAAA,MAAM,iBAAiB,kBAAmB,CAAA,MAAA;AAE1C,MAAA,QAAQ,MAAM,GAAK;AAAA,QACjB,KAAK,QAAU,EAAA;AACb,UAAA,IAAI,cAAgB,EAAA;AAClB,YAAA,KAAA,CAAM,cAAe,EAAA;AAErB,YAAQ,KAAA,GAAA;AAAA,cACN,GAAG,KAAA;AAAA,cACH,cAAc;AAAC,aACjB;AAGA,YAAO,OAAA,MAAA,CAAO,WAAW,EAAE,CAAA;AAAA;AAG7B,UAAA;AAAA;AACF,QAEA,KAAK,WAAA;AAAA,QACL,KAAK,SAAA;AACH,UAAA,IAAI,cAAgB,EAAA;AAClB,YAAA,KAAA,CAAM,cAAe,EAAA;AACrB,YAAA,YAAA,CAAa,aAAc,CAAA,KAAA,CAAM,GAAQ,KAAA,WAAA,GAAc,IAAI,CAAE,CAAA,CAAA;AAC7D,YAAA;AAAA;AAGF,UAAA;AAAA,QAEF,KAAK,OAAS,EAAA;AACZ,UAAA,IAAI,EAAE,KAAA,CAAM,QAAY,IAAA,KAAA,CAAM,YAAY,cAAgB,EAAA;AACxD,YAAA,KAAA,CAAM,cAAe,EAAA;AACrB,YAAA,OAAO,aAAa,gBAAiB,EAAA;AAAA;AAGvC,UAAA;AAAA;AACF,QAEA,KAAK,KAAO,EAAA;AACV,UAAA,IAAI,cAAgB,EAAA;AAClB,YAAA,KAAA,CAAM,cAAe,EAAA;AACrB,YAAA,OAAO,aAAa,gBAAiB,EAAA;AAAA;AAGvC,UAAA;AAAA;AACF,QAEA,SAAS;AAEP,UAAI,IAAA,KAAA,CAAM,GAAI,CAAA,MAAA,KAAW,CAAG,EAAA;AAC1B,YAAyB,wBAAA,CAAA,MAAA,EAAQ,QAAU,EAAA,WAAA,EAAa,SAAS,CAAA;AAAA;AAEnE,UAAA;AAAA;AACF;AAGF,MAAA,OAAO,IAAK,EAAA;AAAA,KACd;AAAA,IAEA,QAAU,EAAA;AAAA,MACR,gBAAA,EAAkB,CAAC,MAAA,EAAQ,UAAuC,KAAA;AAChE,QAAA,MAAM,cAAc,KAAM,CAAA,YAAA;AAC1B,QAAA,IAAI,CAAC,WAAA,IAAe,CAAC,WAAA,CAAY,MAAQ,EAAA;AACvC,UAAO,OAAA,MAAA;AAAA;AAIT,QAAM,MAAA,EAAA,GAAK,MAAO,CAAA,cAAA,CAAe,UAAU,CAAA;AAC3C,QAAyB,wBAAA,CAAA,MAAA,EAAQ,QAAU,EAAA,WAAA,EAAa,SAAS,CAAA;AACjE,QAAO,OAAA,EAAA;AAAA,OACT;AAAA,MAEA,cAAA,EAAgB,CAAC,MAAA,EAAQ,UAA+B,KAAA;AACtD,QAAI,IAAA,cAAA,GAAiB,UAAW,CAAA,UAAA,IAAc,UAAW,CAAA,KAAA;AAEzD,QAAM,MAAA,cAAA,GAAiB,WAAW,IAAS,KAAA,UAAA;AAC3C,QAAM,MAAA,IAAA,GAAO,WAAW,IAAQ,IAAA,CAAA;AAChC,QAAM,MAAA,WAAA,GAAc,IAAO,GAAA,CAAA,GAAI,IAAO,GAAA,CAAA;AACtC,QAAA,MAAM,YAAe,GAAA,IAAA,GAAO,CAAI,GAAA,CAAC,IAAO,GAAA,CAAA;AAExC,QAAA,MAAM,EAAE,eAAA,EAAiB,aAAe,EAAA,gBAAA,EAAqB,GAAA,KAAA;AAE7D,QAAA,IAAI,qBAAuB,EAAA;AACzB,UAAA,cAAA,GAAiB,sBAAsB,cAAgB,EAAA;AAAA,YACrD,cAAc,KAAM,CAAA,YAAA;AAAA,YACpB,gBAAA;AAAA,YACA,eAAA;AAAA,YACA;AAAA,WACD,CAAA;AAAA;AAGH,QAAM,MAAA,EAAE,OAAS,EAAA,QAAA,EAAa,GAAA,mBAAA;AAAA,UAC5B,cAAA;AAAA,UACA,eAAA;AAAA,UACA,aAAA;AAAA,UACA,cAAA;AAAA,UACA,UAAW,CAAA,eAAA;AAAA,UACX;AAAA,SACF;AAGA,QAAI,IAAA,cAAA,CAAe,KAAM,CAAA,IAAI,CAAG,EAAA;AAC9B,UAAM,MAAA,QAAA,GAAW,aAAa,cAAc,CAAA;AAC5C,UAAO,MAAA,CAAA,cAAA,CAAe,QAAQ,CAAE,CAAA,aAAA,CAAc,OAAO,CAAE,CAAA,cAAA,CAAe,QAAQ,CAAA,CAAE,KAAM,EAAA;AACtF,UAAO,OAAA,MAAA;AAAA;AAGT,QAAQ,KAAA,GAAA;AAAA,UACN,GAAG,KAAA;AAAA,UACH,cAAc;AAAC,SACjB;AAEA,QAAA,MAAA,CACG,mBACA,CAAA,cAAA,CAAe,QAAQ,CAAA,CACvB,cAAc,OAAO,CAAA,CACrB,UAAW,CAAA,cAAc,EACzB,WAAY,CAAA,WAAW,EACvB,YAAa,CAAA,YAAY,EACzB,KAAM,EAAA;AAET,QAAO,OAAA,MAAA;AAAA;AACT,KACF;AAAA,IAEA,YAAA,CAAa,KAAO,EAAA,MAAA,EAAQ,IAAM,EAAA;AAChC,MAAI,IAAA,MAAA,CAAO,KAAM,CAAA,SAAA,CAAU,UAAY,EAAA;AACrC,QAAA,OAAO,IAAK,EAAA;AAAA;AAGd,MAAA,MAAM,WAAW,IAAK,EAAA;AAEtB,MAAA,uBAEK,IAAA,CAAA,QAAA,EAAA,EAAA,QAAA,EAAA;AAAA,QAAA,QAAA;AAAA,wBACD,GAAA;AAAA,UAAC,SAAA;AAAA,UAAA;AAAA,YACC,OAAA,EAAS,CAAC,IAAA,KAAqB,YAAe,GAAA,IAAA;AAAA,YAC9C,MAAQ,EAAA,YAAA;AAAA,YACR,QAAQ,KAAM,CAAA,eAAA;AAAA,YACd,MAAQ,EAAA,CAAC,CAAC,KAAA,CAAM,YAAa,CAAA,MAAA;AAAA,YAC7B,cAAc,KAAM,CAAA,YAAA;AAAA,YACpB,oBAAqB,MAA8C,CAAA;AAAA;AAAA;AACrE,OACF,EAAA,CAAA;AAAA;AAEJ,GACF;AACF;AAEA,MAAM,eAAkB,GAAA,OACtB,MACA,EAAA,aAAA,EACA,aACA,SACkB,KAAA;AAClB,EAAA,IAAI,CAAC,WAAa,EAAA;AAChB,IAAA;AAAA;AAGF,EAAM,MAAA,EAAE,OAAU,GAAA,MAAA;AAClB,EAAM,MAAA,EAAE,WAAc,GAAA,KAAA;AAGtB,EAAA,MAAM,cAAc,KAAM,CAAA,QAAA,CAAS,eAAgB,CAAA,KAAA,CAAM,WAAW,GAAG,CAAA;AACvE,EAAA,MAAM,oBAAuB,GAAA,KAAA,CAAM,SAAU,CAAA,KAAA,CAAM,MAAS,GAAA,CAAA;AAC5D,EAAA,MAAM,WAAc,GAAA,WAAA,IAAe,WAAY,CAAA,cAAA,CAAe,MAAa,CAAA;AAE3E,EAAM,MAAA,mBAAA,GAAsB,cACxB,WACG,CAAA,MAAA;AAAA,IACC,CAAC,UACC,KAAA,UAAA,CAAY,KAAM,CAAA,MAAA,IAAU,oBAC5B,IAAA,UAAA,CAAY,GAAI,CAAA,MAAA,GAAS,oBACzB,IAAA,UAAA,CAAY,IAAS,KAAA;AAAA,GACzB,CACC,OAAQ,EAAA,GACX,EAAC;AAGL,EAAM,MAAA,WAAA,GACJ,eACA,WACG,CAAA,MAAA;AAAA,IACC,CAAC,UAAA,KACC,UAAY,CAAA,GAAA,CAAI,UAAU,oBAC1B,IAAA,UAAA,CAAY,IAAS,KAAA,UAAA,IACrB,WAAY,IAAK,CAAA,GAAA,CAAI,WAAW,CAAA,CAAE,SAAS,WAAW;AAAA,IAEzD,IAAK,EAAA;AAEV,EAAM,MAAA,QAAA,GAAW,WAAe,IAAA,KAAA,CAAM,SAAU,CAAA,IAAA,CAAK,KAAM,CAAA,WAAA,CAAY,KAAM,CAAA,MAAA,EAAQ,WAAY,CAAA,GAAA,CAAI,MAAM,CAAA;AAE3G,EAAM,MAAA,cAAA,GAAiB,oBACpB,GAAI,CAAA,CAAC,eAAe,UAAW,CAAA,IAAA,CAAK,IAAI,WAAW,CAAC,EACpD,IAAK,CAAA,GAAG,EACR,KAAM,CAAA,GAAG,EACT,MAAO,CAAA,CAAC,SAAc,KAAA,SAAA,CAAU,MAAM,CAAA;AAEzC,EAAI,IAAA,IAAA,GAAO,MAAM,SAAU,CAAA,IAAA;AAC3B,EAAA,IAAI,SAAS,IAAK,CAAA,KAAA,CAAM,CAAG,EAAA,SAAA,CAAU,MAAM,MAAM,CAAA;AAEjD,EAAA,IAAI,oBAAoB,MAAQ,EAAA;AAC9B,IAAA,IAAA,GAAO,KAAM,CAAA,SAAA,CAAU,IAAK,CAAA,KAAA,CAAM,mBAAoB,CAAA,CAAC,CAAE,CAAA,KAAA,CAAM,MAAQ,EAAA,mBAAA,CAAoB,CAAC,CAAA,CAAE,IAAI,MAAM,CAAA;AACxG,IAAS,MAAA,GAAA,KAAA,CAAM,SAAU,CAAA,IAAA,CAAK,KAAM,CAAA,mBAAA,CAAoB,CAAC,CAAA,CAAE,KAAM,CAAA,MAAA,EAAQ,SAAU,CAAA,KAAA,CAAM,MAAM,CAAA;AAAA;AAKjG,EAAM,MAAA,eAAA,GAAkB,MAAO,CAAA,KAAA,CAAM,mBAAmB,CAAA;AACxD,EAAA,IAAI,eAAiB,EAAA;AACnB,IAAA,MAAA,GAAS,gBAAgB,CAAC,CAAA;AAAA,aACjB,SAAW,EAAA;AACpB,IAAA,MAAA,GAAS,UAAU,MAAM,CAAA;AAAA;AAG3B,EAAA,MAAM,EAAE,WAAA,EAAa,OAAQ,EAAA,GAAI,MAAM,WAAY,CAAA;AAAA,IACjD,MAAA;AAAA,IACA,IAAA;AAAA,IACA,KAAA;AAAA,IACA,cAAA;AAAA,IACA,UAAU,QAAY,IAAA,KAAA,CAAA;AAAA,IACtB;AAAA,GACD,CAAA;AAED,EAAA,MAAM,mBAAsB,GAAA,WAAA,CACzB,GAAI,CAAA,CAAC,KAAU,KAAA;AACd,IAAI,IAAA,CAAC,MAAM,KAAO,EAAA;AAChB,MAAO,OAAA,KAAA;AAAA;AAGT,IAAA,MAAM,qBACJ,KAAM,CAAA,kBAAA,KAAuB,MAAM,WAAc,GAAA,kBAAA,CAAmB,SAAS,kBAAmB,CAAA,IAAA,CAAA;AAClG,IAAM,MAAA,cAAA,GAAiB,kBAAkB,kBAAkB,CAAA;AAC3D,IAAI,IAAA,QAAA,GAAW,EAAE,GAAG,KAAM,EAAA;AAC1B,IAAA,IAAI,MAAQ,EAAA;AAEV,MAAI,IAAA,CAAC,MAAM,UAAY,EAAA;AACrB,QAAA,QAAA,CAAS,KAAQ,GAAA,QAAA,CAAS,KAAM,CAAA,MAAA,CAAO,CAAC,CAAA,KAAA,CAAO,CAAE,CAAA,UAAA,IAAc,CAAE,CAAA,KAAA,EAAO,MAAU,IAAA,MAAA,CAAO,MAAM,CAAA;AAC/F,QAAA,QAAA,CAAS,KAAQ,GAAA,cAAA,CAAe,QAAS,CAAA,KAAA,EAAO,MAAM,CAAA;AAAA;AAIxD,MAAS,QAAA,CAAA,KAAA,GAAQ,SAAS,KAAM,CAAA,MAAA;AAAA,QAC9B,CAAC,CAAG,KAAA;AA9Td,UAAA,IAAA,EAAA;AA8TiB,UAAA,OAAA,EAAE,EAAE,UAAe,KAAA,MAAA,IAAA,CAAA,CAAW,OAAE,UAAF,KAAA,IAAA,GAAA,EAAA,GAAgB,EAAE,KAAW,MAAA,MAAA,CAAA;AAAA;AAAA,OACpE;AAAA;AAGF,IAAI,IAAA,CAAC,MAAM,QAAU,EAAA;AACnB,MAAA,QAAA,CAAS,KAAQ,GAAA,MAAA,CAAO,QAAS,CAAA,KAAA,EAAO,CAAC,IAAyB,KAAA;AAChE,QAAI,IAAA,IAAA,CAAK,aAAa,KAAW,CAAA,EAAA;AAC/B,UAAA,OAAO,IAAK,CAAA,SAAA,KAAc,KAAY,CAAA,GAAA,IAAA,CAAK,YAAY,IAAK,CAAA,KAAA;AAAA,SACvD,MAAA;AAEL,UAAO,OAAA,IAAA,CAAK,YAAY,IAAK,CAAA,KAAA;AAAA;AAC/B,OACD,CAAA;AAAA;AAGH,IAAO,OAAA,QAAA;AAAA,GACR,EACA,MAAO,CAAA,CAAC,OAAO,EAAG,CAAA,KAAA,IAAS,EAAG,CAAA,KAAA,CAAM,MAAM,CAAA;AAE7C,EAAc,aAAA,CAAA;AAAA,IACZ,YAAc,EAAA,mBAAA;AAAA,IACd,eAAiB,EAAA,MAAA;AAAA,IACjB,gBAAkB,EAAA,OAAA;AAAA,IAClB,aAAe,EAAA;AAAA,GAChB,CAAA;AAGD,EAAO,MAAA,CAAA,IAAA,GAAO,KAAM,EAAA;AACtB,CAAA;AAEO,SAAS,oBACd,cACA,EAAA,eAAA,EACA,aACA,EAAA,cAAA,EACA,iBACA,SACA,EAAA;AAEA,EAAM,MAAA,QAAA,GAAW,mBAAmB,eAAgB,CAAA,MAAA;AACpD,EAAA,MAAM,IAAO,GAAA,SAAA,GAAY,SAAU,CAAA,aAAa,CAAI,GAAA,aAAA;AACpD,EAAM,MAAA,MAAA,GAAS,aAAc,CAAA,OAAA,CAAQ,eAAe,CAAA;AAEpD,EAAM,MAAA,YAAA,GACJ,MAAS,GAAA,CAAA,CAAA,GAAK,IAAK,CAAA,MAAA,GAAS,SAAS,eAAgB,CAAA,MAAA,GAAS,IAAK,CAAA,MAAA,GAAS,eAAgB,CAAA,MAAA;AAC9F,EAAA,MAAM,UAAU,OAAS,CAAA,eAAA,IAAmB,YAAe,GAAA,CAAA,IAAM,mBAAmB,aAAa,CAAA;AACjG,EAAA,MAAM,OAAU,GAAA,OAAA,IAAW,CAAC,cAAA,GAAiB,eAAe,MAAS,GAAA,CAAA;AAErE,EAAO,OAAA;AAAA,IACL,OAAA;AAAA,IACA;AAAA,GACF;AACF;;;;"}