lightning-base-components 1.14.2-alpha → 1.14.6-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 +33 -1
- package/package.json +20 -4
- package/scopedImports/@salesforce-label-LightningDualListbox.movedOptionsPlural.js +1 -0
- package/scopedImports/@salesforce-label-LightningDualListbox.movedOptionsSingular.js +1 -0
- package/scopedImports/@salesforce-label-LightningErrorMessage.validitySelectAtleastOne.js +1 -0
- package/scopedImports/@salesforce-label-LightningMap.titleWithAddress.js +1 -0
- package/scopedImports/@salesforce-label-LightningModalBase.cancelandclose.js +1 -0
- package/src/lightning/ariaObserver/__component__/ariaObserver.spec.js +9 -0
- package/src/lightning/ariaObserver/__docs__/ariaObserver.md +142 -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/buttonMenu/keyboard.js +0 -10
- package/src/lightning/card/card.html +6 -0
- package/src/lightning/checkboxGroup/checkboxGroup.html +2 -2
- package/src/lightning/checkboxGroup/checkboxGroup.js +6 -1
- package/src/lightning/colorPickerCustom/colorPickerCustom.js +20 -1
- package/src/lightning/datatable/__docs__/datatable.md +55 -0
- package/src/lightning/datatable/__examples__/basic/basic.html +1 -1
- 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/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-shared.js +1 -1
- package/src/lightning/datatable/datatable.js +104 -33
- package/src/lightning/datatable/errors.js +20 -9
- package/src/lightning/datatable/fixedWidthStrategy.js +43 -8
- package/src/lightning/datatable/headerActions.js +77 -49
- package/src/lightning/datatable/infiniteLoading.js +100 -28
- package/src/lightning/datatable/inlineEdit.js +505 -379
- package/src/lightning/datatable/inlineEditShared.js +24 -0
- package/src/lightning/datatable/keyboard.js +162 -127
- package/src/lightning/datatable/renderManager.js +208 -133
- package/src/lightning/datatable/{datatableResizeObserver.js → resizeObserver.js} +46 -29
- package/src/lightning/datatable/resizeSensor.js +8 -0
- package/src/lightning/datatable/rowLevelActions.js +17 -13
- package/src/lightning/datatable/rowNumber.js +54 -20
- package/src/lightning/datatable/rowSelection.js +760 -0
- package/src/lightning/datatable/rowSelectionShared.js +79 -0
- package/src/lightning/datatable/rows.js +17 -6
- package/src/lightning/datatable/state.js +16 -2
- package/src/lightning/datatable/templates/div/div.css +4 -0
- package/src/lightning/datatable/templates/div/div.html +128 -117
- package/src/lightning/datatable/templates/table/table.html +5 -0
- package/src/lightning/datatable/utils.js +14 -0
- package/src/lightning/datatable/widthManagerShared.js +27 -3
- package/src/lightning/datatable/wrapText.js +77 -47
- package/src/lightning/dualListbox/dualListbox.html +1 -1
- package/src/lightning/dualListbox/dualListbox.js +42 -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/input/input.html +2 -5
- package/src/lightning/inputUtils/validity.js +12 -1
- package/src/lightning/pillContainer/__docs__/pillContainer.md +45 -1
- package/src/lightning/positionLibrary/positionLibrary.js +31 -43
- package/src/lightning/primitiveCellActions/primitiveCellActions.js +69 -12
- package/src/lightning/primitiveCellFactory/cellWithStandardLayout.html +13 -11
- package/src/lightning/primitiveCellFactory/primitiveCellFactory.js +13 -8
- package/src/lightning/primitiveDatatableIeditPanel/primitiveDatatableIeditPanel.html +17 -14
- package/src/lightning/primitiveDatatableIeditPanel/primitiveDatatableIeditPanel.js +167 -98
- package/src/lightning/primitiveDatatableIeditTypeFactory/primitiveDatatableIeditTypeFactory.js +94 -69
- package/src/lightning/primitiveDatatableStatusBar/primitiveDatatableStatusBar.html +4 -4
- package/src/lightning/primitiveDatatableStatusBar/primitiveDatatableStatusBar.js +4 -4
- package/src/lightning/primitiveHeaderActions/primitiveHeaderActions.js +99 -37
- package/src/lightning/progressIndicator/progressIndicator.js +1 -1
- package/src/lightning/progressStep/progressStep.js +1 -1
- package/src/lightning/spinner/spinner.html +1 -1
- package/src/lightning/spinner/spinner.js +12 -0
- package/src/lightning/staticMap/staticMap.html +1 -0
- package/src/lightning/staticMap/staticMap.js +39 -2
- package/src/lightning/utils/classSet.js +4 -1
- package/src/lightning/utilsPrivate/phonify.js +1 -1
- package/scopedImports/@salesforce-label-LightningModalBase.close.js +0 -1
- package/src/lightning/datatable/inlineEdit-shared.js +0 -14
- package/src/lightning/datatable/selector-shared.js +0 -38
- package/src/lightning/datatable/selector.js +0 -527
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retrieves the dirty/unsaved value of a cell that resulted from an inline
|
|
3
|
+
* edit change. If no change was made on the cell, this function
|
|
4
|
+
* returns `undefined`.
|
|
5
|
+
*
|
|
6
|
+
* @param {Object} state - datatable's state object
|
|
7
|
+
* @param {String} rowKeyValue - computed id for the row
|
|
8
|
+
* @param {String} colKeyValue - computed id for the column
|
|
9
|
+
* @returns {String} The dirty/unsaved value of the cell.
|
|
10
|
+
* If no change was made, this returns `undefined`
|
|
11
|
+
*/
|
|
12
|
+
export function getDirtyValueFromCell(state, rowKeyValue, colKeyValue) {
|
|
13
|
+
const dirtyValues = state.inlineEdit.dirtyValues;
|
|
14
|
+
|
|
15
|
+
if (
|
|
16
|
+
dirtyValues &&
|
|
17
|
+
dirtyValues[rowKeyValue] &&
|
|
18
|
+
dirtyValues[rowKeyValue][colKeyValue]
|
|
19
|
+
) {
|
|
20
|
+
return dirtyValues[rowKeyValue][colKeyValue];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
@@ -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 { setFirstVisibleIndex } from './renderManager';
|
|
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';
|
|
@@ -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 {node}
|
|
130
|
+
* @param {node} template - the custom element root `this.template`
|
|
125
131
|
* @param {object} state - datatable state
|
|
126
132
|
* @param {event} event - custom DOM event sent by the cell
|
|
127
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) {
|
|
@@ -1306,7 +1302,7 @@ export function updateRowNavigationMode(hadTreeDataTypePreviously, state) {
|
|
|
1306
1302
|
|
|
1307
1303
|
/***************************** HELPER FUNCTIONS *****************************/
|
|
1308
1304
|
|
|
1309
|
-
function isCellElement(tagName, role) {
|
|
1305
|
+
export function isCellElement(tagName, role) {
|
|
1310
1306
|
return (
|
|
1311
1307
|
SELECTORS.cell.default.includes(tagName) ||
|
|
1312
1308
|
SELECTORS.cell.roleBased.includes(role)
|
|
@@ -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;
|
|
1316
|
+
function getDataRow(rowKeyValue) {
|
|
1317
|
+
return `[data-row-key-value="${rowKeyValue}"]`;
|
|
1323
1318
|
}
|
|
1324
1319
|
|
|
1325
|
-
function
|
|
1326
|
-
const
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
return
|
|
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);
|
|
1330
1325
|
}
|
|
1331
1326
|
|
|
1332
|
-
|
|
1333
|
-
|
|
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);
|
|
1345
|
-
}
|
|
1346
|
-
|
|
1347
|
-
function getRowElementByIndexes(element, rowIndex, state) {
|
|
1348
|
-
const isRenderModeRoleBased = state.renderModeRoleBased;
|
|
1349
|
-
if (isHeaderRow(rowIndex)) {
|
|
1350
|
-
return element.querySelector(getHeaderRow(isRenderModeRoleBased));
|
|
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
|
+
setFirstVisibleIndex(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
|
+
setFirstVisibleIndex(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
|
+
}
|