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
@@ -2,6 +2,7 @@
2
2
  <div class="slds-docked-form-footer slds-is-absolute">
3
3
  <div class="slds-grid slds-grid_align-center">
4
4
  <template if:true={showError}>
5
+ <!-- Error Tooltip -->
5
6
  <lightning-primitive-datatable-tooltip
6
7
  class="slds-button"
7
8
  size="small"
@@ -12,18 +13,17 @@
12
13
  offset={bubbleOffset}
13
14
  ></lightning-primitive-datatable-tooltip>
14
15
  </template>
16
+ <!-- Cancel and Save Buttons -->
15
17
  <button
16
18
  type="button"
17
19
  class="slds-button slds-button_neutral"
18
- onclick={handleCancelButtonClick}
19
- >
20
+ onclick={handleCancelButtonClick}>
20
21
  {i18n.cancel}
21
22
  </button>
22
23
  <button
23
24
  type="button"
24
25
  class="slds-button slds-button_brand save-btn"
25
- onclick={handleSaveButtonClick}
26
- >
26
+ onclick={handleSaveButtonClick}>
27
27
  {i18n.save}
28
28
  </button>
29
29
  </div>
@@ -47,6 +47,10 @@ export default class LightningPrimitiveDatatableStatusBar extends LightningEleme
47
47
  };
48
48
  }
49
49
 
50
+ isSaveBtnFocused() {
51
+ return this.template.querySelector('button.save-btn:focus') !== null;
52
+ }
53
+
50
54
  handleCancelButtonClick(event) {
51
55
  event.preventDefault();
52
56
  event.stopPropagation();
@@ -78,10 +82,6 @@ export default class LightningPrimitiveDatatableStatusBar extends LightningEleme
78
82
  );
79
83
  }
80
84
 
81
- isSaveBtnFocused() {
82
- return this.template.querySelector('button.save-btn:focus') !== null;
83
- }
84
-
85
85
  /**
86
86
  * Handling between displaying/focusing tooltip icon and/or error bubble
87
87
  * If showBubble property is set within error object, display/focus the error bubble.
@@ -10,24 +10,28 @@ const i18n = {
10
10
  wrapText: labelWrapText,
11
11
  };
12
12
 
13
+ /**
14
+ * A header-level action.
15
+ */
13
16
  export default class PrimitiveHeaderActions extends LightningElement {
14
- static delegatesFocus = true;
15
- @api colKeyValue;
16
-
17
+ // Tracked objects
17
18
  @track containerRect;
18
19
  @track _internalActions = [];
19
20
  @track _customerActions = [];
21
+
22
+ // Private variables
23
+ static delegatesFocus = true;
20
24
  _actionMenuAlignment;
21
25
 
22
- @api
23
- focus() {
24
- const btnMenu = this.template.querySelector('lightning-button-menu');
26
+ /************************** PUBLIC ATTRIBUTES ***************************/
25
27
 
26
- if (btnMenu) {
27
- btnMenu.focus();
28
- }
29
- }
28
+ @api colKeyValue;
30
29
 
30
+ /**
31
+ * Defines the actions on a header cell
32
+ *
33
+ * @type {Object}
34
+ */
31
35
  @api
32
36
  get actions() {
33
37
  return this._actions;
@@ -38,49 +42,60 @@ export default class PrimitiveHeaderActions extends LightningElement {
38
42
  this.updateActions();
39
43
  }
40
44
 
41
- get i18n() {
42
- return i18n;
43
- }
44
-
45
- updateActions() {
46
- const actionTypeReducer = (type) => (actions, action) => {
47
- const overrides = { _type: type, _action: action };
48
- actions.push(Object.assign({}, action, overrides));
45
+ /************************** PUBLIC METHODS ***************************/
49
46
 
50
- return actions;
51
- };
47
+ /**
48
+ * Sets focus on a lightning-button-menu
49
+ */
50
+ @api
51
+ focus() {
52
+ const btnMenu = this.template.querySelector('lightning-button-menu');
52
53
 
53
- this._internalActions = this.getActionsByType('internalActions').reduce(
54
- actionTypeReducer('internal'),
55
- []
56
- );
54
+ if (btnMenu) {
55
+ btnMenu.focus();
56
+ }
57
+ }
57
58
 
58
- this._customerActions = this.getActionsByType('customerActions').reduce(
59
- actionTypeReducer('customer'),
60
- []
61
- );
59
+ /************************** PRIVATE GETTERS **************************/
62
60
 
63
- // ToDo: W-8389508 Refactor so menu is outside of header
64
- this._actionMenuAlignment =
65
- this._actions.menuAlignment &&
66
- this._actions.menuAlignment.replace('auto-', '');
61
+ /**
62
+ * Returns the internationalization definition object
63
+ *
64
+ * @return {Object} The i18n definition object
65
+ */
66
+ get i18n() {
67
+ return i18n;
67
68
  }
68
69
 
70
+ /**
71
+ * Determines whether or not a header has actions
72
+ *
73
+ * @return {Boolean}
74
+ */
69
75
  get hasActions() {
70
76
  return (
71
77
  this._internalActions.length > 0 || this._customerActions.length > 0
72
78
  );
73
79
  }
80
+
81
+ /**
82
+ * Determines whether or not a header has an action divider
83
+ *
84
+ * @return {Boolean}
85
+ */
74
86
  get hasActionsDivider() {
75
87
  return (
76
88
  this._internalActions.length > 0 && this._customerActions.length > 0
77
89
  );
78
90
  }
79
91
 
80
- getActionsByType(type) {
81
- return Array.isArray(this._actions[type]) ? this._actions[type] : [];
82
- }
92
+ /************************ EVENT DISPATCHERS **************************/
83
93
 
94
+ /**
95
+ * Handles opening a menu
96
+ *
97
+ * @param {Event} event
98
+ */
84
99
  handleMenuOpen(event) {
85
100
  event.preventDefault();
86
101
  event.stopPropagation();
@@ -107,6 +122,9 @@ export default class PrimitiveHeaderActions extends LightningElement {
107
122
  );
108
123
  }
109
124
 
125
+ /**
126
+ * Handles closing a menu
127
+ */
110
128
  handleMenuClose() {
111
129
  this.dispatchEvent(
112
130
  new CustomEvent('privatecellheaderactionmenuclosed', {
@@ -117,8 +135,13 @@ export default class PrimitiveHeaderActions extends LightningElement {
117
135
  );
118
136
  }
119
137
 
120
- handleActionSelect(evt) {
121
- const action = evt.detail.value;
138
+ /**
139
+ * Handles selecting an action
140
+ *
141
+ * @param {Event} event
142
+ */
143
+ handleActionSelect(event) {
144
+ const action = event.detail.value;
122
145
 
123
146
  this.dispatchEvent(
124
147
  new CustomEvent('privatecellheaderactiontriggered', {
@@ -133,4 +156,43 @@ export default class PrimitiveHeaderActions extends LightningElement {
133
156
  })
134
157
  );
135
158
  }
159
+
160
+ /************************* HELPER FUNCTIONS **************************/
161
+
162
+ /**
163
+ * Updates the actions object
164
+ */
165
+ updateActions() {
166
+ const actionTypeReducer = (type) => (actions, action) => {
167
+ const overrides = { _type: type, _action: action };
168
+ actions.push(Object.assign({}, action, overrides));
169
+
170
+ return actions;
171
+ };
172
+
173
+ this._internalActions = this.getActionsByType('internalActions').reduce(
174
+ actionTypeReducer('internal'),
175
+ []
176
+ );
177
+
178
+ this._customerActions = this.getActionsByType('customerActions').reduce(
179
+ actionTypeReducer('customer'),
180
+ []
181
+ );
182
+
183
+ // TODO: W-8389508 Refactor so menu is outside of header
184
+ this._actionMenuAlignment =
185
+ this._actions.menuAlignment &&
186
+ this._actions.menuAlignment.replace('auto-', '');
187
+ }
188
+
189
+ /**
190
+ * Returns actions by action type
191
+ *
192
+ * @param {String} type The action type to filter by
193
+ * @return {Array} An array of actions that match the provided type
194
+ */
195
+ getActionsByType(type) {
196
+ return Array.isArray(this._actions[type]) ? this._actions[type] : [];
197
+ }
136
198
  }
@@ -53,7 +53,7 @@ export default class LightningProgressIndicator extends LightningElement {
53
53
  set currentStep(value) {
54
54
  this.privateCurrentStep = value;
55
55
  if (this.privateRendered) {
56
- this.updateSteps();
56
+ this.updateSteps(value);
57
57
  }
58
58
  }
59
59
 
@@ -31,6 +31,8 @@ export default class LightningProgressStep extends LightningElement {
31
31
  */
32
32
  @api value;
33
33
 
34
+ _privateLabel;
35
+
34
36
  @track state = {};
35
37
 
36
38
  updateInternal(newStatus, newType, newIndex, newActive, shouldFocus) {
@@ -47,6 +49,7 @@ export default class LightningProgressStep extends LightningElement {
47
49
  this.state.type = newType;
48
50
  this.state.index = newIndex;
49
51
  this.state.active = newActive;
52
+ this.initializeTooltip();
50
53
  }
51
54
  /**
52
55
  * Text to display as the name or tooltip for the step.
@@ -54,30 +57,12 @@ export default class LightningProgressStep extends LightningElement {
54
57
  */
55
58
  @api
56
59
  set label(value) {
57
- if (this._tooltip) {
58
- this._tooltip.value = value;
59
- } else if (value && !this.isPath) {
60
- // Note that because the tooltip target is a child element it may not be present in the
61
- // dom during initial rendering.
62
- this._tooltip = new Tooltip(value, {
63
- root: this,
64
- target: () => this.template.querySelector('button'),
65
- type: TooltipType.Toggle,
66
- align: {
67
- horizontal: Direction.Center,
68
- vertical: Direction.Bottom,
69
- },
70
- targetAlign: {
71
- horizontal: Direction.Center,
72
- vertical: Direction.Top,
73
- },
74
- });
75
- this._tooltip.initialize();
76
- }
60
+ this._privateLabel = value;
61
+ this.initializeTooltip();
77
62
  }
78
63
 
79
64
  get label() {
80
- return this._tooltip ? this._tooltip.value : undefined;
65
+ return this._privateLabel;
81
66
  }
82
67
 
83
68
  computeClassSet(type, status, isActive) {
@@ -87,7 +72,7 @@ export default class LightningProgressStep extends LightningElement {
87
72
  'slds-is-completed': !isPath && status === 'completed',
88
73
  'slds-has-error': !isPath && status === 'error',
89
74
  'slds-is-active':
90
- (type !== 'base' && isActive === true) ||
75
+ (isPath && isActive === true) ||
91
76
  (type === 'base' && status === 'current'),
92
77
  'slds-path__item': isPath,
93
78
  'slds-is-complete': isPath && status === 'completed',
@@ -240,4 +225,27 @@ export default class LightningProgressStep extends LightningElement {
240
225
  }
241
226
  return base;
242
227
  }
228
+
229
+ initializeTooltip() {
230
+ if (this._tooltip) {
231
+ this._tooltip.value = this._privateLabel;
232
+ } else if (this._privateLabel && this.state.type && !this.isPath) {
233
+ // Note that because the tooltip target is a child element it may not be present in the
234
+ // dom during initial rendering.
235
+ this._tooltip = new Tooltip(this._privateLabel, {
236
+ root: this,
237
+ target: () => this.template.querySelector('button'),
238
+ type: TooltipType.Toggle,
239
+ align: {
240
+ horizontal: Direction.Center,
241
+ vertical: Direction.Bottom,
242
+ },
243
+ targetAlign: {
244
+ horizontal: Direction.Center,
245
+ vertical: Direction.Top,
246
+ },
247
+ });
248
+ this._tooltip.initialize();
249
+ }
250
+ }
243
251
  }
@@ -6,6 +6,7 @@
6
6
  oniframeload={handleIframeLoad}
7
7
  width={width}
8
8
  height={height}
9
+ title={mapTitle}
9
10
  frame-style={mapStyle}>
10
11
  </lightning-primitive-iframe>
11
12
  <div class="slds-iframe-cover"></div>
@@ -1,5 +1,7 @@
1
1
  import lang from '@salesforce/i18n/lang';
2
2
  import formFactor from '@salesforce/client/formFactor';
3
+ import labelTitleWithAddress from '@salesforce/label/LightningMap.titleWithAddress';
4
+ import labelTitleWithoutAddress from '@salesforce/label/LightningMap.iframeTitle';
3
5
  import { LightningElement, api, track } from 'lwc';
4
6
  import { ratioToScale, calculateSize } from './util';
5
7
  import {
@@ -9,12 +11,19 @@ import {
9
11
  postMessage,
10
12
  } from 'lightning/messageDispatcher';
11
13
  import { buildMapSourceUrl } from 'lightning/mapUtils';
14
+ import { isEmptyString } from 'lightning/inputUtils';
15
+ import { formatLabel } from 'lightning/utils';
12
16
 
13
17
  const EVENT_NAME = {
14
18
  LOADING_MAP: 'loadingMap',
15
19
  STATIC_MAP_LOADED: 'lightning:staticMapLoaded',
16
20
  };
17
21
 
22
+ const i18n = {
23
+ titleWithAddress: labelTitleWithAddress,
24
+ titleWithoutAddress: labelTitleWithoutAddress,
25
+ };
26
+
18
27
  export default class LightningStaticMap extends LightningElement {
19
28
  @api width;
20
29
  @api height;
@@ -23,6 +32,7 @@ export default class LightningStaticMap extends LightningElement {
23
32
  @api province;
24
33
  @api postalCode;
25
34
  @api country;
35
+ @api title;
26
36
 
27
37
  _zoom = 14;
28
38
  _scale = 1;
@@ -109,8 +119,7 @@ export default class LightningStaticMap extends LightningElement {
109
119
  return '';
110
120
  }
111
121
 
112
- get address() {
113
- // if latitude/longitude specified use that to avoid expensive Google geo-coding processing
122
+ get latLongString() {
114
123
  if (
115
124
  this.latitude != null &&
116
125
  this.latitude >= -90.0 &&
@@ -121,12 +130,40 @@ export default class LightningStaticMap extends LightningElement {
121
130
  ) {
122
131
  return `${this.latitude},${this.longitude}`;
123
132
  }
133
+ return null;
134
+ }
124
135
 
136
+ get addressString() {
125
137
  return `${this.street || ''} ${this.city || ''} ${
126
138
  this.province || ''
127
139
  } ${this.postalCode || ''} ${this.country || ''}`;
128
140
  }
129
141
 
142
+ get address() {
143
+ // if latitude/longitude specified use that to avoid expensive Google geo-coding processing
144
+ return this.latLongString || this.addressString;
145
+ }
146
+
147
+ /**
148
+ * getter for the i18 constant containing the localized strings
149
+ */
150
+ get i18n() {
151
+ return i18n;
152
+ }
153
+
154
+ get mapTitle() {
155
+ if (isEmptyString(this.title)) {
156
+ let titleAddress =
157
+ (this.addressString && this.addressString.trim()) ||
158
+ (this.latLongString && this.latLongString.trim());
159
+ if (isEmptyString(titleAddress)) {
160
+ return this.i18n.titleWithoutAddress;
161
+ }
162
+ return formatLabel(this.i18n.titleWithAddress, titleAddress);
163
+ }
164
+ return this.title;
165
+ }
166
+
130
167
  handleMessage(data) {
131
168
  if (data.event === EVENT_NAME.STATIC_MAP_LOADED) {
132
169
  this._mapLoaded = true;
@@ -3,7 +3,10 @@ const classNamesHash = (classes) => {
3
3
  ? classes
4
4
  .trim()
5
5
  .split(/\s+/)
6
- .reduce((acc, cn) => ({ ...acc, [cn]: true }), {})
6
+ .reduce((acc, cn) => {
7
+ acc[cn] = true;
8
+ return acc;
9
+ }, {})
7
10
  : classes;
8
11
  };
9
12
 
@@ -23,7 +23,6 @@ export {
23
23
  } from './keyboard';
24
24
  export { raf } from './scroll';
25
25
  export { isChrome, isIE11, isSafari } from './browser';
26
- export { ContentMutation } from './contentMutation';
27
26
  export { observePosition } from './observers';
28
27
  export { hasOnlyAllowedVideoIframes } from './videoUtils';
29
28
  export {
@@ -212,3 +211,15 @@ export function buttonGroupOrderClass(groupOrder) {
212
211
  [BUTTON_GROUP_ORDER.ONLY]: 'single-button',
213
212
  }[groupOrder];
214
213
  }
214
+
215
+ /**
216
+ * Checks if the given component is native
217
+ * @param {Object} cmp Component instance
218
+ * @returns {Boolean} Whether the component is native
219
+ */
220
+ export function isNativeComponent(cmp) {
221
+ if (cmp && cmp.template && cmp.template.constructor) {
222
+ return !!String(cmp.template.constructor).match(/\[native code\]/);
223
+ }
224
+ return false;
225
+ }
@@ -1 +0,0 @@
1
- export default 'Close';
@@ -1,14 +0,0 @@
1
- export function getDirtyValue(state, rowKeyValue, colKeyValue) {
2
- const dirtyValues = state.inlineEdit.dirtyValues;
3
-
4
- if (
5
- // eslint-disable-next-line no-prototype-builtins
6
- dirtyValues.hasOwnProperty(rowKeyValue) &&
7
- // eslint-disable-next-line no-prototype-builtins
8
- dirtyValues[rowKeyValue].hasOwnProperty(colKeyValue)
9
- ) {
10
- return dirtyValues[rowKeyValue][colKeyValue];
11
- }
12
-
13
- return undefined;
14
- }
@@ -1,38 +0,0 @@
1
- export function isSelectedRow(state, rowKeyValue) {
2
- return !!state.selectedRowsKeys[rowKeyValue];
3
- }
4
-
5
- export function isDisabledRow(state, rowKeyValue) {
6
- if (!isSelectedRow(state, rowKeyValue)) {
7
- const maxRowSelection = getMaxRowSelection(state);
8
-
9
- // W-4819182 when selection is 1, we should not disable selection.
10
- return (
11
- maxRowSelection !== 1 &&
12
- getCurrentSelectionLength(state) === maxRowSelection
13
- );
14
- }
15
-
16
- return false;
17
- }
18
-
19
- export function getRowSelectionInputType(state) {
20
- if (getMaxRowSelection(state) === 1) {
21
- return 'radio';
22
- }
23
- return 'checkbox';
24
- }
25
-
26
- export function getMaxRowSelection(state) {
27
- return state.maxRowSelection;
28
- }
29
-
30
- export function getCurrentSelectionLength(state) {
31
- return getSelectedRowsKeys(state).length;
32
- }
33
-
34
- export function getSelectedRowsKeys(state) {
35
- return Object.keys(state.selectedRowsKeys).filter(
36
- (key) => state.selectedRowsKeys[key]
37
- );
38
- }