@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 { 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\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":";;;;;;;;AAUO,MAAM,kBAAA,GAAqB;AAQ3B,SAAS,iBAAA,CAAkB;AAAA,EAChC,WAAA;AAAA,EACA,SAAA;AAAA,EACA,qBAAA;AAAA,EACA;AACF,CAAA,EAKgB;AACd,EAAA,IAAI,YAAA;AACJ,EAAA,IAAI,KAAA,GAA0B;AAAA,IAC5B,cAAc,EAAC;AAAA,IACf,eAAA,EAAiB,EAAA;AAAA,IACjB,gBAAA,EAAkB,EAAA;AAAA,IAClB,aAAA,EAAe;AAAA,GACjB;AACA,EAAA,MAAM,wBAAA,GAA2B,QAAA,CAAS,eAAA,EAAiB,kBAAkB,CAAA;AAE7E,EAAA,MAAM,QAAA,GAAW,CAAC,MAAA,KAAsC;AACtD,IAAA,KAAA,GAAQ;AAAA,MACN,GAAG,KAAA;AAAA,MACH,GAAG;AAAA,KACL;AAAA,EACF,CAAA;AAEA,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,CAAC,KAAA,EAAO,MAAA,EAAQ,IAAA,KAAS;AAC/B,MAAA,KAAA,GAAQ;AAAA,QACN,GAAG,KAAA;AAAA,QACH,cAAc;AAAC,OACjB;AAEA,MAAA,OAAO,IAAA,EAAK;AAAA,IACd,CAAA;AAAA,IAEA,OAAA,EAAS,CAAC,KAAA,EAAO,MAAA,EAAQ,IAAA,KAAS;AAChC,MAAA,KAAA,GAAQ;AAAA,QACN,GAAG,KAAA;AAAA,QACH,cAAc;AAAC,OACjB;AAEA,MAAA,OAAO,IAAA,EAAK;AAAA,IACd,CAAA;AAAA,IAEA,SAAA,EAAW,CAAC,KAAA,EAAO,MAAA,EAAQ,IAAA,KAAS;AAClC,MAAA,MAAM,qBAAqB,KAAA,CAAM,YAAA;AAEjC,MAAA,MAAM,iBAAiB,kBAAA,CAAmB,MAAA;AAE1C,MAAA,QAAQ,MAAM,GAAA;AAAK,QACjB,KAAK,QAAA,EAAU;AACb,UAAA,IAAI,cAAA,EAAgB;AAClB,YAAA,KAAA,CAAM,cAAA,EAAe;AAErB,YAAA,KAAA,GAAQ;AAAA,cACN,GAAG,KAAA;AAAA,cACH,cAAc;AAAC,aACjB;AAGA,YAAA,OAAO,MAAA,CAAO,WAAW,EAAE,CAAA;AAAA,UAC7B;AAEA,UAAA;AAAA,QACF;AAAA,QAEA,KAAK,WAAA;AAAA,QACL,KAAK,SAAA;AACH,UAAA,IAAI,cAAA,EAAgB;AAClB,YAAA,KAAA,CAAM,cAAA,EAAe;AACrB,YAAA,YAAA,CAAa,aAAA,CAAc,KAAA,CAAM,GAAA,KAAQ,WAAA,GAAc,IAAI,CAAA,CAAE,CAAA;AAC7D,YAAA;AAAA,UACF;AAEA,UAAA;AAAA,QAEF,KAAK,OAAA,EAAS;AACZ,UAAA,IAAI,EAAE,KAAA,CAAM,QAAA,IAAY,KAAA,CAAM,YAAY,cAAA,EAAgB;AACxD,YAAA,KAAA,CAAM,cAAA,EAAe;AACrB,YAAA,OAAO,aAAa,gBAAA,EAAiB;AAAA,UACvC;AAEA,UAAA;AAAA,QACF;AAAA,QAEA,KAAK,KAAA,EAAO;AACV,UAAA,IAAI,cAAA,EAAgB;AAClB,YAAA,KAAA,CAAM,cAAA,EAAe;AACrB,YAAA,OAAO,aAAa,gBAAA,EAAiB;AAAA,UACvC;AAEA,UAAA;AAAA,QACF;AAAA,QAEA,SAAS;AAEP,UAAA,IAAI,KAAA,CAAM,GAAA,CAAI,MAAA,KAAW,CAAA,EAAG;AAC1B,YAAA,wBAAA,CAAyB,MAAA,EAAQ,QAAA,EAAU,WAAA,EAAa,SAAS,CAAA;AAAA,UACnE;AACA,UAAA;AAAA,QACF;AAAA;AAGF,MAAA,OAAO,IAAA,EAAK;AAAA,IACd,CAAA;AAAA,IAEA,QAAA,EAAU;AAAA,MACR,gBAAA,EAAkB,CAAC,MAAA,EAAQ,UAAA,KAAuC;AAChE,QAAA,MAAM,cAAc,KAAA,CAAM,YAAA;AAC1B,QAAA,IAAI,CAAC,WAAA,IAAe,CAAC,WAAA,CAAY,MAAA,EAAQ;AACvC,UAAA,OAAO,MAAA;AAAA,QACT;AAGA,QAAA,MAAM,EAAA,GAAK,MAAA,CAAO,cAAA,CAAe,UAAU,CAAA;AAC3C,QAAA,wBAAA,CAAyB,MAAA,EAAQ,QAAA,EAAU,WAAA,EAAa,SAAS,CAAA;AACjE,QAAA,OAAO,EAAA;AAAA,MACT,CAAA;AAAA,MAEA,cAAA,EAAgB,CAAC,MAAA,EAAQ,UAAA,KAA+B;AACtD,QAAA,IAAI,cAAA,GAAiB,UAAA,CAAW,UAAA,IAAc,UAAA,CAAW,KAAA;AAEzD,QAAA,MAAM,cAAA,GAAiB,WAAW,IAAA,KAAS,UAAA;AAC3C,QAAA,MAAM,IAAA,GAAO,WAAW,IAAA,IAAQ,CAAA;AAChC,QAAA,MAAM,WAAA,GAAc,IAAA,GAAO,CAAA,GAAI,IAAA,GAAO,CAAA;AACtC,QAAA,MAAM,YAAA,GAAe,IAAA,GAAO,CAAA,GAAI,CAAC,IAAA,GAAO,CAAA;AAExC,QAAA,MAAM,EAAE,eAAA,EAAiB,aAAA,EAAe,gBAAA,EAAiB,GAAI,KAAA;AAE7D,QAAA,IAAI,qBAAA,EAAuB;AACzB,UAAA,cAAA,GAAiB,sBAAsB,cAAA,EAAgB;AAAA,YACrD,cAAc,KAAA,CAAM,YAAA;AAAA,YACpB,gBAAA;AAAA,YACA,eAAA;AAAA,YACA;AAAA,WACD,CAAA;AAAA,QACH;AAEA,QAAA,MAAM,EAAE,OAAA,EAAS,QAAA,EAAS,GAAI,mBAAA;AAAA,UAC5B,cAAA;AAAA,UACA,eAAA;AAAA,UACA,aAAA;AAAA,UACA,cAAA;AAAA,UACA,UAAA,CAAW,eAAA;AAAA,UACX;AAAA,SACF;AAGA,QAAA,IAAI,cAAA,CAAe,KAAA,CAAM,IAAI,CAAA,EAAG;AAC9B,UAAA,MAAM,QAAA,GAAW,aAAa,cAAc,CAAA;AAC5C,UAAA,MAAA,CAAO,cAAA,CAAe,QAAQ,CAAA,CAAE,aAAA,CAAc,OAAO,CAAA,CAAE,cAAA,CAAe,QAAQ,CAAA,CAAE,KAAA,EAAM;AACtF,UAAA,OAAO,MAAA;AAAA,QACT;AAEA,QAAA,KAAA,GAAQ;AAAA,UACN,GAAG,KAAA;AAAA,UACH,cAAc;AAAC,SACjB;AAEA,QAAA,MAAA,CACG,mBAAkB,CAClB,cAAA,CAAe,QAAQ,CAAA,CACvB,cAAc,OAAO,CAAA,CACrB,UAAA,CAAW,cAAc,EACzB,WAAA,CAAY,WAAW,EACvB,YAAA,CAAa,YAAY,EACzB,KAAA,EAAM;AAET,QAAA,OAAO,MAAA;AAAA,MACT;AAAA,KACF;AAAA,IAEA,YAAA,CAAa,KAAA,EAAO,MAAA,EAAQ,IAAA,EAAM;AAChC,MAAA,IAAI,MAAA,CAAO,KAAA,CAAM,SAAA,CAAU,UAAA,EAAY;AACrC,QAAA,OAAO,IAAA,EAAK;AAAA,MACd;AAEA,MAAA,MAAM,WAAW,IAAA,EAAK;AAEtB,MAAA,uBACE,IAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,QAAA,QAAA;AAAA,wBACD,GAAA;AAAA,UAAC,SAAA;AAAA,UAAA;AAAA,YACC,OAAA,EAAS,CAAC,IAAA,KAAqB,YAAA,GAAe,IAAA;AAAA,YAC9C,MAAA,EAAQ,YAAA;AAAA,YACR,QAAQ,KAAA,CAAM,eAAA;AAAA,YACd,MAAA,EAAQ,CAAC,CAAC,KAAA,CAAM,YAAA,CAAa,MAAA;AAAA,YAC7B,cAAc,KAAA,CAAM,YAAA;AAAA,YACpB,oBAAqB,MAAA,CAA8C;AAAA;AAAA;AACrE,OAAA,EACF,CAAA;AAAA,IAEJ;AAAA,GACF;AACF;AAEA,MAAM,eAAA,GAAkB,OACtB,MAAA,EACA,aAAA,EACA,aACA,SAAA,KACkB;AAClB,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,EAAE,OAAM,GAAI,MAAA;AAClB,EAAA,MAAM,EAAE,WAAU,GAAI,KAAA;AAGtB,EAAA,MAAM,cAAc,KAAA,CAAM,QAAA,CAAS,eAAA,CAAgB,KAAA,CAAM,WAAW,GAAG,CAAA;AACvE,EAAA,MAAM,oBAAA,GAAuB,KAAA,CAAM,SAAA,CAAU,KAAA,CAAM,MAAA,GAAS,CAAA;AAC5D,EAAA,MAAM,WAAA,GAAc,WAAA,IAAe,WAAA,CAAY,cAAA,CAAe,MAAa,CAAA;AAE3E,EAAA,MAAM,mBAAA,GAAsB,cACxB,WAAA,CACG,MAAA;AAAA,IACC,CAAC,UAAA,KACC,UAAA,CAAY,KAAA,CAAM,MAAA,IAAU,oBAAA,IAC5B,UAAA,CAAY,GAAA,CAAI,MAAA,GAAS,oBAAA,IACzB,UAAA,CAAY,IAAA,KAAS;AAAA,GACzB,CACC,OAAA,EAAQ,GACX,EAAC;AAGL,EAAA,MAAM,WAAA,GACJ,eACA,WAAA,CACG,MAAA;AAAA,IACC,CAAC,UAAA,KACC,UAAA,CAAY,GAAA,CAAI,UAAU,oBAAA,IAC1B,UAAA,CAAY,IAAA,KAAS,UAAA,IACrB,WAAY,IAAA,CAAK,GAAA,CAAI,WAAW,CAAA,CAAE,SAAS,WAAW;AAAA,IAEzD,IAAA,EAAK;AAEV,EAAA,MAAM,QAAA,GAAW,WAAA,IAAe,KAAA,CAAM,SAAA,CAAU,IAAA,CAAK,KAAA,CAAM,WAAA,CAAY,KAAA,CAAM,MAAA,EAAQ,WAAA,CAAY,GAAA,CAAI,MAAM,CAAA;AAE3G,EAAA,MAAM,cAAA,GAAiB,oBACpB,GAAA,CAAI,CAAC,eAAe,UAAA,CAAW,IAAA,CAAK,IAAI,WAAW,CAAC,EACpD,IAAA,CAAK,GAAG,EACR,KAAA,CAAM,GAAG,EACT,MAAA,CAAO,CAAC,SAAA,KAAc,SAAA,CAAU,MAAM,CAAA;AAEzC,EAAA,IAAI,IAAA,GAAO,MAAM,SAAA,CAAU,IAAA;AAC3B,EAAA,IAAI,SAAS,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,SAAA,CAAU,MAAM,MAAM,CAAA;AAEjD,EAAA,IAAI,oBAAoB,MAAA,EAAQ;AAC9B,IAAA,IAAA,GAAO,KAAA,CAAM,SAAA,CAAU,IAAA,CAAK,KAAA,CAAM,mBAAA,CAAoB,CAAC,CAAA,CAAE,KAAA,CAAM,MAAA,EAAQ,mBAAA,CAAoB,CAAC,CAAA,CAAE,IAAI,MAAM,CAAA;AACxG,IAAA,MAAA,GAAS,KAAA,CAAM,SAAA,CAAU,IAAA,CAAK,KAAA,CAAM,mBAAA,CAAoB,CAAC,CAAA,CAAE,KAAA,CAAM,MAAA,EAAQ,SAAA,CAAU,KAAA,CAAM,MAAM,CAAA;AAAA,EACjG;AAIA,EAAA,MAAM,eAAA,GAAkB,MAAA,CAAO,KAAA,CAAM,mBAAmB,CAAA;AACxD,EAAA,IAAI,eAAA,EAAiB;AACnB,IAAA,MAAA,GAAS,gBAAgB,CAAC,CAAA;AAAA,EAC5B,WAAW,SAAA,EAAW;AACpB,IAAA,MAAA,GAAS,UAAU,MAAM,CAAA;AAAA,EAC3B;AAEA,EAAA,MAAM,EAAE,WAAA,EAAa,OAAA,EAAQ,GAAI,MAAM,WAAA,CAAY;AAAA,IACjD,MAAA;AAAA,IACA,IAAA;AAAA,IACA,KAAA;AAAA,IACA,cAAA;AAAA,IACA,UAAU,QAAA,IAAY,KAAA,CAAA;AAAA,IACtB;AAAA,GACD,CAAA;AAED,EAAA,MAAM,mBAAA,GAAsB,WAAA,CACzB,GAAA,CAAI,CAAC,KAAA,KAAU;AACd,IAAA,IAAI,CAAC,MAAM,KAAA,EAAO;AAChB,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,MAAM,qBACJ,KAAA,CAAM,kBAAA,KAAuB,MAAM,WAAA,GAAc,kBAAA,CAAmB,SAAS,kBAAA,CAAmB,IAAA,CAAA;AAClG,IAAA,MAAM,cAAA,GAAiB,kBAAkB,kBAAkB,CAAA;AAC3D,IAAA,IAAI,QAAA,GAAW,EAAE,GAAG,KAAA,EAAM;AAC1B,IAAA,IAAI,MAAA,EAAQ;AAEV,MAAA,IAAI,CAAC,MAAM,UAAA,EAAY;AACrB,QAAA,QAAA,CAAS,KAAA,GAAQ,QAAA,CAAS,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,KAAA,CAAO,CAAA,CAAE,UAAA,IAAc,CAAA,CAAE,KAAA,EAAO,MAAA,IAAU,MAAA,CAAO,MAAM,CAAA;AAC/F,QAAA,QAAA,CAAS,KAAA,GAAQ,cAAA,CAAe,QAAA,CAAS,KAAA,EAAO,MAAM,CAAA;AAAA,MACxD;AAGA,MAAA,QAAA,CAAS,KAAA,GAAQ,SAAS,KAAA,CAAM,MAAA;AAAA,QAC9B,CAAC,CAAA,KAAG;AAtTd,UAAA,IAAA,EAAA;AAsTiB,UAAA,OAAA,EAAE,EAAE,UAAA,KAAe,MAAA,IAAA,CAAA,CAAW,OAAE,UAAA,KAAF,IAAA,GAAA,EAAA,GAAgB,EAAE,KAAA,MAAW,MAAA,CAAA;AAAA,QAAA;AAAA,OACpE;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,MAAM,QAAA,EAAU;AACnB,MAAA,QAAA,CAAS,KAAA,GAAQ,MAAA,CAAO,QAAA,CAAS,KAAA,EAAO,CAAC,IAAA,KAAyB;AAChE,QAAA,IAAI,IAAA,CAAK,aAAa,KAAA,CAAA,EAAW;AAC/B,UAAA,OAAO,IAAA,CAAK,SAAA,KAAc,KAAA,CAAA,GAAY,IAAA,CAAK,YAAY,IAAA,CAAK,KAAA;AAAA,QAC9D,CAAA,MAAO;AAEL,UAAA,OAAO,IAAA,CAAK,YAAY,IAAA,CAAK,KAAA;AAAA,QAC/B;AAAA,MACF,CAAC,CAAA;AAAA,IACH;AAEA,IAAA,OAAO,QAAA;AAAA,EACT,CAAC,EACA,MAAA,CAAO,CAAC,OAAO,EAAA,CAAG,KAAA,IAAS,EAAA,CAAG,KAAA,CAAM,MAAM,CAAA;AAE7C,EAAA,aAAA,CAAc;AAAA,IACZ,YAAA,EAAc,mBAAA;AAAA,IACd,eAAA,EAAiB,MAAA;AAAA,IACjB,gBAAA,EAAkB,OAAA;AAAA,IAClB,aAAA,EAAe;AAAA,GAChB,CAAA;AAGD,EAAA,MAAA,CAAO,IAAA,GAAO,KAAA,EAAM;AACtB,CAAA;AAEO,SAAS,oBACd,cAAA,EACA,eAAA,EACA,aAAA,EACA,cAAA,EACA,iBACA,SAAA,EACA;AAEA,EAAA,MAAM,QAAA,GAAW,mBAAmB,eAAA,CAAgB,MAAA;AACpD,EAAA,MAAM,IAAA,GAAO,SAAA,GAAY,SAAA,CAAU,aAAa,CAAA,GAAI,aAAA;AACpD,EAAA,MAAM,MAAA,GAAS,aAAA,CAAc,OAAA,CAAQ,eAAe,CAAA;AAEpD,EAAA,MAAM,YAAA,GACJ,MAAA,GAAS,CAAA,CAAA,GAAK,IAAA,CAAK,MAAA,GAAS,SAAS,eAAA,CAAgB,MAAA,GAAS,IAAA,CAAK,MAAA,GAAS,eAAA,CAAgB,MAAA;AAC9F,EAAA,MAAM,UAAU,OAAA,CAAS,eAAA,IAAmB,YAAA,GAAe,CAAA,IAAM,mBAAmB,aAAa,CAAA;AACjG,EAAA,MAAM,OAAA,GAAU,OAAA,IAAW,CAAC,cAAA,GAAiB,eAAe,MAAA,GAAS,CAAA;AAErE,EAAA,OAAO;AAAA,IACL,OAAA;AAAA,IACA;AAAA,GACF;AACF;;;;"}