@maggioli-design-system/mds-modal 3.0.0 → 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/{index-6f89e656.js → index-d859a858.js} +401 -234
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/cjs/mds-modal.cjs.entry.js +36 -48
- package/dist/cjs/mds-modal.cjs.js +2 -2
- package/dist/collection/collection-manifest.json +2 -2
- package/dist/collection/common/aria.js +19 -0
- package/dist/collection/components/mds-modal/mds-modal.css +38 -68
- package/dist/collection/components/mds-modal/mds-modal.js +131 -95
- package/dist/collection/components/mds-modal/test/mds-modal.stories.js +10 -19
- package/dist/collection/dictionary/typography.js +3 -3
- package/dist/components/mds-modal.js +35 -47
- package/dist/esm/{index-7c9adc93.js → index-a5a41aa8.js} +401 -234
- package/dist/esm/loader.js +2 -2
- package/dist/esm/mds-modal.entry.js +36 -48
- package/dist/esm/mds-modal.js +2 -2
- package/dist/esm/polyfills/css-shim.js +1 -1
- package/dist/esm-es5/index-a5a41aa8.js +2 -0
- package/dist/esm-es5/loader.js +1 -1
- package/dist/esm-es5/mds-modal.entry.js +1 -1
- package/dist/esm-es5/mds-modal.js +1 -1
- package/dist/mds-modal/mds-modal.esm.js +1 -1
- package/dist/mds-modal/mds-modal.js +2 -1
- package/dist/mds-modal/p-4fe02e5f.entry.js +1 -0
- package/dist/mds-modal/p-52cd3b82.system.entry.js +1 -0
- package/dist/mds-modal/p-76a04b9e.system.js +2 -0
- package/dist/mds-modal/p-931319fa.js +2 -0
- package/dist/mds-modal/{p-bd6bb90a.system.js → p-a2cf985e.system.js} +1 -1
- package/dist/stats.json +39 -35
- package/dist/types/common/aria.d.ts +4 -0
- package/dist/types/components/mds-modal/test/mds-modal.stories.d.ts +1 -0
- package/dist/types/stencil-public-runtime.d.ts +20 -4
- package/dist/types/types/typography.d.ts +3 -3
- package/loader/package.json +1 -0
- package/package.json +4 -4
- package/src/common/aria.ts +27 -0
- package/src/components/mds-modal/.gitlab-ci.yml +2 -2
- package/src/components/mds-modal/mds-modal.css +1 -1
- package/src/components/mds-modal/mds-modal.tsx +39 -4
- package/src/components/mds-modal/test/mds-modal.e2e.ts +2 -2
- package/src/components/mds-modal/test/mds-modal.stories.tsx +20 -0
- package/src/dictionary/typography.ts +3 -3
- package/src/fixtures/icons.json +2 -2
- package/src/types/typography.ts +3 -3
- package/www/build/mds-modal.esm.js +1 -1
- package/www/build/mds-modal.js +2 -1
- package/www/build/p-4fe02e5f.entry.js +1 -0
- package/www/build/p-52cd3b82.system.entry.js +1 -0
- package/www/build/p-76a04b9e.system.js +2 -0
- package/www/build/p-931319fa.js +2 -0
- package/www/build/{p-bd6bb90a.system.js → p-a2cf985e.system.js} +1 -1
- package/dist/esm-es5/index-7c9adc93.js +0 -2
- package/dist/mds-modal/p-4e7d20d9.system.entry.js +0 -1
- package/dist/mds-modal/p-656f0e04.system.js +0 -2
- package/dist/mds-modal/p-b8cb7be9.js +0 -2
- package/dist/mds-modal/p-f8c5b0c2.entry.js +0 -1
- package/www/build/p-4e7d20d9.system.entry.js +0 -1
- package/www/build/p-656f0e04.system.js +0 -2
- package/www/build/p-b8cb7be9.js +0 -2
- package/www/build/p-f8c5b0c2.entry.js +0 -1
|
@@ -22,66 +22,18 @@ function _interopNamespace(e) {
|
|
|
22
22
|
|
|
23
23
|
const NAMESPACE = 'mds-modal';
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Virtual DOM patching algorithm based on Snabbdom by
|
|
27
|
+
* Simon Friis Vindum (@paldepind)
|
|
28
|
+
* Licensed under the MIT License
|
|
29
|
+
* https://github.com/snabbdom/snabbdom/blob/master/LICENSE
|
|
30
|
+
*
|
|
31
|
+
* Modified for Stencil's renderer and slot projection
|
|
32
|
+
*/
|
|
25
33
|
let scopeId;
|
|
26
34
|
let hostTagName;
|
|
27
35
|
let isSvgMode = false;
|
|
28
36
|
let queuePending = false;
|
|
29
|
-
const win = typeof window !== 'undefined' ? window : {};
|
|
30
|
-
const doc = win.document || { head: {} };
|
|
31
|
-
const plt = {
|
|
32
|
-
$flags$: 0,
|
|
33
|
-
$resourcesUrl$: '',
|
|
34
|
-
jmp: (h) => h(),
|
|
35
|
-
raf: (h) => requestAnimationFrame(h),
|
|
36
|
-
ael: (el, eventName, listener, opts) => el.addEventListener(eventName, listener, opts),
|
|
37
|
-
rel: (el, eventName, listener, opts) => el.removeEventListener(eventName, listener, opts),
|
|
38
|
-
ce: (eventName, opts) => new CustomEvent(eventName, opts),
|
|
39
|
-
};
|
|
40
|
-
const promiseResolve = (v) => Promise.resolve(v);
|
|
41
|
-
const supportsConstructibleStylesheets = /*@__PURE__*/ (() => {
|
|
42
|
-
try {
|
|
43
|
-
new CSSStyleSheet();
|
|
44
|
-
return typeof new CSSStyleSheet().replace === 'function';
|
|
45
|
-
}
|
|
46
|
-
catch (e) { }
|
|
47
|
-
return false;
|
|
48
|
-
})()
|
|
49
|
-
;
|
|
50
|
-
const addHostEventListeners = (elm, hostRef, listeners, attachParentListeners) => {
|
|
51
|
-
if (listeners) {
|
|
52
|
-
listeners.map(([flags, name, method]) => {
|
|
53
|
-
const target = getHostListenerTarget(elm, flags) ;
|
|
54
|
-
const handler = hostListenerProxy(hostRef, method);
|
|
55
|
-
const opts = hostListenerOpts(flags);
|
|
56
|
-
plt.ael(target, name, handler, opts);
|
|
57
|
-
(hostRef.$rmListeners$ = hostRef.$rmListeners$ || []).push(() => plt.rel(target, name, handler, opts));
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
const hostListenerProxy = (hostRef, methodName) => (ev) => {
|
|
62
|
-
try {
|
|
63
|
-
{
|
|
64
|
-
if (hostRef.$flags$ & 256 /* isListenReady */) {
|
|
65
|
-
// instance is ready, let's call it's member method for this event
|
|
66
|
-
hostRef.$lazyInstance$[methodName](ev);
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
(hostRef.$queuedListeners$ = hostRef.$queuedListeners$ || []).push([methodName, ev]);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
catch (e) {
|
|
74
|
-
consoleError(e);
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
const getHostListenerTarget = (elm, flags) => {
|
|
78
|
-
if (flags & 4 /* TargetDocument */)
|
|
79
|
-
return doc;
|
|
80
|
-
return elm;
|
|
81
|
-
};
|
|
82
|
-
// prettier-ignore
|
|
83
|
-
const hostListenerOpts = (flags) => (flags & 2 /* Capture */) !== 0;
|
|
84
|
-
const HYDRATED_CSS = '{visibility:hidden}.hydrated{visibility:inherit}';
|
|
85
37
|
const createTime = (fnName, tagName = '') => {
|
|
86
38
|
{
|
|
87
39
|
return () => {
|
|
@@ -96,71 +48,7 @@ const uniqueTime = (key, measureText) => {
|
|
|
96
48
|
};
|
|
97
49
|
}
|
|
98
50
|
};
|
|
99
|
-
const
|
|
100
|
-
const registerStyle = (scopeId, cssText, allowCS) => {
|
|
101
|
-
let style = styles.get(scopeId);
|
|
102
|
-
if (supportsConstructibleStylesheets && allowCS) {
|
|
103
|
-
style = (style || new CSSStyleSheet());
|
|
104
|
-
style.replace(cssText);
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
style = cssText;
|
|
108
|
-
}
|
|
109
|
-
styles.set(scopeId, style);
|
|
110
|
-
};
|
|
111
|
-
const addStyle = (styleContainerNode, cmpMeta, mode, hostElm) => {
|
|
112
|
-
let scopeId = getScopeId(cmpMeta);
|
|
113
|
-
const style = styles.get(scopeId);
|
|
114
|
-
// if an element is NOT connected then getRootNode() will return the wrong root node
|
|
115
|
-
// so the fallback is to always use the document for the root node in those cases
|
|
116
|
-
styleContainerNode = styleContainerNode.nodeType === 11 /* DocumentFragment */ ? styleContainerNode : doc;
|
|
117
|
-
if (style) {
|
|
118
|
-
if (typeof style === 'string') {
|
|
119
|
-
styleContainerNode = styleContainerNode.head || styleContainerNode;
|
|
120
|
-
let appliedStyles = rootAppliedStyles.get(styleContainerNode);
|
|
121
|
-
let styleElm;
|
|
122
|
-
if (!appliedStyles) {
|
|
123
|
-
rootAppliedStyles.set(styleContainerNode, (appliedStyles = new Set()));
|
|
124
|
-
}
|
|
125
|
-
if (!appliedStyles.has(scopeId)) {
|
|
126
|
-
{
|
|
127
|
-
{
|
|
128
|
-
styleElm = doc.createElement('style');
|
|
129
|
-
styleElm.innerHTML = style;
|
|
130
|
-
}
|
|
131
|
-
styleContainerNode.insertBefore(styleElm, styleContainerNode.querySelector('link'));
|
|
132
|
-
}
|
|
133
|
-
if (appliedStyles) {
|
|
134
|
-
appliedStyles.add(scopeId);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
else if (!styleContainerNode.adoptedStyleSheets.includes(style)) {
|
|
139
|
-
styleContainerNode.adoptedStyleSheets = [...styleContainerNode.adoptedStyleSheets, style];
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
return scopeId;
|
|
143
|
-
};
|
|
144
|
-
const attachStyles = (hostRef) => {
|
|
145
|
-
const cmpMeta = hostRef.$cmpMeta$;
|
|
146
|
-
const elm = hostRef.$hostElement$;
|
|
147
|
-
const flags = cmpMeta.$flags$;
|
|
148
|
-
const endAttachStyles = createTime('attachStyles', cmpMeta.$tagName$);
|
|
149
|
-
const scopeId = addStyle(elm.shadowRoot ? elm.shadowRoot : elm.getRootNode(), cmpMeta);
|
|
150
|
-
if (flags & 10 /* needsScopedEncapsulation */) {
|
|
151
|
-
// only required when we're NOT using native shadow dom (slot)
|
|
152
|
-
// or this browser doesn't support native shadow dom
|
|
153
|
-
// and this host element was NOT created with SSR
|
|
154
|
-
// let's pick out the inner content for slot projection
|
|
155
|
-
// create a node to represent where the original
|
|
156
|
-
// content was first placed, which is useful later on
|
|
157
|
-
// DOM WRITE!!
|
|
158
|
-
elm['s-sc'] = scopeId;
|
|
159
|
-
elm.classList.add(scopeId + '-h');
|
|
160
|
-
}
|
|
161
|
-
endAttachStyles();
|
|
162
|
-
};
|
|
163
|
-
const getScopeId = (cmp, mode) => 'sc-' + (cmp.$tagName$);
|
|
51
|
+
const HYDRATED_CSS = '{visibility:hidden}.hydrated{visibility:inherit}';
|
|
164
52
|
/**
|
|
165
53
|
* Default style mode id
|
|
166
54
|
*/
|
|
@@ -249,6 +137,145 @@ const newVNode = (tag, text) => {
|
|
|
249
137
|
};
|
|
250
138
|
const Host = {};
|
|
251
139
|
const isHost = (node) => node && node.$tag$ === Host;
|
|
140
|
+
/**
|
|
141
|
+
* Parse a new property value for a given property type.
|
|
142
|
+
*
|
|
143
|
+
* While the prop value can reasonably be expected to be of `any` type as far as TypeScript's type checker is concerned,
|
|
144
|
+
* it is not safe to assume that the string returned by evaluating `typeof propValue` matches:
|
|
145
|
+
* 1. `any`, the type given to `propValue` in the function signature
|
|
146
|
+
* 2. the type stored from `propType`.
|
|
147
|
+
*
|
|
148
|
+
* This function provides the capability to parse/coerce a property's value to potentially any other JavaScript type.
|
|
149
|
+
*
|
|
150
|
+
* Property values represented in TSX preserve their type information. In the example below, the number 0 is passed to
|
|
151
|
+
* a component. This `propValue` will preserve its type information (`typeof propValue === 'number'`). Note that is
|
|
152
|
+
* based on the type of the value being passed in, not the type declared of the class member decorated with `@Prop`.
|
|
153
|
+
* ```tsx
|
|
154
|
+
* <my-cmp prop-val={0}></my-cmp>
|
|
155
|
+
* ```
|
|
156
|
+
*
|
|
157
|
+
* HTML prop values on the other hand, will always a string
|
|
158
|
+
*
|
|
159
|
+
* @param propValue the new value to coerce to some type
|
|
160
|
+
* @param propType the type of the prop, expressed as a binary number
|
|
161
|
+
* @returns the parsed/coerced value
|
|
162
|
+
*/
|
|
163
|
+
const parsePropertyValue = (propValue, propType) => {
|
|
164
|
+
// ensure this value is of the correct prop type
|
|
165
|
+
if (propValue != null && !isComplexType(propValue)) {
|
|
166
|
+
if (propType & 4 /* MEMBER_FLAGS.Boolean */) {
|
|
167
|
+
// per the HTML spec, any string value means it is a boolean true value
|
|
168
|
+
// but we'll cheat here and say that the string "false" is the boolean false
|
|
169
|
+
return propValue === 'false' ? false : propValue === '' || !!propValue;
|
|
170
|
+
}
|
|
171
|
+
if (propType & 1 /* MEMBER_FLAGS.String */) {
|
|
172
|
+
// could have been passed as a number or boolean
|
|
173
|
+
// but we still want it as a string
|
|
174
|
+
return String(propValue);
|
|
175
|
+
}
|
|
176
|
+
// redundant return here for better minification
|
|
177
|
+
return propValue;
|
|
178
|
+
}
|
|
179
|
+
// not sure exactly what type we want
|
|
180
|
+
// so no need to change to a different type
|
|
181
|
+
return propValue;
|
|
182
|
+
};
|
|
183
|
+
const getElement = (ref) => (getHostRef(ref).$hostElement$ );
|
|
184
|
+
const createEvent = (ref, name, flags) => {
|
|
185
|
+
const elm = getElement(ref);
|
|
186
|
+
return {
|
|
187
|
+
emit: (detail) => {
|
|
188
|
+
return emitEvent(elm, name, {
|
|
189
|
+
bubbles: !!(flags & 4 /* EVENT_FLAGS.Bubbles */),
|
|
190
|
+
composed: !!(flags & 2 /* EVENT_FLAGS.Composed */),
|
|
191
|
+
cancelable: !!(flags & 1 /* EVENT_FLAGS.Cancellable */),
|
|
192
|
+
detail,
|
|
193
|
+
});
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
};
|
|
197
|
+
/**
|
|
198
|
+
* Helper function to create & dispatch a custom Event on a provided target
|
|
199
|
+
* @param elm the target of the Event
|
|
200
|
+
* @param name the name to give the custom Event
|
|
201
|
+
* @param opts options for configuring a custom Event
|
|
202
|
+
* @returns the custom Event
|
|
203
|
+
*/
|
|
204
|
+
const emitEvent = (elm, name, opts) => {
|
|
205
|
+
const ev = plt.ce(name, opts);
|
|
206
|
+
elm.dispatchEvent(ev);
|
|
207
|
+
return ev;
|
|
208
|
+
};
|
|
209
|
+
const rootAppliedStyles = /*@__PURE__*/ new WeakMap();
|
|
210
|
+
const registerStyle = (scopeId, cssText, allowCS) => {
|
|
211
|
+
let style = styles.get(scopeId);
|
|
212
|
+
if (supportsConstructableStylesheets && allowCS) {
|
|
213
|
+
style = (style || new CSSStyleSheet());
|
|
214
|
+
if (typeof style === 'string') {
|
|
215
|
+
style = cssText;
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
style.replaceSync(cssText);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
style = cssText;
|
|
223
|
+
}
|
|
224
|
+
styles.set(scopeId, style);
|
|
225
|
+
};
|
|
226
|
+
const addStyle = (styleContainerNode, cmpMeta, mode, hostElm) => {
|
|
227
|
+
let scopeId = getScopeId(cmpMeta);
|
|
228
|
+
const style = styles.get(scopeId);
|
|
229
|
+
// if an element is NOT connected then getRootNode() will return the wrong root node
|
|
230
|
+
// so the fallback is to always use the document for the root node in those cases
|
|
231
|
+
styleContainerNode = styleContainerNode.nodeType === 11 /* NODE_TYPE.DocumentFragment */ ? styleContainerNode : doc;
|
|
232
|
+
if (style) {
|
|
233
|
+
if (typeof style === 'string') {
|
|
234
|
+
styleContainerNode = styleContainerNode.head || styleContainerNode;
|
|
235
|
+
let appliedStyles = rootAppliedStyles.get(styleContainerNode);
|
|
236
|
+
let styleElm;
|
|
237
|
+
if (!appliedStyles) {
|
|
238
|
+
rootAppliedStyles.set(styleContainerNode, (appliedStyles = new Set()));
|
|
239
|
+
}
|
|
240
|
+
if (!appliedStyles.has(scopeId)) {
|
|
241
|
+
{
|
|
242
|
+
{
|
|
243
|
+
styleElm = doc.createElement('style');
|
|
244
|
+
styleElm.innerHTML = style;
|
|
245
|
+
}
|
|
246
|
+
styleContainerNode.insertBefore(styleElm, styleContainerNode.querySelector('link'));
|
|
247
|
+
}
|
|
248
|
+
if (appliedStyles) {
|
|
249
|
+
appliedStyles.add(scopeId);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
else if (!styleContainerNode.adoptedStyleSheets.includes(style)) {
|
|
254
|
+
styleContainerNode.adoptedStyleSheets = [...styleContainerNode.adoptedStyleSheets, style];
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return scopeId;
|
|
258
|
+
};
|
|
259
|
+
const attachStyles = (hostRef) => {
|
|
260
|
+
const cmpMeta = hostRef.$cmpMeta$;
|
|
261
|
+
const elm = hostRef.$hostElement$;
|
|
262
|
+
const flags = cmpMeta.$flags$;
|
|
263
|
+
const endAttachStyles = createTime('attachStyles', cmpMeta.$tagName$);
|
|
264
|
+
const scopeId = addStyle(elm.shadowRoot ? elm.shadowRoot : elm.getRootNode(), cmpMeta);
|
|
265
|
+
if (flags & 10 /* CMP_FLAGS.needsScopedEncapsulation */) {
|
|
266
|
+
// only required when we're NOT using native shadow dom (slot)
|
|
267
|
+
// or this browser doesn't support native shadow dom
|
|
268
|
+
// and this host element was NOT created with SSR
|
|
269
|
+
// let's pick out the inner content for slot projection
|
|
270
|
+
// create a node to represent where the original
|
|
271
|
+
// content was first placed, which is useful later on
|
|
272
|
+
// DOM WRITE!!
|
|
273
|
+
elm['s-sc'] = scopeId;
|
|
274
|
+
elm.classList.add(scopeId + '-h');
|
|
275
|
+
}
|
|
276
|
+
endAttachStyles();
|
|
277
|
+
};
|
|
278
|
+
const getScopeId = (cmp, mode) => 'sc-' + (cmp.$tagName$);
|
|
252
279
|
/**
|
|
253
280
|
* Production setAccessor() function based on Preact by
|
|
254
281
|
* Jason Miller (@developit)
|
|
@@ -335,7 +362,7 @@ const setAccessor = (elm, memberName, oldValue, newValue, isSvg, flags) => {
|
|
|
335
362
|
}
|
|
336
363
|
}
|
|
337
364
|
}
|
|
338
|
-
else if ((!isProp || flags & 4 /* isHost */ || isSvg) && !isComplex) {
|
|
365
|
+
else if ((!isProp || flags & 4 /* VNODE_FLAGS.isHost */ || isSvg) && !isComplex) {
|
|
339
366
|
newValue = newValue === true ? '' : newValue;
|
|
340
367
|
{
|
|
341
368
|
elm.setAttribute(memberName, newValue);
|
|
@@ -350,7 +377,7 @@ const updateElement = (oldVnode, newVnode, isSvgMode, memberName) => {
|
|
|
350
377
|
// if the element passed in is a shadow root, which is a document fragment
|
|
351
378
|
// then we want to be adding attrs/props to the shadow root's "host" element
|
|
352
379
|
// if it's not a shadow root, then we add attrs/props to the same element
|
|
353
|
-
const elm = newVnode.$elm$.nodeType === 11 /* DocumentFragment */ && newVnode.$elm$.host
|
|
380
|
+
const elm = newVnode.$elm$.nodeType === 11 /* NODE_TYPE.DocumentFragment */ && newVnode.$elm$.host
|
|
354
381
|
? newVnode.$elm$.host
|
|
355
382
|
: newVnode.$elm$;
|
|
356
383
|
const oldVnodeAttrs = (oldVnode && oldVnode.$attrs$) || EMPTY_OBJ;
|
|
@@ -368,6 +395,16 @@ const updateElement = (oldVnode, newVnode, isSvgMode, memberName) => {
|
|
|
368
395
|
setAccessor(elm, memberName, oldVnodeAttrs[memberName], newVnodeAttrs[memberName], isSvgMode, newVnode.$flags$);
|
|
369
396
|
}
|
|
370
397
|
};
|
|
398
|
+
/**
|
|
399
|
+
* Create a DOM Node corresponding to one of the children of a given VNode.
|
|
400
|
+
*
|
|
401
|
+
* @param oldParentVNode the parent VNode from the previous render
|
|
402
|
+
* @param newParentVNode the parent VNode from the current render
|
|
403
|
+
* @param childIndex the index of the VNode, in the _new_ parent node's
|
|
404
|
+
* children, for which we will create a new DOM node
|
|
405
|
+
* @param parentElm the parent DOM node which our new node will be a child of
|
|
406
|
+
* @returns the newly created node
|
|
407
|
+
*/
|
|
371
408
|
const createElm = (oldParentVNode, newParentVNode, childIndex, parentElm) => {
|
|
372
409
|
// tslint:disable-next-line: prefer-const
|
|
373
410
|
const newVNode = newParentVNode.$children$[childIndex];
|
|
@@ -429,6 +466,74 @@ const removeVnodes = (vnodes, startIdx, endIdx, vnode, elm) => {
|
|
|
429
466
|
}
|
|
430
467
|
}
|
|
431
468
|
};
|
|
469
|
+
/**
|
|
470
|
+
* Reconcile the children of a new VNode with the children of an old VNode by
|
|
471
|
+
* traversing the two collections of children, identifying nodes that are
|
|
472
|
+
* conserved or changed, calling out to `patch` to make any necessary
|
|
473
|
+
* updates to the DOM, and rearranging DOM nodes as needed.
|
|
474
|
+
*
|
|
475
|
+
* The algorithm for reconciling children works by analyzing two 'windows' onto
|
|
476
|
+
* the two arrays of children (`oldCh` and `newCh`). We keep track of the
|
|
477
|
+
* 'windows' by storing start and end indices and references to the
|
|
478
|
+
* corresponding array entries. Initially the two 'windows' are basically equal
|
|
479
|
+
* to the entire array, but we progressively narrow the windows until there are
|
|
480
|
+
* no children left to update by doing the following:
|
|
481
|
+
*
|
|
482
|
+
* 1. Skip any `null` entries at the beginning or end of the two arrays, so
|
|
483
|
+
* that if we have an initial array like the following we'll end up dealing
|
|
484
|
+
* only with a window bounded by the highlighted elements:
|
|
485
|
+
*
|
|
486
|
+
* [null, null, VNode1 , ... , VNode2, null, null]
|
|
487
|
+
* ^^^^^^ ^^^^^^
|
|
488
|
+
*
|
|
489
|
+
* 2. Check to see if the elements at the head and tail positions are equal
|
|
490
|
+
* across the windows. This will basically detect elements which haven't
|
|
491
|
+
* been added, removed, or changed position, i.e. if you had the following
|
|
492
|
+
* VNode elements (represented as HTML):
|
|
493
|
+
*
|
|
494
|
+
* oldVNode: `<div><p><span>HEY</span></p></div>`
|
|
495
|
+
* newVNode: `<div><p><span>THERE</span></p></div>`
|
|
496
|
+
*
|
|
497
|
+
* Then when comparing the children of the `<div>` tag we check the equality
|
|
498
|
+
* of the VNodes corresponding to the `<p>` tags and, since they are the
|
|
499
|
+
* same tag in the same position, we'd be able to avoid completely
|
|
500
|
+
* re-rendering the subtree under them with a new DOM element and would just
|
|
501
|
+
* call out to `patch` to handle reconciling their children and so on.
|
|
502
|
+
*
|
|
503
|
+
* 3. Check, for both windows, to see if the element at the beginning of the
|
|
504
|
+
* window corresponds to the element at the end of the other window. This is
|
|
505
|
+
* a heuristic which will let us identify _some_ situations in which
|
|
506
|
+
* elements have changed position, for instance it _should_ detect that the
|
|
507
|
+
* children nodes themselves have not changed but merely moved in the
|
|
508
|
+
* following example:
|
|
509
|
+
*
|
|
510
|
+
* oldVNode: `<div><element-one /><element-two /></div>`
|
|
511
|
+
* newVNode: `<div><element-two /><element-one /></div>`
|
|
512
|
+
*
|
|
513
|
+
* If we find cases like this then we also need to move the concrete DOM
|
|
514
|
+
* elements corresponding to the moved children to write the re-order to the
|
|
515
|
+
* DOM.
|
|
516
|
+
*
|
|
517
|
+
* 4. Finally, if VNodes have the `key` attribute set on them we check for any
|
|
518
|
+
* nodes in the old children which have the same key as the first element in
|
|
519
|
+
* our window on the new children. If we find such a node we handle calling
|
|
520
|
+
* out to `patch`, moving relevant DOM nodes, and so on, in accordance with
|
|
521
|
+
* what we find.
|
|
522
|
+
*
|
|
523
|
+
* Finally, once we've narrowed our 'windows' to the point that either of them
|
|
524
|
+
* collapse (i.e. they have length 0) we then handle any remaining VNode
|
|
525
|
+
* insertion or deletion that needs to happen to get a DOM state that correctly
|
|
526
|
+
* reflects the new child VNodes. If, for instance, after our window on the old
|
|
527
|
+
* children has collapsed we still have more nodes on the new children that
|
|
528
|
+
* we haven't dealt with yet then we need to add them, or if the new children
|
|
529
|
+
* collapse but we still have unhandled _old_ children then we need to make
|
|
530
|
+
* sure the corresponding DOM nodes are removed.
|
|
531
|
+
*
|
|
532
|
+
* @param parentElm the node into which the parent VNode is rendered
|
|
533
|
+
* @param oldCh the old children of the parent node
|
|
534
|
+
* @param newVNode the new VNode which will replace the parent
|
|
535
|
+
* @param newCh the new children of the parent node
|
|
536
|
+
*/
|
|
432
537
|
const updateChildren = (parentElm, oldCh, newVNode, newCh) => {
|
|
433
538
|
let oldStartIdx = 0;
|
|
434
539
|
let newStartIdx = 0;
|
|
@@ -441,7 +546,7 @@ const updateChildren = (parentElm, oldCh, newVNode, newCh) => {
|
|
|
441
546
|
let node;
|
|
442
547
|
while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
|
|
443
548
|
if (oldStartVnode == null) {
|
|
444
|
-
//
|
|
549
|
+
// VNode might have been moved left
|
|
445
550
|
oldStartVnode = oldCh[++oldStartIdx];
|
|
446
551
|
}
|
|
447
552
|
else if (oldEndVnode == null) {
|
|
@@ -454,34 +559,67 @@ const updateChildren = (parentElm, oldCh, newVNode, newCh) => {
|
|
|
454
559
|
newEndVnode = newCh[--newEndIdx];
|
|
455
560
|
}
|
|
456
561
|
else if (isSameVnode(oldStartVnode, newStartVnode)) {
|
|
562
|
+
// if the start nodes are the same then we should patch the new VNode
|
|
563
|
+
// onto the old one, and increment our `newStartIdx` and `oldStartIdx`
|
|
564
|
+
// indices to reflect that. We don't need to move any DOM Nodes around
|
|
565
|
+
// since things are matched up in order.
|
|
457
566
|
patch(oldStartVnode, newStartVnode);
|
|
458
567
|
oldStartVnode = oldCh[++oldStartIdx];
|
|
459
568
|
newStartVnode = newCh[++newStartIdx];
|
|
460
569
|
}
|
|
461
570
|
else if (isSameVnode(oldEndVnode, newEndVnode)) {
|
|
571
|
+
// likewise, if the end nodes are the same we patch new onto old and
|
|
572
|
+
// decrement our end indices, and also likewise in this case we don't
|
|
573
|
+
// need to move any DOM Nodes.
|
|
462
574
|
patch(oldEndVnode, newEndVnode);
|
|
463
575
|
oldEndVnode = oldCh[--oldEndIdx];
|
|
464
576
|
newEndVnode = newCh[--newEndIdx];
|
|
465
577
|
}
|
|
466
578
|
else if (isSameVnode(oldStartVnode, newEndVnode)) {
|
|
467
579
|
patch(oldStartVnode, newEndVnode);
|
|
580
|
+
// We need to move the element for `oldStartVnode` into a position which
|
|
581
|
+
// will be appropriate for `newEndVnode`. For this we can use
|
|
582
|
+
// `.insertBefore` and `oldEndVnode.$elm$.nextSibling`. If there is a
|
|
583
|
+
// sibling for `oldEndVnode.$elm$` then we want to move the DOM node for
|
|
584
|
+
// `oldStartVnode` between `oldEndVnode` and it's sibling, like so:
|
|
585
|
+
//
|
|
586
|
+
// <old-start-node />
|
|
587
|
+
// <some-intervening-node />
|
|
588
|
+
// <old-end-node />
|
|
589
|
+
// <!-- -> <-- `oldStartVnode.$elm$` should be inserted here
|
|
590
|
+
// <next-sibling />
|
|
591
|
+
//
|
|
592
|
+
// If instead `oldEndVnode.$elm$` has no sibling then we just want to put
|
|
593
|
+
// the node for `oldStartVnode` at the end of the children of
|
|
594
|
+
// `parentElm`. Luckily, `Node.nextSibling` will return `null` if there
|
|
595
|
+
// aren't any siblings, and passing `null` to `Node.insertBefore` will
|
|
596
|
+
// append it to the children of the parent element.
|
|
468
597
|
parentElm.insertBefore(oldStartVnode.$elm$, oldEndVnode.$elm$.nextSibling);
|
|
469
598
|
oldStartVnode = oldCh[++oldStartIdx];
|
|
470
599
|
newEndVnode = newCh[--newEndIdx];
|
|
471
600
|
}
|
|
472
601
|
else if (isSameVnode(oldEndVnode, newStartVnode)) {
|
|
473
602
|
patch(oldEndVnode, newStartVnode);
|
|
603
|
+
// We've already checked above if `oldStartVnode` and `newStartVnode` are
|
|
604
|
+
// the same node, so since we're here we know that they are not. Thus we
|
|
605
|
+
// can move the element for `oldEndVnode` _before_ the element for
|
|
606
|
+
// `oldStartVnode`, leaving `oldStartVnode` to be reconciled in the
|
|
607
|
+
// future.
|
|
474
608
|
parentElm.insertBefore(oldEndVnode.$elm$, oldStartVnode.$elm$);
|
|
475
609
|
oldEndVnode = oldCh[--oldEndIdx];
|
|
476
610
|
newStartVnode = newCh[++newStartIdx];
|
|
477
611
|
}
|
|
478
612
|
else {
|
|
479
613
|
{
|
|
480
|
-
//
|
|
614
|
+
// We either didn't find an element in the old children that matches
|
|
615
|
+
// the key of the first new child OR the build is not using `key`
|
|
616
|
+
// attributes at all. In either case we need to create a new element
|
|
617
|
+
// for the new node.
|
|
481
618
|
node = createElm(oldCh && oldCh[newStartIdx], newVNode, newStartIdx);
|
|
482
619
|
newStartVnode = newCh[++newStartIdx];
|
|
483
620
|
}
|
|
484
621
|
if (node) {
|
|
622
|
+
// if we created a new node then handle inserting it to the DOM
|
|
485
623
|
{
|
|
486
624
|
oldStartVnode.$elm$.parentNode.insertBefore(node, oldStartVnode.$elm$);
|
|
487
625
|
}
|
|
@@ -489,20 +627,49 @@ const updateChildren = (parentElm, oldCh, newVNode, newCh) => {
|
|
|
489
627
|
}
|
|
490
628
|
}
|
|
491
629
|
if (oldStartIdx > oldEndIdx) {
|
|
630
|
+
// we have some more new nodes to add which don't match up with old nodes
|
|
492
631
|
addVnodes(parentElm, newCh[newEndIdx + 1] == null ? null : newCh[newEndIdx + 1].$elm$, newVNode, newCh, newStartIdx, newEndIdx);
|
|
493
632
|
}
|
|
494
633
|
else if (newStartIdx > newEndIdx) {
|
|
634
|
+
// there are nodes in the `oldCh` array which no longer correspond to nodes
|
|
635
|
+
// in the new array, so lets remove them (which entails cleaning up the
|
|
636
|
+
// relevant DOM nodes)
|
|
495
637
|
removeVnodes(oldCh, oldStartIdx, oldEndIdx);
|
|
496
638
|
}
|
|
497
639
|
};
|
|
498
|
-
|
|
640
|
+
/**
|
|
641
|
+
* Compare two VNodes to determine if they are the same
|
|
642
|
+
*
|
|
643
|
+
* **NB**: This function is an equality _heuristic_ based on the available
|
|
644
|
+
* information set on the two VNodes and can be misleading under certain
|
|
645
|
+
* circumstances. In particular, if the two nodes do not have `key` attrs
|
|
646
|
+
* (available under `$key$` on VNodes) then the function falls back on merely
|
|
647
|
+
* checking that they have the same tag.
|
|
648
|
+
*
|
|
649
|
+
* So, in other words, if `key` attrs are not set on VNodes which may be
|
|
650
|
+
* changing order within a `children` array or something along those lines then
|
|
651
|
+
* we could obtain a false positive and then have to do needless re-rendering.
|
|
652
|
+
*
|
|
653
|
+
* @param leftVNode the first VNode to check
|
|
654
|
+
* @param rightVNode the second VNode to check
|
|
655
|
+
* @returns whether they're equal or not
|
|
656
|
+
*/
|
|
657
|
+
const isSameVnode = (leftVNode, rightVNode) => {
|
|
499
658
|
// compare if two vnode to see if they're "technically" the same
|
|
500
659
|
// need to have the same element tag, and same key to be the same
|
|
501
|
-
if (
|
|
660
|
+
if (leftVNode.$tag$ === rightVNode.$tag$) {
|
|
502
661
|
return true;
|
|
503
662
|
}
|
|
504
663
|
return false;
|
|
505
664
|
};
|
|
665
|
+
/**
|
|
666
|
+
* Handle reconciling an outdated VNode with a new one which corresponds to
|
|
667
|
+
* it. This function handles flushing updates to the DOM and reconciling the
|
|
668
|
+
* children of the two nodes (if any).
|
|
669
|
+
*
|
|
670
|
+
* @param oldVNode an old VNode whose DOM element and children we want to update
|
|
671
|
+
* @param newVNode a new VNode representing an updated version of the old one
|
|
672
|
+
*/
|
|
506
673
|
const patch = (oldVNode, newVNode) => {
|
|
507
674
|
const elm = (newVNode.$elm$ = oldVNode.$elm$);
|
|
508
675
|
const oldChildren = oldVNode.$children$;
|
|
@@ -510,7 +677,6 @@ const patch = (oldVNode, newVNode) => {
|
|
|
510
677
|
const tag = newVNode.$tag$;
|
|
511
678
|
const text = newVNode.$text$;
|
|
512
679
|
if (text === null) {
|
|
513
|
-
// element node
|
|
514
680
|
{
|
|
515
681
|
if (tag === 'slot')
|
|
516
682
|
;
|
|
@@ -523,6 +689,7 @@ const patch = (oldVNode, newVNode) => {
|
|
|
523
689
|
}
|
|
524
690
|
if (oldChildren !== null && newChildren !== null) {
|
|
525
691
|
// looks like there's child vnodes for both the old and new vnodes
|
|
692
|
+
// so we need to call `updateChildren` to reconcile them
|
|
526
693
|
updateChildren(elm, oldChildren, newVNode, newChildren);
|
|
527
694
|
}
|
|
528
695
|
else if (newChildren !== null) {
|
|
@@ -556,7 +723,7 @@ const renderVdom = (hostRef, renderFnResults) => {
|
|
|
556
723
|
cmpMeta.$attrsToReflect$.map(([propName, attribute]) => (rootVnode.$attrs$[attribute] = hostElm[propName]));
|
|
557
724
|
}
|
|
558
725
|
rootVnode.$tag$ = null;
|
|
559
|
-
rootVnode.$flags$ |= 4 /* isHost */;
|
|
726
|
+
rootVnode.$flags$ |= 4 /* VNODE_FLAGS.isHost */;
|
|
560
727
|
hostRef.$vnode$ = rootVnode;
|
|
561
728
|
rootVnode.$elm$ = oldVNode.$elm$ = (hostElm.shadowRoot || hostElm );
|
|
562
729
|
{
|
|
@@ -565,32 +732,6 @@ const renderVdom = (hostRef, renderFnResults) => {
|
|
|
565
732
|
// synchronous patch
|
|
566
733
|
patch(oldVNode, rootVnode);
|
|
567
734
|
};
|
|
568
|
-
const getElement = (ref) => (getHostRef(ref).$hostElement$ );
|
|
569
|
-
const createEvent = (ref, name, flags) => {
|
|
570
|
-
const elm = getElement(ref);
|
|
571
|
-
return {
|
|
572
|
-
emit: (detail) => {
|
|
573
|
-
return emitEvent(elm, name, {
|
|
574
|
-
bubbles: !!(flags & 4 /* Bubbles */),
|
|
575
|
-
composed: !!(flags & 2 /* Composed */),
|
|
576
|
-
cancelable: !!(flags & 1 /* Cancellable */),
|
|
577
|
-
detail,
|
|
578
|
-
});
|
|
579
|
-
},
|
|
580
|
-
};
|
|
581
|
-
};
|
|
582
|
-
/**
|
|
583
|
-
* Helper function to create & dispatch a custom Event on a provided target
|
|
584
|
-
* @param elm the target of the Event
|
|
585
|
-
* @param name the name to give the custom Event
|
|
586
|
-
* @param opts options for configuring a custom Event
|
|
587
|
-
* @returns the custom Event
|
|
588
|
-
*/
|
|
589
|
-
const emitEvent = (elm, name, opts) => {
|
|
590
|
-
const ev = plt.ce(name, opts);
|
|
591
|
-
elm.dispatchEvent(ev);
|
|
592
|
-
return ev;
|
|
593
|
-
};
|
|
594
735
|
const attachToAncestor = (hostRef, ancestorComponent) => {
|
|
595
736
|
if (ancestorComponent && !hostRef.$onRenderResolve$ && ancestorComponent['s-p']) {
|
|
596
737
|
ancestorComponent['s-p'].push(new Promise((r) => (hostRef.$onRenderResolve$ = r)));
|
|
@@ -598,10 +739,10 @@ const attachToAncestor = (hostRef, ancestorComponent) => {
|
|
|
598
739
|
};
|
|
599
740
|
const scheduleUpdate = (hostRef, isInitialLoad) => {
|
|
600
741
|
{
|
|
601
|
-
hostRef.$flags$ |= 16 /* isQueuedForUpdate */;
|
|
742
|
+
hostRef.$flags$ |= 16 /* HOST_FLAGS.isQueuedForUpdate */;
|
|
602
743
|
}
|
|
603
|
-
if (hostRef.$flags$ & 4 /* isWaitingForChildren */) {
|
|
604
|
-
hostRef.$flags$ |= 512 /* needsRerender */;
|
|
744
|
+
if (hostRef.$flags$ & 4 /* HOST_FLAGS.isWaitingForChildren */) {
|
|
745
|
+
hostRef.$flags$ |= 512 /* HOST_FLAGS.needsRerender */;
|
|
605
746
|
return;
|
|
606
747
|
}
|
|
607
748
|
attachToAncestor(hostRef, hostRef.$ancestorComponent$);
|
|
@@ -617,7 +758,7 @@ const dispatchHooks = (hostRef, isInitialLoad) => {
|
|
|
617
758
|
let promise;
|
|
618
759
|
if (isInitialLoad) {
|
|
619
760
|
{
|
|
620
|
-
hostRef.$flags$ |= 256 /* isListenReady */;
|
|
761
|
+
hostRef.$flags$ |= 256 /* HOST_FLAGS.isListenReady */;
|
|
621
762
|
if (hostRef.$queuedListeners$) {
|
|
622
763
|
hostRef.$queuedListeners$.map(([methodName, event]) => safeCall(instance, methodName, event));
|
|
623
764
|
hostRef.$queuedListeners$ = null;
|
|
@@ -663,7 +804,7 @@ const updateComponent = async (hostRef, instance, isInitialLoad) => {
|
|
|
663
804
|
}
|
|
664
805
|
else {
|
|
665
806
|
Promise.all(childrenPromises).then(postUpdate);
|
|
666
|
-
hostRef.$flags$ |= 4 /* isWaitingForChildren */;
|
|
807
|
+
hostRef.$flags$ |= 4 /* HOST_FLAGS.isWaitingForChildren */;
|
|
667
808
|
childrenPromises.length = 0;
|
|
668
809
|
}
|
|
669
810
|
}
|
|
@@ -672,10 +813,10 @@ const callRender = (hostRef, instance, elm) => {
|
|
|
672
813
|
try {
|
|
673
814
|
instance = instance.render() ;
|
|
674
815
|
{
|
|
675
|
-
hostRef.$flags$ &= ~16 /* isQueuedForUpdate */;
|
|
816
|
+
hostRef.$flags$ &= ~16 /* HOST_FLAGS.isQueuedForUpdate */;
|
|
676
817
|
}
|
|
677
818
|
{
|
|
678
|
-
hostRef.$flags$ |= 2 /* hasRendered */;
|
|
819
|
+
hostRef.$flags$ |= 2 /* HOST_FLAGS.hasRendered */;
|
|
679
820
|
}
|
|
680
821
|
{
|
|
681
822
|
{
|
|
@@ -702,8 +843,8 @@ const postUpdateComponent = (hostRef) => {
|
|
|
702
843
|
{
|
|
703
844
|
safeCall(instance, 'componentDidRender');
|
|
704
845
|
}
|
|
705
|
-
if (!(hostRef.$flags$ & 64 /* hasLoadedComponent */)) {
|
|
706
|
-
hostRef.$flags$ |= 64 /* hasLoadedComponent */;
|
|
846
|
+
if (!(hostRef.$flags$ & 64 /* HOST_FLAGS.hasLoadedComponent */)) {
|
|
847
|
+
hostRef.$flags$ |= 64 /* HOST_FLAGS.hasLoadedComponent */;
|
|
707
848
|
{
|
|
708
849
|
// DOM WRITE!
|
|
709
850
|
addHydratedFlag(elm);
|
|
@@ -726,10 +867,10 @@ const postUpdateComponent = (hostRef) => {
|
|
|
726
867
|
hostRef.$onRenderResolve$();
|
|
727
868
|
hostRef.$onRenderResolve$ = undefined;
|
|
728
869
|
}
|
|
729
|
-
if (hostRef.$flags$ & 512 /* needsRerender */) {
|
|
870
|
+
if (hostRef.$flags$ & 512 /* HOST_FLAGS.needsRerender */) {
|
|
730
871
|
nextTick(() => scheduleUpdate(hostRef, false));
|
|
731
872
|
}
|
|
732
|
-
hostRef.$flags$ &= ~(4 /* isWaitingForChildren */ | 512 /* needsRerender */);
|
|
873
|
+
hostRef.$flags$ &= ~(4 /* HOST_FLAGS.isWaitingForChildren */ | 512 /* HOST_FLAGS.needsRerender */);
|
|
733
874
|
}
|
|
734
875
|
// ( •_•)
|
|
735
876
|
// ( •_•)>⌐■-■
|
|
@@ -759,49 +900,6 @@ const then = (promise, thenFn) => {
|
|
|
759
900
|
};
|
|
760
901
|
const addHydratedFlag = (elm) => elm.classList.add('hydrated')
|
|
761
902
|
;
|
|
762
|
-
/**
|
|
763
|
-
* Parse a new property value for a given property type.
|
|
764
|
-
*
|
|
765
|
-
* While the prop value can reasonably be expected to be of `any` type as far as TypeScript's type checker is concerned,
|
|
766
|
-
* it is not safe to assume that the string returned by evaluating `typeof propValue` matches:
|
|
767
|
-
* 1. `any`, the type given to `propValue` in the function signature
|
|
768
|
-
* 2. the type stored from `propType`.
|
|
769
|
-
*
|
|
770
|
-
* This function provides the capability to parse/coerce a property's value to potentially any other JavaScript type.
|
|
771
|
-
*
|
|
772
|
-
* Property values represented in TSX preserve their type information. In the example below, the number 0 is passed to
|
|
773
|
-
* a component. This `propValue` will preserve its type information (`typeof propValue === 'number'`). Note that is
|
|
774
|
-
* based on the type of the value being passed in, not the type declared of the class member decorated with `@Prop`.
|
|
775
|
-
* ```tsx
|
|
776
|
-
* <my-cmp prop-val={0}></my-cmp>
|
|
777
|
-
* ```
|
|
778
|
-
*
|
|
779
|
-
* HTML prop values on the other hand, will always a string
|
|
780
|
-
*
|
|
781
|
-
* @param propValue the new value to coerce to some type
|
|
782
|
-
* @param propType the type of the prop, expressed as a binary number
|
|
783
|
-
* @returns the parsed/coerced value
|
|
784
|
-
*/
|
|
785
|
-
const parsePropertyValue = (propValue, propType) => {
|
|
786
|
-
// ensure this value is of the correct prop type
|
|
787
|
-
if (propValue != null && !isComplexType(propValue)) {
|
|
788
|
-
if (propType & 4 /* Boolean */) {
|
|
789
|
-
// per the HTML spec, any string value means it is a boolean true value
|
|
790
|
-
// but we'll cheat here and say that the string "false" is the boolean false
|
|
791
|
-
return propValue === 'false' ? false : propValue === '' || !!propValue;
|
|
792
|
-
}
|
|
793
|
-
if (propType & 1 /* String */) {
|
|
794
|
-
// could have been passed as a number or boolean
|
|
795
|
-
// but we still want it as a string
|
|
796
|
-
return String(propValue);
|
|
797
|
-
}
|
|
798
|
-
// redundant return here for better minification
|
|
799
|
-
return propValue;
|
|
800
|
-
}
|
|
801
|
-
// not sure exactly what type we want
|
|
802
|
-
// so no need to change to a different type
|
|
803
|
-
return propValue;
|
|
804
|
-
};
|
|
805
903
|
const getValue = (ref, propName) => getHostRef(ref).$instanceValues$.get(propName);
|
|
806
904
|
const setValue = (ref, propName, newVal, cmpMeta) => {
|
|
807
905
|
// check our new property value against our internal value
|
|
@@ -814,13 +912,13 @@ const setValue = (ref, propName, newVal, cmpMeta) => {
|
|
|
814
912
|
// explicitly check for NaN on both sides, as `NaN === NaN` is always false
|
|
815
913
|
const areBothNaN = Number.isNaN(oldVal) && Number.isNaN(newVal);
|
|
816
914
|
const didValueChange = newVal !== oldVal && !areBothNaN;
|
|
817
|
-
if ((!(flags & 8 /* isConstructingInstance */) || oldVal === undefined) && didValueChange) {
|
|
915
|
+
if ((!(flags & 8 /* HOST_FLAGS.isConstructingInstance */) || oldVal === undefined) && didValueChange) {
|
|
818
916
|
// gadzooks! the property's value has changed!!
|
|
819
917
|
// set our new value!
|
|
820
918
|
hostRef.$instanceValues$.set(propName, newVal);
|
|
821
919
|
if (instance) {
|
|
822
920
|
// get an array of method names of watch functions to call
|
|
823
|
-
if (cmpMeta.$watchers$ && flags & 128 /* isWatchReady */) {
|
|
921
|
+
if (cmpMeta.$watchers$ && flags & 128 /* HOST_FLAGS.isWatchReady */) {
|
|
824
922
|
const watchMethods = cmpMeta.$watchers$[propName];
|
|
825
923
|
if (watchMethods) {
|
|
826
924
|
// this instance is watching for when this property changed
|
|
@@ -835,7 +933,7 @@ const setValue = (ref, propName, newVal, cmpMeta) => {
|
|
|
835
933
|
});
|
|
836
934
|
}
|
|
837
935
|
}
|
|
838
|
-
if ((flags & (2 /* hasRendered */ | 16 /* isQueuedForUpdate */)) === 2 /* hasRendered */) {
|
|
936
|
+
if ((flags & (2 /* HOST_FLAGS.hasRendered */ | 16 /* HOST_FLAGS.isQueuedForUpdate */)) === 2 /* HOST_FLAGS.hasRendered */) {
|
|
839
937
|
// looks like this value actually changed, so we've got work to do!
|
|
840
938
|
// but only if we've already rendered, otherwise just chill out
|
|
841
939
|
// queue that we need to do an update, but don't worry about queuing
|
|
@@ -845,6 +943,16 @@ const setValue = (ref, propName, newVal, cmpMeta) => {
|
|
|
845
943
|
}
|
|
846
944
|
}
|
|
847
945
|
};
|
|
946
|
+
/**
|
|
947
|
+
* Attach a series of runtime constructs to a compiled Stencil component
|
|
948
|
+
* constructor, including getters and setters for the `@Prop` and `@State`
|
|
949
|
+
* decorators, callbacks for when attributes change, and so on.
|
|
950
|
+
*
|
|
951
|
+
* @param Cstr the constructor for a component that we need to process
|
|
952
|
+
* @param cmpMeta metadata collected previously about the component
|
|
953
|
+
* @param flags a number used to store a series of bit flags
|
|
954
|
+
* @returns a reference to the same constructor passed in (but now mutated)
|
|
955
|
+
*/
|
|
848
956
|
const proxyComponent = (Cstr, cmpMeta, flags) => {
|
|
849
957
|
if (cmpMeta.$members$) {
|
|
850
958
|
if (Cstr.watchers) {
|
|
@@ -854,8 +962,8 @@ const proxyComponent = (Cstr, cmpMeta, flags) => {
|
|
|
854
962
|
const members = Object.entries(cmpMeta.$members$);
|
|
855
963
|
const prototype = Cstr.prototype;
|
|
856
964
|
members.map(([memberName, [memberFlags]]) => {
|
|
857
|
-
if ((memberFlags & 31 /* Prop */ ||
|
|
858
|
-
((flags & 2 /* proxyState */) && memberFlags & 32 /* State */))) {
|
|
965
|
+
if ((memberFlags & 31 /* MEMBER_FLAGS.Prop */ ||
|
|
966
|
+
((flags & 2 /* PROXY_FLAGS.proxyState */) && memberFlags & 32 /* MEMBER_FLAGS.State */))) {
|
|
859
967
|
// proxyComponent - prop
|
|
860
968
|
Object.defineProperty(prototype, memberName, {
|
|
861
969
|
get() {
|
|
@@ -871,7 +979,7 @@ const proxyComponent = (Cstr, cmpMeta, flags) => {
|
|
|
871
979
|
});
|
|
872
980
|
}
|
|
873
981
|
});
|
|
874
|
-
if ((flags & 1 /* isElementConstructor */)) {
|
|
982
|
+
if ((flags & 1 /* PROXY_FLAGS.isElementConstructor */)) {
|
|
875
983
|
const attrNameToPropName = new Map();
|
|
876
984
|
prototype.attributeChangedCallback = function (attrName, _oldValue, newValue) {
|
|
877
985
|
plt.jmp(() => {
|
|
@@ -927,11 +1035,11 @@ const proxyComponent = (Cstr, cmpMeta, flags) => {
|
|
|
927
1035
|
// create an array of attributes to observe
|
|
928
1036
|
// and also create a map of html attribute name to js property name
|
|
929
1037
|
Cstr.observedAttributes = members
|
|
930
|
-
.filter(([_, m]) => m[0] & 15 /* HasAttribute */) // filter to only keep props that should match attributes
|
|
1038
|
+
.filter(([_, m]) => m[0] & 15 /* MEMBER_FLAGS.HasAttribute */) // filter to only keep props that should match attributes
|
|
931
1039
|
.map(([propName, m]) => {
|
|
932
1040
|
const attrName = m[1] || propName;
|
|
933
1041
|
attrNameToPropName.set(attrName, propName);
|
|
934
|
-
if (m[0] & 512 /* ReflectAttr */) {
|
|
1042
|
+
if (m[0] & 512 /* MEMBER_FLAGS.ReflectAttr */) {
|
|
935
1043
|
cmpMeta.$attrsToReflect$.push([propName, attrName]);
|
|
936
1044
|
}
|
|
937
1045
|
return attrName;
|
|
@@ -942,10 +1050,10 @@ const proxyComponent = (Cstr, cmpMeta, flags) => {
|
|
|
942
1050
|
};
|
|
943
1051
|
const initializeComponent = async (elm, hostRef, cmpMeta, hmrVersionId, Cstr) => {
|
|
944
1052
|
// initializeComponent
|
|
945
|
-
if ((hostRef.$flags$ & 32 /* hasInitializedComponent */) === 0) {
|
|
1053
|
+
if ((hostRef.$flags$ & 32 /* HOST_FLAGS.hasInitializedComponent */) === 0) {
|
|
946
1054
|
{
|
|
947
1055
|
// we haven't initialized this element yet
|
|
948
|
-
hostRef.$flags$ |= 32 /* hasInitializedComponent */;
|
|
1056
|
+
hostRef.$flags$ |= 32 /* HOST_FLAGS.hasInitializedComponent */;
|
|
949
1057
|
// lazy loaded components
|
|
950
1058
|
// request the component's implementation to be
|
|
951
1059
|
// wired up with the host element
|
|
@@ -963,7 +1071,7 @@ const initializeComponent = async (elm, hostRef, cmpMeta, hmrVersionId, Cstr) =>
|
|
|
963
1071
|
{
|
|
964
1072
|
cmpMeta.$watchers$ = Cstr.watchers;
|
|
965
1073
|
}
|
|
966
|
-
proxyComponent(Cstr, cmpMeta, 2 /* proxyState */);
|
|
1074
|
+
proxyComponent(Cstr, cmpMeta, 2 /* PROXY_FLAGS.proxyState */);
|
|
967
1075
|
Cstr.isProxied = true;
|
|
968
1076
|
}
|
|
969
1077
|
const endNewInstance = createTime('createInstance', cmpMeta.$tagName$);
|
|
@@ -971,7 +1079,7 @@ const initializeComponent = async (elm, hostRef, cmpMeta, hmrVersionId, Cstr) =>
|
|
|
971
1079
|
// but let's keep track of when we start and stop
|
|
972
1080
|
// so that the getters/setters don't incorrectly step on data
|
|
973
1081
|
{
|
|
974
|
-
hostRef.$flags$ |= 8 /* isConstructingInstance */;
|
|
1082
|
+
hostRef.$flags$ |= 8 /* HOST_FLAGS.isConstructingInstance */;
|
|
975
1083
|
}
|
|
976
1084
|
// construct the lazy-loaded component implementation
|
|
977
1085
|
// passing the hostRef is very important during
|
|
@@ -984,10 +1092,10 @@ const initializeComponent = async (elm, hostRef, cmpMeta, hmrVersionId, Cstr) =>
|
|
|
984
1092
|
consoleError(e);
|
|
985
1093
|
}
|
|
986
1094
|
{
|
|
987
|
-
hostRef.$flags$ &= ~8 /* isConstructingInstance */;
|
|
1095
|
+
hostRef.$flags$ &= ~8 /* HOST_FLAGS.isConstructingInstance */;
|
|
988
1096
|
}
|
|
989
1097
|
{
|
|
990
|
-
hostRef.$flags$ |= 128 /* isWatchReady */;
|
|
1098
|
+
hostRef.$flags$ |= 128 /* HOST_FLAGS.isWatchReady */;
|
|
991
1099
|
}
|
|
992
1100
|
endNewInstance();
|
|
993
1101
|
}
|
|
@@ -997,7 +1105,7 @@ const initializeComponent = async (elm, hostRef, cmpMeta, hmrVersionId, Cstr) =>
|
|
|
997
1105
|
const scopeId = getScopeId(cmpMeta);
|
|
998
1106
|
if (!styles.has(scopeId)) {
|
|
999
1107
|
const endRegisterStyles = createTime('registerStyles', cmpMeta.$tagName$);
|
|
1000
|
-
registerStyle(scopeId, style, !!(cmpMeta.$flags$ & 1 /* shadowDomEncapsulation */));
|
|
1108
|
+
registerStyle(scopeId, style, !!(cmpMeta.$flags$ & 1 /* CMP_FLAGS.shadowDomEncapsulation */));
|
|
1001
1109
|
endRegisterStyles();
|
|
1002
1110
|
}
|
|
1003
1111
|
}
|
|
@@ -1019,13 +1127,13 @@ const initializeComponent = async (elm, hostRef, cmpMeta, hmrVersionId, Cstr) =>
|
|
|
1019
1127
|
}
|
|
1020
1128
|
};
|
|
1021
1129
|
const connectedCallback = (elm) => {
|
|
1022
|
-
if ((plt.$flags$ & 1 /* isTmpDisconnected */) === 0) {
|
|
1130
|
+
if ((plt.$flags$ & 1 /* PLATFORM_FLAGS.isTmpDisconnected */) === 0) {
|
|
1023
1131
|
const hostRef = getHostRef(elm);
|
|
1024
1132
|
const cmpMeta = hostRef.$cmpMeta$;
|
|
1025
1133
|
const endConnected = createTime('connectedCallback', cmpMeta.$tagName$);
|
|
1026
|
-
if (!(hostRef.$flags$ & 1 /* hasConnected */)) {
|
|
1134
|
+
if (!(hostRef.$flags$ & 1 /* HOST_FLAGS.hasConnected */)) {
|
|
1027
1135
|
// first time this component has connected
|
|
1028
|
-
hostRef.$flags$ |= 1 /* hasConnected */;
|
|
1136
|
+
hostRef.$flags$ |= 1 /* HOST_FLAGS.hasConnected */;
|
|
1029
1137
|
{
|
|
1030
1138
|
// find the first ancestor component (if there is one) and register
|
|
1031
1139
|
// this component as one of the actively loading child components for its ancestor
|
|
@@ -1045,7 +1153,7 @@ const connectedCallback = (elm) => {
|
|
|
1045
1153
|
// https://developers.google.com/web/fundamentals/web-components/best-practices#lazy-properties
|
|
1046
1154
|
if (cmpMeta.$members$) {
|
|
1047
1155
|
Object.entries(cmpMeta.$members$).map(([memberName, [memberFlags]]) => {
|
|
1048
|
-
if (memberFlags & 31 /* Prop */ && elm.hasOwnProperty(memberName)) {
|
|
1156
|
+
if (memberFlags & 31 /* MEMBER_FLAGS.Prop */ && elm.hasOwnProperty(memberName)) {
|
|
1049
1157
|
const value = elm[memberName];
|
|
1050
1158
|
delete elm[memberName];
|
|
1051
1159
|
elm[memberName] = value;
|
|
@@ -1066,14 +1174,18 @@ const connectedCallback = (elm) => {
|
|
|
1066
1174
|
}
|
|
1067
1175
|
};
|
|
1068
1176
|
const disconnectedCallback = (elm) => {
|
|
1069
|
-
if ((plt.$flags$ & 1 /* isTmpDisconnected */) === 0) {
|
|
1177
|
+
if ((plt.$flags$ & 1 /* PLATFORM_FLAGS.isTmpDisconnected */) === 0) {
|
|
1070
1178
|
const hostRef = getHostRef(elm);
|
|
1179
|
+
const instance = hostRef.$lazyInstance$ ;
|
|
1071
1180
|
{
|
|
1072
1181
|
if (hostRef.$rmListeners$) {
|
|
1073
1182
|
hostRef.$rmListeners$.map((rmListener) => rmListener());
|
|
1074
1183
|
hostRef.$rmListeners$ = undefined;
|
|
1075
1184
|
}
|
|
1076
1185
|
}
|
|
1186
|
+
{
|
|
1187
|
+
safeCall(instance, 'disconnectedCallback');
|
|
1188
|
+
}
|
|
1077
1189
|
}
|
|
1078
1190
|
};
|
|
1079
1191
|
const bootstrapLazy = (lazyBundles, options = {}) => {
|
|
@@ -1117,7 +1229,7 @@ const bootstrapLazy = (lazyBundles, options = {}) => {
|
|
|
1117
1229
|
super(self);
|
|
1118
1230
|
self = this;
|
|
1119
1231
|
registerHost(self, cmpMeta);
|
|
1120
|
-
if (cmpMeta.$flags$ & 1 /* shadowDomEncapsulation */) {
|
|
1232
|
+
if (cmpMeta.$flags$ & 1 /* CMP_FLAGS.shadowDomEncapsulation */) {
|
|
1121
1233
|
// this component is using shadow dom
|
|
1122
1234
|
// and this browser supports shadow dom
|
|
1123
1235
|
// add the read-only property "shadowRoot" to the host element
|
|
@@ -1152,7 +1264,7 @@ const bootstrapLazy = (lazyBundles, options = {}) => {
|
|
|
1152
1264
|
cmpMeta.$lazyBundleId$ = lazyBundle[0];
|
|
1153
1265
|
if (!exclude.includes(tagName) && !customElements.get(tagName)) {
|
|
1154
1266
|
cmpTags.push(tagName);
|
|
1155
|
-
customElements.define(tagName, proxyComponent(HostElement, cmpMeta, 1 /* isElementConstructor */));
|
|
1267
|
+
customElements.define(tagName, proxyComponent(HostElement, cmpMeta, 1 /* PROXY_FLAGS.isElementConstructor */));
|
|
1156
1268
|
}
|
|
1157
1269
|
});
|
|
1158
1270
|
});
|
|
@@ -1174,7 +1286,41 @@ const bootstrapLazy = (lazyBundles, options = {}) => {
|
|
|
1174
1286
|
// Fallback appLoad event
|
|
1175
1287
|
endBootstrap();
|
|
1176
1288
|
};
|
|
1177
|
-
const
|
|
1289
|
+
const addHostEventListeners = (elm, hostRef, listeners, attachParentListeners) => {
|
|
1290
|
+
if (listeners) {
|
|
1291
|
+
listeners.map(([flags, name, method]) => {
|
|
1292
|
+
const target = getHostListenerTarget(elm, flags) ;
|
|
1293
|
+
const handler = hostListenerProxy(hostRef, method);
|
|
1294
|
+
const opts = hostListenerOpts(flags);
|
|
1295
|
+
plt.ael(target, name, handler, opts);
|
|
1296
|
+
(hostRef.$rmListeners$ = hostRef.$rmListeners$ || []).push(() => plt.rel(target, name, handler, opts));
|
|
1297
|
+
});
|
|
1298
|
+
}
|
|
1299
|
+
};
|
|
1300
|
+
const hostListenerProxy = (hostRef, methodName) => (ev) => {
|
|
1301
|
+
try {
|
|
1302
|
+
{
|
|
1303
|
+
if (hostRef.$flags$ & 256 /* HOST_FLAGS.isListenReady */) {
|
|
1304
|
+
// instance is ready, let's call it's member method for this event
|
|
1305
|
+
hostRef.$lazyInstance$[methodName](ev);
|
|
1306
|
+
}
|
|
1307
|
+
else {
|
|
1308
|
+
(hostRef.$queuedListeners$ = hostRef.$queuedListeners$ || []).push([methodName, ev]);
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
catch (e) {
|
|
1313
|
+
consoleError(e);
|
|
1314
|
+
}
|
|
1315
|
+
};
|
|
1316
|
+
const getHostListenerTarget = (elm, flags) => {
|
|
1317
|
+
if (flags & 4 /* LISTENER_FLAGS.TargetDocument */)
|
|
1318
|
+
return doc;
|
|
1319
|
+
return elm;
|
|
1320
|
+
};
|
|
1321
|
+
// prettier-ignore
|
|
1322
|
+
const hostListenerOpts = (flags) => (flags & 2 /* LISTENER_FLAGS.Capture */) !== 0;
|
|
1323
|
+
const hostRefs = /*@__PURE__*/ new WeakMap();
|
|
1178
1324
|
const getHostRef = (ref) => hostRefs.get(ref);
|
|
1179
1325
|
const registerInstance = (lazyInstance, hostRef) => hostRefs.set((hostRef.$lazyInstance$ = lazyInstance), hostRef);
|
|
1180
1326
|
const registerHost = (elm, cmpMeta) => {
|
|
@@ -1216,14 +1362,35 @@ const loadModule = (cmpMeta, hostRef, hmrVersionId) => {
|
|
|
1216
1362
|
return importedModule[exportName];
|
|
1217
1363
|
}, consoleError);
|
|
1218
1364
|
};
|
|
1219
|
-
const styles = new Map();
|
|
1365
|
+
const styles = /*@__PURE__*/ new Map();
|
|
1366
|
+
const win = typeof window !== 'undefined' ? window : {};
|
|
1367
|
+
const doc = win.document || { head: {} };
|
|
1368
|
+
const plt = {
|
|
1369
|
+
$flags$: 0,
|
|
1370
|
+
$resourcesUrl$: '',
|
|
1371
|
+
jmp: (h) => h(),
|
|
1372
|
+
raf: (h) => requestAnimationFrame(h),
|
|
1373
|
+
ael: (el, eventName, listener, opts) => el.addEventListener(eventName, listener, opts),
|
|
1374
|
+
rel: (el, eventName, listener, opts) => el.removeEventListener(eventName, listener, opts),
|
|
1375
|
+
ce: (eventName, opts) => new CustomEvent(eventName, opts),
|
|
1376
|
+
};
|
|
1377
|
+
const promiseResolve = (v) => Promise.resolve(v);
|
|
1378
|
+
const supportsConstructableStylesheets = /*@__PURE__*/ (() => {
|
|
1379
|
+
try {
|
|
1380
|
+
new CSSStyleSheet();
|
|
1381
|
+
return typeof new CSSStyleSheet().replaceSync === 'function';
|
|
1382
|
+
}
|
|
1383
|
+
catch (e) { }
|
|
1384
|
+
return false;
|
|
1385
|
+
})()
|
|
1386
|
+
;
|
|
1220
1387
|
const queueDomReads = [];
|
|
1221
1388
|
const queueDomWrites = [];
|
|
1222
1389
|
const queueTask = (queue, write) => (cb) => {
|
|
1223
1390
|
queue.push(cb);
|
|
1224
1391
|
if (!queuePending) {
|
|
1225
1392
|
queuePending = true;
|
|
1226
|
-
if (write && plt.$flags$ & 4 /* queueSync */) {
|
|
1393
|
+
if (write && plt.$flags$ & 4 /* PLATFORM_FLAGS.queueSync */) {
|
|
1227
1394
|
nextTick(flush);
|
|
1228
1395
|
}
|
|
1229
1396
|
else {
|