Home Reference Source Repository

src/createPropertyClass.js

import Shadow from "./Shadow";
import StateType from "./StateType";


/*
	Factory function for creating an Property subclass suitable for using with new.

	Parameters (all are optional):
		shadowType: one of a pojo or a class. This parameter defines the new property's shadow
			type. If pojo specified, each property and function is mapped onto a subclass of the
			BaseShadowClass parameter. The BaseShadowClass parameter is ignored if this parameter
			is a class.
		stateType: a StateType instance defining the Property
		specCallback: a callback function that will be passed the StateType spec for additional
			customization, such as setting autoshadow, initial state, or readonly.
		PropertyClass: the base class for defining the property. Must be a Property subclass.
		BaseShadowClass: The base shadow class for when shadowType parameter is not a class/function
			(default is Shadow)
*/
export default function createPropertyClass(
	shadowType,
	initialState,
	specCallback,
	PropertyClass,
	BaseShadowClass=Shadow)
{
	var ShadowClass;

	// get the shadow class
	if (typeof shadowType === 'function') {
		// shadow class passed into method
		ShadowClass = shadowType;
	} else {
		class CustomShadow extends BaseShadowClass { }

		var proto = CustomShadow.prototype;
		var names = Object.getOwnPropertyNames(shadowType);
		var name, desc;

		for (let i=0, len=names.length; i<len; i++) {
			name = names[i];
			desc = Object.getOwnPropertyDescriptor(shadowType, name);

			Object.defineProperty(proto, name, desc);
		}

		ShadowClass = CustomShadow;
	}

	// create the property subclass
	class CustomProperty extends PropertyClass {
		constructor(stateType) {
			super(stateType);

			this.setShadowClass(ShadowClass);
		}
	}

	// create the type class variable
	StateType.defineType(CustomProperty, spec => {
			if (initialState !== undefined) {
				spec.initialState(initialState);
			}

			if (specCallback) {
				specCallback(spec, CustomProperty);
			}
		});

	return CustomProperty;
}