validate = function(data = {}) {

	// Copy root object to avoid changes by reference
	data = Object.assign({}, data)

	if (data.inside == null) data.inside = () => {}
	if (data.outside == null) data.outside = () => {}
	if (data.direct == null) data.direct = false
	if (data.track == null) data.track = true
	if (data.props == null) data.props = {}

	if (data.from == null) throw new Error('Missing property `from`')
	if (data.to == null) throw new Error('Missing property `to`')
	if (typeof data.inside !== 'function') throw new Error('Property `inside` must be undefined or a function')
	if (typeof data.outside !== 'function') throw new Error('Property `outside` must be undefined or a function')
	if (typeof data.direct !== 'boolean' && data.direct instanceof HTMLElement === false) throw new Error('Property `direct` must be undefined, a boolean or a DOM element/node')
	if (data.direct === true && data.elem == null) throw new Error('Property `elem` is required when `direct` is true')
	if (typeof data.track !== 'boolean') throw new Error('Property `track` must be undefined or a boolean')
	if (typeof data.props !== 'object') throw new Error('Property `props` must be undefined or an object')

	if (data.elem == null) {

		if (isAbsoluteValue(data.from) === false) throw new Error('Property `from` must be a absolute value when no `elem` has been provided')
		if (isAbsoluteValue(data.to) === false) throw new Error('Property `to` must be a absolute value when no `elem` has been provided')

	} else {

		if (isRelativeValue(data.from) === true) data.from = relativeToAbsoluteValue(data.from, data.elem)
		if (isRelativeValue(data.to) === true) data.to = relativeToAbsoluteValue(data.to, data.elem)

	}

	data.from = parseAbsoluteValue(data.from)
	data.to = parseAbsoluteValue(data.to)

	// Create a new props object to avoid changes by reference
	data.props = Object.keys(data.props).reduce((acc, key) => {

		// Copy prop object to avoid changes by reference
		const prop = Object.assign({}, data.props[key])

		if (isAbsoluteValue(prop.from) === false) throw new Error('Property `from` of prop must be a absolute value')
		if (isAbsoluteValue(prop.to) === false) throw new Error('Property `from` of prop must be a absolute value')

		prop.from = parseAbsoluteValue(prop.from)
		prop.to = parseAbsoluteValue(prop.to)

		if (prop.timing == null) prop.timing = eases['linear']

		if (typeof prop.timing !== 'string' && typeof prop.timing !== 'function') throw new Error('Property `timing` of prop must be undefined, a string or a function')

		if (typeof prop.timing === 'string' && eases[prop.timing] == null) throw new Error('Unknown timing for property `timing` of prop')
		if (typeof prop.timing === 'string') prop.timing = eases[prop.timing]

		acc[key] = prop

		return acc

	}, {})

	return data

}
Validates data and sets defaults for undefined properties.
@param {?Object} data
@returns {Object} data - Validated data.