diff --git a/.npmignore b/.npmignore index 9b1c8b1..b97863d 100644 --- a/.npmignore +++ b/.npmignore @@ -1 +1,3 @@ -/dist +/src +/spec +/gulpfile.ls diff --git a/README.md b/README.md index 6a563a2..463bdfc 100644 --- a/README.md +++ b/README.md @@ -20,15 +20,15 @@ Right now the library includes a single React mixin, `BaconMixin`. `BaconMixin` provides a few different methods for your components: -### component.propsProperty(_[propName]_) +### component.streamProps(_[propName]_) Returns a memoized `Bacon.Property` backed by the component's props, skipping duplicate values. When a `propName` is present, the values of the property are those of the given prop. If no `propName` is given, the property's values are the whole props objects of the component. The properties returned are cleaned up with a `Bacon.End` when the component unmounts. -### component.stateProperty(_[stateName]_) +### component.streamState(_[stateName]_) -Like `propsProperty(propName)`, but for state values. +Like `streamProps(propName)`, but for state values. ### component.eventStream(functionName) diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000..cf674f8 --- /dev/null +++ b/dist/index.js @@ -0,0 +1,10 @@ +var mixin, resolver; +mixin = require('./mixin'); +resolver = require('./resolver'); +module.exports = { + BaconMixin: mixin, + BaconResolver: resolver, + Mixin: mixin, + Resolver: resolver +}; +//# sourceMappingURL=maps/index.js.map \ No newline at end of file diff --git a/dist/maps/index.js.map b/dist/maps/index.js.map new file mode 100644 index 0000000..756bcbe --- /dev/null +++ b/dist/maps/index.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["index.ls"],"names":[],"mappings":";AAAA,KAAS,CAAA,CAAA,CAAE,QAAQ,SAAA;AACnB,QAAS,CAAA,CAAA,CAAE,QAAQ,YAAA;AAEnB,MAAM,CAAC,OAAQ,CAAA,CAAA,CACb;EAAA,YAAgB;EAChB,eAAgB;EAChB,OAAgB;EAChB,UAAgB;AAHhB","file":"index.js","sourcesContent":["mixin = require './mixin'\nresolver = require './resolver'\n\nmodule.exports =\n BaconMixin : mixin\n BaconResolver : resolver\n Mixin : mixin\n Resolver : resolver\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/dist/maps/mixin.js.map b/dist/maps/mixin.js.map new file mode 100644 index 0000000..0fab509 --- /dev/null +++ b/dist/maps/mixin.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["mixin.ls"],"names":[],"mappings":"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","file":"mixin.js","sourcesContent":["Bacon = require \\baconjs\n\nensure-unsub = ->\n it._bacon ?= {}\n it._bacon.unsub ?= []\nensure-buses = ->\n it._bacon ?= {}\n it._bacon.buses ?= {}\nensure-props = ->\n ensure-buses it .props ?= new Bacon.Bus!\nensure-state = ->\n ensure-buses it .state ?= new Bacon.Bus!\n\nevent-obj = -> \"#{it.target.name}\": it.target.value\nevent-bus = (it, name, generator) ->\n bus = ensure-buses it .[\"event_#name\"] ?= new Bacon.Bus!\n if it[name] then throw \"Cannot re-implement the event-bus end-point\"\n it[name] = generator(bus)\n bus\n\nmodule.exports =\n # offer a bacon event stream for the component's properties.\n stream-props : (pn) -> if pn? then ensure-props @ else ensure-props @ .map -> it[pn]\n # offer a bacon event stream for the component's state.\n stream-state : (sn) -> if sn? then ensure-state @ else ensure-state @ .map -> it[sn]\n # register a callback hook and offer a stream on the other end of it.\n event-stream : (en) -> event-bus @, en, (bus) -> !-> bus.push it\n # similar to event-stream except we push it.target.value through the stream.\n value-stream : (en) -> event-bus @, en, (bus) -> !-> bus.push it.target.value\n # similar to event-stream except we push {it.target.name : it.target.value} through.\n input-stream : (en) -> event-bus @, en, (bus) -> !-> bus.push (it |> event-obj)\n # similar to event-stream except we bother to prevent event propagation.\n dom-event-stream : (en, prevent-default, stop-propagation) -> event-bus @, en, (bus) -> !->\n it.prevent-default! if !!prevent-default and it.prevent-default?\n it.stop-propagation! if !!stop-propagation and it.stop-propagation?\n bus.push it\n # links the unsub function to the component's lifecycle.\n # unsub will be run in component-will-unmount.\n subscribe-to : (unsub) -> ensure-unsub @ .push unsub; unsub\n # plugs a stream into the components state.\n # either under a specific key, or overriding the entire state object.\n plug : (stream, key) ->\n @subscribe-to stream.on-value do\n if key? then !~> @set-state \"#key\": it else !~> @set-state it\n # push values to the props and state streams if they exist.\n component-did-update : !->\n if @_bacon?buses?\n @_bacon.buses.props?push @props\n @_bacon.buses.state?push @state\n # cleanup whenever the component unmounts.\n component-will-unmount : !->\n if @_bacon?\n if @_bacon.buses?\n for b of @_bacon.buses\n @_bacon.buses[b].end!\n @_bacon.unsub?for-each !-> it!\n @_bacon = {}\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/dist/maps/resolver.js.map b/dist/maps/resolver.js.map new file mode 100644 index 0000000..a06b776 --- /dev/null +++ b/dist/maps/resolver.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["resolver.ls"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAQ,CAAA,CAAA,CAAE","file":"resolver.js","sourcesContent":["module.exports = {}\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/dist/mixin.js b/dist/mixin.js new file mode 100644 index 0000000..e36cfc9 --- /dev/null +++ b/dist/mixin.js @@ -0,0 +1,141 @@ +var Bacon, ensureUnsub, ensureBuses, ensureProps, ensureState, eventObj, eventBus; +Bacon = require('baconjs'); +ensureUnsub = function(it){ + var ref$, ref1$; + it._bacon == null && (it._bacon = {}); + return (ref1$ = (ref$ = it._bacon).unsub) != null + ? ref1$ + : ref$.unsub = []; +}; +ensureBuses = function(it){ + var ref$, ref1$; + it._bacon == null && (it._bacon = {}); + return (ref1$ = (ref$ = it._bacon).buses) != null + ? ref1$ + : ref$.buses = {}; +}; +ensureProps = function(it){ + var ref$, ref1$; + return (ref1$ = (ref$ = ensureBuses(it)).props) != null + ? ref1$ + : ref$.props = new Bacon.Bus(); +}; +ensureState = function(it){ + var ref$, ref1$; + return (ref1$ = (ref$ = ensureBuses(it)).state) != null + ? ref1$ + : ref$.state = new Bacon.Bus(); +}; +eventObj = function(it){ + var ref$; + return ref$ = {}, ref$[it.target.name + ""] = it.target.value, ref$; +}; +eventBus = function(it, name, generator){ + var bus, ref$, key$, ref1$; + bus = (ref1$ = (ref$ = ensureBuses(it))[key$ = "event_" + name]) != null + ? ref1$ + : ref$[key$] = new Bacon.Bus(); + if (it[name]) { + throw "Cannot re-implement the event-bus end-point"; + } + it[name] = generator(bus); + return bus; +}; +module.exports = { + streamProps: function(pn){ + if (pn != null) { + return ensureProps(this); + } else { + return ensureProps(this).map(function(it){ + return it[pn]; + }); + } + }, + streamState: function(sn){ + if (sn != null) { + return ensureState(this); + } else { + return ensureState(this).map(function(it){ + return it[sn]; + }); + } + }, + eventStream: function(en){ + return eventBus(this, en, function(bus){ + return function(it){ + bus.push(it); + }; + }); + }, + valueStream: function(en){ + return eventBus(this, en, function(bus){ + return function(it){ + bus.push(it.target.value); + }; + }); + }, + inputStream: function(en){ + return eventBus(this, en, function(bus){ + return function(it){ + bus.push(eventObj( + it)); + }; + }); + }, + domEventStream: function(en, preventDefault, stopPropagation){ + return eventBus(this, en, function(bus){ + return function(it){ + if (!!preventDefault && it.preventDefault != null) { + it.preventDefault(); + } + if (!!stopPropagation && it.stopPropagation != null) { + it.stopPropagation(); + } + bus.push(it); + }; + }); + }, + subscribeTo: function(unsub){ + ensureUnsub(this).push(unsub); + return unsub; + }, + plug: function(stream, key){ + var this$ = this; + return this.subscribeTo(stream.onValue(key != null + ? function(it){ + var ref$; + this$.setState((ref$ = {}, ref$[key + ""] = it, ref$)); + } + : function(it){ + this$.setState(it); + })); + }, + componentDidUpdate: function(){ + var ref$, ref1$, ref2$; + if (((ref$ = this._bacon) != null ? ref$.buses : void 8) != null) { + if ((ref1$ = this._bacon.buses.props) != null) { + ref1$.push(this.props); + } + if ((ref2$ = this._bacon.buses.state) != null) { + ref2$.push(this.state); + } + } + }, + componentWillUnmount: function(){ + var b, ref$; + if (this._bacon != null) { + if (this._bacon.buses != null) { + for (b in this._bacon.buses) { + this._bacon.buses[b].end(); + } + } + if ((ref$ = this._bacon.unsub) != null) { + ref$.forEach(function(it){ + it(); + }); + } + this._bacon = {}; + } + } +}; +//# sourceMappingURL=maps/mixin.js.map \ No newline at end of file diff --git a/dist/react-bacon.js b/dist/react-bacon.js deleted file mode 100644 index 60b38ce..0000000 --- a/dist/react-bacon.js +++ /dev/null @@ -1,106 +0,0 @@ -!function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.ReactBacon=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o + gulp.src './src/*.ls' + .pipe sourcemaps.init() + .pipe livescript bare: true .on('error', gutil.log) + .pipe sourcemaps.write('./maps') + .pipe gulp.dest('./dist') diff --git a/package.json b/package.json index e44e22e..450587f 100644 --- a/package.json +++ b/package.json @@ -1,31 +1,40 @@ { "name": "react-bacon", - "version": "0.0.4", - "description": "A little module for using React with Bacon.js", - "main": "src/react-bacon.js", + "version": "0.1.0", + "description": "Incorporate BaconJS into the ReactJS render cycle", + "main": "dist/index.js", + "author": "Rodolfo Hansen", + "homepage": "https://github.com/kryptt/react-bacon", + "license": "MIT", + "keywords": [ + "async", + "react", + "bacon", + "reactive", + "streams", + "isomorphic" + ], "repository": { "type": "git", - "url": "https://github.com/jamesmacaulay/react-bacon" + "url": "https://github.com/kryptt/react-bacon" }, - "author": "James MacAulay", - "license": "MIT", "bugs": { - "url": "https://github.com/jamesmacaulay/react-bacon/issues" + "url": "https://github.com/kryptt/react-bacon/issues" + }, + "scripts": { + "build": "gulp" }, - "homepage": "https://github.com/jamesmacaulay/react-bacon", "devDependencies": { - "react": "~0.10.0", - "grunt": "~0.4.4", - "grunt-contrib-jasmine": "~0.6.3", - "browserify": "~3.44.2", - "grunt-browserify": "~2.0.8", - "reactify": "~0.13.1", - "browserify-shim": "~3.4.1" + "gulp": "^3.9.0", + "gulp-livescript": "^2.4.0", + "gulp-sourcemaps": "^1.5.2", + "gulp-util": "^3.0.6", + "livescript": "^1.4.0" }, "dependencies": { - "baconjs": "~0.7.10" + "baconjs": "^0.7.70" }, - "browserify-shim": { - "baconjs": "global:Bacon" + "peerDependencies": { + "react": "~0.13" } } diff --git a/src/index.ls b/src/index.ls new file mode 100644 index 0000000..9d463e2 --- /dev/null +++ b/src/index.ls @@ -0,0 +1,8 @@ +mixin = require './mixin' +resolver = require './resolver' + +module.exports = + BaconMixin : mixin + BaconResolver : resolver + Mixin : mixin + Resolver : resolver diff --git a/src/mixin.ls b/src/mixin.ls new file mode 100644 index 0000000..053a343 --- /dev/null +++ b/src/mixin.ls @@ -0,0 +1,57 @@ +Bacon = require \baconjs + +ensure-unsub = -> + it._bacon ?= {} + it._bacon.unsub ?= [] +ensure-buses = -> + it._bacon ?= {} + it._bacon.buses ?= {} +ensure-props = -> + ensure-buses it .props ?= new Bacon.Bus! +ensure-state = -> + ensure-buses it .state ?= new Bacon.Bus! + +event-obj = -> "#{it.target.name}": it.target.value +event-bus = (it, name, generator) -> + bus = ensure-buses it .["event_#name"] ?= new Bacon.Bus! + if it[name] then throw "Cannot re-implement the event-bus end-point" + it[name] = generator(bus) + bus + +module.exports = + # offer a bacon event stream for the component's properties. + stream-props : (pn) -> unless pn? then ensure-props @ else ensure-props @ .map -> it[pn] + # offer a bacon event stream for the component's state. + stream-state : (sn) -> unless sn? then ensure-state @ else ensure-state @ .map -> it[sn] + # register a callback hook and offer a stream on the other end of it. + event-stream : (en) -> event-bus @, en, (bus) -> !-> bus.push it + # similar to event-stream except we push it.target.value through the stream. + value-stream : (en) -> event-bus @, en, (bus) -> !-> bus.push it.target.value + # similar to event-stream except we push {it.target.name : it.target.value} through. + input-stream : (en) -> event-bus @, en, (bus) -> !-> bus.push (it |> event-obj) + # similar to event-stream except we bother to prevent event propagation. + dom-event-stream : (en, prevent-default, stop-propagation) -> event-bus @, en, (bus) -> !-> + it.prevent-default! if !!prevent-default and it.prevent-default? + it.stop-propagation! if !!stop-propagation and it.stop-propagation? + bus.push it + # links the unsub function to the component's lifecycle. + # unsub will be run in component-will-unmount. + subscribe-to : (unsub) -> ensure-unsub @ .push unsub; unsub + # plugs a stream into the components state. + # either under a specific key, or overriding the entire state object. + plug : (stream, key) -> + @subscribe-to stream.on-value do + if key? then !~> @set-state "#key": it else !~> @set-state it + # push values to the props and state streams if they exist. + component-did-update : !-> + if @_bacon?buses? + @_bacon.buses.props?push @props + @_bacon.buses.state?push @state + # cleanup whenever the component unmounts. + component-will-unmount : !-> + if @_bacon? + if @_bacon.buses? + for b of @_bacon.buses + @_bacon.buses[b].end! + @_bacon.unsub?for-each !-> it! + @_bacon = {} diff --git a/src/react-bacon.js b/src/react-bacon.js deleted file mode 100644 index ce49c13..0000000 --- a/src/react-bacon.js +++ /dev/null @@ -1,101 +0,0 @@ -var Bacon = require('baconjs'); - -module.exports.BaconMixin = ((function(){ - 'use strict'; - - function propsOrStateProperty(component, allPropsOrStateKey, groupKey, filterKey) { - var bacon = component._bacon = component._bacon || {}; - var allPropertyKey = 'properties.'+allPropsOrStateKey; - var groupedPropertiesKey = 'properties.'+groupKey; - var property = bacon[allPropertyKey]; - if (!property) { - var bus = bacon['buses.'+allPropsOrStateKey] = new Bacon.Bus(); - property = bacon[allPropertyKey] = bus.toProperty(component[groupKey]).skipDuplicates(); - } - if (filterKey != null) { - var wholePropsOrStateProperty = property; - var filteredPropertyKey = groupedPropertiesKey+'.'+filterKey; - property = bacon[filteredPropertyKey]; - if (!property) { - property = bacon[filteredPropertyKey] = wholePropsOrStateProperty. - filter(function(x){return x;}). - map(function(propsOrState){ - return propsOrState[filterKey]; - }). - skipDuplicates(). - toProperty(); - } - } - return property; - } - return ({ - propsProperty: function(propName) { - return propsOrStateProperty(this, 'allProps', 'props', propName); - }, - stateProperty: function(stateName) { - return propsOrStateProperty(this, 'allState', 'state', stateName); - }, - eventStream: function(eventName) { - var bacon = this._bacon = this._bacon || {}; - var buses = bacon['buses.events'] = bacon['buses.events'] || {}; - var bus = buses[eventName]; - if (!bus) { - bus = buses[eventName] = new Bacon.Bus(); - this[eventName] = function sendEventToStream(event) { - bus.push(event); - }; - } - return bus; - }, - plug: function(stream, stateKey) { - var unsubscribe; - var component = this; - var bacon = this._bacon = this._bacon || {}; - var unsubscribers = bacon.unsubscribers = bacon.unsubscribers || []; - - if (stateKey == null) { - unsubscribe = stream.onValue(function(partialState) { - component.setState(partialState); - }); - } else { - unsubscribe = stream.onValue(function(value) { - var partialState = {}; - partialState[stateKey] = value; - component.setState(partialState); - }); - } - unsubscribers.push(unsubscribe); - return unsubscribe; - }, - componentDidUpdate: function() { - var bacon = this._bacon; - if (bacon) { - var allPropsBus = bacon['buses.allProps']; - allPropsBus && allPropsBus.push(this.props); - var allStateBus = bacon['buses.allState']; - allStateBus && allStateBus.push(this.state); - } - }, - componentWillUnmount: function() { - var bacon = this._bacon; - if (bacon) { - var allPropsBus = bacon['buses.allProps']; - allPropsBus && allPropsBus.end(); - var allStateBus = bacon['buses.allState']; - allStateBus && allStateBus.end(); - - var eventBuses = bacon['buses.events']; - if (eventBuses) { - for (var eventName in eventBuses) { - eventBuses[eventName].end(); - } - } - - var unsubscribers = bacon.unsubscribers; - if (unsubscribers) { - unsubscribers.forEach(function(f) {f()}); - } - } - } - }); -})()); diff --git a/src/resolver.ls b/src/resolver.ls new file mode 100644 index 0000000..4ba52ba --- /dev/null +++ b/src/resolver.ls @@ -0,0 +1 @@ +module.exports = {}