lightning-base-components 1.13.8-alpha → 1.14.2-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 (46) hide show
  1. package/metadata/raptor.json +7 -0
  2. package/package.json +5 -1
  3. package/scopedImports/@salesforce-internal-core.appVersion.js +1 -1
  4. package/scopedImports/@salesforce-label-LightningLookup.recentItems.js +1 -0
  5. package/src/lightning/ariaObserver/__component__/ariaObserver.spec.js +103 -0
  6. package/src/lightning/{utilsPrivate/contentMutation.js → ariaObserver/ariaObserver.js} +51 -78
  7. package/src/lightning/baseCombobox/baseCombobox.html +1 -0
  8. package/src/lightning/baseCombobox/baseCombobox.js +14 -1
  9. package/src/lightning/combobox/combobox.css +12 -0
  10. package/src/lightning/combobox/combobox.html +1 -0
  11. package/src/lightning/datatable/columnWidthManager.js +7 -3
  12. package/src/lightning/datatable/datatable.js +27 -25
  13. package/src/lightning/datatable/inlineEdit.js +15 -3
  14. package/src/lightning/datatable/keyboard.js +1077 -933
  15. package/src/lightning/datatable/resizer.js +91 -108
  16. package/src/lightning/datatable/state.js +0 -9
  17. package/src/lightning/datatable/templates/div/div.css +19 -0
  18. package/src/lightning/datatable/templates/div/div.html +10 -8
  19. package/src/lightning/datatable/templates/table/table.html +8 -6
  20. package/src/lightning/datatable/widthManagerShared.js +1 -1
  21. package/src/lightning/formattedRichText/__docs__/formattedRichText.md +1 -0
  22. package/src/lightning/helptext/helptext.js +8 -0
  23. package/src/lightning/iconSvgTemplates/buildTemplates/templates.js +2 -1
  24. package/src/lightning/iconSvgTemplates/buildTemplates/utility/contract_alt.html +1 -2
  25. package/src/lightning/iconSvgTemplates/buildTemplates/utility/contract_doc.html +8 -0
  26. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/templates.js +2 -1
  27. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/contract_alt.html +1 -2
  28. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/contract_doc.html +8 -0
  29. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/templates.js +2 -1
  30. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/contract_alt.html +1 -2
  31. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/contract_doc.html +8 -0
  32. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/templates.js +2 -1
  33. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/contract_alt.html +1 -2
  34. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/contract_doc.html +8 -0
  35. package/src/lightning/input/input.html +0 -1
  36. package/src/lightning/input/input.js +69 -48
  37. package/src/lightning/positionLibrary/positionLibrary.js +43 -31
  38. package/src/lightning/primitiveDatatableIeditPanel/primitiveDatatableIeditPanel.js +20 -0
  39. package/src/lightning/primitiveDatatableIeditTypeFactory/primitiveDatatableIeditTypeFactory.js +10 -0
  40. package/src/lightning/primitiveHeaderFactory/nonsortableHeader.html +5 -4
  41. package/src/lightning/primitiveHeaderFactory/primitiveHeaderFactory.js +64 -47
  42. package/src/lightning/primitiveHeaderFactory/selectableHeader.html +25 -23
  43. package/src/lightning/primitiveHeaderFactory/sortableHeader.html +13 -9
  44. package/src/lightning/progressIndicator/progressIndicator.js +3 -5
  45. package/src/lightning/progressStep/progressStep.js +31 -22
  46. package/src/lightning/utilsPrivate/utilsPrivate.js +12 -1
@@ -1284,6 +1284,11 @@
1284
1284
  {
1285
1285
  "name": "iconVariant"
1286
1286
  }
1287
+ ],
1288
+ "methods": [
1289
+ {
1290
+ "name": "focus"
1291
+ }
1287
1292
  ]
1288
1293
  },
1289
1294
  "icon": {
@@ -1347,8 +1352,10 @@
1347
1352
  "industriesCibApi": {},
1348
1353
  "industriesDecisionMatrixDesignerApi": {},
1349
1354
  "industriesExplainabilityApi": {},
1355
+ "industriesIdentityVerificationApi": {},
1350
1356
  "industriesInterestTaggingApi": {},
1351
1357
  "industriesLoyaltyEngineApi": {},
1358
+ "industriesRcgTenantmanagementApi": {},
1352
1359
  "industriesRuleBuilderApi": {},
1353
1360
  "industriesSustainabilityRecalculateApi": {},
1354
1361
  "industriesSustainabilityRecordLockUnlockApi": {},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lightning-base-components",
3
- "version": "1.13.8-alpha",
3
+ "version": "1.14.2-alpha",
4
4
  "engines": {
5
5
  "node": ">=12.18.3"
6
6
  },
@@ -793,6 +793,10 @@
793
793
  "name": "@salesforce/label/LightningLookup.recentObject",
794
794
  "path": "scopedImports/@salesforce-label-LightningLookup.recentObject.js"
795
795
  },
796
+ {
797
+ "name": "@salesforce/label/LightningLookup.recentItems",
798
+ "path": "scopedImports/@salesforce-label-LightningLookup.recentItems.js"
799
+ },
796
800
  {
797
801
  "name": "@salesforce/label/LightningLookup.resultsListHeaderMobile",
798
802
  "path": "scopedImports/@salesforce-label-LightningLookup.resultsListHeaderMobile.js"
@@ -1 +1 @@
1
- export default '234';
1
+ export default '236';
@@ -0,0 +1 @@
1
+ export default 'Recent Items';
@@ -0,0 +1,103 @@
1
+ import { createElement } from 'lwc';
2
+ import AriaObserverContainer from 'lightningtest/ariaObserverContainer';
3
+
4
+ function createTestElement(props = {}) {
5
+ const element = createElement('lightningtest-aria-observer-container', {
6
+ is: AriaObserverContainer,
7
+ });
8
+ Object.assign(element, props);
9
+ document.body.appendChild(element);
10
+
11
+ return element;
12
+ }
13
+
14
+ describe('AriaObserver', () => {
15
+ if (process.env.NATIVE_SHADOW) {
16
+ describe('native shadow', () => {
17
+ it('should copy the label content over and set aria-labelledby to be the internal label element', () => {
18
+ const container = createTestElement();
19
+ const testElement = container.testElement;
20
+
21
+ expect(container.labelContent).toEqual(
22
+ testElement.labelContent
23
+ );
24
+ });
25
+
26
+ it('should react to label id changes', async () => {
27
+ const container = createTestElement();
28
+ const oldLabelContent = container.labelContent;
29
+
30
+ container.updateAriaLabelledby('alt-label-id');
31
+ await Promise.resolve();
32
+
33
+ const testElement = container.testElement;
34
+
35
+ expect(container.labelContent).not.toEqual(oldLabelContent);
36
+ expect(container.labelContent).toEqual(
37
+ testElement.labelContent
38
+ );
39
+ });
40
+
41
+ it('should work with multiple label ids', async () => {
42
+ const container = createTestElement();
43
+ container.updateAriaLabelledby('id-label alt-label-id');
44
+ await Promise.resolve();
45
+
46
+ const testElement = container.testElement;
47
+ expect(testElement.labelContent).toEqual('Foo\nBar');
48
+ });
49
+
50
+ it('should update the internal label content when external content changes', async () => {
51
+ const container = createTestElement();
52
+ container.updateLabelContent();
53
+
54
+ // wait for component rehydration
55
+ await Promise.resolve();
56
+ // wait for mutation observer callback
57
+ await Promise.resolve();
58
+
59
+ const testElement = container.testElement;
60
+ expect(container.labelContent).toEqual(
61
+ testElement.labelContent
62
+ );
63
+ });
64
+ });
65
+ } else {
66
+ describe('synthetic shadow', () => {
67
+ it('should set aria-labelledby to be the external label id', () => {
68
+ const container = createTestElement();
69
+ const testElement = container.testElement;
70
+
71
+ expect(container.labelId).toEqual(testElement.labelId);
72
+ });
73
+
74
+ it('should react to label id changes', async () => {
75
+ const container = createTestElement();
76
+ const oldLabelId = container.labelId;
77
+
78
+ container.updateAriaLabelledby('alt-label-id');
79
+ await Promise.resolve();
80
+
81
+ const testElement = container.testElement;
82
+
83
+ expect(container.labelId).not.toEqual(oldLabelId);
84
+ expect(container.labelId).toEqual(testElement.labelId);
85
+ });
86
+
87
+ it('should keep the label id unchanged when the label content changes', async () => {
88
+ const container = createTestElement();
89
+ container.updateLabelContent();
90
+ await Promise.resolve();
91
+
92
+ const testElement = container.testElement;
93
+ expect(container.labelId).toEqual(testElement.labelId);
94
+ });
95
+
96
+ it('should keep track of the live id', () => {
97
+ const container = createTestElement();
98
+ const testElement = container.testElement;
99
+ expect(testElement.labelId).toEqual(testElement.liveId);
100
+ });
101
+ });
102
+ }
103
+ });
@@ -1,50 +1,11 @@
1
- import { guid } from './guid';
2
- import { smartSetAttribute } from './smartSetAttribute';
1
+ import {
2
+ guid,
3
+ synchronizeAttrs,
4
+ isNativeComponent,
5
+ } from 'lightning/utilsPrivate';
3
6
 
4
7
  const CONTENT_SEPARATOR = '\n';
5
8
 
6
- /**
7
- <template>
8
- <span lwc:dom="manual" class="visually-hidden"></span>
9
- <input>
10
- </template>
11
-
12
- class Foo extends LightningElement {
13
- constructor() {
14
- super();
15
- this.ariaObserver = new ContentMutation(this);
16
- }
17
-
18
- connectedCallback() {
19
- if (!this.ariaObserver) {
20
- this.ariaObserver = new ContentMutation(this);
21
- }
22
- }
23
-
24
- disconnectedCallback() {
25
- if (this.ariaObserver) {
26
- this.ariaObserver.disconnect();
27
- this.ariaObserver = undefined;
28
- }
29
- }
30
-
31
- @track ariaLabeledbyValue = '';
32
-
33
- @api
34
- get ariaLabeledby() {
35
- return this.ariaLabeledbyValue; // whatever they set, is what they get back.
36
- }
37
- set ariaLabeledby(refs) {
38
- this.ariaLabeledbyValue = refs;
39
- this.ariaObserver.link('input', 'aria-labeledby', refs, 'span.visually-hidden');
40
- }
41
-
42
- renderedCallback() {
43
- this.ariaObserver.sync();
44
- }
45
- }
46
- **/
47
-
48
9
  function getAttr(elm, attr) {
49
10
  if (elm.tagName.match(/lightning/i)) {
50
11
  return elm[attr];
@@ -95,11 +56,10 @@ function addAriaRefWhenNeeded(elm, attrName, computedIds) {
95
56
  }
96
57
 
97
58
  if (suffix.length !== 0) {
98
- smartSetAttribute(
99
- elm,
100
- attrName,
101
- oldIds + (oldIds.length === 0 ? '' : ' ') + suffix.join(' ')
102
- );
59
+ synchronizeAttrs(elm, {
60
+ [attrName]:
61
+ oldIds + (oldIds.length === 0 ? '' : ' ') + suffix.join(' '),
62
+ });
103
63
  }
104
64
  }
105
65
 
@@ -116,19 +76,28 @@ function removeAriaRefWhenPossible(elm, attrName, computedIds) {
116
76
  newValues.push(newIds[i]);
117
77
  }
118
78
  }
119
- smartSetAttribute(elm, attrName, newValues.join(' '));
79
+
80
+ synchronizeAttrs(elm, {
81
+ [attrName]: newValues.join(' '),
82
+ });
120
83
  }
121
84
 
122
- export class ContentMutation {
85
+ function createPlaceholderContainer() {
86
+ const container = document.createElement('span');
87
+ container.style.display = 'none';
88
+ container.setAttribute('placeholder-container', '');
89
+ return container;
90
+ }
91
+
92
+ export default class AriaObserver {
123
93
  constructor(component) {
124
94
  this.component = component;
125
95
  this.template = component.template;
126
- this.isNative = this.template.constructor
127
- .toString()
128
- .match(/\[native code\]/);
96
+ this.isNative = isNativeComponent(component);
129
97
  this.state = {};
130
98
  this.liveIds = {};
131
99
  this.guid = guid();
100
+ this.placeholderContainer = null;
132
101
  }
133
102
 
134
103
  connectLiveIdRef(refs, callback) {
@@ -141,24 +110,26 @@ export class ContentMutation {
141
110
  this.liveIds[refs] = liveId;
142
111
  }
143
112
 
144
- link(innerSelector, attrName, ids, placeholderContainerSelector) {
145
- let attrState = this.state[attrName];
113
+ connect({ targetSelector, attribute, id, ids }) {
114
+ ids = ids || id;
115
+
116
+ let attrState = this.state[attribute];
146
117
  if (attrState) {
147
- // note: we don't support linking to a different innerSelector,
148
- // attrName, or placeholderContainerSelector
118
+ // note: we don't support linking to a different targetSelector, attribute
149
119
  if (!this.isNative) {
150
- const elm = this.template.querySelector(innerSelector);
120
+ const elm = this.template.querySelector(
121
+ attrState.innerSelector
122
+ );
151
123
  if (elm) {
152
124
  // removing the old ids if possible before setting the new ones
153
- removeAriaRefWhenPossible(elm, attrName, attrState.ids);
125
+ removeAriaRefWhenPossible(elm, attribute, attrState.ids);
154
126
  }
155
127
  attrState.ids = ids;
156
128
  }
157
129
  } else {
158
- attrState = this.state[attrName] = {
130
+ attrState = this.state[attribute] = {
159
131
  ids,
160
- innerSelector,
161
- placeholderContainerSelector,
132
+ innerSelector: targetSelector,
162
133
  };
163
134
  }
164
135
  if (this.isNative) {
@@ -167,11 +138,15 @@ export class ContentMutation {
167
138
  .split(/\s+/)
168
139
  .map((ref) => `#${ref}`)
169
140
  .join(',');
170
- attrState.placeholder = document.createElement('span');
171
- attrState.placeholder.id = `auto-link-${attrName}-${this.guid}`;
141
+
142
+ // create placeholder element for copied content
143
+ if (!attrState.placeholder) {
144
+ attrState.placeholder = document.createElement('span');
145
+ attrState.placeholder.id = `auto-link-${attribute}-${this.guid}`;
146
+ }
172
147
  }
173
148
  if (this.component.isConnected) {
174
- this.privateUpdate(attrName);
149
+ this.privateUpdate(attribute);
175
150
  }
176
151
  }
177
152
 
@@ -238,12 +213,9 @@ export class ContentMutation {
238
213
  }
239
214
  let computedIds;
240
215
  if (this.isNative) {
241
- const {
242
- outerSelector,
243
- content,
244
- placeholder,
245
- placeholderContainerSelector,
246
- } = this.state[attrName];
216
+ const { outerSelector, content, placeholder } =
217
+ this.state[attrName];
218
+
247
219
  const newContent = extractContent(
248
220
  extractElements(this.root, outerSelector)
249
221
  );
@@ -252,13 +224,14 @@ export class ContentMutation {
252
224
  newContent;
253
225
  }
254
226
  if (!placeholder.parentNode) {
255
- // inserting the placeholder once
256
- const container = this.template.querySelector(
257
- placeholderContainerSelector
258
- );
259
- if (container) {
260
- container.appendChild(placeholder);
227
+ // create placeholder container at template root, if not already exist
228
+ if (!this.placeholderContainer) {
229
+ this.placeholderContainer = createPlaceholderContainer();
230
+ this.template.appendChild(this.placeholderContainer);
261
231
  }
232
+
233
+ // inserting the placeholder once
234
+ this.placeholderContainer.appendChild(placeholder);
262
235
  }
263
236
  computedIds = placeholder.id;
264
237
  } else {
@@ -46,6 +46,7 @@
46
46
  name={name}
47
47
  data-value={computedInputValue}
48
48
  disabled={disabled}
49
+ aria-label={computedButtonTriggerAriaLabel}
49
50
  onfocus={handleFocus}
50
51
  onkeydown={handleInputKeyDown}
51
52
  onblur={handleBlur}>
@@ -328,7 +328,9 @@ export default class LightningBaseCombobox extends LightningElement {
328
328
  [ARIA_DESCRIBEDBY]: this.computedAriaDescribedBy,
329
329
  [ARIA_ACTIVEDESCENDANT]: this._activeElementDomId,
330
330
  [ARIA_CONTROLS]: this.computedInputControls,
331
- [ARIA_LABEL]: this.inputLabel,
331
+ [ARIA_LABEL]: this.isUserInputDisabled
332
+ ? this.computedButtonTriggerAriaLabel
333
+ : this.inputLabel,
332
334
  });
333
335
  }
334
336
 
@@ -441,6 +443,17 @@ export default class LightningBaseCombobox extends LightningElement {
441
443
  return this.hasInputPill ? this.inputPill.label : this.inputText;
442
444
  }
443
445
 
446
+ get computedButtonTriggerAriaLabel() {
447
+ const label = this.inputLabel;
448
+ const value = this.computedInputValue || this.computedPlaceholder;
449
+
450
+ if (!label) {
451
+ return value;
452
+ }
453
+
454
+ return `${label}, ${value}`;
455
+ }
456
+
444
457
  handleListboxScroll(event) {
445
458
  // We don't want this to bubble up to the modal which due to event retargeting wouldn't be able
446
459
  // to know what is actually being scrolled and thus may lead to the scrolling of the modal
@@ -1,3 +1,15 @@
1
1
  :host {
2
2
  display: block;
3
3
  }
4
+
5
+ /**
6
+ This is adding the red border around the combobox input when there's an error
7
+ Should be removed once SLDS has added support for this (@W-9240038)
8
+ */
9
+ :host.slds-has-error {
10
+ --slds-c-input-color-border:#ea001e;
11
+ --slds-c-input-shadow:#ea001e 0 0 0 1px inset;
12
+ --slds-c-input-color-background:var(--slds-c-input-color-background, var(--sds-c-input-color-background, white));
13
+ --slds-c-input-text-color:var(--slds-c-input-text-color, var(--sds-c-input-text-color), #74747);
14
+ }
15
+
@@ -15,6 +15,7 @@
15
15
  placeholder={placeholder}
16
16
  items={_items}
17
17
  input-text={_selectedLabel}
18
+ input-label={label}
18
19
  input-icon-size="xx-small"
19
20
  input-icon-name="utility:down"
20
21
  show-dropdown-activity-indicator={spinnerActive}
@@ -13,7 +13,7 @@ import {
13
13
  import {
14
14
  getColumnWidthFromDef,
15
15
  getDomWidth,
16
- getWidthStyle,
16
+ buildCSSWidthStyle,
17
17
  } from './widthManagerShared';
18
18
  import { isRTL } from 'lightning/utilsPrivate';
19
19
 
@@ -35,7 +35,7 @@ export function computeColumnWidths(adjustedWidths, columnDefs, widthsData) {
35
35
  const newWidth = columnWidths[index];
36
36
  widthsData.columnWidths[index] = newWidth;
37
37
  columnDef.columnWidth = newWidth;
38
- columnDef.style = getWidthStyle(newWidth);
38
+ columnDef.style = buildCSSWidthStyle(newWidth);
39
39
 
40
40
  // In RTL, we need to explicitly position the column headers.
41
41
  // We do this by providing the offset (in pixels) from the start of the table.
@@ -312,7 +312,11 @@ export class ColumnWidthManager {
312
312
  return [];
313
313
  },
314
314
  getTableElementWidth() {
315
- const tableElement = root.querySelector(TABLE_SEL);
315
+ // TODO: Figure out a clean way to retrieve and use the correct selectors
316
+ // Currently outside scope of this work. Should be addressed in W-8540110
317
+ const tableElement =
318
+ root.querySelector(TABLE_SEL) ||
319
+ root.querySelector('[role="grid"]');
316
320
  return getDomWidth(tableElement);
317
321
  },
318
322
  };
@@ -35,7 +35,7 @@ import {
35
35
  getColumnsWidths,
36
36
  resizeColumnWithDelta,
37
37
  getCustomerColumnWidths,
38
- getTableWidthStyle,
38
+ getCSSWidthStyleOfTable,
39
39
  updateColumnWidthsMetadata,
40
40
  getResizerDefaultState,
41
41
  } from './resizer';
@@ -56,7 +56,7 @@ import {
56
56
  } from './selector';
57
57
  import {
58
58
  syncActiveCell,
59
- handleCellKeydown,
59
+ handleKeydownOnCell,
60
60
  updateActiveCell,
61
61
  setBlurActiveCell,
62
62
  setFocusActiveCell,
@@ -67,7 +67,7 @@ import {
67
67
  updateTabIndexActiveRow,
68
68
  unsetRowNavigationMode,
69
69
  updateRowNavigationMode,
70
- handleDatatableLosedFocus,
70
+ handleDatatableFocusOut,
71
71
  handleDatatableFocusIn,
72
72
  updateTabIndexRow,
73
73
  getIndexesActiveCell,
@@ -77,7 +77,7 @@ import {
77
77
  resetCellToFocusFromPrev,
78
78
  datatableHasFocus,
79
79
  setCellClickedForFocus,
80
- handleKeyDown,
80
+ handleKeydownOnTable,
81
81
  addFocusStylesToActiveCell,
82
82
  refocusCellElement,
83
83
  } from './keyboard';
@@ -448,7 +448,7 @@ export default class LightningDatatable extends LightningElement {
448
448
 
449
449
  set maxColumnWidth(value) {
450
450
  const { state, widthsData } = this;
451
- setMaxColumnWidth(state, widthsData, value);
451
+ setMaxColumnWidth(getColumns(state), widthsData, value);
452
452
  this._columnWidthManager.maxColumnWidth = this.maxColumnWidth;
453
453
  }
454
454
 
@@ -484,7 +484,7 @@ export default class LightningDatatable extends LightningElement {
484
484
 
485
485
  set minColumnWidth(value) {
486
486
  const { state, widthsData } = this;
487
- setMinColumnWidth(state, widthsData, value);
487
+ setMinColumnWidth(getColumns(state), widthsData, value);
488
488
  this._columnWidthManager.minColumnWidth = this.minColumnWidth;
489
489
  }
490
490
 
@@ -761,16 +761,10 @@ export default class LightningDatatable extends LightningElement {
761
761
  if (this._columnWidthManager.isAutoResizingUpdateQueued()) {
762
762
  return ['table-layout:auto'].join(';');
763
763
  }
764
- return ['table-layout:fixed', getTableWidthStyle(this.widthsData)].join(
765
- ';'
766
- );
767
- }
768
-
769
- get computedTableHeaderClass() {
770
- if (this.state.hideTableHeader) {
771
- return 'slds-assistive-text';
772
- }
773
- return undefined;
764
+ return [
765
+ 'table-layout:fixed',
766
+ getCSSWidthStyleOfTable(this.widthsData),
767
+ ].join(';');
774
768
  }
775
769
 
776
770
  get computedTbodyStyle() {
@@ -802,7 +796,7 @@ export default class LightningDatatable extends LightningElement {
802
796
  if (this._columnWidthManager.isAutoResizingUpdateQueued()) {
803
797
  return `${minHeight}overflow-x:auto`;
804
798
  }
805
- return `${minHeight}${getTableWidthStyle(this.widthsData)}`;
799
+ return `${minHeight}${getCSSWidthStyleOfTable(this.widthsData)}`;
806
800
  }
807
801
 
808
802
  get scrollerXStyles() {
@@ -994,7 +988,7 @@ export default class LightningDatatable extends LightningElement {
994
988
  // Cell Interaction
995
989
  this.template.addEventListener(
996
990
  'privatecellkeydown',
997
- handleCellKeydown.bind(this)
991
+ handleKeydownOnCell.bind(this)
998
992
  );
999
993
 
1000
994
  this.template.addEventListener(
@@ -1133,15 +1127,15 @@ export default class LightningDatatable extends LightningElement {
1133
1127
  * @param {KeyboardEvent} event - `keydown`
1134
1128
  */
1135
1129
  handleTableKeydown(event) {
1136
- handleKeyDown.call(this, event);
1130
+ handleKeydownOnTable.call(this, event);
1137
1131
  }
1138
1132
 
1139
1133
  /**
1140
- * Handles the `keydown` event on <tr> (table-based) and div[role="row"] (role-based)
1134
+ * Handles the `keydown` event on data row <tr> (table-based) and div[role="row"] (role-based)
1141
1135
  *
1142
1136
  * @param {KeyboardEvent} event - `keydown`
1143
1137
  */
1144
- handleTrRowKeyDown(event) {
1138
+ handleKeydownOnDataRow(event) {
1145
1139
  // we probably should not be doing this unless we actually are interested in it
1146
1140
  if (
1147
1141
  this.state.keyboardMode === 'NAVIGATION' &&
@@ -1255,7 +1249,12 @@ export default class LightningDatatable extends LightningElement {
1255
1249
  const { state, widthsData } = this;
1256
1250
  const { colIndex, widthDelta } = event.detail;
1257
1251
  if (widthDelta !== 0) {
1258
- resizeColumnWithDelta(state, widthsData, colIndex, widthDelta);
1252
+ resizeColumnWithDelta(
1253
+ getColumns(state),
1254
+ widthsData,
1255
+ colIndex,
1256
+ widthDelta
1257
+ );
1259
1258
  this.fireOnResize(true);
1260
1259
  this.safariHeaderFix();
1261
1260
  }
@@ -1356,7 +1355,7 @@ export default class LightningDatatable extends LightningElement {
1356
1355
  * @param {FocusEvent} event - `focusout`
1357
1356
  */
1358
1357
  handleTableFocusOut(event) {
1359
- handleDatatableLosedFocus.call(this, event);
1358
+ handleDatatableFocusOut.call(this, event);
1360
1359
  }
1361
1360
 
1362
1361
  /**
@@ -1446,7 +1445,10 @@ export default class LightningDatatable extends LightningElement {
1446
1445
  const { state, widthsData } = this;
1447
1446
  const event = new CustomEvent('resize', {
1448
1447
  detail: {
1449
- columnWidths: getCustomerColumnWidths(state, widthsData),
1448
+ columnWidths: getCustomerColumnWidths(
1449
+ getColumns(state),
1450
+ widthsData
1451
+ ),
1450
1452
  isUserTriggered: !!isUserTriggered,
1451
1453
  },
1452
1454
  });
@@ -1508,7 +1510,7 @@ export default class LightningDatatable extends LightningElement {
1508
1510
  this.updateRowsAndCellIndexes(state);
1509
1511
  updateSelectionState(state);
1510
1512
  this._columnWidthManager.handleRowNumberOffsetChange(state, widthsData);
1511
- updateColumnWidthsMetadata(state, widthsData);
1513
+ updateColumnWidthsMetadata(getColumns(state), widthsData);
1512
1514
  // set the celltofocus next to null if the column still exists after indexes calculation
1513
1515
  updateCellToFocusFromPrev(state);
1514
1516
 
@@ -233,9 +233,21 @@ function openInlineEdit(dt, target) {
233
233
 
234
234
  // eslint-disable-next-line @lwc/lwc/no-async-operation
235
235
  setTimeout(() => {
236
- template
237
- .querySelector('lightning-primitive-datatable-iedit-panel')
238
- .focus();
236
+ const panel = template.querySelector(
237
+ 'lightning-primitive-datatable-iedit-panel'
238
+ );
239
+ if (!panel.isEditableValid) {
240
+ // if panel can't be edited, cancel edit process
241
+ processInlineEditFinish(
242
+ dt,
243
+ 'edit-canceled',
244
+ inlineEdit.rowKeyValue,
245
+ inlineEdit.colKeyValue
246
+ );
247
+ } else {
248
+ // if panel can be edited, focus
249
+ panel.focus();
250
+ }
239
251
  }, 0);
240
252
  }
241
253