@maggioli-design-system/mds-table-row 1.3.1 → 1.4.0

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.
Files changed (54) hide show
  1. package/dist/cjs/{index-797b786c.js → index-b308d20f.js} +156 -371
  2. package/dist/cjs/loader.cjs.js +3 -3
  3. package/dist/cjs/mds-table-row.cjs.entry.js +3 -44
  4. package/dist/cjs/mds-table-row.cjs.js +3 -3
  5. package/dist/collection/collection-manifest.json +2 -2
  6. package/dist/collection/components/mds-table-row/mds-table-row.css +10 -21
  7. package/dist/collection/components/mds-table-row/mds-table-row.js +21 -5
  8. package/dist/collection/dictionary/icon.js +4 -1
  9. package/dist/components/mds-table-row.js +5 -45
  10. package/dist/esm/{index-7d849f54.js → index-7d3be39d.js} +156 -371
  11. package/dist/esm/loader.js +3 -3
  12. package/dist/esm/mds-table-row.entry.js +3 -44
  13. package/dist/esm/mds-table-row.js +3 -3
  14. package/dist/esm/polyfills/css-shim.js +1 -1
  15. package/dist/esm-es5/index-7d3be39d.js +1 -0
  16. package/dist/esm-es5/loader.js +1 -1
  17. package/dist/esm-es5/mds-table-row.entry.js +1 -1
  18. package/dist/esm-es5/mds-table-row.js +1 -1
  19. package/dist/mds-table-row/mds-table-row.esm.js +1 -1
  20. package/dist/mds-table-row/mds-table-row.js +1 -1
  21. package/dist/mds-table-row/p-24980e09.entry.js +1 -0
  22. package/dist/mds-table-row/p-5002b598.js +1 -0
  23. package/dist/mds-table-row/p-84058f8c.system.js +1 -0
  24. package/dist/mds-table-row/p-bfe52009.system.js +1 -0
  25. package/dist/mds-table-row/p-f2da3252.system.entry.js +1 -0
  26. package/dist/stats.json +80 -49
  27. package/dist/types/components/mds-table-row/mds-table-row.d.ts +1 -1
  28. package/dist/types/components.d.ts +2 -0
  29. package/dist/types/dictionary/icon.d.ts +1 -1
  30. package/package.json +3 -3
  31. package/readme.md +8 -0
  32. package/src/components/mds-table-row/mds-table-row.css +10 -20
  33. package/src/components/mds-table-row/mds-table-row.tsx +4 -5
  34. package/src/components/mds-table-row/readme.md +7 -0
  35. package/src/components.d.ts +2 -0
  36. package/src/dictionary/icon.ts +6 -1
  37. package/www/build/mds-table-row.esm.js +1 -1
  38. package/www/build/mds-table-row.js +1 -1
  39. package/www/build/p-24980e09.entry.js +1 -0
  40. package/www/build/p-5002b598.js +1 -0
  41. package/www/build/p-84058f8c.system.js +1 -0
  42. package/www/build/p-bfe52009.system.js +1 -0
  43. package/www/build/p-f2da3252.system.entry.js +1 -0
  44. package/dist/esm-es5/index-7d849f54.js +0 -1
  45. package/dist/mds-table-row/p-13e3a2cc.system.js +0 -1
  46. package/dist/mds-table-row/p-15f2406e.system.js +0 -1
  47. package/dist/mds-table-row/p-3619a466.js +0 -1
  48. package/dist/mds-table-row/p-4829abc6.system.entry.js +0 -1
  49. package/dist/mds-table-row/p-db71d0ac.entry.js +0 -1
  50. package/www/build/p-13e3a2cc.system.js +0 -1
  51. package/www/build/p-15f2406e.system.js +0 -1
  52. package/www/build/p-3619a466.js +0 -1
  53. package/www/build/p-4829abc6.system.entry.js +0 -1
  54. package/www/build/p-db71d0ac.entry.js +0 -1
@@ -1,10 +1,7 @@
1
1
  const NAMESPACE = 'mds-table-row';
2
2
 
3
- let contentRef;
3
+ let scopeId;
4
4
  let hostTagName;
5
- let useNativeShadowDom = false;
6
- let checkSlotFallbackVisibility = false;
7
- let checkSlotRelocate = false;
8
5
  let isSvgMode = false;
9
6
  let queuePending = false;
10
7
  const win = typeof window !== 'undefined' ? window : {};
@@ -125,8 +122,20 @@ const addStyle = (styleContainerNode, cmpMeta, mode, hostElm) => {
125
122
  const attachStyles = (hostRef) => {
126
123
  const cmpMeta = hostRef.$cmpMeta$;
127
124
  const elm = hostRef.$hostElement$;
125
+ const flags = cmpMeta.$flags$;
128
126
  const endAttachStyles = createTime('attachStyles', cmpMeta.$tagName$);
129
- addStyle(elm.getRootNode(), cmpMeta);
127
+ const scopeId = addStyle(elm.shadowRoot ? elm.shadowRoot : elm.getRootNode(), cmpMeta);
128
+ if (flags & 10 /* needsScopedEncapsulation */) {
129
+ // only required when we're NOT using native shadow dom (slot)
130
+ // or this browser doesn't support native shadow dom
131
+ // and this host element was NOT created with SSR
132
+ // let's pick out the inner content for slot projection
133
+ // create a node to represent where the original
134
+ // content was first placed, which is useful later on
135
+ // DOM WRITE!!
136
+ elm['s-sc'] = scopeId;
137
+ elm.classList.add(scopeId + '-h');
138
+ }
130
139
  endAttachStyles();
131
140
  };
132
141
  const getScopeId = (cmp, mode) => 'sc-' + (cmp.$tagName$);
@@ -138,6 +147,7 @@ const getScopeId = (cmp, mode) => 'sc-' + (cmp.$tagName$);
138
147
  * Don't add values to these!!
139
148
  */
140
149
  const EMPTY_OBJ = {};
150
+ const isDef = (v) => v != null;
141
151
  const isComplexType = (o) => {
142
152
  // https://jsperf.com/typeof-fn-object/5
143
153
  o = typeof o;
@@ -156,7 +166,6 @@ const isComplexType = (o) => {
156
166
  // export function h(nodeName: string | d.FunctionalComponent, vnodeData: d.PropsType, ...children: d.ChildType[]): d.VNode;
157
167
  const h = (nodeName, vnodeData, ...children) => {
158
168
  let child = null;
159
- let slotName = null;
160
169
  let simple = false;
161
170
  let lastSimple = false;
162
171
  let vNodeChildren = [];
@@ -183,30 +192,11 @@ const h = (nodeName, vnodeData, ...children) => {
183
192
  }
184
193
  };
185
194
  walk(children);
186
- if (vnodeData) {
187
- if (vnodeData.name) {
188
- slotName = vnodeData.name;
189
- }
190
- {
191
- const classData = vnodeData.className || vnodeData.class;
192
- if (classData) {
193
- vnodeData.class =
194
- typeof classData !== 'object'
195
- ? classData
196
- : Object.keys(classData)
197
- .filter((k) => classData[k])
198
- .join(' ');
199
- }
200
- }
201
- }
202
195
  const vnode = newVNode(nodeName, null);
203
196
  vnode.$attrs$ = vnodeData;
204
197
  if (vNodeChildren.length > 0) {
205
198
  vnode.$children$ = vNodeChildren;
206
199
  }
207
- {
208
- vnode.$name$ = slotName;
209
- }
210
200
  return vnode;
211
201
  };
212
202
  const newVNode = (tag, text) => {
@@ -220,9 +210,6 @@ const newVNode = (tag, text) => {
220
210
  {
221
211
  vnode.$attrs$ = null;
222
212
  }
223
- {
224
- vnode.$name$ = null;
225
- }
226
213
  return vnode;
227
214
  };
228
215
  const Host = {};
@@ -239,14 +226,7 @@ const setAccessor = (elm, memberName, oldValue, newValue, isSvg, flags) => {
239
226
  if (oldValue !== newValue) {
240
227
  let isProp = isMemberInElement(elm, memberName);
241
228
  memberName.toLowerCase();
242
- if (memberName === 'class') {
243
- const classList = elm.classList;
244
- const oldClasses = parseClassList(oldValue);
245
- const newClasses = parseClassList(newValue);
246
- classList.remove(...oldClasses.filter((c) => c && !newClasses.includes(c)));
247
- classList.add(...newClasses.filter((c) => c && !oldClasses.includes(c)));
248
- }
249
- else {
229
+ {
250
230
  // Set property if it exists and it's not a SVG
251
231
  const isComplex = isComplexType(newValue);
252
232
  if ((isProp || (isComplex && newValue !== null)) && !isSvg) {
@@ -283,8 +263,6 @@ const setAccessor = (elm, memberName, oldValue, newValue, isSvg, flags) => {
283
263
  }
284
264
  }
285
265
  };
286
- const parseClassListRegex = /\s/;
287
- const parseClassList = (value) => (!value ? [] : value.split(parseClassListRegex));
288
266
  const updateElement = (oldVnode, newVnode, isSvgMode, memberName) => {
289
267
  // if the element passed in is a shadow root, which is a document fragment
290
268
  // then we want to be adding attrs/props to the shadow root's "host" element
@@ -313,32 +291,18 @@ const createElm = (oldParentVNode, newParentVNode, childIndex, parentElm) => {
313
291
  let i = 0;
314
292
  let elm;
315
293
  let childNode;
316
- let oldVNode;
317
- if (!useNativeShadowDom) {
318
- // remember for later we need to check to relocate nodes
319
- checkSlotRelocate = true;
320
- if (newVNode.$tag$ === 'slot') {
321
- newVNode.$flags$ |= newVNode.$children$
322
- ? // slot element has fallback content
323
- 2 /* isSlotFallback */
324
- : // slot element does not have fallback content
325
- 1 /* isSlotReference */;
326
- }
327
- }
328
- if (newVNode.$flags$ & 1 /* isSlotReference */) {
329
- // create a slot reference node
330
- elm = newVNode.$elm$ =
331
- doc.createTextNode('');
332
- }
333
- else {
294
+ {
334
295
  // create element
335
- elm = newVNode.$elm$ = (doc.createElement(newVNode.$flags$ & 2 /* isSlotFallback */
336
- ? 'slot-fb'
337
- : newVNode.$tag$));
296
+ elm = newVNode.$elm$ = (doc.createElement(newVNode.$tag$));
338
297
  // add css classes, attrs, props, listeners, etc.
339
298
  {
340
299
  updateElement(null, newVNode, isSvgMode);
341
300
  }
301
+ if (isDef(scopeId) && elm['s-si'] !== scopeId) {
302
+ // if there is a scopeId and this is the initial render
303
+ // then let's add the scopeId as a css class
304
+ elm.classList.add((elm['s-si'] = scopeId));
305
+ }
342
306
  if (newVNode.$children$) {
343
307
  for (i = 0; i < newVNode.$children$.length; ++i) {
344
308
  // create the node
@@ -351,59 +315,20 @@ const createElm = (oldParentVNode, newParentVNode, childIndex, parentElm) => {
351
315
  }
352
316
  }
353
317
  }
354
- {
355
- elm['s-hn'] = hostTagName;
356
- if (newVNode.$flags$ & (2 /* isSlotFallback */ | 1 /* isSlotReference */)) {
357
- // remember the content reference comment
358
- elm['s-sr'] = true;
359
- // remember the content reference comment
360
- elm['s-cr'] = contentRef;
361
- // remember the slot name, or empty string for default slot
362
- elm['s-sn'] = newVNode.$name$ || '';
363
- // check if we've got an old vnode for this slot
364
- oldVNode = oldParentVNode && oldParentVNode.$children$ && oldParentVNode.$children$[childIndex];
365
- if (oldVNode && oldVNode.$tag$ === newVNode.$tag$ && oldParentVNode.$elm$) {
366
- // we've got an old slot vnode and the wrapper is being replaced
367
- // so let's move the old slot content back to it's original location
368
- putBackInOriginalLocation(oldParentVNode.$elm$, false);
369
- }
370
- }
371
- }
372
318
  return elm;
373
319
  };
374
- const putBackInOriginalLocation = (parentElm, recursive) => {
375
- plt.$flags$ |= 1 /* isTmpDisconnected */;
376
- const oldSlotChildNodes = parentElm.childNodes;
377
- for (let i = oldSlotChildNodes.length - 1; i >= 0; i--) {
378
- const childNode = oldSlotChildNodes[i];
379
- if (childNode['s-hn'] !== hostTagName && childNode['s-ol']) {
380
- // // this child node in the old element is from another component
381
- // // remove this node from the old slot's parent
382
- // childNode.remove();
383
- // and relocate it back to it's original location
384
- parentReferenceNode(childNode).insertBefore(childNode, referenceNode(childNode));
385
- // remove the old original location comment entirely
386
- // later on the patch function will know what to do
387
- // and move this to the correct spot in need be
388
- childNode['s-ol'].remove();
389
- childNode['s-ol'] = undefined;
390
- checkSlotRelocate = true;
391
- }
392
- if (recursive) {
393
- putBackInOriginalLocation(childNode, recursive);
394
- }
395
- }
396
- plt.$flags$ &= ~1 /* isTmpDisconnected */;
397
- };
398
320
  const addVnodes = (parentElm, before, parentVNode, vnodes, startIdx, endIdx) => {
399
- let containerElm = ((parentElm['s-cr'] && parentElm['s-cr'].parentNode) || parentElm);
321
+ let containerElm = (parentElm);
400
322
  let childNode;
323
+ if (containerElm.shadowRoot && containerElm.tagName === hostTagName) {
324
+ containerElm = containerElm.shadowRoot;
325
+ }
401
326
  for (; startIdx <= endIdx; ++startIdx) {
402
327
  if (vnodes[startIdx]) {
403
328
  childNode = createElm(null, parentVNode, startIdx);
404
329
  if (childNode) {
405
330
  vnodes[startIdx].$elm$ = childNode;
406
- containerElm.insertBefore(childNode, referenceNode(before) );
331
+ containerElm.insertBefore(childNode, before);
407
332
  }
408
333
  }
409
334
  }
@@ -412,20 +337,6 @@ const removeVnodes = (vnodes, startIdx, endIdx, vnode, elm) => {
412
337
  for (; startIdx <= endIdx; ++startIdx) {
413
338
  if ((vnode = vnodes[startIdx])) {
414
339
  elm = vnode.$elm$;
415
- {
416
- // we're removing this element
417
- // so it's possible we need to show slot fallback content now
418
- checkSlotFallbackVisibility = true;
419
- if (elm['s-ol']) {
420
- // remove the original location comment
421
- elm['s-ol'].remove();
422
- }
423
- else {
424
- // it's possible that child nodes of the node
425
- // that's being removed are slot nodes
426
- putBackInOriginalLocation(elm, true);
427
- }
428
- }
429
340
  // remove the vnode's element from the dom
430
341
  elm.remove();
431
342
  }
@@ -466,20 +377,12 @@ const updateChildren = (parentElm, oldCh, newVNode, newCh) => {
466
377
  newEndVnode = newCh[--newEndIdx];
467
378
  }
468
379
  else if (isSameVnode(oldStartVnode, newEndVnode)) {
469
- // Vnode moved right
470
- if ((oldStartVnode.$tag$ === 'slot' || newEndVnode.$tag$ === 'slot')) {
471
- putBackInOriginalLocation(oldStartVnode.$elm$.parentNode, false);
472
- }
473
380
  patch(oldStartVnode, newEndVnode);
474
381
  parentElm.insertBefore(oldStartVnode.$elm$, oldEndVnode.$elm$.nextSibling);
475
382
  oldStartVnode = oldCh[++oldStartIdx];
476
383
  newEndVnode = newCh[--newEndIdx];
477
384
  }
478
385
  else if (isSameVnode(oldEndVnode, newStartVnode)) {
479
- // Vnode moved left
480
- if ((oldStartVnode.$tag$ === 'slot' || newEndVnode.$tag$ === 'slot')) {
481
- putBackInOriginalLocation(oldEndVnode.$elm$.parentNode, false);
482
- }
483
386
  patch(oldEndVnode, newStartVnode);
484
387
  parentElm.insertBefore(oldEndVnode.$elm$, oldStartVnode.$elm$);
485
388
  oldEndVnode = oldCh[--oldEndIdx];
@@ -493,7 +396,7 @@ const updateChildren = (parentElm, oldCh, newVNode, newCh) => {
493
396
  }
494
397
  if (node) {
495
398
  {
496
- parentReferenceNode(oldStartVnode.$elm$).insertBefore(node, referenceNode(oldStartVnode.$elm$));
399
+ oldStartVnode.$elm$.parentNode.insertBefore(node, oldStartVnode.$elm$);
497
400
  }
498
401
  }
499
402
  }
@@ -509,21 +412,10 @@ const isSameVnode = (vnode1, vnode2) => {
509
412
  // compare if two vnode to see if they're "technically" the same
510
413
  // need to have the same element tag, and same key to be the same
511
414
  if (vnode1.$tag$ === vnode2.$tag$) {
512
- if (vnode1.$tag$ === 'slot') {
513
- return vnode1.$name$ === vnode2.$name$;
514
- }
515
415
  return true;
516
416
  }
517
417
  return false;
518
418
  };
519
- const referenceNode = (node) => {
520
- // this node was relocated to a new location in the dom
521
- // because of some other component's slot
522
- // but we still have an html comment in place of where
523
- // it's original location was according to it's original vdom
524
- return (node && node['s-ol']) || node;
525
- };
526
- const parentReferenceNode = (node) => (node['s-ol'] ? node['s-ol'] : node).parentNode;
527
419
  const patch = (oldVNode, newVNode) => {
528
420
  const elm = (newVNode.$elm$ = oldVNode.$elm$);
529
421
  const oldChildren = oldVNode.$children$;
@@ -555,231 +447,25 @@ const patch = (oldVNode, newVNode) => {
555
447
  }
556
448
  }
557
449
  };
558
- const updateFallbackSlotVisibility = (elm) => {
559
- // tslint:disable-next-line: prefer-const
560
- let childNodes = elm.childNodes;
561
- let childNode;
562
- let i;
563
- let ilen;
564
- let j;
565
- let slotNameAttr;
566
- let nodeType;
567
- for (i = 0, ilen = childNodes.length; i < ilen; i++) {
568
- childNode = childNodes[i];
569
- if (childNode.nodeType === 1 /* ElementNode */) {
570
- if (childNode['s-sr']) {
571
- // this is a slot fallback node
572
- // get the slot name for this slot reference node
573
- slotNameAttr = childNode['s-sn'];
574
- // by default always show a fallback slot node
575
- // then hide it if there are other slots in the light dom
576
- childNode.hidden = false;
577
- for (j = 0; j < ilen; j++) {
578
- nodeType = childNodes[j].nodeType;
579
- if (childNodes[j]['s-hn'] !== childNode['s-hn'] || slotNameAttr !== '') {
580
- // this sibling node is from a different component OR is a named fallback slot node
581
- if (nodeType === 1 /* ElementNode */ && slotNameAttr === childNodes[j].getAttribute('slot')) {
582
- childNode.hidden = true;
583
- break;
584
- }
585
- }
586
- else {
587
- // this is a default fallback slot node
588
- // any element or text node (with content)
589
- // should hide the default fallback slot node
590
- if (nodeType === 1 /* ElementNode */ ||
591
- (nodeType === 3 /* TextNode */ && childNodes[j].textContent.trim() !== '')) {
592
- childNode.hidden = true;
593
- break;
594
- }
595
- }
596
- }
597
- }
598
- // keep drilling down
599
- updateFallbackSlotVisibility(childNode);
600
- }
601
- }
602
- };
603
- const relocateNodes = [];
604
- const relocateSlotContent = (elm) => {
605
- // tslint:disable-next-line: prefer-const
606
- let childNode;
607
- let node;
608
- let hostContentNodes;
609
- let slotNameAttr;
610
- let relocateNodeData;
611
- let j;
612
- let i = 0;
613
- let childNodes = elm.childNodes;
614
- let ilen = childNodes.length;
615
- for (; i < ilen; i++) {
616
- childNode = childNodes[i];
617
- if (childNode['s-sr'] && (node = childNode['s-cr']) && node.parentNode) {
618
- // first got the content reference comment node
619
- // then we got it's parent, which is where all the host content is in now
620
- hostContentNodes = node.parentNode.childNodes;
621
- slotNameAttr = childNode['s-sn'];
622
- for (j = hostContentNodes.length - 1; j >= 0; j--) {
623
- node = hostContentNodes[j];
624
- if (!node['s-cn'] && !node['s-nr'] && node['s-hn'] !== childNode['s-hn']) {
625
- // let's do some relocating to its new home
626
- // but never relocate a content reference node
627
- // that is suppose to always represent the original content location
628
- if (isNodeLocatedInSlot(node, slotNameAttr)) {
629
- // it's possible we've already decided to relocate this node
630
- relocateNodeData = relocateNodes.find((r) => r.$nodeToRelocate$ === node);
631
- // made some changes to slots
632
- // let's make sure we also double check
633
- // fallbacks are correctly hidden or shown
634
- checkSlotFallbackVisibility = true;
635
- node['s-sn'] = node['s-sn'] || slotNameAttr;
636
- if (relocateNodeData) {
637
- // previously we never found a slot home for this node
638
- // but turns out we did, so let's remember it now
639
- relocateNodeData.$slotRefNode$ = childNode;
640
- }
641
- else {
642
- // add to our list of nodes to relocate
643
- relocateNodes.push({
644
- $slotRefNode$: childNode,
645
- $nodeToRelocate$: node,
646
- });
647
- }
648
- if (node['s-sr']) {
649
- relocateNodes.map((relocateNode) => {
650
- if (isNodeLocatedInSlot(relocateNode.$nodeToRelocate$, node['s-sn'])) {
651
- relocateNodeData = relocateNodes.find((r) => r.$nodeToRelocate$ === node);
652
- if (relocateNodeData && !relocateNode.$slotRefNode$) {
653
- relocateNode.$slotRefNode$ = relocateNodeData.$slotRefNode$;
654
- }
655
- }
656
- });
657
- }
658
- }
659
- else if (!relocateNodes.some((r) => r.$nodeToRelocate$ === node)) {
660
- // so far this element does not have a slot home, not setting slotRefNode on purpose
661
- // if we never find a home for this element then we'll need to hide it
662
- relocateNodes.push({
663
- $nodeToRelocate$: node,
664
- });
665
- }
666
- }
667
- }
668
- }
669
- if (childNode.nodeType === 1 /* ElementNode */) {
670
- relocateSlotContent(childNode);
671
- }
672
- }
673
- };
674
- const isNodeLocatedInSlot = (nodeToRelocate, slotNameAttr) => {
675
- if (nodeToRelocate.nodeType === 1 /* ElementNode */) {
676
- if (nodeToRelocate.getAttribute('slot') === null && slotNameAttr === '') {
677
- return true;
678
- }
679
- if (nodeToRelocate.getAttribute('slot') === slotNameAttr) {
680
- return true;
681
- }
682
- return false;
683
- }
684
- if (nodeToRelocate['s-sn'] === slotNameAttr) {
685
- return true;
686
- }
687
- return slotNameAttr === '';
688
- };
689
450
  const renderVdom = (hostRef, renderFnResults) => {
690
451
  const hostElm = hostRef.$hostElement$;
691
452
  const cmpMeta = hostRef.$cmpMeta$;
692
453
  const oldVNode = hostRef.$vnode$ || newVNode(null, null);
693
454
  const rootVnode = isHost(renderFnResults) ? renderFnResults : h(null, null, renderFnResults);
694
455
  hostTagName = hostElm.tagName;
456
+ if (cmpMeta.$attrsToReflect$) {
457
+ rootVnode.$attrs$ = rootVnode.$attrs$ || {};
458
+ cmpMeta.$attrsToReflect$.map(([propName, attribute]) => (rootVnode.$attrs$[attribute] = hostElm[propName]));
459
+ }
695
460
  rootVnode.$tag$ = null;
696
461
  rootVnode.$flags$ |= 4 /* isHost */;
697
462
  hostRef.$vnode$ = rootVnode;
698
- rootVnode.$elm$ = oldVNode.$elm$ = (hostElm);
463
+ rootVnode.$elm$ = oldVNode.$elm$ = (hostElm.shadowRoot || hostElm );
699
464
  {
700
- contentRef = hostElm['s-cr'];
701
- useNativeShadowDom = (cmpMeta.$flags$ & 1 /* shadowDomEncapsulation */) !== 0;
702
- // always reset
703
- checkSlotFallbackVisibility = false;
465
+ scopeId = hostElm['s-sc'];
704
466
  }
705
467
  // synchronous patch
706
468
  patch(oldVNode, rootVnode);
707
- {
708
- // while we're moving nodes around existing nodes, temporarily disable
709
- // the disconnectCallback from working
710
- plt.$flags$ |= 1 /* isTmpDisconnected */;
711
- if (checkSlotRelocate) {
712
- relocateSlotContent(rootVnode.$elm$);
713
- let relocateData;
714
- let nodeToRelocate;
715
- let orgLocationNode;
716
- let parentNodeRef;
717
- let insertBeforeNode;
718
- let refNode;
719
- let i = 0;
720
- for (; i < relocateNodes.length; i++) {
721
- relocateData = relocateNodes[i];
722
- nodeToRelocate = relocateData.$nodeToRelocate$;
723
- if (!nodeToRelocate['s-ol']) {
724
- // add a reference node marking this node's original location
725
- // keep a reference to this node for later lookups
726
- orgLocationNode =
727
- doc.createTextNode('');
728
- orgLocationNode['s-nr'] = nodeToRelocate;
729
- nodeToRelocate.parentNode.insertBefore((nodeToRelocate['s-ol'] = orgLocationNode), nodeToRelocate);
730
- }
731
- }
732
- for (i = 0; i < relocateNodes.length; i++) {
733
- relocateData = relocateNodes[i];
734
- nodeToRelocate = relocateData.$nodeToRelocate$;
735
- if (relocateData.$slotRefNode$) {
736
- // by default we're just going to insert it directly
737
- // after the slot reference node
738
- parentNodeRef = relocateData.$slotRefNode$.parentNode;
739
- insertBeforeNode = relocateData.$slotRefNode$.nextSibling;
740
- orgLocationNode = nodeToRelocate['s-ol'];
741
- while ((orgLocationNode = orgLocationNode.previousSibling)) {
742
- refNode = orgLocationNode['s-nr'];
743
- if (refNode && refNode['s-sn'] === nodeToRelocate['s-sn'] && parentNodeRef === refNode.parentNode) {
744
- refNode = refNode.nextSibling;
745
- if (!refNode || !refNode['s-nr']) {
746
- insertBeforeNode = refNode;
747
- break;
748
- }
749
- }
750
- }
751
- if ((!insertBeforeNode && parentNodeRef !== nodeToRelocate.parentNode) ||
752
- nodeToRelocate.nextSibling !== insertBeforeNode) {
753
- // we've checked that it's worth while to relocate
754
- // since that the node to relocate
755
- // has a different next sibling or parent relocated
756
- if (nodeToRelocate !== insertBeforeNode) {
757
- if (!nodeToRelocate['s-hn'] && nodeToRelocate['s-ol']) {
758
- // probably a component in the index.html that doesn't have it's hostname set
759
- nodeToRelocate['s-hn'] = nodeToRelocate['s-ol'].parentNode.nodeName;
760
- }
761
- // add it back to the dom but in its new home
762
- parentNodeRef.insertBefore(nodeToRelocate, insertBeforeNode);
763
- }
764
- }
765
- }
766
- else {
767
- // this node doesn't have a slot home to go to, so let's hide it
768
- if (nodeToRelocate.nodeType === 1 /* ElementNode */) {
769
- nodeToRelocate.hidden = true;
770
- }
771
- }
772
- }
773
- }
774
- if (checkSlotFallbackVisibility) {
775
- updateFallbackSlotVisibility(rootVnode.$elm$);
776
- }
777
- // done moving nodes around
778
- // allow the disconnect callback to work again
779
- plt.$flags$ &= ~1 /* isTmpDisconnected */;
780
- // always reset
781
- relocateNodes.length = 0;
782
- }
783
469
  };
784
470
  /**
785
471
  * Helper function to create & dispatch a custom Event on a provided target
@@ -951,9 +637,37 @@ const then = (promise, thenFn) => {
951
637
  };
952
638
  const addHydratedFlag = (elm) => elm.classList.add('hydrated')
953
639
  ;
640
+ /**
641
+ * Parse a new property value for a given property type.
642
+ *
643
+ * While the prop value can reasonably be expected to be of `any` type as far as TypeScript's type checker is concerned,
644
+ * it is not safe to assume that the string returned by evaluating `typeof propValue` matches:
645
+ * 1. `any`, the type given to `propValue` in the function signature
646
+ * 2. the type stored from `propType`.
647
+ *
648
+ * This function provides the capability to parse/coerce a property's value to potentially any other JavaScript type.
649
+ *
650
+ * Property values represented in TSX preserve their type information. In the example below, the number 0 is passed to
651
+ * a component. This `propValue` will preserve its type information (`typeof propValue === 'number'`). Note that is
652
+ * based on the type of the value being passed in, not the type declared of the class member decorated with `@Prop`.
653
+ * ```tsx
654
+ * <my-cmp prop-val={0}></my-cmp>
655
+ * ```
656
+ *
657
+ * HTML prop values on the other hand, will always a string
658
+ *
659
+ * @param propValue the new value to coerce to some type
660
+ * @param propType the type of the prop, expressed as a binary number
661
+ * @returns the parsed/coerced value
662
+ */
954
663
  const parsePropertyValue = (propValue, propType) => {
955
664
  // ensure this value is of the correct prop type
956
665
  if (propValue != null && !isComplexType(propValue)) {
666
+ if (propType & 4 /* Boolean */) {
667
+ // per the HTML spec, any string value means it is a boolean true value
668
+ // but we'll cheat here and say that the string "false" is the boolean false
669
+ return propValue === 'false' ? false : propValue === '' || !!propValue;
670
+ }
957
671
  // redundant return here for better minification
958
672
  return propValue;
959
673
  }
@@ -968,7 +682,7 @@ const setValue = (ref, propName, newVal, cmpMeta) => {
968
682
  const oldVal = hostRef.$instanceValues$.get(propName);
969
683
  const flags = hostRef.$flags$;
970
684
  const instance = hostRef.$lazyInstance$ ;
971
- newVal = parsePropertyValue(newVal);
685
+ newVal = parsePropertyValue(newVal, cmpMeta.$members$[propName][0]);
972
686
  if ((!(flags & 8 /* isConstructingInstance */) || oldVal === undefined) && newVal !== oldVal) {
973
687
  // gadzooks! the property's value has changed!!
974
688
  // set our new value!
@@ -1000,13 +714,79 @@ const proxyComponent = (Cstr, cmpMeta, flags) => {
1000
714
  },
1001
715
  set(newValue) {
1002
716
  // proxyComponent, set value
1003
- setValue(this, memberName, newValue);
717
+ setValue(this, memberName, newValue, cmpMeta);
1004
718
  },
1005
719
  configurable: true,
1006
720
  enumerable: true,
1007
721
  });
1008
722
  }
1009
723
  });
724
+ if ((flags & 1 /* isElementConstructor */)) {
725
+ const attrNameToPropName = new Map();
726
+ prototype.attributeChangedCallback = function (attrName, _oldValue, newValue) {
727
+ plt.jmp(() => {
728
+ const propName = attrNameToPropName.get(attrName);
729
+ // In a web component lifecycle the attributeChangedCallback runs prior to connectedCallback
730
+ // in the case where an attribute was set inline.
731
+ // ```html
732
+ // <my-component some-attribute="some-value"></my-component>
733
+ // ```
734
+ //
735
+ // There is an edge case where a developer sets the attribute inline on a custom element and then
736
+ // programmatically changes it before it has been upgraded as shown below:
737
+ //
738
+ // ```html
739
+ // <!-- this component has _not_ been upgraded yet -->
740
+ // <my-component id="test" some-attribute="some-value"></my-component>
741
+ // <script>
742
+ // // grab non-upgraded component
743
+ // el = document.querySelector("#test");
744
+ // el.someAttribute = "another-value";
745
+ // // upgrade component
746
+ // customElements.define('my-component', MyComponent);
747
+ // </script>
748
+ // ```
749
+ // In this case if we do not unshadow here and use the value of the shadowing property, attributeChangedCallback
750
+ // will be called with `newValue = "some-value"` and will set the shadowed property (this.someAttribute = "another-value")
751
+ // to the value that was set inline i.e. "some-value" from above example. When
752
+ // the connectedCallback attempts to unshadow it will use "some-value" as the initial value rather than "another-value"
753
+ //
754
+ // The case where the attribute was NOT set inline but was not set programmatically shall be handled/unshadowed
755
+ // by connectedCallback as this attributeChangedCallback will not fire.
756
+ //
757
+ // https://developers.google.com/web/fundamentals/web-components/best-practices#lazy-properties
758
+ //
759
+ // TODO(STENCIL-16) we should think about whether or not we actually want to be reflecting the attributes to
760
+ // properties here given that this goes against best practices outlined here
761
+ // https://developers.google.com/web/fundamentals/web-components/best-practices#avoid-reentrancy
762
+ if (this.hasOwnProperty(propName)) {
763
+ newValue = this[propName];
764
+ delete this[propName];
765
+ }
766
+ else if (prototype.hasOwnProperty(propName) &&
767
+ typeof this[propName] === 'number' &&
768
+ this[propName] == newValue) {
769
+ // if the propName exists on the prototype of `Cstr`, this update may be a result of Stencil using native
770
+ // APIs to reflect props as attributes. Calls to `setAttribute(someElement, propName)` will result in
771
+ // `propName` to be converted to a `DOMString`, which may not be what we want for other primitive props.
772
+ return;
773
+ }
774
+ this[propName] = newValue === null && typeof this[propName] === 'boolean' ? false : newValue;
775
+ });
776
+ };
777
+ // create an array of attributes to observe
778
+ // and also create a map of html attribute name to js property name
779
+ Cstr.observedAttributes = members
780
+ .filter(([_, m]) => m[0] & 15 /* HasAttribute */) // filter to only keep props that should match attributes
781
+ .map(([propName, m]) => {
782
+ const attrName = m[1] || propName;
783
+ attrNameToPropName.set(attrName, propName);
784
+ if (m[0] & 512 /* ReflectAttr */) {
785
+ cmpMeta.$attrsToReflect$.push([propName, attrName]);
786
+ }
787
+ return attrName;
788
+ });
789
+ }
1010
790
  }
1011
791
  return Cstr;
1012
792
  };
@@ -1087,15 +867,6 @@ const connectedCallback = (elm) => {
1087
867
  if (!(hostRef.$flags$ & 1 /* hasConnected */)) {
1088
868
  // first time this component has connected
1089
869
  hostRef.$flags$ |= 1 /* hasConnected */;
1090
- {
1091
- // initUpdate
1092
- // if the slot polyfill is required we'll need to put some nodes
1093
- // in here to act as original content anchors as we move nodes around
1094
- // host element has been connected to the DOM
1095
- if ((cmpMeta.$flags$ & (4 /* hasSlotRelocation */ | 8 /* needsShadowDomShim */))) {
1096
- setContentReference(elm);
1097
- }
1098
- }
1099
870
  {
1100
871
  // find the first ancestor component (if there is one) and register
1101
872
  // this component as one of the actively loading child components for its ancestor
@@ -1111,6 +882,17 @@ const connectedCallback = (elm) => {
1111
882
  }
1112
883
  }
1113
884
  }
885
+ // Lazy properties
886
+ // https://developers.google.com/web/fundamentals/web-components/best-practices#lazy-properties
887
+ if (cmpMeta.$members$) {
888
+ Object.entries(cmpMeta.$members$).map(([memberName, [memberFlags]]) => {
889
+ if (memberFlags & 31 /* Prop */ && elm.hasOwnProperty(memberName)) {
890
+ const value = elm[memberName];
891
+ delete elm[memberName];
892
+ elm[memberName] = value;
893
+ }
894
+ });
895
+ }
1114
896
  {
1115
897
  initializeComponent(elm, hostRef, cmpMeta);
1116
898
  }
@@ -1124,17 +906,6 @@ const connectedCallback = (elm) => {
1124
906
  endConnected();
1125
907
  }
1126
908
  };
1127
- const setContentReference = (elm) => {
1128
- // only required when we're NOT using native shadow dom (slot)
1129
- // or this browser doesn't support native shadow dom
1130
- // and this host element was NOT created with SSR
1131
- // let's pick out the inner content for slot projection
1132
- // create a node to represent where the original
1133
- // content was first placed, which is useful later on
1134
- const contentRefElm = (elm['s-cr'] = doc.createComment(''));
1135
- contentRefElm['s-cn'] = true;
1136
- elm.insertBefore(contentRefElm, elm.firstChild);
1137
- };
1138
909
  const disconnectedCallback = (elm) => {
1139
910
  if ((plt.$flags$ & 1 /* isTmpDisconnected */) === 0) {
1140
911
  const hostRef = getHostRef(elm);
@@ -1173,6 +944,9 @@ const bootstrapLazy = (lazyBundles, options = {}) => {
1173
944
  {
1174
945
  cmpMeta.$listeners$ = compactMeta[3];
1175
946
  }
947
+ {
948
+ cmpMeta.$attrsToReflect$ = [];
949
+ }
1176
950
  const tagName = cmpMeta.$tagName$;
1177
951
  const HostElement = class extends HTMLElement {
1178
952
  // StencilLazyHost
@@ -1181,6 +955,17 @@ const bootstrapLazy = (lazyBundles, options = {}) => {
1181
955
  super(self);
1182
956
  self = this;
1183
957
  registerHost(self, cmpMeta);
958
+ if (cmpMeta.$flags$ & 1 /* shadowDomEncapsulation */) {
959
+ // this component is using shadow dom
960
+ // and this browser supports shadow dom
961
+ // add the read-only property "shadowRoot" to the host element
962
+ // adding the shadow root build conditionals to minimize runtime
963
+ {
964
+ {
965
+ self.attachShadow({ mode: 'open' });
966
+ }
967
+ }
968
+ }
1184
969
  }
1185
970
  connectedCallback() {
1186
971
  if (appLoadFallback) {