lightning-base-components 1.14.3-alpha → 1.14.4-alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/metadata/raptor.json +23 -0
- package/package.json +4 -4
- package/scopedImports/@salesforce-label-LightningModalBase.cancelandclose.js +1 -0
- package/src/lightning/ariaObserver/__component__/ariaObserver.spec.js +9 -0
- package/src/lightning/ariaObserver/ariaObserver.js +24 -35
- package/src/lightning/datatable/datatable.js +44 -49
- package/src/lightning/datatable/infiniteLoading.js +100 -28
- package/src/lightning/datatable/inlineEdit.js +21 -30
- package/src/lightning/datatable/keyboard.js +161 -126
- package/src/lightning/datatable/renderManager.js +76 -120
- package/src/lightning/datatable/rows.js +4 -4
- package/src/lightning/datatable/state.js +6 -1
- package/src/lightning/datatable/templates/div/div.html +5 -0
- package/src/lightning/datatable/templates/table/table.html +5 -0
- package/src/lightning/datatable/wrapText.js +77 -47
- 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 +1 -4
- package/scopedImports/@salesforce-label-LightningModalBase.close.js +0 -1
|
@@ -16,29 +16,32 @@ export function isViewportRenderingEnabled(state) {
|
|
|
16
16
|
return state.enableViewportRendering;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
export function
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function getDTRenderedRowCount() {
|
|
31
|
-
return this._renderedRowCount;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function setDTRenderedRowCount(renderedRowCount) {
|
|
35
|
-
this._renderedRowCount = renderedRowCount;
|
|
19
|
+
export function setVirtualize(state, value) {
|
|
20
|
+
if (state.renderModeRoleBased) {
|
|
21
|
+
state.virtualize = normalizeString(value, {
|
|
22
|
+
fallbackValue: '', //no virtualization enabled
|
|
23
|
+
validValues: [VERTICAL_VIRTUALIZATION],
|
|
24
|
+
});
|
|
25
|
+
} else {
|
|
26
|
+
state.virtualize = '';
|
|
27
|
+
}
|
|
36
28
|
}
|
|
37
29
|
|
|
38
30
|
export function getDTWrapperHeight() {
|
|
39
31
|
return this.template.querySelector('.slds-scrollable_x').offsetHeight;
|
|
40
32
|
}
|
|
41
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Sets the first visible index in the datatable state based on
|
|
36
|
+
* a given scrollTop value and the current rowHeight
|
|
37
|
+
*
|
|
38
|
+
* @param {Object} state - datatable state
|
|
39
|
+
* @param {Number} scrollTop - scroll top to calculate first visible index for
|
|
40
|
+
*/
|
|
41
|
+
export function setFirstVisibleIndex(state, scrollTop) {
|
|
42
|
+
state.firstVisibleIndex = Math.floor(scrollTop / state.rowHeight);
|
|
43
|
+
}
|
|
44
|
+
|
|
42
45
|
function getDefaultPreviousInfo() {
|
|
43
46
|
return {
|
|
44
47
|
renderedRowCount: 0,
|
|
@@ -52,6 +55,8 @@ function getDefaultPreviousInfo() {
|
|
|
52
55
|
* @type {object}
|
|
53
56
|
* @property {boolean} viewportRendering - specifies whether to use viewport rendering
|
|
54
57
|
* @property {number} rowHeight - specifies the height of a row, in px
|
|
58
|
+
* @property {number|string} bufferSize - specifies the number of additional rows to render above/below what's visible on screen
|
|
59
|
+
* @property {string} virtualize - string representing what kind of virtualization to enable; currently only 'vertical' is available
|
|
55
60
|
*/
|
|
56
61
|
|
|
57
62
|
/**
|
|
@@ -63,49 +68,34 @@ function getDefaultPreviousInfo() {
|
|
|
63
68
|
*/
|
|
64
69
|
export class RenderManager {
|
|
65
70
|
constructor() {
|
|
66
|
-
this.bufferSize = DEFAULT_BUFFER_SIZE;
|
|
67
|
-
this.rowHeight = DEFAULT_ROW_HEIGHT;
|
|
68
71
|
this.threshold = DEFAULT_SCROLL_THRESHOLD;
|
|
69
72
|
this.wrapperHeight = 0;
|
|
70
|
-
this.virtualize = '';
|
|
71
73
|
this.previousCache = getDefaultPreviousInfo();
|
|
72
74
|
}
|
|
73
75
|
|
|
74
76
|
/**
|
|
75
77
|
* Updates and normalizes configuration for RenderManager
|
|
76
78
|
* Used when setting renderConfig for datatable
|
|
77
|
-
* @param {
|
|
78
|
-
* @param {Function} getWrapperHeight
|
|
79
|
-
* @param {
|
|
80
|
-
* @param {Function} setRenderedRowCount
|
|
81
|
-
* @param {RenderManagerConfig} config
|
|
79
|
+
* @param {Object} state - datatable state
|
|
80
|
+
* @param {Function} getWrapperHeight - function to get height of datatable wrapper
|
|
81
|
+
* @param {RenderManagerConfig} config - set of properties used for render management
|
|
82
82
|
*/
|
|
83
|
-
configure(
|
|
84
|
-
getRows,
|
|
85
|
-
getWrapperHeight,
|
|
86
|
-
renderedRowCount,
|
|
87
|
-
setRenderedRowCount,
|
|
88
|
-
config
|
|
89
|
-
) {
|
|
83
|
+
configure(state, getWrapperHeight, config) {
|
|
90
84
|
const { viewportRendering, rowHeight, virtualize, bufferSize } = config;
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
getWrapperHeight,
|
|
96
|
-
renderedRowCount,
|
|
97
|
-
setRenderedRowCount
|
|
98
|
-
);
|
|
85
|
+
setVirtualize(state, virtualize);
|
|
86
|
+
|
|
87
|
+
if (normalizeBoolean(viewportRendering) || state.virtualize) {
|
|
88
|
+
this.initializeResizeObserver(state, getWrapperHeight);
|
|
99
89
|
}
|
|
100
|
-
|
|
90
|
+
state.bufferSize = normalizeNumberAttribute(
|
|
101
91
|
'bufferSize',
|
|
102
92
|
bufferSize || DEFAULT_BUFFER_SIZE,
|
|
103
93
|
'non-negative',
|
|
104
94
|
DEFAULT_BUFFER_SIZE
|
|
105
95
|
);
|
|
106
96
|
if (typeof rowHeight === 'number') {
|
|
107
|
-
|
|
108
|
-
this.threshold = ROW_THRESHOLD *
|
|
97
|
+
state.rowHeight = rowHeight;
|
|
98
|
+
this.threshold = ROW_THRESHOLD * state.rowHeight;
|
|
109
99
|
}
|
|
110
100
|
}
|
|
111
101
|
|
|
@@ -117,39 +107,24 @@ export class RenderManager {
|
|
|
117
107
|
* append a viewport's worth of rows to the currently rendered rows. This happens when
|
|
118
108
|
* the user has added more data to the datatable (e.g when a loadMore is triggered)
|
|
119
109
|
*
|
|
120
|
-
* @param {
|
|
121
|
-
* @param {
|
|
122
|
-
* @param {
|
|
123
|
-
* @param {Boolean} forceUpdate
|
|
110
|
+
* @param {Object} state - datatable state
|
|
111
|
+
* @param {Node} gridContainer - node containing datatable header and rows
|
|
112
|
+
* @param {Boolean} forceUpdate - always recalculates row count if true
|
|
124
113
|
*/
|
|
125
|
-
updateViewportRendering(
|
|
126
|
-
rows
|
|
127
|
-
|
|
128
|
-
gridContainer,
|
|
129
|
-
forceUpdate
|
|
130
|
-
) {
|
|
131
|
-
if (this.hasDataChanged(rows) || forceUpdate) {
|
|
132
|
-
this.updateRenderedRows(
|
|
133
|
-
rows,
|
|
134
|
-
setRenderedRowCount,
|
|
135
|
-
this.getRowCountWithBuffer()
|
|
136
|
-
);
|
|
114
|
+
updateViewportRendering(state, gridContainer, forceUpdate) {
|
|
115
|
+
if (this.hasDataChanged(state.rows) || forceUpdate) {
|
|
116
|
+
this.updateRenderedRows(state, this.getRowCountWithBuffer(state));
|
|
137
117
|
} else if (
|
|
138
|
-
this.previousCache.totalRowCount < rows.length &&
|
|
118
|
+
this.previousCache.totalRowCount < state.rows.length &&
|
|
139
119
|
this.isWithinThreshold(gridContainer)
|
|
140
120
|
) {
|
|
141
121
|
this.updateRenderedRows(
|
|
142
|
-
|
|
143
|
-
setRenderedRowCount,
|
|
122
|
+
state,
|
|
144
123
|
this.previousCache.renderedRowCount +
|
|
145
|
-
this.getRowCountWithBuffer()
|
|
124
|
+
this.getRowCountWithBuffer(state)
|
|
146
125
|
);
|
|
147
126
|
} else {
|
|
148
|
-
this.updateRenderedRows(
|
|
149
|
-
rows,
|
|
150
|
-
setRenderedRowCount,
|
|
151
|
-
this.previousCache.renderedRowCount
|
|
152
|
-
);
|
|
127
|
+
this.updateRenderedRows(state, this.previousCache.renderedRowCount);
|
|
153
128
|
}
|
|
154
129
|
}
|
|
155
130
|
|
|
@@ -158,45 +133,33 @@ export class RenderManager {
|
|
|
158
133
|
* If the scroll is within a specified threshold of the bottom,
|
|
159
134
|
* calculate and render the next batch of rows
|
|
160
135
|
*
|
|
161
|
-
* @param {
|
|
162
|
-
* @param {Number} currentLength
|
|
163
|
-
* @param {Function} setRenderedRowCount
|
|
136
|
+
* @param {Object} state - datatable state
|
|
164
137
|
* @param {Event} event - scroll event
|
|
165
138
|
*/
|
|
166
|
-
handleScroll(
|
|
139
|
+
handleScroll(state, event) {
|
|
140
|
+
const { rows, renderedRowCount } = state;
|
|
167
141
|
if (
|
|
168
142
|
this.isWithinThreshold(event.target.firstChild) &&
|
|
169
|
-
|
|
143
|
+
renderedRowCount < rows.length
|
|
170
144
|
) {
|
|
171
145
|
this.updateRenderedRows(
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
currentLength + this.getRowCountWithBuffer()
|
|
146
|
+
state,
|
|
147
|
+
renderedRowCount + this.getRowCountWithBuffer(state)
|
|
175
148
|
);
|
|
176
149
|
}
|
|
177
150
|
}
|
|
178
151
|
|
|
179
|
-
/**
|
|
180
|
-
* gets the index of the first row that should be visible in the viewport
|
|
181
|
-
*
|
|
182
|
-
* @param {Event} event
|
|
183
|
-
* @returns {number} index of first row visible in viewport
|
|
184
|
-
*/
|
|
185
|
-
getFirstVisibleIndex(event) {
|
|
186
|
-
return event.target.scrollTop / this.rowHeight;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
152
|
/**
|
|
190
153
|
* calculates the range of rows that should be rendered based on the
|
|
191
154
|
* first visible index, buffer size and datatable height
|
|
192
155
|
*
|
|
193
|
-
* @param {
|
|
156
|
+
* @param {Object} state - datatable state
|
|
194
157
|
* @returns {Object} object with firstIndex and lastIndex of rendered range of rows
|
|
195
158
|
*/
|
|
196
|
-
getRenderedRange(
|
|
197
|
-
const
|
|
198
|
-
const
|
|
199
|
-
|
|
159
|
+
getRenderedRange(state) {
|
|
160
|
+
const { firstVisibleIndex, bufferSize, renderedRowCount } = state;
|
|
161
|
+
const firstIndex = Math.max(firstVisibleIndex - bufferSize, 0);
|
|
162
|
+
const lastIndex = firstVisibleIndex - bufferSize + renderedRowCount;
|
|
200
163
|
|
|
201
164
|
return { firstIndex, lastIndex };
|
|
202
165
|
}
|
|
@@ -204,16 +167,16 @@ export class RenderManager {
|
|
|
204
167
|
/**
|
|
205
168
|
* Updates internal cache of row counts and first key
|
|
206
169
|
*
|
|
207
|
-
* @param {
|
|
208
|
-
* @param {
|
|
209
|
-
* @param {Number} rowCount
|
|
170
|
+
* @param {Object} state - datatable state
|
|
171
|
+
* @param {Number} rowCount - max number of rows to set renderedRowCount to
|
|
210
172
|
*/
|
|
211
|
-
updateRenderedRows(
|
|
173
|
+
updateRenderedRows(state, rowCount) {
|
|
174
|
+
const rows = state.rows;
|
|
212
175
|
const totalRows = rows.length;
|
|
213
176
|
const normalizedRowCount = rowCount
|
|
214
177
|
? Math.min(rowCount, totalRows)
|
|
215
178
|
: totalRows;
|
|
216
|
-
|
|
179
|
+
state.renderedRowCount = normalizedRowCount;
|
|
217
180
|
|
|
218
181
|
// Update our internal cache
|
|
219
182
|
this.previousCache.renderedRowCount = normalizedRowCount;
|
|
@@ -228,7 +191,7 @@ export class RenderManager {
|
|
|
228
191
|
* Caches the height of the wrapper in Datatable to avoid
|
|
229
192
|
* unnecessary reflows
|
|
230
193
|
*
|
|
231
|
-
* @param {Function} getWrapperHeight
|
|
194
|
+
* @param {Function} getWrapperHeight - function to get height of datatable wrapper
|
|
232
195
|
*/
|
|
233
196
|
updateWrapperHeight(getWrapperHeight) {
|
|
234
197
|
this.wrapperHeight = getWrapperHeight();
|
|
@@ -240,17 +203,10 @@ export class RenderManager {
|
|
|
240
203
|
* Initializes a resize observer to update the wrapper height
|
|
241
204
|
* when the datatable component's height changes
|
|
242
205
|
*
|
|
243
|
-
* @param {
|
|
244
|
-
* @param {Function} getWrapperHeight
|
|
245
|
-
* @param {Function} getRenderedRowCount
|
|
246
|
-
* @param {Function} setRenderedRowCount
|
|
206
|
+
* @param {Object} state - datatable state
|
|
207
|
+
* @param {Function} getWrapperHeight - function to get height of datatable wrapper
|
|
247
208
|
*/
|
|
248
|
-
initializeResizeObserver(
|
|
249
|
-
getRows,
|
|
250
|
-
getWrapperHeight,
|
|
251
|
-
getRenderedRowCount,
|
|
252
|
-
setRenderedRowCount
|
|
253
|
-
) {
|
|
209
|
+
initializeResizeObserver(state, getWrapperHeight) {
|
|
254
210
|
if (!this._heightResizeObserver) {
|
|
255
211
|
this._heightResizeObserver = new LightningResizeObserver(() => {
|
|
256
212
|
if (this._resizeObserverConnected) {
|
|
@@ -258,16 +214,14 @@ export class RenderManager {
|
|
|
258
214
|
|
|
259
215
|
// If the wrapper is now larger than the table or virtualization enabled,
|
|
260
216
|
// we need to update the rendered rows so users can continue scrolling
|
|
261
|
-
const rowCountWithBuffer =
|
|
217
|
+
const rowCountWithBuffer =
|
|
218
|
+
this.getRowCountWithBuffer(state);
|
|
219
|
+
|
|
262
220
|
if (
|
|
263
|
-
rowCountWithBuffer >
|
|
264
|
-
|
|
221
|
+
rowCountWithBuffer > state.renderedRowCount ||
|
|
222
|
+
state.virtualize
|
|
265
223
|
) {
|
|
266
|
-
this.updateRenderedRows(
|
|
267
|
-
getRows(),
|
|
268
|
-
setRenderedRowCount,
|
|
269
|
-
rowCountWithBuffer
|
|
270
|
-
);
|
|
224
|
+
this.updateRenderedRows(state, rowCountWithBuffer);
|
|
271
225
|
}
|
|
272
226
|
}
|
|
273
227
|
});
|
|
@@ -301,19 +255,21 @@ export class RenderManager {
|
|
|
301
255
|
/**
|
|
302
256
|
* Calculates how many rows fits within the current wrapper
|
|
303
257
|
*/
|
|
304
|
-
getRowCountInViewport() {
|
|
305
|
-
return Math.ceil(this.wrapperHeight /
|
|
258
|
+
getRowCountInViewport(state) {
|
|
259
|
+
return Math.ceil(this.wrapperHeight / state.rowHeight);
|
|
306
260
|
}
|
|
307
261
|
|
|
308
262
|
/**
|
|
309
263
|
* Calculates how many rows fit in current wrapper with an added buffer
|
|
310
264
|
* Used to determine how many additional rows to render
|
|
311
265
|
*/
|
|
312
|
-
getRowCountWithBuffer() {
|
|
266
|
+
getRowCountWithBuffer(state) {
|
|
313
267
|
// buffer is before and after with virtualization
|
|
314
268
|
// but only after with viewport rendering
|
|
315
|
-
const multiplier =
|
|
316
|
-
return
|
|
269
|
+
const multiplier = state.virtualize ? 2 : 1;
|
|
270
|
+
return (
|
|
271
|
+
this.getRowCountInViewport(state) + state.bufferSize * multiplier
|
|
272
|
+
);
|
|
317
273
|
}
|
|
318
274
|
|
|
319
275
|
/**
|
|
@@ -115,8 +115,8 @@ export function uniqueRowKeyGenerator(keyField) {
|
|
|
115
115
|
* @param {object} state - the current datatable state
|
|
116
116
|
*/
|
|
117
117
|
export function updateRowsAndCellIndexes() {
|
|
118
|
-
const { state, privateTypes: types
|
|
119
|
-
const { keyField, renderModeRoleBased } = state;
|
|
118
|
+
const { state, privateTypes: types } = this;
|
|
119
|
+
const { keyField, renderModeRoleBased, virtualize } = state;
|
|
120
120
|
const data = getData(state);
|
|
121
121
|
const columns = getColumns(state);
|
|
122
122
|
const computeUniqueRowKey = uniqueRowKeyGenerator(keyField);
|
|
@@ -142,7 +142,7 @@ export function updateRowsAndCellIndexes() {
|
|
|
142
142
|
row.classnames = resolveRowClassNames(row);
|
|
143
143
|
Object.assign(row, getRowStateForTree(rowData, state));
|
|
144
144
|
row.tabIndex = -1;
|
|
145
|
-
if (
|
|
145
|
+
if (virtualize) {
|
|
146
146
|
row.style = styleToString({
|
|
147
147
|
position: 'absolute',
|
|
148
148
|
top: `${rowIndex * DEFAULT_ROW_HEIGHT}px`,
|
|
@@ -402,7 +402,7 @@ function computeCellEditable(row, column) {
|
|
|
402
402
|
* @param {object} row - a row data object stored in datatable state. Must be truthy.
|
|
403
403
|
* @param {object} column - a column data object stored in datatable state. Must be truthy.
|
|
404
404
|
*/
|
|
405
|
-
function isCellEditable(row, column) {
|
|
405
|
+
export function isCellEditable(row, column) {
|
|
406
406
|
return !!resolveAttributeValue(column.editable, row);
|
|
407
407
|
}
|
|
408
408
|
|
|
@@ -55,8 +55,13 @@ export const getDefaultState = function () {
|
|
|
55
55
|
// table render mode
|
|
56
56
|
renderModeRoleBased: false,
|
|
57
57
|
|
|
58
|
-
// viewport rendering
|
|
58
|
+
// viewport rendering and virtualization
|
|
59
59
|
enableViewportRendering: undefined,
|
|
60
|
+
virtualize: '',
|
|
61
|
+
bufferSize: 5, // number of extra rows rendered on each side outside of viewport
|
|
62
|
+
rowHeight: 30.5,
|
|
63
|
+
renderedRowCount: 0,
|
|
64
|
+
firstVisibleIndex: 0, // first row that should be visible in viewport
|
|
60
65
|
|
|
61
66
|
// inline edit
|
|
62
67
|
inlineEdit: {
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
<div class="slds-line-height_reset table-header"
|
|
49
49
|
role="row"
|
|
50
50
|
aria-rowindex="1"
|
|
51
|
+
data-row-key-value="HEADER"
|
|
51
52
|
onprivateresizestart={handleResizeStart}
|
|
52
53
|
onprivateresizeend={handleResizeEnd}>
|
|
53
54
|
<template for:each={state.columns} for:item="def" for:index="colIndex">
|
|
@@ -58,6 +59,7 @@
|
|
|
58
59
|
tabindex={def.tabIndex}
|
|
59
60
|
aria-label={def.ariaLabel}
|
|
60
61
|
aria-sort={def.sortAriaLabel}
|
|
62
|
+
data-col-key-value={def.colKeyValue}
|
|
61
63
|
key={def.colKeyValue}>
|
|
62
64
|
|
|
63
65
|
<template if:true={def.fixedWidth}>
|
|
@@ -130,6 +132,7 @@
|
|
|
130
132
|
role="gridcell"
|
|
131
133
|
tabindex={cell.tabIndex}
|
|
132
134
|
data-label={cell.dataLabel}
|
|
135
|
+
data-col-key-value={cell.colKeyValue}
|
|
133
136
|
key={cell.colKeyValue}>
|
|
134
137
|
<lightning-primitive-cell-checkbox
|
|
135
138
|
dt-context-id={_datatableId}
|
|
@@ -155,6 +158,7 @@
|
|
|
155
158
|
aria-readonly={cell.ariaReadOnly}
|
|
156
159
|
tabindex={cell.tabIndex}
|
|
157
160
|
data-label={cell.dataLabel}
|
|
161
|
+
data-col-key-value={cell.colKeyValue}
|
|
158
162
|
key={cell.colKeyValue}>
|
|
159
163
|
<lightning-primitive-cell-factory
|
|
160
164
|
types={privateTypes}
|
|
@@ -203,6 +207,7 @@
|
|
|
203
207
|
aria-readonly={cell.ariaReadOnly}
|
|
204
208
|
tabindex={cell.tabIndex}
|
|
205
209
|
data-label={cell.dataLabel}
|
|
210
|
+
data-col-key-value={cell.colKeyValue}
|
|
206
211
|
key={cell.colKeyValue}>
|
|
207
212
|
<lightning-primitive-cell-factory
|
|
208
213
|
types={privateTypes}
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
<thead>
|
|
42
42
|
<!-- Column Header Row -->
|
|
43
43
|
<tr class="slds-line-height_reset"
|
|
44
|
+
data-row-key-value="HEADER"
|
|
44
45
|
onprivateresizestart={handleResizeStart}
|
|
45
46
|
onprivateresizeend={handleResizeEnd}>
|
|
46
47
|
<template for:each={state.columns} for:item="def" for:index="colIndex">
|
|
@@ -50,6 +51,7 @@
|
|
|
50
51
|
tabindex={def.tabIndex}
|
|
51
52
|
aria-label={def.ariaLabel}
|
|
52
53
|
aria-sort={def.sortAriaLabel}
|
|
54
|
+
data-col-key-value={def.colKeyValue}
|
|
53
55
|
key={def.colKeyValue}>
|
|
54
56
|
|
|
55
57
|
<template if:true={def.fixedWidth}>
|
|
@@ -117,6 +119,7 @@
|
|
|
117
119
|
role="gridcell"
|
|
118
120
|
tabindex={cell.tabIndex}
|
|
119
121
|
data-label={cell.dataLabel}
|
|
122
|
+
data-col-key-value={cell.colKeyValue}
|
|
120
123
|
key={cell.colKeyValue}>
|
|
121
124
|
<lightning-primitive-cell-checkbox
|
|
122
125
|
dt-context-id={_datatableId}
|
|
@@ -142,6 +145,7 @@
|
|
|
142
145
|
scope="row"
|
|
143
146
|
tabindex={cell.tabIndex}
|
|
144
147
|
data-label={cell.dataLabel}
|
|
148
|
+
data-col-key-value={cell.colKeyValue}
|
|
145
149
|
key={cell.colKeyValue}>
|
|
146
150
|
<lightning-primitive-cell-factory
|
|
147
151
|
types={privateTypes}
|
|
@@ -190,6 +194,7 @@
|
|
|
190
194
|
aria-readonly={cell.ariaReadOnly}
|
|
191
195
|
tabindex={cell.tabIndex}
|
|
192
196
|
data-label={cell.dataLabel}
|
|
197
|
+
data-col-key-value={cell.colKeyValue}
|
|
193
198
|
key={cell.colKeyValue}>
|
|
194
199
|
<lightning-primitive-cell-factory
|
|
195
200
|
types={privateTypes}
|
|
@@ -3,8 +3,10 @@ import labelWrapText from '@salesforce/label/LightningDatatable.wrapText';
|
|
|
3
3
|
import { getStateColumnIndex, getColumns } from './columns';
|
|
4
4
|
import { normalizeBoolean } from 'lightning/utilsPrivate';
|
|
5
5
|
import { normalizeNumberAttribute } from './utils';
|
|
6
|
+
import { getDefaultState } from './state';
|
|
6
7
|
|
|
7
|
-
const
|
|
8
|
+
const WRAP_TEXT_DEFAULT = false;
|
|
9
|
+
const NON_WRAPPABLE_TYPES = [
|
|
8
10
|
'action',
|
|
9
11
|
'boolean',
|
|
10
12
|
'button',
|
|
@@ -13,17 +15,33 @@ const nonWrapableTypes = [
|
|
|
13
15
|
'rowNumber',
|
|
14
16
|
];
|
|
15
17
|
|
|
16
|
-
const WRAP_TEXT_DEFAULT = false;
|
|
17
|
-
|
|
18
18
|
const i18n = {
|
|
19
19
|
clipText: labelClipText,
|
|
20
20
|
wrapText: labelWrapText,
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
/************************** WRAP TEXT STATE **************************/
|
|
24
|
+
|
|
25
|
+
// Returns a boolean representing whether or not the column should be text wrapped
|
|
26
|
+
export function getWrapTextState(state = getDefaultState(), colKeyValue) {
|
|
27
|
+
return state.wrapText[colKeyValue] || WRAP_TEXT_DEFAULT;
|
|
25
28
|
}
|
|
26
29
|
|
|
30
|
+
// Sets a boolean value in state's wrapText object against the column key value
|
|
31
|
+
// representing whether or not the column is text wrapped
|
|
32
|
+
export function setWrapTextState(state = getDefaultState(), columnDefinition) {
|
|
33
|
+
const { colKeyValue, type, wrapText } = columnDefinition;
|
|
34
|
+
|
|
35
|
+
if (isWrappableType(type)) {
|
|
36
|
+
state.wrapText[colKeyValue] =
|
|
37
|
+
normalizeBoolean(wrapText) || WRAP_TEXT_DEFAULT;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/************************** WRAP TEXT MAX LINES **************************/
|
|
42
|
+
|
|
43
|
+
// Normalizes and sets wrapTextMaxLines in datatable's state object
|
|
44
|
+
// The normalized value should be a positive integer or it'll fall back to undefined
|
|
27
45
|
export function setWrapTextMaxLines(state, value) {
|
|
28
46
|
state.wrapTextMaxLines = normalizeNumberAttribute(
|
|
29
47
|
'wrapTextMaxLines',
|
|
@@ -33,6 +51,8 @@ export function setWrapTextMaxLines(state, value) {
|
|
|
33
51
|
);
|
|
34
52
|
}
|
|
35
53
|
|
|
54
|
+
// Sets the `wrapText` and `wrapTextMaxLines` values in the cell object for all cells in a column
|
|
55
|
+
// These values are used by primitiveCellFactory to set the required classes on the cell for wrapping
|
|
36
56
|
function updateWrapTextAndMaxLinesValuesInCells(state, colIndex, colKeyValue) {
|
|
37
57
|
state.rows.forEach((row) => {
|
|
38
58
|
const cell = row.cells[colIndex];
|
|
@@ -43,39 +63,17 @@ function updateWrapTextAndMaxLinesValuesInCells(state, colIndex, colKeyValue) {
|
|
|
43
63
|
});
|
|
44
64
|
}
|
|
45
65
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
updateWrapTextAndMaxLinesValuesInCells(state, colIndex, colKeyValue);
|
|
61
|
-
|
|
62
|
-
// lets force a refresh on this column, because the wrapText checked value changed.
|
|
63
|
-
colData.actions = Object.assign({}, colData.actions);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export function getWrapTextState(state = getDefaultState(), colKeyValue) {
|
|
67
|
-
return state.wrapText[colKeyValue] || WRAP_TEXT_DEFAULT;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export function setWrapTextState(state = getDefaultState(), columnDefinition) {
|
|
71
|
-
const { colKeyValue, type, wrapText } = columnDefinition;
|
|
72
|
-
|
|
73
|
-
if (isWrapableType(type)) {
|
|
74
|
-
state.wrapText[colKeyValue] =
|
|
75
|
-
normalizeBoolean(wrapText) || WRAP_TEXT_DEFAULT;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
66
|
+
/************************** HEADER ACTIONS **************************/
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Returns an object representing the two internal header actions that datatable
|
|
70
|
+
* provides - Wrap Text and Clip Text.
|
|
71
|
+
* Each header action contains a label, title, action name and its selected value (checked)
|
|
72
|
+
*
|
|
73
|
+
* @param {Object} state - datatable's state object
|
|
74
|
+
* @param {Object} columnDefinition - datatable's column definitions
|
|
75
|
+
* @returns
|
|
76
|
+
*/
|
|
79
77
|
export function getActions(state, columnDefinition) {
|
|
80
78
|
const wrapTextActions = [];
|
|
81
79
|
const { hideDefaultActions, type, colKeyValue } = columnDefinition;
|
|
@@ -84,7 +82,7 @@ export function getActions(state, columnDefinition) {
|
|
|
84
82
|
setWrapTextState(state, columnDefinition);
|
|
85
83
|
|
|
86
84
|
// if not hidden and isWrapable, sets the internal actions
|
|
87
|
-
if (
|
|
85
|
+
if (isWrappableType(type) && !hideDefaultActions) {
|
|
88
86
|
const isTextWrapped = getWrapTextState(state, colKeyValue);
|
|
89
87
|
|
|
90
88
|
wrapTextActions.push({
|
|
@@ -105,19 +103,51 @@ export function getActions(state, columnDefinition) {
|
|
|
105
103
|
return wrapTextActions;
|
|
106
104
|
}
|
|
107
105
|
|
|
106
|
+
/**
|
|
107
|
+
* If the action is an internal action and if the wrapText value for a column
|
|
108
|
+
* needs to be changed in the state, change it to the new value and update
|
|
109
|
+
* the check mark to represent the currently selected action
|
|
110
|
+
*
|
|
111
|
+
* @param {Object} state - datatable's state object
|
|
112
|
+
* @param {String} action - action that was selected/triggered
|
|
113
|
+
* @param {String} colKeyValue - column key value
|
|
114
|
+
*/
|
|
108
115
|
export function handleTriggeredAction(state, action, colKeyValue) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
116
|
+
const actionName = action.name;
|
|
117
|
+
if (actionName === 'wrapText' || actionName === 'clipText') {
|
|
118
|
+
// If state should be changed
|
|
119
|
+
if (state.wrapText[colKeyValue] !== (actionName === 'wrapText')) {
|
|
120
|
+
state.wrapText[colKeyValue] = actionName === 'wrapText';
|
|
113
121
|
|
|
114
122
|
updateSelectedOptionInHeaderActions(state, colKeyValue);
|
|
115
123
|
}
|
|
116
124
|
}
|
|
117
125
|
}
|
|
118
126
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
127
|
+
// Update the 'checked' value of the each action to show which action is selected
|
|
128
|
+
// and which action is not selected
|
|
129
|
+
function updateSelectedOptionInHeaderActions(state, colKeyValue) {
|
|
130
|
+
const columns = getColumns(state);
|
|
131
|
+
const colIndex = getStateColumnIndex(state, colKeyValue);
|
|
132
|
+
const colData = columns[colIndex];
|
|
133
|
+
|
|
134
|
+
colData.actions.internalActions.forEach((action) => {
|
|
135
|
+
if (action.name === 'wrapText') {
|
|
136
|
+
action.checked = state.wrapText[colKeyValue];
|
|
137
|
+
}
|
|
138
|
+
if (action.name === 'clipText') {
|
|
139
|
+
action.checked = !state.wrapText[colKeyValue];
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
updateWrapTextAndMaxLinesValuesInCells(state, colIndex, colKeyValue);
|
|
144
|
+
|
|
145
|
+
// Force a refresh on this column, because the wrapText checked value changed.
|
|
146
|
+
colData.actions = Object.assign({}, colData.actions);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/************************** HELPER FUNCTIONS **************************/
|
|
150
|
+
|
|
151
|
+
function isWrappableType(type) {
|
|
152
|
+
return NON_WRAPPABLE_TYPES.indexOf(type) < 0;
|
|
123
153
|
}
|