` tag we check the equality
* of the VNodes corresponding to the `
` tags and, since they are the
* same tag in the same position, we'd be able to avoid completely
* re-rendering the subtree under them with a new DOM element and would just
* call out to `patch` to handle reconciling their children and so on.
*
* 3. Check, for both windows, to see if the element at the beginning of the
* window corresponds to the element at the end of the other window. This is
* a heuristic which will let us identify _some_ situations in which
* elements have changed position, for instance it _should_ detect that the
* children nodes themselves have not changed but merely moved in the
* following example:
*
* oldVNode: `
`
* newVNode: `
`
*
* If we find cases like this then we also need to move the concrete DOM
* elements corresponding to the moved children to write the re-order to the
* DOM.
*
* 4. Finally, if VNodes have the `key` attribute set on them we check for any
* nodes in the old children which have the same key as the first element in
* our window on the new children. If we find such a node we handle calling
* out to `patch`, moving relevant DOM nodes, and so on, in accordance with
* what we find.
*
* Finally, once we've narrowed our 'windows' to the point that either of them
* collapse (i.e. they have length 0) we then handle any remaining VNode
* insertion or deletion that needs to happen to get a DOM state that correctly
* reflects the new child VNodes. If, for instance, after our window on the old
* children has collapsed we still have more nodes on the new children that
* we haven't dealt with yet then we need to add them, or if the new children
* collapse but we still have unhandled _old_ children then we need to make
* sure the corresponding DOM nodes are removed.
*
* @param parentElm the node into which the parent VNode is rendered
* @param oldCh the old children of the parent node
* @param newVNode the new VNode which will replace the parent
* @param newCh the new children of the parent node
*/
const updateChildren = (parentElm, oldCh, newVNode, newCh) => {
let oldStartIdx = 0;
let newStartIdx = 0;
let idxInOld = 0;
let i = 0;
let oldEndIdx = oldCh.length - 1;
let oldStartVnode = oldCh[0];
let oldEndVnode = oldCh[oldEndIdx];
let newEndIdx = newCh.length - 1;
let newStartVnode = newCh[0];
let newEndVnode = newCh[newEndIdx];
let node;
let elmToMove;
while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
if (oldStartVnode == null) {
// VNode might have been moved left
oldStartVnode = oldCh[++oldStartIdx];
}
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)) {
// if the start nodes are the same then we should patch the new VNode
// onto the old one, and increment our `newStartIdx` and `oldStartIdx`
// indices to reflect that. We don't need to move any DOM Nodes around
// since things are matched up in order.
patch(oldStartVnode, newStartVnode);
oldStartVnode = oldCh[++oldStartIdx];
newStartVnode = newCh[++newStartIdx];
}
else if (isSameVnode(oldEndVnode, newEndVnode)) {
// likewise, if the end nodes are the same we patch new onto old and
// decrement our end indices, and also likewise in this case we don't
// need to move any DOM Nodes.
patch(oldEndVnode, newEndVnode);
oldEndVnode = oldCh[--oldEndIdx];
newEndVnode = newCh[--newEndIdx];
}
else if (isSameVnode(oldStartVnode, newEndVnode)) {
patch(oldStartVnode, newEndVnode);
// We need to move the element for `oldStartVnode` into a position which
// will be appropriate for `newEndVnode`. For this we can use
// `.insertBefore` and `oldEndVnode.$elm$.nextSibling`. If there is a
// sibling for `oldEndVnode.$elm$` then we want to move the DOM node for
// `oldStartVnode` between `oldEndVnode` and it's sibling, like so:
//
//
//
//
//
//
//
// ```
// In this case if we do not unshadow here and use the value of the shadowing property, attributeChangedCallback
// will be called with `newValue = "some-value"` and will set the shadowed property (this.someAttribute = "another-value")
// to the value that was set inline i.e. "some-value" from above example. When
// the connectedCallback attempts to unshadow it will use "some-value" as the initial value rather than "another-value"
//
// The case where the attribute was NOT set inline but was not set programmatically shall be handled/unshadowed
// by connectedCallback as this attributeChangedCallback will not fire.
//
// https://developers.google.com/web/fundamentals/web-components/best-practices#lazy-properties
//
// TODO(STENCIL-16) we should think about whether or not we actually want to be reflecting the attributes to
// properties here given that this goes against best practices outlined here
// https://developers.google.com/web/fundamentals/web-components/best-practices#avoid-reentrancy
if (this.hasOwnProperty(propName)) {
newValue = this[propName];
delete this[propName];
}
else if (prototype.hasOwnProperty(propName) &&
typeof this[propName] === 'number' &&
this[propName] == newValue) {
// if the propName exists on the prototype of `Cstr`, this update may be a result of Stencil using native
// APIs to reflect props as attributes. Calls to `setAttribute(someElement, propName)` will result in
// `propName` to be converted to a `DOMString`, which may not be what we want for other primitive props.
return;
}
this[propName] = newValue === null && typeof this[propName] === 'boolean' ? false : newValue;
});
};
// create an array of attributes to observe
// and also create a map of html attribute name to js property name
Cstr.observedAttributes = members
.filter(([_, m]) => m[0] & 15 /* MEMBER_FLAGS.HasAttribute */) // filter to only keep props that should match attributes
.map(([propName, m]) => {
const attrName = m[1] || propName;
attrNameToPropName.set(attrName, propName);
if (m[0] & 512 /* MEMBER_FLAGS.ReflectAttr */) {
cmpMeta.$attrsToReflect$.push([propName, attrName]);
}
return attrName;
});
}
}
return Cstr;
};
const initializeComponent = async (elm, hostRef, cmpMeta, hmrVersionId, Cstr) => {
// initializeComponent
if ((hostRef.$flags$ & 32 /* HOST_FLAGS.hasInitializedComponent */) === 0) {
{
// we haven't initialized this element yet
hostRef.$flags$ |= 32 /* HOST_FLAGS.hasInitializedComponent */;
// lazy loaded components
// request the component's implementation to be
// wired up with the host element
Cstr = loadModule(cmpMeta);
if (Cstr.then) {
// Await creates a micro-task avoid if possible
const endLoad = uniqueTime();
Cstr = await Cstr;
endLoad();
}
if (!Cstr.isProxied) {
// we've never proxied this Constructor before
// let's add the getters/setters to its prototype before
// the first time we create an instance of the implementation
{
cmpMeta.$watchers$ = Cstr.watchers;
}
proxyComponent(Cstr, cmpMeta, 2 /* PROXY_FLAGS.proxyState */);
Cstr.isProxied = true;
}
const endNewInstance = createTime('createInstance', cmpMeta.$tagName$);
// ok, time to construct the instance
// but let's keep track of when we start and stop
// so that the getters/setters don't incorrectly step on data
{
hostRef.$flags$ |= 8 /* HOST_FLAGS.isConstructingInstance */;
}
// construct the lazy-loaded component implementation
// passing the hostRef is very important during
// construction in order to directly wire together the
// host element and the lazy-loaded instance
try {
new Cstr(hostRef);
}
catch (e) {
consoleError(e);
}
{
hostRef.$flags$ &= ~8 /* HOST_FLAGS.isConstructingInstance */;
}
{
hostRef.$flags$ |= 128 /* HOST_FLAGS.isWatchReady */;
}
endNewInstance();
fireConnectedCallback(hostRef.$lazyInstance$);
}
if (Cstr.style) {
// this component has styles but we haven't registered them yet
let style = Cstr.style;
const scopeId = getScopeId(cmpMeta);
if (!styles.has(scopeId)) {
const endRegisterStyles = createTime('registerStyles', cmpMeta.$tagName$);
registerStyle(scopeId, style, !!(cmpMeta.$flags$ & 1 /* CMP_FLAGS.shadowDomEncapsulation */));
endRegisterStyles();
}
}
}
// we've successfully created a lazy instance
const ancestorComponent = hostRef.$ancestorComponent$;
const schedule = () => scheduleUpdate(hostRef, true);
if (ancestorComponent && ancestorComponent['s-rc']) {
// this is the initial load and this component it has an ancestor component
// but the ancestor component has NOT fired its will update lifecycle yet
// so let's just cool our jets and wait for the ancestor to continue first
// this will get fired off when the ancestor component
// finally gets around to rendering its lazy self
// fire off the initial update
ancestorComponent['s-rc'].push(schedule);
}
else {
schedule();
}
};
const fireConnectedCallback = (instance) => {
{
safeCall(instance, 'connectedCallback');
}
};
const connectedCallback = (elm) => {
if ((plt.$flags$ & 1 /* PLATFORM_FLAGS.isTmpDisconnected */) === 0) {
const hostRef = getHostRef(elm);
const cmpMeta = hostRef.$cmpMeta$;
const endConnected = createTime('connectedCallback', cmpMeta.$tagName$);
if (!(hostRef.$flags$ & 1 /* HOST_FLAGS.hasConnected */)) {
// first time this component has connected
hostRef.$flags$ |= 1 /* HOST_FLAGS.hasConnected */;
let hostId;
{
hostId = elm.getAttribute(HYDRATE_ID);
if (hostId) {
if (cmpMeta.$flags$ & 1 /* CMP_FLAGS.shadowDomEncapsulation */) {
const scopeId = addStyle(elm.shadowRoot, cmpMeta);
elm.classList.remove(scopeId + '-h', scopeId + '-s');
}
initializeClientHydrate(elm, cmpMeta.$tagName$, hostId, hostRef);
}
}
{
// find the first ancestor component (if there is one) and register
// this component as one of the actively loading child components for its ancestor
let ancestorComponent = elm;
while ((ancestorComponent = ancestorComponent.parentNode || ancestorComponent.host)) {
// climb up the ancestors looking for the first
// component that hasn't finished its lifecycle update yet
if ((ancestorComponent.nodeType === 1 /* NODE_TYPE.ElementNode */ &&
ancestorComponent.hasAttribute('s-id') &&
ancestorComponent['s-p']) ||
ancestorComponent['s-p']) {
// we found this components first ancestor component
// keep a reference to this component's ancestor component
attachToAncestor(hostRef, (hostRef.$ancestorComponent$ = ancestorComponent));
break;
}
}
}
// Lazy properties
// https://developers.google.com/web/fundamentals/web-components/best-practices#lazy-properties
if (cmpMeta.$members$) {
Object.entries(cmpMeta.$members$).map(([memberName, [memberFlags]]) => {
if (memberFlags & 31 /* MEMBER_FLAGS.Prop */ && elm.hasOwnProperty(memberName)) {
const value = elm[memberName];
delete elm[memberName];
elm[memberName] = value;
}
});
}
{
initializeComponent(elm, hostRef, cmpMeta);
}
}
else {
// not the first time this has connected
// reattach any event listeners to the host
// since they would have been removed when disconnected
addHostEventListeners(elm, hostRef, cmpMeta.$listeners$);
// fire off connectedCallback() on component instance
fireConnectedCallback(hostRef.$lazyInstance$);
}
endConnected();
}
};
const disconnectedCallback = (elm) => {
if ((plt.$flags$ & 1 /* PLATFORM_FLAGS.isTmpDisconnected */) === 0) {
const hostRef = getHostRef(elm);
const instance = hostRef.$lazyInstance$ ;
{
if (hostRef.$rmListeners$) {
hostRef.$rmListeners$.map((rmListener) => rmListener());
hostRef.$rmListeners$ = undefined;
}
}
{
safeCall(instance, 'disconnectedCallback');
}
}
};
const bootstrapLazy = (lazyBundles, options = {}) => {
const endBootstrap = createTime();
const cmpTags = [];
const exclude = options.exclude || [];
const customElements = win.customElements;
const head = doc.head;
const metaCharset = /*@__PURE__*/ head.querySelector('meta[charset]');
const visibilityStyle = /*@__PURE__*/ doc.createElement('style');
const deferredConnectedCallbacks = [];
const styles = /*@__PURE__*/ doc.querySelectorAll(`[${HYDRATED_STYLE_ID}]`);
let appLoadFallback;
let isBootstrapping = true;
let i = 0;
Object.assign(plt, options);
plt.$resourcesUrl$ = new URL(options.resourcesUrl || './', doc.baseURI).href;
{
// If the app is already hydrated there is not point to disable the
// async queue. This will improve the first input delay
plt.$flags$ |= 2 /* PLATFORM_FLAGS.appLoaded */;
}
{
for (; i < styles.length; i++) {
registerStyle(styles[i].getAttribute(HYDRATED_STYLE_ID), convertScopedToShadow(styles[i].innerHTML), true);
}
}
lazyBundles.map((lazyBundle) => {
lazyBundle[1].map((compactMeta) => {
const cmpMeta = {
$flags$: compactMeta[0],
$tagName$: compactMeta[1],
$members$: compactMeta[2],
$listeners$: compactMeta[3],
};
{
cmpMeta.$members$ = compactMeta[2];
}
{
cmpMeta.$listeners$ = compactMeta[3];
}
{
cmpMeta.$attrsToReflect$ = [];
}
{
cmpMeta.$watchers$ = {};
}
const tagName = cmpMeta.$tagName$;
const HostElement = class extends HTMLElement {
// StencilLazyHost
constructor(self) {
// @ts-ignore
super(self);
self = this;
registerHost(self, cmpMeta);
if (cmpMeta.$flags$ & 1 /* CMP_FLAGS.shadowDomEncapsulation */) {
// this component is using shadow dom
// and this browser supports shadow dom
// add the read-only property "shadowRoot" to the host element
// adding the shadow root build conditionals to minimize runtime
{
{
self.attachShadow({ mode: 'open' });
}
}
}
}
connectedCallback() {
if (appLoadFallback) {
clearTimeout(appLoadFallback);
appLoadFallback = null;
}
if (isBootstrapping) {
// connectedCallback will be processed once all components have been registered
deferredConnectedCallbacks.push(this);
}
else {
plt.jmp(() => connectedCallback(this));
}
}
disconnectedCallback() {
plt.jmp(() => disconnectedCallback(this));
}
componentOnReady() {
return getHostRef(this).$onReadyPromise$;
}
};
cmpMeta.$lazyBundleId$ = lazyBundle[0];
if (!exclude.includes(tagName) && !customElements.get(tagName)) {
cmpTags.push(tagName);
customElements.define(tagName, proxyComponent(HostElement, cmpMeta, 1 /* PROXY_FLAGS.isElementConstructor */));
}
});
});
{
visibilityStyle.innerHTML = cmpTags + HYDRATED_CSS;
visibilityStyle.setAttribute('data-styles', '');
head.insertBefore(visibilityStyle, metaCharset ? metaCharset.nextSibling : head.firstChild);
}
// Process deferred connectedCallbacks now all components have been registered
isBootstrapping = false;
if (deferredConnectedCallbacks.length) {
deferredConnectedCallbacks.map((host) => host.connectedCallback());
}
else {
{
plt.jmp(() => (appLoadFallback = setTimeout(appDidLoad, 30)));
}
}
// Fallback appLoad event
endBootstrap();
};
const Fragment = (_, children) => children;
const addHostEventListeners = (elm, hostRef, listeners, attachParentListeners) => {
if (listeners) {
listeners.map(([flags, name, method]) => {
const target = getHostListenerTarget(elm, flags) ;
const handler = hostListenerProxy(hostRef, method);
const opts = hostListenerOpts(flags);
plt.ael(target, name, handler, opts);
(hostRef.$rmListeners$ = hostRef.$rmListeners$ || []).push(() => plt.rel(target, name, handler, opts));
});
}
};
const hostListenerProxy = (hostRef, methodName) => (ev) => {
try {
{
if (hostRef.$flags$ & 256 /* HOST_FLAGS.isListenReady */) {
// instance is ready, let's call it's member method for this event
hostRef.$lazyInstance$[methodName](ev);
}
else {
(hostRef.$queuedListeners$ = hostRef.$queuedListeners$ || []).push([methodName, ev]);
}
}
}
catch (e) {
consoleError(e);
}
};
const getHostListenerTarget = (elm, flags) => {
if (flags & 4 /* LISTENER_FLAGS.TargetDocument */)
return doc;
if (flags & 8 /* LISTENER_FLAGS.TargetWindow */)
return win;
if (flags & 16 /* LISTENER_FLAGS.TargetBody */)
return doc.body;
return elm;
};
// prettier-ignore
const hostListenerOpts = (flags) => (flags & 2 /* LISTENER_FLAGS.Capture */) !== 0;
const hostRefs = /*@__PURE__*/ new WeakMap();
const getHostRef = (ref) => hostRefs.get(ref);
const registerInstance = (lazyInstance, hostRef) => hostRefs.set((hostRef.$lazyInstance$ = lazyInstance), hostRef);
const registerHost = (elm, cmpMeta) => {
const hostRef = {
$flags$: 0,
$hostElement$: elm,
$cmpMeta$: cmpMeta,
$instanceValues$: new Map(),
};
{
hostRef.$onInstancePromise$ = new Promise((r) => (hostRef.$onInstanceResolve$ = r));
}
{
hostRef.$onReadyPromise$ = new Promise((r) => (hostRef.$onReadyResolve$ = r));
elm['s-p'] = [];
elm['s-rc'] = [];
}
addHostEventListeners(elm, hostRef, cmpMeta.$listeners$);
return hostRefs.set(elm, hostRef);
};
const isMemberInElement = (elm, memberName) => memberName in elm;
const consoleError = (e, el) => (0, console.error)(e, el);
const cmpModules = /*@__PURE__*/ new Map();
const loadModule = (cmpMeta, hostRef, hmrVersionId) => {
// loadModuleImport
const exportName = cmpMeta.$tagName$.replace(/-/g, '_');
const bundleId = cmpMeta.$lazyBundleId$;
const module = cmpModules.get(bundleId) ;
if (module) {
return module[exportName];
}
/*!__STENCIL_STATIC_IMPORT_SWITCH__*/
return import(
/* @vite-ignore */
/* webpackInclude: /\.entry\.js$/ */
/* webpackExclude: /\.system\.entry\.js$/ */
/* webpackMode: "lazy" */
`./${bundleId}.entry.js${''}`).then((importedModule) => {
{
cmpModules.set(bundleId, importedModule);
}
return importedModule[exportName];
}, consoleError);
};
const styles = /*@__PURE__*/ new Map();
const win = typeof window !== 'undefined' ? window : {};
const doc = win.document || { head: {} };
const plt = {
$flags$: 0,
$resourcesUrl$: '',
jmp: (h) => h(),
raf: (h) => requestAnimationFrame(h),
ael: (el, eventName, listener, opts) => el.addEventListener(eventName, listener, opts),
rel: (el, eventName, listener, opts) => el.removeEventListener(eventName, listener, opts),
ce: (eventName, opts) => new CustomEvent(eventName, opts),
};
const supportsShadow = true;
const promiseResolve = (v) => Promise.resolve(v);
const supportsConstructableStylesheets = /*@__PURE__*/ (() => {
try {
new CSSStyleSheet();
return typeof new CSSStyleSheet().replaceSync === 'function';
}
catch (e) { }
return false;
})()
;
const queueDomReads = [];
const queueDomWrites = [];
const queueTask = (queue, write) => (cb) => {
queue.push(cb);
if (!queuePending) {
queuePending = true;
if (write && plt.$flags$ & 4 /* PLATFORM_FLAGS.queueSync */) {
nextTick(flush);
}
else {
plt.raf(flush);
}
}
};
const consume = (queue) => {
for (let i = 0; i < queue.length; i++) {
try {
queue[i](performance.now());
}
catch (e) {
consoleError(e);
}
}
queue.length = 0;
};
const flush = () => {
// always force a bunch of medium callbacks to run, but still have
// a throttle on how many can run in a certain time
// DOM READS!!!
consume(queueDomReads);
// DOM WRITES!!!
{
consume(queueDomWrites);
if ((queuePending = queueDomReads.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 tick
plt.raf(flush);
}
}
};
const nextTick = /*@__PURE__*/ (cb) => promiseResolve().then(cb);
const writeTask = /*@__PURE__*/ queueTask(queueDomWrites, true);
export { Fragment as F, Host as H, NAMESPACE as N, getAssetPath as a, bootstrapLazy as b, createEvent as c, doc as d, forceUpdate as f, getElement as g, h, promiseResolve as p, registerInstance as r };