UNPKG

68.1 kBJavaScriptView Raw
1const NAMESPACE = 'taro-components';
2
3let contentRef;
4let hostTagName;
5let useNativeShadowDom = false;
6let checkSlotFallbackVisibility = false;
7let checkSlotRelocate = false;
8let isSvgMode = false;
9let queuePending = false;
10const win = typeof window !== 'undefined' ? window : {};
11const doc = win.document || { head: {} };
12const plt = {
13 $flags$: 0,
14 $resourcesUrl$: '',
15 jmp: (h) => h(),
16 raf: (h) => requestAnimationFrame(h),
17 ael: (el, eventName, listener, opts) => el.addEventListener(eventName, listener, opts),
18 rel: (el, eventName, listener, opts) => el.removeEventListener(eventName, listener, opts),
19 ce: (eventName, opts) => new CustomEvent(eventName, opts),
20};
21const promiseResolve = (v) => Promise.resolve(v);
22const supportsConstructibleStylesheets = /*@__PURE__*/ (() => {
23 try {
24 new CSSStyleSheet();
25 return typeof new CSSStyleSheet().replace === 'function';
26 }
27 catch (e) { }
28 return false;
29 })()
30 ;
31const addHostEventListeners = (elm, hostRef, listeners, attachParentListeners) => {
32 if (listeners) {
33 listeners.map(([flags, name, method]) => {
34 const target = getHostListenerTarget(elm, flags) ;
35 const handler = hostListenerProxy(hostRef, method);
36 const opts = hostListenerOpts(flags);
37 plt.ael(target, name, handler, opts);
38 (hostRef.$rmListeners$ = hostRef.$rmListeners$ || []).push(() => plt.rel(target, name, handler, opts));
39 });
40 }
41};
42const hostListenerProxy = (hostRef, methodName) => (ev) => {
43 try {
44 {
45 if (hostRef.$flags$ & 256 /* isListenReady */) {
46 // instance is ready, let's call it's member method for this event
47 hostRef.$lazyInstance$[methodName](ev);
48 }
49 else {
50 (hostRef.$queuedListeners$ = hostRef.$queuedListeners$ || []).push([methodName, ev]);
51 }
52 }
53 }
54 catch (e) {
55 consoleError(e);
56 }
57};
58const getHostListenerTarget = (elm, flags) => {
59 if (flags & 4 /* TargetDocument */)
60 return doc;
61 return elm;
62};
63// prettier-ignore
64const hostListenerOpts = (flags) => (flags & 2 /* Capture */) !== 0;
65const HYDRATED_CSS = '{visibility:hidden}.hydrated{visibility:inherit}';
66const XLINK_NS = 'http://www.w3.org/1999/xlink';
67const createTime = (fnName, tagName = '') => {
68 {
69 return () => {
70 return;
71 };
72 }
73};
74const uniqueTime = (key, measureText) => {
75 {
76 return () => {
77 return;
78 };
79 }
80};
81const rootAppliedStyles = new WeakMap();
82const registerStyle = (scopeId, cssText, allowCS) => {
83 let style = styles.get(scopeId);
84 if (supportsConstructibleStylesheets && allowCS) {
85 style = (style || new CSSStyleSheet());
86 style.replace(cssText);
87 }
88 else {
89 style = cssText;
90 }
91 styles.set(scopeId, style);
92};
93const addStyle = (styleContainerNode, cmpMeta, mode, hostElm) => {
94 let scopeId = getScopeId(cmpMeta);
95 let style = styles.get(scopeId);
96 // if an element is NOT connected then getRootNode() will return the wrong root node
97 // so the fallback is to always use the document for the root node in those cases
98 styleContainerNode = styleContainerNode.nodeType === 11 /* DocumentFragment */ ? styleContainerNode : doc;
99 if (style) {
100 if (typeof style === 'string') {
101 styleContainerNode = styleContainerNode.head || styleContainerNode;
102 let appliedStyles = rootAppliedStyles.get(styleContainerNode);
103 let styleElm;
104 if (!appliedStyles) {
105 rootAppliedStyles.set(styleContainerNode, (appliedStyles = new Set()));
106 }
107 if (!appliedStyles.has(scopeId)) {
108 {
109 {
110 styleElm = doc.createElement('style');
111 styleElm.innerHTML = style;
112 }
113 styleContainerNode.insertBefore(styleElm, styleContainerNode.querySelector('link'));
114 }
115 if (appliedStyles) {
116 appliedStyles.add(scopeId);
117 }
118 }
119 }
120 else if (!styleContainerNode.adoptedStyleSheets.includes(style)) {
121 styleContainerNode.adoptedStyleSheets = [...styleContainerNode.adoptedStyleSheets, style];
122 }
123 }
124 return scopeId;
125};
126const attachStyles = (hostRef) => {
127 const cmpMeta = hostRef.$cmpMeta$;
128 const elm = hostRef.$hostElement$;
129 const endAttachStyles = createTime('attachStyles', cmpMeta.$tagName$);
130 addStyle(elm.getRootNode(), cmpMeta);
131 endAttachStyles();
132};
133const getScopeId = (cmp, mode) => 'sc-' + (cmp.$tagName$);
134/**
135 * Default style mode id
136 */
137/**
138 * Reusable empty obj/array
139 * Don't add values to these!!
140 */
141const EMPTY_OBJ = {};
142const isComplexType = (o) => {
143 // https://jsperf.com/typeof-fn-object/5
144 o = typeof o;
145 return o === 'object' || o === 'function';
146};
147/**
148 * Production h() function based on Preact by
149 * Jason Miller (@developit)
150 * Licensed under the MIT License
151 * https://github.com/developit/preact/blob/master/LICENSE
152 *
153 * Modified for Stencil's compiler and vdom
154 */
155// const stack: any[] = [];
156// export function h(nodeName: string | d.FunctionalComponent, vnodeData: d.PropsType, child?: d.ChildType): d.VNode;
157// export function h(nodeName: string | d.FunctionalComponent, vnodeData: d.PropsType, ...children: d.ChildType[]): d.VNode;
158const h = (nodeName, vnodeData, ...children) => {
159 let child = null;
160 let key = null;
161 let slotName = null;
162 let simple = false;
163 let lastSimple = false;
164 let vNodeChildren = [];
165 const walk = (c) => {
166 for (let i = 0; i < c.length; i++) {
167 child = c[i];
168 if (Array.isArray(child)) {
169 walk(child);
170 }
171 else if (child != null && typeof child !== 'boolean') {
172 if ((simple = typeof nodeName !== 'function' && !isComplexType(child))) {
173 child = String(child);
174 }
175 if (simple && lastSimple) {
176 // If the previous child was simple (string), we merge both
177 vNodeChildren[vNodeChildren.length - 1].$text$ += child;
178 }
179 else {
180 // Append a new vNode, if it's text, we create a text vNode
181 vNodeChildren.push(simple ? newVNode(null, child) : child);
182 }
183 lastSimple = simple;
184 }
185 }
186 };
187 walk(children);
188 if (vnodeData) {
189 // normalize class / classname attributes
190 if (vnodeData.key) {
191 key = vnodeData.key;
192 }
193 if (vnodeData.name) {
194 slotName = vnodeData.name;
195 }
196 {
197 const classData = vnodeData.className || vnodeData.class;
198 if (classData) {
199 vnodeData.class =
200 typeof classData !== 'object'
201 ? classData
202 : Object.keys(classData)
203 .filter((k) => classData[k])
204 .join(' ');
205 }
206 }
207 }
208 if (typeof nodeName === 'function') {
209 // nodeName is a functional component
210 return nodeName(vnodeData === null ? {} : vnodeData, vNodeChildren, vdomFnUtils);
211 }
212 const vnode = newVNode(nodeName, null);
213 vnode.$attrs$ = vnodeData;
214 if (vNodeChildren.length > 0) {
215 vnode.$children$ = vNodeChildren;
216 }
217 {
218 vnode.$key$ = key;
219 }
220 {
221 vnode.$name$ = slotName;
222 }
223 return vnode;
224};
225const newVNode = (tag, text) => {
226 const vnode = {
227 $flags$: 0,
228 $tag$: tag,
229 $text$: text,
230 $elm$: null,
231 $children$: null,
232 };
233 {
234 vnode.$attrs$ = null;
235 }
236 {
237 vnode.$key$ = null;
238 }
239 {
240 vnode.$name$ = null;
241 }
242 return vnode;
243};
244const Host = {};
245const isHost = (node) => node && node.$tag$ === Host;
246const vdomFnUtils = {
247 forEach: (children, cb) => children.map(convertToPublic).forEach(cb),
248 map: (children, cb) => children.map(convertToPublic).map(cb).map(convertToPrivate),
249};
250const convertToPublic = (node) => ({
251 vattrs: node.$attrs$,
252 vchildren: node.$children$,
253 vkey: node.$key$,
254 vname: node.$name$,
255 vtag: node.$tag$,
256 vtext: node.$text$,
257});
258const convertToPrivate = (node) => {
259 if (typeof node.vtag === 'function') {
260 const vnodeData = Object.assign({}, node.vattrs);
261 if (node.vkey) {
262 vnodeData.key = node.vkey;
263 }
264 if (node.vname) {
265 vnodeData.name = node.vname;
266 }
267 return h(node.vtag, vnodeData, ...(node.vchildren || []));
268 }
269 const vnode = newVNode(node.vtag, node.vtext);
270 vnode.$attrs$ = node.vattrs;
271 vnode.$children$ = node.vchildren;
272 vnode.$key$ = node.vkey;
273 vnode.$name$ = node.vname;
274 return vnode;
275};
276/**
277 * Production setAccessor() function based on Preact by
278 * Jason Miller (@developit)
279 * Licensed under the MIT License
280 * https://github.com/developit/preact/blob/master/LICENSE
281 *
282 * Modified for Stencil's compiler and vdom
283 */
284const setAccessor = (elm, memberName, oldValue, newValue, isSvg, flags) => {
285 if (oldValue !== newValue) {
286 let isProp = isMemberInElement(elm, memberName);
287 let ln = memberName.toLowerCase();
288 if (memberName === 'class') {
289 const classList = elm.classList;
290 const oldClasses = parseClassList(oldValue);
291 const newClasses = parseClassList(newValue);
292 classList.remove(...oldClasses.filter((c) => c && !newClasses.includes(c)));
293 classList.add(...newClasses.filter((c) => c && !oldClasses.includes(c)));
294 }
295 else if (memberName === 'style') {
296 // update style attribute, css properties and values
297 {
298 for (const prop in oldValue) {
299 if (!newValue || newValue[prop] == null) {
300 if (prop.includes('-')) {
301 elm.style.removeProperty(prop);
302 }
303 else {
304 elm.style[prop] = '';
305 }
306 }
307 }
308 }
309 for (const prop in newValue) {
310 if (!oldValue || newValue[prop] !== oldValue[prop]) {
311 if (prop.includes('-')) {
312 elm.style.setProperty(prop, newValue[prop]);
313 }
314 else {
315 elm.style[prop] = newValue[prop];
316 }
317 }
318 }
319 }
320 else if (memberName === 'key')
321 ;
322 else if (memberName === 'ref') {
323 // minifier will clean this up
324 if (newValue) {
325 newValue(elm);
326 }
327 }
328 else if ((!isProp ) &&
329 memberName[0] === 'o' &&
330 memberName[1] === 'n') {
331 // Event Handlers
332 // so if the member name starts with "on" and the 3rd characters is
333 // a capital letter, and it's not already a member on the element,
334 // then we're assuming it's an event listener
335 if (memberName[2] === '-') {
336 // on- prefixed events
337 // allows to be explicit about the dom event to listen without any magic
338 // under the hood:
339 // <my-cmp on-click> // listens for "click"
340 // <my-cmp on-Click> // listens for "Click"
341 // <my-cmp on-ionChange> // listens for "ionChange"
342 // <my-cmp on-EVENTS> // listens for "EVENTS"
343 memberName = memberName.slice(3);
344 }
345 else if (isMemberInElement(win, ln)) {
346 // standard event
347 // the JSX attribute could have been "onMouseOver" and the
348 // member name "onmouseover" is on the window's prototype
349 // so let's add the listener "mouseover", which is all lowercased
350 memberName = ln.slice(2);
351 }
352 else {
353 // custom event
354 // the JSX attribute could have been "onMyCustomEvent"
355 // so let's trim off the "on" prefix and lowercase the first character
356 // and add the listener "myCustomEvent"
357 // except for the first character, we keep the event name case
358 memberName = ln[2] + memberName.slice(3);
359 }
360 if (oldValue) {
361 plt.rel(elm, memberName, oldValue, false);
362 }
363 if (newValue) {
364 plt.ael(elm, memberName, newValue, false);
365 }
366 }
367 else {
368 // Set property if it exists and it's not a SVG
369 const isComplex = isComplexType(newValue);
370 if ((isProp || (isComplex && newValue !== null)) && !isSvg) {
371 try {
372 if (!elm.tagName.includes('-')) {
373 let n = newValue == null ? '' : newValue;
374 // Workaround for Safari, moving the <input> caret when re-assigning the same valued
375 if (memberName === 'list') {
376 isProp = false;
377 }
378 else if (oldValue == null || elm[memberName] != n) {
379 elm[memberName] = n;
380 }
381 }
382 else {
383 elm[memberName] = newValue;
384 }
385 }
386 catch (e) { }
387 }
388 /**
389 * Need to manually update attribute if:
390 * - memberName is not an attribute
391 * - if we are rendering the host element in order to reflect attribute
392 * - if it's a SVG, since properties might not work in <svg>
393 * - if the newValue is null/undefined or 'false'.
394 */
395 let xlink = false;
396 {
397 if (ln !== (ln = ln.replace(/^xlink\:?/, ''))) {
398 memberName = ln;
399 xlink = true;
400 }
401 }
402 if (newValue == null || newValue === false) {
403 if (newValue !== false || elm.getAttribute(memberName) === '') {
404 if (xlink) {
405 elm.removeAttributeNS(XLINK_NS, memberName);
406 }
407 else {
408 elm.removeAttribute(memberName);
409 }
410 }
411 }
412 else if ((!isProp || flags & 4 /* isHost */ || isSvg) && !isComplex) {
413 newValue = newValue === true ? '' : newValue;
414 if (xlink) {
415 elm.setAttributeNS(XLINK_NS, memberName, newValue);
416 }
417 else {
418 elm.setAttribute(memberName, newValue);
419 }
420 }
421 }
422 }
423};
424const parseClassListRegex = /\s/;
425const parseClassList = (value) => (!value ? [] : value.split(parseClassListRegex));
426const updateElement = (oldVnode, newVnode, isSvgMode, memberName) => {
427 // if the element passed in is a shadow root, which is a document fragment
428 // then we want to be adding attrs/props to the shadow root's "host" element
429 // if it's not a shadow root, then we add attrs/props to the same element
430 const elm = newVnode.$elm$.nodeType === 11 /* DocumentFragment */ && newVnode.$elm$.host
431 ? newVnode.$elm$.host
432 : newVnode.$elm$;
433 const oldVnodeAttrs = (oldVnode && oldVnode.$attrs$) || EMPTY_OBJ;
434 const newVnodeAttrs = newVnode.$attrs$ || EMPTY_OBJ;
435 {
436 // remove attributes no longer present on the vnode by setting them to undefined
437 for (memberName in oldVnodeAttrs) {
438 if (!(memberName in newVnodeAttrs)) {
439 setAccessor(elm, memberName, oldVnodeAttrs[memberName], undefined, isSvgMode, newVnode.$flags$);
440 }
441 }
442 }
443 // add new & update changed attributes
444 for (memberName in newVnodeAttrs) {
445 setAccessor(elm, memberName, oldVnodeAttrs[memberName], newVnodeAttrs[memberName], isSvgMode, newVnode.$flags$);
446 }
447};
448const createElm = (oldParentVNode, newParentVNode, childIndex, parentElm) => {
449 // tslint:disable-next-line: prefer-const
450 let newVNode = newParentVNode.$children$[childIndex];
451 let i = 0;
452 let elm;
453 let childNode;
454 let oldVNode;
455 if (!useNativeShadowDom) {
456 // remember for later we need to check to relocate nodes
457 checkSlotRelocate = true;
458 if (newVNode.$tag$ === 'slot') {
459 newVNode.$flags$ |= newVNode.$children$
460 ? // slot element has fallback content
461 2 /* isSlotFallback */
462 : // slot element does not have fallback content
463 1 /* isSlotReference */;
464 }
465 }
466 if (newVNode.$text$ !== null) {
467 // create text node
468 elm = newVNode.$elm$ = doc.createTextNode(newVNode.$text$);
469 }
470 else if (newVNode.$flags$ & 1 /* isSlotReference */) {
471 // create a slot reference node
472 elm = newVNode.$elm$ =
473 doc.createTextNode('');
474 }
475 else {
476 // create element
477 elm = newVNode.$elm$ = (doc.createElement(newVNode.$flags$ & 2 /* isSlotFallback */
478 ? 'slot-fb'
479 : newVNode.$tag$));
480 // add css classes, attrs, props, listeners, etc.
481 {
482 updateElement(null, newVNode, isSvgMode);
483 }
484 if (newVNode.$children$) {
485 for (i = 0; i < newVNode.$children$.length; ++i) {
486 // create the node
487 childNode = createElm(oldParentVNode, newVNode, i);
488 // return node could have been null
489 if (childNode) {
490 // append our new node
491 elm.appendChild(childNode);
492 }
493 }
494 }
495 }
496 {
497 elm['s-hn'] = hostTagName;
498 if (newVNode.$flags$ & (2 /* isSlotFallback */ | 1 /* isSlotReference */)) {
499 // remember the content reference comment
500 elm['s-sr'] = true;
501 // remember the content reference comment
502 elm['s-cr'] = contentRef;
503 // remember the slot name, or empty string for default slot
504 elm['s-sn'] = newVNode.$name$ || '';
505 // check if we've got an old vnode for this slot
506 oldVNode = oldParentVNode && oldParentVNode.$children$ && oldParentVNode.$children$[childIndex];
507 if (oldVNode && oldVNode.$tag$ === newVNode.$tag$ && oldParentVNode.$elm$) {
508 // we've got an old slot vnode and the wrapper is being replaced
509 // so let's move the old slot content back to it's original location
510 putBackInOriginalLocation(oldParentVNode.$elm$, false);
511 }
512 }
513 }
514 return elm;
515};
516const putBackInOriginalLocation = (parentElm, recursive) => {
517 plt.$flags$ |= 1 /* isTmpDisconnected */;
518 const oldSlotChildNodes = parentElm.childNodes;
519 for (let i = oldSlotChildNodes.length - 1; i >= 0; i--) {
520 const childNode = oldSlotChildNodes[i];
521 if (childNode['s-hn'] !== hostTagName && childNode['s-ol']) {
522 // // this child node in the old element is from another component
523 // // remove this node from the old slot's parent
524 // childNode.remove();
525 // and relocate it back to it's original location
526 parentReferenceNode(childNode).insertBefore(childNode, referenceNode(childNode));
527 // remove the old original location comment entirely
528 // later on the patch function will know what to do
529 // and move this to the correct spot in need be
530 childNode['s-ol'].remove();
531 childNode['s-ol'] = undefined;
532 checkSlotRelocate = true;
533 }
534 if (recursive) {
535 putBackInOriginalLocation(childNode, recursive);
536 }
537 }
538 plt.$flags$ &= ~1 /* isTmpDisconnected */;
539};
540const addVnodes = (parentElm, before, parentVNode, vnodes, startIdx, endIdx) => {
541 let containerElm = ((parentElm['s-cr'] && parentElm['s-cr'].parentNode) || parentElm);
542 let childNode;
543 for (; startIdx <= endIdx; ++startIdx) {
544 if (vnodes[startIdx]) {
545 childNode = createElm(null, parentVNode, startIdx);
546 if (childNode) {
547 vnodes[startIdx].$elm$ = childNode;
548 containerElm.insertBefore(childNode, referenceNode(before) );
549 }
550 }
551 }
552};
553const removeVnodes = (vnodes, startIdx, endIdx, vnode, elm) => {
554 for (; startIdx <= endIdx; ++startIdx) {
555 if ((vnode = vnodes[startIdx])) {
556 elm = vnode.$elm$;
557 callNodeRefs(vnode);
558 {
559 // we're removing this element
560 // so it's possible we need to show slot fallback content now
561 checkSlotFallbackVisibility = true;
562 if (elm['s-ol']) {
563 // remove the original location comment
564 elm['s-ol'].remove();
565 }
566 else {
567 // it's possible that child nodes of the node
568 // that's being removed are slot nodes
569 putBackInOriginalLocation(elm, true);
570 }
571 }
572 // remove the vnode's element from the dom
573 elm.remove();
574 }
575 }
576};
577const updateChildren = (parentElm, oldCh, newVNode, newCh) => {
578 let oldStartIdx = 0;
579 let newStartIdx = 0;
580 let idxInOld = 0;
581 let i = 0;
582 let oldEndIdx = oldCh.length - 1;
583 let oldStartVnode = oldCh[0];
584 let oldEndVnode = oldCh[oldEndIdx];
585 let newEndIdx = newCh.length - 1;
586 let newStartVnode = newCh[0];
587 let newEndVnode = newCh[newEndIdx];
588 let node;
589 let elmToMove;
590 while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
591 if (oldStartVnode == null) {
592 // Vnode might have been moved left
593 oldStartVnode = oldCh[++oldStartIdx];
594 }
595 else if (oldEndVnode == null) {
596 oldEndVnode = oldCh[--oldEndIdx];
597 }
598 else if (newStartVnode == null) {
599 newStartVnode = newCh[++newStartIdx];
600 }
601 else if (newEndVnode == null) {
602 newEndVnode = newCh[--newEndIdx];
603 }
604 else if (isSameVnode(oldStartVnode, newStartVnode)) {
605 patch(oldStartVnode, newStartVnode);
606 oldStartVnode = oldCh[++oldStartIdx];
607 newStartVnode = newCh[++newStartIdx];
608 }
609 else if (isSameVnode(oldEndVnode, newEndVnode)) {
610 patch(oldEndVnode, newEndVnode);
611 oldEndVnode = oldCh[--oldEndIdx];
612 newEndVnode = newCh[--newEndIdx];
613 }
614 else if (isSameVnode(oldStartVnode, newEndVnode)) {
615 // Vnode moved right
616 if ((oldStartVnode.$tag$ === 'slot' || newEndVnode.$tag$ === 'slot')) {
617 putBackInOriginalLocation(oldStartVnode.$elm$.parentNode, false);
618 }
619 patch(oldStartVnode, newEndVnode);
620 parentElm.insertBefore(oldStartVnode.$elm$, oldEndVnode.$elm$.nextSibling);
621 oldStartVnode = oldCh[++oldStartIdx];
622 newEndVnode = newCh[--newEndIdx];
623 }
624 else if (isSameVnode(oldEndVnode, newStartVnode)) {
625 // Vnode moved left
626 if ((oldStartVnode.$tag$ === 'slot' || newEndVnode.$tag$ === 'slot')) {
627 putBackInOriginalLocation(oldEndVnode.$elm$.parentNode, false);
628 }
629 patch(oldEndVnode, newStartVnode);
630 parentElm.insertBefore(oldEndVnode.$elm$, oldStartVnode.$elm$);
631 oldEndVnode = oldCh[--oldEndIdx];
632 newStartVnode = newCh[++newStartIdx];
633 }
634 else {
635 // createKeyToOldIdx
636 idxInOld = -1;
637 {
638 for (i = oldStartIdx; i <= oldEndIdx; ++i) {
639 if (oldCh[i] && oldCh[i].$key$ !== null && oldCh[i].$key$ === newStartVnode.$key$) {
640 idxInOld = i;
641 break;
642 }
643 }
644 }
645 if (idxInOld >= 0) {
646 elmToMove = oldCh[idxInOld];
647 if (elmToMove.$tag$ !== newStartVnode.$tag$) {
648 node = createElm(oldCh && oldCh[newStartIdx], newVNode, idxInOld);
649 }
650 else {
651 patch(elmToMove, newStartVnode);
652 oldCh[idxInOld] = undefined;
653 node = elmToMove.$elm$;
654 }
655 newStartVnode = newCh[++newStartIdx];
656 }
657 else {
658 // new element
659 node = createElm(oldCh && oldCh[newStartIdx], newVNode, newStartIdx);
660 newStartVnode = newCh[++newStartIdx];
661 }
662 if (node) {
663 {
664 parentReferenceNode(oldStartVnode.$elm$).insertBefore(node, referenceNode(oldStartVnode.$elm$));
665 }
666 }
667 }
668 }
669 if (oldStartIdx > oldEndIdx) {
670 addVnodes(parentElm, newCh[newEndIdx + 1] == null ? null : newCh[newEndIdx + 1].$elm$, newVNode, newCh, newStartIdx, newEndIdx);
671 }
672 else if (newStartIdx > newEndIdx) {
673 removeVnodes(oldCh, oldStartIdx, oldEndIdx);
674 }
675};
676const isSameVnode = (vnode1, vnode2) => {
677 // compare if two vnode to see if they're "technically" the same
678 // need to have the same element tag, and same key to be the same
679 if (vnode1.$tag$ === vnode2.$tag$) {
680 if (vnode1.$tag$ === 'slot') {
681 return vnode1.$name$ === vnode2.$name$;
682 }
683 {
684 return vnode1.$key$ === vnode2.$key$;
685 }
686 }
687 return false;
688};
689const referenceNode = (node) => {
690 // this node was relocated to a new location in the dom
691 // because of some other component's slot
692 // but we still have an html comment in place of where
693 // it's original location was according to it's original vdom
694 return (node && node['s-ol']) || node;
695};
696const parentReferenceNode = (node) => (node['s-ol'] ? node['s-ol'] : node).parentNode;
697const patch = (oldVNode, newVNode) => {
698 const elm = (newVNode.$elm$ = oldVNode.$elm$);
699 const oldChildren = oldVNode.$children$;
700 const newChildren = newVNode.$children$;
701 const tag = newVNode.$tag$;
702 const text = newVNode.$text$;
703 let defaultHolder;
704 if (text === null) {
705 // element node
706 {
707 if (tag === 'slot')
708 ;
709 else {
710 // either this is the first render of an element OR it's an update
711 // AND we already know it's possible it could have changed
712 // this updates the element's css classes, attrs, props, listeners, etc.
713 updateElement(oldVNode, newVNode, isSvgMode);
714 }
715 }
716 if (oldChildren !== null && newChildren !== null) {
717 // looks like there's child vnodes for both the old and new vnodes
718 updateChildren(elm, oldChildren, newVNode, newChildren);
719 }
720 else if (newChildren !== null) {
721 // no old child vnodes, but there are new child vnodes to add
722 if (oldVNode.$text$ !== null) {
723 // the old vnode was text, so be sure to clear it out
724 elm.textContent = '';
725 }
726 // add the new vnode children
727 addVnodes(elm, null, newVNode, newChildren, 0, newChildren.length - 1);
728 }
729 else if (oldChildren !== null) {
730 // no new child vnodes, but there are old child vnodes to remove
731 removeVnodes(oldChildren, 0, oldChildren.length - 1);
732 }
733 }
734 else if ((defaultHolder = elm['s-cr'])) {
735 // this element has slotted content
736 defaultHolder.parentNode.textContent = text;
737 }
738 else if (oldVNode.$text$ !== text) {
739 // update the text content for the text only vnode
740 // and also only if the text is different than before
741 elm.data = text;
742 }
743};
744const updateFallbackSlotVisibility = (elm) => {
745 // tslint:disable-next-line: prefer-const
746 let childNodes = elm.childNodes;
747 let childNode;
748 let i;
749 let ilen;
750 let j;
751 let slotNameAttr;
752 let nodeType;
753 for (i = 0, ilen = childNodes.length; i < ilen; i++) {
754 childNode = childNodes[i];
755 if (childNode.nodeType === 1 /* ElementNode */) {
756 if (childNode['s-sr']) {
757 // this is a slot fallback node
758 // get the slot name for this slot reference node
759 slotNameAttr = childNode['s-sn'];
760 // by default always show a fallback slot node
761 // then hide it if there are other slots in the light dom
762 childNode.hidden = false;
763 for (j = 0; j < ilen; j++) {
764 nodeType = childNodes[j].nodeType;
765 if (childNodes[j]['s-hn'] !== childNode['s-hn'] || slotNameAttr !== '') {
766 // this sibling node is from a different component OR is a named fallback slot node
767 if (nodeType === 1 /* ElementNode */ && slotNameAttr === childNodes[j].getAttribute('slot')) {
768 childNode.hidden = true;
769 break;
770 }
771 }
772 else {
773 // this is a default fallback slot node
774 // any element or text node (with content)
775 // should hide the default fallback slot node
776 if (nodeType === 1 /* ElementNode */ ||
777 (nodeType === 3 /* TextNode */ && childNodes[j].textContent.trim() !== '')) {
778 childNode.hidden = true;
779 break;
780 }
781 }
782 }
783 }
784 // keep drilling down
785 updateFallbackSlotVisibility(childNode);
786 }
787 }
788};
789const relocateNodes = [];
790const relocateSlotContent = (elm) => {
791 // tslint:disable-next-line: prefer-const
792 let childNode;
793 let node;
794 let hostContentNodes;
795 let slotNameAttr;
796 let relocateNodeData;
797 let j;
798 let i = 0;
799 let childNodes = elm.childNodes;
800 let ilen = childNodes.length;
801 for (; i < ilen; i++) {
802 childNode = childNodes[i];
803 if (childNode['s-sr'] && (node = childNode['s-cr']) && node.parentNode) {
804 // first got the content reference comment node
805 // then we got it's parent, which is where all the host content is in now
806 hostContentNodes = node.parentNode.childNodes;
807 slotNameAttr = childNode['s-sn'];
808 for (j = hostContentNodes.length - 1; j >= 0; j--) {
809 node = hostContentNodes[j];
810 if (!node['s-cn'] && !node['s-nr'] && node['s-hn'] !== childNode['s-hn']) {
811 // let's do some relocating to its new home
812 // but never relocate a content reference node
813 // that is suppose to always represent the original content location
814 if (isNodeLocatedInSlot(node, slotNameAttr)) {
815 // it's possible we've already decided to relocate this node
816 relocateNodeData = relocateNodes.find((r) => r.$nodeToRelocate$ === node);
817 // made some changes to slots
818 // let's make sure we also double check
819 // fallbacks are correctly hidden or shown
820 checkSlotFallbackVisibility = true;
821 node['s-sn'] = node['s-sn'] || slotNameAttr;
822 if (relocateNodeData) {
823 // previously we never found a slot home for this node
824 // but turns out we did, so let's remember it now
825 relocateNodeData.$slotRefNode$ = childNode;
826 }
827 else {
828 // add to our list of nodes to relocate
829 relocateNodes.push({
830 $slotRefNode$: childNode,
831 $nodeToRelocate$: node,
832 });
833 }
834 if (node['s-sr']) {
835 relocateNodes.map((relocateNode) => {
836 if (isNodeLocatedInSlot(relocateNode.$nodeToRelocate$, node['s-sn'])) {
837 relocateNodeData = relocateNodes.find((r) => r.$nodeToRelocate$ === node);
838 if (relocateNodeData && !relocateNode.$slotRefNode$) {
839 relocateNode.$slotRefNode$ = relocateNodeData.$slotRefNode$;
840 }
841 }
842 });
843 }
844 }
845 else if (!relocateNodes.some((r) => r.$nodeToRelocate$ === node)) {
846 // so far this element does not have a slot home, not setting slotRefNode on purpose
847 // if we never find a home for this element then we'll need to hide it
848 relocateNodes.push({
849 $nodeToRelocate$: node,
850 });
851 }
852 }
853 }
854 }
855 if (childNode.nodeType === 1 /* ElementNode */) {
856 relocateSlotContent(childNode);
857 }
858 }
859};
860const isNodeLocatedInSlot = (nodeToRelocate, slotNameAttr) => {
861 if (nodeToRelocate.nodeType === 1 /* ElementNode */) {
862 if (nodeToRelocate.getAttribute('slot') === null && slotNameAttr === '') {
863 return true;
864 }
865 if (nodeToRelocate.getAttribute('slot') === slotNameAttr) {
866 return true;
867 }
868 return false;
869 }
870 if (nodeToRelocate['s-sn'] === slotNameAttr) {
871 return true;
872 }
873 return slotNameAttr === '';
874};
875const callNodeRefs = (vNode) => {
876 {
877 vNode.$attrs$ && vNode.$attrs$.ref && vNode.$attrs$.ref(null);
878 vNode.$children$ && vNode.$children$.map(callNodeRefs);
879 }
880};
881const renderVdom = (hostRef, renderFnResults) => {
882 const hostElm = hostRef.$hostElement$;
883 const cmpMeta = hostRef.$cmpMeta$;
884 const oldVNode = hostRef.$vnode$ || newVNode(null, null);
885 const rootVnode = isHost(renderFnResults) ? renderFnResults : h(null, null, renderFnResults);
886 hostTagName = hostElm.tagName;
887 rootVnode.$tag$ = null;
888 rootVnode.$flags$ |= 4 /* isHost */;
889 hostRef.$vnode$ = rootVnode;
890 rootVnode.$elm$ = oldVNode.$elm$ = (hostElm);
891 {
892 contentRef = hostElm['s-cr'];
893 useNativeShadowDom = (cmpMeta.$flags$ & 1 /* shadowDomEncapsulation */) !== 0;
894 // always reset
895 checkSlotFallbackVisibility = false;
896 }
897 // synchronous patch
898 patch(oldVNode, rootVnode);
899 {
900 // while we're moving nodes around existing nodes, temporarily disable
901 // the disconnectCallback from working
902 plt.$flags$ |= 1 /* isTmpDisconnected */;
903 if (checkSlotRelocate) {
904 relocateSlotContent(rootVnode.$elm$);
905 let relocateData;
906 let nodeToRelocate;
907 let orgLocationNode;
908 let parentNodeRef;
909 let insertBeforeNode;
910 let refNode;
911 let i = 0;
912 for (; i < relocateNodes.length; i++) {
913 relocateData = relocateNodes[i];
914 nodeToRelocate = relocateData.$nodeToRelocate$;
915 if (!nodeToRelocate['s-ol']) {
916 // add a reference node marking this node's original location
917 // keep a reference to this node for later lookups
918 orgLocationNode =
919 doc.createTextNode('');
920 orgLocationNode['s-nr'] = nodeToRelocate;
921 nodeToRelocate.parentNode.insertBefore((nodeToRelocate['s-ol'] = orgLocationNode), nodeToRelocate);
922 }
923 }
924 for (i = 0; i < relocateNodes.length; i++) {
925 relocateData = relocateNodes[i];
926 nodeToRelocate = relocateData.$nodeToRelocate$;
927 if (relocateData.$slotRefNode$) {
928 // by default we're just going to insert it directly
929 // after the slot reference node
930 parentNodeRef = relocateData.$slotRefNode$.parentNode;
931 insertBeforeNode = relocateData.$slotRefNode$.nextSibling;
932 orgLocationNode = nodeToRelocate['s-ol'];
933 while ((orgLocationNode = orgLocationNode.previousSibling)) {
934 refNode = orgLocationNode['s-nr'];
935 if (refNode && refNode['s-sn'] === nodeToRelocate['s-sn'] && parentNodeRef === refNode.parentNode) {
936 refNode = refNode.nextSibling;
937 if (!refNode || !refNode['s-nr']) {
938 insertBeforeNode = refNode;
939 break;
940 }
941 }
942 }
943 if ((!insertBeforeNode && parentNodeRef !== nodeToRelocate.parentNode) ||
944 nodeToRelocate.nextSibling !== insertBeforeNode) {
945 // we've checked that it's worth while to relocate
946 // since that the node to relocate
947 // has a different next sibling or parent relocated
948 if (nodeToRelocate !== insertBeforeNode) {
949 if (!nodeToRelocate['s-hn'] && nodeToRelocate['s-ol']) {
950 // probably a component in the index.html that doesn't have it's hostname set
951 nodeToRelocate['s-hn'] = nodeToRelocate['s-ol'].parentNode.nodeName;
952 }
953 // add it back to the dom but in its new home
954 parentNodeRef.insertBefore(nodeToRelocate, insertBeforeNode);
955 }
956 }
957 }
958 else {
959 // this node doesn't have a slot home to go to, so let's hide it
960 if (nodeToRelocate.nodeType === 1 /* ElementNode */) {
961 nodeToRelocate.hidden = true;
962 }
963 }
964 }
965 }
966 if (checkSlotFallbackVisibility) {
967 updateFallbackSlotVisibility(rootVnode.$elm$);
968 }
969 // done moving nodes around
970 // allow the disconnect callback to work again
971 plt.$flags$ &= ~1 /* isTmpDisconnected */;
972 // always reset
973 relocateNodes.length = 0;
974 }
975};
976const getElement = (ref) => (getHostRef(ref).$hostElement$ );
977const createEvent = (ref, name, flags) => {
978 const elm = getElement(ref);
979 return {
980 emit: (detail) => {
981 return emitEvent(elm, name, {
982 bubbles: !!(flags & 4 /* Bubbles */),
983 composed: !!(flags & 2 /* Composed */),
984 cancelable: !!(flags & 1 /* Cancellable */),
985 detail,
986 });
987 },
988 };
989};
990/**
991 * Helper function to create & dispatch a custom Event on a provided target
992 * @param elm the target of the Event
993 * @param name the name to give the custom Event
994 * @param opts options for configuring a custom Event
995 * @returns the custom Event
996 */
997const emitEvent = (elm, name, opts) => {
998 const ev = plt.ce(name, opts);
999 elm.dispatchEvent(ev);
1000 return ev;
1001};
1002const attachToAncestor = (hostRef, ancestorComponent) => {
1003 if (ancestorComponent && !hostRef.$onRenderResolve$ && ancestorComponent['s-p']) {
1004 ancestorComponent['s-p'].push(new Promise((r) => (hostRef.$onRenderResolve$ = r)));
1005 }
1006};
1007const scheduleUpdate = (hostRef, isInitialLoad) => {
1008 {
1009 hostRef.$flags$ |= 16 /* isQueuedForUpdate */;
1010 }
1011 if (hostRef.$flags$ & 4 /* isWaitingForChildren */) {
1012 hostRef.$flags$ |= 512 /* needsRerender */;
1013 return;
1014 }
1015 attachToAncestor(hostRef, hostRef.$ancestorComponent$);
1016 // there is no ancestor component or the ancestor component
1017 // has already fired off its lifecycle update then
1018 // fire off the initial update
1019 const dispatch = () => dispatchHooks(hostRef, isInitialLoad);
1020 return writeTask(dispatch) ;
1021};
1022const dispatchHooks = (hostRef, isInitialLoad) => {
1023 const endSchedule = createTime('scheduleUpdate', hostRef.$cmpMeta$.$tagName$);
1024 const instance = hostRef.$lazyInstance$ ;
1025 let promise;
1026 if (isInitialLoad) {
1027 {
1028 hostRef.$flags$ |= 256 /* isListenReady */;
1029 if (hostRef.$queuedListeners$) {
1030 hostRef.$queuedListeners$.map(([methodName, event]) => safeCall(instance, methodName, event));
1031 hostRef.$queuedListeners$ = null;
1032 }
1033 }
1034 {
1035 promise = safeCall(instance, 'componentWillLoad');
1036 }
1037 }
1038 else {
1039 {
1040 promise = safeCall(instance, 'componentWillUpdate');
1041 }
1042 }
1043 endSchedule();
1044 return then(promise, () => updateComponent(hostRef, instance, isInitialLoad));
1045};
1046const updateComponent = async (hostRef, instance, isInitialLoad) => {
1047 // updateComponent
1048 const elm = hostRef.$hostElement$;
1049 const endUpdate = createTime('update', hostRef.$cmpMeta$.$tagName$);
1050 const rc = elm['s-rc'];
1051 if (isInitialLoad) {
1052 // DOM WRITE!
1053 attachStyles(hostRef);
1054 }
1055 const endRender = createTime('render', hostRef.$cmpMeta$.$tagName$);
1056 {
1057 callRender(hostRef, instance);
1058 }
1059 if (rc) {
1060 // ok, so turns out there are some child host elements
1061 // waiting on this parent element to load
1062 // let's fire off all update callbacks waiting
1063 rc.map((cb) => cb());
1064 elm['s-rc'] = undefined;
1065 }
1066 endRender();
1067 endUpdate();
1068 {
1069 const childrenPromises = elm['s-p'];
1070 const postUpdate = () => postUpdateComponent(hostRef);
1071 if (childrenPromises.length === 0) {
1072 postUpdate();
1073 }
1074 else {
1075 Promise.all(childrenPromises).then(postUpdate);
1076 hostRef.$flags$ |= 4 /* isWaitingForChildren */;
1077 childrenPromises.length = 0;
1078 }
1079 }
1080};
1081const callRender = (hostRef, instance, elm) => {
1082 try {
1083 instance = instance.render() ;
1084 {
1085 hostRef.$flags$ &= ~16 /* isQueuedForUpdate */;
1086 }
1087 {
1088 hostRef.$flags$ |= 2 /* hasRendered */;
1089 }
1090 {
1091 {
1092 // looks like we've got child nodes to render into this host element
1093 // or we need to update the css class/attrs on the host element
1094 // DOM WRITE!
1095 {
1096 renderVdom(hostRef, instance);
1097 }
1098 }
1099 }
1100 }
1101 catch (e) {
1102 consoleError(e, hostRef.$hostElement$);
1103 }
1104 return null;
1105};
1106const postUpdateComponent = (hostRef) => {
1107 const tagName = hostRef.$cmpMeta$.$tagName$;
1108 const elm = hostRef.$hostElement$;
1109 const endPostUpdate = createTime('postUpdate', tagName);
1110 const instance = hostRef.$lazyInstance$ ;
1111 const ancestorComponent = hostRef.$ancestorComponent$;
1112 {
1113 safeCall(instance, 'componentDidRender');
1114 }
1115 if (!(hostRef.$flags$ & 64 /* hasLoadedComponent */)) {
1116 hostRef.$flags$ |= 64 /* hasLoadedComponent */;
1117 {
1118 // DOM WRITE!
1119 addHydratedFlag(elm);
1120 }
1121 {
1122 safeCall(instance, 'componentDidLoad');
1123 }
1124 endPostUpdate();
1125 {
1126 hostRef.$onReadyResolve$(elm);
1127 if (!ancestorComponent) {
1128 appDidLoad();
1129 }
1130 }
1131 }
1132 else {
1133 {
1134 safeCall(instance, 'componentDidUpdate');
1135 }
1136 endPostUpdate();
1137 }
1138 {
1139 hostRef.$onInstanceResolve$(elm);
1140 }
1141 // load events fire from bottom to top
1142 // the deepest elements load first then bubbles up
1143 {
1144 if (hostRef.$onRenderResolve$) {
1145 hostRef.$onRenderResolve$();
1146 hostRef.$onRenderResolve$ = undefined;
1147 }
1148 if (hostRef.$flags$ & 512 /* needsRerender */) {
1149 nextTick(() => scheduleUpdate(hostRef, false));
1150 }
1151 hostRef.$flags$ &= ~(4 /* isWaitingForChildren */ | 512 /* needsRerender */);
1152 }
1153 // ( •_•)
1154 // ( •_•)>⌐■-■
1155 // (⌐■_■)
1156};
1157const appDidLoad = (who) => {
1158 // on appload
1159 // we have finish the first big initial render
1160 {
1161 addHydratedFlag(doc.documentElement);
1162 }
1163 nextTick(() => emitEvent(win, 'appload', { detail: { namespace: NAMESPACE } }));
1164};
1165const safeCall = (instance, method, arg) => {
1166 if (instance && instance[method]) {
1167 try {
1168 return instance[method](arg);
1169 }
1170 catch (e) {
1171 consoleError(e);
1172 }
1173 }
1174 return undefined;
1175};
1176const then = (promise, thenFn) => {
1177 return promise && promise.then ? promise.then(thenFn) : thenFn();
1178};
1179const addHydratedFlag = (elm) => elm.classList.add('hydrated')
1180 ;
1181const parsePropertyValue = (propValue, propType) => {
1182 // ensure this value is of the correct prop type
1183 if (propValue != null && !isComplexType(propValue)) {
1184 if (propType & 4 /* Boolean */) {
1185 // per the HTML spec, any string value means it is a boolean true value
1186 // but we'll cheat here and say that the string "false" is the boolean false
1187 return propValue === 'false' ? false : propValue === '' || !!propValue;
1188 }
1189 if (propType & 2 /* Number */) {
1190 // force it to be a number
1191 return parseFloat(propValue);
1192 }
1193 if (propType & 1 /* String */) {
1194 // could have been passed as a number or boolean
1195 // but we still want it as a string
1196 return String(propValue);
1197 }
1198 // redundant return here for better minification
1199 return propValue;
1200 }
1201 // not sure exactly what type we want
1202 // so no need to change to a different type
1203 return propValue;
1204};
1205const getValue = (ref, propName) => getHostRef(ref).$instanceValues$.get(propName);
1206const setValue = (ref, propName, newVal, cmpMeta) => {
1207 // check our new property value against our internal value
1208 const hostRef = getHostRef(ref);
1209 const elm = hostRef.$hostElement$ ;
1210 const oldVal = hostRef.$instanceValues$.get(propName);
1211 const flags = hostRef.$flags$;
1212 const instance = hostRef.$lazyInstance$ ;
1213 newVal = parsePropertyValue(newVal, cmpMeta.$members$[propName][0]);
1214 if ((!(flags & 8 /* isConstructingInstance */) || oldVal === undefined) && newVal !== oldVal) {
1215 // gadzooks! the property's value has changed!!
1216 // set our new value!
1217 hostRef.$instanceValues$.set(propName, newVal);
1218 if (instance) {
1219 // get an array of method names of watch functions to call
1220 if (cmpMeta.$watchers$ && flags & 128 /* isWatchReady */) {
1221 const watchMethods = cmpMeta.$watchers$[propName];
1222 if (watchMethods) {
1223 // this instance is watching for when this property changed
1224 watchMethods.map((watchMethodName) => {
1225 try {
1226 // fire off each of the watch methods that are watching this property
1227 instance[watchMethodName](newVal, oldVal, propName);
1228 }
1229 catch (e) {
1230 consoleError(e, elm);
1231 }
1232 });
1233 }
1234 }
1235 if ((flags & (2 /* hasRendered */ | 16 /* isQueuedForUpdate */)) === 2 /* hasRendered */) {
1236 // looks like this value actually changed, so we've got work to do!
1237 // but only if we've already rendered, otherwise just chill out
1238 // queue that we need to do an update, but don't worry about queuing
1239 // up millions cuz this function ensures it only runs once
1240 scheduleUpdate(hostRef, false);
1241 }
1242 }
1243 }
1244};
1245const proxyComponent = (Cstr, cmpMeta, flags) => {
1246 if (cmpMeta.$members$) {
1247 if (Cstr.watchers) {
1248 cmpMeta.$watchers$ = Cstr.watchers;
1249 }
1250 // It's better to have a const than two Object.entries()
1251 const members = Object.entries(cmpMeta.$members$);
1252 const prototype = Cstr.prototype;
1253 members.map(([memberName, [memberFlags]]) => {
1254 if ((memberFlags & 31 /* Prop */ ||
1255 ((flags & 2 /* proxyState */) && memberFlags & 32 /* State */))) {
1256 // proxyComponent - prop
1257 Object.defineProperty(prototype, memberName, {
1258 get() {
1259 // proxyComponent, get value
1260 return getValue(this, memberName);
1261 },
1262 set(newValue) {
1263 // proxyComponent, set value
1264 setValue(this, memberName, newValue, cmpMeta);
1265 },
1266 configurable: true,
1267 enumerable: true,
1268 });
1269 }
1270 else if (flags & 1 /* isElementConstructor */ &&
1271 memberFlags & 64 /* Method */) {
1272 // proxyComponent - method
1273 Object.defineProperty(prototype, memberName, {
1274 value(...args) {
1275 const ref = getHostRef(this);
1276 return ref.$onInstancePromise$.then(() => ref.$lazyInstance$[memberName](...args));
1277 },
1278 });
1279 }
1280 });
1281 if ((flags & 1 /* isElementConstructor */)) {
1282 const attrNameToPropName = new Map();
1283 prototype.attributeChangedCallback = function (attrName, _oldValue, newValue) {
1284 plt.jmp(() => {
1285 const propName = attrNameToPropName.get(attrName);
1286 // In a web component lifecycle the attributeChangedCallback runs prior to connectedCallback
1287 // in the case where an attribute was set inline.
1288 // ```html
1289 // <my-component some-attribute="some-value"></my-component>
1290 // ```
1291 //
1292 // There is an edge case where a developer sets the attribute inline on a custom element and then
1293 // programmatically changes it before it has been upgraded as shown below:
1294 //
1295 // ```html
1296 // <!-- this component has _not_ been upgraded yet -->
1297 // <my-component id="test" some-attribute="some-value"></my-component>
1298 // <script>
1299 // // grab non-upgraded component
1300 // el = document.querySelector("#test");
1301 // el.someAttribute = "another-value";
1302 // // upgrade component
1303 // customElements.define('my-component', MyComponent);
1304 // </script>
1305 // ```
1306 // In this case if we do not unshadow here and use the value of the shadowing property, attributeChangedCallback
1307 // will be called with `newValue = "some-value"` and will set the shadowed property (this.someAttribute = "another-value")
1308 // to the value that was set inline i.e. "some-value" from above example. When
1309 // the connectedCallback attempts to unshadow it will use "some-value" as the initial value rather than "another-value"
1310 //
1311 // The case where the attribute was NOT set inline but was not set programmatically shall be handled/unshadowed
1312 // by connectedCallback as this attributeChangedCallback will not fire.
1313 //
1314 // https://developers.google.com/web/fundamentals/web-components/best-practices#lazy-properties
1315 //
1316 // TODO(STENCIL-16) we should think about whether or not we actually want to be reflecting the attributes to
1317 // properties here given that this goes against best practices outlined here
1318 // https://developers.google.com/web/fundamentals/web-components/best-practices#avoid-reentrancy
1319 if (this.hasOwnProperty(propName)) {
1320 newValue = this[propName];
1321 delete this[propName];
1322 }
1323 else if (prototype.hasOwnProperty(propName) &&
1324 typeof this[propName] === 'number' &&
1325 this[propName] == newValue) {
1326 // if the propName exists on the prototype of `Cstr`, this update may be a result of Stencil using native
1327 // APIs to reflect props as attributes. Calls to `setAttribute(someElement, propName)` will result in
1328 // `propName` to be converted to a `DOMString`, which may not be what we want for other primitive props.
1329 return;
1330 }
1331 this[propName] = newValue === null && typeof this[propName] === 'boolean' ? false : newValue;
1332 });
1333 };
1334 // create an array of attributes to observe
1335 // and also create a map of html attribute name to js property name
1336 Cstr.observedAttributes = members
1337 .filter(([_, m]) => m[0] & 15 /* HasAttribute */) // filter to only keep props that should match attributes
1338 .map(([propName, m]) => {
1339 const attrName = m[1] || propName;
1340 attrNameToPropName.set(attrName, propName);
1341 return attrName;
1342 });
1343 }
1344 }
1345 return Cstr;
1346};
1347const initializeComponent = async (elm, hostRef, cmpMeta, hmrVersionId, Cstr) => {
1348 // initializeComponent
1349 if ((hostRef.$flags$ & 32 /* hasInitializedComponent */) === 0) {
1350 {
1351 // we haven't initialized this element yet
1352 hostRef.$flags$ |= 32 /* hasInitializedComponent */;
1353 // lazy loaded components
1354 // request the component's implementation to be
1355 // wired up with the host element
1356 Cstr = loadModule(cmpMeta);
1357 if (Cstr.then) {
1358 // Await creates a micro-task avoid if possible
1359 const endLoad = uniqueTime();
1360 Cstr = await Cstr;
1361 endLoad();
1362 }
1363 if (!Cstr.isProxied) {
1364 // we've never proxied this Constructor before
1365 // let's add the getters/setters to its prototype before
1366 // the first time we create an instance of the implementation
1367 {
1368 cmpMeta.$watchers$ = Cstr.watchers;
1369 }
1370 proxyComponent(Cstr, cmpMeta, 2 /* proxyState */);
1371 Cstr.isProxied = true;
1372 }
1373 const endNewInstance = createTime('createInstance', cmpMeta.$tagName$);
1374 // ok, time to construct the instance
1375 // but let's keep track of when we start and stop
1376 // so that the getters/setters don't incorrectly step on data
1377 {
1378 hostRef.$flags$ |= 8 /* isConstructingInstance */;
1379 }
1380 // construct the lazy-loaded component implementation
1381 // passing the hostRef is very important during
1382 // construction in order to directly wire together the
1383 // host element and the lazy-loaded instance
1384 try {
1385 new Cstr(hostRef);
1386 }
1387 catch (e) {
1388 consoleError(e);
1389 }
1390 {
1391 hostRef.$flags$ &= ~8 /* isConstructingInstance */;
1392 }
1393 {
1394 hostRef.$flags$ |= 128 /* isWatchReady */;
1395 }
1396 endNewInstance();
1397 fireConnectedCallback(hostRef.$lazyInstance$);
1398 }
1399 if (Cstr.style) {
1400 // this component has styles but we haven't registered them yet
1401 let style = Cstr.style;
1402 const scopeId = getScopeId(cmpMeta);
1403 if (!styles.has(scopeId)) {
1404 const endRegisterStyles = createTime('registerStyles', cmpMeta.$tagName$);
1405 registerStyle(scopeId, style, !!(cmpMeta.$flags$ & 1 /* shadowDomEncapsulation */));
1406 endRegisterStyles();
1407 }
1408 }
1409 }
1410 // we've successfully created a lazy instance
1411 const ancestorComponent = hostRef.$ancestorComponent$;
1412 const schedule = () => scheduleUpdate(hostRef, true);
1413 if (ancestorComponent && ancestorComponent['s-rc']) {
1414 // this is the initial load and this component it has an ancestor component
1415 // but the ancestor component has NOT fired its will update lifecycle yet
1416 // so let's just cool our jets and wait for the ancestor to continue first
1417 // this will get fired off when the ancestor component
1418 // finally gets around to rendering its lazy self
1419 // fire off the initial update
1420 ancestorComponent['s-rc'].push(schedule);
1421 }
1422 else {
1423 schedule();
1424 }
1425};
1426const fireConnectedCallback = (instance) => {
1427 {
1428 safeCall(instance, 'connectedCallback');
1429 }
1430};
1431const connectedCallback = (elm) => {
1432 if ((plt.$flags$ & 1 /* isTmpDisconnected */) === 0) {
1433 const hostRef = getHostRef(elm);
1434 const cmpMeta = hostRef.$cmpMeta$;
1435 const endConnected = createTime('connectedCallback', cmpMeta.$tagName$);
1436 if (!(hostRef.$flags$ & 1 /* hasConnected */)) {
1437 // first time this component has connected
1438 hostRef.$flags$ |= 1 /* hasConnected */;
1439 {
1440 // initUpdate
1441 // if the slot polyfill is required we'll need to put some nodes
1442 // in here to act as original content anchors as we move nodes around
1443 // host element has been connected to the DOM
1444 if ((cmpMeta.$flags$ & (4 /* hasSlotRelocation */ | 8 /* needsShadowDomShim */))) {
1445 setContentReference(elm);
1446 }
1447 }
1448 {
1449 // find the first ancestor component (if there is one) and register
1450 // this component as one of the actively loading child components for its ancestor
1451 let ancestorComponent = elm;
1452 while ((ancestorComponent = ancestorComponent.parentNode || ancestorComponent.host)) {
1453 // climb up the ancestors looking for the first
1454 // component that hasn't finished its lifecycle update yet
1455 if (ancestorComponent['s-p']) {
1456 // we found this components first ancestor component
1457 // keep a reference to this component's ancestor component
1458 attachToAncestor(hostRef, (hostRef.$ancestorComponent$ = ancestorComponent));
1459 break;
1460 }
1461 }
1462 }
1463 // Lazy properties
1464 // https://developers.google.com/web/fundamentals/web-components/best-practices#lazy-properties
1465 if (cmpMeta.$members$) {
1466 Object.entries(cmpMeta.$members$).map(([memberName, [memberFlags]]) => {
1467 if (memberFlags & 31 /* Prop */ && elm.hasOwnProperty(memberName)) {
1468 const value = elm[memberName];
1469 delete elm[memberName];
1470 elm[memberName] = value;
1471 }
1472 });
1473 }
1474 {
1475 initializeComponent(elm, hostRef, cmpMeta);
1476 }
1477 }
1478 else {
1479 // not the first time this has connected
1480 // reattach any event listeners to the host
1481 // since they would have been removed when disconnected
1482 addHostEventListeners(elm, hostRef, cmpMeta.$listeners$);
1483 // fire off connectedCallback() on component instance
1484 fireConnectedCallback(hostRef.$lazyInstance$);
1485 }
1486 endConnected();
1487 }
1488};
1489const setContentReference = (elm) => {
1490 // only required when we're NOT using native shadow dom (slot)
1491 // or this browser doesn't support native shadow dom
1492 // and this host element was NOT created with SSR
1493 // let's pick out the inner content for slot projection
1494 // create a node to represent where the original
1495 // content was first placed, which is useful later on
1496 const contentRefElm = (elm['s-cr'] = doc.createComment(''));
1497 contentRefElm['s-cn'] = true;
1498 elm.insertBefore(contentRefElm, elm.firstChild);
1499};
1500const disconnectedCallback = (elm) => {
1501 if ((plt.$flags$ & 1 /* isTmpDisconnected */) === 0) {
1502 const hostRef = getHostRef(elm);
1503 const instance = hostRef.$lazyInstance$ ;
1504 {
1505 if (hostRef.$rmListeners$) {
1506 hostRef.$rmListeners$.map((rmListener) => rmListener());
1507 hostRef.$rmListeners$ = undefined;
1508 }
1509 }
1510 {
1511 safeCall(instance, 'disconnectedCallback');
1512 }
1513 }
1514};
1515const bootstrapLazy = (lazyBundles, options = {}) => {
1516 const endBootstrap = createTime();
1517 const cmpTags = [];
1518 const exclude = options.exclude || [];
1519 const customElements = win.customElements;
1520 const head = doc.head;
1521 const metaCharset = /*@__PURE__*/ head.querySelector('meta[charset]');
1522 const visibilityStyle = /*@__PURE__*/ doc.createElement('style');
1523 const deferredConnectedCallbacks = [];
1524 let appLoadFallback;
1525 let isBootstrapping = true;
1526 Object.assign(plt, options);
1527 plt.$resourcesUrl$ = new URL(options.resourcesUrl || './', doc.baseURI).href;
1528 lazyBundles.map((lazyBundle) => {
1529 lazyBundle[1].map((compactMeta) => {
1530 const cmpMeta = {
1531 $flags$: compactMeta[0],
1532 $tagName$: compactMeta[1],
1533 $members$: compactMeta[2],
1534 $listeners$: compactMeta[3],
1535 };
1536 {
1537 cmpMeta.$members$ = compactMeta[2];
1538 }
1539 {
1540 cmpMeta.$listeners$ = compactMeta[3];
1541 }
1542 {
1543 cmpMeta.$watchers$ = {};
1544 }
1545 const tagName = cmpMeta.$tagName$;
1546 const HostElement = class extends HTMLElement {
1547 // StencilLazyHost
1548 constructor(self) {
1549 // @ts-ignore
1550 super(self);
1551 self = this;
1552 registerHost(self, cmpMeta);
1553 }
1554 connectedCallback() {
1555 if (appLoadFallback) {
1556 clearTimeout(appLoadFallback);
1557 appLoadFallback = null;
1558 }
1559 if (isBootstrapping) {
1560 // connectedCallback will be processed once all components have been registered
1561 deferredConnectedCallbacks.push(this);
1562 }
1563 else {
1564 plt.jmp(() => connectedCallback(this));
1565 }
1566 }
1567 disconnectedCallback() {
1568 plt.jmp(() => disconnectedCallback(this));
1569 }
1570 componentOnReady() {
1571 return getHostRef(this).$onReadyPromise$;
1572 }
1573 };
1574 cmpMeta.$lazyBundleId$ = lazyBundle[0];
1575 if (!exclude.includes(tagName) && !customElements.get(tagName)) {
1576 cmpTags.push(tagName);
1577 customElements.define(tagName, proxyComponent(HostElement, cmpMeta, 1 /* isElementConstructor */));
1578 }
1579 });
1580 });
1581 {
1582 visibilityStyle.innerHTML = cmpTags + HYDRATED_CSS;
1583 visibilityStyle.setAttribute('data-styles', '');
1584 head.insertBefore(visibilityStyle, metaCharset ? metaCharset.nextSibling : head.firstChild);
1585 }
1586 // Process deferred connectedCallbacks now all components have been registered
1587 isBootstrapping = false;
1588 if (deferredConnectedCallbacks.length) {
1589 deferredConnectedCallbacks.map((host) => host.connectedCallback());
1590 }
1591 else {
1592 {
1593 plt.jmp(() => (appLoadFallback = setTimeout(appDidLoad, 30)));
1594 }
1595 }
1596 // Fallback appLoad event
1597 endBootstrap();
1598};
1599const hostRefs = new WeakMap();
1600const getHostRef = (ref) => hostRefs.get(ref);
1601const registerInstance = (lazyInstance, hostRef) => hostRefs.set((hostRef.$lazyInstance$ = lazyInstance), hostRef);
1602const registerHost = (elm, cmpMeta) => {
1603 const hostRef = {
1604 $flags$: 0,
1605 $hostElement$: elm,
1606 $cmpMeta$: cmpMeta,
1607 $instanceValues$: new Map(),
1608 };
1609 {
1610 hostRef.$onInstancePromise$ = new Promise((r) => (hostRef.$onInstanceResolve$ = r));
1611 }
1612 {
1613 hostRef.$onReadyPromise$ = new Promise((r) => (hostRef.$onReadyResolve$ = r));
1614 elm['s-p'] = [];
1615 elm['s-rc'] = [];
1616 }
1617 addHostEventListeners(elm, hostRef, cmpMeta.$listeners$);
1618 return hostRefs.set(elm, hostRef);
1619};
1620const isMemberInElement = (elm, memberName) => memberName in elm;
1621const consoleError = (e, el) => (0, console.error)(e, el);
1622const cmpModules = /*@__PURE__*/ new Map();
1623const loadModule = (cmpMeta, hostRef, hmrVersionId) => {
1624 // loadModuleImport
1625 const exportName = cmpMeta.$tagName$.replace(/-/g, '_');
1626 const bundleId = cmpMeta.$lazyBundleId$;
1627 const module = cmpModules.get(bundleId) ;
1628 if (module) {
1629 return module[exportName];
1630 }
1631 return import(
1632 /* webpackInclude: /\.entry\.js$/ */
1633 /* webpackExclude: /\.system\.entry\.js$/ */
1634 /* webpackMode: "lazy" */
1635 `./${bundleId}.entry.js${''}`).then((importedModule) => {
1636 {
1637 cmpModules.set(bundleId, importedModule);
1638 }
1639 return importedModule[exportName];
1640 }, consoleError);
1641};
1642const styles = new Map();
1643const queueDomReads = [];
1644const queueDomWrites = [];
1645const queueTask = (queue, write) => (cb) => {
1646 queue.push(cb);
1647 if (!queuePending) {
1648 queuePending = true;
1649 if (write && plt.$flags$ & 4 /* queueSync */) {
1650 nextTick(flush);
1651 }
1652 else {
1653 plt.raf(flush);
1654 }
1655 }
1656};
1657const consume = (queue) => {
1658 for (let i = 0; i < queue.length; i++) {
1659 try {
1660 queue[i](performance.now());
1661 }
1662 catch (e) {
1663 consoleError(e);
1664 }
1665 }
1666 queue.length = 0;
1667};
1668const flush = () => {
1669 // always force a bunch of medium callbacks to run, but still have
1670 // a throttle on how many can run in a certain time
1671 // DOM READS!!!
1672 consume(queueDomReads);
1673 // DOM WRITES!!!
1674 {
1675 consume(queueDomWrites);
1676 if ((queuePending = queueDomReads.length > 0)) {
1677 // still more to do yet, but we've run out of time
1678 // let's let this thing cool off and try again in the next tick
1679 plt.raf(flush);
1680 }
1681 }
1682};
1683const nextTick = /*@__PURE__*/ (cb) => promiseResolve().then(cb);
1684const writeTask = /*@__PURE__*/ queueTask(queueDomWrites, true);
1685
1686export { Host as H, bootstrapLazy as b, createEvent as c, getElement as g, h, promiseResolve as p, registerInstance as r };