diff --git a/component.js b/component.js
index 3014664..0ba5072 100644
--- a/component.js
+++ b/component.js
@@ -1,7 +1,6 @@
"use strict";
-var React = require('react'),
- assign = require('lodash.assign');
+var assign = require('lodash.assign');
var shouldComponentUpdate = require('./shouldupdate');
var cached = require('./cached');
@@ -30,250 +29,285 @@ var cached = require('./cached');
* @returns {Component}
* @api public
*/
-module.exports = factory();
-
-/**
- * Create a “local” instance of the Omniscient component creator by using the `.withDefaults` method.
- * This also allows you to override any defaults that Omniscient use to check equality of objects,
- * unwrap cursors, etc.
- *
- * ### Options
- * ```js
- * {
- * // Goes directly to component
- * shouldComponentUpdate: function (nextProps, nextState), // check update
- * jsx: false, // whether or not to default to jsx components
- * cursorField: '__singleCursor', // cursor property name to "unwrap" before passing in to render
- * isNode: function (propValue), // determines if propValue is a valid React node
- *
- * // Passed on to `shouldComponentUpdate`
- * isCursor: function (cursor), // check if prop is cursor
- * unCursor: function (cursor), // convert cursor to object
- * isEqualCursor: function (oneCursor, otherCursor), // compares cursor
- * isEqualState: function (currentState, nextState), // compares state
- * isIgnorable: function (propertyValue, propertyKey), // check if property item is ignorable
- * isEqualProps: function (currentProps, nextProps), // compares props
- * isImmutable: function (maybeImmutable) // check if object is immutable
- * }
- * ```
- *
- * ### Examples
- * #### Always use JSX
- * ```js
- * var component = require('omniscient');
- * var jsxComponent = component.withDefaults({
- * jsx: true
- * });
- *
- * var Greeting = jsxComponent(function () {
- * return
Hello!
- * });
- * React.render(, document.body);
- * ```
- *
- * #### Un-wrapping curors
- * ```jsx
- * var localComponent = component.withDefaults({
- * cursorField: 'foobar'
- * });
- *
- * var Component = localComponent(function (myCursor) {
- * // Now you have myCursor directly instead of having to do props.foobar
- * });
- *
- * React.render(, document.body);
- * ```
- *
- * @param {Object} Options Options with defaults to override
- *
- * @property {Function} shouldComponentUpdate Get default shouldComponentUpdate
-
- * @module omniscient.withDefaults
- * @returns {Component}
- * @api public
- */
-module.exports.withDefaults = factory;
-
-function factory (options) {
- var debug;
- options = options || {};
- var _shouldComponentUpdate = options.shouldComponentUpdate ||
- shouldComponentUpdate.withDefaults(options);
- var _isCursor = options.isCursor || shouldComponentUpdate.isCursor;
- var _isImmutable = options.isImmutable || shouldComponentUpdate.isImmutable;
- var _isJsx = !!options.jsx;
- var _hiddenCursorField = options.cursorField || '__singleCursor';
- var _isNode = options.isNode || isNode;
- var _cached = cached.withDefaults(_shouldComponentUpdate);
+module.exports = function (React) {
+ var instance = factory();
/**
- * Activate debugging for components. Will log when a component renders,
- * the outcome of `shouldComponentUpdate`, and why the component re-renders.
+ * Create a “local” instance of the Omniscient component creator by using the `.withDefaults` method.
+ * This also allows you to override any defaults that Omniscient use to check equality of objects,
+ * unwrap cursors, etc.
*
- * ### Example
+ * ### Options
* ```js
- * Search>: shouldComponentUpdate => true (cursors have changed)
- * Search>: render
- * SearchBox>: shouldComponentUpdate => true (cursors have changed)
- * SearchBox>: render
+ * {
+ * // Goes directly to component
+ * shouldComponentUpdate: function(nextProps, nextState), // check update
+ * jsx: false, // whether or not to default to jsx components
+ * cursorField: '__singleCursor', // cursor property name to "unwrap" before passing in to render
+ * isNode: function(propValue), // determines if propValue is a valid React node
+ *
+ * // Passed on to `shouldComponentUpdate`
+ * isCursor: function(cursor), // check if prop is cursor
+ * unCursor: function (cursor), // convert cursor to object
+ * isEqualCursor: function (oneCursor, otherCursor), // compares cursor
+ * isEqualState: function (currentState, nextState), // compares state
+ * isEqualProps: function (currentProps, nextProps), // compares props
+ * isImmutable: function (maybeImmutable) // check if object is immutable
+ * }
* ```
*
- * @example omniscient.debug(/Search/i);
+ * ### Examples
+ * #### Always use JSX
+ * ```js
+ * var component = require('omniscient');
+ * var jsxComponent = component.withDefaults({
+ * jsx: true
+ * });
+ *
+ * var Greeting = jsxComponent(function () {
+ * return Hello!
+ * });
+ * React.render(, document.body);
+ * ```
*
- * @param {RegExp} pattern Filter pattern. Only show messages matching pattern
+ * #### Un-wrapping curors
+ * ```jsx
+ * var localComponent = component.withDefaults({
+ * cursorField: 'foobar'
+ * });
*
- * @property {Object} jsx Get component for use in JSX
+ * var Component = localComponent(function (myCursor) {
+ * // Now you have myCursor directly instead of having to do props.foobar
+ * });
*
- * @module omniscient.debug
- * @returns {Immstruct}
+ * React.render(, document.body);
+ * ```
+ *
+ * @param {Object} Options Options with defaults to override
+ *
+ * @property {Function} shouldComponentUpdate Get default shouldComponentUpdate
+ *
+ * @module omniscient.withDefaults
+ * @returns {Component}
* @api public
*/
- ComponentCreator.debug = debugFn;
- ComponentCreator.cached = _cached;
- ComponentCreator.shouldComponentUpdate = _shouldComponentUpdate;
- return ComponentCreator;
-
- function ComponentCreator (displayName, mixins, render) {
- var options = createDefaultArguments(displayName, mixins, render);
- var methodStatics = pickStaticMixins(options.mixins);
-
- var componentObject = {
- displayName: options.displayName || options.render.name,
- mixins: options.mixins,
- render: function render () {
- if (debug) debug.call(this, 'render');
- // If `props['__singleCursor']` is set a single cursor was passed
- // to the component, pick it out and pass it.
- var input = this.props[_hiddenCursorField] || this.props;
- this.cursor = this.props[_hiddenCursorField];
- return options.render.call(this, input, this.props.statics);
- }
- };
-
- if (methodStatics) {
- componentObject.statics = methodStatics;
- removeOldStaticMethods(options.mixins);
- }
-
- var Component = React.createClass(componentObject);
- if (_isJsx) {
- return Component;
- }
+ instance.withDefaults = factory;
+
+ return instance;
+
+ function factory (options) {
+ var debug;
+ options = options || {};
+ var _shouldComponentUpdate = options.shouldComponentUpdate ||
+ shouldComponentUpdate.withDefaults(options);
+ var _isCursor = options.isCursor || shouldComponentUpdate.isCursor;
+ var _isImmutable = options.isImmutable || shouldComponentUpdate.isImmutable;
+ var _isJsx = !!options.jsx;
+ var _hiddenCursorField = options.cursorField || '__singleCursor';
+ var _isNode = options.isNode || isNode;
+ var _cached = cached.withDefaults(_shouldComponentUpdate);
/**
- * Invoke component (rendering it)
+ * Activate debugging for components. Will log when a component renders,
+ * the outcome of `shouldComponentUpdate`, and why the component re-renders.
+ *
+ * ### Example
+ * ```js
+ * Search>: shouldComponentUpdate => true (cursors have changed)
+ * Search>: render
+ * SearchBox>: shouldComponentUpdate => true (cursors have changed)
+ * SearchBox>: render
+ * ```
*
- * @param {String} displayName Component display name. Used in debug and by React
- * @param {Object} props Properties that **do** trigger update when changed. Can be cursors, object and immutable structures
- * @param {Object} statics Properties that do not trigger update when changed. Can be cursors, object and immutable structuress
- * @param {Object} ..rest Child components (React elements, scalar values)
+ * @example omniscient.debug(/Search/i);
+ *
+ * @param {RegExp} pattern Filter pattern. Only show messages matching pattern
*
* @property {Object} jsx Get component for use in JSX
-
- * @module Component
- * @returns {ReactElement}
+ *
+ * @module omniscient.debug
+ * @returns {Immstruct}
* @api public
*/
- var create = function (key, props, statics) {
- var _props;
- var inputCursor;
- var children;
-
- if (typeof key === 'object') {
- statics = props;
- props = key;
- key = void 0;
- }
+ ComponentCreator.debug = debugFn;
+ ComponentCreator.cached = _cached;
+ ComponentCreator.shouldComponentUpdate = _shouldComponentUpdate;
+ return ComponentCreator;
+
+ function ComponentCreator (displayName, mixins, render) {
+ var options = createDefaultArguments(displayName, mixins, render);
+ var methodStatics = pickStaticMixins(options.mixins);
+
+ var componentObject = {
+ displayName: options.displayName || options.render.name,
+ mixins: options.mixins,
+ render: function render () {
+ if (debug) debug.call(this, 'render');
+ // If `props['__singleCursor']` is set a single cursor was passed
+ // to the component, pick it out and pass it.
+ var input = this.props[_hiddenCursorField] || this.props;
+ this.cursor = this.props[_hiddenCursorField];
+ return options.render.call(this, input, this.props.statics);
+ }
+ };
- children = flatten(sliceFrom(arguments, statics).filter(_isNode));
-
- // If passed props is a signle cursor we move it to `props[_hiddenCursorField]`
- // to simplify should component update. The render function will move it back.
- // The name '__singleCursor' is used to not clash with names of user passed properties
- if (_isCursor(props) || _isImmutable(props)) {
- inputCursor = props;
- _props = {};
- _props[_hiddenCursorField] = inputCursor;
- } else {
- _props = assign({}, props);
+ if (methodStatics) {
+ componentObject.statics = methodStatics;
+ removeOldStaticMethods(options.mixins);
}
- // If statics is a node (due to it being optional)
- // don't attach the node to the statics prop
- if (!!statics && !props.statics && !_isNode(statics)) {
- _props.statics = statics;
+ var Component = React.createClass(componentObject);
+ if (_isJsx) {
+ return Component;
}
- if (key) {
- _props.key = key;
- }
+ /**
+ * Invoke component (rendering it)
+ *
+ * @param {String} displayName Component display name. Used in debug and by React
+ * @param {Object} props Properties that **do** trigger update when changed. Can be cursors, object and immutable structures
+ * @param {Object} statics Properties that do not trigger update when changed. Can be cursors, object and immutable structuress
+ * @param {Object} ..rest Child components (React elements, scalar values)
+ *
+ * @property {Object} jsx Get component for use in JSX
+
+ * @module Component
+ * @returns {ReactElement}
+ * @api public
+ */
+ var create = function (key, props, statics) {
+ var _props;
+ var inputCursor;
+ var children;
+
+ if (typeof key === 'object') {
+ statics = props;
+ props = key;
+ key = void 0;
+ }
- if (!!children.length) {
- _props.children = children;
- }
+ children = flatten(sliceFrom(arguments, statics).filter(_isNode));
- return React.createElement(Component, _props);
- };
+ // If passed props is a signle cursor we move it to `props[_hiddenCursorField]`
+ // to simplify should component update. The render function will move it back.
+ // The name '__singleCursor' is used to not clash with names of user passed properties
+ if (_isCursor(props) || _isImmutable(props)) {
+ inputCursor = props;
+ _props = {};
+ _props[_hiddenCursorField] = inputCursor;
+ } else {
+ _props = assign({}, props);
+ }
- create.jsx = Component;
+ // If statics is a node (due to it being optional)
+ // don't attach the node to the statics prop
+ if (!!statics && !props.statics && !_isNode(statics)) {
+ _props.statics = statics;
+ }
- if (methodStatics) {
- create = assign(create, methodStatics);
- }
+ if (key) {
+ _props.key = key;
+ }
- return create;
- }
+ if (!!children.length) {
+ _props.children = children;
+ }
- function debugFn (pattern, logFn) {
- if (_shouldComponentUpdate.debug) {
- debug = _shouldComponentUpdate.debug(pattern, logFn);
- }
- }
+ return React.createElement(Component, _props);
+ };
- function createDefaultArguments (displayName, mixins, render) {
+ create.jsx = Component;
- // (render)
- if (typeof displayName === 'function') {
- render = displayName;
- mixins = [];
- displayName = void 0;
- }
+ if (methodStatics) {
+ create = assign(create, methodStatics);
+ }
- // (mixins, render)
- if (typeof displayName === 'object' && typeof mixins === 'function') {
- render = mixins;
- mixins = displayName;
- displayName = void 0;
+ return create;
}
- // (displayName, render)
- if (typeof displayName === 'string' && typeof mixins === 'function') {
- render = mixins;
- mixins = [];
+ function debugFn (pattern, logFn) {
+ if (_shouldComponentUpdate.debug) {
+ debug = _shouldComponentUpdate.debug(pattern, logFn);
+ }
}
- // Else (displayName, mixins, render)
+ function createDefaultArguments (displayName, mixins, render) {
- if (!Array.isArray(mixins)) {
- mixins = [mixins];
- }
+ // (render)
+ if (typeof displayName === 'function') {
+ render = displayName;
+ mixins = [];
+ displayName = void 0;
+ }
- // Add built-in lifetime methods to keep `statics` up to date.
- mixins.unshift(componentWillMount.asMixin,
- componentWillReceiveProps.asMixin);
+ // (mixins, render)
+ if (typeof displayName === 'object' && typeof mixins === 'function') {
+ render = mixins;
+ mixins = displayName;
+ displayName = void 0;
+ }
- if (!hasShouldComponentUpdate(mixins)) {
- mixins.unshift({
- shouldComponentUpdate: _shouldComponentUpdate
- });
+ // (displayName, render)
+ if (typeof displayName === 'string' && typeof mixins === 'function') {
+ render = mixins;
+ mixins = [];
+ }
+
+ // Else (displayName, mixins, render)
+
+ if (!Array.isArray(mixins)) {
+ mixins = [mixins];
+ }
+
+ // Add built-in lifetime methods to keep `statics` up to date.
+ mixins.unshift(componentWillMount.asMixin,
+ componentWillReceiveProps.asMixin);
+
+ if (!hasShouldComponentUpdate(mixins)) {
+ mixins.unshift({
+ shouldComponentUpdate: _shouldComponentUpdate
+ });
+ }
+
+ return {
+ displayName: displayName,
+ mixins: mixins,
+ render: render
+ };
}
+ }
- return {
- displayName: displayName,
- mixins: mixins,
- render: render
- };
+ /**
+ * Predicate showing whether or not the argument is a valid React Node
+ * or not. Can be numbers, strings, bools, and React Elements.
+ *
+ * React's isNode check from ReactPropTypes validator
+ * but adjusted to not accept objects to avoid collision with props & statics.
+ *
+ * @param {String} propValue Property value to check if is valid React Node
+ *
+ * @returns {Boolean}
+ * @api private
+ */
+ function isNode (propValue) {
+ switch (typeof propValue) {
+ case 'number':
+ case 'string':
+ return true;
+ case 'boolean':
+ return !propValue;
+ case 'object':
+ if (Array.isArray(propValue)) {
+ return propValue.every(isNode);
+ }
+ if (React.isValidElement(propValue)) {
+ return true;
+ }
+ return false;
+ default:
+ return false;
+ }
}
}
@@ -326,38 +360,6 @@ function flatten (array) {
return Array.prototype.concat.apply([], array);
}
-/**
- * Predicate showing whether or not the argument is a valid React Node
- * or not. Can be numbers, strings, bools, and React Elements.
- *
- * React's isNode check from ReactPropTypes validator
- * but adjusted to not accept objects to avoid collision with props & statics.
- *
- * @param {String} propValue Property value to check if is valid React Node
- *
- * @returns {Boolean}
- * @api private
- */
-function isNode (propValue) {
- switch (typeof propValue) {
- case 'number':
- case 'string':
- return true;
- case 'boolean':
- return !propValue;
- case 'object':
- if (Array.isArray(propValue)) {
- return propValue.every(isNode);
- }
- if (React.isValidElement(propValue)) {
- return true;
- }
- return false;
- default:
- return false;
- }
-}
-
function delegate(delegee) {
var delegateFunction = function() {
return delegateFunction.delegee.apply(this, arguments);
@@ -397,8 +399,8 @@ function componentWillReceiveProps (newProps) {
var currentStatics = currentProps.statics;
var newStatics = newProps.statics;
var haveChangedStatics = newStatics !== currentStatics &&
- newStatics &&
- typeof newStatics === 'object';
+ newStatics &&
+ typeof newStatics === 'object';
if (haveChangedStatics) {
Object.keys(newStatics).forEach(function (key) {
diff --git a/dist/test.html b/dist/test.html
new file mode 100644
index 0000000..7ef16e5
--- /dev/null
+++ b/dist/test.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..27a1179
--- /dev/null
+++ b/index.js
@@ -0,0 +1,2 @@
+var React = require('react');
+module.exports = require('./component')(React);
diff --git a/makeBundle.js b/makeBundle.js
index 7405583..f98a5e7 100644
--- a/makeBundle.js
+++ b/makeBundle.js
@@ -7,7 +7,7 @@ var fs = require('fs');
var UglifyJS = require('uglify-js');
var pack = require('./package.json');
-var inputFile = './component.js';
+var inputFile = './index.js';
var outputFile = './dist/omniscient.js';
var outputMinifiedFile = './dist/omniscient.min.js';
diff --git a/native.js b/native.js
new file mode 100644
index 0000000..db0b12b
--- /dev/null
+++ b/native.js
@@ -0,0 +1,2 @@
+var ReactNative = require('react-native');
+module.exports = require('./component')(ReactNative);
\ No newline at end of file
diff --git a/package.json b/package.json
index 762da49..0524eb5 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "omniscient",
"version": "3.2.0",
"description": "A library providing an abstraction for React components for passing the same data structure through the entire component flow using cursors and immutable data structures.",
- "main": "component.js",
+ "main": "index.js",
"directories": {
"example": "example"
},
@@ -28,6 +28,9 @@
"dox": "^0.6.1",
"doxme": "git://github.com/mikaelbr/doxme#dev"
},
+ "optionalDependencies": {
+ "react-native": "^0.8.0"
+ },
"scripts": {
"test": "mocha -R spec tests/**-test.js",
"test-watch": "mocha -G -w -R min tests/**-test.js",