Comparing version 0.8.0 to 0.9.0
## Pre-v1.0.0 changes | ||
[v0.9.0] | ||
- Add support for custom adapters to support non-React setups | ||
[v0.9.0]: https://github.com/rstacruz/remount/compare/v0.8.0...v0.9.0 | ||
[v0.8.0] | ||
@@ -29,3 +35,3 @@ | ||
- Allow *define()* to accept defaults as a second argument (eg, `define({...}, { quiet: true })`) | ||
- Allow _define()_ to accept defaults as a second argument (eg, `define({...}, { quiet: true })`) | ||
- Support the `quiet: true` option (supresses warnings) | ||
@@ -32,0 +38,0 @@ - Support the `shadow: true` option (uses Shadow DOM) |
@@ -11,4 +11,2 @@ (function (global, factory) { | ||
var injected = void 0; | ||
/* | ||
@@ -20,3 +18,3 @@ * Adapted from https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs@2.0.4/custom-elements-es5-adapter.js | ||
function inject() { | ||
if (injected || void 0 === window.Reflect || void 0 === window.customElements || window.customElements.hasOwnProperty('polyfillWrapFlushCallback')) { | ||
if (window.HTMLElement && window.HTMLElement._babelES5Adapter || void 0 === window.Reflect || void 0 === window.customElements || window.customElements.hasOwnProperty('polyfillWrapFlushCallback')) { | ||
return; | ||
@@ -33,3 +31,3 @@ } | ||
Object.setPrototypeOf(HTMLElement, a); | ||
injected = true; | ||
HTMLElement._babelES5Adapter = true; | ||
} | ||
@@ -56,5 +54,7 @@ | ||
ElementEvents | ||
} from './types' | ||
} from '../types' | ||
*/ | ||
var name = 'CustomElements'; | ||
/** | ||
@@ -83,3 +83,4 @@ * Registers a custom element. | ||
var onUpdate = _ref.onUpdate, | ||
onUnmount = _ref.onUnmount; | ||
onUnmount = _ref.onUnmount, | ||
onMount = _ref.onMount; | ||
@@ -102,3 +103,3 @@ inject(); | ||
this._mountPoint = createMountPoint(this, elSpec); | ||
onUpdate(this, this._mountPoint); | ||
onMount(this, this._mountPoint); | ||
} | ||
@@ -161,11 +162,27 @@ }, { | ||
var name = 'CustomElements'; | ||
/** | ||
* Check if Shadow DOM is supported. | ||
*/ | ||
var ElementsAdapter = /*#__PURE__*/Object.freeze({ | ||
function supportsShadow() { | ||
return !!(document && document.body && document.body.attachShadow); | ||
} | ||
var CustomElementsStrategy = /*#__PURE__*/Object.freeze({ | ||
name: name, | ||
defineElement: defineElement, | ||
isSupported: isSupported, | ||
name: name | ||
supportsShadow: supportsShadow | ||
}); | ||
/* List of observers tags */ | ||
/*:: | ||
import type { | ||
ElementSpec, | ||
ElementEvents | ||
} from '../types' | ||
*/ | ||
var name$1 = 'MutationObserver'; | ||
// List of observers tags | ||
var observers = {}; | ||
@@ -185,2 +202,3 @@ | ||
* { | ||
* onMount: () => {}, | ||
* onUpdate: () => {}, | ||
@@ -194,3 +212,6 @@ * onUnmount: () => {}, | ||
function defineElement$1(elSpec, name, _ref) { | ||
function defineElement$1(elSpec /*: ElementSpec */ | ||
, name /*: string */ | ||
, _ref /*: ElementEvents */ | ||
) { | ||
var onUpdate = _ref.onUpdate, | ||
@@ -213,5 +234,5 @@ onUnmount = _ref.onUnmount; | ||
var observer = new window.MutationObserver(function (mutations) { | ||
each(mutations, function (mutation) { | ||
each(mutation.addedNodes, function (node) { | ||
checkForMount(node, name, onUpdate, onUnmount); | ||
each(mutations, function (mutation /*: { addedNodes: HTMLCollection<*> } */) { | ||
each(mutation.addedNodes, function (node /*: Element */) { | ||
checkForMount(node, name, { onUpdate: onUpdate, onUnmount: onUnmount }); | ||
}); | ||
@@ -229,12 +250,20 @@ }); | ||
function checkForMount(node, name, onUpdate, onUnmount) { | ||
/** | ||
* Checks if this new element should fire an `onUpdate` hook. | ||
* Recurses down to its descendant nodes. | ||
*/ | ||
function checkForMount(node /*: Element */ | ||
, name /*: string */ | ||
, events /*: ElementEvents */ | ||
) { | ||
if (node.nodeName.toLowerCase() === name) { | ||
// It's a match! | ||
onUpdate(node, node); | ||
observeForUpdates(node, onUpdate); | ||
observeForRemoval(node, onUnmount); | ||
events.onUpdate(node, node); | ||
observeForUpdates(node, events); | ||
observeForRemoval(node, events); | ||
} else if (node.children && node.children.length) { | ||
// Recurse down into the other additions | ||
each(node.children, function (subnode) { | ||
checkForMount(subnode, name, onUpdate, onUnmount); | ||
each(node.children, function (subnode /*: Element */) { | ||
checkForMount(subnode, name, events); | ||
}); | ||
@@ -248,7 +277,11 @@ } | ||
function observeForUpdates(node /*: Element */, onUpdate) { | ||
function observeForUpdates(node /*: Element */ | ||
, _ref2 /*: ElementEvents */ | ||
) { | ||
var onMount = _ref2.onMount; | ||
var observer = new window.MutationObserver(function (mutations) { | ||
each(mutations, function (mutation) { | ||
each(mutations, function (mutation /*: { target: Element } */) { | ||
var node = mutation.target; | ||
onUpdate(node, node); | ||
onMount(node, node); | ||
}); | ||
@@ -264,8 +297,12 @@ }); | ||
function observeForRemoval(node /*: Element */, onUnmount) { | ||
function observeForRemoval(node /*: Element */ | ||
, _ref3 /*: ElementEvents */ | ||
) { | ||
var onUnmount = _ref3.onUnmount; | ||
var parent = node.parentNode; | ||
var observer = new window.MutationObserver(function (mutations) { | ||
each(mutations, function (mutation) { | ||
each(mutation.removedNodes, function (subnode) { | ||
each(mutations, function (mutation /*: { removedNodes: HTMLCollection<*> } */) { | ||
each(mutation.removedNodes, function (subnode /*: Element */) { | ||
if (node !== subnode) return; | ||
@@ -289,3 +326,5 @@ observer.disconnect(parent); | ||
function each(list, fn) { | ||
function each /*:: <Item> */(list /*: Array<Item> | HTMLCollection<*> */ | ||
, fn /*: Item => any */ | ||
) { | ||
for (var i = 0, len = list.length; i < len; i++) { | ||
@@ -313,11 +352,19 @@ fn(list[i]); | ||
function isValidName(name /*: string */) /*: boolean */{ | ||
return name.indexOf('-') !== -1 && name.match(/^[a-z][a-z0-9-]*$/); | ||
return !!(name.indexOf('-') !== -1 && name.match(/^[a-z][a-z0-9-]*$/)); | ||
} | ||
var name$1 = 'MutationObserver'; | ||
/** | ||
* Shadow DOM is not supported with the Mutation Observer strategy. | ||
*/ | ||
var MutationAdapter = /*#__PURE__*/Object.freeze({ | ||
function supportsShadow$1() { | ||
return false; | ||
} | ||
var MutationObserverStrategy = /*#__PURE__*/Object.freeze({ | ||
name: name$1, | ||
observers: observers, | ||
isSupported: isSupported$1, | ||
defineElement: defineElement$1, | ||
name: name$1 | ||
supportsShadow: supportsShadow$1 | ||
}); | ||
@@ -329,2 +376,9 @@ | ||
function mount(elSpec /*: ElementSpec */ | ||
, mountPoint /*: Element */ | ||
, props /*: {} */ | ||
) { | ||
return update(elSpec, mountPoint, props); | ||
} | ||
/** | ||
@@ -355,2 +409,8 @@ * Updates a custom element by calling `ReactDOM.render()`. | ||
var ReactAdapter = /*#__PURE__*/Object.freeze({ | ||
mount: mount, | ||
update: update, | ||
unmount: unmount | ||
}); | ||
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; }; | ||
@@ -360,30 +420,36 @@ | ||
import type { | ||
Adapter, | ||
Component, | ||
PropertyMap, | ||
Defaults, | ||
ElementMap, | ||
Defaults, | ||
ElementSpec | ||
ElementSpec, | ||
PropertyMap | ||
} from './lib/types' | ||
*/ | ||
/* | ||
* Detect what API can be used; die otherwise. | ||
*/ | ||
var Adapter = isSupported() ? ElementsAdapter : isSupported$1() ? MutationAdapter : null; | ||
if (!Adapter) { | ||
console.warn("Remount: This browser doesn't support the " + 'MutationObserver API or the Custom Elements API. Including ' + 'polyfills might fix this. Remount elements will not work. ' + 'https://github.com/rstacruz/remount'); | ||
} | ||
/** | ||
* Inspect `Remount.adapterName` to see what adapter's being used. | ||
* Detect what API can be used. | ||
* | ||
* @example | ||
* import * as Remount from 'remount' | ||
* console.log(Remount.adapterName) | ||
* Remount.getStrategy().name | ||
*/ | ||
var adapterName = Adapter && Adapter.name; | ||
function getStrategy() { | ||
// $FlowFixMe$ obviously | ||
if (getStrategy._result !== undefined) { | ||
return getStrategy._result; | ||
} | ||
var Strategy = [CustomElementsStrategy, MutationObserverStrategy].reduce(function (result, strat) { | ||
return result || strat.isSupported() && strat; | ||
}, null); | ||
if (!Strategy) { | ||
console.warn("Remount: This browser doesn't support the " + 'MutationObserver API or the Custom Elements API. Including ' + 'polyfills might fix this. Remount elements will not work. ' + 'https://github.com/rstacruz/remount'); | ||
} | ||
getStrategy._result = Strategy; | ||
return Strategy; | ||
} | ||
/** | ||
@@ -405,3 +471,4 @@ * Registers custom elements and links them to React components. | ||
) { | ||
if (!Adapter) return; | ||
var Strategy = getStrategy(); | ||
if (!Strategy) return; | ||
@@ -413,10 +480,16 @@ Object.keys(components).forEach(function (name$$1 /*: string */) { | ||
var adapter /*: Adapter */ = elSpec.adapter || ReactAdapter; | ||
// Define a custom element. | ||
Adapter.defineElement(elSpec, name$$1, { | ||
Strategy.defineElement(elSpec, name$$1, { | ||
onMount: function onMount(element /*: Element */, mountPoint /*: Element */) { | ||
var props = getProps(element, elSpec.attributes); | ||
adapter.mount(elSpec, mountPoint, props); | ||
}, | ||
onUpdate: function onUpdate(element /*: Element */, mountPoint /*: Element */) { | ||
var props = getProps(element, elSpec.attributes); | ||
update(elSpec, mountPoint, props); | ||
adapter.update(elSpec, mountPoint, props); | ||
}, | ||
onUnmount: function onUnmount(element /*: Element */, mountPoint /*: Element */) { | ||
unmount(elSpec, mountPoint); | ||
adapter.unmount(elSpec, mountPoint); | ||
} | ||
@@ -459,3 +532,3 @@ }); | ||
var names /*: Array<string> */ = attributes || []; | ||
var names = attributes || []; | ||
return names.reduce(function (result /*: PropertyMap */, attribute /*: string */) { | ||
@@ -467,3 +540,3 @@ result[attribute] = element.getAttribute(attribute); | ||
exports.adapterName = adapterName; | ||
exports.getStrategy = getStrategy; | ||
exports.define = define; | ||
@@ -470,0 +543,0 @@ |
@@ -1,1 +0,1 @@ | ||
(function(a,b){'object'==typeof exports&&'undefined'!=typeof module?b(exports,require('react'),require('react-dom')):'function'==typeof define&&define.amd?define(['exports','react','react-dom'],b):b(a.Remount={},a.React,a.ReactDOM)})(this,function(a,b,c){'use strict';function d(){if(!(u||void 0===window.Reflect||void 0===window.customElements||window.customElements.hasOwnProperty('polyfillWrapFlushCallback'))){var b=HTMLElement;window.HTMLElement=function(){return Reflect.construct(b,[],this.constructor)},HTMLElement.prototype=b.prototype,HTMLElement.prototype.constructor=HTMLElement,Object.setPrototypeOf(HTMLElement,b),u=!0}}function e(a){if(Array.isArray(a)){for(var b=0,c=Array(a.length);b<a.length;b++)c[b]=a[b];return c}return Array.from(a)}function f(a,b){if(!(a instanceof b))throw new TypeError('Cannot call a class as a function')}function g(a,b){if(!a)throw new ReferenceError('this hasn\'t been initialised - super() hasn\'t been called');return b&&('object'==typeof b||'function'==typeof b)?b:a}function h(a,b){if('function'!=typeof b&&null!==b)throw new TypeError('Super expression must either be null or a function, not '+typeof b);a.prototype=Object.create(b&&b.prototype,{constructor:{value:a,enumerable:!1,writable:!0,configurable:!0}}),b&&(Object.setPrototypeOf?Object.setPrototypeOf(a,b):a.__proto__=b)}function i(){return window.customElements&&window.customElements.define}function j(a,b){var c=b.shadow;if(c&&a.attachShadow){var d=document.createElement('span');return a.attachShadow({mode:'open'}).appendChild(d),d}return a}function k(){return!!window.MutationObserver}function l(a,b,c,d){a.nodeName.toLowerCase()===b?(c(a,a),m(a,c),n(a,d)):a.children&&a.children.length&&o(a.children,function(a){l(a,b,c,d)})}function m(a,b){var c=new window.MutationObserver(function(a){o(a,function(a){var c=a.target;b(c,c)})});c.observe(a,{attributes:!0})}function n(a,b){var c=a.parentNode,d=new window.MutationObserver(function(e){o(e,function(e){o(e.removedNodes,function(e){a!==e||(d.disconnect(c),b(a,a))})})});d.observe(c,{childList:!0,subtree:!0})}function o(a,b){for(var c=0,d=a.length;c<d;c++)b(a[c])}function p(a){return-1!==a.indexOf('-')&&a.match(/^[a-z][a-z0-9-]*$/)}function q(a,d,e){var f=a.component,g=a.attributes,h=b.createElement(f,e);c.render(h,d)}function r(a,b){c.unmountComponentAtNode(b)}function s(a){return'object'===('undefined'==typeof a?'undefined':z(a))&&a.component?a:{component:a}}function t(a,b){var c=a.getAttribute('props-json');if(c)return JSON.parse(c);return(b||[]).reduce(function(b,c){return b[c]=a.getAttribute(c),b},{})}c=c&&c.hasOwnProperty('default')?c['default']:c;var u=void 0,v=function(){function a(a,b){for(var c,d=0;d<b.length;d++)c=b[d],c.enumerable=c.enumerable||!1,c.configurable=!0,'value'in c&&(c.writable=!0),Object.defineProperty(a,c.key,c)}return function(b,c,d){return c&&a(b.prototype,c),d&&a(b,d),b}}(),w=Object.freeze({defineElement:function(a,b,c){var i=c.onUpdate,k=c.onUnmount;d();var l=a.attributes||[],m=function(b){function c(){return f(this,c),g(this,(c.__proto__||Object.getPrototypeOf(c)).apply(this,arguments))}return h(c,b),v(c,[{key:'connectedCallback',value:function(){this._mountPoint=j(this,a),i(this,this._mountPoint)}},{key:'disconnectedCallback',value:function(){this._mountPoint&&k(this,this._mountPoint)}},{key:'attributeChangedCallback',value:function(){this._mountPoint&&i(this,this._mountPoint)}}],[{key:'observedAttributes',get:function(){return['props-json'].concat(e(l))}}]),c}(window.HTMLElement);a.quiet&&window.customElements.get(b)||window.customElements.define(b,m)},isSupported:i,name:'CustomElements'}),x={},y=Object.freeze({isSupported:k,defineElement:function(a,b,c){var d=c.onUpdate,e=c.onUnmount;if(b=b.toLowerCase(),!p(b)){if(a.quiet)return;throw new Error('Remount: "'+b+'" is not a valid custom element name')}if(x[b]){if(a.quiet)return;throw new Error('Remount: "'+b+'" is already registered')}var f=new window.MutationObserver(function(a){o(a,function(a){o(a.addedNodes,function(a){l(a,b,d,e)})})});f.observe(document.body,{childList:!0,subtree:!0}),x[b]=!0},name:'MutationObserver'}),z='function'==typeof Symbol&&'symbol'==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&'function'==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?'symbol':typeof a},A=i()?w:k()?y:null;A||console.warn('Remount: This browser doesn\'t support the MutationObserver API or the Custom Elements API. Including polyfills might fix this. Remount elements will not work. https://github.com/rstacruz/remount');var B=A&&A.name;a.adapterName=B,a.define=function(a,b){A&&Object.keys(a).forEach(function(c){var d=Object.assign({},b,s(a[c]));A.defineElement(d,c,{onUpdate:function(a,b){var c=t(a,d.attributes);q(d,b,c)},onUnmount:function(a,b){r(d,b)}})})},Object.defineProperty(a,'__esModule',{value:!0})}); | ||
(function(a,b){'object'==typeof exports&&'undefined'!=typeof module?b(exports,require('react'),require('react-dom')):'function'==typeof define&&define.amd?define(['exports','react','react-dom'],b):b(a.Remount={},a.React,a.ReactDOM)})(this,function(a,b,c){'use strict';function d(){if(!(window.HTMLElement&&window.HTMLElement._babelES5Adapter||void 0===window.Reflect||void 0===window.customElements||window.customElements.hasOwnProperty('polyfillWrapFlushCallback'))){var b=HTMLElement;window.HTMLElement=function(){return Reflect.construct(b,[],this.constructor)},HTMLElement.prototype=b.prototype,HTMLElement.prototype.constructor=HTMLElement,Object.setPrototypeOf(HTMLElement,b),HTMLElement._babelES5Adapter=!0}}function e(a){if(Array.isArray(a)){for(var b=0,c=Array(a.length);b<a.length;b++)c[b]=a[b];return c}return Array.from(a)}function f(a,b){if(!(a instanceof b))throw new TypeError('Cannot call a class as a function')}function g(a,b){if(!a)throw new ReferenceError('this hasn\'t been initialised - super() hasn\'t been called');return b&&('object'==typeof b||'function'==typeof b)?b:a}function h(a,b){if('function'!=typeof b&&null!==b)throw new TypeError('Super expression must either be null or a function, not '+typeof b);a.prototype=Object.create(b&&b.prototype,{constructor:{value:a,enumerable:!1,writable:!0,configurable:!0}}),b&&(Object.setPrototypeOf?Object.setPrototypeOf(a,b):a.__proto__=b)}function i(a,b){var c=b.shadow;if(c&&a.attachShadow){var d=document.createElement('span');return a.attachShadow({mode:'open'}).appendChild(d),d}return a}function j(a,b,c){a.nodeName.toLowerCase()===b?(c.onUpdate(a,a),k(a,c),l(a,c)):a.children&&a.children.length&&m(a.children,function(a){j(a,b,c)})}function k(a,b){var c=b.onMount,d=new window.MutationObserver(function(a){m(a,function(a){var b=a.target;c(b,b)})});d.observe(a,{attributes:!0})}function l(a,b){var c=b.onUnmount,d=a.parentNode,e=new window.MutationObserver(function(b){m(b,function(b){m(b.removedNodes,function(b){a!==b||(e.disconnect(d),c(a,a))})})});e.observe(d,{childList:!0,subtree:!0})}function m(a,b){for(var c=0,d=a.length;c<d;c++)b(a[c])}function n(a){return!!(-1!==a.indexOf('-')&&a.match(/^[a-z][a-z0-9-]*$/))}function o(a,d,e){var f=a.component,g=a.attributes,h=b.createElement(f,e);c.render(h,d)}function p(a,b){c.unmountComponentAtNode(b)}function q(){if(void 0!==q._result)return q._result;var a=[u,w].reduce(function(a,b){return a||b.isSupported()&&b},null);return a||console.warn('Remount: This browser doesn\'t support the MutationObserver API or the Custom Elements API. Including polyfills might fix this. Remount elements will not work. https://github.com/rstacruz/remount'),q._result=a,a}function r(a){return'object'===('undefined'==typeof a?'undefined':y(a))&&a.component?a:{component:a}}function s(a,b){var c=a.getAttribute('props-json');if(c)return JSON.parse(c);return(b||[]).reduce(function(b,c){return b[c]=a.getAttribute(c),b},{})}c=c&&c.hasOwnProperty('default')?c['default']:c;var t=function(){function a(a,b){for(var c,d=0;d<b.length;d++)c=b[d],c.enumerable=c.enumerable||!1,c.configurable=!0,'value'in c&&(c.writable=!0),Object.defineProperty(a,c.key,c)}return function(b,c,d){return c&&a(b.prototype,c),d&&a(b,d),b}}(),u=Object.freeze({name:'CustomElements',defineElement:function(a,b,c){var j=c.onUpdate,k=c.onUnmount,l=c.onMount;d();var m=a.attributes||[],n=function(b){function c(){return f(this,c),g(this,(c.__proto__||Object.getPrototypeOf(c)).apply(this,arguments))}return h(c,b),t(c,[{key:'connectedCallback',value:function(){this._mountPoint=i(this,a),l(this,this._mountPoint)}},{key:'disconnectedCallback',value:function(){this._mountPoint&&k(this,this._mountPoint)}},{key:'attributeChangedCallback',value:function(){this._mountPoint&&j(this,this._mountPoint)}}],[{key:'observedAttributes',get:function(){return['props-json'].concat(e(m))}}]),c}(window.HTMLElement);a.quiet&&window.customElements.get(b)||window.customElements.define(b,n)},isSupported:function(){return window.customElements&&window.customElements.define},supportsShadow:function(){return!!(document&&document.body&&document.body.attachShadow)}}),v={},w=Object.freeze({name:'MutationObserver',observers:v,isSupported:function(){return!!window.MutationObserver},defineElement:function(a,b,c){var d=c.onUpdate,e=c.onUnmount;if(b=b.toLowerCase(),!n(b)){if(a.quiet)return;throw new Error('Remount: "'+b+'" is not a valid custom element name')}if(v[b]){if(a.quiet)return;throw new Error('Remount: "'+b+'" is already registered')}var f=new window.MutationObserver(function(a){m(a,function(a){m(a.addedNodes,function(a){j(a,b,{onUpdate:d,onUnmount:e})})})});f.observe(document.body,{childList:!0,subtree:!0}),v[b]=!0},supportsShadow:function(){return!1}}),x=Object.freeze({mount:function(a,b,c){return o(a,b,c)},update:o,unmount:p}),y='function'==typeof Symbol&&'symbol'==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&'function'==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?'symbol':typeof a};a.getStrategy=q,a.define=function(a,b){var c=q();c&&Object.keys(a).forEach(function(d){var e=Object.assign({},b,r(a[d])),f=e.adapter||x;c.defineElement(e,d,{onMount:function(a,b){var c=s(a,e.attributes);f.mount(e,b,c)},onUpdate:function(a,b){var c=s(a,e.attributes);f.update(e,b,c)},onUnmount:function(a,b){f.unmount(e,b)}})})},Object.defineProperty(a,'__esModule',{value:!0})}); |
@@ -11,4 +11,2 @@ (function (global, factory) { | ||
let injected; | ||
/* | ||
@@ -21,3 +19,3 @@ * Adapted from https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs@2.0.4/custom-elements-es5-adapter.js | ||
if ( | ||
injected || | ||
(window.HTMLElement && window.HTMLElement._babelES5Adapter) || | ||
void 0 === window.Reflect || | ||
@@ -38,3 +36,3 @@ void 0 === window.customElements || | ||
Object.setPrototypeOf(HTMLElement, a); | ||
injected = true; | ||
HTMLElement._babelES5Adapter = true; | ||
} | ||
@@ -53,5 +51,7 @@ | ||
ElementEvents | ||
} from './types' | ||
} from '../types' | ||
*/ | ||
const name = 'CustomElements'; | ||
/** | ||
@@ -78,3 +78,3 @@ * Registers a custom element. | ||
name /*: string */, | ||
{ onUpdate, onUnmount } /*: ElementEvents */ | ||
{ onUpdate, onUnmount, onMount } /*: ElementEvents */ | ||
) { | ||
@@ -91,3 +91,3 @@ inject(); | ||
this._mountPoint = createMountPoint(this, elSpec); | ||
onUpdate(this, this._mountPoint); | ||
onMount(this, this._mountPoint); | ||
} | ||
@@ -137,13 +137,30 @@ | ||
const name = 'CustomElements'; | ||
/** | ||
* Check if Shadow DOM is supported. | ||
*/ | ||
var ElementsAdapter = /*#__PURE__*/Object.freeze({ | ||
function supportsShadow () { | ||
return !!(document && document.body && document.body.attachShadow) | ||
} | ||
var CustomElementsStrategy = /*#__PURE__*/Object.freeze({ | ||
name: name, | ||
defineElement: defineElement, | ||
isSupported: isSupported, | ||
name: name | ||
supportsShadow: supportsShadow | ||
}); | ||
/* List of observers tags */ | ||
let observers = {}; | ||
// @flow | ||
/*:: | ||
import type { | ||
ElementSpec, | ||
ElementEvents | ||
} from '../types' | ||
*/ | ||
const name$1 = 'MutationObserver'; | ||
// List of observers tags | ||
const observers = {}; | ||
function isSupported$1 () { | ||
@@ -161,2 +178,3 @@ return !!window.MutationObserver | ||
* { | ||
* onMount: () => {}, | ||
* onUpdate: () => {}, | ||
@@ -170,3 +188,7 @@ * onUnmount: () => {}, | ||
function defineElement$1 (elSpec, name, { onUpdate, onUnmount }) { | ||
function defineElement$1 ( | ||
elSpec /*: ElementSpec */, | ||
name /*: string */, | ||
{ onUpdate, onUnmount } /*: ElementEvents */ | ||
) { | ||
name = name.toLowerCase(); | ||
@@ -186,5 +208,5 @@ | ||
const observer = new window.MutationObserver(mutations => { | ||
each(mutations, mutation => { | ||
each(mutation.addedNodes, node => { | ||
checkForMount(node, name, onUpdate, onUnmount); | ||
each(mutations, (mutation /*: { addedNodes: HTMLCollection<*> } */) => { | ||
each(mutation.addedNodes, (node /*: Element */) => { | ||
checkForMount(node, name, { onUpdate, onUnmount }); | ||
}); | ||
@@ -202,12 +224,21 @@ }); | ||
function checkForMount (node, name, onUpdate, onUnmount) { | ||
/** | ||
* Checks if this new element should fire an `onUpdate` hook. | ||
* Recurses down to its descendant nodes. | ||
*/ | ||
function checkForMount ( | ||
node /*: Element */, | ||
name /*: string */, | ||
events /*: ElementEvents */ | ||
) { | ||
if (node.nodeName.toLowerCase() === name) { | ||
// It's a match! | ||
onUpdate(node, node); | ||
observeForUpdates(node, onUpdate); | ||
observeForRemoval(node, onUnmount); | ||
events.onUpdate(node, node); | ||
observeForUpdates(node, events); | ||
observeForRemoval(node, events); | ||
} else if (node.children && node.children.length) { | ||
// Recurse down into the other additions | ||
each(node.children, subnode => { | ||
checkForMount(subnode, name, onUpdate, onUnmount); | ||
each(node.children, (subnode /*: Element */) => { | ||
checkForMount(subnode, name, events); | ||
}); | ||
@@ -221,7 +252,10 @@ } | ||
function observeForUpdates (node /*: Element */, onUpdate) { | ||
function observeForUpdates ( | ||
node /*: Element */, | ||
{ onMount } /*: ElementEvents */ | ||
) { | ||
const observer = new window.MutationObserver(mutations => { | ||
each(mutations, mutation => { | ||
each(mutations, (mutation /*: { target: Element } */) => { | ||
const node = mutation.target; | ||
onUpdate(node, node); | ||
onMount(node, node); | ||
}); | ||
@@ -237,8 +271,11 @@ }); | ||
function observeForRemoval (node /*: Element */, onUnmount) { | ||
function observeForRemoval ( | ||
node /*: Element */, | ||
{ onUnmount } /*: ElementEvents */ | ||
) { | ||
const parent = node.parentNode; | ||
const observer = new window.MutationObserver(mutations => { | ||
each(mutations, mutation => { | ||
each(mutation.removedNodes, subnode => { | ||
each(mutations, (mutation /*: { removedNodes: HTMLCollection<*> } */) => { | ||
each(mutation.removedNodes, (subnode /*: Element */) => { | ||
if (node !== subnode) return | ||
@@ -262,3 +299,6 @@ observer.disconnect(parent); | ||
function each (list, fn) { | ||
function each /*:: <Item> */( | ||
list /*: Array<Item> | HTMLCollection<*> */, | ||
fn /*: Item => any */ | ||
) { | ||
for (let i = 0, len = list.length; i < len; i++) { | ||
@@ -286,11 +326,19 @@ fn(list[i]); | ||
function isValidName (name /*: string */) /*: boolean */ { | ||
return name.indexOf('-') !== -1 && name.match(/^[a-z][a-z0-9-]*$/) | ||
return !!(name.indexOf('-') !== -1 && name.match(/^[a-z][a-z0-9-]*$/)) | ||
} | ||
const name$1 = 'MutationObserver'; | ||
/** | ||
* Shadow DOM is not supported with the Mutation Observer strategy. | ||
*/ | ||
var MutationAdapter = /*#__PURE__*/Object.freeze({ | ||
function supportsShadow$1 () { | ||
return false | ||
} | ||
var MutationObserverStrategy = /*#__PURE__*/Object.freeze({ | ||
name: name$1, | ||
observers: observers, | ||
isSupported: isSupported$1, | ||
defineElement: defineElement$1, | ||
name: name$1 | ||
supportsShadow: supportsShadow$1 | ||
}); | ||
@@ -304,2 +352,10 @@ | ||
function mount ( | ||
elSpec /*: ElementSpec */, | ||
mountPoint /*: Element */, | ||
props /*: {} */ | ||
) { | ||
return update(elSpec, mountPoint, props) | ||
} | ||
/** | ||
@@ -328,2 +384,8 @@ * Updates a custom element by calling `ReactDOM.render()`. | ||
var ReactAdapter = /*#__PURE__*/Object.freeze({ | ||
mount: mount, | ||
update: update, | ||
unmount: unmount | ||
}); | ||
// @flow | ||
@@ -333,38 +395,43 @@ | ||
import type { | ||
Adapter, | ||
Component, | ||
PropertyMap, | ||
Defaults, | ||
ElementMap, | ||
Defaults, | ||
ElementSpec | ||
ElementSpec, | ||
PropertyMap | ||
} from './lib/types' | ||
*/ | ||
/* | ||
* Detect what API can be used; die otherwise. | ||
/** | ||
* Detect what API can be used. | ||
* | ||
* @example | ||
* Remount.getStrategy().name | ||
*/ | ||
const Adapter = isSupported() | ||
? ElementsAdapter | ||
: isSupported$1() | ||
? MutationAdapter | ||
: null; | ||
function getStrategy () { | ||
// $FlowFixMe$ obviously | ||
if (getStrategy._result !== undefined) { | ||
return getStrategy._result | ||
} | ||
if (!Adapter) { | ||
console.warn( | ||
"Remount: This browser doesn't support the " + | ||
'MutationObserver API or the Custom Elements API. Including ' + | ||
'polyfills might fix this. Remount elements will not work. ' + | ||
'https://github.com/rstacruz/remount' | ||
const Strategy = [CustomElementsStrategy, MutationObserverStrategy].reduce( | ||
(result, strat) => { | ||
return result || (strat.isSupported() && strat) | ||
}, | ||
null | ||
); | ||
} | ||
/** | ||
* Inspect `Remount.adapterName` to see what adapter's being used. | ||
* | ||
* @example | ||
* import * as Remount from 'remount' | ||
* console.log(Remount.adapterName) | ||
*/ | ||
if (!Strategy) { | ||
console.warn( | ||
"Remount: This browser doesn't support the " + | ||
'MutationObserver API or the Custom Elements API. Including ' + | ||
'polyfills might fix this. Remount elements will not work. ' + | ||
'https://github.com/rstacruz/remount' | ||
); | ||
} | ||
const adapterName = Adapter && Adapter.name; | ||
getStrategy._result = Strategy; | ||
return Strategy | ||
} | ||
@@ -388,3 +455,4 @@ /** | ||
) { | ||
if (!Adapter) return | ||
const Strategy = getStrategy(); | ||
if (!Strategy) return | ||
@@ -400,11 +468,18 @@ Object.keys(components).forEach((name$$1 /*: string */) => { | ||
const adapter /*: Adapter */ = elSpec.adapter || ReactAdapter; | ||
// Define a custom element. | ||
Adapter.defineElement(elSpec, name$$1, { | ||
Strategy.defineElement(elSpec, name$$1, { | ||
onMount (element /*: Element */, mountPoint /*: Element */) { | ||
const props = getProps(element, elSpec.attributes); | ||
adapter.mount(elSpec, mountPoint, props); | ||
}, | ||
onUpdate (element /*: Element */, mountPoint /*: Element */) { | ||
const props = getProps(element, elSpec.attributes); | ||
update(elSpec, mountPoint, props); | ||
adapter.update(elSpec, mountPoint, props); | ||
}, | ||
onUnmount (element /*: Element */, mountPoint /*: Element */) { | ||
unmount(elSpec, mountPoint); | ||
adapter.unmount(elSpec, mountPoint); | ||
} | ||
@@ -448,3 +523,3 @@ }); | ||
const names /*: Array<string> */ = attributes || []; | ||
const names = attributes || []; | ||
return names.reduce((result /*: PropertyMap */, attribute /*: string */) => { | ||
@@ -456,3 +531,3 @@ result[attribute] = element.getAttribute(attribute); | ||
exports.adapterName = adapterName; | ||
exports.getStrategy = getStrategy; | ||
exports.define = define; | ||
@@ -459,0 +534,0 @@ |
@@ -1,1 +0,1 @@ | ||
(function(a,b){'object'==typeof exports&&'undefined'!=typeof module?b(exports,require('react'),require('react-dom')):'function'==typeof define&&define.amd?define(['exports','react','react-dom'],b):b(a.Remount={},a.React,a.ReactDOM)})(this,function(a,b,c){'use strict';function d(){if(q||void 0===window.Reflect||void 0===window.customElements||window.customElements.hasOwnProperty('polyfillWrapFlushCallback'))return;const b=HTMLElement;window.HTMLElement=function(){return Reflect.construct(b,[],this.constructor)},HTMLElement.prototype=b.prototype,HTMLElement.prototype.constructor=HTMLElement,Object.setPrototypeOf(HTMLElement,b),q=!0}function e(){return window.customElements&&window.customElements.define}function f(a,{shadow:b}){if(b&&a.attachShadow){const b=document.createElement('span');return a.attachShadow({mode:'open'}).appendChild(b),b}return a}function g(){return!!window.MutationObserver}function h(a,b,c,d){a.nodeName.toLowerCase()===b?(c(a,a),i(a,c),j(a,d)):a.children&&a.children.length&&k(a.children,a=>{h(a,b,c,d)})}function i(a,b){const c=new window.MutationObserver(a=>{k(a,a=>{const c=a.target;b(c,c)})});c.observe(a,{attributes:!0})}function j(a,b){const c=a.parentNode,d=new window.MutationObserver(e=>{k(e,e=>{k(e.removedNodes,e=>{a!==e||(d.disconnect(c),b(a,a))})})});d.observe(c,{childList:!0,subtree:!0})}function k(a,b){for(let c=0,d=a.length;c<d;c++)b(a[c])}function l(a){return-1!==a.indexOf('-')&&a.match(/^[a-z][a-z0-9-]*$/)}function m({component:a,attributes:d},e,f){const g=b.createElement(a,f);c.render(g,e)}function n(a,b){c.unmountComponentAtNode(b)}function o(a){return'object'==typeof a&&a.component?a:{component:a}}function p(a,b){const c=a.getAttribute('props-json');if(c)return JSON.parse(c);return(b||[]).reduce((b,c)=>(b[c]=a.getAttribute(c),b),{})}c=c&&c.hasOwnProperty('default')?c['default']:c;let q;var r=Object.freeze({defineElement:function(a,b,{onUpdate:c,onUnmount:e}){d();const g=a.attributes||[];class h extends window.HTMLElement{static get observedAttributes(){return['props-json',...g]}connectedCallback(){this._mountPoint=f(this,a),c(this,this._mountPoint)}disconnectedCallback(){this._mountPoint&&e(this,this._mountPoint)}attributeChangedCallback(){this._mountPoint&&c(this,this._mountPoint)}}a.quiet&&window.customElements.get(b)||window.customElements.define(b,h)},isSupported:e,name:'CustomElements'});let s={};var t=Object.freeze({isSupported:g,defineElement:function(a,b,{onUpdate:c,onUnmount:d}){if(b=b.toLowerCase(),!l(b)){if(a.quiet)return;throw new Error(`Remount: "${b}" is not a valid custom element name`)}if(s[b]){if(a.quiet)return;throw new Error(`Remount: "${b}" is already registered`)}const e=new window.MutationObserver(a=>{k(a,a=>{k(a.addedNodes,a=>{h(a,b,c,d)})})});e.observe(document.body,{childList:!0,subtree:!0}),s[b]=!0},name:'MutationObserver'});const u=e()?r:g()?t:null;u||console.warn('Remount: This browser doesn\'t support the MutationObserver API or the Custom Elements API. Including polyfills might fix this. Remount elements will not work. https://github.com/rstacruz/remount');const v=u&&u.name;a.adapterName=v,a.define=function(a,b){u&&Object.keys(a).forEach((c)=>{const d=Object.assign({},b,o(a[c]));u.defineElement(d,c,{onUpdate(a,b){const c=p(a,d.attributes);m(d,b,c)},onUnmount(a,b){n(d,b)}})})},Object.defineProperty(a,'__esModule',{value:!0})}); | ||
(function(a,b){'object'==typeof exports&&'undefined'!=typeof module?b(exports,require('react'),require('react-dom')):'function'==typeof define&&define.amd?define(['exports','react','react-dom'],b):b(a.Remount={},a.React,a.ReactDOM)})(this,function(a,b,c){'use strict';function d(){if(window.HTMLElement&&window.HTMLElement._babelES5Adapter||void 0===window.Reflect||void 0===window.customElements||window.customElements.hasOwnProperty('polyfillWrapFlushCallback'))return;const b=HTMLElement;window.HTMLElement=function(){return Reflect.construct(b,[],this.constructor)},HTMLElement.prototype=b.prototype,HTMLElement.prototype.constructor=HTMLElement,Object.setPrototypeOf(HTMLElement,b),HTMLElement._babelES5Adapter=!0}function e(a,{shadow:b}){if(b&&a.attachShadow){const b=document.createElement('span');return a.attachShadow({mode:'open'}).appendChild(b),b}return a}function f(a,b,c){a.nodeName.toLowerCase()===b?(c.onUpdate(a,a),g(a,c),h(a,c)):a.children&&a.children.length&&i(a.children,(a)=>{f(a,b,c)})}function g(a,{onMount:b}){const c=new window.MutationObserver(a=>{i(a,(a)=>{const c=a.target;b(c,c)})});c.observe(a,{attributes:!0})}function h(a,{onUnmount:b}){const c=a.parentNode,d=new window.MutationObserver(e=>{i(e,(e)=>{i(e.removedNodes,(e)=>{a!==e||(d.disconnect(c),b(a,a))})})});d.observe(c,{childList:!0,subtree:!0})}function i(a,b){for(let c=0,d=a.length;c<d;c++)b(a[c])}function j(a){return!!(-1!==a.indexOf('-')&&a.match(/^[a-z][a-z0-9-]*$/))}function k({component:a,attributes:d},e,f){const g=b.createElement(a,f);c.render(g,e)}function l(a,b){c.unmountComponentAtNode(b)}function m(){if(void 0!==m._result)return m._result;const a=[p,r].reduce((a,b)=>a||b.isSupported()&&b,null);return a||console.warn('Remount: This browser doesn\'t support the MutationObserver API or the Custom Elements API. Including polyfills might fix this. Remount elements will not work. https://github.com/rstacruz/remount'),m._result=a,a}function n(a){return'object'==typeof a&&a.component?a:{component:a}}function o(a,b){const c=a.getAttribute('props-json');if(c)return JSON.parse(c);return(b||[]).reduce((b,c)=>(b[c]=a.getAttribute(c),b),{})}c=c&&c.hasOwnProperty('default')?c['default']:c;var p=Object.freeze({name:'CustomElements',defineElement:function(a,b,{onUpdate:c,onUnmount:f,onMount:g}){d();const h=a.attributes||[];class i extends window.HTMLElement{static get observedAttributes(){return['props-json',...h]}connectedCallback(){this._mountPoint=e(this,a),g(this,this._mountPoint)}disconnectedCallback(){this._mountPoint&&f(this,this._mountPoint)}attributeChangedCallback(){this._mountPoint&&c(this,this._mountPoint)}}a.quiet&&window.customElements.get(b)||window.customElements.define(b,i)},isSupported:function(){return window.customElements&&window.customElements.define},supportsShadow:function(){return!!(document&&document.body&&document.body.attachShadow)}});const q={};var r=Object.freeze({name:'MutationObserver',observers:q,isSupported:function(){return!!window.MutationObserver},defineElement:function(a,b,{onUpdate:c,onUnmount:d}){if(b=b.toLowerCase(),!j(b)){if(a.quiet)return;throw new Error(`Remount: "${b}" is not a valid custom element name`)}if(q[b]){if(a.quiet)return;throw new Error(`Remount: "${b}" is already registered`)}const e=new window.MutationObserver(a=>{i(a,(a)=>{i(a.addedNodes,(a)=>{f(a,b,{onUpdate:c,onUnmount:d})})})});e.observe(document.body,{childList:!0,subtree:!0}),q[b]=!0},supportsShadow:function(){return!1}}),s=Object.freeze({mount:function(a,b,c){return k(a,b,c)},update:k,unmount:l});a.getStrategy=m,a.define=function(a,b){const c=m();c&&Object.keys(a).forEach((d)=>{const e=Object.assign({},b,n(a[d])),f=e.adapter||s;c.defineElement(e,d,{onMount(a,b){const c=o(a,e.attributes);f.mount(e,b,c)},onUpdate(a,b){const c=o(a,e.attributes);f.update(e,b,c)},onUnmount(a,b){f.unmount(e,b)}})})},Object.defineProperty(a,'__esModule',{value:!0})}); |
77
index.js
// @flow | ||
import * as ElementsAdapter from './lib/custom_elements' | ||
import * as MutationAdapter from './lib/mutation_observer' | ||
import * as CustomElementsStrategy from './lib/strategies/custom_elements' | ||
import * as MutationObserverStrategy from './lib/strategies/mutation_observer' | ||
import * as ReactAdapter from './lib/react' | ||
@@ -8,38 +8,43 @@ | ||
import type { | ||
Adapter, | ||
Component, | ||
PropertyMap, | ||
Defaults, | ||
ElementMap, | ||
Defaults, | ||
ElementSpec | ||
ElementSpec, | ||
PropertyMap | ||
} from './lib/types' | ||
*/ | ||
/* | ||
* Detect what API can be used; die otherwise. | ||
/** | ||
* Detect what API can be used. | ||
* | ||
* @example | ||
* Remount.getStrategy().name | ||
*/ | ||
const Adapter = ElementsAdapter.isSupported() | ||
? ElementsAdapter | ||
: MutationAdapter.isSupported() | ||
? MutationAdapter | ||
: null | ||
export function getStrategy () { | ||
// $FlowFixMe$ obviously | ||
if (getStrategy._result !== undefined) { | ||
return getStrategy._result | ||
} | ||
if (!Adapter) { | ||
console.warn( | ||
"Remount: This browser doesn't support the " + | ||
'MutationObserver API or the Custom Elements API. Including ' + | ||
'polyfills might fix this. Remount elements will not work. ' + | ||
'https://github.com/rstacruz/remount' | ||
const Strategy = [CustomElementsStrategy, MutationObserverStrategy].reduce( | ||
(result, strat) => { | ||
return result || (strat.isSupported() && strat) | ||
}, | ||
null | ||
) | ||
} | ||
/** | ||
* Inspect `Remount.adapterName` to see what adapter's being used. | ||
* | ||
* @example | ||
* import * as Remount from 'remount' | ||
* console.log(Remount.adapterName) | ||
*/ | ||
if (!Strategy) { | ||
console.warn( | ||
"Remount: This browser doesn't support the " + | ||
'MutationObserver API or the Custom Elements API. Including ' + | ||
'polyfills might fix this. Remount elements will not work. ' + | ||
'https://github.com/rstacruz/remount' | ||
) | ||
} | ||
export const adapterName = Adapter && Adapter.name | ||
getStrategy._result = Strategy | ||
return Strategy | ||
} | ||
@@ -63,3 +68,4 @@ /** | ||
) { | ||
if (!Adapter) return | ||
const Strategy = getStrategy() | ||
if (!Strategy) return | ||
@@ -75,11 +81,18 @@ Object.keys(components).forEach((name /*: string */) => { | ||
const adapter /*: Adapter */ = elSpec.adapter || ReactAdapter | ||
// Define a custom element. | ||
Adapter.defineElement(elSpec, name, { | ||
Strategy.defineElement(elSpec, name, { | ||
onMount (element /*: Element */, mountPoint /*: Element */) { | ||
const props = getProps(element, elSpec.attributes) | ||
adapter.mount(elSpec, mountPoint, props) | ||
}, | ||
onUpdate (element /*: Element */, mountPoint /*: Element */) { | ||
const props = getProps(element, elSpec.attributes) | ||
ReactAdapter.update(elSpec, mountPoint, props) | ||
adapter.update(elSpec, mountPoint, props) | ||
}, | ||
onUnmount (element /*: Element */, mountPoint /*: Element */) { | ||
ReactAdapter.unmount(elSpec, mountPoint) | ||
adapter.unmount(elSpec, mountPoint) | ||
} | ||
@@ -123,3 +136,3 @@ }) | ||
const names /*: Array<string> */ = attributes || [] | ||
const names = attributes || [] | ||
return names.reduce((result /*: PropertyMap */, attribute /*: string */) => { | ||
@@ -126,0 +139,0 @@ result[attribute] = element.getAttribute(attribute) |
{ | ||
"name": "remount", | ||
"description": "Mount React components to the DOM using custom elements", | ||
"version": "0.8.0", | ||
"version": "0.9.0", | ||
"author": "Rico Sta. Cruz <rstacruz@users.noreply.github.com>", | ||
@@ -6,0 +6,0 @@ "bugs": { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
66114
1475