<commit_before>/*
  Widgets are used to take control of the patching process, allowing the user
  to create stateful components, control sub-tree rendering, and hook into
  element removal.

  A Widget is a custom data structure for representing an
  object in a virtual tree.

  A Widget allows you to fully specify the semantics of
  intitialization of the object, updating of the object
  and destruction of the object.

  A Widget should generally be used for custom, performance
  critical code.

  type Widget : {
    type: "Widget",
    init: () => DOMElement,
    update: (previous: Widget, domNode: DOMElement) => void,
    destroy: (node: DOMElement) => void
  }
 */

import { h, create, diff, patch } from 'virtual-dom';
import DOMDelegator from 'dom-delegator';

export default class NeoWidget {
  static neo = true;

  static _components = {};

  static delegator = DOMDelegator({ document: document });

  static setComponents(components) {
    NeoWidget._components = components;
  }

  static jsx(jsxObject) {
    const Component = NeoWidget._components[jsxObject.elementName];

    if ((typeof Component === 'function') && (Component.neo === true)) {
      jsxObject.props = jsxObject.attributes;

      if (jsxObject.attributes.key) {
        jsxObject.key = jsxObject.props.key;
      }

      return new Component(jsxObject);
    }

    return h(jsxObject.elementName, jsxObject.attributes, jsxObject.children);
  };

  static _defaults() {
    return {
      elementName: 'DIV',
      type: 'Widget',
      attributes: null,
      children: null,
      props: null,
      _latestUpdateChange: null,
    };
  };

  constructor(config = {}) {
    Object.assign(this, NeoWidget._defaults(), config);
    Object.assign(this, { state: this.getInitialState() });
    this.props = Object.assign(this.getDefaultProps(), this.props);

    this.virtualNode = this.template();
    this.element = create(this.virtualNode, { document: document });

    if (this.isRoot) {
      this.componentDidMount();
    }
  }

  /* Required by virtual-dom.
   * The function called when the widget is being created.
   * Should return a DOM Element.
   * @private, @protected
   * @return DOMElement
   */
  init() {
    this.componentDidMount();
    return this.element;
  }

  /* Required by virtual-dom.
   * The function called when the widget is being updated.
   * @private, @protected
   * @param previous {Object} The previous Widget
   * @param domNode {DOMElement} The previous DOM Element associated with this widget
   */
  update(previous, domNode) {
    if (previous._latestUpdateChange) return;
    if (this.shouldComponentUpdate(previous.state) === false) return;

    let newTree = this.virtualNode;
    let patches = diff(previous.virtualNode, newTree);
    this.element = patch(domNode, patches);
    this.virtualNode = newTree;

    newTree = patches = null;
  }

  /* Required by virtual-dom.
   * The function called when the widget is being removed from the dom.
   * @protected, @override
   * @param domNode {DOMElement} The HTMLElement associated with the widget that will be removed
   */
  destroy(domNode) {
    this.componentDidUnMount();
    this.virtualNode = null;
    this.element = null;
  }

  render(element) {
    element.appendChild(this.element);
    return this;
  }

  /* Calls the _update method of its parent passing the nextState.
   * If it has no parent then it will run the _update method on itself
   * otherwise it will update the state of its parent before calling _update.
   * @public
   * @param nextState {Object}
   * @usage setState({mykey: 'my new value'})
   */
  setState(nextState) {
    if (typeof nextState === 'undefined') return;

    Object.assign(this.state, nextState);
    this._latestUpdateChange = true;

    let newTree = this.template();
    let patches = diff(this.virtualNode, newTree);
    this.element = patch(this.element, patches);
    this.virtualNode = newTree;

    newTree = patches = null;
  }

  /* @override
   */
  getInitialState() { return {}; }

  /* @override
   */
  getDefaultProps() { return {}; }

  /* @override
   */
  template() { return h('div'); }

  /* @override
   */
  componentDidMount() {}

  /* @override
   */
  componentDidUnMount() {}

  /* @override
   */
  shouldComponentUpdate(previousState) { return true; }
}<commit_msg>update / constructor + shouldComponentUpdate<commit_after>/*
  Widgets are used to take control of the patching process, allowing the user
  to create stateful components, control sub-tree rendering, and hook into
  element removal.

  A Widget is a custom data structure for representing an
  object in a virtual tree.

  A Widget allows you to fully specify the semantics of
  intitialization of the object, updating of the object
  and destruction of the object.

  A Widget should generally be used for custom, performance
  critical code.

  type Widget : {
    type: "Widget",
    init: () => DOMElement,
    update: (previous: Widget, domNode: DOMElement) => void,
    destroy: (node: DOMElement) => void
  }
 */

import { h, create, diff, patch } from 'virtual-dom';
import DOMDelegator from 'dom-delegator';

export default class NeoWidget {
  static _components = {};

  static delegator = DOMDelegator({ document });

  static setComponents(components) {
    NeoWidget._components = components;
  }

  static jsx(jsxObject) {
    const Component = NeoWidget._components[jsxObject.elementName];

    if (typeof Component === 'function') {
      return new Component(jsxObject);
    }

    return h(jsxObject.elementName, jsxObject.attributes, jsxObject.children);
  };

  constructor(config = {}) {
    this.type = 'Widget';
    Object.assign(this, config);
    this.state = this.getInitialState();
    this.props = Object.assign(this.getDefaultProps(), this.attributes);
    this._latestUpdateChange = null;

    if (typeof this.props.key !== 'undefined') {
      this.key = this.props.key;
    }

    this.virtualNode = this.template();
    this.element = create(this.virtualNode, { document });

    if (this.isRoot) {
      this.componentDidMount();
    }
  }

  /* Required by virtual-dom.
   * The function called when the widget is being created.
   * Should return a DOM Element.
   * @private, @protected
   * @return DOMElement
   */
  init() {
    this.componentDidMount();
    return this.element;
  }

  /* Required by virtual-dom.
   * The function called when the widget is being updated.
   * @private, @protected
   * @param previous {Object} The previous Widget
   * @param domNode {DOMElement} The previous DOM Element associated with this widget
   */
  update(previous, domNode) {
    if (previous._latestUpdateChange) return;
    if (!this.shouldComponentUpdate(previous.state, previous.props)) return;

    let newTree = this.virtualNode;
    let patches = diff(previous.virtualNode, newTree);
    this.element = patch(domNode, patches);
    this.virtualNode = newTree;

    newTree = patches = null;
  }

  /* Required by virtual-dom.
   * The function called when the widget is being removed from the dom.
   * @protected, @override
   * @param domNode {DOMElement} The HTMLElement associated with the widget that will be removed
   */
  destroy(domNode) {
    this.componentDidUnMount();
    this.virtualNode = null;
    this.element = null;
  }

  render(element) {
    element.appendChild(this.element);
    return this;
  }

  /* Calls the _update method of its parent passing the nextState.
   * If it has no parent then it will run the _update method on itself
   * otherwise it will update the state of its parent before calling _update.
   * @public
   * @param nextState {Object}
   * @usage setState({mykey: 'my new value'})
   */
  setState(nextState) {
    if (typeof nextState === 'undefined') return;
    if (!this.shouldComponentUpdate(nextState, this.props)) return;

    Object.assign(this.state, nextState);
    this._latestUpdateChange = true;

    let newTree = this.template();
    let patches = diff(this.virtualNode, newTree);
    this.element = patch(this.element, patches);
    this.virtualNode = newTree;

    newTree = patches = null;
  }

  /* @override
   */
  getInitialState() { return {}; }

  /* @override
   */
  getDefaultProps() { return {}; }

  /* @override
   */
  template() { return h('div'); }

  /* @override
   */
  componentDidMount() {}

  /* @override
   */
  componentDidUnMount() {}

  /* @override
   */
  shouldComponentUpdate(previousState, previousProps) { return true; }
}
{'fraction_non_alphanumeric': 0.11069241639189825, 'fraction_numerical': 0.0, 'mean_word_length': 3.2002967359050447, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4799075', 'n_tokens_mistral': 2496, 'n_tokens_neox': 2430, 'n_words': 759}