lightning-base-components 1.22.1-alpha → 1.22.3-alpha

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 (127) hide show
  1. package/README.md +2 -0
  2. package/metadata/raptor.json +38 -2
  3. package/package.json +12 -1
  4. package/scopedImports/@salesforce-label-LightningRecordPicker.actionIconAlternativeText.js +1 -0
  5. package/src/lightning/accordionSection/button.slds.css +8 -0
  6. package/src/lightning/ariaObserver/ariaObserver.js +1 -1
  7. package/src/lightning/baseCombobox/baseCombobox.html +1 -1
  8. package/src/lightning/baseCombobox/baseCombobox.js +1 -0
  9. package/src/lightning/baseCombobox/dropdown.slds.css +7 -7
  10. package/src/lightning/baseComboboxItem/card.lbc.native.css +1 -0
  11. package/src/lightning/baseComboboxItem/inline.lbc.native.css +1 -0
  12. package/src/lightning/button/button.slds.css +8 -0
  13. package/src/lightning/buttonIcon/button-icon.slds.css +8 -0
  14. package/src/lightning/buttonIcon/buttonIcon.js +29 -26
  15. package/src/lightning/buttonIconStateful/button-icon.slds.css +8 -0
  16. package/src/lightning/buttonIconStateful/button.slds.css +8 -0
  17. package/src/lightning/buttonMenu/button-icon.slds.css +8 -0
  18. package/src/lightning/buttonMenu/button.slds.css +8 -0
  19. package/src/lightning/buttonMenu/dropdown.slds.css +7 -7
  20. package/src/lightning/buttonStateful/button.slds.css +8 -0
  21. package/src/lightning/calendar/calendar.lbc.native.css +1 -0
  22. package/src/lightning/calendar/dropdown.slds.css +7 -7
  23. package/src/lightning/checkboxGroup/checkboxGroup.js +21 -10
  24. package/src/lightning/checkboxGroup/checkboxGroup.js-meta.xml +3 -0
  25. package/src/lightning/colorPickerPanel/colorPickerPanel.js +1 -11
  26. package/src/lightning/combobox/combobox.html +1 -1
  27. package/src/lightning/datatable/__docs__/datatable.md +10 -5
  28. package/src/lightning/datatable/autoWidthStrategy.js +32 -44
  29. package/src/lightning/datatable/columnResizer.js +3 -2
  30. package/src/lightning/datatable/columnWidthManager.js +16 -10
  31. package/src/lightning/datatable/columns.js +4 -1
  32. package/src/lightning/datatable/datatable.js +108 -46
  33. package/src/lightning/datatable/infiniteLoading.js +8 -20
  34. package/src/lightning/datatable/inlineEdit.js +11 -6
  35. package/src/lightning/datatable/keyboard.js +58 -55
  36. package/src/lightning/datatable/resizeObserver.js +10 -5
  37. package/src/lightning/datatable/rows.js +3 -3
  38. package/src/lightning/datatable/rowsInlining.js +5 -4
  39. package/src/lightning/datatable/state.js +1 -2
  40. package/src/lightning/datatable/templates/div/div.html +150 -43
  41. package/src/lightning/datatable/templates/div/div.lbc.synthetic.css +8 -7
  42. package/src/lightning/datatable/templates/table/table.html +153 -46
  43. package/src/lightning/datatable/utils.js +10 -4
  44. package/src/lightning/datatable/virtualization.js +6 -4
  45. package/src/lightning/datatable/wrapText.js +16 -15
  46. package/src/lightning/groupedCombobox/groupedCombobox.js +21 -28
  47. package/src/lightning/helptext/button-icon.slds.css +8 -0
  48. package/src/lightning/helptext/helptext.html +2 -1
  49. package/src/lightning/helptext/helptext.js +0 -12
  50. package/src/lightning/input/input.html +0 -1
  51. package/src/lightning/interactiveDialogBase/button.slds.css +8 -0
  52. package/src/lightning/modal/__docs__/modal.md +2 -0
  53. package/src/lightning/modalBase/modalBase.html +2 -0
  54. package/src/lightning/modalBase/modalBase.js +30 -31
  55. package/src/lightning/modalBody/modalBody.html +1 -0
  56. package/src/lightning/modalBody/modalBody.js +3 -0
  57. package/src/lightning/modalFooter/modalFooter.html +5 -1
  58. package/src/lightning/modalFooter/modalFooter.js +3 -0
  59. package/src/lightning/modalHeader/modalHeader.html +4 -1
  60. package/src/lightning/modalHeader/modalHeader.js +3 -0
  61. package/src/lightning/overlayManager/overlayManager.js +1 -1
  62. package/src/lightning/pillContainer/button.slds.css +8 -0
  63. package/src/lightning/positionLibrary/elementProxy.js +13 -6
  64. package/src/lightning/positionLibrary/util.js +20 -2
  65. package/src/lightning/primitiveBubble/primitiveBubble.js +9 -4
  66. package/src/lightning/primitiveCellActions/primitiveCellActions.html +1 -0
  67. package/src/lightning/primitiveCellActions/primitiveCellActions.js +3 -5
  68. package/src/lightning/primitiveCellButton/primitiveCellButton.html +2 -0
  69. package/src/lightning/primitiveCellButton/primitiveCellButton.js +3 -5
  70. package/src/lightning/primitiveCellCheckbox/checkbox.html +3 -2
  71. package/src/lightning/primitiveCellCheckbox/primitiveCellCheckbox.js +6 -3
  72. package/src/lightning/primitiveCellCheckbox/radio.html +5 -4
  73. package/src/lightning/primitiveCellEditableButton/primitiveCellEditableButton.html +1 -1
  74. package/src/lightning/primitiveCellEditableButton/primitiveCellEditableButton.js +1 -1
  75. package/src/lightning/primitiveCellFactory/bareCustomCell.html +1 -0
  76. package/src/lightning/primitiveCellFactory/cellWithStandardLayout.html +1 -0
  77. package/src/lightning/primitiveCellFactory/primitiveCellFactory.js +4 -6
  78. package/src/lightning/primitiveColumnSorter/primitiveColumnSorter.html +1 -0
  79. package/src/lightning/primitiveColumnSorter/primitiveColumnSorter.js +1 -1
  80. package/src/lightning/primitiveDatatableIeditPanel/primitiveDatatableIeditPanel.html +3 -1
  81. package/src/lightning/primitiveDatatableIeditPanel/primitiveDatatableIeditPanel.js +3 -3
  82. package/src/lightning/primitiveDatatableStatusBar/primitiveDatatableStatusBar.html +1 -0
  83. package/src/lightning/primitiveDatatableStatusBar/primitiveDatatableStatusBar.js +1 -3
  84. package/src/lightning/primitiveDatatableTooltip/primitiveDatatableTooltip.html +1 -0
  85. package/src/lightning/primitiveDatatableTooltip/primitiveDatatableTooltip.js +1 -1
  86. package/src/lightning/primitiveDatatableTooltipBubble/primitiveDatatableTooltipBubble.html +1 -1
  87. package/src/lightning/primitiveDatatableTooltipBubble/primitiveDatatableTooltipBubble.js +1 -1
  88. package/src/lightning/primitiveHeaderActions/primitiveHeaderActions.html +2 -0
  89. package/src/lightning/primitiveHeaderActions/primitiveHeaderActions.js +2 -4
  90. package/src/lightning/primitiveHeaderFactory/nonsortableHeader.html +8 -3
  91. package/src/lightning/primitiveHeaderFactory/primitiveHeaderFactory.js +43 -13
  92. package/src/lightning/primitiveHeaderFactory/selectableHeader.html +3 -2
  93. package/src/lightning/primitiveHeaderFactory/sortableHeader.html +8 -3
  94. package/src/lightning/primitiveHeaderFactory/sortingMenuHeader.html +1 -1
  95. package/src/lightning/primitiveIcon/primitiveIcon.css +0 -1
  96. package/src/lightning/primitiveInputFile/button.slds.css +8 -0
  97. package/src/lightning/primitiveResizeHandler/primitiveResizeHandler.html +4 -2
  98. package/src/lightning/primitiveResizeHandler/primitiveResizeHandler.js +2 -2
  99. package/src/lightning/primitiveTreegridCellToggle/primitiveTreegridCellToggle.html +1 -1
  100. package/src/lightning/primitiveTreegridCellToggle/primitiveTreegridCellToggle.js +1 -1
  101. package/src/lightning/progressIndicator/progressIndicator.css +1 -1
  102. package/src/lightning/progressIndicator/progressIndicator.js +14 -6
  103. package/src/lightning/progressIndicator/progressIndicator.js-meta.xml +3 -0
  104. package/src/lightning/progressIndicator/progressIndicator.lbc.native.css +2 -0
  105. package/src/lightning/progressStep/__examples__/basic/basic.html +11 -0
  106. package/src/lightning/progressStep/__examples__/basic/basic.js +3 -0
  107. package/src/lightning/progressStep/__examples__/shaded/shaded.html +11 -0
  108. package/src/lightning/progressStep/__examples__/shaded/shaded.js +3 -0
  109. package/src/lightning/progressStep/base.html +2 -1
  110. package/src/lightning/progressStep/progressStep.css +1 -0
  111. package/src/lightning/progressStep/progressStep.js +40 -29
  112. package/src/lightning/progressStep/progressStep.js-meta.xml +3 -0
  113. package/src/lightning/progressStep/progressStep.lbc.native.css +3 -0
  114. package/src/lightning/sldsCommon/sldsCommon.css +1 -1
  115. package/src/lightning/sldsUtilsThemes/sldsUtilsThemes.css +6 -4
  116. package/src/lightning/tabBar/tab-bar.slds.css +17 -3
  117. package/src/lightning/tile/mediaTile.css +2 -0
  118. package/src/lightning/tile/standardTile.css +2 -1
  119. package/src/lightning/tile/tile.js +5 -2
  120. package/src/lightning/tile/tile.js-meta.xml +3 -0
  121. package/src/lightning/tile/tile.lbc.native.css +4 -0
  122. package/src/lightning/toast/button-icon.slds.css +8 -0
  123. package/src/lightning/tooltipLibrary/tooltipLibrary.js +15 -4
  124. package/src/lightning/utilsPrivate/utilsPrivate.js +4 -4
  125. package/src/lightning/verticalNavigationOverflow/button.slds.css +8 -0
  126. package/src/lightning/primitiveIcon/primitiveIcon.lbc.synthetic.css +0 -9
  127. /package/src/lightning/tile/{standardTile.lbc.synthetic.css → tile.lbc.synthetic.css} +0 -0
@@ -411,6 +411,8 @@ Let's see this workflow in action. In this example, we'll create a button (`ligh
411
411
 
412
412
  Because `lightning-navigation` requires you to pass in a `recordId` to construct a page reference, we need to pass the record's data out of `LightningModal`, and then use the methods provided by `lightning-navigation`. With modal's limitations for event bubbling to the Aura layer, we can't just wrap the button or treegrid with `lightning-navigation`. We need to pull that data up to the topmost LWC component, where the `LightningModal` `.open()` is called, for our Aura wrapper to handle the navigation.
413
413
 
414
+ However, in [Aura-based Experience Builder sites](https://developer.salesforce.com/docs/atlas.en-us.communities_dev.meta/communities_dev/communities_dev_basics_templates.htm), the `NavigationMixin` event can reach the Aura layer without being affected by the modal's limitations.
415
+
414
416
  So, we `import` the `lightning-navigation` component into the topmost LWC component that sits within the Aura layer by passing the data through `LightningModal`'s close method, `this.close({ data })`. Then the parent LWC component invokes the methods provided by `lightning-navigation`, which handles the navigation away from the page after the modal exits. From a UX perspective, this also lets us close the modal first, since `lightning-navigation` takes the user away from the current page.
415
417
 
416
418
  Note that this sample code isn't fully functional. We're only showing the relevant code that makes the `lightning-navigation` use case work with `LightningModal`.
@@ -18,6 +18,8 @@
18
18
  onprivatemodalfooterregister={handleFooterRegister}
19
19
  onprivateclose={handlePrivateClose}
20
20
  onprivatedisableclosebutton={handlePrivateDisableCloseButton}
21
+ onfocusin={handleModalBaseFocusin}
22
+ onprivatelightningmodallastfocus={handleLastFocusedElem}
21
23
  data-modal
22
24
  >
23
25
  <template if:true={showAriaDescribedBy}>
@@ -19,7 +19,7 @@ import {
19
19
  import closeButtonAltText from '@salesforce/label/LightningModalBase.cancelandclose';
20
20
  import disableCloseBtnMessage from '@salesforce/label/LightningModalBase.waitstate';
21
21
  import AriaObserver from 'lightning/ariaObserver';
22
- import { isLwcModalActive } from 'lightning/overlayManager';
22
+ import { modalFocusinEventHandler } from 'lightning/modalUtils';
23
23
 
24
24
  const DEBOUNCE_RESIZE = 300;
25
25
  const SMALL_SCREEN_SIZE = 480;
@@ -27,7 +27,6 @@ const SIZE_SMALL = 'small';
27
27
  const SIZE_MEDIUM = 'medium';
28
28
  const SIZE_LARGE = 'large';
29
29
  const SIZE_FULL = 'full';
30
- const MODAL_CONTAINER = 'lightning-overlay-container';
31
30
 
32
31
  export default class LightningModalBase extends LightningShadowBaseClass {
33
32
  // this is visible in DOM, changed from 'lightning-modal-base'
@@ -69,10 +68,9 @@ export default class LightningModalBase extends LightningShadowBaseClass {
69
68
  portraitMatchMedia = null;
70
69
  screenOrientationChangeHandler = null;
71
70
 
72
- // state utilized when performing keyboard Tab/Shift-Tab interactions
71
+ // state utilized when performing keyboard focus trap
73
72
  focusinEventBound = false;
74
- focusinEventHandler = null;
75
- lastFocussedElementOnModal = null;
73
+ lastFocusedElement = null;
76
74
 
77
75
  // modalFooter, child
78
76
  footerRegistered = false;
@@ -468,27 +466,6 @@ export default class LightningModalBase extends LightningShadowBaseClass {
468
466
  }
469
467
  }
470
468
 
471
- /**
472
- * Handler for 'focusin' events, responsible for trapping user focus to open Modal
473
- * @param e - Event
474
- */
475
- handleFocusinEvents(e) {
476
- // eslint-disable-next-line @lwc/lwc/no-async-operation
477
- requestAnimationFrame(() => {
478
- // is current active (open) modal is lwc
479
- if (isLwcModalActive() && this.isModalOpen) {
480
- const isTargetRelatedToModal =
481
- e.target?.closest(MODAL_CONTAINER) ||
482
- e.relatedTarget?.closest(MODAL_CONTAINER);
483
- if (isTargetRelatedToModal) {
484
- this.lastFocussedElementOnModal = getElementWithFocus();
485
- } else {
486
- returnFocusToElement(this.lastFocussedElementOnModal);
487
- }
488
- }
489
- });
490
- }
491
-
492
469
  /**
493
470
  * Opening the modal involves first performing necessary steps to
494
471
  * prepare for when the modal closes
@@ -794,7 +771,11 @@ export default class LightningModalBase extends LightningShadowBaseClass {
794
771
  : fallbackFocusElem;
795
772
 
796
773
  if (focusElem !== null) {
797
- focusElem.focus();
774
+ this.lastFocusedElement = focusElem;
775
+ // eslint-disable-next-line @lwc/lwc/no-async-operation
776
+ requestAnimationFrame(() => {
777
+ focusElem.focus();
778
+ });
798
779
  this.autoFocusCompletedOnce = true;
799
780
  } else {
800
781
  // Should never happen since outerModalElem always present
@@ -1178,8 +1159,10 @@ export default class LightningModalBase extends LightningShadowBaseClass {
1178
1159
  addFocusinEventListener() {
1179
1160
  if (!this.focusinEventBound) {
1180
1161
  this.focusinEventBound = true;
1181
- this.focusinEventHandler = this.handleFocusinEvents.bind(this);
1182
- window.addEventListener('focusin', this.focusinEventHandler);
1162
+ window.addEventListener(
1163
+ 'focusin',
1164
+ modalFocusinEventHandler.bind(this)
1165
+ );
1183
1166
  }
1184
1167
  }
1185
1168
 
@@ -1192,11 +1175,27 @@ export default class LightningModalBase extends LightningShadowBaseClass {
1192
1175
  removeFocusinEventListener() {
1193
1176
  if (this.focusinEventBound) {
1194
1177
  this.focusinEventBound = false;
1195
- window.removeEventListener('focusin', this.focusinEventHandler);
1196
- this.focusinEventHandler = null;
1178
+ window.removeEventListener(
1179
+ 'focusin',
1180
+ modalFocusinEventHandler.bind(this)
1181
+ );
1197
1182
  }
1198
1183
  }
1199
1184
 
1185
+ handleModalBaseFocusin = modalFocusinEventHandler.bind(this);
1186
+
1187
+ handleLastFocusedElem(e) {
1188
+ if (!(e.detail && e.detail[secure])) {
1189
+ console.error(
1190
+ 'Invalid access to onprivatelightningmodallastfocus event'
1191
+ );
1192
+ return;
1193
+ }
1194
+ e.stopPropagation();
1195
+
1196
+ this.lastFocusedElement = e.detail.privatelightningmodallastfocus;
1197
+ }
1198
+
1200
1199
  /**
1201
1200
  * determine if the current screen is less than SMALL_SCREEN_SIZE
1202
1201
  * for Modal, screen size detection is simplified to what's required
@@ -5,6 +5,7 @@
5
5
  part="modal-body"
6
6
  data-content-container
7
7
  onprivatescrollablecontainer={handleScrollableContainerRepositionEvent}
8
+ onfocusin={handleModalBodyFocusin}
8
9
  >
9
10
  <slot
10
11
  data-default-slot
@@ -2,6 +2,7 @@ import LightningShadowBaseClass from 'lightning/shadowBaseClassPrivate';
2
2
  import { classSet } from 'lightning/utils';
3
3
  import { getRealDOMId } from 'lightning/utilsPrivate';
4
4
  import { findAllTabbableElements, filterTooltips } from 'lightning/focusUtils';
5
+ import { modalFocusinEventHandler } from 'lightning/modalUtils';
5
6
 
6
7
  /**
7
8
  * The modal body component to display main content area in lightning modal.
@@ -294,6 +295,8 @@ export default class LightningModalBody extends LightningShadowBaseClass {
294
295
  this.dispatchEvent(evtRegister);
295
296
  }
296
297
 
298
+ handleModalBodyFocusin = modalFocusinEventHandler.bind(this);
299
+
297
300
  /**
298
301
  * When modal body is being created, initialize
299
302
  * private tracked modal body state
@@ -1,5 +1,9 @@
1
1
  <template>
2
- <div class={footerCssClasses} part="modal-footer">
2
+ <div
3
+ class={footerCssClasses}
4
+ part="modal-footer"
5
+ onfocusin={handleModalFooterFocusin}
6
+ >
3
7
  <slot
4
8
  data-footer-slot
5
9
  onslotchange={handleDefaultSlotChange}
@@ -1,5 +1,6 @@
1
1
  import LightningShadowBaseClass from 'lightning/shadowBaseClassPrivate';
2
2
  import { classSet } from 'lightning/utils';
3
+ import { modalFocusinEventHandler } from 'lightning/modalUtils';
3
4
 
4
5
  // SLDS Modal Footer classes
5
6
  const footerClass = 'slds-modal__footer';
@@ -104,6 +105,8 @@ export default class LightningModalFooter extends LightningShadowBaseClass {
104
105
  this.dispatchEvent(evtRegister);
105
106
  }
106
107
 
108
+ handleModalFooterFocusin = modalFocusinEventHandler.bind(this);
109
+
107
110
  /**
108
111
  * When modal footer is being created, initialize
109
112
  * private tracked modal footer state
@@ -1,5 +1,8 @@
1
1
  <template>
2
- <div class="slds-modal__header" part="modal-header">
2
+ <div class="slds-modal__header"
3
+ part="modal-header"
4
+ onfocusin={handleModalHeaderFocusin}
5
+ >
3
6
  <template if:true={label}>
4
7
  <h1
5
8
  id="modal-label"
@@ -1,6 +1,7 @@
1
1
  import { api } from 'lwc';
2
2
  import LightningShadowBaseClass from 'lightning/shadowBaseClassPrivate';
3
3
  import { getRealDOMId } from 'lightning/utilsPrivate';
4
+ import { modalFocusinEventHandler } from 'lightning/modalUtils';
4
5
 
5
6
  // selectors
6
7
  const modalHeaderSelector = '.slds-modal__header';
@@ -152,6 +153,8 @@ export default class LightningModalHeader extends LightningShadowBaseClass {
152
153
  this.dispatchEvent(evtRegister);
153
154
  }
154
155
 
156
+ handleModalHeaderFocusin = modalFocusinEventHandler.bind(this);
157
+
155
158
  /**
156
159
  * When modal header is being created, initialize
157
160
  * private tracked modal header state
@@ -436,7 +436,7 @@ function initAuraOverlayState() {
436
436
 
437
437
  /**
438
438
  * Helper function to detect if a lightning-modal is currently open
439
- * Used in modalBase.js to trap a user's focus while lightning-modal is open
439
+ * Used in modalUtil.js to trap a user's focus while lightning-modal is open
440
440
  * @returns {boolean}
441
441
  */
442
442
  export function isLwcModalActive() {
@@ -296,6 +296,14 @@ Licensed under BSD 3-Clause - see LICENSE.txt or git.io/sfdc-license */
296
296
  --sds-c-button-color-border-disabled: var(--slds-g-color-border-disabled-1);
297
297
  --sds-c-button-text-color-disabled: var(--slds-g-color-on-disabled-1);
298
298
  --sds-c-button-color-background-disabled: var(--slds-g-color-disabled-container-1);
299
+
300
+ /**
301
+ * Needed to override
302
+ * `pointer-event: none` coming from sds
303
+ * that prevent tooltip from showing
304
+ */
305
+ pointer-events: auto;
306
+ cursor: default;
299
307
  }
300
308
  /**
301
309
  * A note about fallbacks on the default variant:
@@ -1,4 +1,4 @@
1
- import { isInDom, WindowManager, pxToInt } from './util';
1
+ import { isInDom, WindowManager, pxToFloat, getTransformValues } from './util';
2
2
 
3
3
  export class ElementProxy {
4
4
  constructor(el, id) {
@@ -137,18 +137,21 @@ export class ElementProxy {
137
137
 
138
138
  const originalLeft = style.left.match(/auto|fixed/)
139
139
  ? '0'
140
- : parseInt(style.left.replace('px', ''), 10);
140
+ : pxToFloat(style.left);
141
141
  const originalTop = style.top.match(/auto|fixed/)
142
142
  ? '0'
143
- : parseInt(style.top.replace('px', ''), 10);
143
+ : pxToFloat(style.top);
144
144
 
145
145
  const marginOffset =
146
146
  this.top < absPos.top
147
- ? pxToInt(style.marginBottom)
148
- : pxToInt(style.marginTop) * -1;
147
+ ? pxToFloat(style.marginBottom) * -1
148
+ : pxToFloat(style.marginTop);
149
+
150
+ const transform = getTransformValues(style.transform);
151
+ const topOffset = transform.y;
149
152
 
150
153
  let leftDif = Math.round(this.left - (absPos.left + scrollLeft));
151
- const topDif = this.top - (absPos.top + marginOffset + scrollTop);
154
+ const topDif = this.top - (absPos.top + scrollTop) + topOffset;
152
155
 
153
156
  const viewPortWidth = w.innerWidth || document.body.clientWidth;
154
157
  let rightPos = parseInt(style.right, 10);
@@ -164,6 +167,10 @@ export class ElementProxy {
164
167
 
165
168
  this._node.style.left = `${originalLeft + leftDif}px`;
166
169
  this._node.style.top = `${originalTop + topDif}px`;
170
+ // translate3d enables CSS Hardware Acceleration and switches to GPU
171
+ this._node.style.transform = `translate3d(0, ${
172
+ topOffset ? topOffset : marginOffset
173
+ }px, 0)`;
167
174
 
168
175
  if (this._restoreSize) {
169
176
  // Only store the first height/width which is the original height/width.
@@ -244,6 +244,24 @@ function isPx(value) {
244
244
  return value.slice(-2) === 'px';
245
245
  }
246
246
 
247
- export function pxToInt(value) {
248
- return value && isPx(value) ? parseInt(value, 10) : 0;
247
+ export function pxToFloat(value) {
248
+ return value && isPx(value) ? parseFloat(value) : 0;
249
+ }
250
+
251
+ export function getTransformValues(value = '') {
252
+ // DOMMatrix is used to get scalar values for css transform string
253
+ // https://developer.mozilla.org/en-US/docs/Web/API/DOMMatrixReadOnly
254
+ const matrix = new DOMMatrixReadOnly(value);
255
+ if (matrix.is2D) {
256
+ return {
257
+ x: matrix.e, // translateX
258
+ y: matrix.f, // translateY
259
+ z: 0,
260
+ };
261
+ }
262
+ return {
263
+ x: matrix.m41, // translateX
264
+ y: matrix.m42, // translateY
265
+ z: matrix.m43, // translateZ
266
+ };
249
267
  }
@@ -130,6 +130,9 @@ export default class LightningPrimitiveBubble extends LightningShadowBaseClass {
130
130
  // manually create <div>, add positional styling, and append as child to bubble
131
131
  createInvisibleDivManually() {
132
132
  if (this.state.visible) {
133
+ // for native shadow, we need to get styles from popover parent and append
134
+ // to popover body so that it is added/removed from DOM depending on tooltip visibility
135
+ const popoverParent = this.template.querySelector('.slds-popover');
133
136
  const popoverBody = this.template.querySelector(
134
137
  '.slds-popover__body'
135
138
  );
@@ -137,8 +140,8 @@ export default class LightningPrimitiveBubble extends LightningShadowBaseClass {
137
140
  const { vertical } = this.align;
138
141
 
139
142
  let computedStyle = null;
140
- if (window && popoverBody) {
141
- computedStyle = window.getComputedStyle(popoverBody);
143
+ if (window && popoverParent && popoverBody) {
144
+ computedStyle = window.getComputedStyle(popoverParent);
142
145
  invisibleDiv.style.width =
143
146
  computedStyle.getPropertyValue('width');
144
147
 
@@ -151,8 +154,10 @@ export default class LightningPrimitiveBubble extends LightningShadowBaseClass {
151
154
  */
152
155
  if (vertical === 'bottom') {
153
156
  invisibleDiv.style.top =
154
- Math.max(POPOVER_MIN_HEIGHT, popoverBody.offsetHeight) +
155
- 'px';
157
+ Math.max(
158
+ POPOVER_MIN_HEIGHT,
159
+ popoverParent.offsetHeight
160
+ ) + 'px';
156
161
  invisibleDiv.style.height =
157
162
  DEFAULT_INVISIBLE_DIV_STYLES.height;
158
163
  } else {
@@ -1,5 +1,6 @@
1
1
  <template>
2
2
  <lightning-button-menu
3
+ lwc:ref="buttonMenu"
3
4
  icon-size="x-small"
4
5
  alternative-text={buttonAlternateText}
5
6
  menu-alignment={computedMenuAlignment}
@@ -68,7 +68,7 @@ export default class PrimitiveCellActions extends LightningElement {
68
68
  @api
69
69
  focus() {
70
70
  if (this._connected) {
71
- this.template.querySelector('lightning-button-menu').focus();
71
+ this.refs.buttonMenu.focus();
72
72
  }
73
73
  }
74
74
 
@@ -81,7 +81,7 @@ export default class PrimitiveCellActions extends LightningElement {
81
81
  // focus/click without changing tabindex doesnt work W-6185168
82
82
  // eslint-disable-next-line @lwc/lwc/no-async-operation
83
83
  setTimeout(() => {
84
- this.template.querySelector('lightning-button-menu').click();
84
+ this.refs.buttonMenu.click();
85
85
  }, 0);
86
86
  }
87
87
  }
@@ -141,9 +141,7 @@ export default class PrimitiveCellActions extends LightningElement {
141
141
  * Handles the opening of an action menu
142
142
  */
143
143
  handleMenuOpen() {
144
- this.elementRect = this.template
145
- .querySelector('lightning-button-menu')
146
- .getBoundingClientRect();
144
+ this.elementRect = this.refs.buttonMenu.getBoundingClientRect();
147
145
 
148
146
  const detail = {
149
147
  rowKeyValue: this.rowKeyValue,
@@ -1,6 +1,7 @@
1
1
  <template>
2
2
  <template if:true={isButtonIconType}>
3
3
  <lightning-button-icon
4
+ lwc:ref="buttonIcon"
4
5
  variant={variant}
5
6
  alternative-text={alternativeText}
6
7
  icon-name={iconName}
@@ -14,6 +15,7 @@
14
15
  </template>
15
16
  <template if:false={isButtonIconType}>
16
17
  <lightning-button
18
+ lwc:ref="button"
17
19
  variant={variant}
18
20
  label={label}
19
21
  icon-name={iconName}
@@ -61,11 +61,9 @@ export default class PrivateCellButton extends LightningElement {
61
61
 
62
62
  get buttonCustomElement() {
63
63
  if (this._connected) {
64
- const qs = this.isButtonIconType
65
- ? 'lightning-button-icon'
66
- : 'lightning-button';
67
-
68
- return this.template.querySelector(qs);
64
+ return this.isButtonIconType
65
+ ? this.refs.buttonIcon
66
+ : this.refs.button;
69
67
  }
70
68
  return undefined;
71
69
  }
@@ -4,7 +4,8 @@
4
4
  onclick={handleCheckboxContainerClick}
5
5
  onmousedown={handleCheckboxContainerMouseDown}
6
6
  >
7
- <input type="checkbox"
7
+ <input lwc:ref="input"
8
+ type="checkbox"
8
9
  name={computedOptionName}
9
10
  id="primitive-cell-checkbox-id"
10
11
  tabindex={internalTabIndex}
@@ -13,7 +14,7 @@
13
14
  onclick={handleCheckboxClick}
14
15
  disabled={isDisabled}
15
16
  checked={isSelected}>
16
- <label
17
+ <label lwc:ref="label"
17
18
  id={labelId}
18
19
  class="slds-checkbox__label"
19
20
  for="primitive-cell-checkbox-id"
@@ -26,7 +26,7 @@ export default class PrimitiveCellCheckbox extends PrimitiveDatatableCell {
26
26
  this._columnHeaderId = id || '';
27
27
  const labelId = this.computedLabelId;
28
28
  if (labelId) {
29
- synchronizeAttrs(this.template.querySelector('input'), {
29
+ synchronizeAttrs(this.refs.input, {
30
30
  'aria-labelledby': `${labelId} ${this._columnHeaderId}`,
31
31
  });
32
32
  }
@@ -41,13 +41,16 @@ export default class PrimitiveCellCheckbox extends PrimitiveDatatableCell {
41
41
 
42
42
  renderedCallback() {
43
43
  //give input the correct aria-labelledby value
44
- synchronizeAttrs(this.template.querySelector('input'), {
44
+ synchronizeAttrs(this.refs.input, {
45
45
  'aria-labelledby': `${this.computedLabelId} ${this.columnHeaderId}`,
46
46
  });
47
47
  }
48
48
 
49
49
  get computedLabelId() {
50
- return getRealDOMId(this.template.querySelector('label'));
50
+ if (this.isConnected && this.refs) {
51
+ return getRealDOMId(this.refs.label);
52
+ }
53
+ return null;
51
54
  }
52
55
 
53
56
  get selectItemAssistiveText() {
@@ -1,6 +1,7 @@
1
1
  <template>
2
2
  <span class="slds-radio">
3
- <input type="radio"
3
+ <input lwc:ref="input"
4
+ type="radio"
4
5
  name={computedOptionName}
5
6
  id="primitive-checkbox-radio-id"
6
7
  tabindex={internalTabIndex}
@@ -11,9 +12,9 @@
11
12
  disabled={isDisabled}
12
13
  onkeydown={handleRadioKeyDown}
13
14
  checked={isSelected}>
14
- <label
15
- id={labelId}
16
- class="slds-radio__label"
15
+ <label lwc:ref="label"
16
+ id={labelId}
17
+ class="slds-radio__label"
17
18
  for="primitive-checkbox-radio-id">
18
19
  <span class="slds-radio_faux"></span>
19
20
  <span class="slds-form-element__label slds-assistive-text">
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <button tabindex={tabIndex} class="slds-button slds-button_icon slds-cell-edit__button slds-m-left_x-small">
2
+ <button lwc:ref="button" tabindex={tabIndex} class="slds-button slds-button_icon slds-cell-edit__button slds-m-left_x-small">
3
3
  <lightning-primitive-icon
4
4
  icon-name="utility:edit"
5
5
  size="xx-small"
@@ -38,7 +38,7 @@ export default class PrivateCellEditableButton extends LightningElement {
38
38
 
39
39
  get htmlButton() {
40
40
  if (!this._htmlButton) {
41
- this._htmlButton = this.template.querySelector('button');
41
+ this._htmlButton = this.refs.button;
42
42
  }
43
43
 
44
44
  return this._htmlButton;
@@ -1,6 +1,7 @@
1
1
  <template>
2
2
  <div class={computedCellDivClass} style={computedCssStyles}>
3
3
  <lightning-primitive-custom-cell
4
+ lwc:ref="customCell"
4
5
  types={types}
5
6
  keyboard-mode={keyboardMode}
6
7
  column-type={columnType}
@@ -104,6 +104,7 @@
104
104
  <!-- custom type -->
105
105
  <template if:true={isCustomType}>
106
106
  <lightning-primitive-custom-cell
107
+ lwc:ref="customCell"
107
108
  class={computedMarginClassWhenLeftIconExists}
108
109
  types={types}
109
110
  keyboard-mode={keyboardMode}
@@ -93,9 +93,7 @@ export default class PrivateCellFactory extends PrimitiveDatatableCell {
93
93
  this.template.querySelectorAll('[data-navigation="enable"]')
94
94
  );
95
95
 
96
- const customType = this.template.querySelector(
97
- 'lightning-primitive-custom-cell'
98
- );
96
+ const customType = this.refs.customCell;
99
97
 
100
98
  if (customType) {
101
99
  const wrapperActionableElements =
@@ -283,7 +281,7 @@ export default class PrivateCellFactory extends PrimitiveDatatableCell {
283
281
  'slds-truncate':
284
282
  columnType !== 'button-icon' && !isActionType && !_wrapText,
285
283
  'slds-hyphenate': _wrapText,
286
- 'slds-line-clamp': _wrapText && this.wrapTextMaxLines,
284
+ 'slds-line-clamp': _wrapText,
287
285
  'ltr-content-in-rtl': document.dir === 'rtl' && this.isLtrType(),
288
286
  });
289
287
  }
@@ -357,8 +355,8 @@ export default class PrivateCellFactory extends PrimitiveDatatableCell {
357
355
  }
358
356
 
359
357
  get computedCssStyles() {
360
- if (this._wrapText && this.wrapTextMaxLines) {
361
- return `${'--lwc-lineClamp'}: ${this.wrapTextMaxLines}`;
358
+ if (this._wrapText) {
359
+ return `${'--lwc-lineClamp'}: ${this.wrapTextMaxLines || 'none'}`;
362
360
  }
363
361
  return null;
364
362
  }
@@ -12,6 +12,7 @@
12
12
  <lightning-button-icon tooltip={i18n.moveDownTooltip} icon-name="utility:arrowdown" onclick={handleMoveDown} disabled={isDownDisabled} variant="border-filled" alternative-text="Arrow Down"></lightning-button-icon>
13
13
  </lightning-button-group>
14
14
  <lightning-combobox
15
+ lwc:ref="combobox"
15
16
  name="column select"
16
17
  disabled={rule.disableInputs}
17
18
  placeholder={i18n.dropdownPlaceholder}
@@ -26,7 +26,7 @@ export default class PrimitiveColumnSorter extends LightningElement {
26
26
  @api
27
27
  get combobox() {
28
28
  if (!this._combobox) {
29
- this._combobox = this.template.querySelector('lightning-combobox');
29
+ this._combobox = this.refs.combobox;
30
30
  }
31
31
  return this._combobox;
32
32
  }
@@ -1,6 +1,7 @@
1
1
  <template>
2
2
  <section
3
3
  if:true={visible}
4
+ lwc:ref="section"
4
5
  class="slds-popover slds-popover_edit"
5
6
  role="dialog"
6
7
  aria-label={dialogAriaLabel}
@@ -35,6 +36,7 @@
35
36
  <template if:true={isMassEditEnabled}>
36
37
  <!-- Checkbox to select in order to mass edit multiple rows -->
37
38
  <lightning-input
39
+ lwc:ref="massSelectCheckbox"
38
40
  data-mass-selection="true"
39
41
  type="checkbox"
40
42
  name="dt-iedit-mass-edit"
@@ -60,12 +62,12 @@
60
62
  onclick={cancelEditing}>
61
63
  </lightning-button>
62
64
  <lightning-button
65
+ lwc:ref="formLastElement"
63
66
  label={i18n.apply}
64
67
  style="margin-left: .25rem"
65
68
  variant="brand"
66
69
  onblur={handleTypeElemBlur}
67
70
  onfocus={handleTypeElemFocus}
68
- data-form-last-element="true"
69
71
  onclick={processSubmission}>
70
72
  </lightning-button>
71
73
  </div>
@@ -53,7 +53,7 @@ export default class PrimitiveDatatableIeditPanel extends LightningElement {
53
53
  get isMassEditChecked() {
54
54
  return (
55
55
  this.isMassEditEnabled &&
56
- this.template.querySelector('[data-mass-selection="true"]').checked
56
+ this.refs.massSelectCheckbox.checked
57
57
  );
58
58
  }
59
59
 
@@ -95,7 +95,7 @@ export default class PrimitiveDatatableIeditPanel extends LightningElement {
95
95
  */
96
96
  @api
97
97
  getPositionedElement() {
98
- return this.template.querySelector('section');
98
+ return this.refs.section;
99
99
  }
100
100
 
101
101
  /************************* PRIVATE GETTERS *************************/
@@ -279,7 +279,7 @@ export default class PrimitiveDatatableIeditPanel extends LightningElement {
279
279
  /************************* HELPER FUNCTIONS *************************/
280
280
 
281
281
  focusLastElement() {
282
- this.template.querySelector('[data-form-last-element="true"]').focus();
282
+ this.refs.formLastElement.focus();
283
283
  }
284
284
 
285
285
  processSubmission() {
@@ -4,6 +4,7 @@
4
4
  <template if:true={showError}>
5
5
  <!-- Error Tooltip -->
6
6
  <lightning-primitive-datatable-tooltip
7
+ lwc:ref="tooltip"
7
8
  class="slds-button"
8
9
  size="small"
9
10
  variant="error"