const React = require('react'); const ReactDOM = require('react-dom'); const createClass = require('create-react-class'); const _ = require('lodash'); const { NUMBER_PATTERN } = require('../constants'); const Hints = createClass({ hintsRef : React.createRef(), activeHintRef : React.createRef(), getDefaultProps : function() { return { hints : [], field : undefined, }; }, getInitialState : function() { return { activeHint : 0 }; }, componentDidUpdate : function({ hints }) { const hintsLength = this.props.hints.length; if(hintsLength - 1 < this.state.activeHint && hintsLength !== hints.length) { this.setState({ activeHint : hintsLength === 0 ? 0 : hintsLength - 1 }); return; } if(this.hintsRef.current && this.activeHintRef.current) { const offset = this.activeHintRef.current.offsetTop; const scrollTop = this.hintsRef.current.scrollTop; if(scrollTop + 50 < offset || scrollTop + 50 > offset) { this.hintsRef.current.scrollTo({ top : offset - 50, behavior : 'smooth' }); } } }, componentDidMount : function() { }, keyDown : function(e) { const { code } = e; const { activeHint } = this.state; const { hints, field } = this.props; const match = field.state.value.match(NUMBER_PATTERN); if(code === 'ArrowDown') { e.preventDefault(); if(!match) { this.setState({ activeHint : activeHint === hints.length - 1 ? 0 : activeHint + 1 }); } } else if(code === 'ArrowUp') { e.preventDefault(); if(!match) { this.setState({ activeHint : activeHint === 0 ? hints.length - 1 : activeHint - 1 }); } } else if(code === 'Enter') { e.preventDefault(); if(!match || !match?.at(3)) { field?.hintSelected(hints[activeHint]); this.setState({ activeHint : 0 }); } } }, render : function() { const { activeHint } = this.state; const { hints, field } = this.props; if(!field) return null; const bounds = field.fieldRef[field.state.id].current?.getBoundingClientRect(); const hintElements = hints .filter((h)=>h.hint !== field.state.value) .map((h, i)=>{ let className = 'CodeMirror-hint'; if(activeHint === i) { className += ' CodeMirror-hint-active'; } return