"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireWildcard(require("react"));
var _utils = require("../utils");
var _utils2 = require("../../utils");
var _propTypes = _interopRequireDefault(require("prop-types"));
var _classnames = _interopRequireDefault(require("classnames"));
var _constants = require("../../constants");
var _jsxRuntime = require("react/jsx-runtime");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } // Copyright 1999-2023. Plesk International GmbH. All rights reserved.
/**
 * `CodeEditor` component is used for editing text as code with proper color highlighting according to selected programming language.
 * @since 0.0.61
 */
class CodeEditor extends _react.Component {
  constructor() {
    super(...arguments);
    (0, _defineProperty2.default)(this, "state", {
      content: this.props.children,
      lineSeparator: this.getLineSeparator(this.props.children),
      options: {
        lineNumbers: true,
        lineWrapping: true,
        matchBrackets: true,
        matchTags: {
          bothTags: true
        },
        indentUnit: 4,
        indentWithTabs: true,
        enterMode: 'keep',
        tabMode: 'shift',
        autoRefresh: true,
        extraKeys: {
          'Ctrl-S': 'save'
        },
        direction: (0, _utils2.isRtl)() ? 'rtl' : 'ltr'
      }
    });
    (0, _defineProperty2.default)(this, "handleScroll", () => {
      const {
        onScroll
      } = this.props;
      (0, _utils.safeInvoke)(onScroll, this.codeMirror.getScrollInfo());
    });
    (0, _defineProperty2.default)(this, "handleChange", (doc, changes) => {
      if (this.props.readOnly || changes.origin === 'setValue') {
        return;
      }
      const {
        lineSeparator
      } = this.state;
      const {
        onChange
      } = this.props;
      const content = doc.getValue(lineSeparator);
      this.setState({
        content
      }, () => {
        (0, _utils.safeInvoke)(onChange, content);
      });
    });
  }
  static getDerivedStateFromProps(_ref, state) {
    let {
      readOnly,
      autofocus,
      options
    } = _ref;
    return {
      options: {
        ...state.options,
        ...options,
        autofocus,
        readOnly
      }
    };
  }
  componentDidMount() {
    Promise.resolve().then(() => _interopRequireWildcard(require( /* webpackChunkName: "codemirror" */'./CodeMirror'))).then(_ref2 => {
      let {
        CodeMirror
      } = _ref2;
      if (!this.textareaNode) {
        return;
      }
      this.CodeMirror = CodeMirror;
      const {
        onInit,
        scrollPosition
      } = this.props;
      const {
        options
      } = this.state;
      this.codeMirror = CodeMirror.fromTextArea(this.textareaNode, options);
      this.codeMirror.on('scroll', this.handleScroll);
      if (scrollPosition) {
        this.codeMirror.scrollTo(scrollPosition.left, scrollPosition.top);
      }
      this.updateMode(this.props);
      CodeMirror.commands.save = this.props.onSave;
      CodeMirror.commands.find = CodeMirror.commands.findPersistent;
      CodeMirror.commands.findNext = CodeMirror.commands.findPersistentNext;
      CodeMirror.commands.findPrev = CodeMirror.commands.findPersistentPrev;
      (0, _utils.safeInvoke)(onInit, this.codeMirror.display.wrapper);
      this.codeMirror.on('change', this.handleChange);
    });
  }
  componentDidUpdate(prevProps) {
    if (!this.codeMirror) {
      return;
    }
    Object.keys(this.state.options).forEach(name => {
      this.codeMirror.setOption(name, this.state.options[name]);
    });
    const {
      children,
      mode,
      fileName,
      autofocus,
      scrollPosition
    } = this.props;
    this.updateMode({
      mode,
      fileName
    });
    const newContent = children || '';
    if (newContent !== prevProps.children && newContent !== this.codeMirror.getValue(this.state.lineSeparator)) {
      const prevScrollPosition = prevProps.scrollPosition || this.codeMirror.getScrollInfo();
      this.codeMirror.setValue(newContent);
      this.codeMirror.scrollTo(prevScrollPosition.left, prevScrollPosition.top);
      if (autofocus) {
        this.codeMirror.focus();
      }
    } else if (scrollPosition !== prevProps.scrollPosition) {
      this.codeMirror.scrollTo(scrollPosition.left, scrollPosition.top);
    }
  }
  componentWillUnmount() {
    if (this.codeMirror) {
      this.codeMirror.off('scroll', this.handleScroll);
      this.codeMirror.toTextArea();
    }
  }
  findModeByFileName(fileName) {
    const modeInfo = this.CodeMirror.findModeByFileName(fileName);
    if (modeInfo) {
      return modeInfo.mode;
    }
    return null;
  }
  updateMode(_ref3) {
    let {
      mode,
      fileName
    } = _ref3;
    if (!mode && fileName) {
      mode = this.findModeByFileName(fileName);
    }
    if (!mode) {
      return;
    }
    this.CodeMirror.loadMode(this.codeMirror, mode);
  }
  getLineSeparator() {
    let content = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
    const sep = /^.*?(\r\n?|\n)/.exec(content);
    return sep && sep[1] ? sep[1] : '\n';
  }
  render() {
    const {
      baseClassName,
      className,
      mode,
      fileName,
      readOnly,
      autofocus,
      children,
      onInit,
      onChange,
      onSave,
      options,
      scrollPosition,
      onScroll,
      ...props
    } = this.props;
    const {
      content
    } = this.state;
    return /*#__PURE__*/(0, _jsxRuntime.jsx)("textarea", {
      style: {
        display: 'none'
      },
      ref: ref => this.textareaNode = ref,
      className: (0, _classnames.default)(baseClassName, className),
      defaultValue: content,
      ...props
    });
  }
}
CodeEditor.propTypes = {
  /**
   * The mode to use. When not given, this will default to the first mode that was loaded.
   * @since 0.0.61
   */
  mode: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.object]),
  /**
   * CodeEditor can detect mode by file name. Will be ignored if you set mode property.
   * @since 0.0.61
   */
  fileName: _propTypes.default.string,
  /**
   * Content of the `CodeEditor`.
   * @since 0.0.61
   */
  children: _propTypes.default.string,
  /**
   * Set read only.
   * @since 0.0.61
   */
  readOnly: _propTypes.default.oneOfType([_propTypes.default.bool, _propTypes.default.string]),
  /**
   * Set auto focus.
   * @since 0.0.61
   */
  autofocus: _propTypes.default.bool,
  /**
   * onInit event handler.
   * @since 0.0.61
   */
  onInit: _propTypes.default.func,
  /**
   * onChange event handler.
   * @since 0.0.61
   */
  onChange: _propTypes.default.func,
  /**
   * onSave event handler.
   * @since 0.0.61
   */
  onSave: _propTypes.default.func,
  /**
   * See all supported options in [CodeMirror](https://codemirror.net/doc/manual.html#config) documentation.
   * @since 0.0.61
   */
  options: _propTypes.default.object,
  /**
   * Set scroll position.
   * @since 1.12.4
   */
  scrollPosition: _propTypes.default.shape({
    left: _propTypes.default.number,
    top: _propTypes.default.number
  }),
  /**
   * onScroll event handler.
   * @since 1.12.4
   */
  onScroll: _propTypes.default.func,
  /**
   * @ignore
   */
  className: _propTypes.default.string,
  /**
   * @ignore
   */
  baseClassName: _propTypes.default.string
};
CodeEditor.defaultProps = {
  mode: '',
  fileName: '',
  children: '',
  readOnly: false,
  autofocus: false,
  onInit: null,
  onChange: null,
  onSave: null,
  options: null,
  className: null,
  baseClassName: `${_constants.CLS_PREFIX}code-editor`,
  scrollPosition: undefined,
  onScroll: undefined
};
var _default = exports.default = CodeEditor;