function define(tagNameOrFunction) {
    let createFunction, tagName;
    if (typeof tagNameOrFunction == 'function') {
      createFunction = tagNameOrFunction;
      tagName = '';
    } else {
      createFunction = createElementHelper;
      tagName = tagNameOrFunction;
    }

    /**
     * Creates a new UI element constructor.
     * @param {Object=} opt_propertyBag Optional bag of properties to set on the
     *     object after created. The property {@code ownerDocument} is special
     *     cased and it allows you to create the element in a different
     *     document than the default.
     * @constructor
     */
    function f(opt_propertyBag) {
      let el = createFunction(tagName, opt_propertyBag);
      f.decorate(el);
      for (let propertyName in opt_propertyBag) {
        el[propertyName] = opt_propertyBag[propertyName];
      }
      return el;
    }

    /**
     * Decorates an element as a UI element class.
     * @param {!Element} el The element to decorate.
     */
    f.decorate = function (el) {
      el.__proto__ = f.prototype;
      el.decorate();
    };

    return f;
  }
Creates the constructor for a UI element class.

Usage:
<pre>
var List = cr.ui.define('list');
List.prototype = {
  __proto__: HTMLUListElement.prototype,
  decorate: function() {
    ...
  },
  ...
};
</pre>

@param {string|Function} tagNameOrFunction The tagName or
    function to use for newly created elements. If this is a function it
    needs to return a new element when called.
@return {function(Object=):Element} The constructor function which takes
    an optional property bag. The function also has a static
    {@code decorate} method added to it.