shadow-component
Advanced tools
Comparing version 0.1.8 to 0.1.9
1344
dist/shaco.js
@@ -0,3 +1,1275 @@ | ||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Shaco = f()}})(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);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | ||
// shim for using process in browser | ||
var process = module.exports = {}; | ||
var queue = []; | ||
var draining = false; | ||
var currentQueue; | ||
var queueIndex = -1; | ||
function cleanUpNextTick() { | ||
draining = false; | ||
if (currentQueue.length) { | ||
queue = currentQueue.concat(queue); | ||
} else { | ||
queueIndex = -1; | ||
} | ||
if (queue.length) { | ||
drainQueue(); | ||
} | ||
} | ||
function drainQueue() { | ||
if (draining) { | ||
return; | ||
} | ||
var timeout = setTimeout(cleanUpNextTick); | ||
draining = true; | ||
var len = queue.length; | ||
while(len) { | ||
currentQueue = queue; | ||
queue = []; | ||
while (++queueIndex < len) { | ||
if (currentQueue) { | ||
currentQueue[queueIndex].run(); | ||
} | ||
} | ||
queueIndex = -1; | ||
len = queue.length; | ||
} | ||
currentQueue = null; | ||
draining = false; | ||
clearTimeout(timeout); | ||
} | ||
process.nextTick = function (fun) { | ||
var args = new Array(arguments.length - 1); | ||
if (arguments.length > 1) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
args[i - 1] = arguments[i]; | ||
} | ||
} | ||
queue.push(new Item(fun, args)); | ||
if (queue.length === 1 && !draining) { | ||
setTimeout(drainQueue, 0); | ||
} | ||
}; | ||
// v8 likes predictible objects | ||
function Item(fun, array) { | ||
this.fun = fun; | ||
this.array = array; | ||
} | ||
Item.prototype.run = function () { | ||
this.fun.apply(null, this.array); | ||
}; | ||
process.title = 'browser'; | ||
process.browser = true; | ||
process.env = {}; | ||
process.argv = []; | ||
process.version = ''; // empty string to avoid regexp issues | ||
process.versions = {}; | ||
function noop() {} | ||
process.on = noop; | ||
process.addListener = noop; | ||
process.once = noop; | ||
process.off = noop; | ||
process.removeListener = noop; | ||
process.removeAllListeners = noop; | ||
process.emit = noop; | ||
process.binding = function (name) { | ||
throw new Error('process.binding is not supported'); | ||
}; | ||
process.cwd = function () { return '/' }; | ||
process.chdir = function (dir) { | ||
throw new Error('process.chdir is not supported'); | ||
}; | ||
process.umask = function() { return 0; }; | ||
},{}],2:[function(require,module,exports){ | ||
(function (process){ | ||
/** | ||
* @license | ||
* Copyright 2015 The Incremental DOM Authors. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS-IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
'use strict'; | ||
/** | ||
* Copyright 2015 The Incremental DOM Authors. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS-IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
/** | ||
* Keeps track whether or not we are in an attributes declaration (after | ||
* elementOpenStart, but before elementOpenEnd). | ||
* @type {boolean} | ||
*/ | ||
var inAttributes = false; | ||
/** | ||
* Keeps track whether or not we are in an element that should not have its | ||
* children cleared. | ||
* @type {boolean} | ||
*/ | ||
var inSkip = false; | ||
/** | ||
* Makes sure that there is a current patch context. | ||
* @param {*} context | ||
*/ | ||
var assertInPatch = function (context) { | ||
if (!context) { | ||
throw new Error('Cannot call currentElement() unless in patch'); | ||
} | ||
}; | ||
/** | ||
* Makes sure that keyed Element matches the tag name provided. | ||
* @param {!string} nodeName The nodeName of the node that is being matched. | ||
* @param {string=} tag The tag name of the Element. | ||
* @param {?string=} key The key of the Element. | ||
*/ | ||
var assertKeyedTagMatches = function (nodeName, tag, key) { | ||
if (nodeName !== tag) { | ||
throw new Error('Was expecting node with key "' + key + '" to be a ' + tag + ', not a ' + nodeName + '.'); | ||
} | ||
}; | ||
/** | ||
* Makes sure that a patch closes every node that it opened. | ||
* @param {?Node} openElement | ||
* @param {!Node|!DocumentFragment} root | ||
*/ | ||
var assertNoUnclosedTags = function (openElement, root) { | ||
if (openElement === root) { | ||
return; | ||
} | ||
var currentElement = openElement; | ||
var openTags = []; | ||
while (currentElement && currentElement !== root) { | ||
openTags.push(currentElement.nodeName.toLowerCase()); | ||
currentElement = currentElement.parentNode; | ||
} | ||
throw new Error('One or more tags were not closed:\n' + openTags.join('\n')); | ||
}; | ||
/** | ||
* Makes sure that the caller is not where attributes are expected. | ||
* @param {string} functionName | ||
*/ | ||
var assertNotInAttributes = function (functionName) { | ||
if (inAttributes) { | ||
throw new Error(functionName + '() may not be called between ' + 'elementOpenStart() and elementOpenEnd().'); | ||
} | ||
}; | ||
/** | ||
* Makes sure that the caller is not inside an element that has declared skip. | ||
* @param {string} functionName | ||
*/ | ||
var assertNotInSkip = function (functionName) { | ||
if (inSkip) { | ||
throw new Error(functionName + '() may not be called inside an element ' + 'that has called skip().'); | ||
} | ||
}; | ||
/** | ||
* Makes sure that the caller is where attributes are expected. | ||
* @param {string} functionName | ||
*/ | ||
var assertInAttributes = function (functionName) { | ||
if (!inAttributes) { | ||
throw new Error(functionName + '() must be called after ' + 'elementOpenStart().'); | ||
} | ||
}; | ||
/** | ||
* Makes sure the patch closes virtual attributes call | ||
*/ | ||
var assertVirtualAttributesClosed = function () { | ||
if (inAttributes) { | ||
throw new Error('elementOpenEnd() must be called after calling ' + 'elementOpenStart().'); | ||
} | ||
}; | ||
/** | ||
* Makes sure that placeholders have a key specified. Otherwise, conditional | ||
* placeholders and conditional elements next to placeholders will cause | ||
* placeholder elements to be re-used as non-placeholders and vice versa. | ||
* @param {string} key | ||
*/ | ||
var assertPlaceholderKeySpecified = function (key) { | ||
if (!key) { | ||
throw new Error('Placeholder elements must have a key specified.'); | ||
} | ||
}; | ||
/** | ||
* Makes sure that tags are correctly nested. | ||
* @param {string} nodeName | ||
* @param {string} tag | ||
*/ | ||
var assertCloseMatchesOpenTag = function (nodeName, tag) { | ||
if (nodeName !== tag) { | ||
throw new Error('Received a call to close ' + tag + ' but ' + nodeName + ' was open.'); | ||
} | ||
}; | ||
/** | ||
* Makes sure that no children elements have been declared yet in the current | ||
* element. | ||
* @param {string} functionName | ||
* @param {?Node} previousNode | ||
*/ | ||
var assertNoChildrenDeclaredYet = function (functionName, previousNode) { | ||
if (previousNode !== null) { | ||
throw new Error(functionName + '() must come before any child ' + 'declarations inside the current element.'); | ||
} | ||
}; | ||
/** | ||
* Updates the state of being in an attribute declaration. | ||
* @param {boolean} value | ||
* @return {boolean} the previous value. | ||
*/ | ||
var setInAttributes = function (value) { | ||
var previous = inAttributes; | ||
inAttributes = value; | ||
return previous; | ||
}; | ||
/** | ||
* Updates the state of being in a skip element. | ||
* @param {boolean} value | ||
* @return {boolean} the previous value. | ||
*/ | ||
var setInSkip = function (value) { | ||
var previous = inSkip; | ||
inSkip = value; | ||
return previous; | ||
}; | ||
/** | ||
* Copyright 2015 The Incremental DOM Authors. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS-IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
/** */ | ||
exports.notifications = { | ||
/** | ||
* Called after patch has compleated with any Nodes that have been created | ||
* and added to the DOM. | ||
* @type {?function(Array<!Node>)} | ||
*/ | ||
nodesCreated: null, | ||
/** | ||
* Called after patch has compleated with any Nodes that have been removed | ||
* from the DOM. | ||
* Note it's an applications responsibility to handle any childNodes. | ||
* @type {?function(Array<!Node>)} | ||
*/ | ||
nodesDeleted: null | ||
}; | ||
/** | ||
* Keeps track of the state of a patch. | ||
* @constructor | ||
*/ | ||
function Context() { | ||
/** | ||
* @type {(Array<!Node>|undefined)} | ||
*/ | ||
this.created = exports.notifications.nodesCreated && []; | ||
/** | ||
* @type {(Array<!Node>|undefined)} | ||
*/ | ||
this.deleted = exports.notifications.nodesDeleted && []; | ||
} | ||
/** | ||
* @param {!Node} node | ||
*/ | ||
Context.prototype.markCreated = function (node) { | ||
if (this.created) { | ||
this.created.push(node); | ||
} | ||
}; | ||
/** | ||
* @param {!Node} node | ||
*/ | ||
Context.prototype.markDeleted = function (node) { | ||
if (this.deleted) { | ||
this.deleted.push(node); | ||
} | ||
}; | ||
/** | ||
* Notifies about nodes that were created during the patch opearation. | ||
*/ | ||
Context.prototype.notifyChanges = function () { | ||
if (this.created && this.created.length > 0) { | ||
exports.notifications.nodesCreated(this.created); | ||
} | ||
if (this.deleted && this.deleted.length > 0) { | ||
exports.notifications.nodesDeleted(this.deleted); | ||
} | ||
}; | ||
/** | ||
* Copyright 2015 The Incremental DOM Authors. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS-IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
/** | ||
* A cached reference to the hasOwnProperty function. | ||
*/ | ||
var hasOwnProperty = Object.prototype.hasOwnProperty; | ||
/** | ||
* A cached reference to the create function. | ||
*/ | ||
var create = Object.create; | ||
/** | ||
* Used to prevent property collisions between our "map" and its prototype. | ||
* @param {!Object<string, *>} map The map to check. | ||
* @param {string} property The property to check. | ||
* @return {boolean} Whether map has property. | ||
*/ | ||
var has = function (map, property) { | ||
return hasOwnProperty.call(map, property); | ||
}; | ||
/** | ||
* Creates an map object without a prototype. | ||
* @return {!Object} | ||
*/ | ||
var createMap = function () { | ||
return create(null); | ||
}; | ||
/** | ||
* Keeps track of information needed to perform diffs for a given DOM node. | ||
* @param {!string} nodeName | ||
* @param {?string=} key | ||
* @constructor | ||
*/ | ||
function NodeData(nodeName, key) { | ||
/** | ||
* The attributes and their values. | ||
* @const {!Object<string, *>} | ||
*/ | ||
this.attrs = createMap(); | ||
/** | ||
* An array of attribute name/value pairs, used for quickly diffing the | ||
* incomming attributes to see if the DOM node's attributes need to be | ||
* updated. | ||
* @const {Array<*>} | ||
*/ | ||
this.attrsArr = []; | ||
/** | ||
* The incoming attributes for this Node, before they are updated. | ||
* @const {!Object<string, *>} | ||
*/ | ||
this.newAttrs = createMap(); | ||
/** | ||
* The key used to identify this node, used to preserve DOM nodes when they | ||
* move within their parent. | ||
* @const | ||
*/ | ||
this.key = key; | ||
/** | ||
* Keeps track of children within this node by their key. | ||
* {?Object<string, !Element>} | ||
*/ | ||
this.keyMap = null; | ||
/** | ||
* Whether or not the keyMap is currently valid. | ||
* {boolean} | ||
*/ | ||
this.keyMapValid = true; | ||
/** | ||
* The node name for this node. | ||
* @const {string} | ||
*/ | ||
this.nodeName = nodeName; | ||
/** | ||
* @type {?string} | ||
*/ | ||
this.text = null; | ||
} | ||
/** | ||
* Initializes a NodeData object for a Node. | ||
* | ||
* @param {Node} node The node to initialize data for. | ||
* @param {string} nodeName The node name of node. | ||
* @param {?string=} key The key that identifies the node. | ||
* @return {!NodeData} The newly initialized data object | ||
*/ | ||
var initData = function (node, nodeName, key) { | ||
var data = new NodeData(nodeName, key); | ||
node['__incrementalDOMData'] = data; | ||
return data; | ||
}; | ||
/** | ||
* Retrieves the NodeData object for a Node, creating it if necessary. | ||
* | ||
* @param {Node} node The node to retrieve the data for. | ||
* @return {!NodeData} The NodeData for this Node. | ||
*/ | ||
var getData = function (node) { | ||
var data = node['__incrementalDOMData']; | ||
if (!data) { | ||
var nodeName = node.nodeName.toLowerCase(); | ||
var key = null; | ||
if (node instanceof Element) { | ||
key = node.getAttribute('key'); | ||
} | ||
data = initData(node, nodeName, key); | ||
} | ||
return data; | ||
}; | ||
/** | ||
* Copyright 2015 The Incremental DOM Authors. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS-IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
exports.symbols = { | ||
default: '__default', | ||
placeholder: '__placeholder' | ||
}; | ||
/** | ||
* Applies an attribute or property to a given Element. If the value is null | ||
* or undefined, it is removed from the Element. Otherwise, the value is set | ||
* as an attribute. | ||
* @param {!Element} el | ||
* @param {string} name The attribute's name. | ||
* @param {?(boolean|number|string)=} value The attribute's value. | ||
*/ | ||
exports.applyAttr = function (el, name, value) { | ||
if (value == null) { | ||
el.removeAttribute(name); | ||
} else { | ||
el.setAttribute(name, value); | ||
} | ||
}; | ||
/** | ||
* Applies a property to a given Element. | ||
* @param {!Element} el | ||
* @param {string} name The property's name. | ||
* @param {*} value The property's value. | ||
*/ | ||
exports.applyProp = function (el, name, value) { | ||
el[name] = value; | ||
}; | ||
/** | ||
* Applies a style to an Element. No vendor prefix expansion is done for | ||
* property names/values. | ||
* @param {!Element} el | ||
* @param {string} name The attribute's name. | ||
* @param {*} style The style to set. Either a string of css or an object | ||
* containing property-value pairs. | ||
*/ | ||
var applyStyle = function (el, name, style) { | ||
if (typeof style === 'string') { | ||
el.style.cssText = style; | ||
} else { | ||
el.style.cssText = ''; | ||
var elStyle = el.style; | ||
var obj = /** @type {!Object<string,string>} */style; | ||
for (var prop in obj) { | ||
if (has(obj, prop)) { | ||
elStyle[prop] = obj[prop]; | ||
} | ||
} | ||
} | ||
}; | ||
/** | ||
* Updates a single attribute on an Element. | ||
* @param {!Element} el | ||
* @param {string} name The attribute's name. | ||
* @param {*} value The attribute's value. If the value is an object or | ||
* function it is set on the Element, otherwise, it is set as an HTML | ||
* attribute. | ||
*/ | ||
var applyAttributeTyped = function (el, name, value) { | ||
var type = typeof value; | ||
if (type === 'object' || type === 'function') { | ||
exports.applyProp(el, name, value); | ||
} else { | ||
exports.applyAttr(el, name, /** @type {?(boolean|number|string)} */value); | ||
} | ||
}; | ||
/** | ||
* Calls the appropriate attribute mutator for this attribute. | ||
* @param {!Element} el | ||
* @param {string} name The attribute's name. | ||
* @param {*} value The attribute's value. | ||
*/ | ||
var updateAttribute = function (el, name, value) { | ||
var data = getData(el); | ||
var attrs = data.attrs; | ||
if (attrs[name] === value) { | ||
return; | ||
} | ||
var mutator = exports.attributes[name] || exports.attributes[exports.symbols.default]; | ||
mutator(el, name, value); | ||
attrs[name] = value; | ||
}; | ||
/** | ||
* A publicly mutable object to provide custom mutators for attributes. | ||
* @const {!Object<string, function(!Element, string, *)>} | ||
*/ | ||
exports.attributes = createMap(); | ||
// Special generic mutator that's called for any attribute that does not | ||
// have a specific mutator. | ||
exports.attributes[exports.symbols.default] = applyAttributeTyped; | ||
exports.attributes[exports.symbols.placeholder] = function () {}; | ||
exports.attributes['style'] = applyStyle; | ||
/** | ||
* Gets the namespace to create an element (of a given tag) in. | ||
* @param {string} tag The tag to get the namespace for. | ||
* @param {?Node} parent | ||
* @return {?string} The namespace to create the tag in. | ||
*/ | ||
var getNamespaceForTag = function (tag, parent) { | ||
if (tag === 'svg') { | ||
return 'http://www.w3.org/2000/svg'; | ||
} | ||
if (getData(parent).nodeName === 'foreignObject') { | ||
return null; | ||
} | ||
return parent.namespaceURI; | ||
}; | ||
/** | ||
* Creates an Element. | ||
* @param {Document} doc The document with which to create the Element. | ||
* @param {?Node} parent | ||
* @param {string} tag The tag for the Element. | ||
* @param {?string=} key A key to identify the Element. | ||
* @param {?Array<*>=} statics An array of attribute name/value pairs of the | ||
* static attributes for the Element. | ||
* @return {!Element} | ||
*/ | ||
var createElement = function (doc, parent, tag, key, statics) { | ||
var namespace = getNamespaceForTag(tag, parent); | ||
var el; | ||
if (namespace) { | ||
el = doc.createElementNS(namespace, tag); | ||
} else { | ||
el = doc.createElement(tag); | ||
} | ||
initData(el, tag, key); | ||
if (statics) { | ||
for (var i = 0; i < statics.length; i += 2) { | ||
updateAttribute(el, /** @type {!string}*/statics[i], statics[i + 1]); | ||
} | ||
} | ||
return el; | ||
}; | ||
/** | ||
* Creates a Text Node. | ||
* @param {Document} doc The document with which to create the Element. | ||
* @return {!Text} | ||
*/ | ||
var createText = function (doc) { | ||
var node = doc.createTextNode(''); | ||
initData(node, '#text', null); | ||
return node; | ||
}; | ||
/** | ||
* Creates a mapping that can be used to look up children using a key. | ||
* @param {?Node} el | ||
* @return {!Object<string, !Element>} A mapping of keys to the children of the | ||
* Element. | ||
*/ | ||
var createKeyMap = function (el) { | ||
var map = createMap(); | ||
var children = el.children; | ||
var count = children.length; | ||
for (var i = 0; i < count; i += 1) { | ||
var child = children[i]; | ||
var key = getData(child).key; | ||
if (key) { | ||
map[key] = child; | ||
} | ||
} | ||
return map; | ||
}; | ||
/** | ||
* Retrieves the mapping of key to child node for a given Element, creating it | ||
* if necessary. | ||
* @param {?Node} el | ||
* @return {!Object<string, !Node>} A mapping of keys to child Elements | ||
*/ | ||
var getKeyMap = function (el) { | ||
var data = getData(el); | ||
if (!data.keyMap) { | ||
data.keyMap = createKeyMap(el); | ||
} | ||
return data.keyMap; | ||
}; | ||
/** | ||
* Retrieves a child from the parent with the given key. | ||
* @param {?Node} parent | ||
* @param {?string=} key | ||
* @return {?Node} The child corresponding to the key. | ||
*/ | ||
var getChild = function (parent, key) { | ||
return key ? getKeyMap(parent)[key] : null; | ||
}; | ||
/** | ||
* Registers an element as being a child. The parent will keep track of the | ||
* child using the key. The child can be retrieved using the same key using | ||
* getKeyMap. The provided key should be unique within the parent Element. | ||
* @param {?Node} parent The parent of child. | ||
* @param {string} key A key to identify the child with. | ||
* @param {!Node} child The child to register. | ||
*/ | ||
var registerChild = function (parent, key, child) { | ||
getKeyMap(parent)[key] = child; | ||
}; | ||
/** @type {?Context} */ | ||
var context = null; | ||
/** @type {?Node} */ | ||
var currentNode; | ||
/** @type {?Node} */ | ||
var currentParent; | ||
/** @type {?Node} */ | ||
var previousNode; | ||
/** @type {?Element|?DocumentFragment} */ | ||
var root; | ||
/** @type {?Document} */ | ||
var doc; | ||
/** | ||
* Patches the document starting at el with the provided function. This function | ||
* may be called during an existing patch operation. | ||
* @param {!Element|!DocumentFragment} node The Element or Document | ||
* to patch. | ||
* @param {!function(T)} fn A function containing elementOpen/elementClose/etc. | ||
* calls that describe the DOM. | ||
* @param {T=} data An argument passed to fn to represent DOM state. | ||
* @template T | ||
*/ | ||
exports.patch = function (node, fn, data) { | ||
var prevContext = context; | ||
var prevRoot = root; | ||
var prevDoc = doc; | ||
var prevCurrentNode = currentNode; | ||
var prevCurrentParent = currentParent; | ||
var prevPreviousNode = previousNode; | ||
var previousInAttributes = false; | ||
var previousInSkip = false; | ||
context = new Context(); | ||
root = node; | ||
doc = node.ownerDocument; | ||
currentNode = node; | ||
currentParent = null; | ||
previousNode = null; | ||
if (process.env.NODE_ENV !== 'production') { | ||
previousInAttributes = setInAttributes(false); | ||
previousInSkip = setInSkip(false); | ||
} | ||
enterNode(); | ||
fn(data); | ||
exitNode(); | ||
if (process.env.NODE_ENV !== 'production') { | ||
assertVirtualAttributesClosed(); | ||
assertNoUnclosedTags(previousNode, node); | ||
setInAttributes(previousInAttributes); | ||
setInSkip(previousInSkip); | ||
} | ||
context.notifyChanges(); | ||
context = prevContext; | ||
root = prevRoot; | ||
doc = prevDoc; | ||
currentNode = prevCurrentNode; | ||
currentParent = prevCurrentParent; | ||
previousNode = prevPreviousNode; | ||
}; | ||
/** | ||
* Checks whether or not the current node matches the specified nodeName and | ||
* key. | ||
* | ||
* @param {?string} nodeName The nodeName for this node. | ||
* @param {?string=} key An optional key that identifies a node. | ||
* @return {boolean} True if the node matches, false otherwise. | ||
*/ | ||
var matches = function (nodeName, key) { | ||
var data = getData(currentNode); | ||
// Key check is done using double equals as we want to treat a null key the | ||
// same as undefined. This should be okay as the only values allowed are | ||
// strings, null and undefined so the == semantics are not too weird. | ||
return nodeName === data.nodeName && key == data.key; | ||
}; | ||
/** | ||
* Aligns the virtual Element definition with the actual DOM, moving the | ||
* corresponding DOM node to the correct location or creating it if necessary. | ||
* @param {string} nodeName For an Element, this should be a valid tag string. | ||
* For a Text, this should be #text. | ||
* @param {?string=} key The key used to identify this element. | ||
* @param {?Array<*>=} statics For an Element, this should be an array of | ||
* name-value pairs. | ||
*/ | ||
var alignWithDOM = function (nodeName, key, statics) { | ||
if (currentNode && matches(nodeName, key)) { | ||
return; | ||
} | ||
var node; | ||
// Check to see if the node has moved within the parent. | ||
if (key) { | ||
node = getChild(currentParent, key); | ||
if (node && process.env.NODE_ENV !== 'production') { | ||
assertKeyedTagMatches(getData(node).nodeName, nodeName, key); | ||
} | ||
} | ||
// Create the node if it doesn't exist. | ||
if (!node) { | ||
if (nodeName === '#text') { | ||
node = createText(doc); | ||
} else { | ||
node = createElement(doc, currentParent, nodeName, key, statics); | ||
} | ||
if (key) { | ||
registerChild(currentParent, key, node); | ||
} | ||
context.markCreated(node); | ||
} | ||
// If the node has a key, remove it from the DOM to prevent a large number | ||
// of re-orders in the case that it moved far or was completely removed. | ||
// Since we hold on to a reference through the keyMap, we can always add it | ||
// back. | ||
if (currentNode && getData(currentNode).key) { | ||
currentParent.replaceChild(node, currentNode); | ||
getData(currentParent).keyMapValid = false; | ||
} else { | ||
currentParent.insertBefore(node, currentNode); | ||
} | ||
currentNode = node; | ||
}; | ||
/** | ||
* Clears out any unvisited Nodes, as the corresponding virtual element | ||
* functions were never called for them. | ||
*/ | ||
var clearUnvisitedDOM = function () { | ||
var node = currentParent; | ||
var data = getData(node); | ||
var keyMap = data.keyMap; | ||
var keyMapValid = data.keyMapValid; | ||
var child = node.lastChild; | ||
var key; | ||
if (child === previousNode && keyMapValid) { | ||
return; | ||
} | ||
if (data.attrs[exports.symbols.placeholder] && node !== root) { | ||
return; | ||
} | ||
while (child !== previousNode) { | ||
node.removeChild(child); | ||
context.markDeleted( /** @type {!Node}*/child); | ||
key = getData(child).key; | ||
if (key) { | ||
delete keyMap[key]; | ||
} | ||
child = node.lastChild; | ||
} | ||
// Clean the keyMap, removing any unusued keys. | ||
if (!keyMapValid) { | ||
for (key in keyMap) { | ||
child = keyMap[key]; | ||
if (child.parentNode !== node) { | ||
context.markDeleted(child); | ||
delete keyMap[key]; | ||
} | ||
} | ||
data.keyMapValid = true; | ||
} | ||
}; | ||
/** | ||
* Changes to the first child of the current node. | ||
*/ | ||
var enterNode = function () { | ||
currentParent = currentNode; | ||
currentNode = currentNode.firstChild; | ||
previousNode = null; | ||
}; | ||
/** | ||
* Changes to the next sibling of the current node. | ||
*/ | ||
var nextNode = function () { | ||
previousNode = currentNode; | ||
currentNode = currentNode.nextSibling; | ||
}; | ||
/** | ||
* Changes to the parent of the current node, removing any unvisited children. | ||
*/ | ||
var exitNode = function () { | ||
clearUnvisitedDOM(); | ||
previousNode = currentParent; | ||
currentNode = currentParent.nextSibling; | ||
currentParent = currentParent.parentNode; | ||
}; | ||
/** | ||
* Makes sure that the current node is an Element with a matching tagName and | ||
* key. | ||
* | ||
* @param {string} tag The element's tag. | ||
* @param {?string=} key The key used to identify this element. This can be an | ||
* empty string, but performance may be better if a unique value is used | ||
* when iterating over an array of items. | ||
* @param {?Array<*>=} statics An array of attribute name/value pairs of the | ||
* static attributes for the Element. These will only be set once when the | ||
* Element is created. | ||
* @return {!Element} The corresponding Element. | ||
*/ | ||
var _elementOpen = function (tag, key, statics) { | ||
alignWithDOM(tag, key, statics); | ||
enterNode(); | ||
return (/** @type {!Element} */currentParent | ||
); | ||
}; | ||
/** | ||
* Closes the currently open Element, removing any unvisited children if | ||
* necessary. | ||
* | ||
* @return {!Element} The corresponding Element. | ||
*/ | ||
var _elementClose = function () { | ||
if (process.env.NODE_ENV !== 'production') { | ||
setInSkip(false); | ||
} | ||
exitNode(); | ||
return (/** @type {!Element} */previousNode | ||
); | ||
}; | ||
/** | ||
* Makes sure the current node is a Text node and creates a Text node if it is | ||
* not. | ||
* | ||
* @return {!Text} The corresponding Text Node. | ||
*/ | ||
var _text = function () { | ||
alignWithDOM('#text', null, null); | ||
nextNode(); | ||
return (/** @type {!Text} */previousNode | ||
); | ||
}; | ||
/** | ||
* Gets the current Element being patched. | ||
* @return {!Element} | ||
*/ | ||
exports.currentElement = function () { | ||
if (process.env.NODE_ENV !== 'production') { | ||
assertInPatch(context); | ||
assertNotInAttributes('currentElement'); | ||
} | ||
return (/** @type {!Element} */currentParent | ||
); | ||
}; | ||
/** | ||
* Skips the children in a subtree, allowing an Element to be closed without | ||
* clearing out the children. | ||
*/ | ||
exports.skip = function () { | ||
if (process.env.NODE_ENV !== 'production') { | ||
assertNoChildrenDeclaredYet('skip', previousNode); | ||
setInSkip(true); | ||
} | ||
previousNode = currentParent.lastChild; | ||
}; | ||
/** | ||
* The offset in the virtual element declaration where the attributes are | ||
* specified. | ||
* @const | ||
*/ | ||
var ATTRIBUTES_OFFSET = 3; | ||
/** | ||
* Builds an array of arguments for use with elementOpenStart, attr and | ||
* elementOpenEnd. | ||
* @const {Array<*>} | ||
*/ | ||
var argsBuilder = []; | ||
/** | ||
* @param {string} tag The element's tag. | ||
* @param {?string=} key The key used to identify this element. This can be an | ||
* empty string, but performance may be better if a unique value is used | ||
* when iterating over an array of items. | ||
* @param {?Array<*>=} statics An array of attribute name/value pairs of the | ||
* static attributes for the Element. These will only be set once when the | ||
* Element is created. | ||
* @param {...*} var_args Attribute name/value pairs of the dynamic attributes | ||
* for the Element. | ||
* @return {!Element} The corresponding Element. | ||
*/ | ||
exports.elementOpen = function (tag, key, statics, var_args) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
assertNotInAttributes('elementOpen'); | ||
assertNotInSkip('elementOpen'); | ||
} | ||
var node = _elementOpen(tag, key, statics); | ||
var data = getData(node); | ||
/* | ||
* Checks to see if one or more attributes have changed for a given Element. | ||
* When no attributes have changed, this is much faster than checking each | ||
* individual argument. When attributes have changed, the overhead of this is | ||
* minimal. | ||
*/ | ||
var attrsArr = data.attrsArr; | ||
var newAttrs = data.newAttrs; | ||
var attrsChanged = false; | ||
var i = ATTRIBUTES_OFFSET; | ||
var j = 0; | ||
for (; i < arguments.length; i += 1, j += 1) { | ||
if (attrsArr[j] !== arguments[i]) { | ||
attrsChanged = true; | ||
break; | ||
} | ||
} | ||
for (; i < arguments.length; i += 1, j += 1) { | ||
attrsArr[j] = arguments[i]; | ||
} | ||
if (j < attrsArr.length) { | ||
attrsChanged = true; | ||
attrsArr.length = j; | ||
} | ||
/* | ||
* Actually perform the attribute update. | ||
*/ | ||
if (attrsChanged) { | ||
for (i = ATTRIBUTES_OFFSET; i < arguments.length; i += 2) { | ||
newAttrs[arguments[i]] = arguments[i + 1]; | ||
} | ||
for (var attr in newAttrs) { | ||
updateAttribute(node, attr, newAttrs[attr]); | ||
newAttrs[attr] = undefined; | ||
} | ||
} | ||
return node; | ||
}; | ||
/** | ||
* Declares a virtual Element at the current location in the document. This | ||
* corresponds to an opening tag and a elementClose tag is required. This is | ||
* like elementOpen, but the attributes are defined using the attr function | ||
* rather than being passed as arguments. Must be folllowed by 0 or more calls | ||
* to attr, then a call to elementOpenEnd. | ||
* @param {string} tag The element's tag. | ||
* @param {?string=} key The key used to identify this element. This can be an | ||
* empty string, but performance may be better if a unique value is used | ||
* when iterating over an array of items. | ||
* @param {?Array<*>=} statics An array of attribute name/value pairs of the | ||
* static attributes for the Element. These will only be set once when the | ||
* Element is created. | ||
*/ | ||
exports.elementOpenStart = function (tag, key, statics) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
assertNotInAttributes('elementOpenStart'); | ||
setInAttributes(true); | ||
} | ||
argsBuilder[0] = tag; | ||
argsBuilder[1] = key; | ||
argsBuilder[2] = statics; | ||
}; | ||
/*** | ||
* Defines a virtual attribute at this point of the DOM. This is only valid | ||
* when called between elementOpenStart and elementOpenEnd. | ||
* | ||
* @param {string} name | ||
* @param {*} value | ||
*/ | ||
exports.attr = function (name, value) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
assertInAttributes('attr'); | ||
} | ||
argsBuilder.push(name, value); | ||
}; | ||
/** | ||
* Closes an open tag started with elementOpenStart. | ||
* @return {!Element} The corresponding Element. | ||
*/ | ||
exports.elementOpenEnd = function () { | ||
if (process.env.NODE_ENV !== 'production') { | ||
assertInAttributes('elementOpenEnd'); | ||
setInAttributes(false); | ||
} | ||
var node = exports.elementOpen.apply(null, argsBuilder); | ||
argsBuilder.length = 0; | ||
return node; | ||
}; | ||
/** | ||
* Closes an open virtual Element. | ||
* | ||
* @param {string} tag The element's tag. | ||
* @return {!Element} The corresponding Element. | ||
*/ | ||
exports.elementClose = function (tag) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
assertNotInAttributes('elementClose'); | ||
} | ||
var node = _elementClose(); | ||
if (process.env.NODE_ENV !== 'production') { | ||
assertCloseMatchesOpenTag(getData(node).nodeName, tag); | ||
} | ||
return node; | ||
}; | ||
/** | ||
* Declares a virtual Element at the current location in the document that has | ||
* no children. | ||
* @param {string} tag The element's tag. | ||
* @param {?string=} key The key used to identify this element. This can be an | ||
* empty string, but performance may be better if a unique value is used | ||
* when iterating over an array of items. | ||
* @param {?Array<*>=} statics An array of attribute name/value pairs of the | ||
* static attributes for the Element. These will only be set once when the | ||
* Element is created. | ||
* @param {...*} var_args Attribute name/value pairs of the dynamic attributes | ||
* for the Element. | ||
* @return {!Element} The corresponding Element. | ||
*/ | ||
exports.elementVoid = function (tag, key, statics, var_args) { | ||
var node = exports.elementOpen.apply(null, arguments); | ||
exports.elementClose.apply(null, arguments); | ||
return node; | ||
}; | ||
/** | ||
* Declares a virtual Element at the current location in the document that is a | ||
* placeholder element. Children of this Element can be manually managed and | ||
* will not be cleared by the library. | ||
* | ||
* A key must be specified to make sure that this node is correctly preserved | ||
* across all conditionals. | ||
* | ||
* @param {string} tag The element's tag. | ||
* @param {string} key The key used to identify this element. | ||
* @param {?Array<*>=} statics An array of attribute name/value pairs of the | ||
* static attributes for the Element. These will only be set once when the | ||
* Element is created. | ||
* @param {...*} var_args Attribute name/value pairs of the dynamic attributes | ||
* for the Element. | ||
* @return {!Element} The corresponding Element. | ||
*/ | ||
exports.elementPlaceholder = function (tag, key, statics, var_args) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
assertPlaceholderKeySpecified(key); | ||
} | ||
exports.elementOpen.apply(null, arguments); | ||
exports.skip(); | ||
return exports.elementClose.apply(null, arguments); | ||
}; | ||
/** | ||
* Declares a virtual Text at this point in the document. | ||
* | ||
* @param {string|number|boolean} value The value of the Text. | ||
* @param {...(function((string|number|boolean)):string)} var_args | ||
* Functions to format the value which are called only when the value has | ||
* changed. | ||
* @return {!Text} The corresponding text node. | ||
*/ | ||
exports.text = function (value, var_args) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
assertNotInAttributes('text'); | ||
assertNotInSkip('text'); | ||
} | ||
var node = _text(); | ||
var data = getData(node); | ||
if (data.text !== value) { | ||
data.text = /** @type {string} */value; | ||
var formatted = value; | ||
for (var i = 1; i < arguments.length; i += 1) { | ||
formatted = arguments[i](formatted); | ||
} | ||
node.data = formatted; | ||
} | ||
return node; | ||
}; | ||
}).call(this,require('_process')) | ||
},{"_process":1}],3:[function(require,module,exports){ | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
@@ -59,2 +1331,4 @@ value: true | ||
exports.default = Builder; | ||
},{}],4:[function(require,module,exports){ | ||
'use strict'; | ||
@@ -76,3 +1350,5 @@ | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _interopRequireDefault(obj) { | ||
return obj && obj.__esModule ? obj : { default: obj }; | ||
} | ||
@@ -102,4 +1378,10 @@ if (!Array.isArray) { | ||
return { | ||
render: function render() { | ||
view.bind(this)(); | ||
render: function render(reRender) { | ||
if (!reRender) { | ||
renderElement(view, this); | ||
} else { | ||
(0, _incrementalDom.patch)(this, function (scope) { | ||
renderElement(view, scope); | ||
}, this); | ||
} | ||
} | ||
@@ -109,7 +1391,16 @@ }; | ||
function renderElement(view, scope) { | ||
var result = view.bind(scope)(); | ||
if (typeof result === 'function') { | ||
result.bind(scope)(); | ||
} | ||
} | ||
function setStateFactory() { | ||
return { | ||
setState: function setState(newState) { | ||
var force = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; | ||
this.state = Object.assign({}, this.state, newState); | ||
this.render(); | ||
this.render(force); | ||
return this.state; | ||
@@ -132,2 +1423,4 @@ } | ||
exports.default = TagFactory; | ||
},{"./builder":3,"./exceptions":5,"incremental-dom":2}],5:[function(require,module,exports){ | ||
'use strict'; | ||
@@ -158,2 +1451,4 @@ | ||
exports.default = ComponentExceptions; | ||
},{}],6:[function(require,module,exports){ | ||
'use strict'; | ||
@@ -171,7 +1466,6 @@ | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _interopRequireDefault(obj) { | ||
return obj && obj.__esModule ? obj : { default: obj }; | ||
} | ||
require('webcomponents-lite'); | ||
var DefaultComponentObject = { | ||
@@ -192,16 +1486,8 @@ state: {} | ||
var element = (0, _incrementalDom.elementOpenEnd)(tagName); | ||
if (typeof element.setState !== 'undefined') { | ||
element.setState(state); | ||
element.setState(Object.assign({}, state, { child: child })); | ||
} else { | ||
renderChild(child); | ||
} | ||
if (typeof child !== 'undefined') { | ||
if (Array.isArray(child)) { | ||
child.forEach(function (appendableView) { | ||
appendableView(); | ||
}); | ||
} else if (typeof child === 'string') { | ||
(0, _incrementalDom.text)(child); | ||
} else { | ||
child(); | ||
} | ||
} | ||
(0, _incrementalDom.elementClose)(tagName); | ||
@@ -211,2 +1497,17 @@ return element; | ||
function renderChild(child) { | ||
if (typeof child === 'undefined') { | ||
return; | ||
} | ||
if (typeof child === 'string') { | ||
return (0, _incrementalDom.text)(child.trim()); | ||
} else if (typeof child === 'function') { | ||
return child(); | ||
} else if (Array.isArray(child)) { | ||
child.forEach(renderChild); | ||
} else { | ||
return child; | ||
} | ||
} | ||
function ComponentFactory() { | ||
@@ -236,1 +1537,4 @@ var object = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; | ||
exports.default = Shaco; | ||
},{"./create":4,"incremental-dom":2}]},{},[6])(6) | ||
}); |
{ | ||
"name": "shadow-component", | ||
"version": "0.1.8", | ||
"version": "0.1.9", | ||
"description": "This is a test implementation of components with shadow dom and full template rendering of changes of state", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1707
75980
34
1