lightning-base-components 1.13.9-alpha → 1.14.3-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 +1 -0
- package/package.json +21 -1
- package/scopedImports/@salesforce-internal-core.appVersion.js +1 -1
- 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-LightningLookup.recentItems.js +1 -0
- package/scopedImports/@salesforce-label-LightningMap.titleWithAddress.js +1 -0
- package/src/lightning/ariaObserver/__component__/ariaObserver.spec.js +103 -0
- package/src/lightning/ariaObserver/__docs__/ariaObserver.md +142 -0
- package/src/lightning/{utilsPrivate/contentMutation.js → ariaObserver/ariaObserver.js} +51 -78
- package/src/lightning/baseCombobox/baseCombobox.html +1 -0
- package/src/lightning/baseCombobox/baseCombobox.js +14 -1
- 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/combobox/combobox.css +12 -0
- package/src/lightning/combobox/combobox.html +1 -0
- package/src/lightning/datatable/__docs__/datatable.md +55 -0
- package/src/lightning/datatable/__examples__/basic/basic.html +1 -1
- package/src/lightning/datatable/columnWidthManager.js +7 -3
- package/src/lightning/datatable/columns-shared.js +1 -1
- package/src/lightning/datatable/datatable.js +122 -40
- package/src/lightning/datatable/errors.js +20 -9
- package/src/lightning/datatable/headerActions.js +77 -49
- package/src/lightning/datatable/inlineEdit.js +520 -373
- package/src/lightning/datatable/inlineEditShared.js +24 -0
- package/src/lightning/datatable/keyboard.js +1077 -933
- package/src/lightning/datatable/renderManager.js +241 -129
- package/src/lightning/datatable/resizer.js +91 -108
- 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 +16 -5
- package/src/lightning/datatable/state.js +10 -10
- package/src/lightning/datatable/templates/div/div.css +23 -0
- package/src/lightning/datatable/templates/div/div.html +6 -5
- package/src/lightning/datatable/templates/table/table.html +4 -4
- package/src/lightning/datatable/utils.js +14 -0
- package/src/lightning/datatable/widthManagerShared.js +1 -1
- package/src/lightning/dualListbox/dualListbox.html +1 -1
- package/src/lightning/dualListbox/dualListbox.js +42 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/templates.js +2 -1
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/contract_alt.html +1 -2
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/contract_doc.html +8 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/templates.js +2 -1
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/contract_alt.html +1 -2
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/contract_doc.html +8 -0
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/templates.js +2 -1
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/contract_alt.html +1 -2
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/contract_doc.html +8 -0
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/templates.js +2 -1
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/contract_alt.html +1 -2
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/contract_doc.html +8 -0
- package/src/lightning/input/input.html +0 -1
- package/src/lightning/input/input.js +69 -48
- package/src/lightning/inputUtils/validity.js +12 -1
- package/src/lightning/pillContainer/__docs__/pillContainer.md +45 -1
- 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 +169 -80
- package/src/lightning/primitiveDatatableIeditTypeFactory/primitiveDatatableIeditTypeFactory.js +97 -62
- 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/primitiveHeaderFactory/nonsortableHeader.html +5 -4
- package/src/lightning/primitiveHeaderFactory/primitiveHeaderFactory.js +46 -46
- package/src/lightning/primitiveHeaderFactory/selectableHeader.html +25 -23
- package/src/lightning/primitiveHeaderFactory/sortableHeader.html +13 -9
- package/src/lightning/progressIndicator/progressIndicator.js +4 -6
- package/src/lightning/progressStep/progressStep.js +31 -22
- 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/utilsPrivate.js +12 -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
|
@@ -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
|
|
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;
|
|
@@ -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,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
|
-
}
|
|
@@ -1,527 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
resolveRowClassNames,
|
|
3
|
-
getRows,
|
|
4
|
-
getRowByKey,
|
|
5
|
-
getRowsTotal,
|
|
6
|
-
getRowIndexByKey,
|
|
7
|
-
rowKeyExists,
|
|
8
|
-
} from './rows';
|
|
9
|
-
import {
|
|
10
|
-
getColumns,
|
|
11
|
-
getStateColumnIndex,
|
|
12
|
-
SELECTABLE_ROW_CHECKBOX,
|
|
13
|
-
} from './columns';
|
|
14
|
-
import { isNonNegativeInteger } from './utils';
|
|
15
|
-
|
|
16
|
-
export {
|
|
17
|
-
getCurrentSelectionLength,
|
|
18
|
-
isSelectedRow,
|
|
19
|
-
isDisabledRow,
|
|
20
|
-
getRowSelectionInputType,
|
|
21
|
-
getMaxRowSelection,
|
|
22
|
-
} from './selector-shared';
|
|
23
|
-
|
|
24
|
-
import {
|
|
25
|
-
getCurrentSelectionLength,
|
|
26
|
-
isSelectedRow,
|
|
27
|
-
isDisabledRow,
|
|
28
|
-
getRowSelectionInputType,
|
|
29
|
-
getMaxRowSelection,
|
|
30
|
-
getSelectedRowsKeys as sharedGetSelectedRowsKeys,
|
|
31
|
-
} from './selector-shared';
|
|
32
|
-
|
|
33
|
-
// Looks like mocks are failing if this is exported via a direct export from selector-shared, so we need to
|
|
34
|
-
// implement this as a direct function
|
|
35
|
-
export function getSelectedRowsKeys(state) {
|
|
36
|
-
return sharedGetSelectedRowsKeys(state);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const MAX_ROW_SELECTION_DEFAULT = undefined;
|
|
40
|
-
|
|
41
|
-
export function getSelectorDefaultState() {
|
|
42
|
-
return {
|
|
43
|
-
selectedRowsKeys: {},
|
|
44
|
-
maxRowSelection: MAX_ROW_SELECTION_DEFAULT,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function handleSelectAllRows(event) {
|
|
49
|
-
event.stopPropagation();
|
|
50
|
-
markAllRowsSelected(this.state);
|
|
51
|
-
this.fireSelectedRowsChange(this.getSelectedRows());
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function handleDeselectAllRows(event) {
|
|
55
|
-
event.stopPropagation();
|
|
56
|
-
markAllRowsDeselected(this.state);
|
|
57
|
-
this.fireSelectedRowsChange(this.getSelectedRows());
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Will select the cell identified by rowKeyValue, colKeyValue.
|
|
62
|
-
* This will reflect as aria-selected="true" attribute in the cell td or th.
|
|
63
|
-
*
|
|
64
|
-
* Note: This change is volatile, and will be reset (lost) in the next index regeneration.
|
|
65
|
-
*
|
|
66
|
-
* @param {Object} state - the state of the datatable
|
|
67
|
-
* @param {String} rowKeyValue - the row key of the cell to select
|
|
68
|
-
* @param {String} colKeyValue - the col key of the cell to select
|
|
69
|
-
*/
|
|
70
|
-
export function markSelectedCell(state, rowKeyValue, colKeyValue) {
|
|
71
|
-
const row = getRowByKey(state, rowKeyValue);
|
|
72
|
-
const colIndex = getStateColumnIndex(state, colKeyValue);
|
|
73
|
-
|
|
74
|
-
if (row && colIndex) {
|
|
75
|
-
row.cells[colIndex].ariaSelected = 'true';
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Will deselect the cell identified by rowKeyValue, colKeyValue.
|
|
81
|
-
* This will reflect in removing aria-selected attribute in the cell td or th (if it was previously added).
|
|
82
|
-
*
|
|
83
|
-
* Note: This change is volatile, and will be reset (lost) in the next index regeneration.
|
|
84
|
-
*
|
|
85
|
-
* @param {Object} state - the state of the datatable
|
|
86
|
-
* @param {String} rowKeyValue - the row key of the cell to select
|
|
87
|
-
* @param {String} colKeyValue - the col key of the cell to select
|
|
88
|
-
*/
|
|
89
|
-
export function markDeselectedCell(state, rowKeyValue, colKeyValue) {
|
|
90
|
-
const row = getRowByKey(state, rowKeyValue);
|
|
91
|
-
const colIndex = getStateColumnIndex(state, colKeyValue);
|
|
92
|
-
|
|
93
|
-
if (row && colIndex) {
|
|
94
|
-
row.cells[colIndex].ariaSelected = false;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Returns the last rowKey that was clicked, false otherwise.
|
|
100
|
-
* @param {Object} state - the datatable state.
|
|
101
|
-
* @return {String | undefined } the row key or false.
|
|
102
|
-
*/
|
|
103
|
-
function getLastRowSelection(state) {
|
|
104
|
-
const lastSelectedRowKey = state.selectionLastSelectedRow;
|
|
105
|
-
const keyIsValid =
|
|
106
|
-
lastSelectedRowKey !== undefined &&
|
|
107
|
-
getRowIndexByKey(state, lastSelectedRowKey) !== undefined;
|
|
108
|
-
|
|
109
|
-
return keyIsValid ? lastSelectedRowKey : undefined;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function setLastRowSelection(state, rowKeyValue) {
|
|
113
|
-
state.selectionLastSelectedRow = rowKeyValue;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export function handleSelectRow(event) {
|
|
117
|
-
event.stopPropagation();
|
|
118
|
-
const { rowKeyValue, isMultiple } = event.detail;
|
|
119
|
-
let fromRowKey = rowKeyValue;
|
|
120
|
-
|
|
121
|
-
if (isMultiple) {
|
|
122
|
-
fromRowKey = getLastRowSelection(this.state) || rowKeyValue;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
markSelectedRowsInterval(this.state, fromRowKey, rowKeyValue);
|
|
126
|
-
setLastRowSelection(this.state, rowKeyValue);
|
|
127
|
-
this.fireSelectedRowsChange(this.getSelectedRows());
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
function markSelectedRowsInterval(state, startRowKey, endRowKey) {
|
|
131
|
-
const rows = getRows(state);
|
|
132
|
-
const { start, end } = getRowIntervalIndexes(state, startRowKey, endRowKey);
|
|
133
|
-
const maxRowSelection = getMaxRowSelection(state) || getRowsTotal(state);
|
|
134
|
-
let i = start,
|
|
135
|
-
maxSelectionReached;
|
|
136
|
-
|
|
137
|
-
do {
|
|
138
|
-
markRowSelected(state, rows[i].key);
|
|
139
|
-
maxSelectionReached =
|
|
140
|
-
getCurrentSelectionLength(state) >= maxRowSelection;
|
|
141
|
-
i++;
|
|
142
|
-
} while (i <= end && !maxSelectionReached);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
export function handleDeselectRow(event) {
|
|
146
|
-
event.stopPropagation();
|
|
147
|
-
const { rowKeyValue, isMultiple } = event.detail;
|
|
148
|
-
let fromRowKey = rowKeyValue;
|
|
149
|
-
|
|
150
|
-
if (isMultiple) {
|
|
151
|
-
fromRowKey = getLastRowSelection(this.state) || rowKeyValue;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
markDeselectedRowsInterval(this.state, fromRowKey, rowKeyValue);
|
|
155
|
-
setLastRowSelection(this.state, rowKeyValue);
|
|
156
|
-
this.fireSelectedRowsChange(this.getSelectedRows());
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
function getRowIntervalIndexes(state, startRowKey, endRowKey) {
|
|
160
|
-
const start =
|
|
161
|
-
startRowKey === 'HEADER' ? 0 : getRowIndexByKey(state, startRowKey);
|
|
162
|
-
const end = getRowIndexByKey(state, endRowKey);
|
|
163
|
-
|
|
164
|
-
return {
|
|
165
|
-
start: Math.min(start, end),
|
|
166
|
-
end: Math.max(start, end),
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
function markDeselectedRowsInterval(state, startRowKey, endRowKey) {
|
|
171
|
-
const rows = getRows(state);
|
|
172
|
-
const { start, end } = getRowIntervalIndexes(state, startRowKey, endRowKey);
|
|
173
|
-
|
|
174
|
-
for (let i = start; i <= end; i++) {
|
|
175
|
-
markRowDeselected(state, rows[i].key);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
function getSelectedDiff(state, value) {
|
|
180
|
-
const selectedRowsKeys = state.selectedRowsKeys;
|
|
181
|
-
return value.filter((key) => !selectedRowsKeys[key]);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
function getDeselectedDiff(state, value) {
|
|
185
|
-
const currentSelectedRowsKeys = state.selectedRowsKeys;
|
|
186
|
-
return Object.keys(currentSelectedRowsKeys).filter(
|
|
187
|
-
(key) => currentSelectedRowsKeys[key] && !value[key]
|
|
188
|
-
);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
function normalizeSelectedRowsKey(value) {
|
|
192
|
-
return value.reduce((map, key) => {
|
|
193
|
-
map[key] = true;
|
|
194
|
-
return map;
|
|
195
|
-
}, {});
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
function markRowsSelectedByKeys(state, keys) {
|
|
199
|
-
keys.forEach((rowKeyValue) => {
|
|
200
|
-
const row = getRowByKey(state, rowKeyValue);
|
|
201
|
-
row.isSelected = true;
|
|
202
|
-
row.ariaSelected = 'true';
|
|
203
|
-
row.classnames = resolveRowClassNames(row);
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
function markRowsDeselectedByKeys(state, keys) {
|
|
208
|
-
keys.forEach((rowKeyValue) => {
|
|
209
|
-
const row = getRowByKey(state, rowKeyValue);
|
|
210
|
-
row.isSelected = false;
|
|
211
|
-
row.ariaSelected = false;
|
|
212
|
-
row.classnames = resolveRowClassNames(row);
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
function filterValidKeys(state, keys) {
|
|
217
|
-
return keys.filter((key) => rowKeyExists(state, key));
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
export function setSelectedRowsKeys(state, value) {
|
|
221
|
-
if (Array.isArray(value)) {
|
|
222
|
-
const maxRowSelection = getMaxRowSelection(state);
|
|
223
|
-
const previousSelectionLength = getCurrentSelectionLength(state);
|
|
224
|
-
let selectedRows = filterValidKeys(state, value);
|
|
225
|
-
if (selectedRows.length > maxRowSelection) {
|
|
226
|
-
// eslint-disable-next-line no-console
|
|
227
|
-
console.warn(`The number of keys in selectedRows for lightning:datatable
|
|
228
|
-
exceeds the limit defined by maxRowSelection.`);
|
|
229
|
-
selectedRows = selectedRows.slice(0, maxRowSelection);
|
|
230
|
-
}
|
|
231
|
-
const normalizedSelectedRowsKeys =
|
|
232
|
-
normalizeSelectedRowsKey(selectedRows);
|
|
233
|
-
const selectionOperations = getSelectedDiff(state, selectedRows);
|
|
234
|
-
const deselectionOperations = getDeselectedDiff(
|
|
235
|
-
state,
|
|
236
|
-
normalizedSelectedRowsKeys
|
|
237
|
-
);
|
|
238
|
-
markRowsSelectedByKeys(state, selectionOperations);
|
|
239
|
-
markRowsDeselectedByKeys(state, deselectionOperations);
|
|
240
|
-
state.selectedRowsKeys = normalizedSelectedRowsKeys;
|
|
241
|
-
|
|
242
|
-
if (selectedRows.length === maxRowSelection && maxRowSelection > 1) {
|
|
243
|
-
markDeselectedRowDisabled(state);
|
|
244
|
-
} else if (
|
|
245
|
-
selectedRows.length < maxRowSelection &&
|
|
246
|
-
previousSelectionLength === maxRowSelection
|
|
247
|
-
) {
|
|
248
|
-
markDeselectedRowEnabled(state);
|
|
249
|
-
}
|
|
250
|
-
} else {
|
|
251
|
-
// eslint-disable-next-line no-console
|
|
252
|
-
console.error(`The "selectedRows" passed into "lightning:datatable"
|
|
253
|
-
must be an Array with the keys of the selected rows. We receive instead ${value}`);
|
|
254
|
-
markAllRowsDeselected(state);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
export function getHideSelectAllCheckbox(state) {
|
|
259
|
-
return getMaxRowSelection(state) === 1;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* sets maxRowSelection to provided value,
|
|
264
|
-
* only keeping up to maxRowSelection values selected
|
|
265
|
-
* Use input type checkbox if maxRowSelection > 1
|
|
266
|
-
* and input type is radio if maxRowSelection = 1.
|
|
267
|
-
* Invalid values are set to default and log an error
|
|
268
|
-
* @param {Object} state - the datatable state.
|
|
269
|
-
* @param {Number | String} - value to set for maxRowSelection
|
|
270
|
-
*/
|
|
271
|
-
export function setMaxRowSelection(state, value) {
|
|
272
|
-
const previousSelectedRowsKeys = getSelectedRowsKeys(state);
|
|
273
|
-
markAllRowsDeselected(state);
|
|
274
|
-
if (isNonNegativeInteger(value)) {
|
|
275
|
-
const previousMaxRowSelection = getMaxRowSelection(state);
|
|
276
|
-
state.maxRowSelection = Number(value);
|
|
277
|
-
const newMaxRowSelection = getMaxRowSelection(state);
|
|
278
|
-
// reselect up to maxRowSelection rows
|
|
279
|
-
const numberOfRows = Math.min(
|
|
280
|
-
previousSelectedRowsKeys.length,
|
|
281
|
-
newMaxRowSelection
|
|
282
|
-
);
|
|
283
|
-
for (let i = 0; i < numberOfRows; i++) {
|
|
284
|
-
markRowSelected(state, previousSelectedRowsKeys[i]);
|
|
285
|
-
}
|
|
286
|
-
if (
|
|
287
|
-
inputTypeNeedsToChange(
|
|
288
|
-
previousMaxRowSelection,
|
|
289
|
-
getMaxRowSelection(state)
|
|
290
|
-
)
|
|
291
|
-
) {
|
|
292
|
-
updateRowSelectionInputType(state);
|
|
293
|
-
updateSelectionState(state);
|
|
294
|
-
}
|
|
295
|
-
} else {
|
|
296
|
-
state.maxRowSelection = MAX_ROW_SELECTION_DEFAULT;
|
|
297
|
-
// eslint-disable-next-line no-console
|
|
298
|
-
console.error(
|
|
299
|
-
`The maxRowSelection value passed into lightning:datatable
|
|
300
|
-
should be a positive integer. We receive instead (${value}).`
|
|
301
|
-
);
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
export function inputTypeNeedsToChange(
|
|
306
|
-
previousMaxRowSelection,
|
|
307
|
-
newMaxRowSelection
|
|
308
|
-
) {
|
|
309
|
-
return (
|
|
310
|
-
(previousMaxRowSelection === 1 &&
|
|
311
|
-
isMultiSelection(newMaxRowSelection)) ||
|
|
312
|
-
(isMultiSelection(previousMaxRowSelection) &&
|
|
313
|
-
newMaxRowSelection === 1) ||
|
|
314
|
-
previousMaxRowSelection === 0 ||
|
|
315
|
-
newMaxRowSelection === 0
|
|
316
|
-
);
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
export function isMultiSelection(value) {
|
|
320
|
-
return value > 1 || value === undefined;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
export function updateRowSelectionInputType(state) {
|
|
324
|
-
const type = getRowSelectionInputType(state);
|
|
325
|
-
const rows = getRows(state);
|
|
326
|
-
|
|
327
|
-
rows.forEach((row) => {
|
|
328
|
-
row.inputType = type;
|
|
329
|
-
row.isDisabled = isDisabledRow(state, row.key);
|
|
330
|
-
});
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
export function markDeselectedRowDisabled(state) {
|
|
334
|
-
const rows = getRows(state);
|
|
335
|
-
rows.forEach((row) => {
|
|
336
|
-
if (!isSelectedRow(state, row.key)) {
|
|
337
|
-
row.isDisabled = true;
|
|
338
|
-
}
|
|
339
|
-
});
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
export function markDeselectedRowEnabled(state) {
|
|
343
|
-
const rows = getRows(state);
|
|
344
|
-
rows.forEach((row) => {
|
|
345
|
-
if (!isSelectedRow(state, row.key)) {
|
|
346
|
-
row.isDisabled = false;
|
|
347
|
-
}
|
|
348
|
-
});
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
export function markRowSelected(state, rowKeyValue) {
|
|
352
|
-
const row = getRowByKey(state, rowKeyValue);
|
|
353
|
-
const maxRowSelection = getMaxRowSelection(state) || getRowsTotal(state);
|
|
354
|
-
const previousSelectionLength = getCurrentSelectionLength(state);
|
|
355
|
-
|
|
356
|
-
row.isSelected = true;
|
|
357
|
-
row.ariaSelected = 'true';
|
|
358
|
-
row.classnames = resolveRowClassNames(row);
|
|
359
|
-
|
|
360
|
-
if (maxRowSelection > 1) {
|
|
361
|
-
addKeyToSelectedRowKeys(state, row.key);
|
|
362
|
-
if (previousSelectionLength + 1 === maxRowSelection) {
|
|
363
|
-
markDeselectedRowDisabled(state);
|
|
364
|
-
}
|
|
365
|
-
} else {
|
|
366
|
-
if (previousSelectionLength === 1) {
|
|
367
|
-
const previousSelectedRow = getRowByKey(
|
|
368
|
-
state,
|
|
369
|
-
Object.keys(state.selectedRowsKeys)[0]
|
|
370
|
-
);
|
|
371
|
-
previousSelectedRow.isSelected = false;
|
|
372
|
-
previousSelectedRow.ariaSelected = false;
|
|
373
|
-
previousSelectedRow.classnames =
|
|
374
|
-
resolveRowClassNames(previousSelectedRow);
|
|
375
|
-
resetSelectedRowsKeys(state);
|
|
376
|
-
}
|
|
377
|
-
addKeyToSelectedRowKeys(state, row.key);
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
export function markRowDeselected(state, rowKeyValue) {
|
|
382
|
-
const row = getRowByKey(state, rowKeyValue);
|
|
383
|
-
const maxRowSelection = getMaxRowSelection(state);
|
|
384
|
-
|
|
385
|
-
row.isSelected = false;
|
|
386
|
-
row.ariaSelected = false;
|
|
387
|
-
row.classnames = resolveRowClassNames(row);
|
|
388
|
-
removeKeyFromSelectedRowKeys(state, row.key);
|
|
389
|
-
|
|
390
|
-
if (getCurrentSelectionLength(state) === maxRowSelection - 1) {
|
|
391
|
-
markDeselectedRowEnabled(state);
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
export function resetSelectedRowsKeys(state) {
|
|
396
|
-
state.selectedRowsKeys = {};
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
export function markAllRowsSelected(state) {
|
|
400
|
-
const rows = getRows(state);
|
|
401
|
-
const maxRowSelection = getMaxRowSelection(state);
|
|
402
|
-
|
|
403
|
-
resetSelectedRowsKeys(state);
|
|
404
|
-
rows.forEach((row, index) => {
|
|
405
|
-
if (index < maxRowSelection || maxRowSelection === undefined) {
|
|
406
|
-
row.isSelected = true;
|
|
407
|
-
row.ariaSelected = 'true';
|
|
408
|
-
row.classnames = resolveRowClassNames(row);
|
|
409
|
-
addKeyToSelectedRowKeys(state, row.key);
|
|
410
|
-
} else {
|
|
411
|
-
row.isDisabled = true;
|
|
412
|
-
row.isSelected = false;
|
|
413
|
-
row.ariaSelected = false;
|
|
414
|
-
row.classnames = resolveRowClassNames(row);
|
|
415
|
-
}
|
|
416
|
-
});
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
export function markAllRowsDeselected(state) {
|
|
420
|
-
const rows = getRows(state);
|
|
421
|
-
|
|
422
|
-
resetSelectedRowsKeys(state);
|
|
423
|
-
rows.forEach((row) => {
|
|
424
|
-
row.isDisabled = false;
|
|
425
|
-
row.isSelected = false;
|
|
426
|
-
row.ariaSelected = false;
|
|
427
|
-
row.classnames = resolveRowClassNames(row);
|
|
428
|
-
});
|
|
429
|
-
return state;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
export function syncSelectedRowsKeys(state, selectedRows) {
|
|
433
|
-
let changed = false;
|
|
434
|
-
const { selectedRowsKeys, keyField } = state;
|
|
435
|
-
|
|
436
|
-
if (Object.keys(selectedRowsKeys).length !== selectedRows.length) {
|
|
437
|
-
changed = true;
|
|
438
|
-
state.selectedRowsKeys = updateSelectedRowsKeysFromSelectedRows(
|
|
439
|
-
selectedRows,
|
|
440
|
-
keyField
|
|
441
|
-
);
|
|
442
|
-
} else {
|
|
443
|
-
changed = selectedRows.some((row) => !selectedRowsKeys[row[keyField]]);
|
|
444
|
-
if (changed) {
|
|
445
|
-
state.selectedRowsKeys = updateSelectedRowsKeysFromSelectedRows(
|
|
446
|
-
selectedRows,
|
|
447
|
-
keyField
|
|
448
|
-
);
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
updateSelectionState(state);
|
|
453
|
-
|
|
454
|
-
return {
|
|
455
|
-
ifChanged: (callback) => {
|
|
456
|
-
if (changed && typeof callback === 'function') {
|
|
457
|
-
callback(selectedRows);
|
|
458
|
-
}
|
|
459
|
-
},
|
|
460
|
-
};
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
export function handleRowSelectionChange() {
|
|
464
|
-
updateSelectionState(this.state);
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
function updateSelectedRowsKeysFromSelectedRows(selectedRows, keyField) {
|
|
468
|
-
return selectedRows.reduce((selectedRowsKeys, row) => {
|
|
469
|
-
selectedRowsKeys[row[keyField]] = true;
|
|
470
|
-
return selectedRowsKeys;
|
|
471
|
-
}, {});
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
function addKeyToSelectedRowKeys(state, key) {
|
|
475
|
-
state.selectedRowsKeys[key] = true;
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
function removeKeyFromSelectedRowKeys(state, key) {
|
|
479
|
-
// not using delete this.state.selectedRowsKeys[key]
|
|
480
|
-
// because that cause perf issues
|
|
481
|
-
state.selectedRowsKeys[key] = false;
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
export function updateSelectionState(state) {
|
|
485
|
-
const selectBoxesColumnIndex = getSelectBoxesColumnIndex(state);
|
|
486
|
-
if (selectBoxesColumnIndex >= 0) {
|
|
487
|
-
state.columns[selectBoxesColumnIndex] = Object.assign(
|
|
488
|
-
{},
|
|
489
|
-
state.columns[selectBoxesColumnIndex],
|
|
490
|
-
{
|
|
491
|
-
bulkSelection: getBulkSelectionState(state),
|
|
492
|
-
isBulkSelectionDisabled: isBulkSelectionDisabled(state),
|
|
493
|
-
}
|
|
494
|
-
);
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
export function getBulkSelectionState(state) {
|
|
499
|
-
const selected = getCurrentSelectionLength(state);
|
|
500
|
-
const total = getMaxRowSelection(state) || getRowsTotal(state);
|
|
501
|
-
if (selected === 0) {
|
|
502
|
-
return 'none';
|
|
503
|
-
} else if (selected === total) {
|
|
504
|
-
return 'all';
|
|
505
|
-
}
|
|
506
|
-
return 'some';
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
export function isBulkSelectionDisabled(state) {
|
|
510
|
-
return getRowsTotal(state) === 0 || getMaxRowSelection(state) === 0;
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
function getSelectBoxesColumnIndex(state) {
|
|
514
|
-
const columns = getColumns(state) || [];
|
|
515
|
-
let selectBoxColumnIndex = -1;
|
|
516
|
-
|
|
517
|
-
columns.some((column, index) => {
|
|
518
|
-
if (column.type === SELECTABLE_ROW_CHECKBOX) {
|
|
519
|
-
selectBoxColumnIndex = index;
|
|
520
|
-
return true;
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
return false;
|
|
524
|
-
});
|
|
525
|
-
|
|
526
|
-
return selectBoxColumnIndex;
|
|
527
|
-
}
|