UNPKG

react-values

Version:

A set of tiny, composable React components for handling state with render props.

789 lines (644 loc) 22.4 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react')) : typeof define === 'function' && define.amd ? define(['exports', 'react'], factory) : (factory((global.ReactValues = {}),global.React)); }(this, (function (exports,React) { 'use strict'; React = React && React.hasOwnProperty('default') ? React['default'] : React; var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; var createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }; var possibleConstructorReturn = function (self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }; function createComponent(Store) { return function (_React$Component) { inherits(Value, _React$Component); function Value(props, context) { classCallCheck(this, Value); var _this = possibleConstructorReturn(this, (Value.__proto__ || Object.getPrototypeOf(Value)).call(this, props)); var value = props.value, defaultValue = props.defaultValue, store = props.store; var connected = !store; var controlled = false; if (!store) { if (value !== undefined) { store = new Store(value, props); controlled = true; } else { store = new Store(defaultValue, props); } } _this.state = { connected: connected, controlled: controlled, store: store, value: store.value }; return _this; } createClass(Value, [{ key: 'componentDidMount', value: function componentDidMount() { var _this2 = this; var _state = this.state, controlled = _state.controlled, store = _state.store; this.mounted = true; this.unsubscribe = store.on(function (value) { if (!_this2.mounted) return; if (controlled) { _this2.onChange(value); } else { _this2.setState({ value: value }, function () { return _this2.onChange(_this2.state.value); }); } }); } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { this.mounted = false; this.unsubscribe(); } }, { key: 'onChange', value: function onChange(value) { if (this.props.onChange) { this.props.onChange(value); } } }, { key: 'render', value: function render() { var _props = this.props, children = _props.children, render = _props.render, _props$disabled = _props.disabled, disabled = _props$disabled === undefined ? false : _props$disabled; var _state2 = this.state, controlled = _state2.controlled, connected = _state2.connected, store = _state2.store; var value = controlled ? this.props.value : this.state.value; var transforms = disabled ? store.noops : store.transforms; var fn = children || render; if (controlled) { store.value = value; } if (!connected) { store.props = this.props; } if (fn === null) { return null; } var renderProps = _extends({ value: value, disabled: disabled }, transforms); for (var key in store.computeds) { renderProps[key] = store.computeds[key](); } var ret = typeof fn === 'function' ? fn(renderProps) : fn; return ret; } }]); return Value; }(React.Component); } function createFactory(Store, Value) { return function (initial, props) { var store = new Store(initial, props); var Connected = function (_React$Component) { inherits(Connected, _React$Component); function Connected() { classCallCheck(this, Connected); return possibleConstructorReturn(this, (Connected.__proto__ || Object.getPrototypeOf(Connected)).apply(this, arguments)); } createClass(Connected, [{ key: 'render', value: function render() { return React.createElement(Value, _extends({}, this.props, { store: store })); } }], [{ key: 'value', get: function get$$1() { return store.value; } }]); return Connected; }(React.Component); for (var k in store.transforms) { Connected[k] = store.transforms[k]; } Connected.store = store; Connected.displayName = 'Connected' + Value.displayName; return Connected; }; } var Store = function () { function Store(value) { var _this = this; var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var empty = arguments[2]; classCallCheck(this, Store); this.callbacks = []; this.value = value === undefined ? empty : value; this.transforms = {}; this.noops = {}; this.computeds = {}; this.props = props; this.define('set', function (v, next) { return next; }); this.define('reset', function () { return _this.clone(value); }); this.define('clear', function () { return _this.clone(empty); }); if (props.onChange) { this.on(props.onChange); } } createClass(Store, [{ key: 'on', value: function on(callback) { var _this2 = this; var index = this.callbacks.push(callback) - 1; var off = function off() { return _this2.callbacks[index] = null; }; return off; } }, { key: 'clone', value: function clone(v) { return v; } }, { key: 'transform', value: function transform(fn) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var value = this.value, callbacks = this.callbacks; var _options$mutates = options.mutates, mutates = _options$mutates === undefined ? false : _options$mutates; var current = mutates ? this.clone(value) : value; var next = typeof fn === 'function' ? fn(current) : fn; this.value = next; callbacks.forEach(function (cb) { return cb && cb(next); }); } }, { key: 'define', value: function define(name, fn, options) { var _this3 = this; this.noops[name] = function () {}; this.transforms[name] = function () { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this3.transform(function (v) { return fn.apply(undefined, [v].concat(args)); }, options); }; } }, { key: 'compute', value: function compute(name, fn) { var _this4 = this; this.computeds[name] = function () { return fn(_this4.value); }; } }, { key: 'proxy', value: function proxy(method) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var _options$alias = options.alias, alias = _options$alias === undefined ? method : _options$alias, _options$mutates2 = options.mutates, mutates = _options$mutates2 === undefined ? false : _options$mutates2; this.define(alias, function (v) { for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { args[_key2 - 1] = arguments[_key2]; } var ret = v[method].apply(v, args); return mutates ? v : ret; }, options); } }]); return Store; }(); var Value = createComponent(Store); var createValue = createFactory(Store, Value); var ArrayStore = function (_Store) { inherits(ArrayStore, _Store); function ArrayStore(value, props) { classCallCheck(this, ArrayStore); var _this = possibleConstructorReturn(this, (ArrayStore.__proto__ || Object.getPrototypeOf(ArrayStore)).call(this, value, props, [])); _this.compute('first', function (v) { return v[0]; }); _this.compute('last', function (v) { return v[Math.max(0, v.length - 1)]; }); _this.proxy('concat'); _this.proxy('fill', { mutates: true }); _this.proxy('filter'); _this.proxy('flat'); _this.proxy('flatMap'); _this.proxy('map'); _this.proxy('pop', { mutates: true }); _this.proxy('push', { mutates: true }); _this.proxy('reverse', { mutates: true }); _this.proxy('shift', { mutates: true }); _this.proxy('slice'); _this.proxy('sort', { mutates: true }); _this.proxy('splice', { mutates: true }); _this.proxy('unshift', { mutates: true }); return _this; } createClass(ArrayStore, [{ key: 'clone', value: function clone(value) { return value.slice(); } }]); return ArrayStore; }(Store); var ArrayValue = createComponent(ArrayStore); var createArrayValue = createFactory(ArrayStore, ArrayValue); var BooleanStore = function (_Store) { inherits(BooleanStore, _Store); function BooleanStore(value, props) { classCallCheck(this, BooleanStore); var _this = possibleConstructorReturn(this, (BooleanStore.__proto__ || Object.getPrototypeOf(BooleanStore)).call(this, value, props, false)); _this.define('toggle', function (v) { return !v; }); return _this; } return BooleanStore; }(Store); var BooleanValue = createComponent(BooleanStore); var createBooleanValue = createFactory(BooleanStore, BooleanValue); var SECONDS = 1000; var MINUTES = 1000 * 60; var HOURS = 1000 * 60 * 60; var DateStore = function (_Store) { inherits(DateStore, _Store); function DateStore(value, props) { classCallCheck(this, DateStore); var _this = possibleConstructorReturn(this, (DateStore.__proto__ || Object.getPrototypeOf(DateStore)).call(this, value, props, new Date())); _this.compute('date', function (v) { return v.getDate(); }); _this.compute('hours', function (v) { return v.getHours(); }); _this.compute('milliseconds', function (v) { return v.getMilliseconds(); }); _this.compute('minutes', function (v) { return v.getMinutes(); }); _this.compute('month', function (v) { return v.getMonth(); }); _this.compute('seconds', function (v) { return v.getSeconds(); }); _this.compute('year', function (v) { return v.getFullYear(); }); _this.define('setMonth', setMonth); _this.proxy('setDate', { mutates: true }); _this.proxy('setFullYear', { alias: 'setYear', mutates: true }); _this.proxy('setFullYear', { mutates: true }); _this.proxy('setHours', { mutates: true }); _this.proxy('setMilliseconds', { mutates: true }); _this.proxy('setMinutes', { mutates: true }); _this.proxy('setSeconds', { mutates: true }); _this.define('incrementDate', function (v) { var n = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; return incDate(v, n); }); _this.define('incrementHours', function (v) { var n = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; return incMil(v, n * HOURS); }); _this.define('incrementMilliseconds', function (v) { var n = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; return incMil(v, n); }); _this.define('incrementMinutes', function (v) { var n = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; return incMil(v, n * MINUTES); }); _this.define('incrementMonth', function (v) { var n = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; return incMonth(v, n); }); _this.define('incrementSeconds', function (v) { var n = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; return incMil(v, n * SECONDS); }); _this.define('incrementYear', function (v) { var n = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; return incMonth(v, n * 12); }); _this.define('decrementDate', function (v) { var n = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; return incDate(v, 0 - n); }); _this.define('decrementHours', function (v) { var n = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; return incMil(v, 0 - n * HOURS); }); _this.define('decrementMilliseconds', function (v) { var n = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; return incMil(v, 0 - n); }); _this.define('decrementMinutes', function (v) { var n = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; return incMil(v, 0 - n * MINUTES); }); _this.define('decrementMonth', function (v) { var n = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; return incMonth(v, 0 - n); }); _this.define('decrementSeconds', function (v) { var n = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; return incMil(v, 0 - n * SECONDS); }); _this.define('decrementYear', function (v) { var n = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; return incMonth(v, 0 - n * 12); }); return _this; } createClass(DateStore, [{ key: 'clone', value: function clone(value) { return new Date(value.getTime()); } }]); return DateStore; }(Store); function incMil(v, n) { return new Date(v.getTime() + n); } function incDate(v, n) { var d = new Date(v.getTime()); d.setDate(d.getDate() + n); return d; } function incMonth(v, n) { var year = v.getFullYear(); var desiredMonth = v.getMonth() + n; var desired = new Date(0); desired.setFullYear(year, desiredMonth, 1); desired.setHours(0, 0, 0, 0); var max = days(desired); v.setMonth(desiredMonth, Math.min(max, v.getDate())); return v; } function setMonth(v, m) { var d = new Date(v.getTime()); var year = d.getFullYear(); var day = d.getDate(); var desired = new Date(0); desired.setFullYear(year, m, 15); desired.setHours(0, 0, 0, 0); var max = days(desired); d.setMonth(m, Math.min(day, max)); return d; } function days(v) { var year = v.getFullYear(); var monthIndex = v.getMonth(); var lastDayOfMonth = new Date(0); lastDayOfMonth.setFullYear(year, monthIndex + 1, 0); lastDayOfMonth.setHours(0, 0, 0, 0); return lastDayOfMonth.getDate(); } var DateValue = createComponent(DateStore); var createDateValue = createFactory(DateStore, DateValue); var MapStore = function (_Store) { inherits(MapStore, _Store); function MapStore(value, props) { classCallCheck(this, MapStore); var _this = possibleConstructorReturn(this, (MapStore.__proto__ || Object.getPrototypeOf(MapStore)).call(this, value, props, new Map())); _this.define('set', function (v) { for (var _len = arguments.length, a = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { a[_key - 1] = arguments[_key]; } var first = a[0]; return a.length === 1 ? typeof first === 'function' ? first(v) : first : v.set.apply(v, a); }); _this.proxy('clear', { mutates: true }); _this.proxy('delete', { mutates: true }); _this.proxy('delete', { alias: 'unset', mutates: true }); return _this; } createClass(MapStore, [{ key: 'clone', value: function clone(value) { return new Map(value); } }]); return MapStore; }(Store); var MapValue = createComponent(MapStore); var createMapValue = createFactory(MapStore, MapValue); var NumberStore = function (_Store) { inherits(NumberStore, _Store); function NumberStore(value, props) { classCallCheck(this, NumberStore); var _this = possibleConstructorReturn(this, (NumberStore.__proto__ || Object.getPrototypeOf(NumberStore)).call(this, value, props, 0)); _this.define('increment', function (v) { var n = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; var num = typeof n !== 'number' ? 1 : n; return Math.min(v + num, _this.props.max); }); _this.define('decrement', function (v) { var n = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; var num = typeof n !== 'number' ? 1 : n; return Math.max(v - num, _this.props.min); }); return _this; } return NumberStore; }(Store); var NumberValue = createComponent(NumberStore); var createNumberValue = createFactory(NumberStore, NumberValue); NumberValue.defaultProps = { max: Number.MAX_SAFE_INTEGER, min: Number.MIN_SAFE_INTEGER }; var ObjectStore = function (_Store) { inherits(ObjectStore, _Store); function ObjectStore(value, props) { classCallCheck(this, ObjectStore); var _this = possibleConstructorReturn(this, (ObjectStore.__proto__ || Object.getPrototypeOf(ObjectStore)).call(this, value, props, {})); _this.define('set', function (v) { for (var _len = arguments.length, a = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { a[_key - 1] = arguments[_key]; } var first = a[0]; if (a.length === 1) { return typeof first === 'function' ? first(v) : first; } var key = a[0], val = a[1]; var clone = _extends({}, v); clone[key] = val; return clone; }); _this.define('assign', function (v) { var val = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; return _extends({}, v, val); }); _this.define('clear', function () { return {}; }); _this.define('delete', unset); _this.define('unset', unset); return _this; } createClass(ObjectStore, [{ key: 'clone', value: function clone(value) { return _extends({}, value); } }]); return ObjectStore; }(Store); function unset(v, key) { var clone = _extends({}, v); delete clone[key]; return clone; } var ObjectValue = createComponent(ObjectStore); var createObjectValue = createFactory(ObjectStore, ObjectValue); var SetStore = function (_Store) { inherits(SetStore, _Store); function SetStore(value, props) { classCallCheck(this, SetStore); var _this = possibleConstructorReturn(this, (SetStore.__proto__ || Object.getPrototypeOf(SetStore)).call(this, value, props, new Set())); _this.define('toggle', function (v, val, boolean) { if (boolean) { return v.add(val); } else { v.delete(val); return v; } }, { mutates: true }); _this.proxy('add'); _this.proxy('clear', { mutates: true }); _this.proxy('delete', { mutates: true }); _this.proxy('delete', { alias: 'remove', mutates: true }); return _this; } createClass(SetStore, [{ key: 'clone', value: function clone(value) { return new Set(value); } }]); return SetStore; }(Store); var SetValue = createComponent(SetStore); var createSetValue = createFactory(SetStore, SetValue); var StringStore = function (_Store) { inherits(StringStore, _Store); function StringStore(value, props) { classCallCheck(this, StringStore); var _this = possibleConstructorReturn(this, (StringStore.__proto__ || Object.getPrototypeOf(StringStore)).call(this, value, props, '')); _this.proxy('concat'); _this.proxy('normalize'); _this.proxy('padEnd'); _this.proxy('padStart'); _this.proxy('repeat'); _this.proxy('replace'); _this.proxy('slice'); _this.proxy('substr'); _this.proxy('substring'); _this.proxy('toLowerCase'); _this.proxy('toUpperCase'); _this.proxy('trim'); _this.proxy('trimEnd'); _this.proxy('trimStart'); return _this; } return StringStore; }(Store); var StringValue = createComponent(StringStore); var createStringValue = createFactory(StringStore, StringValue); exports.ArrayValue = ArrayValue; exports.createArrayValue = createArrayValue; exports.BooleanValue = BooleanValue; exports.createBooleanValue = createBooleanValue; exports.DateValue = DateValue; exports.createDateValue = createDateValue; exports.MapValue = MapValue; exports.createMapValue = createMapValue; exports.NumberValue = NumberValue; exports.createNumberValue = createNumberValue; exports.ObjectValue = ObjectValue; exports.createObjectValue = createObjectValue; exports.SetValue = SetValue; exports.createSetValue = createSetValue; exports.StringValue = StringValue; exports.createStringValue = createStringValue; exports.Value = Value; exports.createValue = createValue; Object.defineProperty(exports, '__esModule', { value: true }); })));