const React = require('react'); const { _ } = require('@joplin/lib/locale'); const { themeStyle } = require('@joplin/lib/theme'); const time = require('@joplin/lib/time').default; const Datetime = require('react-datetime'); const CreatableSelect = require('react-select/lib/Creatable').default; const Select = require('react-select').default; const makeAnimated = require('react-select/lib/animated').default; class PromptDialog extends React.Component { constructor() { super(); this.answerInput_ = React.createRef(); } UNSAFE_componentWillMount() { this.setState({ visible: false, answer: this.props.defaultValue ? this.props.defaultValue : '', }); this.focusInput_ = true; } UNSAFE_componentWillReceiveProps(newProps) { if ('visible' in newProps && newProps.visible !== this.props.visible) { this.setState({ visible: newProps.visible }); if (newProps.visible) this.focusInput_ = true; } if ('defaultValue' in newProps && newProps.defaultValue !== this.props.defaultValue) { this.setState({ answer: newProps.defaultValue }); } } componentDidUpdate() { if (this.focusInput_ && this.answerInput_.current) this.answerInput_.current.focus(); this.focusInput_ = false; } styles(themeId, width, height, visible) { const styleKey = `${themeId}_${width}_${height}_${visible}`; if (styleKey === this.styleKey_) return this.styles_; const theme = themeStyle(themeId); this.styleKey_ = styleKey; this.styles_ = {}; const paddingTop = 20; this.styles_.modalLayer = { zIndex: 9999, position: 'absolute', top: 0, left: 0, width: width, height: height, backgroundColor: 'rgba(0,0,0,0.6)', display: visible ? 'flex' : 'none', alignItems: 'flex-start', justifyContent: 'center', paddingTop: `${paddingTop}px`, }; this.styles_.promptDialog = { backgroundColor: theme.backgroundColor, padding: 16, display: 'inline-block', maxWidth: width * 0.5, boxShadow: '6px 6px 20px rgba(0,0,0,0.5)', }; this.styles_.button = { minWidth: theme.buttonMinWidth, minHeight: theme.buttonMinHeight, marginLeft: 5, color: theme.color, backgroundColor: theme.backgroundColor, border: '1px solid', borderColor: theme.dividerColor, }; this.styles_.label = { marginRight: 5, fontSize: theme.fontSize, color: theme.color, fontFamily: theme.fontFamily, verticalAlign: 'middle', }; this.styles_.input = { width: 0.5 * width, maxWidth: 400, color: theme.color, backgroundColor: theme.backgroundColor, border: '1px solid', borderColor: theme.dividerColor, }; this.styles_.select = { control: provided => Object.assign(provided, { minWidth: width * 0.2, maxWidth: width * 0.5, fontFamily: theme.fontFamily, }), input: provided => Object.assign(provided, { minWidth: '20px', color: theme.color, }), menu: provided => Object.assign(provided, { color: theme.color, fontFamily: theme.fontFamily, backgroundColor: theme.backgroundColor, }), option: (provided, state) => Object.assign(provided, { color: theme.color, fontFamily: theme.fontFamily, paddingLeft: `${10 + (state.data.indentDepth || 0) * 20}px`, }), multiValueLabel: provided => Object.assign(provided, { fontFamily: theme.fontFamily, }), multiValueRemove: provided => Object.assign(provided, { color: theme.color, }), }; this.styles_.selectTheme = tagTheme => Object.assign(tagTheme, { borderRadius: 2, colors: Object.assign(tagTheme.colors, { primary: theme.raisedBackgroundColor, primary25: theme.raisedBackgroundColor, neutral0: theme.backgroundColor, neutral5: theme.backgroundColor, neutral10: theme.raisedBackgroundColor, neutral20: theme.raisedBackgroundColor, neutral30: theme.raisedBackgroundColor, neutral40: theme.color, neutral50: theme.color, neutral60: theme.color, neutral70: theme.color, neutral80: theme.color, neutral90: theme.color, danger: theme.backgroundColor, dangerLight: theme.colorError2, }), }); this.styles_.desc = Object.assign({}, theme.textStyle, { marginTop: 10, }); return this.styles_; } render() { const style = this.props.style; const theme = themeStyle(this.props.themeId); const buttonTypes = this.props.buttons ? this.props.buttons : ['ok', 'cancel']; const styles = this.styles(this.props.themeId, style.width, style.height, this.state.visible); const onClose = (accept, buttonType) => { if (this.props.onClose) { let outputAnswer = this.state.answer; if (this.props.inputType === 'datetime') { // outputAnswer = anythingToDate(outputAnswer); outputAnswer = time.anythingToDateTime(outputAnswer); } this.props.onClose(accept ? outputAnswer : null, buttonType); } this.setState({ visible: false, answer: '' }); }; const onChange = event => { this.setState({ answer: event.target.value }); }; // const anythingToDate = (o) => { // if (o && o.toDate) return o.toDate(); // if (!o) return null; // let m = moment(o, time.dateTimeFormat()); // if (m.isValid()) return m.toDate(); // m = moment(o, time.dateFormat()); // return m.isValid() ? m.toDate() : null; // } const onDateTimeChange = momentObject => { this.setState({ answer: momentObject }); }; const onSelectChange = newValue => { this.setState({ answer: newValue }); this.focusInput_ = true; }; const onKeyDown = event => { if (event.key === 'Enter') { if (this.props.inputType !== 'tags' && this.props.inputType !== 'dropdown') { onClose(true); } else if (this.answerInput_.current && !this.answerInput_.current.state.menuIsOpen) { // The menu will be open if the user is selecting a new item onClose(true); } } else if (event.key === 'Escape') { onClose(false); } }; const descComp = this.props.description ?
{this.props.description}
: null; let inputComp = null; if (this.props.inputType === 'datetime') { inputComp = onDateTimeChange(momentObject)} />; } else if (this.props.inputType === 'tags') { inputComp = onKeyDown(event)} />; } else if (this.props.inputType === 'dropdown') { inputComp = onChange(event)} onKeyDown={event => onKeyDown(event)} />; } const buttonComps = []; if (buttonTypes.indexOf('create') >= 0) { buttonComps.push( ); } if (buttonTypes.indexOf('ok') >= 0) { buttonComps.push( ); } if (buttonTypes.indexOf('cancel') >= 0) { buttonComps.push( ); } if (buttonTypes.indexOf('clear') >= 0) { buttonComps.push( ); } return (
{inputComp} {descComp}
{buttonComps}
); } } module.exports = { PromptDialog };