You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

@getoccasion/mitragyna

Package Overview
Dependencies
Maintainers
2
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@getoccasion/mitragyna - npm Package Compare versions

Comparing version
0.1.2
to
0.2.0
+1041
build/mitragyna.js
(function (global, factory) {
if (typeof define === "function" && define.amd) {
define(['exports', 'react', 'prop-types', 'active-resource', 'underscore', 'classnames', 'shallowequal'], factory);
} else if (typeof exports !== "undefined") {
factory(exports, require('react'), require('prop-types'), require('active-resource'), require('underscore'), require('classnames'), require('shallowequal'));
} else {
var mod = {
exports: {}
};
factory(mod.exports, global.react, global.propTypes, global.activeResource, global.underscore, global.classnames, global.shallowequal);
global.mitragyna = mod.exports;
}
})(this, function (exports, _react, _propTypes, _activeResource, _underscore, _classnames, _shallowequal) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Resource = exports.Field = exports.ErrorsFor = exports.Collection = undefined;
var _react2 = _interopRequireDefault(_react);
var _propTypes2 = _interopRequireDefault(_propTypes);
var _activeResource2 = _interopRequireDefault(_activeResource);
var _underscore2 = _interopRequireDefault(_underscore);
var _classnames2 = _interopRequireDefault(_classnames);
var _shallowequal2 = _interopRequireDefault(_shallowequal);
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
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;
};
function _classCallCheck(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;
};
}();
function _possibleConstructorReturn(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 _inherits(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 Collection = exports.Collection = function (_React$PureComponent) {
_inherits(Collection, _React$PureComponent);
// link to global state by enabling afterLoad, afterAdd, afterRemove, afterUpdate callbacks that can call
// an action linked to dispatch
function Collection() {
_classCallCheck(this, Collection);
var _this = _possibleConstructorReturn(this, (Collection.__proto__ || Object.getPrototypeOf(Collection)).call(this));
_this.state = {
target: _activeResource2.default.prototype.Collection.build()
};
_underscore2.default.bindAll(_this, 'buildOnTarget', 'cloneTarget', 'replaceOnTarget', 'removeFromTarget');
return _this;
}
_createClass(Collection, [{
key: 'componentDidMount',
value: function componentDidMount() {
this.setTarget(this.props);
}
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(nextProps) {
this.setTarget(nextProps);
}
}, {
key: 'setTarget',
value: function setTarget(props) {
var subject = props.subject;
this.setState({ target: subject.target() });
}
}, {
key: 'buildOnTarget',
value: function buildOnTarget(attributes) {
var subject = this.props.subject;
var target = this.cloneTarget();
target.push(subject.build(attributes));
this.setState({ target: target });
}
}, {
key: 'replaceOnTarget',
value: function replaceOnTarget(newItem, oldItem) {
var target = this.cloneTarget();
target.replace(oldItem, newItem);
return this.setState({ target: target });
}
}, {
key: 'removeFromTarget',
value: function removeFromTarget(item) {
var target = this.cloneTarget();
target.delete(item);
return this.setState({ target: target });
}
}, {
key: 'cloneTarget',
value: function cloneTarget() {
return this.state.target.clone();
}
}, {
key: 'render',
value: function render() {
var _this2 = this;
var _props = this.props,
blankComponent = _props.blankComponent,
children = _props.children,
className = _props.className,
component = _props.component,
componentProps = _props.componentProps,
reflection = _props.reflection;
var target = this.state.target;
return _react2.default.createElement(
'section',
{ className: className },
target.size() > 0 ? target.map(function (t, indexOf) {
return _react2.default.createElement(
Resource,
{ afterUpdate: _this2.replaceOnTarget,
component: component, componentProps: _extends({}, componentProps, { indexOf: indexOf }),
key: t.id || t.klass().className + '-' + indexOf,
reflection: reflection,
subject: t },
children
);
}).toArray() : blankComponent != null && blankComponent()
);
}
}]);
return Collection;
}(_react2.default.PureComponent);
Collection.propTypes = {
children: _propTypes2.default.oneOfType([_propTypes2.default.array, _propTypes2.default.node]),
className: _propTypes2.default.string,
blankComponent: _propTypes2.default.func,
component: _propTypes2.default.func,
componentProps: _propTypes2.default.object,
subject: _propTypes2.default.oneOfType([_propTypes2.default.object, _propTypes2.default.func]).isRequired,
reflection: _propTypes2.default.string
};
Collection.defaultProps = {
inlineRows: false
};
var ErrorsFor = exports.ErrorsFor = function (_React$Component) {
_inherits(ErrorsFor, _React$Component);
function ErrorsFor() {
_classCallCheck(this, ErrorsFor);
return _possibleConstructorReturn(this, (ErrorsFor.__proto__ || Object.getPrototypeOf(ErrorsFor)).apply(this, arguments));
}
_createClass(ErrorsFor, [{
key: 'shouldComponentUpdate',
value: function shouldComponentUpdate(nextProps, nextState, nextContext) {
return !((0, _shallowequal2.default)(this.props, nextProps) && (0, _shallowequal2.default)(this.state, nextState) && (0, _shallowequal2.default)(this.context, nextContext));
}
}, {
key: 'render',
value: function render() {
var resource = this.context.resource;
var _props2 = this.props,
component = _props2.component,
field = _props2.field;
var errors = resource.errors().forField(field);
if (errors.empty()) return null;
var customProps = _underscore2.default.omit(this.props, _underscore2.default.keys(ErrorsFor.propTypes));
var finalComponent = component || 'summary';
return _react2.default.createElement(finalComponent, _extends({}, customProps, {
key: field
}), errors.map(function (error) {
return _react2.default.createElement(
'span',
{ key: error.code },
error.message
);
}).toArray());
}
}]);
return ErrorsFor;
}(_react2.default.Component);
ErrorsFor.propTypes = {
component: _propTypes2.default.func,
field: _propTypes2.default.string
};
ErrorsFor.contextTypes = {
resource: _propTypes2.default.object
};
;
var Field = exports.Field = function (_React$Component2) {
_inherits(Field, _React$Component2);
function Field() {
_classCallCheck(this, Field);
var _this4 = _possibleConstructorReturn(this, (Field.__proto__ || Object.getPrototypeOf(Field)).call(this));
_underscore2.default.bindAll(_this4, 'afterChange', 'changeRadio', 'classNames', 'commonInputProps', 'customInputProps', 'getValue', 'handleChange', 'renderCheckboxComponent', 'renderInputComponent', 'renderRadioComponent', 'renderSelectComponent', 'renderTextareaComponent', 'setValue', 'valueFor');
_this4.state = {};
return _this4;
}
_createClass(Field, [{
key: 'shouldComponentUpdate',
value: function shouldComponentUpdate(nextProps, nextState, nextContext) {
return !((0, _shallowequal2.default)(this.props, nextProps) && (0, _shallowequal2.default)(this.state, nextState) && (0, _shallowequal2.default)(this.context, nextContext));
}
}, {
key: 'getChildContext',
value: function getChildContext() {
var type = this.props.type;
var value = this.state.value;
switch (type) {
case 'radioGroup':
return {
changeRadio: this.changeRadio,
radioValue: value
};
}
}
}, {
key: 'changeRadio',
value: function changeRadio(value) {
this.setState({ value: value });
}
}, {
key: 'componentWillMount',
value: function componentWillMount() {
var type = this.props.type;
var resource = this.context.resource;
// Set initial value to that of the resources
this.setState({
resource: resource,
value: this.valueFor(resource, this.props)
});
switch (type) {
case 'email':
case 'number':
case 'text':
case 'textarea':
this.afterChange = _underscore2.default.debounce(this.afterChange, 500);
}
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate(prevProps, prevState) {
var prevResource = prevState.resource;
var resource = this.context.resource;
if (prevResource !== resource) {
this.setState({ resource: resource });
}
if (!(_underscore2.default.isNull(prevResource.id) || _underscore2.default.isUndefined(prevResource.id)) && prevResource.id !== resource.id) {
this.setState({
value: this.valueFor(resource, this.props)
});
}
}
}, {
key: 'classNames',
value: function classNames() {
var _props3 = this.props,
className = _props3.className,
invalidClassName = _props3.invalidClassName,
name = _props3.name;
var resource = this.context.resource;
return (0, _classnames2.default)(className, _defineProperty({}, invalidClassName, !resource.errors().forField(name).empty()));
}
}, {
key: 'commonInputProps',
value: function commonInputProps() {
var name = this.props.name;
var props = {
className: this.classNames(),
key: name,
name: name,
onChange: this.handleChange
};
return props;
}
}, {
key: 'componentFor',
value: function componentFor(type) {
switch (type) {
case 'checkbox':
return this.renderCheckboxComponent();
case 'radio':
return this.renderRadioComponent();
case 'radioGroup':
return this.renderRadioGroupComponent();
case 'select':
return this.renderSelectComponent();
case 'textarea':
return this.renderTextareaComponent();
default:
return this.renderInputComponent();
}
}
// @note type='radio' will pass down +name+ prop
// @note type='select' will only pass down +type+ prop if +component+ prop is defined
}, {
key: 'customInputProps',
value: function customInputProps() {
var _props4 = this.props,
component = _props4.component,
type = _props4.type;
var omittedProps;
switch (type) {
case 'radio':
omittedProps = _underscore2.default.omit(Field.propTypes, ['type', 'name']);
break;
case 'select':
omittedProps = component ? _underscore2.default.omit(Field.propTypes, 'type') : Field.propTypes;
break;
default:
omittedProps = _underscore2.default.omit(Field.propTypes, 'type');
}
return _underscore2.default.omit(this.props, _underscore2.default.keys(omittedProps));
}
// TODO: Add support for non-resource options on select and radioGroup
}, {
key: 'valueFor',
value: function valueFor(resource, props) {
var name = props.name,
type = props.type,
uncheckedValue = props.uncheckedValue,
value = props.value;
switch (type) {
case 'checkbox':
var resourceValue = resource[name];
if (resourceValue == value) {
return true;
} else if (resourceValue == uncheckedValue || _underscore2.default.isUndefined(resourceValue) || _underscore2.default.isNull(resourceValue)) {
return false;
} else {
throw 'Field ' + name + ' with value ' + resource[name] + ' does not match value or uncheckedValue for checkbox';
}
case 'radioGroup':
case 'select':
var val = resource[name]();
return val ? val.id : '';
default:
var val = resource[name];
return val ? val : '';
}
}
}, {
key: 'render',
value: function render() {
var type = this.props.type;
return this.componentFor(type);
}
}, {
key: 'renderCheckboxComponent',
value: function renderCheckboxComponent() {
var component = this.props.component;
var finalComponent = component || 'input';
return _react2.default.createElement(finalComponent, _extends({}, this.commonInputProps(), this.customInputProps(), {
checked: this.state.value
}));
}
}, {
key: 'renderInputComponent',
value: function renderInputComponent() {
var component = this.props.component;
var finalComponent = component || 'input';
return _react2.default.createElement(finalComponent, _extends({}, this.commonInputProps(), this.customInputProps(), {
value: this.state.value
}));
}
}, {
key: 'renderRadioComponent',
value: function renderRadioComponent() {
var _props5 = this.props,
component = _props5.component,
value = _props5.value;
var radioValue = this.context.radioValue;
if (_underscore2.default.isUndefined(value)) {
throw 'Input type="radio" must have prop "value"';
}
var finalComponent = component || 'input';
return _react2.default.createElement(finalComponent, _extends({}, this.commonInputProps(), this.customInputProps(), {
checked: value.id == radioValue,
value: value.id,
name: value.questionId
}));
}
}, {
key: 'renderRadioGroupComponent',
value: function renderRadioGroupComponent() {
return _react2.default.createElement(
'div',
null,
this.props.children
);
}
}, {
key: 'renderSelectComponent',
value: function renderSelectComponent() {
var _props6 = this.props,
component = _props6.component,
includeBlank = _props6.includeBlank,
options = _props6.options,
optionsLabel = _props6.optionsLabel;
var selectOptions = null;
if (options.empty()) {
throw 'Input type="select" must have options';
} else {
selectOptions = options.map(function (o) {
return _react2.default.createElement(
'option',
{ key: o.id, value: o.id },
_underscore2.default.isString(optionsLabel) ? o[optionsLabel] : optionsLabel(o)
);
});
if (includeBlank) {
selectOptions.unshift(_react2.default.createElement('option', { key: -1, value: '' }));
}
}
var finalComponent = component || 'select';
return _react2.default.createElement(finalComponent, _extends({}, this.commonInputProps(), this.customInputProps(), {
value: this.state.value
}), selectOptions.toArray());
}
}, {
key: 'renderTextareaComponent',
value: function renderTextareaComponent() {
var component = this.props.component;
var finalComponent = component || 'textarea';
return _react2.default.createElement(finalComponent, _extends({}, this.commonInputProps(), this.customInputProps(), {
value: this.state.value
}));
}
}, {
key: 'handleChange',
value: function handleChange(e) {
e.persist();
var _props7 = this.props,
max = _props7.max,
min = _props7.min,
type = _props7.type;
var changeRadio = this.context.changeRadio;
var value = void 0;
switch (type) {
case 'checkbox':
value = e.target.checked;
break;
case 'number':
if (e.target.value > max) {
value = max;
} else if (e.target.value < min) {
value = min;
} else {
value = e.target.value || min;
}
break;
case 'radio':
changeRadio(e.target.value);
break;
default:
value = e.target.value;
}
this.setState({ value: value }, this.afterChange);
}
}, {
key: 'afterChange',
value: function afterChange() {
var _props8 = this.props,
name = _props8.name,
type = _props8.type,
options = _props8.options,
uncheckedValue = _props8.uncheckedValue,
value = _props8.value;
var stateValue = this.state.value;
var queueChange = this.context.queueChange;
var mappedValue = void 0;
switch (type) {
case 'checkbox':
if (stateValue) {
mappedValue = value;
} else {
mappedValue = uncheckedValue;
}
break;
case 'radio':
mappedValue = value;
break;
case 'select':
mappedValue = options.detect(function (o) {
return o.id === stateValue;
});
break;
default:
mappedValue = stateValue;
}
queueChange(_defineProperty({}, name, mappedValue));
}
}, {
key: 'getValue',
value: function getValue() {
return this.state.value;
}
}, {
key: 'setValue',
value: function setValue(value) {
var type = this.props.type;
var mappedValue = { persist: _underscore2.default.noop };
switch (type) {
case 'checkbox':
mappedValue = _extends({}, mappedValue, { target: { checked: value } });
break;
default:
mappedValue = _extends({}, mappedValue, { target: { value: value } });
}
this.handleChange(mappedValue);
}
}]);
return Field;
}(_react2.default.Component);
Field.contextTypes = {
changeRadio: _propTypes2.default.func,
queueChange: _propTypes2.default.func,
radioValue: _propTypes2.default.any,
resource: _propTypes2.default.object
};
Field.childContextTypes = {
changeRadio: _propTypes2.default.func,
radioValue: _propTypes2.default.any
};
Field.propTypes = {
className: _propTypes2.default.string,
component: _propTypes2.default.func,
includeBlank: _propTypes2.default.bool,
name: _propTypes2.default.string.isRequired,
options: _propTypes2.default.instanceOf(_activeResource2.default.Collection),
optionsLabel: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.func]),
type: _propTypes2.default.string.isRequired,
uncheckedValue: _propTypes2.default.oneOfType([_propTypes2.default.object, _propTypes2.default.func, _propTypes2.default.string, _propTypes2.default.number, _propTypes2.default.bool]),
invalidClassName: _propTypes2.default.string,
value: _propTypes2.default.oneOfType([_propTypes2.default.object, _propTypes2.default.func, _propTypes2.default.string, _propTypes2.default.number, _propTypes2.default.bool])
};
var Resource = exports.Resource = function (_React$Component3) {
_inherits(Resource, _React$Component3);
function Resource(props, context) {
_classCallCheck(this, Resource);
var _this5 = _possibleConstructorReturn(this, (Resource.__proto__ || Object.getPrototypeOf(Resource)).call(this));
_underscore2.default.bindAll(_this5, "afterUpdate", "assignChanges", "queueReflectionChange", "shiftReflectionQueue", "queueChange", "handleSubmit", "updateRoot");
var root = context.root;
var parent = props.parent,
reflection = props.reflection,
subject = props.subject;
var state = { resource: subject };
if (reflection) {
var reflectionInstance = (root || parent).klass().reflectOnAssociation(reflection);
if (_underscore2.default.isUndefined(reflectionInstance)) throw "Reflection " + reflection + " not found.";
var inverseReflection = reflectionInstance.inverseOf();
if (_underscore2.default.isUndefined(inverseReflection)) throw "Reflection " + reflection + " must have inverse.";
state = _extends({}, state, {
inverseReflection: inverseReflection,
queuedChanges: {},
reflection: reflectionInstance,
updating: false
});
} else {
state = _extends({}, state, {
queuedReflectionChanges: []
});
}
_this5.beforeSubmit = props.beforeSubmit;
_this5.state = state;
return _this5;
}
_createClass(Resource, [{
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(nextProps) {
var afterUpdate = this.props.afterUpdate;
var inverseReflection = this.state.inverseReflection;
var _context = this.context,
afterUpdateRoot = _context.afterUpdateRoot,
queuedReflectionChanges = _context.queuedReflectionChanges,
shiftReflectionQueue = _context.shiftReflectionQueue;
this.setState({ resource: nextProps.subject });
if (afterUpdate && !inverseReflection) {
this.setState({ updating: false });
this.assignChanges();
} else {
if (afterUpdateRoot && inverseReflection && queuedReflectionChanges[0] === this) {
shiftReflectionQueue();
this.assignChanges();
}
}
}
}, {
key: 'componentDidCatch',
value: function componentDidCatch(error) {
return _react2.default.createElement(
'p',
null,
error
);
}
}, {
key: 'afterUpdate',
value: function afterUpdate(newResource) {
var updateRoot = this.context.updateRoot;
var _state = this.state,
inverseReflection = _state.inverseReflection,
resource = _state.resource;
if (inverseReflection) {
var oldTarget = resource.association(inverseReflection.name).target;
var newTarget = newResource.association(inverseReflection.name).target;
if (inverseReflection.collection()) {
// FIXME: Allow autosave inverseOf collection to appropriately handle multiple resources in the collection,
// not just the first. If changing multiple fields of resource quickly, root may not be found in oldTarget
// because it has already been replaced by a previous change
// var index = oldTarget.indexOf(root);
// var newRoot = newTarget.get(index);
updateRoot(newTarget.first());
} else {
updateRoot(newTarget);
}
} else {
this.updateRoot(newResource);
}
}
}, {
key: 'assignChanges',
value: function assignChanges() {
var _state2 = this.state,
queuedChanges = _state2.queuedChanges,
resource = _state2.resource;
if (_underscore2.default.keys(queuedChanges).length == 0) return;
var newResource = resource.assignAttributes(queuedChanges);
this.setState({ queuedChanges: {} });
this.afterUpdate(newResource);
}
}, {
key: 'queueChange',
value: function queueChange(change) {
var _this6 = this;
var afterUpdate = this.props.afterUpdate;
var _state3 = this.state,
inverseReflection = _state3.inverseReflection,
queuedChanges = _state3.queuedChanges,
updating = _state3.updating;
this.setState({
queuedChanges: _extends({}, queuedChanges, change)
}, function () {
var _context2 = _this6.context,
afterUpdateRoot = _context2.afterUpdateRoot,
queueReflectionChange = _context2.queueReflectionChange,
updatingRoot = _context2.updatingRoot;
if (afterUpdate || afterUpdateRoot) {
if (inverseReflection) {
if (updatingRoot) {
queueReflectionChange(_this6);
} else {
_this6.assignChanges();
}
} else {
if (!updating) _this6.assignChanges();
}
} else {
_this6.assignChanges();
}
});
}
}, {
key: 'queueReflectionChange',
value: function queueReflectionChange(resource) {
var queuedReflectionChanges = this.state.queuedReflectionChanges;
queuedReflectionChanges.push(resource);
this.setState({ queuedReflectionChanges: queuedReflectionChanges });
}
}, {
key: 'shiftReflectionQueue',
value: function shiftReflectionQueue() {
var queuedReflectionChanges = this.state.queuedReflectionChanges;
queuedReflectionChanges.shift();
this.setState({ queuedReflectionChanges: queuedReflectionChanges });
}
}, {
key: 'getChildContext',
value: function getChildContext() {
var _props9 = this.props,
afterUpdate = _props9.afterUpdate,
parent = _props9.parent;
var root = this.context.root;
var _state4 = this.state,
resource = _state4.resource,
queuedReflectionChanges = _state4.queuedReflectionChanges,
updating = _state4.updating;
var childContext = {
afterUpdateRoot: afterUpdate,
isNestedResource: true,
queueChange: this.queueChange,
queuedReflectionChanges: queuedReflectionChanges,
queueReflectionChange: this.queueReflectionChange,
shiftReflectionQueue: this.shiftReflectionQueue,
root: parent || root || resource,
resource: resource,
updateRoot: this.updateRoot,
updatingRoot: updating
};
return childContext;
}
}, {
key: 'handleSubmit',
value: function handleSubmit(e, callback) {
if (e) e.preventDefault();
var _props10 = this.props,
onSubmit = _props10.onSubmit,
onInvalidSubmit = _props10.onInvalidSubmit;
var resource = this.state.resource;
var onSubmitCallback = function onSubmitCallback(resourceToSubmit) {
if (!_underscore2.default.isUndefined(onSubmit)) {
onSubmit(resourceToSubmit);
}
if (!_underscore2.default.isUndefined(callback)) {
callback(resourceToSubmit);
}
};
var onInvalidSubmitCallback = function onInvalidSubmitCallback(invalidResource) {
if (!_underscore2.default.isUndefined(onInvalidSubmit)) {
onInvalidSubmit(invalidResource);
}
if (!_underscore2.default.isUndefined(callback)) {
callback(invalidResource);
}
};
var beforeSubmit = this.beforeSubmit || this.componentRef && this.componentRef.beforeSubmit;
if (!_underscore2.default.isUndefined(beforeSubmit)) {
new Promise(function (resolve, reject) {
try {
var result = beforeSubmit(resource);
resolve(result);
} catch (invalid) {
reject(invalid);
}
}).then(onSubmitCallback).catch(onInvalidSubmitCallback);
} else {
onSubmitCallback(resource);
}
}
}, {
key: 'render',
value: function render() {
var _this7 = this;
var isNestedResource = this.context.isNestedResource;
var _props11 = this.props,
afterError = _props11.afterError,
children = _props11.children,
className = _props11.className,
component = _props11.component,
componentProps = _props11.componentProps,
componentRef = _props11.componentRef;
var resource = this.state.resource;
var body = void 0;
if (component) {
body = _react2.default.createElement(component, _extends({}, componentProps, {
afterUpdate: this.afterUpdate,
afterError: afterError,
onSubmit: this.handleSubmit,
subject: resource,
ref: function ref(c) {
_this7.componentRef = c;
componentRef(c);
}
}));
} else {
body = children;
}
if (isNestedResource) {
return _react2.default.createElement(
'section',
{ className: className },
body
);
} else {
return _react2.default.createElement(
'form',
{ className: className, onSubmit: this.handleSubmit },
body
);
}
}
}, {
key: 'updateRoot',
value: function updateRoot(newRoot) {
var afterUpdate = this.props.afterUpdate;
var resource = this.state.resource;
this.setState({ resource: newRoot });
if (afterUpdate) {
afterUpdate(newRoot, resource);
this.setState({ updating: true });
}
}
}]);
return Resource;
}(_react2.default.Component);
Resource.propTypes = {
afterError: _propTypes2.default.func,
afterUpdate: _propTypes2.default.func,
children: _propTypes2.default.oneOfType([_propTypes2.default.array, _propTypes2.default.node]),
className: _propTypes2.default.string,
component: _propTypes2.default.func,
componentProps: _propTypes2.default.object,
onInvalidSubmit: _propTypes2.default.func,
onSubmit: _propTypes2.default.func,
parent: _propTypes2.default.object,
reflection: _propTypes2.default.string,
subject: _propTypes2.default.object.isRequired
};
Resource.contextTypes = {
afterUpdateRoot: _propTypes2.default.func,
isNestedResource: _propTypes2.default.bool,
queuedReflectionChanges: _propTypes2.default.array,
queueReflectionChange: _propTypes2.default.func,
shiftReflectionQueue: _propTypes2.default.func,
root: _propTypes2.default.object,
updateRoot: _propTypes2.default.func,
updatingRoot: _propTypes2.default.bool
};
Resource.childContextTypes = {
afterUpdateRoot: _propTypes2.default.func,
isNestedResource: _propTypes2.default.bool,
queueChange: _propTypes2.default.func,
queuedReflectionChanges: _propTypes2.default.array,
queueReflectionChange: _propTypes2.default.func,
shiftReflectionQueue: _propTypes2.default.func,
resource: _propTypes2.default.object,
root: _propTypes2.default.object,
updateRoot: _propTypes2.default.func,
updatingRoot: _propTypes2.default.bool
};
Resource.defaultProps = {
componentProps: {},
componentRef: _underscore2.default.noop
};
});
import React from 'react';
import PropTypes from 'prop-types';
import ActiveResource from 'active-resource';
import _ from 'underscore';
export class Collection extends React.PureComponent {
static propTypes = {
children: PropTypes.oneOfType([
PropTypes.array,
PropTypes.node,
]),
className: PropTypes.string,
blankComponent: PropTypes.func,
component: PropTypes.func,
componentProps: PropTypes.object,
subject: PropTypes.oneOfType([
PropTypes.object,
PropTypes.func,
]).isRequired,
reflection: PropTypes.string,
};
static defaultProps = {
inlineRows: false
};
// link to global state by enabling afterLoad, afterAdd, afterRemove, afterUpdate callbacks that can call
// an action linked to dispatch
constructor() {
super();
this.state = {
target: ActiveResource.prototype.Collection.build()
};
_.bindAll(this,
'buildOnTarget',
'cloneTarget',
'replaceOnTarget',
'removeFromTarget',
);
}
componentDidMount() {
this.setTarget(this.props);
}
componentWillReceiveProps(nextProps) {
this.setTarget(nextProps);
}
setTarget(props) {
const { subject } = props;
this.setState({ target: subject.target() })
}
buildOnTarget(attributes) {
const { subject } = this.props;
let target = this.cloneTarget();
target.push(subject.build(attributes));
this.setState({ target: target });
}
replaceOnTarget(newItem, oldItem) {
let target = this.cloneTarget();
target.replace(oldItem, newItem);
return this.setState({ target });
}
removeFromTarget(item) {
let target = this.cloneTarget();
target.delete(item);
return this.setState({ target });
}
cloneTarget() {
return this.state.target.clone();
}
render() {
const { blankComponent, children, className, component, componentProps, reflection } = this.props;
const { target } = this.state;
return (
<section className={ className }>
{
target.size() > 0 ? (
target.map((t, indexOf) =>
<Resource afterUpdate={this.replaceOnTarget}
component={component} componentProps={{...componentProps, indexOf}}
key={t.id || (t.klass().className + '-' + indexOf)}
reflection={reflection}
subject={t}>
{children}
</Resource>
).toArray()
) : (blankComponent != null &&
blankComponent()
)
}
</section>
);
}
}
export class ErrorsFor extends React.Component {
static propTypes = {
component: PropTypes.func,
field: PropTypes.string,
};
static contextTypes = {
resource: PropTypes.object,
};
shouldComponentUpdate(nextProps, nextState, nextContext) {
return !(shallowEqual(this.props, nextProps) && shallowEqual(this.state, nextState) && shallowEqual(this.context, nextContext));
}
render() {
const { resource } = this.context;
const { component, field } = this.props;
var errors = resource.errors().forField(field);
if(errors.empty()) return null;
let customProps = _.omit(this.props, _.keys(ErrorsFor.propTypes));
let finalComponent = component || 'summary';
return React.createElement(finalComponent, {
...customProps,
key: field,
},
errors.map((error) => {
return <span key={ error.code }>{ error.message }</span>
}).toArray()
);
}
};
import classNames from 'classnames';
import shallowEqual from 'shallowequal';
export class Field extends React.Component {
static contextTypes = {
changeRadio: PropTypes.func,
queueChange: PropTypes.func,
radioValue: PropTypes.any,
resource: PropTypes.object,
};
static childContextTypes = {
changeRadio: PropTypes.func,
radioValue: PropTypes.any,
};
static propTypes = {
className: PropTypes.string,
component: PropTypes.func,
includeBlank: PropTypes.bool,
name: PropTypes.string.isRequired,
options: PropTypes.instanceOf(ActiveResource.Collection),
optionsLabel: PropTypes.oneOfType([
PropTypes.string,
PropTypes.func,
]),
type: PropTypes.string.isRequired,
uncheckedValue: PropTypes.oneOfType([
PropTypes.object,
PropTypes.func,
PropTypes.string,
PropTypes.number,
PropTypes.bool,
]),
invalidClassName: PropTypes.string,
value: PropTypes.oneOfType([
PropTypes.object,
PropTypes.func,
PropTypes.string,
PropTypes.number,
PropTypes.bool,
])
};
constructor() {
super();
_.bindAll(this,
'afterChange',
'changeRadio',
'classNames',
'commonInputProps',
'customInputProps',
'getValue',
'handleChange',
'renderCheckboxComponent',
'renderInputComponent',
'renderRadioComponent',
'renderSelectComponent',
'renderTextareaComponent',
'setValue',
'valueFor',
);
this.state = {};
}
shouldComponentUpdate(nextProps, nextState, nextContext) {
return !(shallowEqual(this.props, nextProps) && shallowEqual(this.state, nextState) && shallowEqual(this.context, nextContext));
}
getChildContext() {
const { type } = this.props;
const { value } = this.state;
switch(type) {
case 'radioGroup':
return {
changeRadio: this.changeRadio,
radioValue: value,
};
}
}
changeRadio(value) {
this.setState({ value });
}
componentWillMount() {
const { type } = this.props;
const { resource } = this.context;
// Set initial value to that of the resources
this.setState({
resource,
value: this.valueFor(resource, this.props)
});
switch(type) {
case 'email':
case 'number':
case 'text':
case 'textarea':
this.afterChange = _.debounce(this.afterChange, 500);
}
}
componentDidUpdate(prevProps, prevState) {
const { resource: prevResource } = prevState
const { resource } = this.context
if(prevResource !== resource) {
this.setState({ resource })
}
if(!(_.isNull(prevResource.id) || _.isUndefined(prevResource.id)) && prevResource.id !== resource.id) {
this.setState({
value: this.valueFor(resource, this.props)
})
}
}
classNames() {
const { className, invalidClassName, name } = this.props;
const { resource } = this.context;
return classNames(
className,
{
[invalidClassName]: !resource.errors().forField(name).empty()
}
);
}
commonInputProps() {
const { name } = this.props;
let props = {
className: this.classNames(),
key: name,
name,
onChange: this.handleChange,
};
return props;
}
componentFor(type) {
switch(type) {
case 'checkbox':
return this.renderCheckboxComponent();
case 'radio':
return this.renderRadioComponent();
case 'radioGroup':
return this.renderRadioGroupComponent();
case 'select':
return this.renderSelectComponent();
case 'textarea':
return this.renderTextareaComponent();
default:
return this.renderInputComponent();
}
}
// @note type='radio' will pass down +name+ prop
// @note type='select' will only pass down +type+ prop if +component+ prop is defined
customInputProps() {
const { component, type } = this.props;
var omittedProps;
switch(type) {
case 'radio':
omittedProps = _.omit(Field.propTypes, ['type', 'name']);
break;
case 'select':
omittedProps = component ? _.omit(Field.propTypes, 'type') : Field.propTypes;
break;
default:
omittedProps = _.omit(Field.propTypes, 'type');
}
return _.omit(this.props, _.keys(omittedProps));
}
// TODO: Add support for non-resource options on select and radioGroup
valueFor(resource, props) {
const { name, type, uncheckedValue, value } = props;
switch(type) {
case 'checkbox':
var resourceValue = resource[name];
if(resourceValue == value) {
return true;
} else if(resourceValue == uncheckedValue || _.isUndefined(resourceValue) || _.isNull(resourceValue)) {
return false;
} else {
throw 'Field ' + name + ' with value ' + resource[name] + ' does not match value or uncheckedValue for checkbox'
}
case 'radioGroup':
case 'select':
var val = resource[name]();
return val ? val.id : '';
default:
var val = resource[name];
return val ? val : '';
}
}
render() {
const { type } = this.props;
return this.componentFor(type);
}
renderCheckboxComponent() {
const { component } = this.props;
let finalComponent = component || 'input';
return React.createElement(finalComponent, {
...this.commonInputProps(),
...this.customInputProps(),
checked: this.state.value,
});
}
renderInputComponent() {
const { component } = this.props;
let finalComponent = component || 'input';
return React.createElement(finalComponent, {
...this.commonInputProps(),
...this.customInputProps(),
value: this.state.value,
});
}
renderRadioComponent() {
const { component, value } = this.props;
const { radioValue } = this.context;
if (_.isUndefined(value)) {
throw 'Input type="radio" must have prop "value"';
}
let finalComponent = component || 'input';
return React.createElement(finalComponent, {
...this.commonInputProps(),
...this.customInputProps(),
checked: value.id == radioValue,
value: value.id,
name: value.questionId
});
}
renderRadioGroupComponent() {
return <div>
{ this.props.children }
</div>;
}
renderSelectComponent() {
const { component, includeBlank, options, optionsLabel } = this.props;
let selectOptions = null;
if (options.empty()) {
throw 'Input type="select" must have options';
} else {
selectOptions = options.map((o) => {
return <option key={o.id} value={o.id}>
{
_.isString(optionsLabel) ? (
o[optionsLabel]
) : (
optionsLabel(o)
)
}
</option>;
});
if (includeBlank) {
selectOptions.unshift(<option key={-1} value=''></option>);
}
}
let finalComponent = component || 'select';
return React.createElement(finalComponent, {
...this.commonInputProps(),
...this.customInputProps(),
value: this.state.value,
}, selectOptions.toArray());
}
renderTextareaComponent() {
const { component } = this.props;
let finalComponent = component || 'textarea';
return React.createElement(finalComponent, {
...this.commonInputProps(),
...this.customInputProps(),
value: this.state.value,
});
}
handleChange(e) {
e.persist();
const { max, min, type } = this.props;
const { changeRadio } = this.context;
let value;
switch(type) {
case 'checkbox':
value = e.target.checked;
break;
case 'number':
if(e.target.value > max) {
value = max;
} else if(e.target.value < min) {
value = min;
} else {
value = e.target.value || min;
}
break;
case 'radio':
changeRadio(e.target.value);
break;
default:
value = e.target.value;
}
this.setState({ value }, this.afterChange);
}
afterChange() {
const { name, type, options, uncheckedValue, value } = this.props;
const { value: stateValue } = this.state;
const { queueChange } = this.context;
let mappedValue;
switch(type) {
case 'checkbox':
if(stateValue) {
mappedValue = value;
} else {
mappedValue = uncheckedValue;
}
break;
case 'radio':
mappedValue = value;
break;
case 'select':
mappedValue = options.detect((o) => o.id === stateValue);
break;
default:
mappedValue = stateValue;
}
queueChange({ [name]: mappedValue });
}
getValue() {
return this.state.value;
}
setValue(value) {
const { type } = this.props;
let mappedValue = { persist: _.noop };
switch(type) {
case 'checkbox':
mappedValue = { ...mappedValue, target: { checked: value } };
break;
default:
mappedValue = { ...mappedValue, target: { value } };
}
this.handleChange(mappedValue);
}
}
export class Resource extends React.Component {
static propTypes = {
afterError: PropTypes.func,
afterUpdate: PropTypes.func,
children: PropTypes.oneOfType([PropTypes.array, PropTypes.node]),
className: PropTypes.string,
component: PropTypes.func,
componentProps: PropTypes.object,
onInvalidSubmit: PropTypes.func,
onSubmit: PropTypes.func,
parent: PropTypes.object,
reflection: PropTypes.string,
subject: PropTypes.object.isRequired,
};
static contextTypes = {
afterUpdateRoot: PropTypes.func,
isNestedResource: PropTypes.bool,
queuedReflectionChanges: PropTypes.array,
queueReflectionChange: PropTypes.func,
shiftReflectionQueue: PropTypes.func,
root: PropTypes.object,
updateRoot: PropTypes.func,
updatingRoot: PropTypes.bool,
};
static childContextTypes = {
afterUpdateRoot: PropTypes.func,
isNestedResource: PropTypes.bool,
queueChange: PropTypes.func,
queuedReflectionChanges: PropTypes.array,
queueReflectionChange: PropTypes.func,
shiftReflectionQueue: PropTypes.func,
resource: PropTypes.object,
root: PropTypes.object,
updateRoot: PropTypes.func,
updatingRoot: PropTypes.bool,
};
static defaultProps = {
componentProps: {},
componentRef: _.noop,
};
constructor(props, context) {
super();
_.bindAll(
this,
"afterUpdate",
"assignChanges",
"queueReflectionChange",
"shiftReflectionQueue",
"queueChange",
"handleSubmit",
"updateRoot"
);
const root = context.root;
const { parent, reflection, subject } = props;
let state = { resource: subject };
if (reflection) {
var reflectionInstance = (root || parent).klass().reflectOnAssociation(reflection);
if (_.isUndefined(reflectionInstance)) throw "Reflection " + reflection + " not found.";
var inverseReflection = reflectionInstance.inverseOf();
if (_.isUndefined(inverseReflection)) throw "Reflection " + reflection + " must have inverse.";
state = {
...state,
inverseReflection,
queuedChanges: {},
reflection: reflectionInstance,
updating: false,
};
} else {
state = {
...state,
queuedReflectionChanges: [],
};
}
this.beforeSubmit = props.beforeSubmit;
this.state = state;
}
componentWillReceiveProps(nextProps) {
const { afterUpdate } = this.props;
const { inverseReflection } = this.state;
const { afterUpdateRoot, queuedReflectionChanges, shiftReflectionQueue } = this.context;
this.setState({ resource: nextProps.subject });
if (afterUpdate && !inverseReflection) {
this.setState({ updating: false });
this.assignChanges();
} else {
if (afterUpdateRoot && inverseReflection && queuedReflectionChanges[0] === this) {
shiftReflectionQueue();
this.assignChanges();
}
}
}
componentDidCatch(error) {
return <p>{error}</p>;
}
afterUpdate(newResource) {
const { updateRoot } = this.context;
const { inverseReflection, resource } = this.state;
if (inverseReflection) {
var oldTarget = resource.association(inverseReflection.name).target;
var newTarget = newResource.association(inverseReflection.name).target;
if (inverseReflection.collection()) {
// FIXME: Allow autosave inverseOf collection to appropriately handle multiple resources in the collection,
// not just the first. If changing multiple fields of resource quickly, root may not be found in oldTarget
// because it has already been replaced by a previous change
// var index = oldTarget.indexOf(root);
// var newRoot = newTarget.get(index);
updateRoot(newTarget.first());
} else {
updateRoot(newTarget);
}
} else {
this.updateRoot(newResource);
}
}
assignChanges() {
const { queuedChanges, resource } = this.state;
if (_.keys(queuedChanges).length == 0) return;
var newResource = resource.assignAttributes(queuedChanges);
this.setState({ queuedChanges: {} });
this.afterUpdate(newResource);
}
queueChange(change) {
const { afterUpdate } = this.props;
const { inverseReflection, queuedChanges, updating } = this.state;
this.setState(
{
queuedChanges: {
...queuedChanges,
...change,
},
},
() => {
const { afterUpdateRoot, queueReflectionChange, updatingRoot } = this.context;
if (afterUpdate || afterUpdateRoot) {
if (inverseReflection) {
if (updatingRoot) {
queueReflectionChange(this);
} else {
this.assignChanges();
}
} else {
if (!updating) this.assignChanges();
}
} else {
this.assignChanges();
}
}
);
}
queueReflectionChange(resource) {
let { queuedReflectionChanges } = this.state;
queuedReflectionChanges.push(resource);
this.setState({ queuedReflectionChanges });
}
shiftReflectionQueue() {
let { queuedReflectionChanges } = this.state;
queuedReflectionChanges.shift();
this.setState({ queuedReflectionChanges });
}
getChildContext() {
const { afterUpdate, parent } = this.props;
const { root } = this.context;
const { resource, queuedReflectionChanges, updating } = this.state;
let childContext = {
afterUpdateRoot: afterUpdate,
isNestedResource: true,
queueChange: this.queueChange,
queuedReflectionChanges: queuedReflectionChanges,
queueReflectionChange: this.queueReflectionChange,
shiftReflectionQueue: this.shiftReflectionQueue,
root: parent || root || resource,
resource,
updateRoot: this.updateRoot,
updatingRoot: updating,
};
return childContext;
}
handleSubmit(e, callback) {
if (e) e.preventDefault();
const { onSubmit, onInvalidSubmit } = this.props;
const { resource } = this.state;
var onSubmitCallback = (resourceToSubmit) => {
if (!_.isUndefined(onSubmit)) {
onSubmit(resourceToSubmit);
}
if (!_.isUndefined(callback)) {
callback(resourceToSubmit);
}
};
var onInvalidSubmitCallback = (invalidResource) => {
if (!_.isUndefined(onInvalidSubmit)) {
onInvalidSubmit(invalidResource);
}
if (!_.isUndefined(callback)) {
callback(invalidResource);
}
};
let beforeSubmit = this.beforeSubmit || (this.componentRef && this.componentRef.beforeSubmit);
if (!_.isUndefined(beforeSubmit)) {
new Promise((resolve, reject) => {
try {
var result = beforeSubmit(resource);
resolve(result);
} catch (invalid) {
reject(invalid);
}
})
.then(onSubmitCallback)
.catch(onInvalidSubmitCallback);
} else {
onSubmitCallback(resource);
}
}
render() {
const { isNestedResource } = this.context;
const { afterError, children, className, component, componentProps, componentRef } = this.props;
const { resource } = this.state;
let body;
if (component) {
body = React.createElement(component, {
...componentProps,
afterUpdate: this.afterUpdate,
afterError,
onSubmit: this.handleSubmit,
subject: resource,
ref: (c) => {
this.componentRef = c;
componentRef(c);
},
});
} else {
body = children;
}
if (isNestedResource) {
return <section className={className}>{body}</section>;
} else {
return (
<form className={className} onSubmit={this.handleSubmit}>
{body}
</form>
);
}
}
updateRoot(newRoot) {
const { afterUpdate } = this.props;
const { resource } = this.state;
this.setState({ resource: newRoot });
if (afterUpdate) {
afterUpdate(newRoot, resource);
this.setState({ updating: true });
}
}
}
module.exports = function(grunt) {
require('load-grunt-tasks')(grunt);
// configure the tasks
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
clean: {
dist: {
src: [ 'dist' ]
},
specs: {
src: 'spec/spec.js'
}
},
babel: {
options: {
presets: ['env'],
plugins: [
'transform-class-properties',
'transform-es2015-modules-umd',
'transform-object-rest-spread',
'transform-react-jsx'
]
},
build: {
files: {
'build/mitragyna.js': 'build/mitragyna.jsx'
}
},
specs: {
files: {
'spec/spec.js': [ 'spec/**/*.jsx' ]
}
}
},
concat: {
release: {
options: {
banner:
'/*\n' +
'\tmitragyna <%= pkg.version %>\n' +
'\t(c) <%= grunt.template.today("yyyy") %> Nick Landgrebe\n' +
'\tmitragyna may be freely distributed under the MIT license\n' +
'*/\n\n'
},
files: {
'dist/mitragyna.js': ['build/mitragyna.js'],
'dist/mitragyna.min.js': ['build/mitragyna.min.js'],
'dist/mitragyna.min.js.map': ['build/mitragyna.min.js.map']
}
},
build: {
files: {
'build/mitragyna.jsx': 'src/**/*.jsx'
}
}
},
connect: {
test: {
options: {
port: 8000
}
}
}
});
// load the tasks
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-umd');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-connect');
// define the tasks
grunt.registerTask(
'spec',
'Compiles and runs the Javascript spec files for source code.',
[ 'clean:specs', 'babel:specs', 'connect:test' ]
);
grunt.registerTask(
'build',
'Creates a build of the library in the build folder, then runs the specs on it.',
[ 'concat:build', 'babel:build' ]
);
grunt.registerTask(
'release',
'Creates a new release of the library in the dist folder',
[ 'clean:dist', 'build', 'concat:release' ]
);
grunt.registerTask(
'default',
'Watches the project for changes, automatically builds them and runs specs.',
[ 'build', 'watch' ]
);
};
ActiveResource.js binding framework for React components
## Installation
```javascript
yarn add @getoccasion/mitragyna
```
You can also use the CDN address https://unpkg.com/@getoccasion/mitragyna to add it to your AMD loader or into your page:
```html
<script type="text/javascript" src="https://unpkg.com/@getoccasion/mitragyna"></script>
```
## Getting Started
1. Set a resource, and attach a child component to render with that subject
```jsx
<Resource component={Customer} reflection="customer" subject={customer} />
```
2. Have a field in the child component that responds to the subject from the parent Resource
```jsx
<Field
type="email"
name="email"
id="email"
component={Input}
invalidClassName="is-invalid"
placeholder="jane.doe@example.com"
/>
<ErrorsFor className="customer-email-errors" component={FormFeedback} field="email" />
```
3. You can nest Resources with setting a reflection
```jsx
<Resource component={Customer} reflection="customer" subject={customer} />
```
4. Bind some callback logic to the (root) resource
- afterError: PropTypes.func
- afterUpdate: PropTypes.func
- onInvalidSubmit: PropTypes.func
- onSubmit: PropTypes.func
- beforeSubmit: PropTypes.func
### If using nested resources
```jsx
<Resource component={Customer} reflection="customer" subject={subject.customer()} parent={subject} />
```
### Binding and updating values from Fields
```jsx
const fulfillmentType = useRef()
// Render <Input> component for value that keeps subject up to date
<Field
type="hidden"
name="fulfillmentType"
id="fulfillmentType"
component={Input}
ref={fulfillmentType}
/>
// Get value
fulfillmentType.current && fulfillmentType.current.state.value
// Update value
fulfillmentType.current && fulfillmentType.current.setValue('value here')
```
+6
-22

@@ -1,29 +0,13 @@

## [0.1.2] - 2020-05-07
## [0.2.0] - 2020-05-013
### Added
- add active resource as a peer dependency
### Fixed
- main pointing to index.js
- Allow boolean for value and uncheckedValue prop
### Removed
### Added
- Underscore dependency
- Add support for multi-nested Resources with the `parent={}` prop
## [0.1.1] - 2020-05-07
## [0.0.3]
### Fixed
- use Component to allow impure resources
## [0.1.0] - 2020-05-07
### Fixed
- Allow boolean for value and uncheckedValue prop
### Removed
- Build with grunt, now using src as a main
- No changelog
{
"name": "@getoccasion/mitragyna",
"version": "0.1.2",
"version": "0.2.0",
"description": "A library for managing ActiveResource.js as React components",
"main": "src/index.js",
"main": "build/mitragyna.js",
"scripts": {
"test": "grunt spec",
"develop": "grunt",
"build": "grunt build",
"version": "npm version",
"publish": "npm publish --access public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/getOccasion/mitragyna.git"
"url": "git+https://github.com/getoccasion/mitragyna.git"
},

@@ -14,8 +21,8 @@ "keywords": [

],
"author": "Nick Landgrebe, Kieran Klaassen & Pelle ten Cate",
"author": "Nick Landgrebe, Pelle ten Cate & Kieran Klaassen",
"license": "MIT",
"bugs": {
"url": "https://github.com/getOccasion/mitragyna/issues"
"url": "https://github.com/getoccasion/mitragyna/issues"
},
"homepage": "https://github.com/getOccasion/mitragyna#readme",
"homepage": "https://github.com/getoccasion/mitragyna#readme",
"devDependencies": {

@@ -27,13 +34,21 @@ "babel-core": "^6.26.0",

"babel-plugin-transform-react-jsx": "^6.24.1",
"babel-preset-env": "^1.6.1"
"babel-preset-env": "^1.6.1",
"grunt": "0.x.x",
"grunt-babel": "^7.0.0",
"grunt-contrib-clean": "0.5.x",
"grunt-contrib-concat": "^1.0.1",
"grunt-contrib-connect": "0.4.x",
"grunt-contrib-uglify": "^3.3.0",
"grunt-contrib-watch": "0.5.x",
"grunt-umd": "^2.4.0",
"load-grunt-tasks": "^3.5.2"
},
"dependencies": {
"active-resource": "GetOccasion/activeresource.js#track_local_changes",
"classnames": "^2.2.5",
"prop-types": "^15.6.0",
"react": "^16.2.0",
"shallowequal": "^1.0.2"
},
"peerDependencies": {
"active-resource": "GetOccasion/activeresource.js#track_local_changes"
"shallowequal": "^1.0.2",
"underscore": "^1.8.3"
}
}

@@ -1,8 +0,12 @@

import React from "react";
import PropTypes from "prop-types";
import ActiveResource from "active-resource";
import React from 'react';
import PropTypes from 'prop-types';
import ActiveResource from 'active-resource';
import _ from 'underscore';
export default class Collection extends React.PureComponent {
export class Collection extends React.PureComponent {
static propTypes = {
children: PropTypes.oneOfType([PropTypes.array, PropTypes.node]),
children: PropTypes.oneOfType([
PropTypes.array,
PropTypes.node,
]),
className: PropTypes.string,

@@ -12,3 +16,6 @@ blankComponent: PropTypes.func,

componentProps: PropTypes.object,
subject: PropTypes.oneOfType([PropTypes.object, PropTypes.func]).isRequired,
subject: PropTypes.oneOfType([
PropTypes.object,
PropTypes.func,
]).isRequired,
reflection: PropTypes.string,

@@ -18,3 +25,3 @@ };

static defaultProps = {
inlineRows: false,
inlineRows: false
};

@@ -29,4 +36,11 @@

this.state = {
target: ActiveResource.prototype.Collection.build(),
target: ActiveResource.prototype.Collection.build()
};
_.bindAll(this,
'buildOnTarget',
'cloneTarget',
'replaceOnTarget',
'removeFromTarget',
);
}

@@ -45,6 +59,6 @@

this.setState({ target: subject.target() });
this.setState({ target: subject.target() })
}
buildOnTarget = (attributes) => {
buildOnTarget(attributes) {
const { subject } = this.props;

@@ -56,5 +70,5 @@ let target = this.cloneTarget();

this.setState({ target: target });
};
}
replaceOnTarget = (newItem, oldItem) => {
replaceOnTarget(newItem, oldItem) {
let target = this.cloneTarget();

@@ -65,5 +79,5 @@

return this.setState({ target });
};
}
removeFromTarget = (item) => {
removeFromTarget(item) {
let target = this.cloneTarget();

@@ -74,7 +88,7 @@

return this.setState({ target });
};
}
cloneTarget = () => {
cloneTarget() {
return this.state.target.clone();
};
}

@@ -86,19 +100,20 @@ render() {

return (
<section className={className}>
{target.size() > 0
? target
.map((t, indexOf) => (
<Resource
afterUpdate={this.replaceOnTarget}
component={component}
componentProps={{ ...componentProps, indexOf }}
key={t.id || t.klass().className + "-" + indexOf}
reflection={reflection}
subject={t}
>
{children}
</Resource>
))
.toArray()
: blankComponent != null && blankComponent()}
<section className={ className }>
{
target.size() > 0 ? (
target.map((t, indexOf) =>
<Resource afterUpdate={this.replaceOnTarget}
component={component} componentProps={{...componentProps, indexOf}}
key={t.id || (t.klass().className + '-' + indexOf)}
reflection={reflection}
subject={t}>
{children}
</Resource>
).toArray()
) : (blankComponent != null &&
blankComponent()
)
}
</section>

@@ -105,0 +120,0 @@ );

@@ -1,2 +0,2 @@

export default class ErrorsFor extends React.Component {
export class ErrorsFor extends React.Component {
static propTypes = {

@@ -12,7 +12,3 @@ component: PropTypes.func,

shouldComponentUpdate(nextProps, nextState, nextContext) {
return !(
shallowEqual(this.props, nextProps) &&
shallowEqual(this.state, nextState) &&
shallowEqual(this.context, nextContext)
);
return !(shallowEqual(this.props, nextProps) && shallowEqual(this.state, nextState) && shallowEqual(this.context, nextContext));
}

@@ -26,20 +22,16 @@

if (errors.empty()) return null;
if(errors.empty()) return null;
let customProps = _.omit(this.props, _.keys(ErrorsFor.propTypes));
let finalComponent = component || "summary";
return React.createElement(
finalComponent,
{
...customProps,
key: field,
},
errors
.map((error) => {
return <span key={error.code}>{error.message}</span>;
})
.toArray()
let finalComponent = component || 'summary';
return React.createElement(finalComponent, {
...customProps,
key: field,
},
errors.map((error) => {
return <span key={ error.code }>{ error.message }</span>
}).toArray()
);
}
}
};

@@ -1,5 +0,5 @@

import classNames from "classnames";
import shallowEqual from "shallowequal";
import classNames from 'classnames';
import shallowEqual from 'shallowequal';
export default class Field extends React.Component {
export class Field extends React.Component {
static contextTypes = {

@@ -23,3 +23,6 @@ changeRadio: PropTypes.func,

options: PropTypes.instanceOf(ActiveResource.Collection),
optionsLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
optionsLabel: PropTypes.oneOfType([
PropTypes.string,
PropTypes.func,
]),
type: PropTypes.string.isRequired,

@@ -34,3 +37,9 @@ uncheckedValue: PropTypes.oneOfType([

invalidClassName: PropTypes.string,
value: PropTypes.oneOfType([PropTypes.object, PropTypes.func, PropTypes.string, PropTypes.number, PropTypes.bool]),
value: PropTypes.oneOfType([
PropTypes.object,
PropTypes.func,
PropTypes.string,
PropTypes.number,
PropTypes.bool,
])
};

@@ -41,18 +50,17 @@

_.bindAll(
this,
"afterChange",
"changeRadio",
"classNames",
"commonInputProps",
"customInputProps",
"getValue",
"handleChange",
"renderCheckboxComponent",
"renderInputComponent",
"renderRadioComponent",
"renderSelectComponent",
"renderTextareaComponent",
"setValue",
"valueFor"
_.bindAll(this,
'afterChange',
'changeRadio',
'classNames',
'commonInputProps',
'customInputProps',
'getValue',
'handleChange',
'renderCheckboxComponent',
'renderInputComponent',
'renderRadioComponent',
'renderSelectComponent',
'renderTextareaComponent',
'setValue',
'valueFor',
);

@@ -64,7 +72,3 @@

shouldComponentUpdate(nextProps, nextState, nextContext) {
return !(
shallowEqual(this.props, nextProps) &&
shallowEqual(this.state, nextState) &&
shallowEqual(this.context, nextContext)
);
return !(shallowEqual(this.props, nextProps) && shallowEqual(this.state, nextState) && shallowEqual(this.context, nextContext));
}

@@ -76,4 +80,4 @@

switch (type) {
case "radioGroup":
switch(type) {
case 'radioGroup':
return {

@@ -97,10 +101,10 @@ changeRadio: this.changeRadio,

resource,
value: this.valueFor(resource, this.props),
value: this.valueFor(resource, this.props)
});
switch (type) {
case "email":
case "number":
case "text":
case "textarea":
switch(type) {
case 'email':
case 'number':
case 'text':
case 'textarea':
this.afterChange = _.debounce(this.afterChange, 500);

@@ -111,13 +115,13 @@ }

componentDidUpdate(prevProps, prevState) {
const { resource: prevResource } = prevState;
const { resource } = this.context;
const { resource: prevResource } = prevState
const { resource } = this.context
if (prevResource !== resource) {
this.setState({ resource });
if(prevResource !== resource) {
this.setState({ resource })
}
if (!(_.isNull(prevResource.id) || _.isUndefined(prevResource.id)) && prevResource.id !== resource.id) {
if(!(_.isNull(prevResource.id) || _.isUndefined(prevResource.id)) && prevResource.id !== resource.id) {
this.setState({
value: this.valueFor(resource, this.props),
});
value: this.valueFor(resource, this.props)
})
}

@@ -130,5 +134,8 @@ }

return classNames(className, {
[invalidClassName]: !resource.errors().forField(name).empty(),
});
return classNames(
className,
{
[invalidClassName]: !resource.errors().forField(name).empty()
}
);
}

@@ -150,12 +157,12 @@

componentFor(type) {
switch (type) {
case "checkbox":
switch(type) {
case 'checkbox':
return this.renderCheckboxComponent();
case "radio":
case 'radio':
return this.renderRadioComponent();
case "radioGroup":
case 'radioGroup':
return this.renderRadioGroupComponent();
case "select":
case 'select':
return this.renderSelectComponent();
case "textarea":
case 'textarea':
return this.renderTextareaComponent();

@@ -173,11 +180,11 @@ default:

var omittedProps;
switch (type) {
case "radio":
omittedProps = _.omit(Field.propTypes, ["type", "name"]);
switch(type) {
case 'radio':
omittedProps = _.omit(Field.propTypes, ['type', 'name']);
break;
case "select":
omittedProps = component ? _.omit(Field.propTypes, "type") : Field.propTypes;
case 'select':
omittedProps = component ? _.omit(Field.propTypes, 'type') : Field.propTypes;
break;
default:
omittedProps = _.omit(Field.propTypes, "type");
omittedProps = _.omit(Field.propTypes, 'type');
}

@@ -192,22 +199,20 @@

switch (type) {
case "checkbox":
switch(type) {
case 'checkbox':
var resourceValue = resource[name];
if (resourceValue == value) {
if(resourceValue == value) {
return true;
} else if (resourceValue == uncheckedValue || _.isUndefined(resourceValue) || _.isNull(resourceValue)) {
} else if(resourceValue == uncheckedValue || _.isUndefined(resourceValue) || _.isNull(resourceValue)) {
return false;
} else {
throw (
"Field " + name + " with value " + resource[name] + " does not match value or uncheckedValue for checkbox"
);
throw 'Field ' + name + ' with value ' + resource[name] + ' does not match value or uncheckedValue for checkbox'
}
case "radioGroup":
case "select":
case 'radioGroup':
case 'select':
var val = resource[name]();
return val ? val.id : "";
return val ? val.id : '';
default:
var val = resource[name];
return val ? val : "";
return val ? val : '';
}

@@ -225,3 +230,3 @@ }

let finalComponent = component || "input";
let finalComponent = component || 'input';
return React.createElement(finalComponent, {

@@ -237,3 +242,3 @@ ...this.commonInputProps(),

let finalComponent = component || "input";
let finalComponent = component || 'input';
return React.createElement(finalComponent, {

@@ -254,3 +259,3 @@ ...this.commonInputProps(),

let finalComponent = component || "input";
let finalComponent = component || 'input';
return React.createElement(finalComponent, {

@@ -261,3 +266,3 @@ ...this.commonInputProps(),

value: value.id,
name: value.questionId,
name: value.questionId
});

@@ -267,3 +272,5 @@ }

renderRadioGroupComponent() {
return <div>{this.props.children}</div>;
return <div>
{ this.props.children }
</div>;
}

@@ -279,23 +286,23 @@

selectOptions = options.map((o) => {
return (
<option key={o.id} value={o.id}>
{_.isString(optionsLabel) ? o[optionsLabel] : optionsLabel(o)}
</option>
);
return <option key={o.id} value={o.id}>
{
_.isString(optionsLabel) ? (
o[optionsLabel]
) : (
optionsLabel(o)
)
}
</option>;
});
if (includeBlank) {
selectOptions.unshift(<option key={-1} value=""></option>);
selectOptions.unshift(<option key={-1} value=''></option>);
}
}
let finalComponent = component || "select";
return React.createElement(
finalComponent,
{
...this.commonInputProps(),
...this.customInputProps(),
value: this.state.value,
},
selectOptions.toArray()
);
let finalComponent = component || 'select';
return React.createElement(finalComponent, {
...this.commonInputProps(),
...this.customInputProps(),
value: this.state.value,
}, selectOptions.toArray());
}

@@ -306,3 +313,3 @@

let finalComponent = component || "textarea";
let finalComponent = component || 'textarea';
return React.createElement(finalComponent, {

@@ -323,10 +330,10 @@ ...this.commonInputProps(),

switch (type) {
case "checkbox":
switch(type) {
case 'checkbox':
value = e.target.checked;
break;
case "number":
if (e.target.value > max) {
case 'number':
if(e.target.value > max) {
value = max;
} else if (e.target.value < min) {
} else if(e.target.value < min) {
value = min;

@@ -338,3 +345,3 @@ } else {

break;
case "radio":
case 'radio':
changeRadio(e.target.value);

@@ -355,5 +362,5 @@ break;

let mappedValue;
switch (type) {
case "checkbox":
if (stateValue) {
switch(type) {
case 'checkbox':
if(stateValue) {
mappedValue = value;

@@ -364,6 +371,6 @@ } else {

break;
case "radio":
case 'radio':
mappedValue = value;
break;
case "select":
case 'select':
mappedValue = options.detect((o) => o.id === stateValue);

@@ -386,4 +393,4 @@ break;

let mappedValue = { persist: _.noop };
switch (type) {
case "checkbox":
switch(type) {
case 'checkbox':
mappedValue = { ...mappedValue, target: { checked: value } };

@@ -390,0 +397,0 @@ break;

@@ -1,2 +0,2 @@

export default class Resource extends React.Component {
export class Resource extends React.Component {
static propTypes = {

@@ -11,2 +11,3 @@ afterError: PropTypes.func,

onSubmit: PropTypes.func,
parent: PropTypes.object,
reflection: PropTypes.string,

@@ -59,4 +60,4 @@ subject: PropTypes.object.isRequired,

const { root } = context;
const { reflection, subject } = props;
const root = context.root;
const { parent, reflection, subject } = props;

@@ -66,3 +67,3 @@ let state = { resource: subject };

if (reflection) {
var reflectionInstance = root.klass().reflectOnAssociation(reflection);
var reflectionInstance = (root || parent).klass().reflectOnAssociation(reflection);
if (_.isUndefined(reflectionInstance)) throw "Reflection " + reflection + " not found.";

@@ -193,3 +194,3 @@ var inverseReflection = reflectionInstance.inverseOf();

getChildContext() {
const { afterUpdate } = this.props;
const { afterUpdate, parent } = this.props;
const { root } = this.context;

@@ -205,3 +206,3 @@ const { resource, queuedReflectionChanges, updating } = this.state;

shiftReflectionQueue: this.shiftReflectionQueue,
root: root || resource,
root: parent || root || resource,
resource,

@@ -208,0 +209,0 @@ updateRoot: this.updateRoot,

export { default as Collection } from "./Collection.jsx";
export { default as ErrorsFor } from "./ErrorsFor.jsx";
export { default as Field } from "./Field.jsx";
export { default as Resource } from "./Resource.jsx";