From 9a2460d3cbea10d61e2cc9c1d013b476347d35ea Mon Sep 17 00:00:00 2001 From: Josh Thomas Date: Wed, 26 Jul 2017 11:39:17 -0500 Subject: [PATCH] chore(): moved stencil-fiber-demo into its own repo. --- packages/stencil-fiber-demo/package.json | 25 - .../stencil-fiber-demo/src/components/app.tsx | 53 - .../stencil-fiber-demo/src/components/dot.tsx | 52 - .../src/components/triangle.tsx | 51 - packages/stencil-fiber-demo/stencil.config.js | 5 - packages/stencil-fiber-demo/tsconfig.json | 36 - packages/stencil-fiber-demo/www/build/app.js | 44 - .../www/build/app.registry.json | 75 - .../www/build/app/app.core.ce.js | 2073 ----------------- .../www/build/app/app.core.js | 2064 ---------------- .../fiber-demo.fiber-dot.fiber-triangle.js | 146 -- packages/stencil-fiber-demo/www/index.html | 59 - packages/stencil-fiber-demo/www/perf.html | 57 - 13 files changed, 4740 deletions(-) delete mode 100644 packages/stencil-fiber-demo/package.json delete mode 100644 packages/stencil-fiber-demo/src/components/app.tsx delete mode 100644 packages/stencil-fiber-demo/src/components/dot.tsx delete mode 100644 packages/stencil-fiber-demo/src/components/triangle.tsx delete mode 100644 packages/stencil-fiber-demo/stencil.config.js delete mode 100644 packages/stencil-fiber-demo/tsconfig.json delete mode 100644 packages/stencil-fiber-demo/www/build/app.js delete mode 100644 packages/stencil-fiber-demo/www/build/app.registry.json delete mode 100644 packages/stencil-fiber-demo/www/build/app/app.core.ce.js delete mode 100644 packages/stencil-fiber-demo/www/build/app/app.core.js delete mode 100644 packages/stencil-fiber-demo/www/build/app/fiber-demo.fiber-dot.fiber-triangle.js delete mode 100644 packages/stencil-fiber-demo/www/index.html delete mode 100644 packages/stencil-fiber-demo/www/perf.html diff --git a/packages/stencil-fiber-demo/package.json b/packages/stencil-fiber-demo/package.json deleted file mode 100644 index 5d7208ec05..0000000000 --- a/packages/stencil-fiber-demo/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@stencil/fiber-demo", - "version": "0.0.1", - "description": "Demo of Stencil app using Ionic components to show rendering capabilities", - "main": "index.js", - "scripts": { - "build": "npm run clean && stencil build", - "clean": "rm -Rf ./dist/*", - "link.stencil": "npm link @stencil/core", - "test": "echo \"Error: no test specified\" && exit 1" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/ionic-team/ionic.git" - }, - "dependencies": { - "@stencil/core": "^0.0.1" - }, - "author": "", - "license": "MIT", - "bugs": { - "url": "https://github.com/ionic-team/ionic/issues" - }, - "homepage": "https://github.com/ionic-team/ionic#readme" -} diff --git a/packages/stencil-fiber-demo/src/components/app.tsx b/packages/stencil-fiber-demo/src/components/app.tsx deleted file mode 100644 index a70524a4ce..0000000000 --- a/packages/stencil-fiber-demo/src/components/app.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { Component, Prop } from '@stencil/core'; - -@Component({ - tag: 'fiber-demo' -}) -export class FiberDemo { - @Prop() elapsed: number = 0; - - seconds: number = 0; - intervalID: number; - - ionViewDidLoad() { - var tick: Function = this.tick.bind(this); - this.intervalID = setInterval(tick, 1000); - } - tick() { - this.seconds = (this.seconds % 10) + 1; - } - - hostData() { - const elapsed = this.elapsed; - const t = (elapsed / 1000) % 10; - const scale = 1 + (t > 5 ? 10 - t : t) / 10; - var containerStyle = { - position: 'absolute', - transformOrigin: '0 0', - left: '50%', - top: '50%', - width: '10px', - height: '10px', - background: '#eee', - transform: 'scaleX(' + (scale / 2.1) + ') scaleY(0.7) translateZ(0.1px)' - }; - - return { - style: containerStyle - }; - } - - render() { - return ( -
- - -
- ); - } -} diff --git a/packages/stencil-fiber-demo/src/components/dot.tsx b/packages/stencil-fiber-demo/src/components/dot.tsx deleted file mode 100644 index d1f6416d69..0000000000 --- a/packages/stencil-fiber-demo/src/components/dot.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { Component, Prop, State } from '@stencil/core'; - -@Component({ - tag: 'fiber-dot' -}) -export class FiberDot { - @Prop() size: number; - @Prop() x: number; - @Prop() y: number; - @Prop() text: string; - - @State() hover: boolean = false; - - enter() { - this.hover = true; - } - - leave() { - this.hover = false; - } - - hostData() { - const s = this.size * 1.3; - const style = { - position: 'absolute', - font: 'normal 15px sans-serif', - textAlign: 'center', - cursor: 'pointer', - width: s + 'px', - height: s + 'px', - left: (this.x) + 'px', - top: (this.y) + 'px', - borderRadius: (s / 2) + 'px', - lineHeight: (s) + 'px', - background: this.hover ? '#ff0' : '#61dafb' - }; - - return { - style: style, - on: { - mouseenter: this.enter.bind(this), - mouseleave: this.leave.bind(this) - }, - }; - } - - render() { - return ( - this.hover ? '**' + this.text + '**' : this.text - ); - } -} diff --git a/packages/stencil-fiber-demo/src/components/triangle.tsx b/packages/stencil-fiber-demo/src/components/triangle.tsx deleted file mode 100644 index 489a91bc16..0000000000 --- a/packages/stencil-fiber-demo/src/components/triangle.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { Component, Prop, h } from '@stencil/core'; - -var targetSize = 25; - -@Component({ - tag: 'fiber-triangle', - shadow: false -}) -export class FiberTriangle { - - @Prop() x: number; - @Prop() y: number; - @Prop() s: number; - @Prop() seconds: number; - - render() { - var s = this.s; - if (s <= targetSize) { - return ( - - ); - } - s = s / 2; - - return [ - , - , - - ]; - } -} diff --git a/packages/stencil-fiber-demo/stencil.config.js b/packages/stencil-fiber-demo/stencil.config.js deleted file mode 100644 index 85eb8ecb32..0000000000 --- a/packages/stencil-fiber-demo/stencil.config.js +++ /dev/null @@ -1,5 +0,0 @@ -exports.config = { - bundles: [ - { components: ['fiber-demo', 'fiber-triangle', 'fiber-dot'] } - ] -}; diff --git a/packages/stencil-fiber-demo/tsconfig.json b/packages/stencil-fiber-demo/tsconfig.json deleted file mode 100644 index 8637d52011..0000000000 --- a/packages/stencil-fiber-demo/tsconfig.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "compilerOptions": { - "allowJs": true, - "alwaysStrict": true, - "allowSyntheticDefaultImports": true, - "allowUnreachableCode": false, - "declaration": false, - "experimentalDecorators": true, - "forceConsistentCasingInFileNames": true, - "lib": [ - "dom", - "es2015" - ], - "moduleResolution": "node", - "module": "es2015", - "target": "es2015", - "noImplicitAny": true, - "noImplicitReturns": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "outDir": "dist", - "pretty": true, - "removeComments": false, - "sourceMap": false, - "jsx": "react", - "jsxFactory": "h" - }, - "include": [ - "**/*.ts", - "**/*.tsx", - "types/jsx.d.ts" - ], - "exclude": [ - "node_modules" - ] -} diff --git a/packages/stencil-fiber-demo/www/build/app.js b/packages/stencil-fiber-demo/www/build/app.js deleted file mode 100644 index faf763badc..0000000000 --- a/packages/stencil-fiber-demo/www/build/app.js +++ /dev/null @@ -1,44 +0,0 @@ -/*! Built with http://stenciljs.com */ - -(function (window, document, projectNamespace, projectFileName, projectCore, projectCoreEs5, components) { - 'use strict'; - // create global namespace if it doesn't already exist - - var Project = window[projectNamespace] = window[projectNamespace] || {}; - Project.components = Project.components || components; - Project.ns = projectNamespace; - // find the static directory, which should be the same as this JS file - // reusing the "x" and "y" variables for funzies - var x = document.getElementsByTagName('script'); - x = x[x.length - 1]; - var y = document.querySelector('script[data-static-dir]'); - if (y) { - Project.staticDir = y.dataset['staticDir']; - } else { - y = x.src.split('/'); - y.pop(); - Project.staticDir = x.dataset['staticDir'] = y.join('/') + '/'; - } - Project.staticDir += projectFileName + '/'; - // auto hide components until they been fully hydrated - x = document.createElement('style'); - x.innerHTML = Project.components.map(function (c) { - return c[0]; - }).join(',') + '{visibility:hidden}.hydrated{visibility:inherit}'; - x.innerHTML += 'ion-app:not(.hydrated){display:none}'; - document.head.appendChild(x); - // request the core file this browser needs - y = document.createElement('script'); - y.src = Project.staticDir + (window.customElements ? projectCore : projectCoreEs5); - document.head.appendChild(y); - // performance.now() polyfill - if ('performance' in window === false) { - window.performance = {}; - } - if ('now' in performance === false) { - var navStart = Date.now(); - performance.now = function () { - return Date.now() - navStart; - }; - } -})(window, document, "App","app","app.core.js","app.core.ce.js",[["FIBER-DEMO","fiber-demo.fiber-dot.fiber-triangle",{},0,[["elapsed",0,2]]],["FIBER-DOT","fiber-demo.fiber-dot.fiber-triangle",{},0,[["size",0,2],["text"],["x",0,2],["y",0,2]]],["FIBER-TRIANGLE","fiber-demo.fiber-dot.fiber-triangle",{},0,[["s",0,2],["seconds",0,2],["x",0,2],["y",0,2]]]]); \ No newline at end of file diff --git a/packages/stencil-fiber-demo/www/build/app.registry.json b/packages/stencil-fiber-demo/www/build/app.registry.json deleted file mode 100644 index 0bec2dc5f3..0000000000 --- a/packages/stencil-fiber-demo/www/build/app.registry.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "namespace": "App", - "components": [ - [ - "FIBER-DEMO", - "fiber-demo.fiber-dot.fiber-triangle", - {}, - 0, - [ - [ - "elapsed", - 0, - 2 - ] - ] - ], - [ - "FIBER-DOT", - "fiber-demo.fiber-dot.fiber-triangle", - {}, - 0, - [ - [ - "size", - 0, - 2 - ], - [ - "text" - ], - [ - "x", - 0, - 2 - ], - [ - "y", - 0, - 2 - ] - ] - ], - [ - "FIBER-TRIANGLE", - "fiber-demo.fiber-dot.fiber-triangle", - {}, - 0, - [ - [ - "s", - 0, - 2 - ], - [ - "seconds", - 0, - 2 - ], - [ - "x", - 0, - 2 - ], - [ - "y", - 0, - 2 - ] - ] - ] - ], - "loader": "app", - "core": "app/app.core.js", - "coreEs5": "app/app.core.ce.js" -} \ No newline at end of file diff --git a/packages/stencil-fiber-demo/www/build/app/app.core.ce.js b/packages/stencil-fiber-demo/www/build/app/app.core.ce.js deleted file mode 100644 index c2e7642599..0000000000 --- a/packages/stencil-fiber-demo/www/build/app/app.core.ce.js +++ /dev/null @@ -1,2073 +0,0 @@ -/*! document-register-element, 1.5.0 -https://github.com/WebReflection/document-register-element -(C) Andrea Giammarchi - @WebReflection - Mit Style License */ -(function(e,t){"use strict";function Ht(){var e=wt.splice(0,wt.length);Et=0;while(e.length)e.shift().call(null,e.shift())}function Bt(e,t){for(var n=0,r=e.length;n1)&&Zt(this)}}}),ot(u,h,{value:function(e){-1<_.call(a,e)&&o[h].apply(this,arguments)}}),o[d]&&ot(u,p,{value:o[d]}),o[v]&&ot(u,g,{value:o[v]}),i&&(f[c]=i),e=e.toUpperCase(),G[e]={constructor:t,create:i?[i,et(e)]:[e]},Z.set(t,e),n[s](e.toLowerCase(),f),en(e),Y[e].r()}function Gt(e){var t=G[e.toUpperCase()];return t&&t.constructor}function Yt(e){return typeof e=="string"?e:e&&e.is||""}function Zt(e){var t=e[h],n=t?e.attributes:j,r=n.length,i;while(r--)i=n[r],t.call(e,i.name||i.nodeName,null,i.value||i.nodeValue)}function en(e){return e=e.toUpperCase(),e in Y||(Y[e]={},Y[e].p=new K(function(t){Y[e].r=t})),Y[e].p}function tn(){X&&delete e.customElements,B(e,"customElements",{configurable:!0,value:new Kt}),B(e,"CustomElementRegistry",{configurable:!0,value:Kt});for(var t=function(t){var r=e[t];if(r){e[t]=function(t){var i,s;return t||(t=this),t[W]||(Q=!0,i=G[Z.get(t.constructor)],s=V&&i.create.length===1,t=s?Reflect.construct(r,j,i.constructor):n.createElement.apply(n,i.create),t[W]=!0,Q=!1,s||Zt(t)),t},e[t].prototype=r.prototype;try{r.prototype.constructor=e[t]}catch(i){z=!0,B(r,W,{value:e[t]})}}},r=i.get(/^HTML[A-Z]*[a-z]/),o=r.length;o--;t(r[o]));n.createElement=function(e,t){var n=Yt(t);return n?gt.call(this,e,et(n)):gt.call(this,e)},St||(Tt=!0,n[s](""))}var n=e.document,r=e.Object,i=function(e){var t=/^[A-Z]+[a-z]/,n=function(e){var t=[],n;for(n in s)e.test(n)&&t.push(n);return t},i=function(e,t){t=t.toLowerCase(),t in s||(s[e]=(s[e]||[]).concat(t),s[t]=s[t.toUpperCase()]=e)},s=(r.create||r)(null),o={},u,a,f,l;for(a in e)for(l in e[a]){f=e[a][l],s[l]=f;for(u=0;u>0),u="addEventListener",a="attached",f="Callback",l="detached",c="extends",h="attributeChanged"+f,p=a+f,d="connected"+f,v="disconnected"+f,m="created"+f,g=l+f,y="ADDITION",b="MODIFICATION",w="REMOVAL",E="DOMAttrModified",S="DOMContentLoaded",x="DOMSubtreeModified",T="<",N="=",C=/^[A-Z][A-Z0-9]*(?:-[A-Z0-9]+)+$/,k=["ANNOTATION-XML","COLOR-PROFILE","FONT-FACE","FONT-FACE-SRC","FONT-FACE-URI","FONT-FACE-FORMAT","FONT-FACE-NAME","MISSING-GLYPH"],L=[],A=[],O="",M=n.documentElement,_=L.indexOf||function(e){for(var t=this.length;t--&&this[t]!==e;);return t},D=r.prototype,P=D.hasOwnProperty,H=D.isPrototypeOf,B=r.defineProperty,j=[],F=r.getOwnPropertyDescriptor,I=r.getOwnPropertyNames,q=r.getPrototypeOf,R=r.setPrototypeOf,U=!!r.__proto__,z=!1,W="__dreCEv1",X=e.customElements,V=t!=="force"&&!!(X&&X.define&&X.get&&X.whenDefined),$=r.create||r,J=e.Map||function(){var t=[],n=[],r;return{get:function(e){return n[_.call(t,e)]},set:function(e,i){r=_.call(t,e),r<0?n[t.push(e)-1]=i:n[r]=i}}},K=e.Promise||function(e){function i(e){n=!0;while(t.length)t.shift()(e)}var t=[],n=!1,r={"catch":function(){return r},then:function(e){return t.push(e),n&&setTimeout(i,1),r}};return e(i),r},Q=!1,G=$(null),Y=$(null),Z=new J,et=function(e){return e.toLowerCase()},tt=r.create||function sn(e){return e?(sn.prototype=e,new sn):this},nt=R||(U?function(e,t){return e.__proto__=t,e}:I&&F?function(){function e(e,t){for(var n,r=I(t),i=0,s=r.length;i 8) { - break; - } - } - } catch (e) { - err = e; - } - if (rafPending = readCBs.length > 0 || writeCBs.length > 0) { - raf(rafFlush); - } - if (err) { - console.error(err); - } - } - return { - read: domRead, - write: domWrite, - raf: raf, - now: now - }; - } - - /** - * This constants file is largely for minification tricks, and to - * have easy to read variable names. Enums would make more sense - * in most cases, but doing values like this as constants allows - * minifiers to just place the raw value directly in source, and in - * production there is no variable at all. For example, the minifier - * turns data[BUNDLE_ID] turns into data[0] for production builds. - */ - /** - * Prop Change Meta Indexes - */ - var PROP_CHANGE_PROP_NAME = 0; - var PROP_CHANGE_METHOD_NAME = 1; - /** - * Property Types - */ - - var TYPE_BOOLEAN = 1; - var TYPE_NUMBER = 2; - /** - * JS Property to Attribute Name Options - */ - - var ATTR_LOWER_CASE = 1; - /** - * Priority Levels - */ - var PRIORITY_HIGH = 3; - - var PRIORITY_LOW = 1; - /** - * Slot Meta - */ - var SLOT_TAG = 0; - var HAS_SLOTS = 1; - var HAS_NAMED_SLOTS = 2; - /** - * SSR Attribute Names - */ - var SSR_VNODE_ID = 'ssrv'; - var SSR_CHILD_ID = 'ssrc'; - /** - * Node Types - */ - var ELEMENT_NODE = 1; - var TEXT_NODE = 3; - var COMMENT_NODE = 8; - /** - * Key Name to Key Code Map - */ - var KEY_CODE_MAP = { - 'enter': 13, - 'escape': 27, - 'space': 32, - 'tab': 9 - }; - /** - * CSS class that gets added to the host element - * after the component has fully hydrated - */ - var HYDRATED_CSS = 'hydrated'; - /** - * Namespaces - */ - - /** - * File names and value - */ - - var VNode = function VNode() {} - - /** - * Production h() function based on Preact by - * Jason Miller (@developit) - * Licensed under the MIT License - * https://github.com/developit/preact/blob/master/LICENSE - * - * Modified for Stencil's compiler and vdom - */ - var stack = []; - function h(nodeName, vnodeData, child) { - var children = void 0, - lastSimple = void 0, - simple = void 0, - i = void 0; - for (i = arguments.length; i-- > 2;) { - stack.push(arguments[i]); - } - while (stack.length) { - if ((child = stack.pop()) && child.pop !== undefined) { - for (i = child.length; i--;) { - stack.push(child[i]); - } - } else { - if (typeof child === 'boolean') child = null; - if (simple = typeof nodeName !== 'function') { - if (child == null) child = '';else if (typeof child === 'number') child = String(child);else if (typeof child !== 'string') simple = false; - } - if (simple && lastSimple) { - children[children.length - 1].vtext += child; - } else if (children === undefined) { - children = [simple ? t(child) : child]; - } else { - children.push(simple ? t(child) : child); - } - lastSimple = simple; - } - } - var vnode = new VNode(); - vnode.vtag = nodeName; - vnode.vchildren = children; - if (vnodeData) { - // data object was provided - vnode.vattrs = vnodeData.a; - vnode.vprops = vnodeData.p; - vnode.vclass = vnodeData.c; - vnode.vstyle = vnodeData.s; - vnode.vlisteners = vnodeData.o; - vnode.vkey = vnodeData.k; - vnode.vnamespace = vnodeData.n; - // x = undefined: always check both data and children - // x = 0 skip checking only data on update - // x = 1 skip checking only children on update - // x = 2 skip checking both data and children on update - vnode.skipDataOnUpdate = vnodeData.x === 0 || vnodeData.x === 2; - vnode.skipChildrenOnUpdate = vnodeData.x > 0; - } else { - // no data object was provided - // so no data, so don't both checking data - vnode.skipDataOnUpdate = true; - // since no data was provided, than no x was provided - // if no x was provided then we need to always check children - // if if there are no children at all, then we know never to check children - vnode.skipChildrenOnUpdate = !children || children.length === 0; - } - return vnode; - } - function t(textValue) { - var vnode = new VNode(); - vnode.vtext = textValue; - return vnode; - } - - function createVNodesFromSsr(domApi, rootElm) { - var allSsrElms = rootElm.querySelectorAll('[' + SSR_VNODE_ID + ']'), - elm, - ssrVNodeId, - ssrVNode, - i, - ilen = allSsrElms.length, - j, - jlen; - if (rootElm._hasLoaded = ilen > 0) { - for (i = 0; i < ilen; i++) { - elm = allSsrElms[i]; - ssrVNodeId = domApi.$getAttribute(elm, SSR_VNODE_ID); - ssrVNode = elm._vnode = new VNode(); - ssrVNode.vtag = domApi.$tagName(ssrVNode.elm = elm).toLowerCase(); - for (j = 0, jlen = elm.childNodes.length; j < jlen; j++) { - addChildSsrVNodes(domApi, elm.childNodes[j], ssrVNode, ssrVNodeId, true); - } - } - } - } - function addChildSsrVNodes(domApi, node, parentVNode, ssrVNodeId, checkNestedElements) { - var nodeType = domApi.$nodeType(node); - var previousComment; - var childVNodeId, childVNodeSplt, childVNode; - if (checkNestedElements && nodeType === ELEMENT_NODE) { - childVNodeId = domApi.$getAttribute(node, SSR_CHILD_ID); - if (childVNodeId) { - // split the start comment's data with a period - childVNodeSplt = childVNodeId.split('.'); - // ensure this this element is a child element of the ssr vnode - if (childVNodeSplt[0] === ssrVNodeId) { - // cool, this element is a child to the parent vnode - childVNode = new VNode(); - childVNode.vtag = domApi.$tagName(childVNode.elm = node).toLowerCase(); - // this is a new child vnode - // so ensure its parent vnode has the vchildren array - if (!parentVNode.vchildren) { - parentVNode.vchildren = []; - } - // add our child vnode to a specific index of the vnode's children - parentVNode.vchildren[childVNodeSplt[1]] = childVNode; - // this is now the new parent vnode for all the next child checks - parentVNode = childVNode; - // if there's a trailing period, then it means there aren't any - // more nested elements, but maybe nested text nodes - // either way, don't keep walking down the tree after this next call - checkNestedElements = childVNodeSplt[2] !== ''; - } - } - // keep drilling down through the elements - for (var i = 0; i < node.childNodes.length; i++) { - addChildSsrVNodes(domApi, node.childNodes[i], parentVNode, ssrVNodeId, checkNestedElements); - } - } else if (nodeType === TEXT_NODE && (previousComment = node.previousSibling) && domApi.$nodeType(previousComment) === COMMENT_NODE) { - // split the start comment's data with a period - childVNodeSplt = domApi.$getTextContent(previousComment).split('.'); - // ensure this is an ssr text node start comment - // which should start with an "s" and delimited by periods - if (childVNodeSplt[0] === 's' && childVNodeSplt[1] === ssrVNodeId) { - // cool, this is a text node and it's got a start comment - childVNode = t(domApi.$getTextContent(node)); - childVNode.elm = node; - // this is a new child vnode - // so ensure its parent vnode has the vchildren array - if (!parentVNode.vchildren) { - parentVNode.vchildren = []; - } - // add our child vnode to a specific index of the vnode's children - parentVNode.vchildren[childVNodeSplt[2]] = childVNode; - } - } - } - function assignHostContentSlots(domApi, elm, slotMeta) { - // compiler has already figured out if this component has slots or not - // if the component doesn't even have slots then we'll skip over all of this code - var childNodes = elm.childNodes; - if (slotMeta === HAS_NAMED_SLOTS) { - // looks like this component has named slots - // so let's loop through each of the childNodes to the host element - // and pick out the ones that have a slot attribute - // if it doesn't have a slot attribute, than it's a default slot - var slotName = void 0; - var defaultSlot = void 0; - var namedSlots = void 0; - for (var i = 0, childNodeLen = childNodes.length; i < childNodeLen; i++) { - var childNode = childNodes[i]; - if (domApi.$nodeType(childNode) === 1 && (slotName = domApi.$getAttribute(childNode, 'slot')) != null) { - // is element node - // this element has a slot name attribute - // so this element will end up getting relocated into - // the component's named slot once it renders - namedSlots = namedSlots || {}; - if (namedSlots[slotName]) { - namedSlots[slotName].push(childNode); - } else { - namedSlots[slotName] = [childNode]; - } - } else { - // this is a text node - // or it's an element node that doesn't have a slot attribute - // let's add this node to our collection for the default slot - if (defaultSlot) { - defaultSlot.push(childNode); - } else { - defaultSlot = [childNode]; - } - } - } - // keep a reference to all of the initial nodes - // found as immediate childNodes to the host element - elm._hostContentNodes = { - defaultSlot: defaultSlot, - namedSlots: namedSlots - }; - } else if (slotMeta === HAS_SLOTS) { - // this component doesn't have named slots, but it does - // have at least a default slot, so the work here is alot easier than - // when we're not looping through each element and reading attribute values - elm._hostContentNodes = { - defaultSlot: childNodes.length ? Array.apply(null, childNodes) : null - }; - } - } - - function isDef(v) { - return v !== undefined && v !== null; - } - function isUndef(v) { - return v === undefined || v === null; - } - - function isObject(v) { - return v !== null && typeof v === 'object'; - } - - function isFunction(v) { - return typeof v === 'function'; - } - - function toDashCase(str) { - return str.replace(/([A-Z])/g, function (g) { - return '-' + g[0].toLowerCase(); - }); - } - - function noop() {} - - function getElementReference(elm, ref) { - if (ref === 'child') { - return elm.firstElementChild; - } - if (ref === 'parent') { - return getParentElement(elm) || elm; - } - if (ref === 'body') { - return elm.ownerDocument.body; - } - if (ref === 'document') { - return elm.ownerDocument; - } - if (ref === 'window') { - return elm.ownerDocument.defaultView; - } - return elm; - } - function getParentElement(elm) { - if (elm.parentElement) { - // normal element with a parent element - return elm.parentElement; - } - if (elm.parentNode && elm.parentNode.host) { - // shadow dom's document fragment - return elm.parentNode.host; - } - return null; - } - - var EMPTY = {}; - var DEFAULT_OPTS = null; - function updateElement(plt, nodeOps, oldVnode, newVnode) { - var isUpdate = oldVnode != null; - oldVnode = oldVnode || EMPTY; - newVnode = newVnode || EMPTY; - var key, - cur, - elm = newVnode.elm, - oldData, - newData; - // update attrs - if (oldVnode.vattrs || newVnode.vattrs) { - oldData = oldVnode.vattrs || EMPTY; - newData = newVnode.vattrs || EMPTY; - // update modified attributes, add new attributes - for (key in newData) { - cur = newData[key]; - if (oldData[key] !== cur) { - if (BOOLEAN_ATTRS[key] === 1) { - if (cur) { - nodeOps.$setAttribute(elm, key, ''); - } else { - nodeOps.$removeAttribute(elm, key); - } - } else { - if (key.charCodeAt(0) !== 120 /* xChar */) { - nodeOps.$setAttribute(elm, key, cur); - } else if (key.charCodeAt(3) === 58 /* colonChar */) { - // Assume xml namespace - nodeOps.$setAttributeNS(elm, XML_NS$1, key, cur); - } else if (key.charCodeAt(5) === 58 /* colonChar */) { - // Assume xlink namespace - nodeOps.$setAttributeNS(elm, XLINK_NS$1, key, cur); - } else { - nodeOps.$setAttribute(elm, key, cur); - } - } - } - } - // remove removed attributes - // use `in` operator since the previous `for` iteration uses it (.i.e. add even attributes with undefined value) - // the other option is to remove all attributes with value == undefined - if (isUpdate) { - for (key in oldData) { - if (!(key in newData)) { - nodeOps.$removeAttribute(elm, key); - } - } - } - } - // update class - if (oldVnode.vclass || newVnode.vclass) { - oldData = oldVnode.vclass || EMPTY; - newData = newVnode.vclass || EMPTY; - if (isUpdate) { - for (key in oldData) { - if (!newData[key]) { - elm.classList.remove(key); - } - } - } - for (key in newData) { - cur = newData[key]; - if (cur !== oldData[key]) { - elm.classList[newData[key] ? 'add' : 'remove'](key); - } - } - } - // update props - if (oldVnode.vprops || newVnode.vprops) { - oldData = oldVnode.vprops || EMPTY; - newData = newVnode.vprops || EMPTY; - if (isUpdate) { - for (key in oldData) { - if (newData[key] === undefined) { - // only delete the old property when the - // new property is undefined, otherwise we'll - // end up deleting getters/setters - delete elm[key]; - } - } - } - for (key in newData) { - cur = newData[key]; - if (oldData[key] !== cur && (key !== 'value' || elm[key] !== cur)) { - elm[key] = cur; - } - } - } - // update style - if (oldVnode.vstyle || newVnode.vstyle) { - oldData = oldVnode.vstyle || EMPTY; - newData = newVnode.vstyle || EMPTY; - if (isUpdate) { - for (key in oldData) { - if (!newData[key]) { - elm.style[key] = ''; - } - } - } - for (key in newData) { - cur = newData[key]; - if (cur !== oldData[key]) { - elm.style[key] = cur; - } - } - } - // update event listeners - oldData = oldVnode.vlisteners; - newData = newVnode.vlisteners; - if (oldData || newData) { - if (!DEFAULT_OPTS) { - DEFAULT_OPTS = plt.getEventOptions(); - } - // remove existing listeners which no longer used - if (isUpdate && oldData && oldVnode.assignedListener) { - // if element changed or deleted we remove all existing listeners unconditionally - for (key in oldData) { - // remove listener if existing listener removed - if (!newData || !newData[key]) { - oldVnode.elm.removeEventListener(key, oldVnode.assignedListener, DEFAULT_OPTS); - } - } - } - // add new listeners which has not already attached - if (newData) { - // reuse existing listener or create new - cur = newVnode.assignedListener = oldVnode.assignedListener || createListener(); - // update vnode for listener - cur.vnode = newVnode; - // if element changed or added we add all needed listeners unconditionally - for (key in newData) { - // add listener if new listener added - if (!oldData || !oldData[key]) { - elm.addEventListener(key, cur, DEFAULT_OPTS); - } - } - } - } - } - function createListener() { - return function handler(event) { - handleEvent(event, handler.vnode); - }; - } - function handleEvent(event, vnode) { - var eventName = event.type, - on = vnode.vlisteners; - // call event handler(s) if they exists - if (on && on[eventName]) { - invokeHandler(on[eventName], vnode, event); - } - } - function invokeHandler(handler, vnode, event) { - if (isFunction(handler)) { - // call function handler - handler.call(vnode, event, vnode); - } else if (isObject(handler)) { - // call handler with arguments - if (isFunction(handler[0])) { - // special case for single argument for performance - if (handler.length === 2) { - handler[0].call(vnode, handler[1], event, vnode); - } else { - var args = handler.slice(1); - args.push(event); - args.push(vnode); - handler[0].apply(vnode, args); - } - } else { - // call multiple handlers - for (var i = 0; i < handler.length; i++) { - invokeHandler(handler[i]); - } - } - } - } - var BOOLEAN_ATTRS = { - 'allowfullscreen': 1, - 'async': 1, - 'autofocus': 1, - 'autoplay': 1, - 'checked': 1, - 'controls': 1, - 'disabled': 1, - 'enabled': 1, - 'formnovalidate': 1, - 'hidden': 1, - 'multiple': 1, - 'noresize': 1, - 'readonly': 1, - 'required': 1, - 'selected': 1, - 'spellcheck': 1 - }; - var XLINK_NS$1 = 'http://www.w3.org/1999/xlink'; - var XML_NS$1 = 'http://www.w3.org/XML/1998/namespace'; - - /** - * Virtual DOM patching algorithm based on Snabbdom by - * Simon Friis Vindum (@paldepind) - * Licensed under the MIT License - * https://github.com/snabbdom/snabbdom/blob/master/LICENSE - * - * Modified for Stencil's renderer and slot projection - */ - function createRenderer(plt, domApi) { - // createRenderer() is only created once per app - // the patch() function which createRenderer() returned is the function - // which gets called numerous times by each component - function createElm(vnode, parentElm, childIndex) { - var i = 0; - if (vnode.vtag === SLOT_TAG) { - if (hostContentNodes) { - // special case for manually relocating host content nodes - // to their new home in either a named slot or the default slot - var namedSlot = vnode.vattrs && vnode.vattrs.name; - var slotNodes = void 0; - if (isDef(namedSlot)) { - // this vnode is a named slot - slotNodes = hostContentNodes.namedSlots && hostContentNodes.namedSlots[namedSlot]; - } else { - // this vnode is the default slot - slotNodes = hostContentNodes.defaultSlot; - } - if (isDef(slotNodes)) { - // the host element has some nodes that need to be moved around - // we have a slot for the user's vnode to go into - // while we're moving nodes around, temporarily disable - // the disconnectCallback from working - plt.tmpDisconnected = true; - for (; i < slotNodes.length; i++) { - // remove the host content node from it's original parent node - // then relocate the host content node to its new slotted home - domApi.$appendChild(parentElm, domApi.$removeChild(domApi.$parentNode(slotNodes[i]), slotNodes[i])); - } - // done moving nodes around - // allow the disconnect callback to work again - plt.tmpDisconnected = false; - } - } - // this was a slot node, we do not create slot elements, our work here is done - // no need to return any element to be added to the dom - return null; - } - if (isDef(vnode.vtext)) { - // create text node - vnode.elm = domApi.$createTextNode(vnode.vtext); - } else { - // create element - var elm = vnode.elm = vnode.vnamespace ? domApi.$createElementNS(vnode.vnamespace, vnode.vtag) : domApi.$createElement(vnode.vtag); - // add css classes, attrs, props, listeners, etc. - updateElement(plt, domApi, null, vnode); - var children = vnode.vchildren; - if (isDef(ssrId)) { - // SSR ONLY: this is an SSR render and this - // logic does not run on the client - // give this element the SSR child id that can be read by the client - domApi.$setAttribute(vnode.elm, SSR_CHILD_ID, ssrId + '.' + childIndex + (hasChildNodes(children) ? '' : '.')); - } - if (children) { - var childNode = void 0; - for (; i < children.length; ++i) { - // create the node - childNode = createElm(children[i], elm, i); - // return node could have been null - if (childNode) { - if (isDef(ssrId) && childNode.nodeType === 3) { - // SSR ONLY: add the text node's start comment - domApi.$appendChild(elm, domApi.$createComment('s.' + ssrId + '.' + i)); - } - // append our new node - domApi.$appendChild(elm, childNode); - if (isDef(ssrId) && childNode.nodeType === 3) { - // SSR ONLY: add the text node's end comment - domApi.$appendChild(elm, domApi.$createComment('/')); - } - } - } - } - } - return vnode.elm; - } - function addVnodes(parentElm, before, vnodes, startIdx, endIdx) { - var childNode = void 0; - for (; startIdx <= endIdx; ++startIdx) { - var vnodeChild = vnodes[startIdx]; - if (isDef(vnodeChild)) { - if (isDef(vnodeChild.vtext)) { - childNode = domApi.$createTextNode(vnodeChild.vtext); - } else { - childNode = createElm(vnodeChild, parentElm, startIdx); - } - if (isDef(childNode)) { - vnodeChild.elm = childNode; - domApi.$insertBefore(parentElm, childNode, before); - } - } - } - } - function removeVnodes(parentElm, vnodes, startIdx, endIdx) { - for (; startIdx <= endIdx; ++startIdx) { - var vnode = vnodes[startIdx]; - if (isDef(vnode)) { - if (isDef(vnode.elm)) { - invokeDestroy(vnode); - } - domApi.$removeChild(parentElm, vnode.elm); - } - } - } - function updateChildren(parentElm, oldCh, newCh) { - var oldStartIdx = 0, - newStartIdx = 0; - var oldEndIdx = oldCh.length - 1; - var oldStartVnode = oldCh[0]; - var oldEndVnode = oldCh[oldEndIdx]; - var newEndIdx = newCh.length - 1; - var newStartVnode = newCh[0]; - var newEndVnode = newCh[newEndIdx]; - var oldKeyToIdx = void 0; - var idxInOld = void 0; - var elmToMove = void 0; - var node = void 0; - while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) { - if (oldStartVnode == null) { - oldStartVnode = oldCh[++oldStartIdx]; // Vnode might have been moved left - } else if (oldEndVnode == null) { - oldEndVnode = oldCh[--oldEndIdx]; - } else if (newStartVnode == null) { - newStartVnode = newCh[++newStartIdx]; - } else if (newEndVnode == null) { - newEndVnode = newCh[--newEndIdx]; - } else if (isSameVnode(oldStartVnode, newStartVnode)) { - patchVNode(oldStartVnode, newStartVnode); - oldStartVnode = oldCh[++oldStartIdx]; - newStartVnode = newCh[++newStartIdx]; - } else if (isSameVnode(oldEndVnode, newEndVnode)) { - patchVNode(oldEndVnode, newEndVnode); - oldEndVnode = oldCh[--oldEndIdx]; - newEndVnode = newCh[--newEndIdx]; - } else if (isSameVnode(oldStartVnode, newEndVnode)) { - patchVNode(oldStartVnode, newEndVnode); - domApi.$insertBefore(parentElm, oldStartVnode.elm, domApi.$nextSibling(oldEndVnode.elm)); - oldStartVnode = oldCh[++oldStartIdx]; - newEndVnode = newCh[--newEndIdx]; - } else if (isSameVnode(oldEndVnode, newStartVnode)) { - patchVNode(oldEndVnode, newStartVnode); - domApi.$insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm); - oldEndVnode = oldCh[--oldEndIdx]; - newStartVnode = newCh[++newStartIdx]; - } else { - if (isUndef(oldKeyToIdx)) { - oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx); - } - idxInOld = oldKeyToIdx[newStartVnode.vkey]; - if (isUndef(idxInOld)) { - // new element - node = createElm(newStartVnode, parentElm, newStartIdx); - newStartVnode = newCh[++newStartIdx]; - } else { - elmToMove = oldCh[idxInOld]; - if (elmToMove.vtag !== newStartVnode.vtag) { - node = createElm(newStartVnode, parentElm, idxInOld); - } else { - patchVNode(elmToMove, newStartVnode); - oldCh[idxInOld] = undefined; - node = elmToMove.elm; - } - newStartVnode = newCh[++newStartIdx]; - } - if (node) { - domApi.$insertBefore(parentElm, node, oldStartVnode.elm); - } - } - } - if (oldStartIdx > oldEndIdx) { - addVnodes(parentElm, newCh[newEndIdx + 1] == null ? null : newCh[newEndIdx + 1].elm, newCh, newStartIdx, newEndIdx); - } else if (newStartIdx > newEndIdx) { - removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx); - } - } - function isSameVnode(vnode1, vnode2) { - // compare if two vnode to see if they're "technically" the same - // need to have the same element tag, and same key to be the same - return vnode1.vtag === vnode2.vtag && vnode1.vkey === vnode2.vkey; - } - function createKeyToOldIdx(children, beginIdx, endIdx) { - var i = void 0, - map = {}, - key = void 0, - ch = void 0; - for (i = beginIdx; i <= endIdx; ++i) { - ch = children[i]; - if (ch != null) { - key = ch.vkey; - if (key !== undefined) { - map.k = i; - } - } - } - return map; - } - function patchVNode(oldVnode, newVnode) { - var elm = newVnode.elm = oldVnode.elm; - var oldChildren = oldVnode.vchildren; - var newChildren = newVnode.vchildren; - if (isUndef(newVnode.vtext)) { - // element node - if ((!isUpdate || !newVnode.skipDataOnUpdate) && newVnode.vtag !== SLOT_TAG) { - // either this is the first render of an element OR it's an update - // AND we already know it's possible it could have changed - // this updates the element's css classes, attrs, props, listeners, etc. - updateElement(plt, domApi, oldVnode, newVnode); - } - if (isDef(oldChildren) && isDef(newChildren)) { - // looks like there's child vnodes for both the old and new vnodes - if (!isUpdate || !newVnode.skipChildrenOnUpdate) { - // either this is the first render of an element OR it's an update - // AND we already know it's possible that the children could have changed - updateChildren(elm, oldChildren, newChildren); - } - } else if (isDef(newChildren)) { - // no old child vnodes, but there are new child vnodes to add - if (isDef(oldVnode.vtext)) { - // the old vnode was text, so be sure to clear it out - domApi.$setTextContent(elm, ''); - } - // add the new vnode children - addVnodes(elm, null, newChildren, 0, newChildren.length - 1); - } else if (isDef(oldChildren)) { - // no new child vnodes, but there are old child vnodes to remove - removeVnodes(elm, oldChildren, 0, oldChildren.length - 1); - } - } else if (elm._hostContentNodes && elm._hostContentNodes.defaultSlot) { - // this element has slotted content - var parentElement = elm._hostContentNodes.defaultSlot[0].parentElement; - domApi.$setTextContent(parentElement, newVnode.vtext); - elm._hostContentNodes.defaultSlot = [parentElement.childNodes[0]]; - } else { - // update the text content for the text only vnode - domApi.$setTextContent(elm, newVnode.vtext); - } - } - // internal variables to be reused per patch() call - var isUpdate = void 0, - hostContentNodes = void 0, - ssrId = void 0; - return function patch(oldVnode, newVnode, isUpdatePatch, hostElementContentNodes, ssrPatchId) { - // patchVNode() is synchronous - // so it is safe to set these variables and internally - // the same patch() call will reference the same data - isUpdate = isUpdatePatch; - hostContentNodes = hostElementContentNodes; - ssrId = ssrPatchId; - // synchronous patch - patchVNode(oldVnode, newVnode); - if (isDef(ssrId)) { - // SSR ONLY: we've been given an SSR id, so the host element - // should be given the ssr id attribute - domApi.$setAttribute(oldVnode.elm, SSR_VNODE_ID, ssrId); - } - // return our new vnode - return newVnode; - }; - } - function invokeDestroy(vnode) { - if (vnode.vlisteners && vnode.assignedListener) { - for (var key in vnode.vlisteners) { - vnode.elm.removeEventListener(key, vnode.vlisteners, false); - } - } - if (isDef(vnode.vchildren)) { - for (var i = 0; i < vnode.vchildren.length; ++i) { - vnode.vchildren[i] && invokeDestroy(vnode.vchildren[i]); - } - } - } - function hasChildNodes(children) { - // SSR ONLY: check if there are any more nested child elements - // if there aren't, this info is useful so the client runtime - // doesn't have to climb down and check so many elements - if (children) { - for (var i = 0; i < children.length; i++) { - if (children[i].vtag !== SLOT_TAG || hasChildNodes(children[i].vchildren)) { - return true; - } - } - } - return false; - } - - function getMode(domApi, config, elm) { - var attrMode = domApi.$getAttribute(elm, 'mode'); - // first let's see if they set the mode directly on the property - if (isDef(elm.mode)) { - return elm.mode; - } - // next let's see if they set the mode on the elements attribute - if (isDef(attrMode)) { - return attrMode; - } - // ok fine, let's just get the values from the config - return config.get('mode', 'md'); - } - - function attachListeners(plt, listeners, elm, instance) { - if (listeners) { - for (var i = 0; i < listeners.length; i++) { - var listener = listeners[i]; - if (listener.eventEnabled !== false) { - (elm._listeners = elm._listeners || {})[listener.eventName] = addEventListener(plt, elm, listener.eventName, instance[listener.eventMethodName].bind(instance), listener); - } - } - } - } - function enableListener(plt, elm, instance, eventName, shouldEnable, attachTo) { - if (instance) { - var listenerMeta = plt.getComponentMeta(elm).listenersMeta; - if (listenerMeta) { - var deregisterFns = elm._listeners = elm._listeners || {}; - for (var i = 0; i < listenerMeta.length; i++) { - var listener = listenerMeta[i]; - if (listener.eventName === eventName) { - if (shouldEnable && !deregisterFns[eventName]) { - var attachToEventName = attachTo ? attachTo + ':' + eventName : eventName; - deregisterFns[eventName] = addEventListener(plt, instance.$el, attachToEventName, instance[listener.eventMethodName].bind(instance), listener); - } else if (!shouldEnable && deregisterFns[eventName]) { - deregisterFns[eventName](); - delete elm._listeners[eventName]; - } - return; - } - } - } - } - } - function addEventListener(plt, elm, eventName, userEventListener, opts) { - if (!elm) { - return noop; - } - var splt = eventName.split(':'); - if (splt.length > 1) { - // document:mousemove - // parent:touchend - // body:keyup.enter - elm = getElementReference(elm, splt[0]); - eventName = splt[1]; - } - if (!elm) { - return noop; - } - splt = eventName.split('.'); - var testKeyCode = 0; - if (splt.length > 1) { - // keyup.enter - eventName = splt[0]; - testKeyCode = KEY_CODE_MAP[splt[1]]; - } - var eventListener = function (ev) { - if (testKeyCode > 0 && ev.keyCode !== testKeyCode) { - // we're looking for a specific keycode but this wasn't it - return; - } - // fire the component's event listener callback - userEventListener(ev); - // test if this is the user's interaction - if (isUserInteraction(eventName)) { - // so it's very important to flush the queue now - // so that the app reflects whatever they just did - // basically don't let requestIdleCallback delay the important - plt.queue.flush(); - } - }; - var eventListenerOpts = plt.getEventOptions(opts); - elm.addEventListener(eventName, eventListener, eventListenerOpts); - return function removeListener() { - if (elm) { - elm.removeEventListener(eventName, eventListener, eventListenerOpts); - } - }; - } - function isUserInteraction(eventName) { - for (var i = 0; i < USER_INTERACTIONS.length; i++) { - if (eventName.indexOf(USER_INTERACTIONS[i]) > -1) { - return true; - } - } - return false; - } - var USER_INTERACTIONS = ['touch', 'mouse', 'pointer', 'key', 'focus', 'blur', 'drag']; - function detachListeners(elm) { - var deregisterFns = elm._listeners; - if (deregisterFns) { - var eventNames = Object.keys(deregisterFns); - for (var i = 0; i < eventNames.length; i++) { - deregisterFns[eventNames[i]](); - } - elm._listeners = null; - } - } - - function parseComponentRegistry(cmpRegistryData, registry) { - // tag name will always be upper case - var cmpMeta = { - tagNameMeta: cmpRegistryData[0], - propsMeta: [ - // every component defaults to always have - // the mode and color properties - // but only observe the color attribute - // mode cannot change after the component was created - { propName: 'color', attribName: 'color' }, { propName: 'mode' }] - }; - cmpMeta.moduleId = cmpRegistryData[1]; - // map of the modes w/ bundle id and style data - cmpMeta.styleIds = cmpRegistryData[2] || {}; - // slot - cmpMeta.slotMeta = cmpRegistryData[3]; - if (cmpRegistryData[4]) { - // parse prop meta - for (var i = 0; i < cmpRegistryData[4].length; i++) { - var data = cmpRegistryData[4][i]; - cmpMeta.propsMeta.push({ - propName: data[0], - attribName: data[1] === ATTR_LOWER_CASE ? data[0].toLowerCase() : toDashCase(data[0]), - propType: data[2], - isStateful: !!data[3] - }); - } - } - // bundle load priority - cmpMeta.loadPriority = cmpRegistryData[5]; - return registry[cmpMeta.tagNameMeta] = cmpMeta; - } - function parseComponentMeta(registry, moduleImports, cmpMetaData) { - // tag name will always be upper case - var cmpMeta = registry[cmpMetaData[0]]; - // get the component class which was added to moduleImports - // using the tag as the key on the export object - cmpMeta.componentModuleMeta = moduleImports[cmpMeta.tagNameMeta]; - // host - cmpMeta.hostMeta = cmpMetaData[1]; - // component listeners - if (cmpMetaData[2]) { - cmpMeta.listenersMeta = []; - for (var i = 0; i < cmpMetaData[2].length; i++) { - var data = cmpMetaData[2][i]; - cmpMeta.listenersMeta.push({ - eventMethodName: data[0], - eventName: data[1], - eventCapture: !!data[2], - eventPassive: !!data[3], - eventEnabled: !!data[4] - }); - } - } - // component states - cmpMeta.statesMeta = cmpMetaData[3]; - // component instance prop WILL change methods - cmpMeta.propWillChangeMeta = cmpMetaData[4]; - // component instance prop DID change methods - cmpMeta.propDidChangeMeta = cmpMetaData[5]; - // component methods - cmpMeta.methodsMeta = cmpMetaData[6]; - return cmpMeta; - } - function parsePropertyValue(propType, propValue) { - // ensure this value is of the correct prop type - if (isDef(propValue)) { - if (propType === TYPE_BOOLEAN) { - // per the HTML spec, any string value means it is a boolean "true" value - // but we'll cheat here and say that the string "false" is the boolean false - return propValue === 'false' ? false : propValue === '' || !!propValue; - } - if (propType === TYPE_NUMBER) { - // force it to be a number - return parseFloat(propValue); - } - } - // not sure exactly what type we want - // so no need to change to a different type - return propValue; - } - - function attributeChangedCallback(plt, elm, attribName, oldVal, newVal) { - // only react if the attribute values actually changed - if (oldVal !== newVal) { - // normalize the attribute name w/ lower case - attribName = attribName.toLowerCase(); - // using the known component meta data - // look up to see if we have a property wired up to this attribute name - var prop = plt.getComponentMeta(elm).propsMeta.find(function (p) { - return p.attribName === attribName; - }); - if (prop) { - // cool we've got a prop using this attribute name the value will - // be a string, so let's convert it to the correct type the app wants - // below code is ugly yes, but great minification ;) - elm[prop.propName] = parsePropertyValue(prop.propType, newVal); - } - } - } - - function connectedCallback(plt, elm) { - // do not reconnect if we've already created an instance for this element - if (!elm._hasConnected) { - // first time we've connected - elm._hasConnected = true; - // if somehow this node was reused, ensure we've removed this property - delete elm._hasDestroyed; - // add to the queue to load the bundle - // it's important to have an async tick in here so we can - // ensure the "mode" attribute has been added to the element - // place in high priority since it's not much work and we need - // to know as fast as possible, but still an async tick in between - plt.queue.add(function () { - // get the component meta data about this component - var cmpMeta = plt.getComponentMeta(elm); - // async tick has happened, so all of the child - // nodes and host attributes should now be in the DOM - collectHostContent(plt, elm); - // only collects slot references if this component even has slots - plt.connectHostElement(elm, cmpMeta.slotMeta); - // start loading this component mode's bundle - // if it's already loaded then the callback will be synchronous - plt.loadBundle(cmpMeta, elm, function loadComponentCallback() { - // we've fully loaded the component mode data - // let's queue it up to be rendered next - elm._queueUpdate(); - }); - }, PRIORITY_HIGH); - } - } - function collectHostContent(plt, elm) { - // find the first ancestor host element (if there is one) and register - // this element as one of the actively loading child elements for its ancestor - var ancestorHostElement = elm; - while (ancestorHostElement = getParentElement(ancestorHostElement)) { - // climb up the ancestors looking for the first registered component - if (plt.getComponentMeta(ancestorHostElement)) { - // we found this elements the first ancestor host element - // if the ancestor already loaded then do nothing, it's too late - if (!ancestorHostElement._hasLoaded) { - // keep a reference to this element's ancestor host element - elm._ancestorHostElement = ancestorHostElement; - // ensure there is an array to contain a reference to each of the child elements - // and set this element as one of the ancestor's child elements it should wait on - if (ancestorHostElement._activelyLoadingChildren) { - ancestorHostElement._activelyLoadingChildren.push(elm); - } else { - ancestorHostElement._activelyLoadingChildren = [elm]; - } - } - break; - } - } - } - - function disconnectedCallback(plt, elm) { - // only disconnect if we're not temporarily disconnected - // tmpDisconnected will happen when slot nodes are being relocated - if (!plt.tmpDisconnected) { - // ok, let's officially destroy this thing - // set this to true so that any of our pending async stuff - // doesn't continue since we already decided to destroy this node - elm._hasDestroyed = true; - // call instance Did Unload and destroy instance stuff - // if we've created an instance for this - var instance = elm.$instance; - if (instance) { - // call the user's componentDidUnload if there is one - instance.componentDidUnload && instance.componentDidUnload(); - elm.$instance = instance.$el = instance.__values = instance.__values.__propWillChange = instance.__values.__propDidChange = null; - } - // detatch any event listeners that may have been added - // this will also set _listeners to null if there are any - detachListeners(elm); - // destroy the vnode and child vnodes if they exist - elm._vnode && invokeDestroy(elm._vnode); - if (elm._hostContentNodes) { - // overreacting here just to reduce any memory leak issues - elm._hostContentNodes = elm._hostContentNodes.defaultSlot = elm._hostContentNodes.namedSlots = null; - } - // fuhgeddaboudit - // set it all to null to ensure we forget references - // and reset values incase this node gets reused somehow - // (possible that it got disconnected, but the node was reused) - elm._root = elm._vnode = elm._ancestorHostElement = elm._activelyLoadingChildren = elm._hasConnected = elm._isQueuedForUpdate = elm._hasLoaded = null; - } - } - - function queueUpdate(plt, elm) { - // only run patch if it isn't queued already - if (!elm._isQueuedForUpdate) { - elm._isQueuedForUpdate = true; - // run the patch in the next tick - plt.queue.add(function queueUpdateNextTick() { - // no longer queued - elm._isQueuedForUpdate = false; - // vdom diff and patch the host element for differences - update(plt, elm); - }); - } - } - function update(plt, elm) { - // everything is async, so somehow we could have already disconnected - // this node, so be sure to do nothing if we've already disconnected - if (!elm._hasDestroyed) { - var isInitialLoad = !elm.$instance; - if (isInitialLoad) { - // haven't created a component instance for this host element yet - initInstance(plt, elm); - } - // if this component has a render function, let's fire - // it off and generate a vnode for this - elm._render(!isInitialLoad); - if (isInitialLoad) { - elm._initLoad(); - } - } - } - - function initProxy(plt, elm, instance, cmpMeta) { - var i = 0; - if (cmpMeta.methodsMeta) { - // instances will already have the methods on them - // but you can also expose methods to the proxy element - // using @Method(). Think of like .focus() for an element. - for (; i < cmpMeta.methodsMeta.length; i++) { - initMethod(cmpMeta.methodsMeta[i], elm, instance); - } - } - // used to store instance data internally so that we can add - // getters/setters with the same name, and then do change detection - var values = instance.__values = {}; - if (cmpMeta.propWillChangeMeta) { - // this component has prop WILL change methods, so init the object to store them - values.__propWillChange = {}; - } - if (cmpMeta.propDidChangeMeta) { - // this component has prop DID change methods, so init the object to store them - values.__propDidChange = {}; - } - if (cmpMeta.statesMeta) { - // add getters/setters to instance properties that are not already set as @Prop() - // these are instance properties that should trigger a render update when - // they change. Like @Prop(), except data isn't passed in and is only state data. - // Unlike @Prop, state properties do not add getters/setters to the proxy element - // and initial values are not checked against the proxy element or config - for (i = 0; i < cmpMeta.statesMeta.length; i++) { - initProperty(false, true, '', cmpMeta.statesMeta[i], 0, instance, values, plt, elm, cmpMeta.propWillChangeMeta, cmpMeta.propDidChangeMeta); - } - } - if (cmpMeta.propsMeta) { - for (i = 0; i < cmpMeta.propsMeta.length; i++) { - // add getters/setters for @Prop()s - initProperty(true, cmpMeta.propsMeta[i].isStateful, cmpMeta.propsMeta[i].attribName, cmpMeta.propsMeta[i].propName, cmpMeta.propsMeta[i].propType, instance, instance.__values, plt, elm, cmpMeta.propWillChangeMeta, cmpMeta.propDidChangeMeta); - } - } - } - function initMethod(methodName, elm, instance) { - // add a getter on the dom's element instance - // pointed at the instance's method - Object.defineProperty(elm, methodName, { - configurable: true, - value: instance[methodName].bind(instance) - }); - } - function initProperty(isProp, isStateful, attrName, propName, propType, instance, internalValues, plt, elm, propWillChangeMeta, propDidChangeMeta) { - if (isProp) { - // @Prop() property, so check initial value from the proxy element, instance - // and config, before we create getters/setters on this same property name - var hostAttrValue = elm.getAttribute(attrName); - if (hostAttrValue !== null) { - // looks like we've got an initial value from the attribute - internalValues[propName] = parsePropertyValue(propType, hostAttrValue); - } else if (elm[propName] !== undefined) { - // looks like we've got an initial value on the proxy element - internalValues[propName] = parsePropertyValue(propType, elm[propName]); - } else if (instance[propName] !== undefined) { - // looks like we've got an initial value on the instance already - internalValues[propName] = instance[propName]; - } else if (propName === 'mode') { - // special case for just "mode" property - // which all component automatically get - internalValues[propName] = plt.config.get(propName); - } - } else { - // @State() property, so copy the value directly from the instance - // before we create getters/setters on this same property name - internalValues[propName] = instance[propName]; - } - var i = 0; - if (propWillChangeMeta) { - // there are prop WILL change methods for this component - for (i = 0; i < propWillChangeMeta.length; i++) { - if (propWillChangeMeta[i][PROP_CHANGE_PROP_NAME] === propName) { - // cool, we should watch for changes to this property - // let's bind their watcher function and add it to our list - // of watchers, so any time this property changes we should - // also fire off their @PropWillChange() method - internalValues.__propWillChange[propName] = instance[propWillChangeMeta[i][PROP_CHANGE_METHOD_NAME]].bind(instance); - } - } - } - if (propDidChangeMeta) { - // there are prop DID change methods for this component - for (i = 0; i < propDidChangeMeta.length; i++) { - if (propDidChangeMeta[i][PROP_CHANGE_PROP_NAME] === propName) { - // cool, we should watch for changes to this property - // let's bind their watcher function and add it to our list - // of watchers, so any time this property changes we should - // also fire off their @PropDidChange() method - internalValues.__propDidChange[propName] = instance[propDidChangeMeta[i][PROP_CHANGE_METHOD_NAME]].bind(instance); - } - } - } - function getValue() { - // get the property value directly from our internal values - return internalValues[propName]; - } - function setValue(newVal) { - // check our new property value against our internal value - var oldVal = internalValues[propName]; - // TODO: account for Arrays/Objects - if (newVal !== oldVal) { - // gadzooks! the property's value has changed!! - if (internalValues.__propWillChange && internalValues.__propWillChange[propName]) { - // this instance is watching for when this property WILL change - internalValues.__propWillChange[propName](newVal, oldVal); - } - // set our new value! - internalValues[propName] = newVal; - if (internalValues.__propDidChange && internalValues.__propDidChange[propName]) { - // this instance is watching for when this property DID change - internalValues.__propDidChange[propName](newVal, oldVal); - } - // looks like this value actually changed, we've got work to do! - // queue that we need to do an update, don't worry - // about queuing up millions cuz this function - // ensures it only runs once - queueUpdate(plt, elm); - } - } - if (isProp) { - // dom's element instance - // only place getters/setters on element for props - // state getters/setters should not be assigned to the element - Object.defineProperty(elm, propName, { - configurable: true, - get: getValue, - set: setValue - }); - } - // user's component class instance - var instancePropDesc = { - configurable: true, - get: getValue - }; - if (isStateful) { - // this is a state property, or it's a prop that can keep state - // for props it's mainly used for props on inputs like "checked" - instancePropDesc.set = setValue; - } else { - // dev mode warning only - instancePropDesc.set = function invalidSetValue() { - // this is not a stateful prop - // so do not update the instance or host element - console.warn('@Prop() "' + propName + '" on "' + elm.tagName.toLowerCase() + '" cannot be modified.'); - }; - } - // define on component class instance - Object.defineProperty(instance, propName, instancePropDesc); - } - - function createThemedClasses(mode, color, classList) { - var allClassObj = {}; - return classList.split(' ').reduce(function (classObj, classString) { - classObj[classString] = true; - if (mode) { - classObj[classString + '-' + mode] = true; - if (color) { - classObj[classString + '-' + color] = true; - classObj[classString + '-' + mode + '-' + color] = true; - } - } - return classObj; - }, allClassObj); - } - - function render(plt, elm, isUpdateRender) { - var instance = elm.$instance; - var cmpMeta = plt.getComponentMeta(elm); - if (isUpdateRender) { - // fire off the user's componentWillUpdate method (if one was provided) - // componentWillUpdate runs BEFORE render() has been called - // but only BEFORE an UPDATE and not before the intial render - instance.componentWillUpdate && instance.componentWillUpdate(); - } - // if this component has a render function, let's fire - // it off and generate the child vnodes for this host element - // note that we do not create the host element cuz it already exists - var vnodeChildren = instance.render && instance.render(); - var vnodeHostData = instance.hostData && instance.hostData(); - var hostMeta = cmpMeta.hostMeta; - if (vnodeChildren || vnodeHostData || hostMeta) { - if (hostMeta) { - vnodeHostData = Object.keys(hostMeta).reduce(function (hostData, key) { - switch (key) { - case 'theme': - hostData['class'] = hostData['class'] || {}; - hostData['class'] = Object.assign(hostData['class'], createThemedClasses(instance.mode, instance.color, hostMeta['theme'])); - } - return hostData; - }, vnodeHostData || {}); - } - // looks like we've got child nodes to render into this host element - // or we need to update the css class/attrs on the host element - // if we haven't already created a vnode, then we give the renderer the actual element - // if this is a re-render, then give the renderer the last vnode we already created - var oldVNode = elm._vnode || new VNode(); - oldVNode.elm = elm; - // normalize host data keys to abbr. key - if (vnodeHostData) { - vnodeHostData.a = vnodeHostData['attrs']; - vnodeHostData.c = vnodeHostData['class']; - vnodeHostData.s = vnodeHostData['style']; - vnodeHostData.o = vnodeHostData['on']; - } - // each patch always gets a new vnode - // the host element itself isn't patched because it already exists - // kick off the actual render and any DOM updates - elm._vnode = plt.render(oldVNode, h(null, vnodeHostData, vnodeChildren), isUpdateRender, elm._hostContentNodes); - } - if (isUpdateRender) { - // fire off the user's componentDidUpdate method (if one was provided) - // componentDidUpdate runs AFTER render() has been called - // but only AFTER an UPDATE and not after the intial render - instance.componentDidUpdate && instance.componentDidUpdate(); - } - } - - function initHostConstructor(plt, HostElementConstructor) { - Object.defineProperties(HostElementConstructor, { - 'connectedCallback': { - value: function () { - connectedCallback(plt, this); - } - }, - 'attributeChangedCallback': { - value: function (attribName, oldVal, newVal) { - attributeChangedCallback(plt, this, attribName, oldVal, newVal); - } - }, - 'disconnectedCallback': { - value: function () { - disconnectedCallback(plt, this); - } - }, - _queueUpdate: { - value: function () { - queueUpdate(plt, this); - } - }, - _initLoad: { - value: function () { - initLoad(plt, this); - } - }, - _render: { - value: function (isInitialRender) { - render(plt, this, isInitialRender); - } - } - }); - } - function initInstance(plt, elm) { - // using the component's class, let's create a new instance - var cmpMeta = plt.getComponentMeta(elm); - var instance = elm.$instance = new cmpMeta.componentModuleMeta(); - // let's automatically add a reference to the host element on the instance - instance.$el = elm; - // so we've got an host element now, and a actual instance - // let's wire them up together with getter/settings - // the setters are use for change detection and knowing when to re-render - initProxy(plt, elm, instance, cmpMeta); - // fire off the user's componentWillLoad method (if one was provided) - // componentWillLoad only runs ONCE, after instance.$el has been assigned - // the host element, but BEFORE render() has been called - instance.componentWillLoad && instance.componentWillLoad(); - } - function initLoad(plt, elm) { - var instance = elm.$instance; - // it's possible that we've already decided to destroy this element - // check if this element has any actively loading child elements - if (instance && !elm._hasDestroyed && (!elm._activelyLoadingChildren || !elm._activelyLoadingChildren.length)) { - // cool, so at this point this element isn't already being destroyed - // and it does not have any child elements that are still loading - // ensure we remove any child references cuz it doesn't matter at this point - elm._activelyLoadingChildren = null; - // the element is within the DOM now, so let's attach the event listeners - attachListeners(plt, plt.getComponentMeta(elm).listenersMeta, elm, instance); - // sweet, this particular element is good to go - // all of this element's children have loaded (if any) - elm._hasLoaded = true; - // fire off the user's componentDidLoad method (if one was provided) - // componentDidLoad only runs ONCE, after instance.$el has been assigned - // the host element, and AFTER render() has been called - instance.componentDidLoad && instance.componentDidLoad(); - // add the css class that this element has officially hydrated - elm.classList.add(HYDRATED_CSS); - // ( •_•) - // ( •_•)>⌐■-■ - // (⌐■_■) - // load events fire from bottom to top, the deepest elements first then bubbles up - // if this element did have an ancestor host element - if (elm._ancestorHostElement) { - // ok so this element already has a known ancestor host element - // let's make sure we remove this element from its ancestor's - // known list of child elements which are actively loading - var ancestorsActivelyLoadingChildren = elm._ancestorHostElement._activelyLoadingChildren; - var index = ancestorsActivelyLoadingChildren && ancestorsActivelyLoadingChildren.indexOf(elm); - if (index > -1) { - // yup, this element is in the list of child elements to wait on - // remove it so we can work to get the length down to 0 - ancestorsActivelyLoadingChildren.splice(index, 1); - } - // the ancestor's initLoad method will do the actual checks - // to see if the ancestor is actually loaded or not - // then let's call the ancestor's initLoad method if there's no length - // (which actually ends up as this method again but for the ancestor) - !ancestorsActivelyLoadingChildren.length && elm._ancestorHostElement._initLoad(); - // fuhgeddaboudit, no need to keep a reference after this element loaded - delete elm._ancestorHostElement; - } - } - } - - function initGlobal(Gbl, win, domApi, plt, config, domCtrl) { - if (typeof win.CustomEvent !== 'function') { - // CustomEvent polyfill - var CustomEvent = function (event, params) { - params = params || { bubbles: false, cancelable: false, detail: undefined }; - var evt = domApi.$createEvent(); - evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); - return evt; - }; - - CustomEvent.prototype = win.Event.prototype; - win.CustomEvent = CustomEvent; - } - // properties that can stay hidden from public use - var controllers = Gbl.controllers = {}; - Gbl.isClient = true; - Gbl.isServer = false; - // properties to be exposed to public - // in actuality it's the exact same object - Gbl.config = config; - Gbl.dom = domCtrl; - Gbl.emit = function (instance, eventName, data) { - data = data || {}; - if (data.bubbles === undefined) { - data.bubbles = true; - } - if (data.composed === undefined) { - // https://developers.google.com/web/fundamentals/getting-started/primers/shadowdom#events - data.composed = true; - } - if (Gbl.eventNameFn) { - eventName = Gbl.eventNameFn(eventName); - } - instance && instance.$el && instance.$el.dispatchEvent(new win.CustomEvent(eventName, data)); - }; - Gbl.listener = { - enable: function (instance, eventName, shouldEnable, attachTo) { - enableListener(plt, instance.$el, instance, eventName, shouldEnable, attachTo); - }, - add: function (elm, eventName, cb, opts) { - return addEventListener(plt, elm, eventName, cb, opts); - } - }; - // used to store the queued controller promises to - // be resolved when the controller finishes loading - var queuedCtrlResolves = {}; - Gbl.controller = function (ctrlName, opts) { - // loading a controller is always async so return a promise - return new Promise(function (resolve) { - // see if we already have the controller loaded - var ctrl = controllers[ctrlName]; - if (ctrl) { - // we've already loaded this controller - resolveController(ctrl, resolve, opts); - } else { - // oh noz! we haven't already loaded this controller yet! - var ctrlResolveQueue = queuedCtrlResolves[ctrlName]; - if (ctrlResolveQueue) { - // cool we've already "started" to load the controller - // but it hasn't finished loading yet, so let's add - // this one also to the queue of to-be resolved promises - ctrlResolveQueue.push(resolve, opts); - } else { - // looks like we haven't even started the request - // yet lets add the component to the DOM and create - // a queue for this controller - queuedCtrlResolves[ctrlName] = [resolve, opts]; - domApi.$appendChild(domApi.$body, domApi.$createElement('ion-' + ctrlName + '-controller')); - } - } - }); - }; - Gbl.loadController = function (ctrlName, ctrl) { - // this method is called when the singleton - // instance of our controller initially loads - // add this controller instance to our map of controller singletons - controllers[ctrlName] = ctrl; - // check for to-be resolved controller promises - var pendingCtrlResolves = queuedCtrlResolves[ctrlName]; - if (pendingCtrlResolves) { - for (var i = 0; i < pendingCtrlResolves.length; i += 2) { - // first arg is the original promise's resolve - // which still needs to be resolved - // second arg was the originally passed in options - resolveController(ctrl, pendingCtrlResolves[i], pendingCtrlResolves[i + 1]); - } - // all good, go ahead and remove from the queue - delete queuedCtrlResolves[ctrlName]; - } - }; - function resolveController(ctrl, resolve, opts) { - if (opts) { - // if the call had options passed in then - // it should run the controller's load() method - // and let the controller's load() do the resolve - // which then will resolve the user's promise - ctrl.load(opts).then(resolve); - } else { - // no options passed in, so resolve with - // the actual controller instance - resolve(ctrl); - } - } - return Gbl; - } - - function createPlatformClient(Gbl, win, domApi, config, domCtrl, queue, staticDir) { - var registry = { 'HTML': {} }; - var moduleImports = {}; - var moduleCallbacks = {}; - var loadedModules = {}; - var pendingModuleRequests = {}; - // create the platform api which will be passed around for external use - var plt = { - registerComponents: registerComponents, - defineComponent: defineComponent, - getComponentMeta: getComponentMeta, - loadBundle: loadBundle, - config: config, - queue: queue, - connectHostElement: connectHostElement, - getEventOptions: getEventOptions - }; - // create the renderer that will be used - plt.render = createRenderer(plt, domApi); - // create the global which will be injected into the user's instances - var injectedGlobal = initGlobal(Gbl, win, domApi, plt, config, domCtrl); - // setup the root element which is the mighty tag - // the has the final say of when the app has loaded - var rootElm = domApi.$documentElement; - rootElm._activelyLoadingChildren = []; - rootElm._initLoad = function appLoadedCallback() { - // this will fire when all components have finished loaded - rootElm._hasLoaded = true; - }; - // if the HTML was generated from SSR - // then let's walk the tree and generate vnodes out of the data - createVNodesFromSsr(domApi, rootElm); - function getComponentMeta(elm) { - // get component meta using the element - // important that the registry has upper case tag names - return registry[elm.tagName]; - } - function connectHostElement(elm, slotMeta) { - // host element has been connected to the DOM - if (!domApi.$getAttribute(elm, SSR_VNODE_ID)) { - // this host element was NOT created with SSR - // let's pick out the inner content for slot projection - assignHostContentSlots(domApi, elm, slotMeta); - } - } - function registerComponents(components) { - // this is the part that just registers the minimal amount of data - // it's basically a map of the component tag name to its associated external bundles - return (components || []).map(function (data) { - return parseComponentRegistry(data, registry); - }); - } - function defineComponent(cmpMeta, HostElementConstructor) { - // initialize the properties on the component module prototype - initHostConstructor(plt, HostElementConstructor.prototype); - // add which attributes should be observed - HostElementConstructor.observedAttributes = cmpMeta.propsMeta.filter(function (p) { - return p.attribName; - }).map(function (p) { - return p.attribName; - }); - // define the custom element - win.customElements.define(cmpMeta.tagNameMeta.toLowerCase(), HostElementConstructor); - } - Gbl.defineComponents = function defineComponents(moduleId, importFn) { - var args = arguments; - // import component function - // inject globals - importFn(moduleImports, h, t, injectedGlobal); - for (var i = 2; i < args.length; i++) { - parseComponentMeta(registry, moduleImports, args[i]); - } - // fire off all the callbacks waiting on this module to load - var callbacks = moduleCallbacks[moduleId]; - if (callbacks) { - for (i = 0; i < callbacks.length; i++) { - callbacks[i](); - } - delete moduleCallbacks[moduleId]; - } - // remember that we've already loaded this module - loadedModules[moduleId] = true; - }; - function loadBundle(cmpMeta, elm, cb) { - var moduleId = cmpMeta.moduleId; - if (loadedModules[moduleId]) { - // sweet, we've already loaded this module - cb(); - } else { - // never seen this module before, let's start the request - // and add it to the callbacks to fire when it has loaded - if (moduleCallbacks[moduleId]) { - moduleCallbacks[moduleId].push(cb); - } else { - moduleCallbacks[moduleId] = [cb]; - } - // create the url we'll be requesting - var url = getBundlePath(moduleId + '.js'); - if (!pendingModuleRequests[url]) { - // not already actively requesting this url - // remember that we're now actively requesting this url - pendingModuleRequests[url] = true; - // let's kick off the module request - jsonp(url); - } - // we also need to load the css file in the head - var styleId = cmpMeta.styleIds[getMode(domApi, config, elm)] || cmpMeta.styleIds.$; - if (styleId && !loadedModules[styleId]) { - // this style hasn't been added to the head yet - loadedModules[styleId] = true; - // append this link element to the head, which starts the request for the file - var linkElm = domApi.$createElement('link'); - linkElm.href = getBundlePath(styleId + '.css'); - linkElm.rel = 'stylesheet'; - domApi.$insertBefore(domApi.$head, linkElm, domApi.$head.firstChild); - } - } - } - function getBundlePath(fileName) { - return '' + staticDir + fileName; - } - function jsonp(url) { - // create a sript element to add to the document.head - var scriptElm = domApi.$createElement('script'); - scriptElm.charset = 'utf-8'; - scriptElm.async = true; - scriptElm.src = url; - // create a fallback timeout if something goes wrong - var tmrId = setTimeout(onScriptComplete, 120000); - function onScriptComplete() { - clearTimeout(tmrId); - scriptElm.onerror = scriptElm.onload = null; - domApi.$removeChild(scriptElm.parentNode, scriptElm); - // remove from our list of active requests - delete pendingModuleRequests[url]; - } - // add script completed listener to this script element - scriptElm.onerror = scriptElm.onload = onScriptComplete; - // inject a script tag in the head - // kick off the actual request - domApi.$appendChild(domApi.$head, scriptElm); - } - // test if this browser supports event options or not - var supportsEventOptions = false; - try { - win.addEventListener('evopt', null, Object.defineProperty({}, 'passive', { - get: function () { - supportsEventOptions = true; - } - })); - } catch (e) {} - function getEventOptions(opts) { - return supportsEventOptions ? { - 'capture': !!(opts && opts.capture), - 'passive': !(opts && opts.passive === false) - } : !!(opts && opts.capture); - } - return plt; - } - - function createQueueClient(domCtrl) { - var now = domCtrl.now; - var raf = domCtrl.raf; - var highPromise = Promise.resolve(); - var highCallbacks = []; - var mediumCallbacks = []; - var lowCallbacks = []; - var resolvePending = false; - var ricPending = false; - function doHighPriority() { - // holy geez we need to get this stuff done and fast - // all high priority callbacks should be fired off immediately - while (highCallbacks.length > 0) { - highCallbacks.shift()(); - } - resolvePending = false; - } - function doWork() { - var start = now(); - // always run all of the high priority work if there is any - doHighPriority(); - while (mediumCallbacks.length > 0 && now() - start < 40) { - mediumCallbacks.shift()(); - } - if (mediumCallbacks.length === 0) { - // we successfully drained the medium queue or the medium queue is empty - // so now let's drain the low queue with our remaining time - while (lowCallbacks.length > 0 && now() - start < 40) { - lowCallbacks.shift()(); - } - } - // check to see if we still have work to do - if (ricPending = mediumCallbacks.length > 0 || lowCallbacks.length > 0) { - // everyone just settle down now - // we already don't have time to do anything in this callback - // let's throw the next one in a requestAnimationFrame - // so we can just simmer down for a bit - raf(flush); - } - } - function flush() { - // always run all of the high priority work if there is any - doHighPriority(); - // always force a bunch of medium callbacks to run, but still have - // a throttle on how many can run in a certain time - var start = now(); - while (mediumCallbacks.length > 0 && now() - start < 4) { - mediumCallbacks.shift()(); - } - if (ricPending = mediumCallbacks.length > 0 || lowCallbacks.length > 0) { - // still more to do yet, but we've run out of time - // let's let this thing cool off and try again in the next ric - raf(doWork); - } - } - function add(cb, priority) { - if (priority === PRIORITY_HIGH) { - // uses Promise.resolve() for next tick - highCallbacks.push(cb); - if (!resolvePending) { - // not already pending work to do, so let's tee it up - resolvePending = true; - highPromise.then(doHighPriority); - } - } else { - if (priority === PRIORITY_LOW) { - lowCallbacks.push(cb); - } else { - // defaults to medium priority - // uses requestIdleCallback - mediumCallbacks.push(cb); - } - if (!ricPending) { - // not already pending work to do, so let's tee it up - ricPending = true; - raf(doWork); - } - } - } - return { - add: add, - flush: flush - }; - } - - function detectPlatforms(url, userAgent, platforms, defaultPlatform) { - // bracket notation to ensure they're not property renamed - var validPlatforms = platforms.filter(function (p) { - return p['isMatch'] && p['isMatch'](url, userAgent); - }); - if (!validPlatforms.length) { - validPlatforms = platforms.filter(function (p) { - return p['name'] === defaultPlatform; - }); - } - return validPlatforms; - } - function isPlatformMatch(url, userAgent, platformName, userAgentAtLeastHas, userAgentMustNotHave) { - var queryValue = queryParam(url, 'ionicplatform'); - if (queryValue) { - return queryValue === platformName; - } - if (userAgent) { - userAgent = userAgent.toLowerCase(); - for (var i = 0; i < userAgentAtLeastHas.length; i++) { - if (userAgent.indexOf(userAgentAtLeastHas[i]) > -1) { - for (var j = 0; j < userAgentMustNotHave.length; j++) { - if (userAgent.indexOf(userAgentMustNotHave[j]) > -1) { - return false; - } - } - return true; - } - } - } - return false; - } - function queryParam(url, key) { - key = key.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]'); - var regex = new RegExp('[\\?&]' + key + '=([^&#]*)'); - var results = regex.exec(url); - return results ? decodeURIComponent(results[1].replace(/\+/g, ' ')) : null; - } - - // order from most specifc to least specific - var PLATFORM_CONFIGS = [{ - 'name': 'ipad', - 'isMatch': function (url, userAgent) { - return isPlatformMatch(url, userAgent, 'ipad', ['ipad'], ['windows phone']); - } - }, { - 'name': 'iphone', - 'isMatch': function (url, userAgent) { - return isPlatformMatch(url, userAgent, 'iphone', ['iphone'], ['windows phone']); - } - }, { - 'name': 'ios', - 'settings': { - 'mode': 'ios' - }, - 'isMatch': function (url, userAgent) { - return isPlatformMatch(url, userAgent, 'ios', ['iphone', 'ipad', 'ipod'], ['windows phone']); - } - }, { - 'name': 'android', - 'settings': { - 'activator': 'ripple', - 'mode': 'md' - }, - 'isMatch': function (url, userAgent) { - return isPlatformMatch(url, userAgent, 'android', ['android', 'silk'], ['windows phone']); - } - }, { - 'name': 'windows', - 'settings': { - 'mode': 'wp' - }, - 'isMatch': function (url, userAgent) { - return isPlatformMatch(url, userAgent, 'windows', ['windows phone'], []); - } - }, { - 'name': 'core', - 'settings': { - 'mode': 'md' - } - }]; - - var Gbl = window[globalNamespace] = window[globalNamespace] || {}; - var domCtrl = createDomControllerClient(window); - var plt = createPlatformClient(Gbl, window, createDomApi(document), createConfigController(Gbl.config, detectPlatforms(window.location.href, window.navigator.userAgent, PLATFORM_CONFIGS, 'core')), domCtrl, createQueueClient(domCtrl), Gbl.staticDir); - plt.registerComponents(Gbl.components).forEach(function (cmpMeta) { - function HostElement(self) { - return HTMLElement.call(this, self); - } - HostElement.prototype = Object.create(HTMLElement.prototype, { constructor: { value: HostElement, configurable: true } }); - plt.defineComponent(cmpMeta, HostElement); - }); -})(window, document, "App"); \ No newline at end of file diff --git a/packages/stencil-fiber-demo/www/build/app/app.core.js b/packages/stencil-fiber-demo/www/build/app/app.core.js deleted file mode 100644 index c5fd0ac6ce..0000000000 --- a/packages/stencil-fiber-demo/www/build/app/app.core.js +++ /dev/null @@ -1,2064 +0,0 @@ -/*! Built with http://stenciljs.com */ - -(function (window, document, globalNamespace) { - "use strict"; - - function createConfigController(configObj, platforms) { - configObj = configObj || {}; - function get(key, fallback) { - if (configObj[key] !== undefined) { - return configObj[key]; - } - var settings = null; - for (var i = 0; i < platforms.length; i++) { - settings = platforms[i]['settings']; - if (settings && settings[key] !== undefined) { - return settings[key]; - } - } - return fallback !== undefined ? fallback : null; - } - function getBoolean(key, fallback) { - var val = get(key); - if (val === null) { - return fallback !== undefined ? fallback : false; - } - if (typeof val === 'string') { - return val === 'true'; - } - return !!val; - } - function getNumber(key, fallback) { - var val = parseFloat(get(key)); - return isNaN(val) ? fallback !== undefined ? fallback : NaN : val; - } - return { - get: get, - getBoolean: getBoolean, - getNumber: getNumber - }; - } - - function createDomApi(document) { - // using the $ prefix so that closure if - // cool with property renaming each of these - return { - $documentElement: document.documentElement, - $head: document.head, - $body: document.body, - $nodeType: function nodeType(node) { - return node.nodeType; - }, - $createEvent: function createEvent() { - return document.createEvent('CustomEvent'); - }, - $createElement: function createElement(tagName) { - return document.createElement(tagName); - }, - $createElementNS: function createElementNS(namespace, tagName) { - return document.createElementNS(namespace, tagName); - }, - $createTextNode: function createTextNode(text) { - return document.createTextNode(text); - }, - $createComment: function createComment(data) { - return document.createComment(data); - }, - $insertBefore: function insertBefore(parentNode, childNode, referenceNode) { - parentNode.insertBefore(childNode, referenceNode); - }, - $removeChild: function removeChild(parentNode, childNode) { - return parentNode.removeChild(childNode); - }, - $appendChild: function appendChild(parentNode, childNode) { - parentNode.appendChild(childNode); - }, - $childNodes: function childNodes(node) { - return node.childNodes; - }, - $parentNode: function parentNode(node) { - return node.parentNode; - }, - $nextSibling: function nextSibling(node) { - return node.nextSibling; - }, - $tagName: function tagName(elm) { - return elm.tagName; - }, - $getTextContent: function (node) { - return node.textContent; - }, - $setTextContent: function setTextContent(node, text) { - node.textContent = text; - }, - $getAttribute: function getAttribute(elm, key) { - return elm.getAttribute(key); - }, - $setAttribute: function setAttribute(elm, key, val) { - elm.setAttribute(key, val); - }, - $setAttributeNS: function $setAttributeNS(elm, namespaceURI, qualifiedName, val) { - elm.setAttributeNS(namespaceURI, qualifiedName, val); - }, - $removeAttribute: function removeAttribute(elm, key) { - elm.removeAttribute(key); - } - }; - } - - function createDomControllerClient(win) { - var readCBs = []; - var writeCBs = []; - var rafPending = false; - function now() { - return win.performance.now(); - } - function raf(cb) { - return win.requestAnimationFrame(cb); - } - function domRead(cb) { - readCBs.push(cb); - if (!rafPending) { - rafPending = true; - raf(rafFlush); - } - } - function domWrite(cb) { - writeCBs.push(cb); - if (!rafPending) { - rafPending = true; - raf(rafFlush); - } - } - function rafFlush(timeStamp, startTime, cb, err) { - try { - startTime = now(); - // ******** DOM READS **************** - while (cb = readCBs.shift()) { - cb(timeStamp); - } - // ******** DOM WRITES **************** - while (cb = writeCBs.shift()) { - cb(timeStamp); - if (now() - startTime > 8) { - break; - } - } - } catch (e) { - err = e; - } - if (rafPending = readCBs.length > 0 || writeCBs.length > 0) { - raf(rafFlush); - } - if (err) { - console.error(err); - } - } - return { - read: domRead, - write: domWrite, - raf: raf, - now: now - }; - } - - /** - * This constants file is largely for minification tricks, and to - * have easy to read variable names. Enums would make more sense - * in most cases, but doing values like this as constants allows - * minifiers to just place the raw value directly in source, and in - * production there is no variable at all. For example, the minifier - * turns data[BUNDLE_ID] turns into data[0] for production builds. - */ - /** - * Prop Change Meta Indexes - */ - var PROP_CHANGE_PROP_NAME = 0; - var PROP_CHANGE_METHOD_NAME = 1; - /** - * Property Types - */ - - var TYPE_BOOLEAN = 1; - var TYPE_NUMBER = 2; - /** - * JS Property to Attribute Name Options - */ - - var ATTR_LOWER_CASE = 1; - /** - * Priority Levels - */ - var PRIORITY_HIGH = 3; - - var PRIORITY_LOW = 1; - /** - * Slot Meta - */ - var SLOT_TAG = 0; - var HAS_SLOTS = 1; - var HAS_NAMED_SLOTS = 2; - /** - * SSR Attribute Names - */ - var SSR_VNODE_ID = 'ssrv'; - var SSR_CHILD_ID = 'ssrc'; - /** - * Node Types - */ - var ELEMENT_NODE = 1; - var TEXT_NODE = 3; - var COMMENT_NODE = 8; - /** - * Key Name to Key Code Map - */ - var KEY_CODE_MAP = { - 'enter': 13, - 'escape': 27, - 'space': 32, - 'tab': 9 - }; - /** - * CSS class that gets added to the host element - * after the component has fully hydrated - */ - var HYDRATED_CSS = 'hydrated'; - /** - * Namespaces - */ - - /** - * File names and value - */ - - class VNode {} - - /** - * Production h() function based on Preact by - * Jason Miller (@developit) - * Licensed under the MIT License - * https://github.com/developit/preact/blob/master/LICENSE - * - * Modified for Stencil's compiler and vdom - */ - var stack = []; - function h(nodeName, vnodeData, child) { - var children = void 0, - lastSimple = void 0, - simple = void 0, - i = void 0; - for (i = arguments.length; i-- > 2;) { - stack.push(arguments[i]); - } - while (stack.length) { - if ((child = stack.pop()) && child.pop !== undefined) { - for (i = child.length; i--;) { - stack.push(child[i]); - } - } else { - if (typeof child === 'boolean') child = null; - if (simple = typeof nodeName !== 'function') { - if (child == null) child = '';else if (typeof child === 'number') child = String(child);else if (typeof child !== 'string') simple = false; - } - if (simple && lastSimple) { - children[children.length - 1].vtext += child; - } else if (children === undefined) { - children = [simple ? t(child) : child]; - } else { - children.push(simple ? t(child) : child); - } - lastSimple = simple; - } - } - var vnode = new VNode(); - vnode.vtag = nodeName; - vnode.vchildren = children; - if (vnodeData) { - // data object was provided - vnode.vattrs = vnodeData.a; - vnode.vprops = vnodeData.p; - vnode.vclass = vnodeData.c; - vnode.vstyle = vnodeData.s; - vnode.vlisteners = vnodeData.o; - vnode.vkey = vnodeData.k; - vnode.vnamespace = vnodeData.n; - // x = undefined: always check both data and children - // x = 0 skip checking only data on update - // x = 1 skip checking only children on update - // x = 2 skip checking both data and children on update - vnode.skipDataOnUpdate = vnodeData.x === 0 || vnodeData.x === 2; - vnode.skipChildrenOnUpdate = vnodeData.x > 0; - } else { - // no data object was provided - // so no data, so don't both checking data - vnode.skipDataOnUpdate = true; - // since no data was provided, than no x was provided - // if no x was provided then we need to always check children - // if if there are no children at all, then we know never to check children - vnode.skipChildrenOnUpdate = !children || children.length === 0; - } - return vnode; - } - function t(textValue) { - var vnode = new VNode(); - vnode.vtext = textValue; - return vnode; - } - - function createVNodesFromSsr(domApi, rootElm) { - var allSsrElms = rootElm.querySelectorAll('[' + SSR_VNODE_ID + ']'), - elm, - ssrVNodeId, - ssrVNode, - i, - ilen = allSsrElms.length, - j, - jlen; - if (rootElm._hasLoaded = ilen > 0) { - for (i = 0; i < ilen; i++) { - elm = allSsrElms[i]; - ssrVNodeId = domApi.$getAttribute(elm, SSR_VNODE_ID); - ssrVNode = elm._vnode = new VNode(); - ssrVNode.vtag = domApi.$tagName(ssrVNode.elm = elm).toLowerCase(); - for (j = 0, jlen = elm.childNodes.length; j < jlen; j++) { - addChildSsrVNodes(domApi, elm.childNodes[j], ssrVNode, ssrVNodeId, true); - } - } - } - } - function addChildSsrVNodes(domApi, node, parentVNode, ssrVNodeId, checkNestedElements) { - var nodeType = domApi.$nodeType(node); - var previousComment; - var childVNodeId, childVNodeSplt, childVNode; - if (checkNestedElements && nodeType === ELEMENT_NODE) { - childVNodeId = domApi.$getAttribute(node, SSR_CHILD_ID); - if (childVNodeId) { - // split the start comment's data with a period - childVNodeSplt = childVNodeId.split('.'); - // ensure this this element is a child element of the ssr vnode - if (childVNodeSplt[0] === ssrVNodeId) { - // cool, this element is a child to the parent vnode - childVNode = new VNode(); - childVNode.vtag = domApi.$tagName(childVNode.elm = node).toLowerCase(); - // this is a new child vnode - // so ensure its parent vnode has the vchildren array - if (!parentVNode.vchildren) { - parentVNode.vchildren = []; - } - // add our child vnode to a specific index of the vnode's children - parentVNode.vchildren[childVNodeSplt[1]] = childVNode; - // this is now the new parent vnode for all the next child checks - parentVNode = childVNode; - // if there's a trailing period, then it means there aren't any - // more nested elements, but maybe nested text nodes - // either way, don't keep walking down the tree after this next call - checkNestedElements = childVNodeSplt[2] !== ''; - } - } - // keep drilling down through the elements - for (var i = 0; i < node.childNodes.length; i++) { - addChildSsrVNodes(domApi, node.childNodes[i], parentVNode, ssrVNodeId, checkNestedElements); - } - } else if (nodeType === TEXT_NODE && (previousComment = node.previousSibling) && domApi.$nodeType(previousComment) === COMMENT_NODE) { - // split the start comment's data with a period - childVNodeSplt = domApi.$getTextContent(previousComment).split('.'); - // ensure this is an ssr text node start comment - // which should start with an "s" and delimited by periods - if (childVNodeSplt[0] === 's' && childVNodeSplt[1] === ssrVNodeId) { - // cool, this is a text node and it's got a start comment - childVNode = t(domApi.$getTextContent(node)); - childVNode.elm = node; - // this is a new child vnode - // so ensure its parent vnode has the vchildren array - if (!parentVNode.vchildren) { - parentVNode.vchildren = []; - } - // add our child vnode to a specific index of the vnode's children - parentVNode.vchildren[childVNodeSplt[2]] = childVNode; - } - } - } - function assignHostContentSlots(domApi, elm, slotMeta) { - // compiler has already figured out if this component has slots or not - // if the component doesn't even have slots then we'll skip over all of this code - var childNodes = elm.childNodes; - if (slotMeta === HAS_NAMED_SLOTS) { - // looks like this component has named slots - // so let's loop through each of the childNodes to the host element - // and pick out the ones that have a slot attribute - // if it doesn't have a slot attribute, than it's a default slot - var slotName = void 0; - var defaultSlot = void 0; - var namedSlots = void 0; - for (var i = 0, childNodeLen = childNodes.length; i < childNodeLen; i++) { - var childNode = childNodes[i]; - if (domApi.$nodeType(childNode) === 1 && (slotName = domApi.$getAttribute(childNode, 'slot')) != null) { - // is element node - // this element has a slot name attribute - // so this element will end up getting relocated into - // the component's named slot once it renders - namedSlots = namedSlots || {}; - if (namedSlots[slotName]) { - namedSlots[slotName].push(childNode); - } else { - namedSlots[slotName] = [childNode]; - } - } else { - // this is a text node - // or it's an element node that doesn't have a slot attribute - // let's add this node to our collection for the default slot - if (defaultSlot) { - defaultSlot.push(childNode); - } else { - defaultSlot = [childNode]; - } - } - } - // keep a reference to all of the initial nodes - // found as immediate childNodes to the host element - elm._hostContentNodes = { - defaultSlot: defaultSlot, - namedSlots: namedSlots - }; - } else if (slotMeta === HAS_SLOTS) { - // this component doesn't have named slots, but it does - // have at least a default slot, so the work here is alot easier than - // when we're not looping through each element and reading attribute values - elm._hostContentNodes = { - defaultSlot: childNodes.length ? Array.apply(null, childNodes) : null - }; - } - } - - function isDef(v) { - return v !== undefined && v !== null; - } - function isUndef(v) { - return v === undefined || v === null; - } - - function isObject(v) { - return v !== null && typeof v === 'object'; - } - - function isFunction(v) { - return typeof v === 'function'; - } - - function toDashCase(str) { - return str.replace(/([A-Z])/g, function (g) { - return '-' + g[0].toLowerCase(); - }); - } - - function noop() {} - - function getElementReference(elm, ref) { - if (ref === 'child') { - return elm.firstElementChild; - } - if (ref === 'parent') { - return getParentElement(elm) || elm; - } - if (ref === 'body') { - return elm.ownerDocument.body; - } - if (ref === 'document') { - return elm.ownerDocument; - } - if (ref === 'window') { - return elm.ownerDocument.defaultView; - } - return elm; - } - function getParentElement(elm) { - if (elm.parentElement) { - // normal element with a parent element - return elm.parentElement; - } - if (elm.parentNode && elm.parentNode.host) { - // shadow dom's document fragment - return elm.parentNode.host; - } - return null; - } - - var EMPTY = {}; - var DEFAULT_OPTS = null; - function updateElement(plt, nodeOps, oldVnode, newVnode) { - var isUpdate = oldVnode != null; - oldVnode = oldVnode || EMPTY; - newVnode = newVnode || EMPTY; - var key, - cur, - elm = newVnode.elm, - oldData, - newData; - // update attrs - if (oldVnode.vattrs || newVnode.vattrs) { - oldData = oldVnode.vattrs || EMPTY; - newData = newVnode.vattrs || EMPTY; - // update modified attributes, add new attributes - for (key in newData) { - cur = newData[key]; - if (oldData[key] !== cur) { - if (BOOLEAN_ATTRS[key] === 1) { - if (cur) { - nodeOps.$setAttribute(elm, key, ''); - } else { - nodeOps.$removeAttribute(elm, key); - } - } else { - if (key.charCodeAt(0) !== 120 /* xChar */) { - nodeOps.$setAttribute(elm, key, cur); - } else if (key.charCodeAt(3) === 58 /* colonChar */) { - // Assume xml namespace - nodeOps.$setAttributeNS(elm, XML_NS$1, key, cur); - } else if (key.charCodeAt(5) === 58 /* colonChar */) { - // Assume xlink namespace - nodeOps.$setAttributeNS(elm, XLINK_NS$1, key, cur); - } else { - nodeOps.$setAttribute(elm, key, cur); - } - } - } - } - // remove removed attributes - // use `in` operator since the previous `for` iteration uses it (.i.e. add even attributes with undefined value) - // the other option is to remove all attributes with value == undefined - if (isUpdate) { - for (key in oldData) { - if (!(key in newData)) { - nodeOps.$removeAttribute(elm, key); - } - } - } - } - // update class - if (oldVnode.vclass || newVnode.vclass) { - oldData = oldVnode.vclass || EMPTY; - newData = newVnode.vclass || EMPTY; - if (isUpdate) { - for (key in oldData) { - if (!newData[key]) { - elm.classList.remove(key); - } - } - } - for (key in newData) { - cur = newData[key]; - if (cur !== oldData[key]) { - elm.classList[newData[key] ? 'add' : 'remove'](key); - } - } - } - // update props - if (oldVnode.vprops || newVnode.vprops) { - oldData = oldVnode.vprops || EMPTY; - newData = newVnode.vprops || EMPTY; - if (isUpdate) { - for (key in oldData) { - if (newData[key] === undefined) { - // only delete the old property when the - // new property is undefined, otherwise we'll - // end up deleting getters/setters - delete elm[key]; - } - } - } - for (key in newData) { - cur = newData[key]; - if (oldData[key] !== cur && (key !== 'value' || elm[key] !== cur)) { - elm[key] = cur; - } - } - } - // update style - if (oldVnode.vstyle || newVnode.vstyle) { - oldData = oldVnode.vstyle || EMPTY; - newData = newVnode.vstyle || EMPTY; - if (isUpdate) { - for (key in oldData) { - if (!newData[key]) { - elm.style[key] = ''; - } - } - } - for (key in newData) { - cur = newData[key]; - if (cur !== oldData[key]) { - elm.style[key] = cur; - } - } - } - // update event listeners - oldData = oldVnode.vlisteners; - newData = newVnode.vlisteners; - if (oldData || newData) { - if (!DEFAULT_OPTS) { - DEFAULT_OPTS = plt.getEventOptions(); - } - // remove existing listeners which no longer used - if (isUpdate && oldData && oldVnode.assignedListener) { - // if element changed or deleted we remove all existing listeners unconditionally - for (key in oldData) { - // remove listener if existing listener removed - if (!newData || !newData[key]) { - oldVnode.elm.removeEventListener(key, oldVnode.assignedListener, DEFAULT_OPTS); - } - } - } - // add new listeners which has not already attached - if (newData) { - // reuse existing listener or create new - cur = newVnode.assignedListener = oldVnode.assignedListener || createListener(); - // update vnode for listener - cur.vnode = newVnode; - // if element changed or added we add all needed listeners unconditionally - for (key in newData) { - // add listener if new listener added - if (!oldData || !oldData[key]) { - elm.addEventListener(key, cur, DEFAULT_OPTS); - } - } - } - } - } - function createListener() { - return function handler(event) { - handleEvent(event, handler.vnode); - }; - } - function handleEvent(event, vnode) { - var eventName = event.type, - on = vnode.vlisteners; - // call event handler(s) if they exists - if (on && on[eventName]) { - invokeHandler(on[eventName], vnode, event); - } - } - function invokeHandler(handler, vnode, event) { - if (isFunction(handler)) { - // call function handler - handler.call(vnode, event, vnode); - } else if (isObject(handler)) { - // call handler with arguments - if (isFunction(handler[0])) { - // special case for single argument for performance - if (handler.length === 2) { - handler[0].call(vnode, handler[1], event, vnode); - } else { - var args = handler.slice(1); - args.push(event); - args.push(vnode); - handler[0].apply(vnode, args); - } - } else { - // call multiple handlers - for (var i = 0; i < handler.length; i++) { - invokeHandler(handler[i]); - } - } - } - } - var BOOLEAN_ATTRS = { - 'allowfullscreen': 1, - 'async': 1, - 'autofocus': 1, - 'autoplay': 1, - 'checked': 1, - 'controls': 1, - 'disabled': 1, - 'enabled': 1, - 'formnovalidate': 1, - 'hidden': 1, - 'multiple': 1, - 'noresize': 1, - 'readonly': 1, - 'required': 1, - 'selected': 1, - 'spellcheck': 1 - }; - var XLINK_NS$1 = 'http://www.w3.org/1999/xlink'; - var XML_NS$1 = 'http://www.w3.org/XML/1998/namespace'; - - /** - * Virtual DOM patching algorithm based on Snabbdom by - * Simon Friis Vindum (@paldepind) - * Licensed under the MIT License - * https://github.com/snabbdom/snabbdom/blob/master/LICENSE - * - * Modified for Stencil's renderer and slot projection - */ - function createRenderer(plt, domApi) { - // createRenderer() is only created once per app - // the patch() function which createRenderer() returned is the function - // which gets called numerous times by each component - function createElm(vnode, parentElm, childIndex) { - var i = 0; - if (vnode.vtag === SLOT_TAG) { - if (hostContentNodes) { - // special case for manually relocating host content nodes - // to their new home in either a named slot or the default slot - var namedSlot = vnode.vattrs && vnode.vattrs.name; - var slotNodes = void 0; - if (isDef(namedSlot)) { - // this vnode is a named slot - slotNodes = hostContentNodes.namedSlots && hostContentNodes.namedSlots[namedSlot]; - } else { - // this vnode is the default slot - slotNodes = hostContentNodes.defaultSlot; - } - if (isDef(slotNodes)) { - // the host element has some nodes that need to be moved around - // we have a slot for the user's vnode to go into - // while we're moving nodes around, temporarily disable - // the disconnectCallback from working - plt.tmpDisconnected = true; - for (; i < slotNodes.length; i++) { - // remove the host content node from it's original parent node - // then relocate the host content node to its new slotted home - domApi.$appendChild(parentElm, domApi.$removeChild(domApi.$parentNode(slotNodes[i]), slotNodes[i])); - } - // done moving nodes around - // allow the disconnect callback to work again - plt.tmpDisconnected = false; - } - } - // this was a slot node, we do not create slot elements, our work here is done - // no need to return any element to be added to the dom - return null; - } - if (isDef(vnode.vtext)) { - // create text node - vnode.elm = domApi.$createTextNode(vnode.vtext); - } else { - // create element - var elm = vnode.elm = vnode.vnamespace ? domApi.$createElementNS(vnode.vnamespace, vnode.vtag) : domApi.$createElement(vnode.vtag); - // add css classes, attrs, props, listeners, etc. - updateElement(plt, domApi, null, vnode); - var children = vnode.vchildren; - if (isDef(ssrId)) { - // SSR ONLY: this is an SSR render and this - // logic does not run on the client - // give this element the SSR child id that can be read by the client - domApi.$setAttribute(vnode.elm, SSR_CHILD_ID, ssrId + '.' + childIndex + (hasChildNodes(children) ? '' : '.')); - } - if (children) { - var childNode = void 0; - for (; i < children.length; ++i) { - // create the node - childNode = createElm(children[i], elm, i); - // return node could have been null - if (childNode) { - if (isDef(ssrId) && childNode.nodeType === 3) { - // SSR ONLY: add the text node's start comment - domApi.$appendChild(elm, domApi.$createComment('s.' + ssrId + '.' + i)); - } - // append our new node - domApi.$appendChild(elm, childNode); - if (isDef(ssrId) && childNode.nodeType === 3) { - // SSR ONLY: add the text node's end comment - domApi.$appendChild(elm, domApi.$createComment('/')); - } - } - } - } - } - return vnode.elm; - } - function addVnodes(parentElm, before, vnodes, startIdx, endIdx) { - var childNode = void 0; - for (; startIdx <= endIdx; ++startIdx) { - var vnodeChild = vnodes[startIdx]; - if (isDef(vnodeChild)) { - if (isDef(vnodeChild.vtext)) { - childNode = domApi.$createTextNode(vnodeChild.vtext); - } else { - childNode = createElm(vnodeChild, parentElm, startIdx); - } - if (isDef(childNode)) { - vnodeChild.elm = childNode; - domApi.$insertBefore(parentElm, childNode, before); - } - } - } - } - function removeVnodes(parentElm, vnodes, startIdx, endIdx) { - for (; startIdx <= endIdx; ++startIdx) { - var vnode = vnodes[startIdx]; - if (isDef(vnode)) { - if (isDef(vnode.elm)) { - invokeDestroy(vnode); - } - domApi.$removeChild(parentElm, vnode.elm); - } - } - } - function updateChildren(parentElm, oldCh, newCh) { - var oldStartIdx = 0, - newStartIdx = 0; - var oldEndIdx = oldCh.length - 1; - var oldStartVnode = oldCh[0]; - var oldEndVnode = oldCh[oldEndIdx]; - var newEndIdx = newCh.length - 1; - var newStartVnode = newCh[0]; - var newEndVnode = newCh[newEndIdx]; - var oldKeyToIdx = void 0; - var idxInOld = void 0; - var elmToMove = void 0; - var node = void 0; - while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) { - if (oldStartVnode == null) { - oldStartVnode = oldCh[++oldStartIdx]; // Vnode might have been moved left - } else if (oldEndVnode == null) { - oldEndVnode = oldCh[--oldEndIdx]; - } else if (newStartVnode == null) { - newStartVnode = newCh[++newStartIdx]; - } else if (newEndVnode == null) { - newEndVnode = newCh[--newEndIdx]; - } else if (isSameVnode(oldStartVnode, newStartVnode)) { - patchVNode(oldStartVnode, newStartVnode); - oldStartVnode = oldCh[++oldStartIdx]; - newStartVnode = newCh[++newStartIdx]; - } else if (isSameVnode(oldEndVnode, newEndVnode)) { - patchVNode(oldEndVnode, newEndVnode); - oldEndVnode = oldCh[--oldEndIdx]; - newEndVnode = newCh[--newEndIdx]; - } else if (isSameVnode(oldStartVnode, newEndVnode)) { - patchVNode(oldStartVnode, newEndVnode); - domApi.$insertBefore(parentElm, oldStartVnode.elm, domApi.$nextSibling(oldEndVnode.elm)); - oldStartVnode = oldCh[++oldStartIdx]; - newEndVnode = newCh[--newEndIdx]; - } else if (isSameVnode(oldEndVnode, newStartVnode)) { - patchVNode(oldEndVnode, newStartVnode); - domApi.$insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm); - oldEndVnode = oldCh[--oldEndIdx]; - newStartVnode = newCh[++newStartIdx]; - } else { - if (isUndef(oldKeyToIdx)) { - oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx); - } - idxInOld = oldKeyToIdx[newStartVnode.vkey]; - if (isUndef(idxInOld)) { - // new element - node = createElm(newStartVnode, parentElm, newStartIdx); - newStartVnode = newCh[++newStartIdx]; - } else { - elmToMove = oldCh[idxInOld]; - if (elmToMove.vtag !== newStartVnode.vtag) { - node = createElm(newStartVnode, parentElm, idxInOld); - } else { - patchVNode(elmToMove, newStartVnode); - oldCh[idxInOld] = undefined; - node = elmToMove.elm; - } - newStartVnode = newCh[++newStartIdx]; - } - if (node) { - domApi.$insertBefore(parentElm, node, oldStartVnode.elm); - } - } - } - if (oldStartIdx > oldEndIdx) { - addVnodes(parentElm, newCh[newEndIdx + 1] == null ? null : newCh[newEndIdx + 1].elm, newCh, newStartIdx, newEndIdx); - } else if (newStartIdx > newEndIdx) { - removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx); - } - } - function isSameVnode(vnode1, vnode2) { - // compare if two vnode to see if they're "technically" the same - // need to have the same element tag, and same key to be the same - return vnode1.vtag === vnode2.vtag && vnode1.vkey === vnode2.vkey; - } - function createKeyToOldIdx(children, beginIdx, endIdx) { - var i = void 0, - map = {}, - key = void 0, - ch = void 0; - for (i = beginIdx; i <= endIdx; ++i) { - ch = children[i]; - if (ch != null) { - key = ch.vkey; - if (key !== undefined) { - map.k = i; - } - } - } - return map; - } - function patchVNode(oldVnode, newVnode) { - var elm = newVnode.elm = oldVnode.elm; - var oldChildren = oldVnode.vchildren; - var newChildren = newVnode.vchildren; - if (isUndef(newVnode.vtext)) { - // element node - if ((!isUpdate || !newVnode.skipDataOnUpdate) && newVnode.vtag !== SLOT_TAG) { - // either this is the first render of an element OR it's an update - // AND we already know it's possible it could have changed - // this updates the element's css classes, attrs, props, listeners, etc. - updateElement(plt, domApi, oldVnode, newVnode); - } - if (isDef(oldChildren) && isDef(newChildren)) { - // looks like there's child vnodes for both the old and new vnodes - if (!isUpdate || !newVnode.skipChildrenOnUpdate) { - // either this is the first render of an element OR it's an update - // AND we already know it's possible that the children could have changed - updateChildren(elm, oldChildren, newChildren); - } - } else if (isDef(newChildren)) { - // no old child vnodes, but there are new child vnodes to add - if (isDef(oldVnode.vtext)) { - // the old vnode was text, so be sure to clear it out - domApi.$setTextContent(elm, ''); - } - // add the new vnode children - addVnodes(elm, null, newChildren, 0, newChildren.length - 1); - } else if (isDef(oldChildren)) { - // no new child vnodes, but there are old child vnodes to remove - removeVnodes(elm, oldChildren, 0, oldChildren.length - 1); - } - } else if (elm._hostContentNodes && elm._hostContentNodes.defaultSlot) { - // this element has slotted content - var parentElement = elm._hostContentNodes.defaultSlot[0].parentElement; - domApi.$setTextContent(parentElement, newVnode.vtext); - elm._hostContentNodes.defaultSlot = [parentElement.childNodes[0]]; - } else { - // update the text content for the text only vnode - domApi.$setTextContent(elm, newVnode.vtext); - } - } - // internal variables to be reused per patch() call - var isUpdate = void 0, - hostContentNodes = void 0, - ssrId = void 0; - return function patch(oldVnode, newVnode, isUpdatePatch, hostElementContentNodes, ssrPatchId) { - // patchVNode() is synchronous - // so it is safe to set these variables and internally - // the same patch() call will reference the same data - isUpdate = isUpdatePatch; - hostContentNodes = hostElementContentNodes; - ssrId = ssrPatchId; - // synchronous patch - patchVNode(oldVnode, newVnode); - if (isDef(ssrId)) { - // SSR ONLY: we've been given an SSR id, so the host element - // should be given the ssr id attribute - domApi.$setAttribute(oldVnode.elm, SSR_VNODE_ID, ssrId); - } - // return our new vnode - return newVnode; - }; - } - function invokeDestroy(vnode) { - if (vnode.vlisteners && vnode.assignedListener) { - for (var key in vnode.vlisteners) { - vnode.elm.removeEventListener(key, vnode.vlisteners, false); - } - } - if (isDef(vnode.vchildren)) { - for (var i = 0; i < vnode.vchildren.length; ++i) { - vnode.vchildren[i] && invokeDestroy(vnode.vchildren[i]); - } - } - } - function hasChildNodes(children) { - // SSR ONLY: check if there are any more nested child elements - // if there aren't, this info is useful so the client runtime - // doesn't have to climb down and check so many elements - if (children) { - for (var i = 0; i < children.length; i++) { - if (children[i].vtag !== SLOT_TAG || hasChildNodes(children[i].vchildren)) { - return true; - } - } - } - return false; - } - - function getMode(domApi, config, elm) { - var attrMode = domApi.$getAttribute(elm, 'mode'); - // first let's see if they set the mode directly on the property - if (isDef(elm.mode)) { - return elm.mode; - } - // next let's see if they set the mode on the elements attribute - if (isDef(attrMode)) { - return attrMode; - } - // ok fine, let's just get the values from the config - return config.get('mode', 'md'); - } - - function attachListeners(plt, listeners, elm, instance) { - if (listeners) { - for (var i = 0; i < listeners.length; i++) { - var listener = listeners[i]; - if (listener.eventEnabled !== false) { - (elm._listeners = elm._listeners || {})[listener.eventName] = addEventListener(plt, elm, listener.eventName, instance[listener.eventMethodName].bind(instance), listener); - } - } - } - } - function enableListener(plt, elm, instance, eventName, shouldEnable, attachTo) { - if (instance) { - var listenerMeta = plt.getComponentMeta(elm).listenersMeta; - if (listenerMeta) { - var deregisterFns = elm._listeners = elm._listeners || {}; - for (var i = 0; i < listenerMeta.length; i++) { - var listener = listenerMeta[i]; - if (listener.eventName === eventName) { - if (shouldEnable && !deregisterFns[eventName]) { - var attachToEventName = attachTo ? attachTo + ':' + eventName : eventName; - deregisterFns[eventName] = addEventListener(plt, instance.$el, attachToEventName, instance[listener.eventMethodName].bind(instance), listener); - } else if (!shouldEnable && deregisterFns[eventName]) { - deregisterFns[eventName](); - delete elm._listeners[eventName]; - } - return; - } - } - } - } - } - function addEventListener(plt, elm, eventName, userEventListener, opts) { - if (!elm) { - return noop; - } - var splt = eventName.split(':'); - if (splt.length > 1) { - // document:mousemove - // parent:touchend - // body:keyup.enter - elm = getElementReference(elm, splt[0]); - eventName = splt[1]; - } - if (!elm) { - return noop; - } - splt = eventName.split('.'); - var testKeyCode = 0; - if (splt.length > 1) { - // keyup.enter - eventName = splt[0]; - testKeyCode = KEY_CODE_MAP[splt[1]]; - } - var eventListener = function (ev) { - if (testKeyCode > 0 && ev.keyCode !== testKeyCode) { - // we're looking for a specific keycode but this wasn't it - return; - } - // fire the component's event listener callback - userEventListener(ev); - // test if this is the user's interaction - if (isUserInteraction(eventName)) { - // so it's very important to flush the queue now - // so that the app reflects whatever they just did - // basically don't let requestIdleCallback delay the important - plt.queue.flush(); - } - }; - var eventListenerOpts = plt.getEventOptions(opts); - elm.addEventListener(eventName, eventListener, eventListenerOpts); - return function removeListener() { - if (elm) { - elm.removeEventListener(eventName, eventListener, eventListenerOpts); - } - }; - } - function isUserInteraction(eventName) { - for (var i = 0; i < USER_INTERACTIONS.length; i++) { - if (eventName.indexOf(USER_INTERACTIONS[i]) > -1) { - return true; - } - } - return false; - } - var USER_INTERACTIONS = ['touch', 'mouse', 'pointer', 'key', 'focus', 'blur', 'drag']; - function detachListeners(elm) { - var deregisterFns = elm._listeners; - if (deregisterFns) { - var eventNames = Object.keys(deregisterFns); - for (var i = 0; i < eventNames.length; i++) { - deregisterFns[eventNames[i]](); - } - elm._listeners = null; - } - } - - function parseComponentRegistry(cmpRegistryData, registry) { - // tag name will always be upper case - var cmpMeta = { - tagNameMeta: cmpRegistryData[0], - propsMeta: [ - // every component defaults to always have - // the mode and color properties - // but only observe the color attribute - // mode cannot change after the component was created - { propName: 'color', attribName: 'color' }, { propName: 'mode' }] - }; - cmpMeta.moduleId = cmpRegistryData[1]; - // map of the modes w/ bundle id and style data - cmpMeta.styleIds = cmpRegistryData[2] || {}; - // slot - cmpMeta.slotMeta = cmpRegistryData[3]; - if (cmpRegistryData[4]) { - // parse prop meta - for (var i = 0; i < cmpRegistryData[4].length; i++) { - var data = cmpRegistryData[4][i]; - cmpMeta.propsMeta.push({ - propName: data[0], - attribName: data[1] === ATTR_LOWER_CASE ? data[0].toLowerCase() : toDashCase(data[0]), - propType: data[2], - isStateful: !!data[3] - }); - } - } - // bundle load priority - cmpMeta.loadPriority = cmpRegistryData[5]; - return registry[cmpMeta.tagNameMeta] = cmpMeta; - } - function parseComponentMeta(registry, moduleImports, cmpMetaData) { - // tag name will always be upper case - var cmpMeta = registry[cmpMetaData[0]]; - // get the component class which was added to moduleImports - // using the tag as the key on the export object - cmpMeta.componentModuleMeta = moduleImports[cmpMeta.tagNameMeta]; - // host - cmpMeta.hostMeta = cmpMetaData[1]; - // component listeners - if (cmpMetaData[2]) { - cmpMeta.listenersMeta = []; - for (var i = 0; i < cmpMetaData[2].length; i++) { - var data = cmpMetaData[2][i]; - cmpMeta.listenersMeta.push({ - eventMethodName: data[0], - eventName: data[1], - eventCapture: !!data[2], - eventPassive: !!data[3], - eventEnabled: !!data[4] - }); - } - } - // component states - cmpMeta.statesMeta = cmpMetaData[3]; - // component instance prop WILL change methods - cmpMeta.propWillChangeMeta = cmpMetaData[4]; - // component instance prop DID change methods - cmpMeta.propDidChangeMeta = cmpMetaData[5]; - // component methods - cmpMeta.methodsMeta = cmpMetaData[6]; - return cmpMeta; - } - function parsePropertyValue(propType, propValue) { - // ensure this value is of the correct prop type - if (isDef(propValue)) { - if (propType === TYPE_BOOLEAN) { - // per the HTML spec, any string value means it is a boolean "true" value - // but we'll cheat here and say that the string "false" is the boolean false - return propValue === 'false' ? false : propValue === '' || !!propValue; - } - if (propType === TYPE_NUMBER) { - // force it to be a number - return parseFloat(propValue); - } - } - // not sure exactly what type we want - // so no need to change to a different type - return propValue; - } - - function attributeChangedCallback(plt, elm, attribName, oldVal, newVal) { - // only react if the attribute values actually changed - if (oldVal !== newVal) { - // normalize the attribute name w/ lower case - attribName = attribName.toLowerCase(); - // using the known component meta data - // look up to see if we have a property wired up to this attribute name - var prop = plt.getComponentMeta(elm).propsMeta.find(function (p) { - return p.attribName === attribName; - }); - if (prop) { - // cool we've got a prop using this attribute name the value will - // be a string, so let's convert it to the correct type the app wants - // below code is ugly yes, but great minification ;) - elm[prop.propName] = parsePropertyValue(prop.propType, newVal); - } - } - } - - function connectedCallback(plt, elm) { - // do not reconnect if we've already created an instance for this element - if (!elm._hasConnected) { - // first time we've connected - elm._hasConnected = true; - // if somehow this node was reused, ensure we've removed this property - delete elm._hasDestroyed; - // add to the queue to load the bundle - // it's important to have an async tick in here so we can - // ensure the "mode" attribute has been added to the element - // place in high priority since it's not much work and we need - // to know as fast as possible, but still an async tick in between - plt.queue.add(function () { - // get the component meta data about this component - var cmpMeta = plt.getComponentMeta(elm); - // async tick has happened, so all of the child - // nodes and host attributes should now be in the DOM - collectHostContent(plt, elm); - // only collects slot references if this component even has slots - plt.connectHostElement(elm, cmpMeta.slotMeta); - // start loading this component mode's bundle - // if it's already loaded then the callback will be synchronous - plt.loadBundle(cmpMeta, elm, function loadComponentCallback() { - // we've fully loaded the component mode data - // let's queue it up to be rendered next - elm._queueUpdate(); - }); - }, PRIORITY_HIGH); - } - } - function collectHostContent(plt, elm) { - // find the first ancestor host element (if there is one) and register - // this element as one of the actively loading child elements for its ancestor - var ancestorHostElement = elm; - while (ancestorHostElement = getParentElement(ancestorHostElement)) { - // climb up the ancestors looking for the first registered component - if (plt.getComponentMeta(ancestorHostElement)) { - // we found this elements the first ancestor host element - // if the ancestor already loaded then do nothing, it's too late - if (!ancestorHostElement._hasLoaded) { - // keep a reference to this element's ancestor host element - elm._ancestorHostElement = ancestorHostElement; - // ensure there is an array to contain a reference to each of the child elements - // and set this element as one of the ancestor's child elements it should wait on - if (ancestorHostElement._activelyLoadingChildren) { - ancestorHostElement._activelyLoadingChildren.push(elm); - } else { - ancestorHostElement._activelyLoadingChildren = [elm]; - } - } - break; - } - } - } - - function disconnectedCallback(plt, elm) { - // only disconnect if we're not temporarily disconnected - // tmpDisconnected will happen when slot nodes are being relocated - if (!plt.tmpDisconnected) { - // ok, let's officially destroy this thing - // set this to true so that any of our pending async stuff - // doesn't continue since we already decided to destroy this node - elm._hasDestroyed = true; - // call instance Did Unload and destroy instance stuff - // if we've created an instance for this - var instance = elm.$instance; - if (instance) { - // call the user's componentDidUnload if there is one - instance.componentDidUnload && instance.componentDidUnload(); - elm.$instance = instance.$el = instance.__values = instance.__values.__propWillChange = instance.__values.__propDidChange = null; - } - // detatch any event listeners that may have been added - // this will also set _listeners to null if there are any - detachListeners(elm); - // destroy the vnode and child vnodes if they exist - elm._vnode && invokeDestroy(elm._vnode); - if (elm._hostContentNodes) { - // overreacting here just to reduce any memory leak issues - elm._hostContentNodes = elm._hostContentNodes.defaultSlot = elm._hostContentNodes.namedSlots = null; - } - // fuhgeddaboudit - // set it all to null to ensure we forget references - // and reset values incase this node gets reused somehow - // (possible that it got disconnected, but the node was reused) - elm._root = elm._vnode = elm._ancestorHostElement = elm._activelyLoadingChildren = elm._hasConnected = elm._isQueuedForUpdate = elm._hasLoaded = null; - } - } - - function queueUpdate(plt, elm) { - // only run patch if it isn't queued already - if (!elm._isQueuedForUpdate) { - elm._isQueuedForUpdate = true; - // run the patch in the next tick - plt.queue.add(function queueUpdateNextTick() { - // no longer queued - elm._isQueuedForUpdate = false; - // vdom diff and patch the host element for differences - update(plt, elm); - }); - } - } - function update(plt, elm) { - // everything is async, so somehow we could have already disconnected - // this node, so be sure to do nothing if we've already disconnected - if (!elm._hasDestroyed) { - var isInitialLoad = !elm.$instance; - if (isInitialLoad) { - // haven't created a component instance for this host element yet - initInstance(plt, elm); - } - // if this component has a render function, let's fire - // it off and generate a vnode for this - elm._render(!isInitialLoad); - if (isInitialLoad) { - elm._initLoad(); - } - } - } - - function initProxy(plt, elm, instance, cmpMeta) { - var i = 0; - if (cmpMeta.methodsMeta) { - // instances will already have the methods on them - // but you can also expose methods to the proxy element - // using @Method(). Think of like .focus() for an element. - for (; i < cmpMeta.methodsMeta.length; i++) { - initMethod(cmpMeta.methodsMeta[i], elm, instance); - } - } - // used to store instance data internally so that we can add - // getters/setters with the same name, and then do change detection - var values = instance.__values = {}; - if (cmpMeta.propWillChangeMeta) { - // this component has prop WILL change methods, so init the object to store them - values.__propWillChange = {}; - } - if (cmpMeta.propDidChangeMeta) { - // this component has prop DID change methods, so init the object to store them - values.__propDidChange = {}; - } - if (cmpMeta.statesMeta) { - // add getters/setters to instance properties that are not already set as @Prop() - // these are instance properties that should trigger a render update when - // they change. Like @Prop(), except data isn't passed in and is only state data. - // Unlike @Prop, state properties do not add getters/setters to the proxy element - // and initial values are not checked against the proxy element or config - for (i = 0; i < cmpMeta.statesMeta.length; i++) { - initProperty(false, true, '', cmpMeta.statesMeta[i], 0, instance, values, plt, elm, cmpMeta.propWillChangeMeta, cmpMeta.propDidChangeMeta); - } - } - if (cmpMeta.propsMeta) { - for (i = 0; i < cmpMeta.propsMeta.length; i++) { - // add getters/setters for @Prop()s - initProperty(true, cmpMeta.propsMeta[i].isStateful, cmpMeta.propsMeta[i].attribName, cmpMeta.propsMeta[i].propName, cmpMeta.propsMeta[i].propType, instance, instance.__values, plt, elm, cmpMeta.propWillChangeMeta, cmpMeta.propDidChangeMeta); - } - } - } - function initMethod(methodName, elm, instance) { - // add a getter on the dom's element instance - // pointed at the instance's method - Object.defineProperty(elm, methodName, { - configurable: true, - value: instance[methodName].bind(instance) - }); - } - function initProperty(isProp, isStateful, attrName, propName, propType, instance, internalValues, plt, elm, propWillChangeMeta, propDidChangeMeta) { - if (isProp) { - // @Prop() property, so check initial value from the proxy element, instance - // and config, before we create getters/setters on this same property name - var hostAttrValue = elm.getAttribute(attrName); - if (hostAttrValue !== null) { - // looks like we've got an initial value from the attribute - internalValues[propName] = parsePropertyValue(propType, hostAttrValue); - } else if (elm[propName] !== undefined) { - // looks like we've got an initial value on the proxy element - internalValues[propName] = parsePropertyValue(propType, elm[propName]); - } else if (instance[propName] !== undefined) { - // looks like we've got an initial value on the instance already - internalValues[propName] = instance[propName]; - } else if (propName === 'mode') { - // special case for just "mode" property - // which all component automatically get - internalValues[propName] = plt.config.get(propName); - } - } else { - // @State() property, so copy the value directly from the instance - // before we create getters/setters on this same property name - internalValues[propName] = instance[propName]; - } - var i = 0; - if (propWillChangeMeta) { - // there are prop WILL change methods for this component - for (i = 0; i < propWillChangeMeta.length; i++) { - if (propWillChangeMeta[i][PROP_CHANGE_PROP_NAME] === propName) { - // cool, we should watch for changes to this property - // let's bind their watcher function and add it to our list - // of watchers, so any time this property changes we should - // also fire off their @PropWillChange() method - internalValues.__propWillChange[propName] = instance[propWillChangeMeta[i][PROP_CHANGE_METHOD_NAME]].bind(instance); - } - } - } - if (propDidChangeMeta) { - // there are prop DID change methods for this component - for (i = 0; i < propDidChangeMeta.length; i++) { - if (propDidChangeMeta[i][PROP_CHANGE_PROP_NAME] === propName) { - // cool, we should watch for changes to this property - // let's bind their watcher function and add it to our list - // of watchers, so any time this property changes we should - // also fire off their @PropDidChange() method - internalValues.__propDidChange[propName] = instance[propDidChangeMeta[i][PROP_CHANGE_METHOD_NAME]].bind(instance); - } - } - } - function getValue() { - // get the property value directly from our internal values - return internalValues[propName]; - } - function setValue(newVal) { - // check our new property value against our internal value - var oldVal = internalValues[propName]; - // TODO: account for Arrays/Objects - if (newVal !== oldVal) { - // gadzooks! the property's value has changed!! - if (internalValues.__propWillChange && internalValues.__propWillChange[propName]) { - // this instance is watching for when this property WILL change - internalValues.__propWillChange[propName](newVal, oldVal); - } - // set our new value! - internalValues[propName] = newVal; - if (internalValues.__propDidChange && internalValues.__propDidChange[propName]) { - // this instance is watching for when this property DID change - internalValues.__propDidChange[propName](newVal, oldVal); - } - // looks like this value actually changed, we've got work to do! - // queue that we need to do an update, don't worry - // about queuing up millions cuz this function - // ensures it only runs once - queueUpdate(plt, elm); - } - } - if (isProp) { - // dom's element instance - // only place getters/setters on element for props - // state getters/setters should not be assigned to the element - Object.defineProperty(elm, propName, { - configurable: true, - get: getValue, - set: setValue - }); - } - // user's component class instance - var instancePropDesc = { - configurable: true, - get: getValue - }; - if (isStateful) { - // this is a state property, or it's a prop that can keep state - // for props it's mainly used for props on inputs like "checked" - instancePropDesc.set = setValue; - } else { - // dev mode warning only - instancePropDesc.set = function invalidSetValue() { - // this is not a stateful prop - // so do not update the instance or host element - console.warn('@Prop() "' + propName + '" on "' + elm.tagName.toLowerCase() + '" cannot be modified.'); - }; - } - // define on component class instance - Object.defineProperty(instance, propName, instancePropDesc); - } - - function createThemedClasses(mode, color, classList) { - var allClassObj = {}; - return classList.split(' ').reduce(function (classObj, classString) { - classObj[classString] = true; - if (mode) { - classObj[classString + '-' + mode] = true; - if (color) { - classObj[classString + '-' + color] = true; - classObj[classString + '-' + mode + '-' + color] = true; - } - } - return classObj; - }, allClassObj); - } - - function render(plt, elm, isUpdateRender) { - var instance = elm.$instance; - var cmpMeta = plt.getComponentMeta(elm); - if (isUpdateRender) { - // fire off the user's componentWillUpdate method (if one was provided) - // componentWillUpdate runs BEFORE render() has been called - // but only BEFORE an UPDATE and not before the intial render - instance.componentWillUpdate && instance.componentWillUpdate(); - } - // if this component has a render function, let's fire - // it off and generate the child vnodes for this host element - // note that we do not create the host element cuz it already exists - var vnodeChildren = instance.render && instance.render(); - var vnodeHostData = instance.hostData && instance.hostData(); - var hostMeta = cmpMeta.hostMeta; - if (vnodeChildren || vnodeHostData || hostMeta) { - if (hostMeta) { - vnodeHostData = Object.keys(hostMeta).reduce(function (hostData, key) { - switch (key) { - case 'theme': - hostData['class'] = hostData['class'] || {}; - hostData['class'] = Object.assign(hostData['class'], createThemedClasses(instance.mode, instance.color, hostMeta['theme'])); - } - return hostData; - }, vnodeHostData || {}); - } - // looks like we've got child nodes to render into this host element - // or we need to update the css class/attrs on the host element - // if we haven't already created a vnode, then we give the renderer the actual element - // if this is a re-render, then give the renderer the last vnode we already created - var oldVNode = elm._vnode || new VNode(); - oldVNode.elm = elm; - // normalize host data keys to abbr. key - if (vnodeHostData) { - vnodeHostData.a = vnodeHostData['attrs']; - vnodeHostData.c = vnodeHostData['class']; - vnodeHostData.s = vnodeHostData['style']; - vnodeHostData.o = vnodeHostData['on']; - } - // each patch always gets a new vnode - // the host element itself isn't patched because it already exists - // kick off the actual render and any DOM updates - elm._vnode = plt.render(oldVNode, h(null, vnodeHostData, vnodeChildren), isUpdateRender, elm._hostContentNodes); - } - if (isUpdateRender) { - // fire off the user's componentDidUpdate method (if one was provided) - // componentDidUpdate runs AFTER render() has been called - // but only AFTER an UPDATE and not after the intial render - instance.componentDidUpdate && instance.componentDidUpdate(); - } - } - - function initHostConstructor(plt, HostElementConstructor) { - Object.defineProperties(HostElementConstructor, { - 'connectedCallback': { - value: function () { - connectedCallback(plt, this); - } - }, - 'attributeChangedCallback': { - value: function (attribName, oldVal, newVal) { - attributeChangedCallback(plt, this, attribName, oldVal, newVal); - } - }, - 'disconnectedCallback': { - value: function () { - disconnectedCallback(plt, this); - } - }, - _queueUpdate: { - value: function () { - queueUpdate(plt, this); - } - }, - _initLoad: { - value: function () { - initLoad(plt, this); - } - }, - _render: { - value: function (isInitialRender) { - render(plt, this, isInitialRender); - } - } - }); - } - function initInstance(plt, elm) { - // using the component's class, let's create a new instance - var cmpMeta = plt.getComponentMeta(elm); - var instance = elm.$instance = new cmpMeta.componentModuleMeta(); - // let's automatically add a reference to the host element on the instance - instance.$el = elm; - // so we've got an host element now, and a actual instance - // let's wire them up together with getter/settings - // the setters are use for change detection and knowing when to re-render - initProxy(plt, elm, instance, cmpMeta); - // fire off the user's componentWillLoad method (if one was provided) - // componentWillLoad only runs ONCE, after instance.$el has been assigned - // the host element, but BEFORE render() has been called - instance.componentWillLoad && instance.componentWillLoad(); - } - function initLoad(plt, elm) { - var instance = elm.$instance; - // it's possible that we've already decided to destroy this element - // check if this element has any actively loading child elements - if (instance && !elm._hasDestroyed && (!elm._activelyLoadingChildren || !elm._activelyLoadingChildren.length)) { - // cool, so at this point this element isn't already being destroyed - // and it does not have any child elements that are still loading - // ensure we remove any child references cuz it doesn't matter at this point - elm._activelyLoadingChildren = null; - // the element is within the DOM now, so let's attach the event listeners - attachListeners(plt, plt.getComponentMeta(elm).listenersMeta, elm, instance); - // sweet, this particular element is good to go - // all of this element's children have loaded (if any) - elm._hasLoaded = true; - // fire off the user's componentDidLoad method (if one was provided) - // componentDidLoad only runs ONCE, after instance.$el has been assigned - // the host element, and AFTER render() has been called - instance.componentDidLoad && instance.componentDidLoad(); - // add the css class that this element has officially hydrated - elm.classList.add(HYDRATED_CSS); - // ( •_•) - // ( •_•)>⌐■-■ - // (⌐■_■) - // load events fire from bottom to top, the deepest elements first then bubbles up - // if this element did have an ancestor host element - if (elm._ancestorHostElement) { - // ok so this element already has a known ancestor host element - // let's make sure we remove this element from its ancestor's - // known list of child elements which are actively loading - var ancestorsActivelyLoadingChildren = elm._ancestorHostElement._activelyLoadingChildren; - var index = ancestorsActivelyLoadingChildren && ancestorsActivelyLoadingChildren.indexOf(elm); - if (index > -1) { - // yup, this element is in the list of child elements to wait on - // remove it so we can work to get the length down to 0 - ancestorsActivelyLoadingChildren.splice(index, 1); - } - // the ancestor's initLoad method will do the actual checks - // to see if the ancestor is actually loaded or not - // then let's call the ancestor's initLoad method if there's no length - // (which actually ends up as this method again but for the ancestor) - !ancestorsActivelyLoadingChildren.length && elm._ancestorHostElement._initLoad(); - // fuhgeddaboudit, no need to keep a reference after this element loaded - delete elm._ancestorHostElement; - } - } - } - - function initGlobal(Gbl, win, domApi, plt, config, domCtrl) { - if (typeof win.CustomEvent !== 'function') { - // CustomEvent polyfill - var CustomEvent = function (event, params) { - params = params || { bubbles: false, cancelable: false, detail: undefined }; - var evt = domApi.$createEvent(); - evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); - return evt; - }; - - CustomEvent.prototype = win.Event.prototype; - win.CustomEvent = CustomEvent; - } - // properties that can stay hidden from public use - var controllers = Gbl.controllers = {}; - Gbl.isClient = true; - Gbl.isServer = false; - // properties to be exposed to public - // in actuality it's the exact same object - Gbl.config = config; - Gbl.dom = domCtrl; - Gbl.emit = function (instance, eventName, data) { - data = data || {}; - if (data.bubbles === undefined) { - data.bubbles = true; - } - if (data.composed === undefined) { - // https://developers.google.com/web/fundamentals/getting-started/primers/shadowdom#events - data.composed = true; - } - if (Gbl.eventNameFn) { - eventName = Gbl.eventNameFn(eventName); - } - instance && instance.$el && instance.$el.dispatchEvent(new win.CustomEvent(eventName, data)); - }; - Gbl.listener = { - enable: function (instance, eventName, shouldEnable, attachTo) { - enableListener(plt, instance.$el, instance, eventName, shouldEnable, attachTo); - }, - add: function (elm, eventName, cb, opts) { - return addEventListener(plt, elm, eventName, cb, opts); - } - }; - // used to store the queued controller promises to - // be resolved when the controller finishes loading - var queuedCtrlResolves = {}; - Gbl.controller = function (ctrlName, opts) { - // loading a controller is always async so return a promise - return new Promise(function (resolve) { - // see if we already have the controller loaded - var ctrl = controllers[ctrlName]; - if (ctrl) { - // we've already loaded this controller - resolveController(ctrl, resolve, opts); - } else { - // oh noz! we haven't already loaded this controller yet! - var ctrlResolveQueue = queuedCtrlResolves[ctrlName]; - if (ctrlResolveQueue) { - // cool we've already "started" to load the controller - // but it hasn't finished loading yet, so let's add - // this one also to the queue of to-be resolved promises - ctrlResolveQueue.push(resolve, opts); - } else { - // looks like we haven't even started the request - // yet lets add the component to the DOM and create - // a queue for this controller - queuedCtrlResolves[ctrlName] = [resolve, opts]; - domApi.$appendChild(domApi.$body, domApi.$createElement('ion-' + ctrlName + '-controller')); - } - } - }); - }; - Gbl.loadController = function (ctrlName, ctrl) { - // this method is called when the singleton - // instance of our controller initially loads - // add this controller instance to our map of controller singletons - controllers[ctrlName] = ctrl; - // check for to-be resolved controller promises - var pendingCtrlResolves = queuedCtrlResolves[ctrlName]; - if (pendingCtrlResolves) { - for (var i = 0; i < pendingCtrlResolves.length; i += 2) { - // first arg is the original promise's resolve - // which still needs to be resolved - // second arg was the originally passed in options - resolveController(ctrl, pendingCtrlResolves[i], pendingCtrlResolves[i + 1]); - } - // all good, go ahead and remove from the queue - delete queuedCtrlResolves[ctrlName]; - } - }; - function resolveController(ctrl, resolve, opts) { - if (opts) { - // if the call had options passed in then - // it should run the controller's load() method - // and let the controller's load() do the resolve - // which then will resolve the user's promise - ctrl.load(opts).then(resolve); - } else { - // no options passed in, so resolve with - // the actual controller instance - resolve(ctrl); - } - } - return Gbl; - } - - function createPlatformClient(Gbl, win, domApi, config, domCtrl, queue, staticDir) { - var registry = { 'HTML': {} }; - var moduleImports = {}; - var moduleCallbacks = {}; - var loadedModules = {}; - var pendingModuleRequests = {}; - // create the platform api which will be passed around for external use - var plt = { - registerComponents: registerComponents, - defineComponent: defineComponent, - getComponentMeta: getComponentMeta, - loadBundle: loadBundle, - config: config, - queue: queue, - connectHostElement: connectHostElement, - getEventOptions: getEventOptions - }; - // create the renderer that will be used - plt.render = createRenderer(plt, domApi); - // create the global which will be injected into the user's instances - var injectedGlobal = initGlobal(Gbl, win, domApi, plt, config, domCtrl); - // setup the root element which is the mighty tag - // the has the final say of when the app has loaded - var rootElm = domApi.$documentElement; - rootElm._activelyLoadingChildren = []; - rootElm._initLoad = function appLoadedCallback() { - // this will fire when all components have finished loaded - rootElm._hasLoaded = true; - }; - // if the HTML was generated from SSR - // then let's walk the tree and generate vnodes out of the data - createVNodesFromSsr(domApi, rootElm); - function getComponentMeta(elm) { - // get component meta using the element - // important that the registry has upper case tag names - return registry[elm.tagName]; - } - function connectHostElement(elm, slotMeta) { - // host element has been connected to the DOM - if (!domApi.$getAttribute(elm, SSR_VNODE_ID)) { - // this host element was NOT created with SSR - // let's pick out the inner content for slot projection - assignHostContentSlots(domApi, elm, slotMeta); - } - } - function registerComponents(components) { - // this is the part that just registers the minimal amount of data - // it's basically a map of the component tag name to its associated external bundles - return (components || []).map(function (data) { - return parseComponentRegistry(data, registry); - }); - } - function defineComponent(cmpMeta, HostElementConstructor) { - // initialize the properties on the component module prototype - initHostConstructor(plt, HostElementConstructor.prototype); - // add which attributes should be observed - HostElementConstructor.observedAttributes = cmpMeta.propsMeta.filter(function (p) { - return p.attribName; - }).map(function (p) { - return p.attribName; - }); - // define the custom element - win.customElements.define(cmpMeta.tagNameMeta.toLowerCase(), HostElementConstructor); - } - Gbl.defineComponents = function defineComponents(moduleId, importFn) { - var args = arguments; - // import component function - // inject globals - importFn(moduleImports, h, t, injectedGlobal); - for (var i = 2; i < args.length; i++) { - parseComponentMeta(registry, moduleImports, args[i]); - } - // fire off all the callbacks waiting on this module to load - var callbacks = moduleCallbacks[moduleId]; - if (callbacks) { - for (i = 0; i < callbacks.length; i++) { - callbacks[i](); - } - delete moduleCallbacks[moduleId]; - } - // remember that we've already loaded this module - loadedModules[moduleId] = true; - }; - function loadBundle(cmpMeta, elm, cb) { - var moduleId = cmpMeta.moduleId; - if (loadedModules[moduleId]) { - // sweet, we've already loaded this module - cb(); - } else { - // never seen this module before, let's start the request - // and add it to the callbacks to fire when it has loaded - if (moduleCallbacks[moduleId]) { - moduleCallbacks[moduleId].push(cb); - } else { - moduleCallbacks[moduleId] = [cb]; - } - // create the url we'll be requesting - var url = getBundlePath(moduleId + '.js'); - if (!pendingModuleRequests[url]) { - // not already actively requesting this url - // remember that we're now actively requesting this url - pendingModuleRequests[url] = true; - // let's kick off the module request - jsonp(url); - } - // we also need to load the css file in the head - var styleId = cmpMeta.styleIds[getMode(domApi, config, elm)] || cmpMeta.styleIds.$; - if (styleId && !loadedModules[styleId]) { - // this style hasn't been added to the head yet - loadedModules[styleId] = true; - // append this link element to the head, which starts the request for the file - var linkElm = domApi.$createElement('link'); - linkElm.href = getBundlePath(styleId + '.css'); - linkElm.rel = 'stylesheet'; - domApi.$insertBefore(domApi.$head, linkElm, domApi.$head.firstChild); - } - } - } - function getBundlePath(fileName) { - return '' + staticDir + fileName; - } - function jsonp(url) { - // create a sript element to add to the document.head - var scriptElm = domApi.$createElement('script'); - scriptElm.charset = 'utf-8'; - scriptElm.async = true; - scriptElm.src = url; - // create a fallback timeout if something goes wrong - var tmrId = setTimeout(onScriptComplete, 120000); - function onScriptComplete() { - clearTimeout(tmrId); - scriptElm.onerror = scriptElm.onload = null; - domApi.$removeChild(scriptElm.parentNode, scriptElm); - // remove from our list of active requests - delete pendingModuleRequests[url]; - } - // add script completed listener to this script element - scriptElm.onerror = scriptElm.onload = onScriptComplete; - // inject a script tag in the head - // kick off the actual request - domApi.$appendChild(domApi.$head, scriptElm); - } - // test if this browser supports event options or not - var supportsEventOptions = false; - try { - win.addEventListener('evopt', null, Object.defineProperty({}, 'passive', { - get: function () { - supportsEventOptions = true; - } - })); - } catch (e) {} - function getEventOptions(opts) { - return supportsEventOptions ? { - 'capture': !!(opts && opts.capture), - 'passive': !(opts && opts.passive === false) - } : !!(opts && opts.capture); - } - return plt; - } - - function createQueueClient(domCtrl) { - var now = domCtrl.now; - var raf = domCtrl.raf; - var highPromise = Promise.resolve(); - var highCallbacks = []; - var mediumCallbacks = []; - var lowCallbacks = []; - var resolvePending = false; - var ricPending = false; - function doHighPriority() { - // holy geez we need to get this stuff done and fast - // all high priority callbacks should be fired off immediately - while (highCallbacks.length > 0) { - highCallbacks.shift()(); - } - resolvePending = false; - } - function doWork() { - var start = now(); - // always run all of the high priority work if there is any - doHighPriority(); - while (mediumCallbacks.length > 0 && now() - start < 40) { - mediumCallbacks.shift()(); - } - if (mediumCallbacks.length === 0) { - // we successfully drained the medium queue or the medium queue is empty - // so now let's drain the low queue with our remaining time - while (lowCallbacks.length > 0 && now() - start < 40) { - lowCallbacks.shift()(); - } - } - // check to see if we still have work to do - if (ricPending = mediumCallbacks.length > 0 || lowCallbacks.length > 0) { - // everyone just settle down now - // we already don't have time to do anything in this callback - // let's throw the next one in a requestAnimationFrame - // so we can just simmer down for a bit - raf(flush); - } - } - function flush() { - // always run all of the high priority work if there is any - doHighPriority(); - // always force a bunch of medium callbacks to run, but still have - // a throttle on how many can run in a certain time - var start = now(); - while (mediumCallbacks.length > 0 && now() - start < 4) { - mediumCallbacks.shift()(); - } - if (ricPending = mediumCallbacks.length > 0 || lowCallbacks.length > 0) { - // still more to do yet, but we've run out of time - // let's let this thing cool off and try again in the next ric - raf(doWork); - } - } - function add(cb, priority) { - if (priority === PRIORITY_HIGH) { - // uses Promise.resolve() for next tick - highCallbacks.push(cb); - if (!resolvePending) { - // not already pending work to do, so let's tee it up - resolvePending = true; - highPromise.then(doHighPriority); - } - } else { - if (priority === PRIORITY_LOW) { - lowCallbacks.push(cb); - } else { - // defaults to medium priority - // uses requestIdleCallback - mediumCallbacks.push(cb); - } - if (!ricPending) { - // not already pending work to do, so let's tee it up - ricPending = true; - raf(doWork); - } - } - } - return { - add: add, - flush: flush - }; - } - - function detectPlatforms(url, userAgent, platforms, defaultPlatform) { - // bracket notation to ensure they're not property renamed - var validPlatforms = platforms.filter(function (p) { - return p['isMatch'] && p['isMatch'](url, userAgent); - }); - if (!validPlatforms.length) { - validPlatforms = platforms.filter(function (p) { - return p['name'] === defaultPlatform; - }); - } - return validPlatforms; - } - function isPlatformMatch(url, userAgent, platformName, userAgentAtLeastHas, userAgentMustNotHave) { - var queryValue = queryParam(url, 'ionicplatform'); - if (queryValue) { - return queryValue === platformName; - } - if (userAgent) { - userAgent = userAgent.toLowerCase(); - for (var i = 0; i < userAgentAtLeastHas.length; i++) { - if (userAgent.indexOf(userAgentAtLeastHas[i]) > -1) { - for (var j = 0; j < userAgentMustNotHave.length; j++) { - if (userAgent.indexOf(userAgentMustNotHave[j]) > -1) { - return false; - } - } - return true; - } - } - } - return false; - } - function queryParam(url, key) { - key = key.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]'); - var regex = new RegExp('[\\?&]' + key + '=([^&#]*)'); - var results = regex.exec(url); - return results ? decodeURIComponent(results[1].replace(/\+/g, ' ')) : null; - } - - // order from most specifc to least specific - var PLATFORM_CONFIGS = [{ - 'name': 'ipad', - 'isMatch': function (url, userAgent) { - return isPlatformMatch(url, userAgent, 'ipad', ['ipad'], ['windows phone']); - } - }, { - 'name': 'iphone', - 'isMatch': function (url, userAgent) { - return isPlatformMatch(url, userAgent, 'iphone', ['iphone'], ['windows phone']); - } - }, { - 'name': 'ios', - 'settings': { - 'mode': 'ios' - }, - 'isMatch': function (url, userAgent) { - return isPlatformMatch(url, userAgent, 'ios', ['iphone', 'ipad', 'ipod'], ['windows phone']); - } - }, { - 'name': 'android', - 'settings': { - 'activator': 'ripple', - 'mode': 'md' - }, - 'isMatch': function (url, userAgent) { - return isPlatformMatch(url, userAgent, 'android', ['android', 'silk'], ['windows phone']); - } - }, { - 'name': 'windows', - 'settings': { - 'mode': 'wp' - }, - 'isMatch': function (url, userAgent) { - return isPlatformMatch(url, userAgent, 'windows', ['windows phone'], []); - } - }, { - 'name': 'core', - 'settings': { - 'mode': 'md' - } - }]; - - var Gbl = window[globalNamespace] = window[globalNamespace] || {}; - var domCtrl = createDomControllerClient(window); - var plt = createPlatformClient(Gbl, window, createDomApi(document), createConfigController(Gbl.config, detectPlatforms(window.location.href, window.navigator.userAgent, PLATFORM_CONFIGS, 'core')), domCtrl, createQueueClient(domCtrl), Gbl.staticDir); - plt.registerComponents(Gbl.components).forEach(function (cmpMeta) { - plt.defineComponent(cmpMeta, class HostElement extends HTMLElement {}); - }); -})(window, document, "App"); \ No newline at end of file diff --git a/packages/stencil-fiber-demo/www/build/app/fiber-demo.fiber-dot.fiber-triangle.js b/packages/stencil-fiber-demo/www/build/app/fiber-demo.fiber-dot.fiber-triangle.js deleted file mode 100644 index 6c38417a1e..0000000000 --- a/packages/stencil-fiber-demo/www/build/app/fiber-demo.fiber-dot.fiber-triangle.js +++ /dev/null @@ -1,146 +0,0 @@ -/*! Built with http://stenciljs.com */ - -App.defineComponents( - -/**** module id ****/ -'fiber-demo.fiber-dot.fiber-triangle', - -/**** component modules ****/ -function importComponent(exports, h, t, Ionic) { -var FiberDemo = (function () { - function FiberDemo() { - this.elapsed = 0; - this.seconds = 0; - } - FiberDemo.prototype["componentDidLoad"] = function () { - var tick = this.tick.bind(this); - this.intervalID = setInterval(tick, 1000); - }; - FiberDemo.prototype.tick = function () { - this.seconds = (this.seconds % 10) + 1; - }; - FiberDemo.prototype.hostData = function () { - var elapsed = this.elapsed; - var t = (elapsed / 1000) % 10; - var scale = 1 + (t > 5 ? 10 - t : t) / 10; - var containerStyle = { - position: 'absolute', - transformOrigin: '0 0', - left: '50%', - top: '50%', - width: '10px', - height: '10px', - background: '#eee', - transform: 'scaleX(' + (scale / 2.1) + ') scaleY(0.7) translateZ(0.1px)' - }; - return { - style: containerStyle - }; - }; - FiberDemo.prototype.render = function () { - return (h("div", 0, - h("fiber-triangle", { "p": { "x": 0, "y": 0, "s": 1000, "seconds": this.seconds } }))); - }; - return FiberDemo; -}()); - -var FiberDot = (function () { - function FiberDot() { - this.hover = false; - } - FiberDot.prototype.enter = function () { - this.hover = true; - }; - FiberDot.prototype.leave = function () { - this.hover = false; - }; - FiberDot.prototype.hostData = function () { - var s = this.size * 1.3; - var style = { - position: 'absolute', - font: 'normal 15px sans-serif', - textAlign: 'center', - cursor: 'pointer', - width: s + 'px', - height: s + 'px', - left: (this.x) + 'px', - top: (this.y) + 'px', - borderRadius: (s / 2) + 'px', - lineHeight: (s) + 'px', - background: this.hover ? '#ff0' : '#61dafb' - }; - return { - style: style, - on: { - mouseenter: this.enter.bind(this), - mouseleave: this.leave.bind(this) - }, - }; - }; - FiberDot.prototype.render = function () { - return (this.hover ? '**' + this.text + '**' : this.text); - }; - return FiberDot; -}()); - -var targetSize = 25; -var FiberTriangle = (function () { - function FiberTriangle() { - } - FiberTriangle.prototype.render = function () { - var s = this.s; - if (s <= targetSize) { - return (h("fiber-dot", { "p": { "x": this.x - (targetSize / 2), "y": this.y - (targetSize / 2), "size": targetSize, "text": this.seconds.toString() } })); - } - s = s / 2; - return [ - h("fiber-triangle", { "p": { "x": this.x, "y": this.y - (s / 2), "s": s, "seconds": this.seconds } }), - h("fiber-triangle", { "p": { "x": this.x - s, "y": this.y + (s / 2), "s": s, "seconds": this.seconds } }), - h("fiber-triangle", { "p": { "x": this.x + s, "y": this.y + (s / 2), "s": s, "seconds": this.seconds } }) - ]; - }; - return FiberTriangle; -}()); - -exports['FIBER-DEMO'] = FiberDemo; -exports['FIBER-DOT'] = FiberDot; -exports['FIBER-TRIANGLE'] = FiberTriangle; -}, - - -/***************** fiber-demo *****************/ -[ -/** fiber-demo: [0] tag **/ -'FIBER-DEMO', - -/** fiber-demo: [1] host **/ -{} - -], - -/***************** fiber-dot *****************/ -[ -/** fiber-dot: [0] tag **/ -'FIBER-DOT', - -/** fiber-dot: [1] host **/ -{}, - -/** fiber-dot: [2] listeners **/ -0 /* no listeners */, - -/** fiber-dot: [3] states **/ -['hover'] - -], - -/***************** fiber-triangle *****************/ -[ -/** fiber-triangle: [0] tag **/ -'FIBER-TRIANGLE', - -/** fiber-triangle: [1] host **/ -{} - -] -) \ No newline at end of file diff --git a/packages/stencil-fiber-demo/www/index.html b/packages/stencil-fiber-demo/www/index.html deleted file mode 100644 index 74bb13be8d..0000000000 --- a/packages/stencil-fiber-demo/www/index.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - - Ionic Perf Demo - - - - -

Ionic Perf Demo

-

- The goal of this demo is to show smooth animations while at - the same time updating 729 text nodes every second. Only one property - is updated at the root node, which is then passed down through over - 1,700 nodes every second. Additionally, user interactions, such as - mouseenter and mouseleave, take precedence, yet should not interfer with - animations and node updates. This demo was adopted from the - React Fiber demo. -

- - Show Demo - - diff --git a/packages/stencil-fiber-demo/www/perf.html b/packages/stencil-fiber-demo/www/perf.html deleted file mode 100644 index 7817f4d7ff..0000000000 --- a/packages/stencil-fiber-demo/www/perf.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - - Ionic Perf Demo - - - - -

Ionic Perf Demo

- - - - - -