Comparing version 0.11.0 to 0.12.0-rc1
@@ -13,2 +13,6 @@ 'use strict'; | ||
var _lodash = require('lodash.pick'); | ||
var _lodash2 = _interopRequireDefault(_lodash); | ||
var _webcomponent = require('webcomponent'); | ||
@@ -69,3 +73,3 @@ | ||
return _possibleConstructorReturn(this, (Component.__proto__ || Object.getPrototypeOf(Component)).apply(this, arguments)); | ||
return _possibleConstructorReturn(this, Object.getPrototypeOf(Component).apply(this, arguments)); | ||
} | ||
@@ -88,3 +92,3 @@ | ||
value: function child(tagName) { | ||
var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
var config = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
@@ -133,2 +137,15 @@ config.props = Object.assign({}, config.props, { $panelParentID: this.panelID }); | ||
/** | ||
* Returns whether this.state is shared with other components (the default). | ||
* @returns true if this.state is shared, false if this.appState is the shared store | ||
* @example | ||
* myWidget.isStateShared() | ||
*/ | ||
}, { | ||
key: 'isStateShared', | ||
value: function isStateShared() { | ||
return !this.appState; // if appState is not specified, all state is shared | ||
} | ||
/** | ||
* Executes the route handler matching the given URL fragment, and updates | ||
@@ -199,18 +216,24 @@ * the URL, as though the user had navigated explicitly to that address. | ||
value: function update() { | ||
var stateUpdate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
var stateUpdate = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; | ||
if (!this.initialized) { | ||
Object.assign(this.state, stateUpdate); | ||
} else if (this.isPanelRoot) { | ||
var updateHash = '$fragment' in stateUpdate && stateUpdate.$fragment !== this.state.$fragment; | ||
return this._updateStore(stateUpdate, { store: 'state', cascade: this.isStateShared() }); | ||
} | ||
Object.assign(this.state, stateUpdate); | ||
this.updateSelfAndChildren(this.state); | ||
/** | ||
* Applies a state update specifically to app state shared across components. | ||
* In apps which don't specify `appState` in the root component config, all | ||
* state is shared across all parent and child components and the standard | ||
* update() method should be used instead. | ||
* @param {object} [stateUpdate={}] - keys and values of entries to update in | ||
* the app's appState object | ||
* @example | ||
* myWidget.updateApp({name: 'Bob'}); | ||
*/ | ||
if (updateHash) { | ||
this.router.replaceHash(this.state.$fragment); | ||
} | ||
} else { | ||
this.$panelRoot.update(stateUpdate); | ||
} | ||
}, { | ||
key: 'updateApp', | ||
value: function updateApp() { | ||
var stateUpdate = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; | ||
return this._updateStore(stateUpdate, { store: 'appState', cascade: true }); | ||
} | ||
@@ -269,3 +292,6 @@ }, { | ||
this.$panelParent.$panelChildren.add(this); | ||
this.state = this.$panelRoot.state; | ||
// share either appState or all of state | ||
this.appState = this.$panelRoot.appState; | ||
this.state = this.isStateShared() ? this.$panelRoot.state : {}; | ||
} else { | ||
@@ -275,2 +301,3 @@ this.isPanelRoot = true; | ||
this.$panelParent = null; | ||
this.appState = this.getConfig('appState'); | ||
} | ||
@@ -339,33 +366,2 @@ this.app = this.$panelRoot; | ||
}, { | ||
key: 'updateSelfAndChildren', | ||
value: function updateSelfAndChildren(state) { | ||
if (this.initialized && this.shouldUpdate(state)) { | ||
this.domPatcher.update(state); | ||
var _iteratorNormalCompletion = true; | ||
var _didIteratorError = false; | ||
var _iteratorError = undefined; | ||
try { | ||
for (var _iterator = this.$panelChildren[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { | ||
var child = _step.value; | ||
child.updateSelfAndChildren(state); | ||
} | ||
} catch (err) { | ||
_didIteratorError = true; | ||
_iteratorError = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion && _iterator.return) { | ||
_iterator.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError) { | ||
throw _iteratorError; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}, { | ||
key: '_render', | ||
@@ -376,2 +372,3 @@ value: function _render(state) { | ||
this._rendered = this.getConfig('template')(Object.assign({}, state, { | ||
$app: this.appState, | ||
$component: this, | ||
@@ -403,3 +400,80 @@ $helpers: this.helpers | ||
} | ||
// update helpers | ||
// Update a given state store (this.state or this.appState), with option | ||
// to 'cascade' the update across other linked components | ||
}, { | ||
key: '_updateStore', | ||
value: function _updateStore(stateUpdate) { | ||
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
var cascade = options.cascade; | ||
var store = options.store; | ||
if (!this.initialized) { | ||
// just update store without patching DOM etc | ||
Object.assign(this[store], stateUpdate); | ||
} else { | ||
// update DOM, router, descendants etc. | ||
var updateHash = '$fragment' in stateUpdate && stateUpdate.$fragment !== this[store].$fragment; | ||
this.updateSelfAndChildren(stateUpdate, { cascade: cascade, store: store }); | ||
if (cascade && !this.isPanelRoot) { | ||
this.$panelRoot.updateSelfAndChildren(stateUpdate, { exclude: this, cascade: cascade, store: store }); | ||
} | ||
if (updateHash) { | ||
this.router.replaceHash(this[store].$fragment); | ||
} | ||
} | ||
} | ||
// Apply the given update down the component hierarchy from this node, | ||
// optionally excluding one node's subtree. This is useful for applying | ||
// a full state update to one component while sending only "shared" state | ||
// updates to the app root. | ||
}, { | ||
key: 'updateSelfAndChildren', | ||
value: function updateSelfAndChildren(stateUpdate) { | ||
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
var store = options.store; | ||
var cascade = options.cascade; | ||
if (this.initialized && this.shouldUpdate(stateUpdate)) { | ||
Object.assign(this[store], stateUpdate); | ||
this.domPatcher.update(this.state); | ||
if (cascade) { | ||
var _iteratorNormalCompletion = true; | ||
var _didIteratorError = false; | ||
var _iteratorError = undefined; | ||
try { | ||
for (var _iterator = this.$panelChildren[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { | ||
var child = _step.value; | ||
if (options.exclude !== child) { | ||
child.updateSelfAndChildren(stateUpdate, options); | ||
} | ||
} | ||
} catch (err) { | ||
_didIteratorError = true; | ||
_iteratorError = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion && _iterator.return) { | ||
_iterator.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError) { | ||
throw _iteratorError; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}, { | ||
key: 'config', | ||
@@ -414,2 +488,5 @@ | ||
* @property {object} [routes={}] - object mapping string route expressions to handler functions | ||
* @property {object} [appState={}] - (app root component only) state object to share with nested descendant components; | ||
* if not set, root component shares entire state object with all descendants | ||
* @property {object} [defaultState={}] - default entries for component state | ||
* @property {boolean} [updateSync=false] - whether to apply updates to DOM | ||
@@ -416,0 +493,0 @@ * immediately, instead of batching to one update per frame |
@@ -31,3 +31,3 @@ 'use strict'; | ||
return _possibleConstructorReturn(this, (ControlledComponent.__proto__ || Object.getPrototypeOf(ControlledComponent)).apply(this, arguments)); | ||
return _possibleConstructorReturn(this, Object.getPrototypeOf(ControlledComponent).apply(this, arguments)); | ||
} | ||
@@ -40,3 +40,3 @@ | ||
_get(ControlledComponent.prototype.__proto__ || Object.getPrototypeOf(ControlledComponent.prototype), 'createdCallback', this).apply(this, arguments); | ||
_get(Object.getPrototypeOf(ControlledComponent.prototype), 'createdCallback', this).apply(this, arguments); | ||
this.controller = this.getConfig('controller'); | ||
@@ -59,3 +59,3 @@ if (!this.controller) { | ||
value: function detachedCallback() { | ||
_get(ControlledComponent.prototype.__proto__ || Object.getPrototypeOf(ControlledComponent.prototype), 'detachedCallback', this).call(this); | ||
_get(Object.getPrototypeOf(ControlledComponent.prototype), 'detachedCallback', this).call(this); | ||
this.controller.unsubscribeUpdates(this._updateListener); | ||
@@ -62,0 +62,0 @@ } |
@@ -57,3 +57,3 @@ 'use strict'; | ||
function DOMPatcher(initialState, renderFunc) { | ||
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; | ||
var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; | ||
@@ -60,0 +60,0 @@ _classCallCheck(this, DOMPatcher); |
@@ -66,3 +66,3 @@ 'use strict'; | ||
var _this = _possibleConstructorReturn(this, (HTMLElement.__proto__ || Object.getPrototypeOf(HTMLElement)).apply(this, arguments)); | ||
var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(HTMLElement).apply(this, arguments)); | ||
@@ -77,3 +77,3 @@ _this.createdCallback && _this.createdCallback(); | ||
var oldValue = this.getAttribute(name); | ||
_get(HTMLElement.prototype.__proto__ || Object.getPrototypeOf(HTMLElement.prototype), 'setAttribute', this).apply(this, arguments); | ||
_get(Object.getPrototypeOf(HTMLElement.prototype), 'setAttribute', this).apply(this, arguments); | ||
this.attributeChangedCallback && this.attributeChangedCallback(name, oldValue, value); | ||
@@ -80,0 +80,0 @@ } |
@@ -7,3 +7,3 @@ 'use strict'; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; | ||
@@ -17,2 +17,3 @@ 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; }; }(); | ||
// just the necessary bits of Backbone router+history | ||
var Router = function () { | ||
@@ -22,3 +23,3 @@ function Router(app) { | ||
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
@@ -77,3 +78,3 @@ _classCallCheck(this, Router); | ||
var stateUpdate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
var stateUpdate = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
@@ -80,0 +81,0 @@ fragment = stripHash(fragment); |
@@ -24,9 +24,12 @@ 'use strict'; | ||
*/ | ||
var StateController = function () { | ||
// Create's a default store if one isn't given | ||
function StateController() { | ||
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, | ||
_ref$store = _ref.store, | ||
store = _ref$store === undefined ? null : _ref$store; | ||
var _ref = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; | ||
var _ref$store = _ref.store; | ||
var store = _ref$store === undefined ? null : _ref$store; | ||
_classCallCheck(this, StateController); | ||
@@ -33,0 +36,0 @@ |
@@ -14,2 +14,3 @@ "use strict"; | ||
*/ | ||
var StateStore = function () { | ||
@@ -16,0 +17,0 @@ function StateStore() { |
import cuid from 'cuid'; | ||
import pick from 'lodash.pick'; | ||
import WebComponent from 'webcomponent'; | ||
@@ -45,2 +46,5 @@ | ||
* @property {object} [routes={}] - object mapping string route expressions to handler functions | ||
* @property {object} [appState={}] - (app root component only) state object to share with nested descendant components; | ||
* if not set, root component shares entire state object with all descendants | ||
* @property {object} [defaultState={}] - default entries for component state | ||
* @property {boolean} [updateSync=false] - whether to apply updates to DOM | ||
@@ -126,2 +130,12 @@ * immediately, instead of batching to one update per frame | ||
/** | ||
* Returns whether this.state is shared with other components (the default). | ||
* @returns true if this.state is shared, false if this.appState is the shared store | ||
* @example | ||
* myWidget.isStateShared() | ||
*/ | ||
isStateShared() { | ||
return !this.appState; // if appState is not specified, all state is shared | ||
} | ||
/** | ||
* Executes the route handler matching the given URL fragment, and updates | ||
@@ -178,16 +192,17 @@ * the URL, as though the user had navigated explicitly to that address. | ||
update(stateUpdate={}) { | ||
if (!this.initialized) { | ||
Object.assign(this.state, stateUpdate); | ||
} else if (this.isPanelRoot) { | ||
const updateHash = '$fragment' in stateUpdate && stateUpdate.$fragment !== this.state.$fragment; | ||
return this._updateStore(stateUpdate, {store: `state`, cascade: this.isStateShared()}); | ||
} | ||
Object.assign(this.state, stateUpdate); | ||
this.updateSelfAndChildren(this.state); | ||
if (updateHash) { | ||
this.router.replaceHash(this.state.$fragment); | ||
} | ||
} else { | ||
this.$panelRoot.update(stateUpdate); | ||
} | ||
/** | ||
* Applies a state update specifically to app state shared across components. | ||
* In apps which don't specify `appState` in the root component config, all | ||
* state is shared across all parent and child components and the standard | ||
* update() method should be used instead. | ||
* @param {object} [stateUpdate={}] - keys and values of entries to update in | ||
* the app's appState object | ||
* @example | ||
* myWidget.updateApp({name: 'Bob'}); | ||
*/ | ||
updateApp(stateUpdate={}) { | ||
return this._updateStore(stateUpdate, {store: `appState`, cascade: true}); | ||
} | ||
@@ -241,3 +256,7 @@ | ||
this.$panelParent.$panelChildren.add(this); | ||
this.state = this.$panelRoot.state; | ||
// share either appState or all of state | ||
this.appState = this.$panelRoot.appState; | ||
this.state = this.isStateShared() ? this.$panelRoot.state : {}; | ||
} else { | ||
@@ -247,2 +266,3 @@ this.isPanelRoot = true; | ||
this.$panelParent = null; | ||
this.appState = this.getConfig(`appState`); | ||
} | ||
@@ -310,11 +330,2 @@ this.app = this.$panelRoot; | ||
updateSelfAndChildren(state) { | ||
if (this.initialized && this.shouldUpdate(state)) { | ||
this.domPatcher.update(state); | ||
for (let child of this.$panelChildren) { | ||
child.updateSelfAndChildren(state); | ||
} | ||
} | ||
} | ||
_render(state) { | ||
@@ -324,2 +335,3 @@ if (this.shouldUpdate(state)) { | ||
this._rendered = this.getConfig('template')(Object.assign({}, state, { | ||
$app: this.appState, | ||
$component: this, | ||
@@ -350,4 +362,49 @@ $helpers: this.helpers, | ||
} | ||
// update helpers | ||
// Update a given state store (this.state or this.appState), with option | ||
// to 'cascade' the update across other linked components | ||
_updateStore(stateUpdate, options={}) { | ||
const {cascade, store} = options; | ||
if (!this.initialized) { | ||
// just update store without patching DOM etc | ||
Object.assign(this[store], stateUpdate); | ||
} else { | ||
// update DOM, router, descendants etc. | ||
const updateHash = '$fragment' in stateUpdate && stateUpdate.$fragment !== this[store].$fragment; | ||
this.updateSelfAndChildren(stateUpdate, {cascade, store}); | ||
if (cascade && !this.isPanelRoot) { | ||
this.$panelRoot.updateSelfAndChildren(stateUpdate, {exclude: this, cascade, store}); | ||
} | ||
if (updateHash) { | ||
this.router.replaceHash(this[store].$fragment); | ||
} | ||
} | ||
} | ||
// Apply the given update down the component hierarchy from this node, | ||
// optionally excluding one node's subtree. This is useful for applying | ||
// a full state update to one component while sending only "shared" state | ||
// updates to the app root. | ||
updateSelfAndChildren(stateUpdate, options={}) { | ||
const {store, cascade} = options; | ||
if (this.initialized && this.shouldUpdate(stateUpdate)) { | ||
Object.assign(this[store], stateUpdate); | ||
this.domPatcher.update(this.state); | ||
if (cascade) { | ||
for (let child of this.$panelChildren) { | ||
if (options.exclude !== child) { | ||
child.updateSelfAndChildren(stateUpdate, options); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
export default Component; |
{ | ||
"name": "panel", | ||
"version": "0.11.0", | ||
"version": "0.12.0-rc1", | ||
"description": "Web Components with Virtual DOM: lightweight composable web apps", | ||
@@ -12,3 +12,3 @@ "main": "build/index.js", | ||
"build": "babel lib -d build && cp -r build/isorender .", | ||
"build-test": "webpack --config test/fixtures/webpack.config.js", | ||
"build-test": "webpack --config test/browser/webpack.config.js", | ||
"docs": "rm -rf docs && jsdoc lib lib/isorender -t node_modules/minami -R README-API.md -d docs", | ||
@@ -42,2 +42,3 @@ "prepublish": "npm run build", | ||
"html-element": "2.2.0", | ||
"lodash.pick": "4.4.0", | ||
"raf": "3.2.0", | ||
@@ -44,0 +45,0 @@ "snabbdom": "0.6.1", |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
88678
1676
0
7
+ Addedlodash.pick@4.4.0
+ Addedlodash.pick@4.4.0(transitive)