import * as React from 'react'; import ClickAwayListener from '@mui/base/ClickAwayListener'; import Chip from '@mui/material/Chip'; import Popper from '@mui/material/Popper'; import InputLabel from '@mui/material/InputLabel'; import FormHelperText from '@mui/material/FormHelperText'; import { Controller, useFormContext } from 'react-hook-form'; import { Editor, Transforms, Range, createEditor } from 'slate'; import { Slate, Editable, useSelected, useFocused, } from 'slate-react'; import { serialize, deserialize, insertVariable, customizeEditor, } from './utils'; import Suggestions from './Suggestions'; import { StepExecutionsContext } from 'contexts/StepExecutions'; import { FakeInput, InputLabelWrapper } from './style'; import { VariableElement } from './types'; import { processStepWithExecutions } from './data'; type PowerInputProps = { onChange?: (value: string) => void; onBlur?: (value: string) => void; defaultValue?: string; name: string; label?: string; type?: string; required?: boolean; readOnly?: boolean; description?: string; docUrl?: string; clickToCopy?: boolean; } const PowerInput = (props: PowerInputProps) => { const { control } = useFormContext(); const { defaultValue = '', onBlur, name, label, required, description, } = props; const priorStepsWithExecutions = React.useContext(StepExecutionsContext); const editorRef = React.useRef(null); const [target, setTarget] = React.useState(null); const [index, setIndex] = React.useState(0); const [search, setSearch] = React.useState(null); const renderElement = React.useCallback(props => , []); const [editor] = React.useState(() => customizeEditor(createEditor())); const stepsWithVariables = React.useMemo(() => { return processStepWithExecutions(priorStepsWithExecutions); }, [priorStepsWithExecutions]) const handleBlur = React.useCallback((value) => { onBlur?.(value); }, [onBlur]); const handleVariableSuggestionClick = React.useCallback( (variable: Pick) => { if (target) { Transforms.select(editor, target); insertVariable(editor, variable); setTarget(null); } }, [index, target] ); const onKeyDown = React.useCallback( event => { if (target) { switch (event.key) { case 'ArrowDown': { event.preventDefault(); setIndex((currentIndex) => currentIndex + 1); break } case 'ArrowUp': { event.preventDefault(); setIndex((currentIndex) => currentIndex - 1 < 0 ? 0 : currentIndex - 1); break } case 'Tab': case 'Enter': { event.preventDefault(); Transforms.select(editor, target); insertVariable(editor, stepsWithVariables[0].output[index]); setTarget(null); break } case 'Escape': { event.preventDefault(); setTarget(null); break } } } }, [index, search, target, stepsWithVariables] ); return ( ( { controllerOnChange(serialize(value)); const { selection } = editor if (selection && Range.isCollapsed(selection)) { const [start] = Range.edges(selection); const lineBefore = Editor.before(editor, start, { unit: 'line' }); const before = lineBefore && Editor.before(editor, lineBefore); const beforeRange = (before || lineBefore) && Editor.range(editor, before || lineBefore, start); const beforeText = beforeRange && Editor.string(editor, beforeRange); const variableMatch = beforeText && beforeText.match(/@([\w.]*?)$/); if (variableMatch) { const beginningOfVariable = Editor.before( editor, start, { unit: 'offset', distance: (variableMatch[1].length || 0) + 1 } ); if (beginningOfVariable) { const newTarget = Editor.range(editor, beginningOfVariable, start); if (newTarget) { setTarget(newTarget); } } setIndex(0); setSearch(variableMatch[1]); return; } } setSearch(null); }} > setSearch(null)}> {/* ref-able single child for ClickAwayListener */}
{label} { controllerOnBlur(); handleBlur(value); }} /> {/* ghost placer for the variables popover */}
{description}
)} /> ) } const Element = (props: any) => { const { attributes, children, element } = props; switch (element.type) { case 'variable': return ; default: return

{children}

; } } const Variable = ({ attributes, children, element }: any) => { const selected = useSelected(); const focused = useFocused(); const label = ( <> {element.name} {children} ); return ( ) } export default PowerInput;