lightning-base-components 1.13.10-alpha → 1.14.4-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 (69) hide show
  1. package/metadata/raptor.json +24 -0
  2. package/package.json +20 -4
  3. package/scopedImports/@salesforce-internal-core.appVersion.js +1 -1
  4. package/scopedImports/@salesforce-label-LightningDualListbox.movedOptionsPlural.js +1 -0
  5. package/scopedImports/@salesforce-label-LightningDualListbox.movedOptionsSingular.js +1 -0
  6. package/scopedImports/@salesforce-label-LightningErrorMessage.validitySelectAtleastOne.js +1 -0
  7. package/scopedImports/@salesforce-label-LightningMap.titleWithAddress.js +1 -0
  8. package/scopedImports/@salesforce-label-LightningModalBase.cancelandclose.js +1 -0
  9. package/src/lightning/ariaObserver/__component__/ariaObserver.spec.js +112 -0
  10. package/src/lightning/ariaObserver/__docs__/ariaObserver.md +142 -0
  11. package/src/lightning/{utilsPrivate/contentMutation.js → ariaObserver/ariaObserver.js} +60 -98
  12. package/src/lightning/buttonMenu/keyboard.js +0 -10
  13. package/src/lightning/card/card.html +6 -0
  14. package/src/lightning/checkboxGroup/checkboxGroup.html +2 -2
  15. package/src/lightning/checkboxGroup/checkboxGroup.js +6 -1
  16. package/src/lightning/colorPickerCustom/colorPickerCustom.js +20 -1
  17. package/src/lightning/datatable/__docs__/datatable.md +55 -0
  18. package/src/lightning/datatable/__examples__/basic/basic.html +1 -1
  19. package/src/lightning/datatable/columns-shared.js +1 -1
  20. package/src/lightning/datatable/datatable.js +98 -30
  21. package/src/lightning/datatable/errors.js +20 -9
  22. package/src/lightning/datatable/headerActions.js +77 -49
  23. package/src/lightning/datatable/infiniteLoading.js +100 -28
  24. package/src/lightning/datatable/inlineEdit.js +505 -379
  25. package/src/lightning/datatable/inlineEditShared.js +24 -0
  26. package/src/lightning/datatable/keyboard.js +162 -127
  27. package/src/lightning/datatable/renderManager.js +201 -133
  28. package/src/lightning/datatable/rowLevelActions.js +17 -13
  29. package/src/lightning/datatable/rowNumber.js +54 -20
  30. package/src/lightning/datatable/rowSelection.js +760 -0
  31. package/src/lightning/datatable/rowSelectionShared.js +79 -0
  32. package/src/lightning/datatable/rows.js +17 -6
  33. package/src/lightning/datatable/state.js +16 -2
  34. package/src/lightning/datatable/templates/div/div.css +4 -0
  35. package/src/lightning/datatable/templates/div/div.html +6 -0
  36. package/src/lightning/datatable/templates/table/table.html +5 -0
  37. package/src/lightning/datatable/utils.js +14 -0
  38. package/src/lightning/datatable/wrapText.js +77 -47
  39. package/src/lightning/dualListbox/dualListbox.html +1 -1
  40. package/src/lightning/dualListbox/dualListbox.js +42 -0
  41. package/src/lightning/formattedDateTime/__docs__/formattedDateTime.md +36 -3
  42. package/src/lightning/formattedDateTime/__examples__/datetime/datetime.html +2 -2
  43. package/src/lightning/formattedDateTime/__examples__/datetime/datetime.js +3 -1
  44. package/src/lightning/formattedDateTime/__examples__/time/time.html +1 -1
  45. package/src/lightning/formattedDateTime/__examples__/time/time.js +3 -1
  46. package/src/lightning/formattedDateTime/formattedDateTime.js +1 -0
  47. package/src/lightning/input/input.html +1 -5
  48. package/src/lightning/input/input.js +69 -48
  49. package/src/lightning/inputUtils/validity.js +12 -1
  50. package/src/lightning/pillContainer/__docs__/pillContainer.md +45 -1
  51. package/src/lightning/primitiveCellActions/primitiveCellActions.js +69 -12
  52. package/src/lightning/primitiveCellFactory/cellWithStandardLayout.html +13 -11
  53. package/src/lightning/primitiveCellFactory/primitiveCellFactory.js +13 -8
  54. package/src/lightning/primitiveDatatableIeditPanel/primitiveDatatableIeditPanel.html +17 -14
  55. package/src/lightning/primitiveDatatableIeditPanel/primitiveDatatableIeditPanel.js +167 -98
  56. package/src/lightning/primitiveDatatableIeditTypeFactory/primitiveDatatableIeditTypeFactory.js +94 -69
  57. package/src/lightning/primitiveDatatableStatusBar/primitiveDatatableStatusBar.html +4 -4
  58. package/src/lightning/primitiveDatatableStatusBar/primitiveDatatableStatusBar.js +4 -4
  59. package/src/lightning/primitiveHeaderActions/primitiveHeaderActions.js +99 -37
  60. package/src/lightning/progressIndicator/progressIndicator.js +1 -1
  61. package/src/lightning/progressStep/progressStep.js +30 -22
  62. package/src/lightning/staticMap/staticMap.html +1 -0
  63. package/src/lightning/staticMap/staticMap.js +39 -2
  64. package/src/lightning/utils/classSet.js +4 -1
  65. package/src/lightning/utilsPrivate/utilsPrivate.js +12 -1
  66. package/scopedImports/@salesforce-label-LightningModalBase.close.js +0 -1
  67. package/src/lightning/datatable/inlineEdit-shared.js +0 -14
  68. package/src/lightning/datatable/selector-shared.js +0 -38
  69. package/src/lightning/datatable/selector.js +0 -527
@@ -5,7 +5,7 @@
5
5
  <p><lightning-formatted-date-time value="1547250828000" hour="2-digit" second="2-digit"></lightning-formatted-date-time></p>
6
6
  <p><lightning-formatted-date-time value="1547250828000" hour="2-digit" minute="2-digit" time-zone="UTC"
7
7
  time-zone-name="short"></lightning-formatted-date-time></p>
8
- <p><lightning-formatted-date-time value="1547250828000" hour="2-digit" minute="2-digit" second="2-digit" hour12="false"
8
+ <p><lightning-formatted-date-time value="1547250828000" hour="2-digit" minute="2-digit" second="2-digit" hour12={ampm}
9
9
  time-zone-name="long"></lightning-formatted-date-time></p>
10
10
  </div>
11
11
  </template>
@@ -1,3 +1,5 @@
1
1
  import { LightningElement } from 'lwc';
2
2
 
3
- export default class FormattedDateTimeTime extends LightningElement {}
3
+ export default class FormattedDateTimeTime extends LightningElement {
4
+ ampm = false;
5
+ }
@@ -92,6 +92,7 @@ export default class LightningFormattedDateTime extends LightningElement {
92
92
 
93
93
  /**
94
94
  * Determines whether time is displayed as 12-hour. If false, time displays as 24-hour. The default setting is determined by the user's locale.
95
+ * Set the value using a variable. If set to any string directly, the component interprets its value as true.
95
96
  * @type {boolean}
96
97
  *
97
98
  */
@@ -1,5 +1,4 @@
1
1
  <template>
2
- <span data-aria class="slds-assistive-text"></span>
3
2
  <template if:true={isTypeSimple}>
4
3
  <template if:false={hasExternalLabel}>
5
4
  <label class={computedLabelClass} for="input">
@@ -203,7 +202,6 @@
203
202
  </div>
204
203
  </template>
205
204
 
206
-
207
205
  <template if:true={isTypeColor}>
208
206
  <div class="slds-color-picker">
209
207
  <div class="slds-form-element slds-color-picker__summary">
@@ -214,6 +212,7 @@
214
212
  </template>
215
213
  {label}
216
214
  </label>
215
+ <lightning-helptext if:true={fieldLevelHelp} content={fieldLevelHelp} alternative-text={helptextAlternativeText}></lightning-helptext>
217
216
  </template>
218
217
  <div class="slds-form-element__control">
219
218
  <lightning-primitive-colorpicker-button
@@ -240,9 +239,6 @@
240
239
  oninput={handleInput}>
241
240
  </div>
242
241
  </div>
243
- <template if:false={hasExternalLabel}>
244
- <lightning-helptext if:true={fieldLevelHelp} content={fieldLevelHelp} alternative-text={helptextAlternativeText}></lightning-helptext>
245
- </template>
246
242
  </div>
247
243
  </div>
248
244
  </template>
@@ -18,9 +18,9 @@ import { classSet, formatLabel } from 'lightning/utils';
18
18
  import {
19
19
  assert,
20
20
  classListMutation,
21
- ContentMutation,
22
21
  getRealDOMId,
23
22
  isSafari,
23
+ isNativeComponent,
24
24
  isNotUndefinedOrNull,
25
25
  isUndefinedOrNull,
26
26
  normalizeAriaAttribute,
@@ -31,6 +31,7 @@ import {
31
31
  decorateInputForDragon,
32
32
  setDecoratedDragonInputValueWithoutEvent,
33
33
  } from 'lightning/utilsPrivate';
34
+ import AriaObserver from 'lightning/ariaObserver';
34
35
  import { normalizeInput } from './normalize';
35
36
  import {
36
37
  normalizeDate,
@@ -76,7 +77,7 @@ const i18n = {
76
77
 
77
78
  const ARIA_CONTROLS = 'aria-controls';
78
79
  const ARIA_LABEL = 'aria-label';
79
- const ARIA_LABELEDBY = 'aria-labelledby';
80
+ const ARIA_LABELLEDBY = 'aria-labelledby';
80
81
  const ARIA_DESCRIBEDBY = 'aria-describedby';
81
82
 
82
83
  /*
@@ -306,13 +307,11 @@ export default class LightningInput extends LightningElement {
306
307
 
307
308
  constructor() {
308
309
  super();
309
- this.ariaObserver = new ContentMutation(this);
310
+ this.ariaObserver = new AriaObserver(this);
310
311
 
311
312
  // Native Shadow Root will return [native code].
312
313
  // Our synthetic method will return the function source.
313
- this.isNative = this.template.querySelector
314
- .toString()
315
- .match(/\[native code\]/);
314
+ this.isNative = isNativeComponent(this);
316
315
 
317
316
  // The selection cache allows us an input to remember what text was selected
318
317
  // in cases where we change the text on blur or in browsers (Safari) that
@@ -322,12 +321,12 @@ export default class LightningInput extends LightningElement {
322
321
 
323
322
  connectedCallback() {
324
323
  if (!this.ariaObserver) {
325
- this.ariaObserver = new ContentMutation(this);
324
+ this.ariaObserver = new AriaObserver(this);
326
325
  }
327
326
  // Manually track connected state because this.template.isConnected can be false
328
327
  // when input is created using createElement and inserted into dom manually.
329
328
  // i.e. create an input element and pass it to showCustomOverlay
330
- // Remove this state and the one in ContentMutation once the issue is fixed.
329
+ // Remove this state and the one in AriaObserver once the issue is fixed.
331
330
  // PR: https://github.com/salesforce/lwc/pull/1798
332
331
  this.isConnected = true;
333
332
 
@@ -523,12 +522,11 @@ export default class LightningInput extends LightningElement {
523
522
 
524
523
  set ariaControls(references) {
525
524
  this._ariaControls = references;
526
- this.ariaObserver.link(
527
- 'input',
528
- 'aria-controls',
529
- references,
530
- '[data-aria]'
531
- );
525
+ this.ariaObserver.connect({
526
+ targetSelector: 'input',
527
+ attribute: ARIA_CONTROLS,
528
+ ids: references,
529
+ });
532
530
  }
533
531
 
534
532
  /**
@@ -539,8 +537,7 @@ export default class LightningInput extends LightningElement {
539
537
  get ariaLabelledBy() {
540
538
  // native version returns the auto linked value
541
539
  if (this.isNative) {
542
- const ariaValues =
543
- this._inputElement.getAttribute('aria-labelledby');
540
+ const ariaValues = this._inputElement.getAttribute(ARIA_LABELLEDBY);
544
541
  return filterNonAutoLink(ariaValues);
545
542
  }
546
543
  return this._ariaLabelledBy;
@@ -548,12 +545,11 @@ export default class LightningInput extends LightningElement {
548
545
 
549
546
  set ariaLabelledBy(references) {
550
547
  this._ariaLabelledBy = references;
551
- this.ariaObserver.link(
552
- 'input',
553
- 'aria-labelledby',
554
- references,
555
- '[data-aria]'
556
- );
548
+ this.ariaObserver.connect({
549
+ targetSelector: 'input',
550
+ attribute: ARIA_LABELLEDBY,
551
+ ids: references,
552
+ });
557
553
  }
558
554
 
559
555
  /**
@@ -565,7 +561,7 @@ export default class LightningInput extends LightningElement {
565
561
  if (this.isNative) {
566
562
  // in native case return the linked value
567
563
  const ariaValues =
568
- this._inputElement.getAttribute('aria-describedby');
564
+ this._inputElement.getAttribute(ARIA_DESCRIBEDBY);
569
565
  return filterNonAutoLink(ariaValues);
570
566
  }
571
567
  return this._ariaDescribedBy;
@@ -573,12 +569,11 @@ export default class LightningInput extends LightningElement {
573
569
 
574
570
  set ariaDescribedBy(references) {
575
571
  this._ariaDescribedBy = references;
576
- this.ariaObserver.link(
577
- 'input',
578
- 'aria-describedby',
579
- references,
580
- '[data-aria]'
581
- );
572
+ this.ariaObserver.connect({
573
+ targetSelector: 'input',
574
+ attribute: ARIA_DESCRIBEDBY,
575
+ ids: references,
576
+ });
582
577
  }
583
578
 
584
579
  /**
@@ -2037,32 +2032,58 @@ export default class LightningInput extends LightningElement {
2037
2032
  return result;
2038
2033
  }
2039
2034
 
2035
+ _updateInputA11y(elem) {
2036
+ synchronizeAttrs(elem, {
2037
+ [ARIA_LABELLEDBY]: this.computedAriaLabelledBy,
2038
+ [ARIA_DESCRIBEDBY]: this.computedAriaDescribedBy,
2039
+ [ARIA_CONTROLS]: this.computedAriaControls,
2040
+ [ARIA_LABEL]: this.computedAriaLabel,
2041
+ });
2042
+ }
2043
+
2044
+ _updateDateOrTimePickerA11y(elem) {
2045
+ synchronizeAttrs(elem, {
2046
+ ariaLabelledByElement: this.ariaLabelledBy,
2047
+ ariaDescribedByElements: this.ariaDescribedBy,
2048
+ ariaControlsElement: this.ariaControls,
2049
+ [ARIA_LABEL]: this.computedAriaLabel,
2050
+ });
2051
+ }
2052
+
2053
+ _updateDateTimePickerA11y(elem) {
2054
+ synchronizeAttrs(elem, {
2055
+ // datepicker aria attributes
2056
+ dateAriaLabelledBy: this.dateAriaLabelledBy,
2057
+ dateAriaDescribedBy: this.dateAriaDescribedBy,
2058
+ dateAriaControls: this.dateAriaControls,
2059
+ dateAriaLabel: this.dateAriaLabel,
2060
+ // timepicker aria attributes
2061
+ timeAriaLabelledBy: this.timeAriaLabelledBy,
2062
+ timeAriaDescribedBy: this.timeAriaDescribedBy,
2063
+ timeAriaControls: this.timeAriaControls,
2064
+ timeAriaLabel: this.timeAriaLabel,
2065
+ });
2066
+ }
2067
+
2040
2068
  _synchronizeA11y() {
2069
+ // each of these templates are mutually exclusive and are selected
2070
+ // depending on the [type] of input.
2041
2071
  const input = this.template.querySelector('input');
2042
2072
  const datepicker = this.template.querySelector('lightning-datepicker');
2043
2073
  const timepicker = this.template.querySelector('lightning-timepicker');
2044
-
2074
+ const datetimepicker = this.template.querySelector(
2075
+ 'lightning-datetimepicker'
2076
+ );
2077
+ // determine which template type is present,
2078
+ // and update a11y props accordingly
2045
2079
  if (input) {
2046
- synchronizeAttrs(input, {
2047
- [ARIA_LABELEDBY]: this.computedAriaLabelledBy,
2048
- [ARIA_DESCRIBEDBY]: this.computedAriaDescribedBy,
2049
- [ARIA_CONTROLS]: this.computedAriaControls,
2050
- [ARIA_LABEL]: this.computedAriaLabel,
2051
- });
2080
+ this._updateInputA11y(input);
2052
2081
  } else if (datepicker) {
2053
- synchronizeAttrs(datepicker, {
2054
- ariaLabelledByElement: this.ariaLabelledBy,
2055
- ariaDescribedByElements: this.ariaDescribedBy,
2056
- ariaControlsElement: this.ariaControls,
2057
- [ARIA_LABEL]: this.computedAriaLabel,
2058
- });
2082
+ this._updateDateOrTimePickerA11y(datepicker);
2059
2083
  } else if (timepicker) {
2060
- synchronizeAttrs(timepicker, {
2061
- ariaLabelledByElement: this.ariaLabelledBy,
2062
- ariaDescribedByElements: this.ariaDescribedBy,
2063
- ariaControlsElement: this.ariaControls,
2064
- [ARIA_LABEL]: this.computedAriaLabel,
2065
- });
2084
+ this._updateDateOrTimePickerA11y(timepicker);
2085
+ } else if (datetimepicker) {
2086
+ this._updateDateTimePickerA11y(datetimepicker);
2066
2087
  }
2067
2088
  }
2068
2089
  }
@@ -7,6 +7,7 @@ import labelTooLong from '@salesforce/label/LightningErrorMessage.validityTooLon
7
7
  import labelTooShort from '@salesforce/label/LightningErrorMessage.validityTooShort';
8
8
  import labelTypeMismatch from '@salesforce/label/LightningErrorMessage.validityTypeMismatch';
9
9
  import labelValueMissing from '@salesforce/label/LightningErrorMessage.validityValueMissing';
10
+ import labelSelectAtleastOneValue from '@salesforce/label/LightningErrorMessage.validitySelectAtleastOne';
10
11
  import { assert } from 'lightning/utilsPrivate';
11
12
 
12
13
  const constraintsSortedByPriority = [
@@ -20,6 +21,7 @@ const constraintsSortedByPriority = [
20
21
  'tooShort',
21
22
  'typeMismatch',
22
23
  'valueMissing',
24
+ 'selectAtleastOneValue',
23
25
  ];
24
26
 
25
27
  const defaultLabels = {
@@ -33,6 +35,7 @@ const defaultLabels = {
33
35
  tooShort: labelTooShort,
34
36
  typeMismatch: labelTypeMismatch,
35
37
  valueMissing: labelValueMissing,
38
+ selectAtleastOneValue: labelSelectAtleastOneValue,
36
39
  };
37
40
 
38
41
  function resolveBestMatch(validity) {
@@ -103,6 +106,12 @@ function newValidityState(constraintsProvider) {
103
106
  get badInput() {
104
107
  return computeConstraint(constraintsProvider, 'badInput');
105
108
  }
109
+ get selectAtleastOneValue() {
110
+ return computeConstraint(
111
+ constraintsProvider,
112
+ 'validitySelectAtleastOneValue'
113
+ );
114
+ }
106
115
 
107
116
  get valid() {
108
117
  return !(
@@ -115,7 +124,8 @@ function newValidityState(constraintsProvider) {
115
124
  this.rangeOverflow ||
116
125
  this.stepMismatch ||
117
126
  this.customError ||
118
- this.badInput
127
+ this.badInput ||
128
+ this.selectAtleastOneValue
119
129
  );
120
130
  }
121
131
  }
@@ -200,6 +210,7 @@ export class FieldConstraintApi {
200
210
  tooLong: this.inputComponent.messageWhenTooLong,
201
211
  typeMismatch: this.inputComponent.messageWhenTypeMismatch,
202
212
  valueMissing: this.inputComponent.messageWhenValueMissing,
213
+ selectAtleastOneValue: this.inputComponent.messageWhenValueMissing,
203
214
  });
204
215
  }
205
216
 
@@ -14,6 +14,7 @@ selections when filtering a list, such as from a multi-select picklist.
14
14
  To specify the pills, set the `items` attribute to an array of values in your component's JavaScript.
15
15
 
16
16
  By default, all pills in the container are displayed and wrap to additional lines if they can't fit on one line.
17
+ For information about changing the behavior, see **Managing Pill Layout in the Container**.
17
18
 
18
19
  This example creates three pills: a text-only pill, a pill with an avatar, and
19
20
  a pill with an icon.
@@ -70,7 +71,7 @@ To create a pill with an avatar, use the following attributes.
70
71
  To create a pill with an icon, use the following attributes.
71
72
 
72
73
  - `type`: The media type. Use `icon`.
73
- - `iconName`: Required. The Lightning Design System name of the icon. Names are written in the format '\utility:down\' where 'utility' is the category, and 'down' is the specific icon to be displayed. Only utility icons can be used in this component.
74
+ - `iconName`: Required. The Lightning Design System name of the icon. Names are written in the format 'utility:down' where 'utility' is the category, and 'down' is the specific icon to be displayed. Only utility icons can be used for the `iconName`.
74
75
  - `alternativeText`: The alternative text used to describe the icon. Describe what happens when you click the button, for example 'Upload File', not what the icon looks like, 'Paperclip'.
75
76
 
76
77
  `lightning-pill-container` provides two variants: `bare` and `standard` (default). They are visually the same. However, the `standard` variant renders pills in an unordered list element. For more information, see the **Accessibility** section.
@@ -135,9 +136,12 @@ set to false by default, which makes all pills display and wrap to multiple line
135
136
  - `single-line`: Specifies that the pill container can display one line of pills. By default, if pills can't fit on one line, they are wrapped to additional lines to fit the container. Set `single-line` to true to limit pill display to one line. This attribute overrides `is-collapsible` and `is-expanded`.
136
137
 
137
138
  If all pills aren't displayed, the component shows a text button indicating how many more pills there are.
139
+ For example, if there are five more pills that aren’t displayed, the text button shows `+5 more`. The text button fires the `focus` event when you click it.
138
140
 
139
141
  To display a long list of pills as collapsed, set `is-collapsible` to true and optionally set `is-expanded` to false. Otherwise, pills are displayed expanded.
140
142
 
143
+ ##### Expand and Collapse Pills Programmatically
144
+
141
145
  Use `is-collapsible` and `is-expanded` to programmatically expand and collapse the pills.
142
146
 
143
147
  This example sets `is-collapsible` and uses a button to change the value of `is-expanded`.
@@ -175,6 +179,46 @@ export default class PillContainerCanCollapse extends LightningElement {
175
179
  ];
176
180
  }
177
181
  ```
182
+ ##### Display All Pills With the `+n more` Button
183
+
184
+ If all pills aren't displayed, the component shows a text button labeled `+n more` to indicate more pills can be displayed. By default, `lightning-pill-container` doesn’t handle the `focus` event that’s fired when you click the button. You can handle the event to display more pills or write logic to do something else when the button is clicked.
185
+
186
+ This example sets the pills to be collapsible but not expanded and handles the focus event.
187
+
188
+ ```html
189
+ <template>
190
+ <div style="width: 600px">
191
+ <lightning-pill-container
192
+ items={items}
193
+ is-collapsible={collapsible}
194
+ is-expanded={expanded}
195
+ onfocus={handlePillExpansion}
196
+ >
197
+ </lightning-pill-container>
198
+ </div>
199
+ </template>
200
+ ```
201
+
202
+ The list of pills is initially collapsed. When there are too many pills to be displayed, the text button labeled `+n more` displays. The handler for the `focus` event enables all the pills to display.
203
+
204
+ ```javascript
205
+ import { LightningElement } from 'lwc';
206
+
207
+ export default class PillContainerMoreButtonExpands extends LightningElement {
208
+ collapsible = true;
209
+ expanded = false;
210
+
211
+ handlePillExpansion(){
212
+ this.expanded = true;
213
+ }
214
+
215
+ items = [
216
+ {
217
+ //define the pills
218
+ }
219
+ ];
220
+ }
221
+ ```
178
222
 
179
223
  #### Component Styling
180
224
 
@@ -21,28 +21,33 @@ const i18n = {
21
21
  showActions: labelShowActions,
22
22
  };
23
23
 
24
+ /**
25
+ * A cell-level action.
26
+ */
24
27
  export default class PrimitiveCellActions extends LightningElement {
25
- static delegatesFocus = true;
26
-
27
- @api rowKeyValue;
28
- @api colKeyValue;
29
- @api rowActions;
30
-
28
+ // Tracked objects
31
29
  @track containerRect;
32
30
  @track _actions = [];
33
31
 
32
+ // Private variables
33
+ static delegatesFocus = true;
34
34
  _isLoadingActions;
35
35
  _menuAlignment = DEFAULT_MENU_ALIGNMENT;
36
36
  _internalTabIndex = false;
37
37
 
38
- connectedCallback() {
39
- this._connected = true;
40
- }
38
+ /************************** PUBLIC ATTRIBUTES ***************************/
41
39
 
42
- disconnectedCallback() {
43
- this._connected = false;
44
- }
40
+ @api rowKeyValue;
41
+ @api colKeyValue;
42
+ @api rowActions;
45
43
 
44
+ /**
45
+ * Defines the current menu alignment
46
+ * See `VALID_MENU_ALIGNMENT` for valid menu alignment values
47
+ * See `DEFAULT_MENU_ALIGNMENT` for the default menu alignment
48
+ *
49
+ * @type {string}
50
+ */
46
51
  @api
47
52
  get menuAlignment() {
48
53
  return this._menuAlignment;
@@ -55,6 +60,11 @@ export default class PrimitiveCellActions extends LightningElement {
55
60
  });
56
61
  }
57
62
 
63
+ /************************** PUBLIC METHODS ***************************/
64
+
65
+ /**
66
+ * Sets focus on a lightning-button-menu
67
+ */
58
68
  @api
59
69
  focus() {
60
70
  if (this._connected) {
@@ -62,6 +72,9 @@ export default class PrimitiveCellActions extends LightningElement {
62
72
  }
63
73
  }
64
74
 
75
+ /**
76
+ * Clicks a lightning-button-menu
77
+ */
65
78
  @api
66
79
  click() {
67
80
  if (this._connected) {
@@ -73,18 +86,42 @@ export default class PrimitiveCellActions extends LightningElement {
73
86
  }
74
87
  }
75
88
 
89
+ /************************** PRIVATE GETTERS **************************/
90
+
91
+ /**
92
+ * Returns the computed menu alignment value
93
+ *
94
+ * @return {string} Current computed menu alignment
95
+ */
76
96
  get computedMenuAlignment() {
77
97
  return this.menuAlignment;
78
98
  }
79
99
 
100
+ /**
101
+ * Returns the button alternative text in the appropriate language
102
+ *
103
+ * @return {string} Language-specific button alternative text
104
+ */
80
105
  get buttonAlternateText() {
81
106
  return `${i18n.showActions}`;
82
107
  }
83
108
 
109
+ /**
110
+ * Returns the spinner alternative text in the appropriate language
111
+ *
112
+ * @return {string} Language-specific spinner alternative text
113
+ */
84
114
  get spinnerAlternateText() {
85
115
  return `${i18n.loadingActions}`;
86
116
  }
87
117
 
118
+ /************************ EVENT DISPATCHERS **************************/
119
+
120
+ /**
121
+ * Handles selecting an action
122
+ *
123
+ * @param {Event} event
124
+ */
88
125
  handleActionSelect(event) {
89
126
  this.dispatchEvent(
90
127
  new CustomEvent('privatecellactiontriggered', {
@@ -100,6 +137,9 @@ export default class PrimitiveCellActions extends LightningElement {
100
137
  );
101
138
  }
102
139
 
140
+ /**
141
+ * Handles the opening of an action menu
142
+ */
103
143
  handleMenuOpen() {
104
144
  this.elementRect = this.template
105
145
  .querySelector('lightning-button-menu')
@@ -135,6 +175,23 @@ export default class PrimitiveCellActions extends LightningElement {
135
175
  }
136
176
  }
137
177
 
178
+ /************************** LIFECYCLE HOOKS **************************/
179
+
180
+ connectedCallback() {
181
+ this._connected = true;
182
+ }
183
+
184
+ disconnectedCallback() {
185
+ this._connected = false;
186
+ }
187
+
188
+ /************************* HELPER FUNCTIONS **************************/
189
+
190
+ /**
191
+ * Resets loading state when all actions have been loaded
192
+ *
193
+ * @param {object} actions - Actions displayed in the menu
194
+ */
138
195
  finishLoadingActions(actions) {
139
196
  this._isLoadingActions = false;
140
197
  this._actions = actions;
@@ -215,18 +215,20 @@
215
215
 
216
216
  <!-- row number -->
217
217
  <template if:true={isRowNumber}>
218
- <lightning-primitive-datatable-tooltip data-navigation="enable"
219
- data-action-triggers="enter,space"
220
- class={rowNumberErrorClass}
221
- size="xx-small"
222
- header={typeAttribute0.title}
223
- content={typeAttribute0.messages}
224
- variant='error'
225
- internal-tab-index={internalTabIndex}
226
- alternative-text={typeAttribute0.alternativeText}>
218
+ <template if:true={_rowHasError}>
219
+ <lightning-primitive-datatable-tooltip data-navigation="enable"
220
+ data-action-triggers="enter,space"
221
+ class="slds-m-horizontal_xxx-small"
222
+ size="xx-small"
223
+ header={typeAttribute0.title}
224
+ content={typeAttribute0.messages}
225
+ variant='error'
226
+ internal-tab-index={internalTabIndex}
227
+ alternative-text={typeAttribute0.alternativeText}>
227
228
 
228
- </lightning-primitive-datatable-tooltip>
229
- <span class="slds-row-number slds-text-body_small slds-text-color_weak"></span>
229
+ </lightning-primitive-datatable-tooltip>
230
+ </template>
231
+ <span class="slds-row-number slds-text-body_small slds-text-color_weak" style={computedRowNumberStyle}></span>
230
232
  </template>
231
233
 
232
234
  <!-- text -->
@@ -8,6 +8,9 @@ import labelEditHasError from '@salesforce/label/LightningDatatable.editHasError
8
8
  import labelTrue from '@salesforce/label/LightningDatatable.true';
9
9
  import labelFalse from '@salesforce/label/LightningDatatable.false';
10
10
 
11
+ // Same constant (TOOLTIP_ALLOWANCE) as used in lightning/datatable/rowNumber.js
12
+ // If making change to this, make sure to modify in rowNumber.js as well
13
+ const TOOLTIP_ALLOWANCE = 20;
11
14
  const i18n = {
12
15
  edit: labelEdit,
13
16
  editHasError: labelEditHasError,
@@ -58,6 +61,7 @@ export default class PrivateCellFactory extends PrimitiveDatatableCell {
58
61
  @api wrapTextMaxLines;
59
62
 
60
63
  _wrapText = false;
64
+ _rowHasError = false;
61
65
 
62
66
  @api
63
67
  get wrapText() {
@@ -153,7 +157,13 @@ export default class PrivateCellFactory extends PrimitiveDatatableCell {
153
157
  }
154
158
 
155
159
  get isRowNumber() {
156
- return this.isType('rowNumber');
160
+ if (this.isType('rowNumber')) {
161
+ const error = this.typeAttribute0;
162
+ this._rowHasError = error && error.title && error.messages;
163
+ return true;
164
+ }
165
+
166
+ return false;
157
167
  }
158
168
 
159
169
  get isAction() {
@@ -285,13 +295,8 @@ export default class PrivateCellFactory extends PrimitiveDatatableCell {
285
295
  .toString();
286
296
  }
287
297
 
288
- get rowNumberErrorClass() {
289
- const classes = classSet('slds-m-horizontal_xxx-small');
290
- const error = this.typeAttribute0;
291
- if (error) {
292
- classes.add({ 'slds-hidden': !error.title && !error.messages });
293
- }
294
- return classes.toString();
298
+ get computedRowNumberStyle() {
299
+ return this._rowHasError ? '' : `padding-left: ${TOOLTIP_ALLOWANCE}px;`;
295
300
  }
296
301
 
297
302
  get editIconAssistiveText() {