lightning-base-components 1.14.3-alpha → 1.15.1-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.
- package/metadata/raptor.json +37 -4
- package/package.json +11 -4
- package/scopedImports/@salesforce-internal-core.appVersion.js +1 -1
- package/scopedImports/@salesforce-label-LightningModalBase.cancelandclose.js +1 -0
- package/scopedImports/@salesforce-label-LightningProgressBar.progressBar.js +1 -0
- package/src/lightning/alert/__docs__/alert.md +101 -0
- package/src/lightning/alert/__examples__disabled/basic/basic.css +7 -0
- package/src/lightning/alert/__examples__disabled/basic/basic.html +8 -0
- package/src/lightning/alert/__examples__disabled/basic/basic.js +14 -0
- package/src/lightning/alert/alert.html +3 -0
- package/src/lightning/alert/alert.js +78 -0
- package/src/lightning/alert/alert.js-meta.xml +6 -0
- package/src/lightning/ariaObserver/__component__/ariaObserver.spec.js +9 -0
- package/src/lightning/ariaObserver/ariaObserver.js +24 -35
- package/src/lightning/baseFormattedText/baseFormattedText.html +6 -1
- package/src/lightning/baseFormattedText/baseFormattedText.js +5 -0
- package/src/lightning/button/__wdio__/utam/utam.html +3 -0
- package/src/lightning/button/__wdio__/utam/utam.js +3 -0
- package/src/lightning/button/__wdio__/utam/utam.spec.js +20 -0
- package/src/lightning/buttonMenu/buttonMenu.js +12 -0
- package/src/lightning/confirm/__docs__/confirm.md +100 -0
- package/src/lightning/confirm/__examples__disabled/basic/basic.css +7 -0
- package/src/lightning/confirm/__examples__disabled/basic/basic.html +8 -0
- package/src/lightning/confirm/__examples__disabled/basic/basic.js +14 -0
- package/src/lightning/confirm/confirm.html +3 -0
- package/src/lightning/confirm/confirm.js +80 -0
- package/src/lightning/confirm/confirm.js-meta.xml +6 -0
- package/src/lightning/datatable/__examples__/withInfiniteLoading/fetchDataHelper.js +21 -0
- package/src/lightning/datatable/__examples__/withInfiniteLoading/withInfiniteLoading.html +13 -0
- package/src/lightning/datatable/__examples__/withInfiniteLoading/withInfiniteLoading.js +42 -0
- package/src/lightning/datatable/__wdio__/utam/utam.html +17 -0
- package/src/lightning/datatable/__wdio__/utam/utam.js +91 -0
- package/src/lightning/datatable/__wdio__/utam/utam.spec.js +189 -0
- package/src/lightning/datatable/autoWidthStrategy.js +170 -61
- package/src/lightning/datatable/{resizer.js → columnResizer.js} +0 -0
- package/src/lightning/datatable/columnWidthManager.js +226 -44
- package/src/lightning/datatable/columns.js +166 -71
- package/src/lightning/datatable/datatable.js +136 -60
- package/src/lightning/datatable/fixedWidthStrategy.js +43 -8
- package/src/lightning/datatable/headerActions.js +2 -2
- package/src/lightning/datatable/infiniteLoading.js +100 -28
- package/src/lightning/datatable/inlineEdit.js +21 -30
- package/src/lightning/datatable/keyboard.js +166 -131
- package/src/lightning/datatable/renderManager.js +117 -122
- package/src/lightning/datatable/{datatableResizeObserver.js → resizeObserver.js} +46 -29
- package/src/lightning/datatable/resizeSensor.js +19 -3
- package/src/lightning/datatable/rowSelection.js +1 -1
- package/src/lightning/datatable/rowSelectionShared.js +33 -20
- package/src/lightning/datatable/rows.js +9 -8
- package/src/lightning/datatable/sort.js +8 -8
- package/src/lightning/datatable/state.js +14 -2
- package/src/lightning/datatable/templates/div/div.html +133 -119
- package/src/lightning/datatable/templates/table/table.html +10 -2
- package/src/lightning/datatable/tree.js +25 -0
- package/src/lightning/datatable/types.js +77 -9
- package/src/lightning/datatable/utils.js +51 -24
- package/src/lightning/datatable/virtualization.js +319 -0
- package/src/lightning/datatable/widthManagerShared.js +27 -3
- package/src/lightning/datatable/wrapText.js +115 -48
- package/src/lightning/datepicker/__perf__DISABLED/datepickerWithCalendarOpen.perf.js +55 -0
- package/src/lightning/formattedDateTime/__docs__/formattedDateTime.md +36 -3
- package/src/lightning/formattedDateTime/__examples__/datetime/datetime.html +2 -2
- package/src/lightning/formattedDateTime/__examples__/datetime/datetime.js +3 -1
- package/src/lightning/formattedDateTime/__examples__/time/time.html +1 -1
- package/src/lightning/formattedDateTime/__examples__/time/time.js +3 -1
- package/src/lightning/formattedDateTime/formattedDateTime.js +1 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/dashboard_component.html +7 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/slack.html +7 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/tableau.html +7 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/travel_mode.html +2 -2
- package/src/lightning/iconSvgTemplates/buildTemplates/templates.js +8 -1
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/data_model.html +7 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/serialized_product.html +1 -1
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/serialized_product_transaction.html +2 -1
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/slack.html +7 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/tableau.html +7 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/video_off.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/dashboard_component.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/slack.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/tableau.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/travel_mode.html +2 -2
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/templates.js +8 -1
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/data_model.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/serialized_product.html +1 -1
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/serialized_product_transaction.html +2 -1
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/slack.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/tableau.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/video_off.html +7 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/dashboard_component.html +7 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/slack.html +7 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/tableau.html +7 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/travel_mode.html +2 -2
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/templates.js +4 -1
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/dashboard_component.html +7 -0
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/slack.html +7 -0
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/tableau.html +7 -0
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/travel_mode.html +2 -2
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/templates.js +4 -1
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/templates.js +5 -1
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/data_model.html +7 -0
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/serialized_product.html +1 -1
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/serialized_product_transaction.html +2 -1
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/slack.html +7 -0
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/tableau.html +7 -0
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/video_off.html +7 -0
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/templates.js +5 -1
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/data_model.html +7 -0
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/serialized_product.html +1 -1
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/serialized_product_transaction.html +2 -1
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/slack.html +7 -0
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/tableau.html +7 -0
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/video_off.html +7 -0
- package/src/lightning/input/__docs__/input.md +2 -0
- package/src/lightning/input/input.html +2 -5
- package/src/lightning/interactiveDialogBase/interactiveDialogBase.css +494 -0
- package/src/lightning/interactiveDialogBase/interactiveDialogBase.html +63 -0
- package/src/lightning/interactiveDialogBase/interactiveDialogBase.js +200 -0
- package/src/lightning/menuItem/menuItem.js +4 -1
- package/src/lightning/modalBase/modalBase.css +20 -0
- package/src/lightning/modalBase/modalBase.html +54 -0
- package/src/lightning/modalBase/modalBase.js +1039 -0
- package/src/lightning/overlay/__docs__/overlay.md +90 -0
- package/src/lightning/overlay/__examples__/alert/alert.html +27 -0
- package/src/lightning/overlay/__examples__/alert/alert.js +33 -0
- package/src/lightning/overlay/__examples__/basic/basic.css +7 -0
- package/src/lightning/overlay/__examples__/basic/basic.html +18 -0
- package/src/lightning/overlay/__examples__/basic/basic.js +61 -0
- package/src/lightning/overlay/__examples__/demo/demo.html +29 -0
- package/src/lightning/overlay/__examples__/demo/demo.js +40 -0
- package/src/lightning/overlay/__examples__/panel/panel.html +17 -0
- package/src/lightning/overlay/__examples__/panel/panel.js +21 -0
- package/src/lightning/overlay/overlay.html +3 -0
- package/src/lightning/overlay/overlay.js +45 -0
- package/src/lightning/overlayContainer/__docs__/overlayContainer.md +0 -0
- package/src/lightning/overlayContainer/overlayContainer.html +3 -0
- package/src/lightning/overlayContainer/overlayContainer.js +138 -0
- package/src/lightning/overlayManager/overlayManager.js +54 -0
- package/src/lightning/overlayUtils/overlayUtils.js +17 -0
- package/src/lightning/progressBar/progressBar.html +2 -1
- package/src/lightning/progressBar/progressBar.js +18 -1
- package/src/lightning/prompt/__docs__/prompt.md +102 -0
- package/src/lightning/prompt/__examples__disabled/basic/basic.css +7 -0
- package/src/lightning/prompt/__examples__disabled/basic/basic.html +8 -0
- package/src/lightning/prompt/__examples__disabled/basic/basic.js +15 -0
- package/src/lightning/prompt/prompt.css +81 -0
- package/src/lightning/prompt/prompt.html +8 -0
- package/src/lightning/prompt/prompt.js +92 -0
- package/src/lightning/prompt/prompt.js-meta.xml +6 -0
- package/src/lightning/spinner/spinner.html +1 -1
- package/src/lightning/spinner/spinner.js +12 -0
- package/src/lightning/utilsPrivate/phonify.js +1 -1
- package/scopedImports/@salesforce-label-LightningModalBase.close.js +0 -1
|
@@ -8,14 +8,16 @@ import {
|
|
|
8
8
|
reactToTabBackward,
|
|
9
9
|
reactToTabForward,
|
|
10
10
|
getActiveCellElement,
|
|
11
|
-
getCellElementByIndexes,
|
|
12
11
|
updateActiveCell,
|
|
12
|
+
isActiveCellEditable,
|
|
13
|
+
isValidCell,
|
|
13
14
|
} from './keyboard';
|
|
14
15
|
import {
|
|
15
16
|
updateRowsAndCellIndexes,
|
|
16
17
|
getRowByKey,
|
|
17
18
|
getKeyField,
|
|
18
19
|
getUserRowByCellKeys,
|
|
20
|
+
isCellEditable,
|
|
19
21
|
} from './rows';
|
|
20
22
|
import {
|
|
21
23
|
getColumnIndexByColumnKey,
|
|
@@ -315,6 +317,11 @@ function openInlineEdit(dt, target) {
|
|
|
315
317
|
|
|
316
318
|
const { rowKeyValue, colKeyValue } = target;
|
|
317
319
|
|
|
320
|
+
// ensure that focus remains on inline edit panel instead of active cell
|
|
321
|
+
if (state.activeCell) {
|
|
322
|
+
state.activeCell.focused = false;
|
|
323
|
+
}
|
|
324
|
+
|
|
318
325
|
inlineEdit.isPanelVisible = true;
|
|
319
326
|
inlineEdit.rowKeyValue = rowKeyValue;
|
|
320
327
|
inlineEdit.colKeyValue = colKeyValue;
|
|
@@ -378,11 +385,7 @@ function openInlineEdit(dt, target) {
|
|
|
378
385
|
export function openInlineEditOnActiveCell(dt) {
|
|
379
386
|
const hasData = dt.state.data && dt.state.data.length > 0;
|
|
380
387
|
if (hasData) {
|
|
381
|
-
|
|
382
|
-
const isEditable = activeCellElement.editable;
|
|
383
|
-
if (isEditable) {
|
|
384
|
-
setFocusAndOpenInlineEdit(dt, activeCellElement);
|
|
385
|
-
} else {
|
|
388
|
+
if (!isActiveCellEditable(dt.state)) {
|
|
386
389
|
const firstEditableCell = getFirstEditableCell(dt);
|
|
387
390
|
if (firstEditableCell) {
|
|
388
391
|
updateActiveCell(
|
|
@@ -390,8 +393,10 @@ export function openInlineEditOnActiveCell(dt) {
|
|
|
390
393
|
firstEditableCell.rowKeyValue,
|
|
391
394
|
firstEditableCell.colKeyValue
|
|
392
395
|
);
|
|
393
|
-
setFocusAndOpenInlineEdit(dt,
|
|
396
|
+
setFocusAndOpenInlineEdit(dt, dt.state.activeCell);
|
|
394
397
|
}
|
|
398
|
+
} else {
|
|
399
|
+
setFocusAndOpenInlineEdit(dt, dt.state.activeCell);
|
|
395
400
|
}
|
|
396
401
|
}
|
|
397
402
|
}
|
|
@@ -400,11 +405,11 @@ export function openInlineEditOnActiveCell(dt) {
|
|
|
400
405
|
* Async function to await setting focus on an editable cell before opening inline-edit panel
|
|
401
406
|
*
|
|
402
407
|
* @param {Object} dt - The datatable instance
|
|
403
|
-
* @param {Object} cell - editable cell to be focused before open inline-edit panel
|
|
404
408
|
*/
|
|
405
409
|
// eslint-disable-next-line @lwc/lwc/no-async-await
|
|
406
|
-
async function setFocusAndOpenInlineEdit(dt
|
|
410
|
+
async function setFocusAndOpenInlineEdit(dt) {
|
|
407
411
|
await setFocusActiveCell(dt.template, dt.state, 0);
|
|
412
|
+
const cell = getActiveCellElement(dt.template, dt.state);
|
|
408
413
|
openInlineEdit(dt, cell);
|
|
409
414
|
}
|
|
410
415
|
|
|
@@ -716,8 +721,8 @@ function resolveNestedTypeAttributesHelper(rowData, typeAttributesValue) {
|
|
|
716
721
|
/************************** HELPER FUNCTIONS **************************/
|
|
717
722
|
|
|
718
723
|
/**
|
|
719
|
-
* Returns
|
|
720
|
-
* then undefined is returned.
|
|
724
|
+
* Returns the row and column keys of the first editable cell in the table.
|
|
725
|
+
* If no editable cells exist in the table then undefined is returned.
|
|
721
726
|
*
|
|
722
727
|
* @param {Object} dt - The datatable instance. Must be a truthy and valid datatable reference.
|
|
723
728
|
*/
|
|
@@ -732,18 +737,11 @@ function getFirstEditableCell(dt) {
|
|
|
732
737
|
// Loop through the editable columns in order and examine the corresponding cells
|
|
733
738
|
// in the current row for editability, returning the first such cell that is editable
|
|
734
739
|
const editableColumn = editableColumns[i];
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
dt.template,
|
|
741
|
-
rowIndex,
|
|
742
|
-
editableColumnIndex,
|
|
743
|
-
dt.state
|
|
744
|
-
);
|
|
745
|
-
if (cell.editable) {
|
|
746
|
-
return cell;
|
|
740
|
+
if (isCellEditable(rows[rowIndex], editableColumn)) {
|
|
741
|
+
return {
|
|
742
|
+
rowKeyValue: rows[rowIndex].key,
|
|
743
|
+
colKeyValue: editableColumn.colKeyValue,
|
|
744
|
+
};
|
|
747
745
|
}
|
|
748
746
|
}
|
|
749
747
|
}
|
|
@@ -768,13 +766,6 @@ function getCellValue(state, rowKeyValue, colKeyValue) {
|
|
|
768
766
|
return row.cells[colIndex].value;
|
|
769
767
|
}
|
|
770
768
|
|
|
771
|
-
function isValidCell(state, rowKeyValue, colKeyValue) {
|
|
772
|
-
const row = getRowByKey(state, rowKeyValue);
|
|
773
|
-
const colIndex = getStateColumnIndex(state, colKeyValue);
|
|
774
|
-
|
|
775
|
-
return row && row.cells[colIndex];
|
|
776
|
-
}
|
|
777
|
-
|
|
778
769
|
/**
|
|
779
770
|
* Sets `aria-selected` to true on cells whose rows are selected
|
|
780
771
|
* and are in the same column as the cell being currently edited
|
|
@@ -1,16 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
isCustomerColumn,
|
|
3
|
+
generateColKeyValue,
|
|
4
|
+
getStateColumnIndex,
|
|
5
|
+
} from './columns';
|
|
2
6
|
import {
|
|
3
7
|
hasTreeDataType,
|
|
4
8
|
getStateTreeColumn,
|
|
5
9
|
fireRowToggleEvent,
|
|
6
10
|
} from './tree';
|
|
11
|
+
import { isCellEditable, getRowByKey } from './rows';
|
|
7
12
|
import { isRTL, getShadowActiveElements } from 'lightning/utilsPrivate';
|
|
13
|
+
import { findFirstVisibleIndex } from './virtualization';
|
|
8
14
|
|
|
9
15
|
// Indicator/flag for a header row
|
|
10
16
|
const HEADER_ROW = 'HEADER';
|
|
11
17
|
|
|
12
18
|
// SLDS Class for Focus
|
|
13
|
-
const FOCUS_CLASS = 'slds-has-focus';
|
|
19
|
+
export const FOCUS_CLASS = 'slds-has-focus';
|
|
14
20
|
|
|
15
21
|
// Keyboard Navigation Modes
|
|
16
22
|
const NAVIGATION_MODE = 'NAVIGATION';
|
|
@@ -82,7 +88,7 @@ const SELECTORS = {
|
|
|
82
88
|
* user keys down on a cell that contains actionable items (ex. edit button, links,
|
|
83
89
|
* email, buttons).
|
|
84
90
|
*
|
|
85
|
-
* @param {Event} event
|
|
91
|
+
* @param {Event} event Custom DOM event (privatecellkeydown) sent by the cell
|
|
86
92
|
*/
|
|
87
93
|
export function handleKeydownOnCell(event) {
|
|
88
94
|
event.stopPropagation();
|
|
@@ -104,7 +110,7 @@ export function handleKeydownOnCell(event) {
|
|
|
104
110
|
* Those events are handled by `handleKeydownOnCell()` and the remaining are
|
|
105
111
|
* handled by this function.
|
|
106
112
|
*
|
|
107
|
-
* @param {
|
|
113
|
+
* @param {Event} event
|
|
108
114
|
*/
|
|
109
115
|
export function handleKeydownOnTable(event) {
|
|
110
116
|
const targetTagName = event.target.tagName.toLowerCase();
|
|
@@ -121,28 +127,28 @@ export function handleKeydownOnTable(event) {
|
|
|
121
127
|
* Changes the datatable state based on the keyboard event sent from the cell component.
|
|
122
128
|
* The result of those changes may trigger a re-render on the table
|
|
123
129
|
*
|
|
124
|
-
* @param {
|
|
125
|
-
* @param {
|
|
126
|
-
* @param {
|
|
127
|
-
* @returns {
|
|
130
|
+
* @param {Node} template The custom element root `this.template`
|
|
131
|
+
* @param {Object} state Datatable state
|
|
132
|
+
* @param {Event} event Custom DOM event sent by the cell
|
|
133
|
+
* @returns {Object} Mutated state
|
|
128
134
|
*/
|
|
129
|
-
function reactToKeyboardInActionMode(
|
|
135
|
+
function reactToKeyboardInActionMode(template, state, event) {
|
|
130
136
|
switch (event.detail.keyCode) {
|
|
131
137
|
case ARROW_LEFT:
|
|
132
|
-
return reactToArrowLeft(
|
|
138
|
+
return reactToArrowLeft(template, state, event);
|
|
133
139
|
case ARROW_RIGHT:
|
|
134
|
-
return reactToArrowRight(
|
|
140
|
+
return reactToArrowRight(template, state, event);
|
|
135
141
|
case ARROW_UP:
|
|
136
|
-
return reactToArrowUp(
|
|
142
|
+
return reactToArrowUp(template, state, event);
|
|
137
143
|
case ARROW_DOWN:
|
|
138
|
-
return reactToArrowDown(
|
|
144
|
+
return reactToArrowDown(template, state, event);
|
|
139
145
|
case ENTER:
|
|
140
146
|
case SPACE:
|
|
141
|
-
return reactToEnter(
|
|
147
|
+
return reactToEnter(template, state, event);
|
|
142
148
|
case ESCAPE:
|
|
143
|
-
return reactToEscape(
|
|
149
|
+
return reactToEscape(template, state, event);
|
|
144
150
|
case TAB:
|
|
145
|
-
return reactToTab(
|
|
151
|
+
return reactToTab(template, state, event);
|
|
146
152
|
default:
|
|
147
153
|
return state;
|
|
148
154
|
}
|
|
@@ -642,12 +648,15 @@ function setDefaultActiveCell(state) {
|
|
|
642
648
|
* Given a datatable template and state, returns an LWC component reference that represents
|
|
643
649
|
* the currently active cell in the table.
|
|
644
650
|
*
|
|
645
|
-
* @param {Object}
|
|
651
|
+
* @param {Object} template - A reference to the datatable's template
|
|
646
652
|
* @param {Object} state - A reference to the datatable's state
|
|
647
653
|
*/
|
|
648
|
-
export function getActiveCellElement(
|
|
649
|
-
|
|
650
|
-
|
|
654
|
+
export function getActiveCellElement(template, state) {
|
|
655
|
+
if (state.activeCell) {
|
|
656
|
+
const { rowKeyValue, colKeyValue } = state.activeCell;
|
|
657
|
+
return getCellElementByKeys(template, rowKeyValue, colKeyValue);
|
|
658
|
+
}
|
|
659
|
+
return null;
|
|
651
660
|
}
|
|
652
661
|
|
|
653
662
|
/**
|
|
@@ -805,45 +814,59 @@ function stillValidActiveCell(state) {
|
|
|
805
814
|
* - update the tabindex of the activeCell
|
|
806
815
|
* - set the current keyboard mode
|
|
807
816
|
* - set the focus to the cell
|
|
808
|
-
* @param {node}
|
|
817
|
+
* @param {node} template - the custom element template `this.template`
|
|
809
818
|
* @param {object} state - datatable state
|
|
810
819
|
* @param {int} direction - direction (-1 left, 1 right and 0 for no direction) its used to know which actionable element to activate.
|
|
811
|
-
* @param {object} info - extra information when setting the cell mode
|
|
820
|
+
* @param {object} info - extra information when setting the cell mode; currently only set when pressing tab
|
|
821
|
+
* @param {boolean} shouldScroll - true if scrollTop should be adjusted when setting focus
|
|
812
822
|
*/
|
|
813
|
-
export function setFocusActiveCell(
|
|
823
|
+
export function setFocusActiveCell(
|
|
824
|
+
template,
|
|
825
|
+
state,
|
|
826
|
+
direction,
|
|
827
|
+
info,
|
|
828
|
+
shouldScroll = true
|
|
829
|
+
) {
|
|
814
830
|
const { keyboardMode } = state;
|
|
815
831
|
const { rowIndex, colIndex } = getIndexesActiveCell(state);
|
|
816
832
|
|
|
833
|
+
// if pressing tab on editable cell, focus will go to inline edit panel instead of cell
|
|
834
|
+
state.activeCell.focused =
|
|
835
|
+
!(info && isActiveCellEditable(state)) && isActiveCellValid(state);
|
|
817
836
|
updateTabIndex(state, rowIndex, colIndex);
|
|
837
|
+
|
|
838
|
+
let cellElement = getActiveCellElement(template, state);
|
|
839
|
+
// if the cell wasn't found, but does exist in the table, scroll to where it should be
|
|
840
|
+
if (!cellElement && isActiveCellValid(state) && shouldScroll) {
|
|
841
|
+
scrollToCell(state, template, rowIndex);
|
|
842
|
+
}
|
|
843
|
+
|
|
818
844
|
return new Promise((resolve) => {
|
|
819
845
|
// eslint-disable-next-line @lwc/lwc/no-async-operation
|
|
820
846
|
setTimeout(() => {
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
847
|
+
// reset cell element if falsy or no longer valid
|
|
848
|
+
if (
|
|
849
|
+
!cellElement ||
|
|
850
|
+
!isValidCell(
|
|
851
|
+
state,
|
|
852
|
+
cellElement.rowKeyValue,
|
|
853
|
+
cellElement.colKeyValue
|
|
854
|
+
)
|
|
855
|
+
) {
|
|
856
|
+
cellElement = getActiveCellElement(template, state);
|
|
857
|
+
}
|
|
827
858
|
if (cellElement) {
|
|
828
859
|
if (direction) {
|
|
829
860
|
cellElement.resetCurrentInputIndex(direction, keyboardMode);
|
|
830
861
|
}
|
|
831
862
|
cellElement.addFocusStyles();
|
|
832
863
|
cellElement.parentElement.classList.add(FOCUS_CLASS);
|
|
833
|
-
cellElement.parentElement.focus(
|
|
864
|
+
cellElement.parentElement.focus({
|
|
865
|
+
preventScroll: !shouldScroll,
|
|
866
|
+
});
|
|
834
867
|
cellElement.setMode(keyboardMode, info);
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
const scrollingParent = scrollableY.parentElement;
|
|
838
|
-
const parentRect = scrollingParent.getBoundingClientRect();
|
|
839
|
-
const findMeRect = cellElement.getBoundingClientRect();
|
|
840
|
-
if (findMeRect.top < parentRect.top + TOP_MARGIN) {
|
|
841
|
-
scrollableY.scrollTop -= SCROLL_OFFSET;
|
|
842
|
-
} else if (
|
|
843
|
-
findMeRect.bottom >
|
|
844
|
-
parentRect.bottom - BOTTOM_MARGIN
|
|
845
|
-
) {
|
|
846
|
-
scrollableY.scrollTop += SCROLL_OFFSET;
|
|
868
|
+
if (shouldScroll) {
|
|
869
|
+
updateScrollTop(state, template, cellElement);
|
|
847
870
|
}
|
|
848
871
|
}
|
|
849
872
|
resolve();
|
|
@@ -855,22 +878,27 @@ export function setFocusActiveCell(element, state, direction, info) {
|
|
|
855
878
|
* It blur to the current activeCell, this operation imply multiple changes
|
|
856
879
|
* - blur the activeCell
|
|
857
880
|
* - update the tabindex to -1
|
|
858
|
-
* @param {node}
|
|
881
|
+
* @param {node} template - the custom element root `this.template`
|
|
859
882
|
* @param {object} state - datatable state
|
|
860
883
|
*/
|
|
861
|
-
export function setBlurActiveCell(
|
|
884
|
+
export function setBlurActiveCell(template, state) {
|
|
862
885
|
if (state.activeCell) {
|
|
863
886
|
const { rowIndex, colIndex } = getIndexesActiveCell(state);
|
|
887
|
+
let cellElement = getActiveCellElement(template, state);
|
|
888
|
+
state.activeCell.focused = false;
|
|
864
889
|
// eslint-disable-next-line @lwc/lwc/no-async-operation
|
|
865
890
|
setTimeout(() => {
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
891
|
+
// check cellElement; value may have changed
|
|
892
|
+
if (
|
|
893
|
+
!cellElement ||
|
|
894
|
+
!isValidCell(
|
|
895
|
+
state,
|
|
896
|
+
cellElement.rowKeyValue,
|
|
897
|
+
cellElement.colKeyValue
|
|
898
|
+
)
|
|
899
|
+
) {
|
|
900
|
+
cellElement = getActiveCellElement(template, state);
|
|
901
|
+
}
|
|
874
902
|
if (cellElement) {
|
|
875
903
|
if (document.activeElement === cellElement) {
|
|
876
904
|
cellElement.blur();
|
|
@@ -940,18 +968,12 @@ export function resetCellToFocusFromPrev(state) {
|
|
|
940
968
|
/**
|
|
941
969
|
* It adds and the focus classes to the th/td or div[role=gridcell/rowheader].
|
|
942
970
|
*
|
|
943
|
-
* @param {node}
|
|
971
|
+
* @param {node} template - the custom element template `this.template`
|
|
944
972
|
* @param {object} state - datatable state
|
|
945
973
|
*/
|
|
946
|
-
export function addFocusStylesToActiveCell(
|
|
947
|
-
const
|
|
948
|
-
|
|
949
|
-
const cellElement = getCellElementByIndexes(
|
|
950
|
-
element,
|
|
951
|
-
rowIndex,
|
|
952
|
-
colIndex,
|
|
953
|
-
state
|
|
954
|
-
);
|
|
974
|
+
export function addFocusStylesToActiveCell(template, state) {
|
|
975
|
+
const cellElement = getActiveCellElement(template, state);
|
|
976
|
+
state.activeCell.focused = true;
|
|
955
977
|
|
|
956
978
|
if (cellElement) {
|
|
957
979
|
cellElement.parentElement.classList.add(FOCUS_CLASS);
|
|
@@ -959,31 +981,22 @@ export function addFocusStylesToActiveCell(element, state) {
|
|
|
959
981
|
}
|
|
960
982
|
|
|
961
983
|
/**
|
|
962
|
-
* It set the focus to the current activeCell, this operation
|
|
984
|
+
* It set the focus to the row of current activeCell, this operation implies multiple changes
|
|
963
985
|
* - update the tabindex of the activeCell
|
|
964
986
|
* - set the current keyboard mode
|
|
965
|
-
* - set the focus to the
|
|
966
|
-
* @param {node}
|
|
987
|
+
* - set the focus to the row
|
|
988
|
+
* @param {node} template - the custom element root `this.template`
|
|
967
989
|
* @param {object} state - datatable state
|
|
968
990
|
*/
|
|
969
|
-
function setFocusActiveRow(
|
|
991
|
+
function setFocusActiveRow(template, state) {
|
|
970
992
|
const { rowIndex } = getIndexesActiveCell(state);
|
|
993
|
+
const row = getActiveCellRow(template, state);
|
|
971
994
|
|
|
972
995
|
updateTabIndexRow(state, rowIndex);
|
|
973
996
|
// eslint-disable-next-line @lwc/lwc/no-async-operation
|
|
974
997
|
setTimeout(() => {
|
|
975
|
-
|
|
976
|
-
row
|
|
977
|
-
|
|
978
|
-
const scrollableY = element.querySelector('.slds-scrollable_y');
|
|
979
|
-
const scrollingParent = scrollableY.parentElement;
|
|
980
|
-
const parentRect = scrollingParent.getBoundingClientRect();
|
|
981
|
-
const findMeRect = row.getBoundingClientRect();
|
|
982
|
-
if (findMeRect.top < parentRect.top + TOP_MARGIN) {
|
|
983
|
-
scrollableY.scrollTop -= SCROLL_OFFSET;
|
|
984
|
-
} else if (findMeRect.bottom > parentRect.bottom - BOTTOM_MARGIN) {
|
|
985
|
-
scrollableY.scrollTop += SCROLL_OFFSET;
|
|
986
|
-
}
|
|
998
|
+
row.focus({ preventScroll: true });
|
|
999
|
+
updateScrollTop(state, template, row);
|
|
987
1000
|
}, 0);
|
|
988
1001
|
}
|
|
989
1002
|
|
|
@@ -991,15 +1004,15 @@ function setFocusActiveRow(element, state) {
|
|
|
991
1004
|
* It blurs the active row, this operation implies multiple changes
|
|
992
1005
|
* - blur the active row
|
|
993
1006
|
* - update the tabindex to -1
|
|
994
|
-
* @param {node}
|
|
1007
|
+
* @param {node} template - the custom element root `this.template`
|
|
995
1008
|
* @param {object} state - datatable state
|
|
996
1009
|
*/
|
|
997
|
-
function setBlurActiveRow(
|
|
1010
|
+
function setBlurActiveRow(template, state) {
|
|
998
1011
|
if (state.activeCell) {
|
|
999
1012
|
const { rowIndex } = getIndexesActiveCell(state);
|
|
1000
1013
|
// eslint-disable-next-line @lwc/lwc/no-async-operation
|
|
1001
1014
|
setTimeout(() => {
|
|
1002
|
-
const row =
|
|
1015
|
+
const row = getActiveCellRow(template, state);
|
|
1003
1016
|
if (document.activeElement === row) {
|
|
1004
1017
|
row.blur();
|
|
1005
1018
|
}
|
|
@@ -1017,13 +1030,7 @@ function setBlurActiveRow(element, state) {
|
|
|
1017
1030
|
*/
|
|
1018
1031
|
export function refocusCellElement(template, state, needsRefocusOnCellElement) {
|
|
1019
1032
|
if (needsRefocusOnCellElement) {
|
|
1020
|
-
const
|
|
1021
|
-
const cellElement = getCellElementByIndexes(
|
|
1022
|
-
template,
|
|
1023
|
-
rowIndex,
|
|
1024
|
-
colIndex,
|
|
1025
|
-
state
|
|
1026
|
-
);
|
|
1033
|
+
const cellElement = getActiveCellElement(template, state);
|
|
1027
1034
|
if (cellElement) {
|
|
1028
1035
|
cellElement.parentElement.focus();
|
|
1029
1036
|
}
|
|
@@ -1056,13 +1063,8 @@ export function handleDatatableFocusIn(event) {
|
|
|
1056
1063
|
// workaround for delegatesFocus issue that focusin is called when not supposed to W-6220418
|
|
1057
1064
|
if (isFocusInside(event.currentTarget)) {
|
|
1058
1065
|
if (!state.rowMode && state.activeCell) {
|
|
1059
|
-
|
|
1060
|
-
const cellElement =
|
|
1061
|
-
this.template,
|
|
1062
|
-
rowIndex,
|
|
1063
|
-
colIndex,
|
|
1064
|
-
state
|
|
1065
|
-
);
|
|
1066
|
+
state.activeCell.focused = true;
|
|
1067
|
+
const cellElement = getActiveCellElement(this.template, state);
|
|
1066
1068
|
// we need to check because of the tree,
|
|
1067
1069
|
// at this point it may remove/change the rows/keys because opening or closing a row.
|
|
1068
1070
|
if (cellElement) {
|
|
@@ -1090,13 +1092,7 @@ export function handleDatatableFocusOut(event) {
|
|
|
1090
1092
|
state.isExitingActionMode)
|
|
1091
1093
|
) {
|
|
1092
1094
|
if (state.activeCell && !state.rowMode) {
|
|
1093
|
-
const
|
|
1094
|
-
const cellElement = getCellElementByIndexes(
|
|
1095
|
-
this.template,
|
|
1096
|
-
rowIndex,
|
|
1097
|
-
colIndex,
|
|
1098
|
-
state
|
|
1099
|
-
);
|
|
1095
|
+
const cellElement = getActiveCellElement(this.template, state);
|
|
1100
1096
|
// we need to check because of the tree,
|
|
1101
1097
|
// at this point it may remove/change the rows/keys because opening or closing a row.
|
|
1102
1098
|
if (cellElement) {
|
|
@@ -1317,40 +1313,24 @@ function isHeaderRow(rowIndex) {
|
|
|
1317
1313
|
return rowIndex === -1;
|
|
1318
1314
|
}
|
|
1319
1315
|
|
|
1320
|
-
function
|
|
1321
|
-
|
|
1322
|
-
return isRenderModeRoleBased ? selectors.roleBased : selectors.default;
|
|
1323
|
-
}
|
|
1324
|
-
|
|
1325
|
-
function getDataRow(rowIndex, isRenderModeRoleBased) {
|
|
1326
|
-
const dataRowRowGroupSelector = isRenderModeRoleBased
|
|
1327
|
-
? SELECTORS.dataRowRowGroup.roleBased
|
|
1328
|
-
: SELECTORS.dataRowRowGroup.default;
|
|
1329
|
-
return `${dataRowRowGroupSelector} > :nth-child(${rowIndex + 1})`;
|
|
1316
|
+
export function getDataRow(rowKeyValue) {
|
|
1317
|
+
return `[data-row-key-value="${rowKeyValue}"]`;
|
|
1330
1318
|
}
|
|
1331
1319
|
|
|
1332
|
-
export function
|
|
1333
|
-
const
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
selector = `${getHeaderRow(isRenderModeRoleBased)}
|
|
1338
|
-
> :nth-child(${colIndex + 1}) > :first-child`;
|
|
1339
|
-
return element.querySelector(selector);
|
|
1340
|
-
}
|
|
1341
|
-
|
|
1342
|
-
selector = `${getDataRow(rowIndex, isRenderModeRoleBased)}
|
|
1343
|
-
> :nth-child(${colIndex + 1}) > :first-child`;
|
|
1344
|
-
return element.querySelector(selector);
|
|
1320
|
+
export function getCellElementByKeys(template, rowKeyValue, colKeyValue) {
|
|
1321
|
+
const selector = `${getDataRow(
|
|
1322
|
+
rowKeyValue
|
|
1323
|
+
)} [data-col-key-value="${colKeyValue}"] > :first-child`;
|
|
1324
|
+
return template.querySelector(selector);
|
|
1345
1325
|
}
|
|
1346
1326
|
|
|
1347
|
-
function
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1327
|
+
function getActiveCellRow(template, state) {
|
|
1328
|
+
if (state.activeCell) {
|
|
1329
|
+
const { rowKeyValue } = state.activeCell;
|
|
1330
|
+
const selector = getDataRow(rowKeyValue);
|
|
1331
|
+
return template.querySelector(selector);
|
|
1351
1332
|
}
|
|
1352
|
-
|
|
1353
|
-
return element.querySelector(getDataRow(rowIndex, isRenderModeRoleBased));
|
|
1333
|
+
return null;
|
|
1354
1334
|
}
|
|
1355
1335
|
|
|
1356
1336
|
export function getRowParent(state, rowLevel, rowIndex) {
|
|
@@ -1374,3 +1354,58 @@ function getCellFromIndexes(state, rowIndex, colIndex) {
|
|
|
1374
1354
|
}
|
|
1375
1355
|
return undefined;
|
|
1376
1356
|
}
|
|
1357
|
+
|
|
1358
|
+
function updateScrollTop(state, template, element) {
|
|
1359
|
+
const scrollableY = template.querySelector('.slds-scrollable_y');
|
|
1360
|
+
const scrollingParent = scrollableY.parentElement;
|
|
1361
|
+
const parentRect = scrollingParent.getBoundingClientRect();
|
|
1362
|
+
const findMeRect = element.getBoundingClientRect();
|
|
1363
|
+
if (findMeRect.top < parentRect.top + TOP_MARGIN) {
|
|
1364
|
+
scrollableY.scrollTop -= SCROLL_OFFSET;
|
|
1365
|
+
} else if (findMeRect.bottom > parentRect.bottom - BOTTOM_MARGIN) {
|
|
1366
|
+
scrollableY.scrollTop += SCROLL_OFFSET;
|
|
1367
|
+
}
|
|
1368
|
+
findFirstVisibleIndex(state, scrollableY.scrollTop);
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
function scrollToCell(state, template, rowIndex) {
|
|
1372
|
+
const { firstVisibleIndex, bufferSize, renderedRowCount, rowHeight } =
|
|
1373
|
+
state;
|
|
1374
|
+
|
|
1375
|
+
let scrollTop = rowIndex * rowHeight;
|
|
1376
|
+
if (firstVisibleIndex > rowIndex) {
|
|
1377
|
+
const rowsInViewport = renderedRowCount - 2 * bufferSize;
|
|
1378
|
+
scrollTop = Math.max(scrollTop - rowsInViewport * rowHeight, 0);
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
const scrollableY = template.querySelector('.slds-scrollable_y');
|
|
1382
|
+
scrollableY.scrollTop = scrollTop;
|
|
1383
|
+
findFirstVisibleIndex(state, scrollTop);
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
export function isActiveCellEditable(state) {
|
|
1387
|
+
const { activeCell, rows, columns } = state;
|
|
1388
|
+
if (activeCell) {
|
|
1389
|
+
const { rowIndex, colIndex } = getIndexesActiveCell(state);
|
|
1390
|
+
return isCellEditable(rows[rowIndex], columns[colIndex]);
|
|
1391
|
+
}
|
|
1392
|
+
return false;
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
export function isValidCell(state, rowKeyValue, colKeyValue) {
|
|
1396
|
+
if (rowKeyValue === HEADER_ROW) {
|
|
1397
|
+
return state.headerIndexes[colKeyValue] !== undefined;
|
|
1398
|
+
}
|
|
1399
|
+
const row = getRowByKey(state, rowKeyValue);
|
|
1400
|
+
const colIndex = getStateColumnIndex(state, colKeyValue);
|
|
1401
|
+
|
|
1402
|
+
return row && row.cells[colIndex];
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
function isActiveCellValid(state) {
|
|
1406
|
+
if (state.activeCell) {
|
|
1407
|
+
const { rowKeyValue, colKeyValue } = state.activeCell;
|
|
1408
|
+
return isValidCell(state, rowKeyValue, colKeyValue);
|
|
1409
|
+
}
|
|
1410
|
+
return false;
|
|
1411
|
+
}
|