<commit_before>'use strict'

let co = require('co')

class Base {
	constructor({mailClient, cfg, logger}) {
		this.defaults = {
			orderBy: 'id',
			orderDirection: 'DESC',
			page: 1,
			perPage: 10
		}
		this.cfg = cfg
		this.logger = logger
	}

	associate(components) {
		let rel = this.model.associate(components)
		this.relations = rel[rel.key]
		return rel.key
	}

	setDb(db) {
		this.db = db
	}

	generateHandle(name) {
		return name.toLowerCase().split(' ').join('-')
	}

	generateRandomNumber(length) {
		let number = ''
		for (let i = 0; i < length; i++) {
			number += Math.floor(Math.random() * 9)
		}
		return parseInt(number, 10)
	}

	generateRandomString(length) {
		let buf = new Buffer(length)
		for (let i = 0; i < buf.length; i++) {
			buf[i] = Math.floor(Math.random() * 256)
		}
		return buf
	}

	checkQueryItem({fieldData}) {
		if (typeof fieldData === 'undefined') {
			return false
		}

		if (typeof fieldData === 'object') {
			if (fieldData instanceof Array) {
				for (let i in fieldData) {
					if (typeof fieldData[i] === 'object') {
						return false
					}
				}
				return true
			}

			if ((typeof fieldData.$not !== 'undefined') && (typeof fieldData.$not !== 'object')) {
				return true
			}

			if (fieldData.$not instanceof Array) {
				let not = fieldData.$not
				for (let i in not) {
					if (typeof not[i] === 'object') {
						return false
					}
				}
				return true
			}

			if (fieldData.$and instanceof Array) {
				let and = fieldData.$and
				for (let i in and) {
					if ((typeof and[i] === 'object') && !this.checkQueryItem({fieldData: and[i]})) {
						return false
					}
				}
				return true
			}

			return false
		}

		return true
	}

	getWhereQuery({filters, relSearch, exactMatch}) {
		let where = {}
		if ((typeof filters === 'object') && Object.keys(filters).length > 0) {
			this.searchFields.forEach((element, index) => {
				let fieldData = filters[element.field],
					field = element.field,
					searchHolder = where,
					hasValue = this.checkQueryItem({fieldData})

				if (element.associatedModel && (hasValue || element.between)) {
					searchHolder = relSearch[element.associatedModel]
					field = element.associatedModelField
					if (element.nestedInclude) {
						if (!searchHolder.nestedIncludeFields) {
							searchHolder.nestedIncludeFields = {}
						}
						searchHolder = searchHolder.nestedIncludeFields
					}
				}

				if (hasValue) {
					if (element.like && (exactMatch.indexOf(element.field) === -1)) {
						let prefix = '',
							suffix = ''
						if (element.like[0] === '%') {
							prefix = '%'
						}
						if (element.like[1] === '%') {
							suffix = '%'
						}
						searchHolder[field] = {[element.caseSensitive ? '$like' : '$iLike']: `${prefix}${fieldData}${suffix}`}
						return;
					}
					searchHolder[field] = fieldData
					return;
				}

				if (element.between) {
					let from = {field: `${element.field}${element.between[0]}`, condition: '$gt'},
						to = {field: `${element.field}${element.between[1]}`, condition: '$lt'},
						clause = {}
					if (exactMatch.indexOf(field) !== -1) {
						from.condition = '$gte'
						to.condition = '$lte'
					} else {
						if (exactMatch.indexOf(from.field) !== -1) {
							from.condition = '$lte'
						}
						if (exactMatch.indexOf(to.field) !== -1) {
							to.condition = '$lte'
						}
					}
					if ((typeof filters[from.field] !== 'undefined') && (typeof filters[from.field] !== 'object')) {
						clause[from.condition] = filters[from.field]
					}
					if ((typeof filters[to.field] !== 'undefined') && (typeof filters[to.field] !== 'object')) {
						clause[to.condition] = filters[to.field]
					}
					if (Object.keys(clause).length > 0) {
						searchHolder[field] = clause
					}
				}
			})
		}
		return where
	}

	getIncludeQuery({data, rel, relSearch}) {
		let include = []
		this.relReadKeys.forEach((key, index) => {
			let relSearchLength = relSearch[key] && Object.keys(relSearch[key]).length || 0
			if (data[key] || relSearchLength) {
				let thisInclude = {},
					relS = relSearch[key]
				for (let iKey in rel[key].include) {
					thisInclude[iKey] = rel[key].include[iKey]
				}

				if (relSearchLength) {
					if (!thisInclude.where) {
						thisInclude.where = relS
					} else {
						for (let sKey in relS) {
							thisInclude.where[sKey] = relS[sKey]
						}
					}

					if (thisInclude.where.nestedIncludeFields) {
						delete thisInclude.where.nestedIncludeFields
						for (let sKey in relS.nestedIncludeFields) {
							if (!thisInclude.include.where) {
								thisInclude.include.where = relS.nestedIncludeFields
							} else {
								for (let sKey in relS.nestedIncludeFields) {
									thisInclude.include.where[sKey] = relS.nestedIncludeFields[sKey]
								}
							}
						}
					}
				}

				include.push(thisInclude)
			}
		})
		return include
	}

	create(data) {
		let instance = this
		return co(function*() {
			return yield instance.model.create(data)
		})
	}

	bulkCreate({dbObjects, options}) {
		let instance = this
		return co(function*() {
			let opt = {}
			if (options.transaction) {
				opt.transaction = options.transaction
			}
			return yield instance.model.bulkCreate(data, opt)
		})
	}

	read(data) {
		let instance = this
		return co(function*() {
			let where = {},
				include = [],
				rel = instance.relations,
				relSearch = {},
				exactMatch = (data.exactMatch instanceof Array) && data.exactMatch || []

			for (let key in rel) {
				relSearch[key] = {}
			}
			let options = {
				where: instance.getWhereQuery({filters: data, relSearch, exactMatch}),
				include: instance.getIncludeQuery({data, rel, relSearch})
			}

			return yield instance.model.findOne(options)
		})
	}

	readList(data) {
		let instance = this
		return co(function*() {
			let order = [
					[data.orderBy || instance.defaults.orderBy, data.orderDirection || instance.defaults.orderDirection]
				],
				page = data.page ? parseInt(data.page, 10) : instance.defaults.page,
				perPage = data.perPage ? parseInt(data.perPage, 10) : instance.defaults.perPage,
				include = [],
				more = false,
				rel = instance.relations,
				relSearch = {},
				filters = data.filters || {},
				exactMatch = (data.exactMatch instanceof Array) && data.exactMatch || [] //disables 'like' and makes 'between' >= <=, instead of > <

			for (let key in rel) {
				relSearch[key] = {}
			}

			let options = {
				where: instance.getWhereQuery({filters, relSearch, exactMatch}),
				include: instance.getIncludeQuery({data, rel, relSearch}),
				order
			}

			if (data.fields) {
				options.attributes = data.fields
			}

			if ((data.excludeIdsFromSearch instanceof Array) && data.excludeIdsFromSearch.length) {
				if (typeof options.where.id !== 'undefined') {
					options.where.id = {$and: [options.where.id, {$not: data.excludeIdsFromSearch}]}
				} else {
					options.where.id = {$not: data.excludeIdsFromSearch}
				}
			}

			let totalCount = yield instance.model.count({where: options.where, include: options.include}),
				totalPages = 0
			if (data.readAll) {
				totalPages = 1
				page = 1
				perPage = totalCount
			} else {
				totalPages = Math.ceil(totalCount / perPage)
				if ((totalPages > 0) && (page > totalPages)) {
					page = totalPages
				}
				options.offset = (page - 1) * perPage
				options.limit = perPage + 1
			}

			let results = yield instance.model.findAll(options)
			if (results.length === (perPage + 1)) {
				results.pop()
				more = true
			}
			return {totalPages, page, perPage, more, results}
		})
	}

	update({dbObject, where, transaction}) {
		let instance = this
		return co(function*() {
			if ((typeof where !== 'object') || (Object.keys(where).length === 0)) {
				throw {customMessage: 'Cannot update without criteria.'}
			}
			let options = {
				where,
				returning: true
			}
			if (transaction) {
				options.transaction = transaction
			}
			return yield instance.model.update(dbObject, options)
		})
	}

	delete(data) {
		let instance = this
		return co(function*() {
			return {deleted: yield instance.model.destroy({where: {id: data.id}})}
		})
	}
}

module.exports = Base
<commit_msg>association ordering support in the query builder<commit_after>'use strict'

let co = require('co')

class Base {
	constructor({mailClient, cfg, logger}) {
		this.defaults = {
			orderBy: 'id',
			orderDirection: 'DESC',
			page: 1,
			perPage: 10
		}
		this.cfg = cfg
		this.logger = logger
	}

	associate(components) {
		let rel = this.model.associate(components)
		this.relations = rel[rel.key]
		return rel.key
	}

	setDb(db) {
		this.db = db
	}

	generateHandle(name) {
		return name.toLowerCase().split(' ').join('-')
	}

	generateRandomNumber(length) {
		let number = ''
		for (let i = 0; i < length; i++) {
			number += Math.floor(Math.random() * 9)
		}
		return parseInt(number, 10)
	}

	generateRandomString(length) {
		let buf = new Buffer(length)
		for (let i = 0; i < buf.length; i++) {
			buf[i] = Math.floor(Math.random() * 256)
		}
		return buf
	}

	checkQueryItem({fieldData}) {
		if (typeof fieldData === 'undefined') {
			return false
		}

		if (typeof fieldData === 'object') {
			if (fieldData instanceof Array) {
				for (let i in fieldData) {
					if (typeof fieldData[i] === 'object') {
						return false
					}
				}
				return true
			}

			if ((typeof fieldData.$not !== 'undefined') && (typeof fieldData.$not !== 'object')) {
				return true
			}

			if (fieldData.$not instanceof Array) {
				let not = fieldData.$not
				for (let i in not) {
					if (typeof not[i] === 'object') {
						return false
					}
				}
				return true
			}

			if (fieldData.$and instanceof Array) {
				let and = fieldData.$and
				for (let i in and) {
					if ((typeof and[i] === 'object') && !this.checkQueryItem({fieldData: and[i]})) {
						return false
					}
				}
				return true
			}

			return false
		}

		return true
	}

	getWhereQuery({filters, relSearch, exactMatch}) {
		let where = {}
		if ((typeof filters === 'object') && Object.keys(filters).length > 0) {
			this.searchFields.forEach((element, index) => {
				let fieldData = filters[element.field],
					field = element.field,
					searchHolder = where,
					hasValue = this.checkQueryItem({fieldData})

				if (element.associatedModel && (hasValue || element.between)) {
					searchHolder = relSearch[element.associatedModel]
					field = element.associatedModelField
					if (element.nestedInclude) {
						if (!searchHolder.nestedIncludeFields) {
							searchHolder.nestedIncludeFields = {}
						}
						searchHolder = searchHolder.nestedIncludeFields
					}
				}

				if (hasValue) {
					if (element.like && (exactMatch.indexOf(element.field) === -1)) {
						let prefix = '',
							suffix = ''
						if (element.like[0] === '%') {
							prefix = '%'
						}
						if (element.like[1] === '%') {
							suffix = '%'
						}
						searchHolder[field] = {[element.caseSensitive ? '$like' : '$iLike']: `${prefix}${fieldData}${suffix}`}
						return;
					}
					searchHolder[field] = fieldData
					return;
				}

				if (element.between) {
					let from = {field: `${element.field}${element.between[0]}`, condition: '$gt'},
						to = {field: `${element.field}${element.between[1]}`, condition: '$lt'},
						clause = {}
					if (exactMatch.indexOf(field) !== -1) {
						from.condition = '$gte'
						to.condition = '$lte'
					} else {
						if (exactMatch.indexOf(from.field) !== -1) {
							from.condition = '$lte'
						}
						if (exactMatch.indexOf(to.field) !== -1) {
							to.condition = '$lte'
						}
					}
					if ((typeof filters[from.field] !== 'undefined') && (typeof filters[from.field] !== 'object')) {
						clause[from.condition] = filters[from.field]
					}
					if ((typeof filters[to.field] !== 'undefined') && (typeof filters[to.field] !== 'object')) {
						clause[to.condition] = filters[to.field]
					}
					if (Object.keys(clause).length > 0) {
						searchHolder[field] = clause
					}
				}
			})
		}
		return where
	}

	getIncludeQuery({data, rel, relSearch}) {
		let include = [],
			order = []
		this.relReadKeys.forEach((key, index) => {
			let relSearchLength = relSearch[key] && Object.keys(relSearch[key]).length || 0
			if (data[key] || relSearchLength) {
				let thisInclude = {},
					relS = relSearch[key]
				for (let iKey in rel[key].include) {
					if (iKey === 'order') {
						order = order.concat(rel[key].include[iKey])
						continue
					}
					thisInclude[iKey] = rel[key].include[iKey]
				}

				if (relSearchLength) {
					if (!thisInclude.where) {
						thisInclude.where = relS
					} else {
						for (let sKey in relS) {
							thisInclude.where[sKey] = relS[sKey]
						}
					}

					if (thisInclude.where.nestedIncludeFields) {
						delete thisInclude.where.nestedIncludeFields
						for (let sKey in relS.nestedIncludeFields) {
							if (!thisInclude.include.where) {
								thisInclude.include.where = relS.nestedIncludeFields
							} else {
								for (let sKey in relS.nestedIncludeFields) {
									thisInclude.include.where[sKey] = relS.nestedIncludeFields[sKey]
								}
							}
						}
					}
				}

				include.push(thisInclude)
			}
		})
		return {include, order}
	}

	create(data) {
		let instance = this
		return co(function*() {
			return yield instance.model.create(data)
		})
	}

	bulkCreate({dbObjects, options}) {
		let instance = this
		return co(function*() {
			let opt = {}
			if (options.transaction) {
				opt.transaction = options.transaction
			}
			return yield instance.model.bulkCreate(data, opt)
		})
	}

	read(data) {
		let instance = this
		return co(function*() {
			let where = {},
				include = [],
				rel = instance.relations,
				relSearch = {},
				exactMatch = (data.exactMatch instanceof Array) && data.exactMatch || []

			for (let key in rel) {
				relSearch[key] = {}
			}
			let includeQueryData = instance.getIncludeQuery({data, rel, relSearch}),
				options = {
					where: instance.getWhereQuery({filters: data, relSearch, exactMatch}),
					include: includeQueryData.include,
					order: includeQueryData.order
				}

			return yield instance.model.findOne(options)
		})
	}

	readList(data) {
		let instance = this
		return co(function*() {
			let order = [
					[data.orderBy || instance.defaults.orderBy, data.orderDirection || instance.defaults.orderDirection]
				],
				page = data.page ? parseInt(data.page, 10) : instance.defaults.page,
				perPage = data.perPage ? parseInt(data.perPage, 10) : instance.defaults.perPage,
				include = [],
				more = false,
				rel = instance.relations,
				relSearch = {},
				filters = data.filters || {},
				exactMatch = (data.exactMatch instanceof Array) && data.exactMatch || [] //disables 'like' and makes 'between' >= <=, instead of > <

			for (let key in rel) {
				relSearch[key] = {}
			}

			let includeQueryData = instance.getIncludeQuery({data, rel, relSearch}),
				options = {
					where: instance.getWhereQuery({filters, relSearch, exactMatch}),
					include: includeQueryData.include,
					order: order.concat(includeQueryData.order)
				}

			if (data.fields) {
				options.attributes = data.fields
			}

			if ((data.excludeIdsFromSearch instanceof Array) && data.excludeIdsFromSearch.length) {
				if (typeof options.where.id !== 'undefined') {
					options.where.id = {$and: [options.where.id, {$not: data.excludeIdsFromSearch}]}
				} else {
					options.where.id = {$not: data.excludeIdsFromSearch}
				}
			}

			let totalCount = yield instance.model.count({where: options.where, include: options.include}),
				totalPages = 0
			if (data.readAll) {
				totalPages = 1
				page = 1
				perPage = totalCount
			} else {
				totalPages = Math.ceil(totalCount / perPage)
				if ((totalPages > 0) && (page > totalPages)) {
					page = totalPages
				}
				options.offset = (page - 1) * perPage
				options.limit = perPage + 1
			}

			let results = yield instance.model.findAll(options)
			if (results.length === (perPage + 1)) {
				results.pop()
				more = true
			}
			return {totalPages, page, perPage, more, results}
		})
	}

	update({dbObject, where, transaction}) {
		let instance = this
		return co(function*() {
			if ((typeof where !== 'object') || (Object.keys(where).length === 0)) {
				throw {customMessage: 'Cannot update without criteria.'}
			}
			let options = {
				where,
				returning: true
			}
			if (transaction) {
				options.transaction = transaction
			}
			return yield instance.model.update(dbObject, options)
		})
	}

	delete(data) {
		let instance = this
		return co(function*() {
			return {deleted: yield instance.model.destroy({where: {id: data.id}})}
		})
	}
}

module.exports = Base
<|endoftext|>


<commit_before>// Reverse digits of an integer.

// Example1: x = 123, return 321
// Example2: x = -123, return -321
<commit_msg>add desc<commit_after>// Reverse digits of an integer.

// Example1: x = 123, return 321
// Example2: x = -123, return -321

// Have you thought about this?
// Here are some good questions to ask before coding. Bonus points for you if you have already thought through this!

// If the integer's last digit is 0, what should the output be? ie, cases such as 10, 100.

// Did you notice that the reversed integer might overflow? Assume the input is a 32-bit integer,
// then the reverse of 1000000003 overflows. How should you handle such cases?

// For the purpose of this problem, assume that your function returns 0 when the reversed integer overflows.
<|endoftext|>


<commit_before>// Copyright 2002-2015, University of Colorado Boulder
/**
 * @fileoverview Rule to check that the PhET copyright statement is present and correct
 * @author Sam Reid (PhET Interactive Simulations)
 * @copyright 2015 University of Colorado Boulder
 */

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

module.exports = function( context ) {
  'use strict';

  return {

    Program: function checkCopyright( node ) {
      // Get the whole source code, not for node only.
      var comments = context.getSourceCode().getAllComments();

      if ( !comments || comments.length === 0 ) {
        context.report( {
          node: node,
          loc: 1,
          message: 'Incorrect copyright statement in first comment'
        } );
      }
      else {
        // second year must be between 2010 and 2099, inclusive
        if ( ! / Copyright 2002-20[1-9]\d, University of Colorado Boulder/.test( comments[ 0 ].value ) ) {
          context.report( {
            node: node,
            loc: comments[ 0 ].loc.start,
            message: 'Incorrect copyright statement in first comment'
          } );
        }
      }
    }
  };

};

module.exports.schema = [
  // JSON Schema for rule options goes here
];<commit_msg>#394 add special chars for begin/end of input<commit_after>// Copyright 2002-2015, University of Colorado Boulder
/**
 * @fileoverview Rule to check that the PhET copyright statement is present and correct
 * @author Sam Reid (PhET Interactive Simulations)
 * @copyright 2015 University of Colorado Boulder
 */

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

module.exports = function( context ) {
  'use strict';

  return {

    Program: function checkCopyright( node ) {
      // Get the whole source code, not for node only.
      var comments = context.getSourceCode().getAllComments();

      if ( !comments || comments.length === 0 ) {
        context.report( {
          node: node,
          loc: 1,
          message: 'Incorrect copyright statement in first comment'
        } );
      }
      else {
        // second year must be between 2010 and 2099, inclusive
        if ( ! /^ Copyright 2002-20[1-9]\d, University of Colorado Boulder$/.test( comments[ 0 ].value ) ) {
          context.report( {
            node: node,
            loc: comments[ 0 ].loc.start,
            message: 'Incorrect copyright statement in first comment'
          } );
        }
      }
    }
  };

};

module.exports.schema = [
  // JSON Schema for rule options goes here
];<|endoftext|>


<commit_before>var util = require('util');
var utility = require('../utility.js');
var Emitter = require('../eventEmitter.js');
var ObservableCollection = require('../collections/observableCollection.js');

module.exports.type = type;
module.exports.create = create;

// itemType: The itemType info
function create(itemType) {
    return new CollectionValue(itemType);
}

function type(itemType) {
    return {
        name: 'collection',
        itemType: itemType,
        equals: function equals(other) {
            if(!other.hasOwnProperty('name') || !other.hasOwnProperty('itemType')) {
                return false;
            }

            return other.name === 'collection' && other.itemType.equals(this.itemType);
        }
    }
}

function create(itemType) {
    return new CollectionValue(itemType);
}

function CollectionValue(itemType) {
    Emitter.mixin(this);
    this.itemType = itemType;
    this._items = new ObservableCollection();
    this.type = type(itemType);

    Object.defineProperty(this, 'items', {
        get: function() {
            return this._value;
        },

        set: function(value) {
            if(value === this._value) {
                return;
            }

            this.emit('value-changing');
            this._value = value;
            this.emit('value-changed');
        }
    });

    this._itemsEvents = utility.events.forward({
        source: this_items,
        dest: this,
        events: ObservableCollection.events
    });

    this._itemsEvents.subscribe();
}

CollectionValue.prototype.clone = function clone() {
    // TODO: Copy the values
    return new CollectionValue(this.itemType);
}

CollectionValue.prototype.equals = function equals(other) {
    if(this === other) {
        return true;
    }

    if(!(other instanceof CollectionValue) || !this.itemType.equals(other.itemType)) {
        return false;
    }

    if(this._items.length != other._items.length) {
        return false;
    }

    for(var i = 0; i < this._items.length; i++) {
        try {
            if(!this._items[i].equals(other._items[i])) {
                return false;
            }
        } catch(e) {
            return false;
        }
    }

    return true;
}

CollectionValue.prototype.next = function next() {
    return this._items.next();
}

CollectionValue.prototype.add = function add(value) {
    if(!this.itemType.equals(value.type))
        throw new Error('Invalid item type for this collection');

    return this._items.next();
}

<commit_msg>Incremental checkin<commit_after>var util = require('util');
var utility = require('../utility.js');
var Emitter = require('../eventEmitter.js');
var ObservableCollection = require('../collections/observableCollection.js');

module.exports.type = type;
module.exports.create = create;

// itemType: The itemType info
function create(itemType) {
    return new CollectionValue(itemType);
}

function type(itemType) {
    return {
        name: 'collection',
        itemType: itemType,
        equals: function equals(other) {
            if(!other.hasOwnProperty('name') || !other.hasOwnProperty('itemType')) {
                return false;
            }

            return other.name === 'collection' && other.itemType.equals(this.itemType);
        }
    }
}

function create(itemType) {
    return new CollectionValue(itemType);
}

function CollectionValue(itemType) {
    Emitter.mixin(this);
    this.itemType = itemType;
    this._items = new ObservableCollection();
    this.type = type(itemType);

    Object.defineProperty(this, 'items', {
        get: function() {
            return this._value;
        },

        set: function(value) {
            if(value === this._value) {
                return;
            }

            this.emit('value-changing');
            this._value = value;
            this.emit('value-changed');
        }
    });

    this._itemsEvents = utility.events.forward({
        source: this._items,
        dest: this,
        events: ObservableCollection.events
    });

    this._itemsEvents.subscribe();
}

CollectionValue.prototype.clone = function clone() {
    // TODO: Copy the values
    return new CollectionValue(this.itemType);
}

CollectionValue.prototype.equals = function equals(other) {
    if(this === other) {
        return true;
    }

    if(!(other instanceof CollectionValue) || !this.itemType.equals(other.itemType)) {
        return false;
    }

    if(this._items.length != other._items.length) {
        return false;
    }

    for(var i = 0; i < this._items.length; i++) {
        try {
            if(!this._items[i].equals(other._items[i])) {
                return false;
            }
        } catch(e) {
            return false;
        }
    }

    return true;
}

CollectionValue.prototype.next = function next() {
    return this._items.next();
}

CollectionValue.prototype.add = function add(value) {
    if(!this.itemType.equals(value.type))
        throw new Error('Invalid item type for this collection');

    return this._items.next();
}

<|endoftext|>


<commit_before>import React, { Component, createElement } from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import omit from 'lodash.omit';
import {
  IconChevronUpSmallOutline,
  IconChevronDownSmallOutline,
  IconWarningBadgedSmallFilled,
} from '@teamleader/ui-icons';
import InputMetaPropTypes from './InputMetaPropTypes';
import Box from '../box';
import Counter from '../counter';
import { TextSmall } from '../typography';
import theme from './theme.css';

export default class Input extends Component {
  static propTypes = {
    bold: PropTypes.bool,
    className: PropTypes.string,
    counter: PropTypes.number,
    disabled: PropTypes.bool,
    helpText: PropTypes.string,
    icon: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
    iconPlacement: PropTypes.oneOf(['left', 'right']),
    id: PropTypes.string,
    inverse: PropTypes.bool,
    meta: InputMetaPropTypes,
    onBlur: PropTypes.func,
    onChange: PropTypes.func,
    onFocus: PropTypes.func,
    placeholder: PropTypes.string,
    readOnly: PropTypes.bool,
    size: PropTypes.oneOf(['small', 'medium', 'large']),
    step: PropTypes.number,
    type: PropTypes.string,
    value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  };

  static defaultProps = {
    iconPlacement: 'left',
    inverse: false,
    disabled: false,
    placeholder: '',
    readOnly: false,
    size: 'medium',
    step: 1,
  };

  constructor(props) {
    super(props);

    this.isNumberInput = Boolean(props.type === 'number');
    this.handleChange = ::this.onChange;
    this.handleIncreaseValue = ::this.increaseValue;
    this.handleDecreaseValue = ::this.decreaseValue;

    this.state = {
      value: this.isNumberInput ? Number(props.value) || '' : props.value || '',
    };
  }

  componentWillUpdate(props, state) {
    if (props.onChange && state.value) {
      props.onChange(state.value);
    }
  }

  onChange(event) {
    const value = event.target.value;

    this.setState(() => ({
      value: this.isNumberInput ? Number(value) : value,
    }));
  }

  increaseValue() {
    this.setState((previousState, props) => ({
      value: previousState.value ? previousState.value + props.step : props.step,
    }));
  }

  decreaseValue() {
    this.setState((previousState, props) => ({
      value: previousState.value ? previousState.value - props.step : -props.step,
    }));
  }

  renderInput() {
    const { bold, disabled, id, onBlur, onFocus, placeholder, readOnly, step, type } = this.props;
    const classNames = cx(theme['input'], {
      [theme['is-bold']]: bold,
    });
    const props = {
      className: classNames,
      disabled: disabled,
      id,
      onBlur: onBlur,
      onChange: this.handleChange,
      onFocus: onFocus,
      placeholder,
      readOnly,
      step,
      type,
      value: this.state.value,
    };

    return <input {...props} />;
  }

  renderCounter() {
    if (this.props.counter) {
      return <Counter className={theme.counter} count={this.props.counter} color="ruby" size="small" />;
    }
  }

  renderHelpText() {
    const { helpText, inverse } = this.props;

    return (
      helpText && (
        <TextSmall color={inverse ? 'white' : 'neutral'} marginTop={1} soft>
          {helpText}
        </TextSmall>
      )
    );
  }

  renderSpinnerControls() {
    if (this.isNumberInput) {
      return (

          <button className={theme['spinner-up']} onClick={this.handleIncreaseValue}>
            <IconChevronUpSmallOutline />
          </button>
          <button className={theme['spinner-down']} onClick={this.handleDecreaseValue}>
            <IconChevronDownSmallOutline />
          </button>

      );
    }
  }

  renderValidationMessage() {
    const { meta } = this.props;
    const props = {
      className: theme['validation-text'],
      marginTop: 2,
    };

    if (meta && meta.error) {
      return <TextSmall {...props}>{meta.error}</TextSmall>;
    }
  }

  renderValidationIcon() {
    if (this.props.meta && this.props.meta.error) {
      return <IconWarningBadgedSmallFilled className={theme['validation-icon']} />;
    }
  }

  render() {
    const { className, counter, disabled, icon, iconPlacement, inverse, size, meta, readOnly, ...others } = this.props;
    const classNames = cx(
      theme.wrapper,
      theme[`is-${size}`],
      {
        [theme[`has-icon-${iconPlacement}`]]: icon,
        [theme['has-counter']]: counter,
        [theme['has-error']]: Boolean(meta && meta.error),
        [theme['has-validation-feedback']]: Boolean(meta && meta.error),
        [theme['is-inverse']]: inverse,
        [theme['is-numeric']]: this.isNumberInput,
        [theme['is-disabled']]: disabled,
        [theme['is-read-only']]: readOnly,
      },
      className,
    );

    const rest = omit(others, [
      'bold',
      'id',
      'helpText',
      'onBlur',
      'onChange',
      'onFocus',
      'placeholder',
      'step',
      'type',
      'value',
    ]);

    return (
      <Box className={classNames} {...rest}>

          {icon &&
            createElement(icon, {
              className: theme.icon,
            })}

          {this.renderInput()}
          {this.renderCounter()}
          {this.renderSpinnerControls()}
          {this.renderValidationIcon()}

        {this.renderHelpText()}
        {this.renderValidationMessage()}
      </Box>
    );
  }
}
<commit_msg>Drop the 'if' and use '&&' instead<commit_after>import React, { Component, createElement } from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import omit from 'lodash.omit';
import {
  IconChevronUpSmallOutline,
  IconChevronDownSmallOutline,
  IconWarningBadgedSmallFilled,
} from '@teamleader/ui-icons';
import InputMetaPropTypes from './InputMetaPropTypes';
import Box from '../box';
import Counter from '../counter';
import { TextSmall } from '../typography';
import theme from './theme.css';

export default class Input extends Component {
  static propTypes = {
    bold: PropTypes.bool,
    className: PropTypes.string,
    counter: PropTypes.number,
    disabled: PropTypes.bool,
    helpText: PropTypes.string,
    icon: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
    iconPlacement: PropTypes.oneOf(['left', 'right']),
    id: PropTypes.string,
    inverse: PropTypes.bool,
    meta: InputMetaPropTypes,
    onBlur: PropTypes.func,
    onChange: PropTypes.func,
    onFocus: PropTypes.func,
    placeholder: PropTypes.string,
    readOnly: PropTypes.bool,
    size: PropTypes.oneOf(['small', 'medium', 'large']),
    step: PropTypes.number,
    type: PropTypes.string,
    value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  };

  static defaultProps = {
    iconPlacement: 'left',
    inverse: false,
    disabled: false,
    placeholder: '',
    readOnly: false,
    size: 'medium',
    step: 1,
  };

  constructor(props) {
    super(props);

    this.isNumberInput = Boolean(props.type === 'number');
    this.handleChange = ::this.onChange;
    this.handleIncreaseValue = ::this.increaseValue;
    this.handleDecreaseValue = ::this.decreaseValue;

    this.state = {
      value: this.isNumberInput ? Number(props.value) || '' : props.value || '',
    };
  }

  componentWillUpdate(props, state) {
    if (props.onChange && state.value) {
      props.onChange(state.value);
    }
  }

  onChange(event) {
    const value = event.target.value;

    this.setState(() => ({
      value: this.isNumberInput ? Number(value) : value,
    }));
  }

  increaseValue() {
    this.setState((previousState, props) => ({
      value: previousState.value ? previousState.value + props.step : props.step,
    }));
  }

  decreaseValue() {
    this.setState((previousState, props) => ({
      value: previousState.value ? previousState.value - props.step : -props.step,
    }));
  }

  renderInput() {
    const { bold, disabled, id, onBlur, onFocus, placeholder, readOnly, step, type } = this.props;
    const classNames = cx(theme['input'], {
      [theme['is-bold']]: bold,
    });
    const props = {
      className: classNames,
      disabled: disabled,
      id,
      onBlur: onBlur,
      onChange: this.handleChange,
      onFocus: onFocus,
      placeholder,
      readOnly,
      step,
      type,
      value: this.state.value,
    };

    return <input {...props} />;
  }

  renderCounter() {
    if (this.props.counter) {
      return <Counter className={theme.counter} count={this.props.counter} color="ruby" size="small" />;
    }
  }

  renderHelpText() {
    const { helpText, inverse } = this.props;

    return (
      helpText && (
        <TextSmall color={inverse ? 'white' : 'neutral'} marginTop={1} soft>
          {helpText}
        </TextSmall>
      )
    );
  }

  renderSpinnerControls() {
    return (
      this.isNumberInput && (

          <button className={theme['spinner-up']} onClick={this.handleIncreaseValue}>
            <IconChevronUpSmallOutline />
          </button>
          <button className={theme['spinner-down']} onClick={this.handleDecreaseValue}>
            <IconChevronDownSmallOutline />
          </button>

      )
    );
  }

  renderValidationMessage() {
    const { meta } = this.props;
    const props = {
      className: theme['validation-text'],
      marginTop: 2,
    };

    if (meta && meta.error) {
      return <TextSmall {...props}>{meta.error}</TextSmall>;
    }
  }

  renderValidationIcon() {
    if (this.props.meta && this.props.meta.error) {
      return <IconWarningBadgedSmallFilled className={theme['validation-icon']} />;
    }
  }

  render() {
    const { className, counter, disabled, icon, iconPlacement, inverse, size, meta, readOnly, ...others } = this.props;
    const classNames = cx(
      theme.wrapper,
      theme[`is-${size}`],
      {
        [theme[`has-icon-${iconPlacement}`]]: icon,
        [theme['has-counter']]: counter,
        [theme['has-error']]: Boolean(meta && meta.error),
        [theme['has-validation-feedback']]: Boolean(meta && meta.error),
        [theme['is-inverse']]: inverse,
        [theme['is-numeric']]: this.isNumberInput,
        [theme['is-disabled']]: disabled,
        [theme['is-read-only']]: readOnly,
      },
      className,
    );

    const rest = omit(others, [
      'bold',
      'id',
      'helpText',
      'onBlur',
      'onChange',
      'onFocus',
      'placeholder',
      'step',
      'type',
      'value',
    ]);

    return (
      <Box className={classNames} {...rest}>

          {icon &&
            createElement(icon, {
              className: theme.icon,
            })}

          {this.renderInput()}
          {this.renderCounter()}
          {this.renderSpinnerControls()}
          {this.renderValidationIcon()}

        {this.renderHelpText()}
        {this.renderValidationMessage()}
      </Box>
    );
  }
}
<|endoftext|>


<commit_before>// Copyright 2016, University of Colorado Boulder

/**
 * NOTE (AA): ModelElementImage is an EFAC Java class, but I have my doubts about
 * whether it really belongs here. It appears to be completely general.
 * TODO: Check with other devs about this. For now, rename to EFACModelImage and
 * tentatively make use of it.
 *
 * Class that provides information about an image that is used in the view
 * representation of a model element.
 *
 * @author John Blanco
 * @author  Andrew Adare
 */
define( function( require ) {
  'use strict';

  // Modules
  var inherit = require( 'PHET_CORE/inherit' );
  // var Image = require( 'SCENERY/nodes/Image' );
  var EFACConstants = require( 'ENERGY_FORMS_AND_CHANGES/common/EFACConstants' );
  // var Vector2 = require( 'DOT/Vector2' );

  // Constants
  // This is not used, but could be used to scale image.getImageWidth() to set
  // this.width.
  var DEFAULT_SCALE_FACTOR = 1 / EFACConstants.ENERGY_SYSTEMS_MVT_SCALE_FACTOR;

  /**
   * @param {Image}   image
   * @param {Vector2} centerToCenterOffset
   * @param {object} options
   * @constructor
   */
  function EFACModelImage( image, centerToCenterOffset, options ) {

    options = _.extend( {
      width: image.width * DEFAULT_SCALE_FACTOR,
      scale: 1.0
    }, options );

    this.image = image;

    // Width of the image in model units (meters).
    // Height is derived from aspect ratio of image.
    this.width = options.width;

    this.scale = options.scale;

    // Offset in model units (meters) from the center of the position of the
    // model element that owns this image to the center of the image.
    this.centerToCenterOffset = centerToCenterOffset;
  }

  return inherit( Object, EFACModelImage, {
    getHeight: function() {
      return ( this.width / this.image.getImageWidth() * this.image.getImageHeight() );
    }
  } );
} );
<commit_msg>Use .width, .height instead of getters<commit_after>// Copyright 2016, University of Colorado Boulder

/**
 * NOTE (AA): ModelElementImage is an EFAC Java class, but I have my doubts about
 * whether it really belongs here. It appears to be completely general.
 * TODO: Check with other devs about this. For now, rename to EFACModelImage and
 * tentatively make use of it.
 *
 * Class that provides information about an image that is used in the view
 * representation of a model element.
 *
 * @author John Blanco
 * @author  Andrew Adare
 */
define( function( require ) {
  'use strict';

  // Modules
  var inherit = require( 'PHET_CORE/inherit' );
  // var Image = require( 'SCENERY/nodes/Image' );
  var EFACConstants = require( 'ENERGY_FORMS_AND_CHANGES/common/EFACConstants' );
  // var Vector2 = require( 'DOT/Vector2' );

  // Constants
  // This is not used, but could be used to scale image.getImageWidth() to set
  // this.width.
  var DEFAULT_SCALE_FACTOR = 1 / EFACConstants.ENERGY_SYSTEMS_MVT_SCALE_FACTOR;

  /**
   * @param {Image}   image
   * @param {Vector2} centerToCenterOffset
   * @param {object} options
   * @constructor
   */
  function EFACModelImage( image, centerToCenterOffset, options ) {

    options = _.extend( {
      width: image.width * DEFAULT_SCALE_FACTOR,
      scale: 1.0
    }, options );

    this.image = image;

    // Width of the image in model units (meters).
    // Height is derived from aspect ratio of image.
    this.width = options.width;

    this.scale = options.scale;

    // Offset in model units (meters) from the center of the position of the
    // model element that owns this image to the center of the image.
    this.centerToCenterOffset = centerToCenterOffset;
  }

  return inherit( Object, EFACModelImage, {
    getHeight: function() {
      return ( this.width / this.image.width * this.image.height );
    }
  } );
} );
<|endoftext|>


<commit_before>"use strict";
module.exports =
{
	"env"   : { "es6" : true },
	// Use this comment to disable a rule in a file:	/* eslint-disable <rule> */
	// Use this comment to disable a rule for a block:	/* eslint-disable <rule> */   <YOUR BLOCK HERE, MULTIPLE LINES FINE>    /* eslint-enable <rule> */
	// Use this comment to disable a rule on a line:	// eslint-disable-line <rule>
	"rules" :
	{
		// Possible Errors
		"for-direction"               : 2,
		"getter-return"               : 0,
		"no-await-in-loop"            : 2,
		"no-compare-neg-zero"         : 2,
		"no-cond-assign"              : [2, "always"],
		"no-console"                  : 0,
		"no-constant-condition"       : [2, {"checkLoops" : false}],
		"no-control-regex"            : 2,
		"no-debugger"                 : 2,
		"no-dupe-args"                : 2,
		"no-dupe-keys"                : 2,
		"no-duplicate-case"           : 2,
		"no-empty"                    : [2, {"allowEmptyCatch" : true}],
		"no-empty-character-class"    : 2,
		"no-ex-assign"                : 2,
		"no-extra-boolean-cast"       : 2,
		"no-extra-parens"             : 0,
		"no-extra-semi"               : 2,
		"no-func-assign"              : 2,
		"no-inner-declarations"       : [2, "functions"],
		"no-invalid-regexp"           : 2,
		"no-irregular-whitespace"     : [2, {"skipStrings" : true, "skipTemplates" : true}],
		"no-obj-calls"                : 2,
		"no-prototype-builtins"       : 0,
		"no-regex-spaces"             : 2,
		"no-sparse-arrays"            : 2,
		"no-template-curly-in-string" : 2,
		"no-unexpected-multiline"     : 2,
		"no-unreachable"              : 2,
		"no-unsafe-finally"           : 2,
		"no-unsafe-negation"          : 2,
		"use-isnan"                   : 2,
		"valid-jsdoc"                 : 0,
		"valid-typeof"                : 2,

		// Best Practices
		"accessor-pairs"               : 0,
		"array-callback-return"        : 2,
		"block-scoped-var"             : 2,
		"class-methods-use-this"       : 0,
		"complexity"                   : 0,
		"consistent-return"            : 0,
		"curly"                        : [2, "multi-or-nest", "consistent"],
		"default-case"                 : 0,
		"dot-location"                 : [2, "object"],
		"dot-notation"                 : [2, {"allowKeywords" : false}],
		"eqeqeq"                       : [2, "always"],
		"guard-for-in"                 : 2,
		"no-alert"                     : 2,
		"no-caller"                    : 2,
		"no-case-declarations"         : 2,
		"no-div-regex"                 : 2,
		"no-else-return"               : 2,
		"no-empty-function"            : 0,
		"no-empty-pattern"             : 2,
		"no-eq-null"                   : 2,
		"no-eval"                      : 2,
		"no-extend-native"             : 0,
		"no-extra-bind"                : 2,
		"no-extra-label"               : 2,
		"no-fallthrough"               : 2,
		"no-floating-decimal"          : 2,
		"no-global-assign"             : 2,
		"no-implicit-coercion"         : 0,
		// "no-implicit-globals" : Handled in parents "node", "browser", "both"
		"no-implied-eval"              : 2,
		"no-invalid-this"              : 0,
		"no-iterator"                  : 2,
		"no-labels"                    : 2,
		"no-lone-blocks"               : 2,
		"no-loop-func"                 : 2,
		"no-magic-numbers"             : 0,
		"no-multi-spaces"              : 2,
		"no-multi-str"                 : 2,
		"no-new"                       : 2,
		"no-new-func"                  : 2,
		"no-new-wrappers"              : 2,
		"no-octal"                     : 2,
		"no-octal-escape"              : 2,
		"no-param-reassign"            : 2,
		"no-proto"                     : 2,
		"no-redeclare"                 : 2,
		"no-restricted-properties"     : 0,
		"no-return-assign"             : 2,
		"no-return-await"              : 2,
		"no-script-url"                : 2,
		"no-self-assign"               : 2,
		"no-self-compare"              : 2,
		"no-sequences"                 : 0,
		"no-throw-literal"             : 2,
		"no-unmodified-loop-condition" : 2,
		"no-unused-expressions"        : 2,
		"no-unused-labels"             : 2,
		"no-useless-call"              : 2,
		"no-useless-concat"            : 2,
		"no-useless-escape"            : 2,
		"no-useless-return"            : 2,
		"no-void"                      : 2,
		"no-warning-comments"          : 2,
		"no-with"                      : 2,
		"prefer-promise-reject-errors" : 0,
		"radix"                        : 2,
		"require-await"                : 2,
		"vars-on-top"                  : 2,
		"wrap-iife"                    : [2, "inside"],
		"yoda"                         : 2,

		// Strict Mode
		"strict" : [2, "global"],

		// Variables
		"init-declarations"          : [2, "always"],
		"no-catch-shadow"            : 0,
		"no-delete-var"              : 2,
		"no-label-var"               : 2,
		"no-restricted-globals"      : 0,
		"no-shadow"                  : 2,
		"no-shadow-restricted-names" : 2,
		"no-undef"                   : 2,
		"no-undef-init"              : 0,
		"no-undefined"               : 0,
		"no-unused-vars"             : [2, {"argsIgnorePattern" : "^[iI]gnored$|^e$|^err$", "varsIgnorePattern" : "^base$" }],
		"no-use-before-define"       : [2, {"functions" : false}],

		// Node.js and CommonJS : Handled in parents "node", "browser", "both"

		// Stylistic Issues
		"array-bracket-newline"            : 0,
		"array-bracket-spacing"            : [2, "never"],
		"array-element-newline"            : 0,
		"block-spacing"                    : 2,
		"brace-style"                      : [2, "allman", {"allowSingleLine" : true}],
		"camelcase"                        : [2, {properties : "always"}],
		"capitalized-comments"             : 0,
		"comma-dangle"                     : [2, "never"],
		"comma-spacing"                    : [2, { "before" : false, "after" : true }],
		"comma-style"                      : [2, "last"],
		"computed-property-spacing"        : [2, "never"],
		"consistent-this"                  : [2, "self"],
		"eol-last"                         : [2, "always"],
		"func-call-spacing"                : [2, "never"],
		"func-name-matching"               : 0,
		"func-names"                       : [2, "as-needed"],
		"func-style"                       : 0,
		"function-paren-newline"           : [2, "consistent"],
		"id-blacklist"                     : 0,
		"id-length"                        : 0,
		"id-match"                         : 0,
		"indent"                           : [2, "tab"],
		"jsx-quotes"                       : 0,
		"key-spacing"                      : [2, {"beforeColon" : true, "afterColon" : true, "mode" : "minimum"}],
		"keyword-spacing"                  : 0,
		"line-comment-position"            : 0,
		"linebreak-style"                  : [2, "unix"],
		"lines-around-comment"             : 0,
		"max-depth"                        : [2, 4],
		"max-len"                          : [2, 271],
		"max-lines"                        : 0,
		"max-nested-callbacks"             : [2, 5],
		"max-params"                       : [2, 7],
		"max-statements"                   : 0,
		"max-statements-per-line"          : 0,
		"multiline-ternary"                : [2, "never"],
		"new-cap"                          : 2,
		"new-parens"                       : 2,
		"newline-per-chained-call"         : 0,
		"no-array-constructor"             : 2,
		"no-bitwise"                       : 2,
		"no-continue"                      : 0,
		"no-inline-comments"               : 0,
		"no-lonely-if"                     : 2,
		"no-mixed-operators"               : 2,
		"no-mixed-spaces-and-tabs"         : [2, "smart-tabs"],
		"no-multi-assign"                  : 0,
		"no-multiple-empty-lines"          : 2,
		"no-negated-condition"             : 0,
		"no-nested-ternary"                : 0,
		"no-new-object"                    : 2,
		"no-plusplus"                      : 0,
		"no-restricted-syntax"             : 0,
		"no-tabs"                          : 0,
		"no-ternary"                       : 0,
		"no-trailing-spaces"               : [2, {"skipBlankLines" : true}],
		"no-underscore-dangle"             : [2, { "allow" : ["_gsTransform"]}],
		"no-unneeded-ternary"              : 2,
		"no-whitespace-before-property"    : 2,
		"nonblock-statement-body-position" : [2, "below"],
		"object-curly-newline"             : 0,
		"object-curly-spacing"             : 0,
		"object-property-newline"          : 0,
		"one-var"                          : 0,
		"one-var-declaration-per-line"     : 0,
		"operator-assignment"              : 0,
		"operator-linebreak"               : 0,
		"padded-blocks"                    : [2, "never"],
		"padding-line-between-statements"  : 0,
		"quote-props"                      : 0,
		"quotes"                           : [2, "double", {"avoidEscape" : true}],
		"require-jsdoc"                    : 0,
		"semi"                             : [2, "always"],
		"semi-spacing"                     : 0,
		"semi-style"                       : [2, "last"],
		"sort-keys"                        : 0,
		"sort-vars"                        : 0,
		"space-before-blocks"              : [2, "always"],
		"space-before-function-paren"      : [2, "never"],
		"space-in-parens"                  : 0,
		"space-infix-ops"                  : 0,
		"space-unary-ops"                  : 2,
		"spaced-comment"                   : 0,
		"switch-colon-spacing"             : [2, {"after" : true, "before" : false}],
		"template-tag-spacing"             : 2,
		"unicode-bom"                      : 0,
		"wrap-regex"                       : 2,

		// ECMAScript 6
		"arrow-body-style"        : [2, "as-needed"],
		"arrow-parens"            : [2, "as-needed"],
		"arrow-spacing"           : [2, {"before" : true, "after" : true}],
		"constructor-super"       : 2,
		"generator-star-spacing"  : 0,
		"no-class-assign"         : 2,
		"no-confusing-arrow"      : [2, {"allowParens" : true}],
		"no-const-assign"         : 2,
		"no-dupe-class-members"   : 2,
		"no-duplicate-imports"    : 2,
		"no-new-symbol"           : 2,
		"no-restricted-imports"   : 0,
		"no-this-before-super"    : 2,
		"no-useless-computed-key" : 2,
		"no-useless-constructor"  : 2,
		"no-useless-rename"       : 0,
		"no-var"                  : 2,
		"object-shorthand"        : [2, "always"],
		"prefer-arrow-callback"   : [2, {"allowNamedFunctions" : true}],
		"prefer-const"            : 2,
		"prefer-destructuring"    : 0,
		"prefer-numeric-literals" : 2,
		"prefer-rest-params"      : 2,
		"prefer-spread"           : 2,
		"prefer-template"         : 0,
		"require-yield"           : 2,
		"rest-spread-spacing"     : [2, "never"],
		"sort-imports"            : 0,
		"symbol-description"      : 0,
		"template-curly-spacing"  : [2, "never"],
		"yield-star-spacing"      : 0
	}
};
<commit_msg>Updated shared eslint with new features from latest eslint<commit_after>"use strict";
module.exports =
{
	"env"   : { "es6" : true },
	// Use this comment to disable a rule in a file:	/* eslint-disable <rule> */
	// Use this comment to disable a rule for a block:	/* eslint-disable <rule> */   <YOUR BLOCK HERE, MULTIPLE LINES FINE>    /* eslint-enable <rule> */
	// Use this comment to disable a rule on a line:	// eslint-disable-line <rule>

	// 0 == off
	// 1 == warn
	// 2 == error

	"rules" :
	{
		// New
		"multiline-comment-style"     : 0,
		"implicit-arrow-linebreak"    : 0,

		// Possible Errors
		"for-direction"               : 2,
		"getter-return"               : 0,
		"no-await-in-loop"            : 2,
		"no-compare-neg-zero"         : 2,
		"no-cond-assign"              : [2, "always"],
		"no-console"                  : 0,
		"no-constant-condition"       : [2, {"checkLoops" : false}],
		"no-control-regex"            : 2,
		"no-debugger"                 : 2,
		"no-dupe-args"                : 2,
		"no-dupe-keys"                : 2,
		"no-duplicate-case"           : 2,
		"no-empty"                    : [2, {"allowEmptyCatch" : true}],
		"no-empty-character-class"    : 2,
		"no-ex-assign"                : 2,
		"no-extra-boolean-cast"       : 2,
		"no-extra-parens"             : 0,
		"no-extra-semi"               : 2,
		"no-func-assign"              : 2,
		"no-inner-declarations"       : [2, "functions"],
		"no-invalid-regexp"           : 2,
		"no-irregular-whitespace"     : [2, {"skipStrings" : true, "skipTemplates" : true}],
		"no-obj-calls"                : 2,
		"no-prototype-builtins"       : 0,
		"no-regex-spaces"             : 2,
		"no-sparse-arrays"            : 2,
		"no-template-curly-in-string" : 2,
		"no-unexpected-multiline"     : 2,
		"no-unreachable"              : 2,
		"no-unsafe-finally"           : 2,
		"no-unsafe-negation"          : 2,
		"use-isnan"                   : 2,
		"valid-jsdoc"                 : 0,
		"valid-typeof"                : 2,

		// Best Practices
		"accessor-pairs"               : 0,
		"array-callback-return"        : 2,
		"block-scoped-var"             : 2,
		"class-methods-use-this"       : 0,
		"complexity"                   : 0,
		"consistent-return"            : 0,
		"curly"                        : [2, "multi-or-nest", "consistent"],
		"default-case"                 : 0,
		"dot-location"                 : [2, "object"],
		"dot-notation"                 : [2, {"allowKeywords" : false}],
		"eqeqeq"                       : [2, "always"],
		"guard-for-in"                 : 2,
		"no-alert"                     : 2,
		"no-caller"                    : 2,
		"no-case-declarations"         : 2,
		"no-div-regex"                 : 2,
		"no-else-return"               : 2,
		"no-empty-function"            : 0,
		"no-empty-pattern"             : 2,
		"no-eq-null"                   : 2,
		"no-eval"                      : 2,
		"no-extend-native"             : 0,
		"no-extra-bind"                : 2,
		"no-extra-label"               : 2,
		"no-fallthrough"               : 2,
		"no-floating-decimal"          : 2,
		"no-global-assign"             : 2,
		"no-implicit-coercion"         : 0,
		// "no-implicit-globals" : Handled in parents "node", "browser", "both"
		"no-implied-eval"              : 2,
		"no-invalid-this"              : 0,
		"no-iterator"                  : 2,
		"no-labels"                    : 2,
		"no-lone-blocks"               : 2,
		"no-loop-func"                 : 2,
		"no-magic-numbers"             : 0,
		"no-multi-spaces"              : 2,
		"no-multi-str"                 : 2,
		"no-new"                       : 2,
		"no-new-func"                  : 2,
		"no-new-wrappers"              : 2,
		"no-octal"                     : 2,
		"no-octal-escape"              : 2,
		"no-param-reassign"            : 2,
		"no-proto"                     : 2,
		"no-redeclare"                 : 2,
		"no-restricted-properties"     : 0,
		"no-return-assign"             : 2,
		"no-return-await"              : 2,
		"no-script-url"                : 2,
		"no-self-assign"               : 2,
		"no-self-compare"              : 2,
		"no-sequences"                 : 0,
		"no-throw-literal"             : 2,
		"no-unmodified-loop-condition" : 2,
		"no-unused-expressions"        : 2,
		"no-unused-labels"             : 2,
		"no-useless-call"              : 2,
		"no-useless-concat"            : 2,
		"no-useless-escape"            : 2,
		"no-useless-return"            : 2,
		"no-void"                      : 2,
		"no-warning-comments"          : 2,
		"no-with"                      : 2,
		"prefer-promise-reject-errors" : 0,
		"radix"                        : 2,
		"require-await"                : 2,
		"vars-on-top"                  : 2,
		"wrap-iife"                    : [2, "inside"],
		"yoda"                         : 2,

		// Strict Mode
		"strict" : [2, "global"],

		// Variables
		"init-declarations"          : [2, "always"],
		"no-catch-shadow"            : 0,
		"no-delete-var"              : 2,
		"no-label-var"               : 2,
		"no-restricted-globals"      : 0,
		"no-shadow"                  : 2,
		"no-shadow-restricted-names" : 2,
		"no-undef"                   : 2,
		"no-undef-init"              : 0,
		"no-undefined"               : 0,
		"no-unused-vars"             : [2, {"argsIgnorePattern" : "^[iI]gnored$|^e$|^err$", "varsIgnorePattern" : "^base$" }],
		"no-use-before-define"       : [2, {"functions" : false}],

		// Node.js and CommonJS : Handled in parents "node", "browser", "both"

		// Stylistic Issues
		"array-bracket-newline"            : 0,
		"array-bracket-spacing"            : [2, "never"],
		"array-element-newline"            : 0,
		"block-spacing"                    : 2,
		"brace-style"                      : [2, "allman", {"allowSingleLine" : true}],
		"camelcase"                        : [2, {properties : "always"}],
		"capitalized-comments"             : 0,
		"comma-dangle"                     : [2, "never"],
		"comma-spacing"                    : [2, { "before" : false, "after" : true }],
		"comma-style"                      : [2, "last"],
		"computed-property-spacing"        : [2, "never"],
		"consistent-this"                  : [2, "self"],
		"eol-last"                         : [2, "always"],
		"func-call-spacing"                : [2, "never"],
		"func-name-matching"               : 0,
		"func-names"                       : [2, "as-needed"],
		"func-style"                       : 0,
		"function-paren-newline"           : [2, "consistent"],
		"id-blacklist"                     : 0,
		"id-length"                        : 0,
		"id-match"                         : 0,
		"indent"                           : [2, "tab"],
		"jsx-quotes"                       : 0,
		"key-spacing"                      : [2, {"beforeColon" : true, "afterColon" : true, "mode" : "minimum"}],
		"keyword-spacing"                  : 0,
		"line-comment-position"            : 0,
		"linebreak-style"                  : [2, "unix"],
		"lines-around-comment"             : 0,
		"max-depth"                        : [2, 4],
		"max-len"                          : [2, 271],
		"max-lines"                        : 0,
		"max-nested-callbacks"             : [2, 5],
		"max-params"                       : [2, 7],
		"max-statements"                   : 0,
		"max-statements-per-line"          : 0,
		"multiline-ternary"                : [2, "never"],
		"new-cap"                          : 2,
		"new-parens"                       : 2,
		"newline-per-chained-call"         : 0,
		"no-array-constructor"             : 2,
		"no-bitwise"                       : 2,
		"no-continue"                      : 0,
		"no-inline-comments"               : 0,
		"no-lonely-if"                     : 2,
		"no-mixed-operators"               : 2,
		"no-mixed-spaces-and-tabs"         : [2, "smart-tabs"],
		"no-multi-assign"                  : 0,
		"no-multiple-empty-lines"          : 2,
		"no-negated-condition"             : 0,
		"no-nested-ternary"                : 0,
		"no-new-object"                    : 2,
		"no-plusplus"                      : 0,
		"no-restricted-syntax"             : 0,
		"no-tabs"                          : 0,
		"no-ternary"                       : 0,
		"no-trailing-spaces"               : [2, {"skipBlankLines" : true}],
		"no-underscore-dangle"             : [2, { "allow" : ["_gsTransform"]}],
		"no-unneeded-ternary"              : 2,
		"no-whitespace-before-property"    : 2,
		"nonblock-statement-body-position" : [2, "below"],
		"object-curly-newline"             : 0,
		"object-curly-spacing"             : 0,
		"object-property-newline"          : 0,
		"one-var"                          : 0,
		"one-var-declaration-per-line"     : 0,
		"operator-assignment"              : 0,
		"operator-linebreak"               : 0,
		"padded-blocks"                    : [2, "never"],
		"padding-line-between-statements"  : 0,
		"quote-props"                      : 0,
		"quotes"                           : [2, "double", {"avoidEscape" : true}],
		"require-jsdoc"                    : 0,
		"semi"                             : [2, "always"],
		"semi-spacing"                     : 0,
		"semi-style"                       : [2, "last"],
		"sort-keys"                        : 0,
		"sort-vars"                        : 0,
		"space-before-blocks"              : [2, "always"],
		"space-before-function-paren"      : [2, "never"],
		"space-in-parens"                  : 0,
		"space-infix-ops"                  : 0,
		"space-unary-ops"                  : 2,
		"spaced-comment"                   : 0,
		"switch-colon-spacing"             : [2, {"after" : true, "before" : false}],
		"template-tag-spacing"             : 2,
		"unicode-bom"                      : 0,
		"wrap-regex"                       : 2,

		// ECMAScript 6
		"arrow-body-style"        : [2, "as-needed"],
		"arrow-parens"            : [2, "as-needed"],
		"arrow-spacing"           : [2, {"before" : true, "after" : true}],
		"constructor-super"       : 2,
		"generator-star-spacing"  : 0,
		"no-class-assign"         : 2,
		"no-confusing-arrow"      : [2, {"allowParens" : true}],
		"no-const-assign"         : 2,
		"no-dupe-class-members"   : 2,
		"no-duplicate-imports"    : 2,
		"no-new-symbol"           : 2,
		"no-restricted-imports"   : 0,
		"no-this-before-super"    : 2,
		"no-useless-computed-key" : 2,
		"no-useless-constructor"  : 2,
		"no-useless-rename"       : 0,
		"no-var"                  : 2,
		"object-shorthand"        : [2, "always"],
		"prefer-arrow-callback"   : [2, {"allowNamedFunctions" : true}],
		"prefer-const"            : 2,
		"prefer-destructuring"    : 0,
		"prefer-numeric-literals" : 2,
		"prefer-rest-params"      : 2,
		"prefer-spread"           : 2,
		"prefer-template"         : 0,
		"require-yield"           : 2,
		"rest-spread-spacing"     : [2, "never"],
		"sort-imports"            : 0,
		"symbol-description"      : 0,
		"template-curly-spacing"  : [2, "never"],
		"yield-star-spacing"      : 0
	}
};
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { themr } from 'react-css-themr';
import { INPUT } from '../identifiers';
import InjectedFontIcon from '../font_icon/FontIcon';

const factory = (FontIcon) => {
  class Input extends React.Component {
    static propTypes = {
      children: PropTypes.node,
      className: PropTypes.string,
      defaultValue: PropTypes.string,
      disabled: PropTypes.bool,
      error: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.node,
      ]),
      floating: PropTypes.bool,
      hint: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.node,
      ]),
      icon: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.element,
      ]),
      label: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.node,
      ]),
      maxLength: PropTypes.number,
      multiline: PropTypes.bool,
      name: PropTypes.string,
      onBlur: PropTypes.func,
      onChange: PropTypes.func,
      onFocus: PropTypes.func,
      onKeyPress: PropTypes.func,
      required: PropTypes.bool,
      role: PropTypes.string,
      rows: PropTypes.number,
      theme: PropTypes.shape({
        bar: PropTypes.string,
        counter: PropTypes.string,
        disabled: PropTypes.string,
        error: PropTypes.string,
        errored: PropTypes.string,
        hidden: PropTypes.string,
        hint: PropTypes.string,
        icon: PropTypes.string,
        input: PropTypes.string,
        inputElement: PropTypes.string,
        required: PropTypes.string,
        withIcon: PropTypes.string,
      }),
      type: PropTypes.string,
      value: PropTypes.oneOfType([
        PropTypes.number,
        PropTypes.object,
        PropTypes.string,
      ]),
    };

    static defaultProps = {
      className: '',
      hint: '',
      disabled: false,
      floating: true,
      multiline: false,
      required: false,
      role: 'input',
      type: 'text',
    };

    componentDidMount() {
      if (this.props.multiline) {
        window.addEventListener('resize', this.handleAutoresize);
        this.handleAutoresize();
      }
    }

    componentWillReceiveProps(nextProps) {
      if (!this.props.multiline && nextProps.multiline) {
        window.addEventListener('resize', this.handleAutoresize);
      } else if (this.props.multiline && !nextProps.multiline) {
        window.removeEventListener('resize', this.handleAutoresize);
      }
    }

    componentDidUpdate() {
      // resize the textarea, if nessesary
      if (this.props.multiline) this.handleAutoresize();
    }

    componentWillUnmount() {
      if (this.props.multiline) window.removeEventListener('resize', this.handleAutoresize);
    }

    handleChange = (event) => {
      const { onChange, multiline, maxLength } = this.props;
      const valueFromEvent = event.target.value;

      // Trim value to maxLength if that exists (only on multiline inputs).
      // Note that this is still required even tho we have the onKeyPress filter
      // because the user could paste smt in the textarea.
      const haveToTrim = (multiline && maxLength && event.target.value.length > maxLength);
      const value = haveToTrim ? valueFromEvent.substr(0, maxLength) : valueFromEvent;

      // propagate to to store and therefore to the input
      if (onChange) onChange(value, event);
    };

    handleAutoresize = () => {
      const element = this.inputNode;
      const rows = this.props.rows;

      if (typeof rows === 'number' && !isNaN(rows)) {
        element.style.height = null;
      } else {
        // compute the height difference between inner height and outer height
        const style = getComputedStyle(element, null);
        const heightOffset = style.boxSizing === 'content-box'
          ? -(parseFloat(style.paddingTop) + parseFloat(style.paddingBottom))
          : parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);

        // resize the input to its content size
        element.style.height = 'auto';
        element.style.height = `${element.scrollHeight + heightOffset}px`;
      }
    }

    handleKeyPress = (event) => {
      // prevent insertion of more characters if we're a multiline input
      // and maxLength exists
      const { multiline, maxLength, onKeyPress } = this.props;
      if (multiline && maxLength) {
        // check if smt is selected, in which case the newly added charcter would
        // replace the selected characters, so the length of value doesn't actually
        // increase.
        const isReplacing = event.target.selectionEnd - event.target.selectionStart;
        const value = event.target.value;

        if (!isReplacing && value.length === maxLength) {
          event.preventDefault();
          event.stopPropagation();
          return undefined;
        }
      }

      if (onKeyPress) onKeyPress(event);
      return undefined;
    };

    blur() {
      this.inputNode.blur();
    }

    focus() {
      this.inputNode.focus();
    }

    valuePresent = value => (
      value !== null
        && value !== undefined
        && value !== ''
        && !(typeof value === 'number' && isNaN(value))
    )

    render() {
      const { children, defaultValue, disabled, error, floating, hint, icon,
              name, label: labelText, maxLength, multiline, required, role,
              theme, type, value, onKeyPress, rows = 1, ...others } = this.props;
      const length = maxLength && value ? value.length : 0;
      const labelClassName = classnames(theme.label, { [theme.fixed]: !floating });

      const className = classnames(theme.input, {
        [theme.disabled]: disabled,
        [theme.errored]: error,
        [theme.hidden]: type === 'hidden',
        [theme.withIcon]: icon,
      }, this.props.className);

      const valuePresent = this.valuePresent(value) || this.valuePresent(defaultValue);

      const inputElementProps = {
        ...others,
        className: classnames(theme.inputElement, { [theme.filled]: valuePresent }),
        onChange: this.handleChange,
        ref: (node) => { this.inputNode = node; },
        role,
        name,
        defaultValue,
        disabled,
        required,
        type,
        value,
      };
      if (!multiline) {
        inputElementProps.maxLength = maxLength;
        inputElementProps.onKeyPress = onKeyPress;
      } else {
        inputElementProps.rows = rows;
        inputElementProps.onKeyPress = this.handleKeyPress;
      }

      return (

          {React.createElement(multiline ? 'textarea' : 'input', inputElementProps)}
          {icon ? <FontIcon className={theme.icon} value={icon} /> : null}

          {labelText
            ?
              {labelText}
              {required ?  *  : null}

            : null}
          {hint ? {hint} : null}
          {error ? {error} : null}
          {maxLength ? {length}/{maxLength} : null}
          {children}

      );
    }
  }

  return Input;
};

const Input = factory(InjectedFontIcon);
export default themr(INPUT)(Input);
export { factory as inputFactory };
export { Input };
<commit_msg>Enforce max length on input in js.<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { themr } from 'react-css-themr';
import { INPUT } from '../identifiers';
import InjectedFontIcon from '../font_icon/FontIcon';

const factory = (FontIcon) => {
  class Input extends React.Component {
    static propTypes = {
      children: PropTypes.node,
      className: PropTypes.string,
      defaultValue: PropTypes.string,
      disabled: PropTypes.bool,
      error: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.node,
      ]),
      floating: PropTypes.bool,
      hint: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.node,
      ]),
      icon: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.element,
      ]),
      label: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.node,
      ]),
      maxLength: PropTypes.number,
      multiline: PropTypes.bool,
      name: PropTypes.string,
      onBlur: PropTypes.func,
      onChange: PropTypes.func,
      onFocus: PropTypes.func,
      onKeyPress: PropTypes.func,
      required: PropTypes.bool,
      role: PropTypes.string,
      rows: PropTypes.number,
      theme: PropTypes.shape({
        bar: PropTypes.string,
        counter: PropTypes.string,
        disabled: PropTypes.string,
        error: PropTypes.string,
        errored: PropTypes.string,
        hidden: PropTypes.string,
        hint: PropTypes.string,
        icon: PropTypes.string,
        input: PropTypes.string,
        inputElement: PropTypes.string,
        required: PropTypes.string,
        withIcon: PropTypes.string,
      }),
      type: PropTypes.string,
      value: PropTypes.oneOfType([
        PropTypes.number,
        PropTypes.object,
        PropTypes.string,
      ]),
    };

    static defaultProps = {
      className: '',
      hint: '',
      disabled: false,
      floating: true,
      multiline: false,
      required: false,
      role: 'input',
      type: 'text',
    };

    componentDidMount() {
      if (this.props.multiline) {
        window.addEventListener('resize', this.handleAutoresize);
        this.handleAutoresize();
      }
    }

    componentWillReceiveProps(nextProps) {
      if (!this.props.multiline && nextProps.multiline) {
        window.addEventListener('resize', this.handleAutoresize);
      } else if (this.props.multiline && !nextProps.multiline) {
        window.removeEventListener('resize', this.handleAutoresize);
      }
    }

    componentDidUpdate() {
      // resize the textarea, if nessesary
      if (this.props.multiline) this.handleAutoresize();
    }

    componentWillUnmount() {
      if (this.props.multiline) window.removeEventListener('resize', this.handleAutoresize);
    }

    handleChange = (event) => {
      const { onChange, maxLength } = this.props;
      const valueFromEvent = event.target.value;

      // Trim value to maxLength if that exists (only on multiline inputs).
      // Note that this is still required even tho we have the onKeyPress filter
      // because the user could paste smt in the textarea.
      const haveToTrim = (maxLength && event.target.value.length > maxLength);
      const value = haveToTrim ? valueFromEvent.substr(0, maxLength) : valueFromEvent;

      // propagate to to store and therefore to the input
      if (onChange) onChange(value, event);
    };

    handleAutoresize = () => {
      const element = this.inputNode;
      const rows = this.props.rows;

      if (typeof rows === 'number' && !isNaN(rows)) {
        element.style.height = null;
      } else {
        // compute the height difference between inner height and outer height
        const style = getComputedStyle(element, null);
        const heightOffset = style.boxSizing === 'content-box'
          ? -(parseFloat(style.paddingTop) + parseFloat(style.paddingBottom))
          : parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);

        // resize the input to its content size
        element.style.height = 'auto';
        element.style.height = `${element.scrollHeight + heightOffset}px`;
      }
    }

    handleKeyPress = (event) => {
      // prevent insertion of more characters if we're a multiline input
      // and maxLength exists
      const { maxLength, onKeyPress } = this.props;
      if (maxLength) {
        // check if smt is selected, in which case the newly added charcter would
        // replace the selected characters, so the length of value doesn't actually
        // increase.
        const isReplacing = event.target.selectionEnd - event.target.selectionStart;
        const value = event.target.value;

        if (!isReplacing && value.length === maxLength) {
          event.preventDefault();
          event.stopPropagation();
          return undefined;
        }
      }

      if (onKeyPress) onKeyPress(event);
      return undefined;
    };

    blur() {
      this.inputNode.blur();
    }

    focus() {
      this.inputNode.focus();
    }

    valuePresent = value => (
      value !== null
        && value !== undefined
        && value !== ''
        && !(typeof value === 'number' && isNaN(value))
    )

    render() {
      const { children, defaultValue, disabled, error, floating, hint, icon,
              name, label: labelText, maxLength, multiline, required, role,
              theme, type, value, onKeyPress, rows = 1, ...others } = this.props;
      const length = maxLength && value ? value.length : 0;
      const labelClassName = classnames(theme.label, { [theme.fixed]: !floating });

      const className = classnames(theme.input, {
        [theme.disabled]: disabled,
        [theme.errored]: error,
        [theme.hidden]: type === 'hidden',
        [theme.withIcon]: icon,
      }, this.props.className);

      const valuePresent = this.valuePresent(value) || this.valuePresent(defaultValue);

      const inputElementProps = {
        ...others,
        className: classnames(theme.inputElement, { [theme.filled]: valuePresent }),
        onChange: this.handleChange,
        ref: (node) => { this.inputNode = node; },
        role,
        name,
        defaultValue,
        disabled,
        required,
        type,
        value,
      };
      if (!multiline) {
        inputElementProps.maxLength = maxLength;
        inputElementProps.onKeyPress = onKeyPress;
      } else {
        inputElementProps.rows = rows;
        inputElementProps.onKeyPress = this.handleKeyPress;
      }

      return (

          {React.createElement(multiline ? 'textarea' : 'input', inputElementProps)}
          {icon ? <FontIcon className={theme.icon} value={icon} /> : null}

          {labelText
            ?
              {labelText}
              {required ?  *  : null}

            : null}
          {hint ? {hint} : null}
          {error ? {error} : null}
          {maxLength ? {length}/{maxLength} : null}
          {children}

      );
    }
  }

  return Input;
};

const Input = factory(InjectedFontIcon);
export default themr(INPUT)(Input);
export { factory as inputFactory };
export { Input };
<|endoftext|>


<commit_before>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

// MODULES //

var tape = require( 'tape' );
var proxyquire = require( 'proxyquire' );
var now = require( '@stdlib/time/now' );
var randn = require( '@stdlib/random/base/randn' ).factory;
var iteratorSymbol = require( '@stdlib/symbol/iterator' );
var iterator = require( './../lib' );

// TESTS //

tape( 'main export is a function', function test( t ) {
	t.ok( true, __filename );
	t.equal( typeof iterator, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function throws an error if provided an options argument which is not an object', function test( t ) {
	var values;
	var i;

	values = [
		'abc',
		5,
		null,
		true,
		false,
		void 0,
		NaN,
		[],
		function noop() {}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			iterator( value );
		};
	}
});

tape( 'the function throws an error if provided an invalid `name` option', function test( t ) {
	var values;
	var i;

	values = [
		'normal',
		3.14,
		NaN,
		true,
		null,
		void 0,
		[],
		{},
		function noop() {}
	];
	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), Error, 'throws an error when provided '+values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			iterator({
				'name': value
			});
		};
	}
});

tape( 'the function throws an error if provided an invalid `iter` option', function test( t ) {
	var values;
	var i;

	values = [
		'abc',
		-5,
		3.14,
		null,
		true,
		false,
		void 0,
		NaN,
		[],
		{},
		function noop() {}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			iterator({
				'iter': value
			});
		};
	}
});

tape( 'the function returns an iterator protocol-compliant object (no seed)', function test( t ) {
	var it;
	var r;
	var i;

	it = iterator();
	t.equal( it.next.length, 0, 'has zero arity' );

	for ( i = 0; i < 100; i++ ) {
		r = it.next();
		t.equal( typeof r.value, 'number', 'returns a number' );
		t.equal( typeof r.done, 'boolean', 'returns a boolean' );
	}
	t.end();
});

tape( 'the function returns an iterator protocol-compliant object (seed)', function test( t ) {
	var seed;
	var it1;
	var it2;
	var r1;
	var r2;
	var i;

	seed = now();

	it1 = iterator({
		'seed': seed
	});
	it2 = iterator({
		'seed': seed
	});

	t.notEqual( it1, it2, 'separate iterators' );

	for ( i = 0; i < 100; i++ ) {
		r1 = it1.next();
		r2 = it2.next();
		t.equal( r1.value, r2.value, 'both return same number' );
	}
	t.end();
});

tape( 'attached to the returned iterator is the generator seed', function test( t ) {
	var it = iterator({
		'seed': 12345
	});
	t.equal( typeof it.SEED, 'number', 'has `SEED` property' );
	t.equal( it.SEED, 12345, 'equal to provided seed' );
	t.end();
});

tape( 'attached to the returned iterator is the underlying PRNG', function test( t ) {
	var it = iterator({
		'name': 'box-muller'
	});
	t.equal( typeof it.PRNG, 'function', 'has `PRNG` property' );
	t.end();
});

tape( 'the function returns an iterator for generating standard normally distributed pseudorandom numbers', function test( t ) {
	var rand;
	var it;
	var i;

	// Note: we assume that the underlying generator is the following PRNG...
	rand = randn( {
		'seed': 12345
	});

	it = iterator({
		'seed': 12345
	});

	for ( i = 0; i < 1e3; i++ ) {
		t.equal( rand(), it.next().value, 'returns expected value' );
	}
	t.end();
});

tape( 'the function supports limiting the number of iterations', function test( t ) {
	var niter;
	var it;
	var r;
	var i;
	var j;

	niter = 10;

	it = iterator({
		'iter': niter
	});

	for ( i = 0; i < 100; i++ ) {
		r = it.next();
		j = i + 1;
		if ( j <= niter ) {
			t.equal( typeof r.value, 'number', 'returns expected `value` value. iteration: '+j );
			t.equal( r.done, false, 'returns expected `done` value. iteration: '+j );
		} else {
			t.equal( r.value, void 0, 'returns expected `value` value. iteration: '+j );
			t.equal( r.done, true, 'returns expected `done` value. iteration: '+j );
		}
	}
	t.end();
});

tape( 'the returned iterator has a `return` method for closing an iterator (no argument)', function test( t ) {
	var it;
	var r;

	it = iterator();

	r = it.next();
	t.equal( typeof r.value, 'number', 'returns a number' );
	t.equal( r.done, false, 'returns expected value' );

	r = it.next();
	t.equal( typeof r.value, 'number', 'returns a number' );
	t.equal( r.done, false, 'returns expected value' );

	r = it.return();
	t.equal( r.value, void 0, 'returns expected value' );
	t.equal( r.done, true, 'returns expected value' );

	r = it.next();
	t.equal( r.value, void 0, 'returns expected value' );
	t.equal( r.done, true, 'returns expected value' );

	t.end();
});

tape( 'the returned iterator has a `return` method for closing an iterator (argument)', function test( t ) {
	var it;
	var r;

	it = iterator();

	r = it.next();
	t.equal( typeof r.value, 'number', 'returns a number' );
	t.equal( r.done, false, 'returns expected value' );

	r = it.next();
	t.equal( typeof r.value, 'number', 'returns a number' );
	t.equal( r.done, false, 'returns expected value' );

	r = it.return( 'finished' );
	t.equal( r.value, 'finished', 'returns expected value' );
	t.equal( r.done, true, 'returns expected value' );

	r = it.next();
	t.equal( r.value, void 0, 'returns expected value' );
	t.equal( r.done, true, 'returns expected value' );

	t.end();
});

tape( 'if an environment supports `Symbol.iterator`, the returned iterator is iterable', function test( t ) {
	var iterator;
	var it1;
	var it2;
	var i;

	iterator = proxyquire( './../lib/main.js', {
		'@stdlib/symbol/iterator': '__ITERATOR_SYMBOL__'
	});

	it1 = iterator();
	t.equal( typeof it1[ '__ITERATOR_SYMBOL__' ], 'function', 'has method' );
	t.equal( it1[ '__ITERATOR_SYMBOL__' ].length, 0, 'has zero arity' );

	it2 = it1[ '__ITERATOR_SYMBOL__' ]();
	t.equal( typeof it2, 'object', 'returns an object' );
	t.equal( typeof it2.next, 'function', 'has `next` method' );
	t.equal( typeof it2.return, 'function', 'has `return` method' );
	t.equal( it2.SEED, it1.SEED, 'has expected seed' );

	for ( i = 0; i < 100; i++ ) {
		t.equal( it2.next().value, it1.next().value, 'returns expected value' );
	}
	t.end();
});

tape( 'if an environment does not support `Symbol.iterator`, the returned iterator is not "iterable"', function test( t ) {
	var iterator;
	var it;

	iterator = proxyquire( './../lib/main.js', {
		'@stdlib/symbol/iterator': false
	});

	it = iterator();
	t.equal( it[ iteratorSymbol ], void 0, 'does not have property' );

	t.end();
});
<commit_msg>Add test assertion<commit_after>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

// MODULES //

var tape = require( 'tape' );
var proxyquire = require( 'proxyquire' );
var now = require( '@stdlib/time/now' );
var randn = require( '@stdlib/random/base/randn' ).factory;
var iteratorSymbol = require( '@stdlib/symbol/iterator' );
var iterator = require( './../lib' );

// TESTS //

tape( 'main export is a function', function test( t ) {
	t.ok( true, __filename );
	t.equal( typeof iterator, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function throws an error if provided an options argument which is not an object', function test( t ) {
	var values;
	var i;

	values = [
		'abc',
		5,
		null,
		true,
		false,
		void 0,
		NaN,
		[],
		function noop() {}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			iterator( value );
		};
	}
});

tape( 'the function throws an error if provided an invalid `name` option', function test( t ) {
	var values;
	var i;

	values = [
		'normal',
		3.14,
		NaN,
		true,
		null,
		void 0,
		[],
		{},
		function noop() {}
	];
	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), Error, 'throws an error when provided '+values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			iterator({
				'name': value
			});
		};
	}
});

tape( 'the function throws an error if provided an invalid `iter` option', function test( t ) {
	var values;
	var i;

	values = [
		'abc',
		-5,
		3.14,
		null,
		true,
		false,
		void 0,
		NaN,
		[],
		{},
		function noop() {}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			iterator({
				'iter': value
			});
		};
	}
});

tape( 'the function returns an iterator protocol-compliant object (no seed)', function test( t ) {
	var it;
	var r;
	var i;

	it = iterator();
	t.equal( it.next.length, 0, 'has zero arity' );

	for ( i = 0; i < 100; i++ ) {
		r = it.next();
		t.equal( typeof r.value, 'number', 'returns a number' );
		t.equal( typeof r.done, 'boolean', 'returns a boolean' );
	}
	t.end();
});

tape( 'the function returns an iterator protocol-compliant object (seed)', function test( t ) {
	var seed;
	var it1;
	var it2;
	var r1;
	var r2;
	var i;

	seed = now();

	it1 = iterator({
		'seed': seed
	});
	it2 = iterator({
		'seed': seed
	});

	t.notEqual( it1, it2, 'separate iterators' );

	for ( i = 0; i < 100; i++ ) {
		r1 = it1.next();
		r2 = it2.next();
		t.equal( r1.value, r2.value, 'both return same number' );
	}
	t.end();
});

tape( 'attached to the returned iterator is the generator seed', function test( t ) {
	var it = iterator({
		'seed': 12345
	});
	t.equal( typeof it.SEED, 'number', 'has `SEED` property' );
	t.equal( it.SEED, 12345, 'equal to provided seed' );
	t.end();
});

tape( 'attached to the returned iterator is the underlying PRNG', function test( t ) {
	var it = iterator({
		'name': 'box-muller'
	});
	t.equal( typeof it.PRNG, 'function', 'has `PRNG` property' );
	t.equal( it.PRNG.NAME, 'box-muller', 'equal to provided PRNG' );
	t.end();
});

tape( 'the function returns an iterator for generating standard normally distributed pseudorandom numbers', function test( t ) {
	var rand;
	var it;
	var i;

	// Note: we assume that the underlying generator is the following PRNG...
	rand = randn( {
		'seed': 12345
	});

	it = iterator({
		'seed': 12345
	});

	for ( i = 0; i < 1e3; i++ ) {
		t.equal( rand(), it.next().value, 'returns expected value' );
	}
	t.end();
});

tape( 'the function supports limiting the number of iterations', function test( t ) {
	var niter;
	var it;
	var r;
	var i;
	var j;

	niter = 10;

	it = iterator({
		'iter': niter
	});

	for ( i = 0; i < 100; i++ ) {
		r = it.next();
		j = i + 1;
		if ( j <= niter ) {
			t.equal( typeof r.value, 'number', 'returns expected `value` value. iteration: '+j );
			t.equal( r.done, false, 'returns expected `done` value. iteration: '+j );
		} else {
			t.equal( r.value, void 0, 'returns expected `value` value. iteration: '+j );
			t.equal( r.done, true, 'returns expected `done` value. iteration: '+j );
		}
	}
	t.end();
});

tape( 'the returned iterator has a `return` method for closing an iterator (no argument)', function test( t ) {
	var it;
	var r;

	it = iterator();

	r = it.next();
	t.equal( typeof r.value, 'number', 'returns a number' );
	t.equal( r.done, false, 'returns expected value' );

	r = it.next();
	t.equal( typeof r.value, 'number', 'returns a number' );
	t.equal( r.done, false, 'returns expected value' );

	r = it.return();
	t.equal( r.value, void 0, 'returns expected value' );
	t.equal( r.done, true, 'returns expected value' );

	r = it.next();
	t.equal( r.value, void 0, 'returns expected value' );
	t.equal( r.done, true, 'returns expected value' );

	t.end();
});

tape( 'the returned iterator has a `return` method for closing an iterator (argument)', function test( t ) {
	var it;
	var r;

	it = iterator();

	r = it.next();
	t.equal( typeof r.value, 'number', 'returns a number' );
	t.equal( r.done, false, 'returns expected value' );

	r = it.next();
	t.equal( typeof r.value, 'number', 'returns a number' );
	t.equal( r.done, false, 'returns expected value' );

	r = it.return( 'finished' );
	t.equal( r.value, 'finished', 'returns expected value' );
	t.equal( r.done, true, 'returns expected value' );

	r = it.next();
	t.equal( r.value, void 0, 'returns expected value' );
	t.equal( r.done, true, 'returns expected value' );

	t.end();
});

tape( 'if an environment supports `Symbol.iterator`, the returned iterator is iterable', function test( t ) {
	var iterator;
	var it1;
	var it2;
	var i;

	iterator = proxyquire( './../lib/main.js', {
		'@stdlib/symbol/iterator': '__ITERATOR_SYMBOL__'
	});

	it1 = iterator();
	t.equal( typeof it1[ '__ITERATOR_SYMBOL__' ], 'function', 'has method' );
	t.equal( it1[ '__ITERATOR_SYMBOL__' ].length, 0, 'has zero arity' );

	it2 = it1[ '__ITERATOR_SYMBOL__' ]();
	t.equal( typeof it2, 'object', 'returns an object' );
	t.equal( typeof it2.next, 'function', 'has `next` method' );
	t.equal( typeof it2.return, 'function', 'has `return` method' );
	t.equal( it2.SEED, it1.SEED, 'has expected seed' );

	for ( i = 0; i < 100; i++ ) {
		t.equal( it2.next().value, it1.next().value, 'returns expected value' );
	}
	t.end();
});

tape( 'if an environment does not support `Symbol.iterator`, the returned iterator is not "iterable"', function test( t ) {
	var iterator;
	var it;

	iterator = proxyquire( './../lib/main.js', {
		'@stdlib/symbol/iterator': false
	});

	it = iterator();
	t.equal( it[ iteratorSymbol ], void 0, 'does not have property' );

	t.end();
});
<|endoftext|>