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.
Files changed (152) hide show
  1. package/metadata/raptor.json +37 -4
  2. package/package.json +11 -4
  3. package/scopedImports/@salesforce-internal-core.appVersion.js +1 -1
  4. package/scopedImports/@salesforce-label-LightningModalBase.cancelandclose.js +1 -0
  5. package/scopedImports/@salesforce-label-LightningProgressBar.progressBar.js +1 -0
  6. package/src/lightning/alert/__docs__/alert.md +101 -0
  7. package/src/lightning/alert/__examples__disabled/basic/basic.css +7 -0
  8. package/src/lightning/alert/__examples__disabled/basic/basic.html +8 -0
  9. package/src/lightning/alert/__examples__disabled/basic/basic.js +14 -0
  10. package/src/lightning/alert/alert.html +3 -0
  11. package/src/lightning/alert/alert.js +78 -0
  12. package/src/lightning/alert/alert.js-meta.xml +6 -0
  13. package/src/lightning/ariaObserver/__component__/ariaObserver.spec.js +9 -0
  14. package/src/lightning/ariaObserver/ariaObserver.js +24 -35
  15. package/src/lightning/baseFormattedText/baseFormattedText.html +6 -1
  16. package/src/lightning/baseFormattedText/baseFormattedText.js +5 -0
  17. package/src/lightning/button/__wdio__/utam/utam.html +3 -0
  18. package/src/lightning/button/__wdio__/utam/utam.js +3 -0
  19. package/src/lightning/button/__wdio__/utam/utam.spec.js +20 -0
  20. package/src/lightning/buttonMenu/buttonMenu.js +12 -0
  21. package/src/lightning/confirm/__docs__/confirm.md +100 -0
  22. package/src/lightning/confirm/__examples__disabled/basic/basic.css +7 -0
  23. package/src/lightning/confirm/__examples__disabled/basic/basic.html +8 -0
  24. package/src/lightning/confirm/__examples__disabled/basic/basic.js +14 -0
  25. package/src/lightning/confirm/confirm.html +3 -0
  26. package/src/lightning/confirm/confirm.js +80 -0
  27. package/src/lightning/confirm/confirm.js-meta.xml +6 -0
  28. package/src/lightning/datatable/__examples__/withInfiniteLoading/fetchDataHelper.js +21 -0
  29. package/src/lightning/datatable/__examples__/withInfiniteLoading/withInfiniteLoading.html +13 -0
  30. package/src/lightning/datatable/__examples__/withInfiniteLoading/withInfiniteLoading.js +42 -0
  31. package/src/lightning/datatable/__wdio__/utam/utam.html +17 -0
  32. package/src/lightning/datatable/__wdio__/utam/utam.js +91 -0
  33. package/src/lightning/datatable/__wdio__/utam/utam.spec.js +189 -0
  34. package/src/lightning/datatable/autoWidthStrategy.js +170 -61
  35. package/src/lightning/datatable/{resizer.js → columnResizer.js} +0 -0
  36. package/src/lightning/datatable/columnWidthManager.js +226 -44
  37. package/src/lightning/datatable/columns.js +166 -71
  38. package/src/lightning/datatable/datatable.js +136 -60
  39. package/src/lightning/datatable/fixedWidthStrategy.js +43 -8
  40. package/src/lightning/datatable/headerActions.js +2 -2
  41. package/src/lightning/datatable/infiniteLoading.js +100 -28
  42. package/src/lightning/datatable/inlineEdit.js +21 -30
  43. package/src/lightning/datatable/keyboard.js +166 -131
  44. package/src/lightning/datatable/renderManager.js +117 -122
  45. package/src/lightning/datatable/{datatableResizeObserver.js → resizeObserver.js} +46 -29
  46. package/src/lightning/datatable/resizeSensor.js +19 -3
  47. package/src/lightning/datatable/rowSelection.js +1 -1
  48. package/src/lightning/datatable/rowSelectionShared.js +33 -20
  49. package/src/lightning/datatable/rows.js +9 -8
  50. package/src/lightning/datatable/sort.js +8 -8
  51. package/src/lightning/datatable/state.js +14 -2
  52. package/src/lightning/datatable/templates/div/div.html +133 -119
  53. package/src/lightning/datatable/templates/table/table.html +10 -2
  54. package/src/lightning/datatable/tree.js +25 -0
  55. package/src/lightning/datatable/types.js +77 -9
  56. package/src/lightning/datatable/utils.js +51 -24
  57. package/src/lightning/datatable/virtualization.js +319 -0
  58. package/src/lightning/datatable/widthManagerShared.js +27 -3
  59. package/src/lightning/datatable/wrapText.js +115 -48
  60. package/src/lightning/datepicker/__perf__DISABLED/datepickerWithCalendarOpen.perf.js +55 -0
  61. package/src/lightning/formattedDateTime/__docs__/formattedDateTime.md +36 -3
  62. package/src/lightning/formattedDateTime/__examples__/datetime/datetime.html +2 -2
  63. package/src/lightning/formattedDateTime/__examples__/datetime/datetime.js +3 -1
  64. package/src/lightning/formattedDateTime/__examples__/time/time.html +1 -1
  65. package/src/lightning/formattedDateTime/__examples__/time/time.js +3 -1
  66. package/src/lightning/formattedDateTime/formattedDateTime.js +1 -0
  67. package/src/lightning/iconSvgTemplates/buildTemplates/standard/dashboard_component.html +7 -0
  68. package/src/lightning/iconSvgTemplates/buildTemplates/standard/slack.html +7 -0
  69. package/src/lightning/iconSvgTemplates/buildTemplates/standard/tableau.html +7 -0
  70. package/src/lightning/iconSvgTemplates/buildTemplates/standard/travel_mode.html +2 -2
  71. package/src/lightning/iconSvgTemplates/buildTemplates/templates.js +8 -1
  72. package/src/lightning/iconSvgTemplates/buildTemplates/utility/data_model.html +7 -0
  73. package/src/lightning/iconSvgTemplates/buildTemplates/utility/serialized_product.html +1 -1
  74. package/src/lightning/iconSvgTemplates/buildTemplates/utility/serialized_product_transaction.html +2 -1
  75. package/src/lightning/iconSvgTemplates/buildTemplates/utility/slack.html +7 -0
  76. package/src/lightning/iconSvgTemplates/buildTemplates/utility/tableau.html +7 -0
  77. package/src/lightning/iconSvgTemplates/buildTemplates/utility/video_off.html +7 -0
  78. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/dashboard_component.html +7 -0
  79. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/slack.html +7 -0
  80. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/tableau.html +7 -0
  81. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/travel_mode.html +2 -2
  82. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/templates.js +8 -1
  83. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/data_model.html +7 -0
  84. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/serialized_product.html +1 -1
  85. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/serialized_product_transaction.html +2 -1
  86. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/slack.html +7 -0
  87. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/tableau.html +7 -0
  88. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/video_off.html +7 -0
  89. package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/dashboard_component.html +7 -0
  90. package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/slack.html +7 -0
  91. package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/tableau.html +7 -0
  92. package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/travel_mode.html +2 -2
  93. package/src/lightning/iconSvgTemplatesStandard/buildTemplates/templates.js +4 -1
  94. package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/dashboard_component.html +7 -0
  95. package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/slack.html +7 -0
  96. package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/tableau.html +7 -0
  97. package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/travel_mode.html +2 -2
  98. package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/templates.js +4 -1
  99. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/templates.js +5 -1
  100. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/data_model.html +7 -0
  101. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/serialized_product.html +1 -1
  102. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/serialized_product_transaction.html +2 -1
  103. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/slack.html +7 -0
  104. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/tableau.html +7 -0
  105. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/video_off.html +7 -0
  106. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/templates.js +5 -1
  107. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/data_model.html +7 -0
  108. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/serialized_product.html +1 -1
  109. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/serialized_product_transaction.html +2 -1
  110. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/slack.html +7 -0
  111. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/tableau.html +7 -0
  112. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/video_off.html +7 -0
  113. package/src/lightning/input/__docs__/input.md +2 -0
  114. package/src/lightning/input/input.html +2 -5
  115. package/src/lightning/interactiveDialogBase/interactiveDialogBase.css +494 -0
  116. package/src/lightning/interactiveDialogBase/interactiveDialogBase.html +63 -0
  117. package/src/lightning/interactiveDialogBase/interactiveDialogBase.js +200 -0
  118. package/src/lightning/menuItem/menuItem.js +4 -1
  119. package/src/lightning/modalBase/modalBase.css +20 -0
  120. package/src/lightning/modalBase/modalBase.html +54 -0
  121. package/src/lightning/modalBase/modalBase.js +1039 -0
  122. package/src/lightning/overlay/__docs__/overlay.md +90 -0
  123. package/src/lightning/overlay/__examples__/alert/alert.html +27 -0
  124. package/src/lightning/overlay/__examples__/alert/alert.js +33 -0
  125. package/src/lightning/overlay/__examples__/basic/basic.css +7 -0
  126. package/src/lightning/overlay/__examples__/basic/basic.html +18 -0
  127. package/src/lightning/overlay/__examples__/basic/basic.js +61 -0
  128. package/src/lightning/overlay/__examples__/demo/demo.html +29 -0
  129. package/src/lightning/overlay/__examples__/demo/demo.js +40 -0
  130. package/src/lightning/overlay/__examples__/panel/panel.html +17 -0
  131. package/src/lightning/overlay/__examples__/panel/panel.js +21 -0
  132. package/src/lightning/overlay/overlay.html +3 -0
  133. package/src/lightning/overlay/overlay.js +45 -0
  134. package/src/lightning/overlayContainer/__docs__/overlayContainer.md +0 -0
  135. package/src/lightning/overlayContainer/overlayContainer.html +3 -0
  136. package/src/lightning/overlayContainer/overlayContainer.js +138 -0
  137. package/src/lightning/overlayManager/overlayManager.js +54 -0
  138. package/src/lightning/overlayUtils/overlayUtils.js +17 -0
  139. package/src/lightning/progressBar/progressBar.html +2 -1
  140. package/src/lightning/progressBar/progressBar.js +18 -1
  141. package/src/lightning/prompt/__docs__/prompt.md +102 -0
  142. package/src/lightning/prompt/__examples__disabled/basic/basic.css +7 -0
  143. package/src/lightning/prompt/__examples__disabled/basic/basic.html +8 -0
  144. package/src/lightning/prompt/__examples__disabled/basic/basic.js +15 -0
  145. package/src/lightning/prompt/prompt.css +81 -0
  146. package/src/lightning/prompt/prompt.html +8 -0
  147. package/src/lightning/prompt/prompt.js +92 -0
  148. package/src/lightning/prompt/prompt.js-meta.xml +6 -0
  149. package/src/lightning/spinner/spinner.html +1 -1
  150. package/src/lightning/spinner/spinner.js +12 -0
  151. package/src/lightning/utilsPrivate/phonify.js +1 -1
  152. package/scopedImports/@salesforce-label-LightningModalBase.close.js +0 -1
@@ -0,0 +1,100 @@
1
+ The `lightning/confirm` module lets you create a confirm modal within your component. Use `LightningConfirm` on your component to ask the user to respond before they continue.
2
+
3
+ `lightning/confirm` is not supported on mobile devices.
4
+
5
+ Use `LightningConfirm.open()` instead of the native `window.confirm()` for a more consistent user experience. They have similar functions, but `LightningConfirm.open()` works in cross-origin iframes, where the `.confirm()` method is no longer supported in Chrome and Safari. Unlike `window.confirm()`, `LightningConfirm.open()` doesn't halt execution on the page, it returns a Promise. Use `async`/`await` or `.then()` for any code you want to execute after the confirm has closed.
6
+
7
+ Import `LightningConfirm` from the `lightning/confirm` module in the component that will launch the confirm modal, and call `LightningConfirm.open()` with your desired attributes.
8
+
9
+ This example creates a headerless confirm modal with two buttons, **OK** and **Cancel**. The `.open()` function returns a promise that resolves to true when you click **OK** and false when you click **Cancel**.
10
+
11
+ ```html
12
+ <!-- c/myApp.html -->
13
+ <template>
14
+ <lightning-button onclick="{handleConfirmClick}" label="Open Confirm Modal">
15
+ </lightning-button>
16
+ </template>
17
+ ```
18
+
19
+ ```javascript
20
+ import { LightningElement } from 'lwc';
21
+ import LightningConfirm from 'lightning/confirm';
22
+
23
+ export default class MyApp extends LightningElement {
24
+ async handleConfirmClick() {
25
+ const result = await LightningConfirm.open({
26
+ message: 'this is the prompt message',
27
+ variant: 'headerless',
28
+ label: 'this is the aria-label value',
29
+ // setting theme would have no effect
30
+ });
31
+ //Confirm has been closed
32
+ //result is true if OK was clicked
33
+ //and false if cancel was clicked
34
+ }
35
+ }
36
+ ```
37
+
38
+ #### Component Styling
39
+
40
+ This component uses the Salesforce Lightning Design System (SLDS) [`prompt` blueprint](https://www.lightningdesignsystem.com/components/prompt/#site-main-content).
41
+
42
+ `LightningConfirm` supports the following attributes:
43
+
44
+ - `message`: Message text that displays in the confirm.
45
+ - `label`: Header text, also used as the `aria-label`. Default string is `Confirm`.
46
+ - `variant`: Two values, `header` and `headerless`. Default value is `header`.
47
+ - `theme`: Color theme for the header. The `theme` attribute supports the following [options](https://www.lightningdesignsystem.com/utilities/themes/#site-main-content) from SLDS:
48
+ - `default`: white
49
+ - `shade`: gray
50
+ - `inverse`: dark blue
51
+ - `alt-inverse`: darker blue
52
+ - `success`: green
53
+ - `info`: gray-ish blue
54
+ - `warning`: yellow
55
+ - `error`: red
56
+ - `offline`: ​black​
57
+
58
+ If an invalid value is provided, `LightningConfirm` uses the `default` theme.
59
+
60
+ #### Testing Your Component's Confirm
61
+
62
+ Code using `LightningConfirm` can be tested by mocking the `LightningConfirm.open()` method.
63
+
64
+ The example below uses a button to open a confirm dialog and sets the result in a template.
65
+
66
+ ```html
67
+ <button data-button onclick="{handleClick}">Open Confirm</button>
68
+ <div data-result>{result}</div>
69
+ ```
70
+
71
+ ```js
72
+ import LightningConfirm from 'lightning/confirm';
73
+ jest.mock('lightning/confirm');
74
+
75
+ test(() => {
76
+ // Create and appendChild(element)
77
+
78
+ const buttonEle = element.shadowRoot.querySelector('[data-button]');
79
+ const resultEle = element.shadowRoot.querySelector('[data-result]');
80
+
81
+ // Mock .open()
82
+ // Pass true if testing when user clicks "OK"
83
+ // Pass false if testing when user clicks "Cancel"
84
+ LightningConfirm.open = jest.fn().mockResolvedValue(true);
85
+ // Initial value
86
+ expect(resultEle.textContent).toBe('unknown');
87
+ // Click modal open button
88
+ buttonEle.click();
89
+
90
+ // Click handler render cycle
91
+ await Promise.resolve();
92
+ // Render cycle triggered by tracked value {result}
93
+ await Promise.resolve();
94
+
95
+ // Verify result is set in the template
96
+ expect(resultEle.textContent).toBe('true');
97
+ // Open triggered once
98
+ expect(LightningConfirm.open.mock.calls).toHaveLength(1);
99
+ })
100
+ ```
@@ -0,0 +1,7 @@
1
+ .example {
2
+ margin: 0.5rem;
3
+ border-radius: 0.5rem;
4
+ background: #FFF;
5
+ box-shadow: 0 1px 0.25rem rgba(0, 0, 0, 0.2);
6
+ padding: 1rem;
7
+ }
@@ -0,0 +1,8 @@
1
+ <template>
2
+ <div class="example">
3
+ <button
4
+ aria-haspopup="modal"
5
+ onclick={handleConfirmModal}
6
+ >Open the Confirm Modal</button>
7
+ </div>
8
+ </template>
@@ -0,0 +1,14 @@
1
+ import { LightningElement } from 'lwc';
2
+ import LightningConfirm from 'lightning/confirm';
3
+
4
+ export default class ConfirmBasic extends LightningElement {
5
+ handleConfirmModal() {
6
+ LightningConfirm.open({
7
+ message: 'this is the confirm message',
8
+ label: 'Please Confirm',
9
+ theme: 'warning',
10
+ }).then((result) => {
11
+ console.log('confirm result', result);
12
+ });
13
+ }
14
+ }
@@ -0,0 +1,3 @@
1
+ <template>
2
+ <p>{message}</p>
3
+ </template>
@@ -0,0 +1,80 @@
1
+ import { api } from 'lwc';
2
+ import LightningInteractiveDialogBase from 'lightning/interactiveDialogBase';
3
+ import { parent, instanceName, secure } from 'lightning/overlayUtils';
4
+ import LightningOverlay from 'lightning/overlay';
5
+ import labelDefault from '@salesforce/label/LightningConfirm.defaultLabel';
6
+
7
+ /**
8
+ * Create a confirm modal within your component that asks the user
9
+ * to respond before they continue.
10
+ */
11
+
12
+ export default class LightningConfirm extends LightningOverlay {
13
+ static [instanceName] = 'lightning-confirm';
14
+ static [parent] = LightningInteractiveDialogBase;
15
+
16
+ /**
17
+ * value to use for header text in "header" variant
18
+ * or aria-label in "headerless" variant
19
+ * @type {string}
20
+ * @default "Confirm" (translated accordingly)
21
+ */
22
+ @api label = labelDefault;
23
+
24
+ /**
25
+ * text to display in body of modal
26
+ */
27
+ @api message = '';
28
+
29
+ /**
30
+ * variant to use for alert; may be
31
+ * set to "header" or "headerless"
32
+ */
33
+ @api variant = 'header';
34
+
35
+ /**
36
+ * theme to use when variant is "header"
37
+ * valid values are based on SLDS themes and are
38
+ * listed in "themeOptions" of interactiveDialogBase.js
39
+ */
40
+ @api theme = 'default';
41
+
42
+ /**
43
+ * Dispatches privateclose event
44
+ * and closes dialog
45
+ */
46
+ close(result) {
47
+ const promise = new Promise((resolve) => {
48
+ this.dispatchEvent(
49
+ new CustomEvent('privateclose', {
50
+ detail: {
51
+ resolve,
52
+ [secure]: true,
53
+ },
54
+ bubbles: true,
55
+ })
56
+ );
57
+ });
58
+ super.close(result, promise);
59
+ }
60
+
61
+ /**
62
+ * Dispatches privatechildrender event
63
+ * with data parent needs to correctly render
64
+ */
65
+ renderedCallback() {
66
+ const evt = new CustomEvent('privatechildrender', {
67
+ bubbles: true,
68
+ detail: {
69
+ message: this.message,
70
+ label: this.label,
71
+ hideCancel: false,
72
+ showDescription: true,
73
+ getOkValue: () => true,
74
+ getCancelValue: () => false,
75
+ role: 'alertdialog',
76
+ },
77
+ });
78
+ this.dispatchEvent(evt);
79
+ }
80
+ }
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
3
+ <isExposed>true</isExposed>
4
+ <minApiVersion>54.0</minApiVersion>
5
+ <support>GA</support>
6
+ </LightningComponentBundle>
@@ -0,0 +1,21 @@
1
+ const recordMetadata = {
2
+ name: 'name',
3
+ email: 'email',
4
+ website: 'url',
5
+ amount: 'currency',
6
+ phone: 'phoneNumber',
7
+ closeAt: 'dateInFuture',
8
+ };
9
+
10
+ export default function fetchData(amountOfRecords) {
11
+ return fetch('https://data-faker.herokuapp.com/collection', {
12
+ method: 'POST',
13
+ headers: {
14
+ 'Content-Type': 'application/json; charset=utf-8',
15
+ },
16
+ body: JSON.stringify({
17
+ amountOfRecords,
18
+ recordMetadata,
19
+ }),
20
+ }).then((response) => response.json());
21
+ }
@@ -0,0 +1,13 @@
1
+ <template>
2
+ <p>Total Rows: {data.length}</p>
3
+ <div style="height: 300px;">
4
+ <lightning-datatable
5
+ key-field="id"
6
+ data={data}
7
+ columns={columns}
8
+ enable-infinite-loading
9
+ onloadmore={handleLoadMore}>
10
+ </lightning-datatable>
11
+ </div>
12
+ <p>{loadMoreStatus}</p>
13
+ </template>
@@ -0,0 +1,42 @@
1
+ import { LightningElement } from 'lwc';
2
+ import fetchData from './fetchDataHelper';
3
+
4
+ const columns = [
5
+ { label: 'Label', fieldName: 'name' },
6
+ { label: 'Website', fieldName: 'website', type: 'url' },
7
+ { label: 'Phone', fieldName: 'phone', type: 'phone' },
8
+ { label: 'Balance', fieldName: 'amount', type: 'currency' },
9
+ { label: 'CloseAt', fieldName: 'closeAt', type: 'date' },
10
+ ];
11
+
12
+ export default class DatatableWithInfiniteLoading extends LightningElement {
13
+ data = [];
14
+ columns = columns;
15
+ loadMoreStatus;
16
+ totalNumberOfRows = 250;
17
+
18
+ // eslint-disable-next-line @lwc/lwc/no-async-await
19
+ async connectedCallback() {
20
+ const data = await fetchData(100);
21
+ this.data = data;
22
+ }
23
+
24
+ // eslint-disable-next-line @lwc/lwc/no-async-await
25
+ async handleLoadMore(event) {
26
+ const datatable = event.target;
27
+ //Displays a spinner to signal that data is being loaded
28
+ datatable.isLoading = true;
29
+ //Displays "Loading" text when more data is being loaded
30
+ this.loadMoreStatus = 'Loading';
31
+
32
+ const newData = await fetchData(50);
33
+ if (this.data.length >= this.totalNumberOfRows) {
34
+ datatable.enableInfiniteLoading = false;
35
+ this.loadMoreStatus = 'No more data to load';
36
+ } else {
37
+ this.data = this.data.concat(newData);
38
+ this.loadMoreStatus = '';
39
+ }
40
+ datatable.isLoading = false;
41
+ }
42
+ }
@@ -0,0 +1,17 @@
1
+ <template>
2
+ <div style="height:160px">
3
+ <lightning-datatable
4
+ key-field="id"
5
+ columns={columns}
6
+ data={data}
7
+ default-sort-direction={defaultSortDirection}
8
+ sorted-direction={sortDirection}
9
+ sorted-by={sortedBy}
10
+ onsort={onHandleSort}
11
+ is-loading={loading}>
12
+ </lightning-datatable>
13
+ </div>
14
+
15
+ <lightning-button label="Enable Loading State" onclick={handleLoadingClick}></lightning-button>
16
+ <lightning-button label="Add More Rows" onclick={handleMoreRowsClick}></lightning-button>
17
+ </template>
@@ -0,0 +1,91 @@
1
+ import { LightningElement } from 'lwc';
2
+
3
+ const data = [
4
+ { id: 1, name: 'Billy Simmons', age: 40, email: 'billy@salesforce.com' },
5
+ { id: 2, name: 'Kelsey Denesik', age: 35, email: 'kelsey@salesforce.com' },
6
+ { id: 3, name: 'Kyle Ruecker', age: 50, email: 'kyle@salesforce.com' },
7
+ {
8
+ id: 4,
9
+ name: 'Krystina Kerluke',
10
+ age: 37,
11
+ email: 'krystina@salesforce.com',
12
+ },
13
+ ];
14
+
15
+ const actions = [
16
+ { label: 'Show details', name: 'show_details' },
17
+ { label: 'Delete', name: 'delete' },
18
+ ];
19
+
20
+ const columns = [
21
+ { label: 'Name', fieldName: 'name' },
22
+ {
23
+ label: 'Age',
24
+ fieldName: 'age',
25
+ type: 'number',
26
+ sortable: true,
27
+ cellAttributes: { alignment: 'left' },
28
+ },
29
+ {
30
+ label: 'Email',
31
+ fieldName: 'email',
32
+ type: 'email',
33
+ hideDefaultActions: true,
34
+ },
35
+ {
36
+ type: 'action',
37
+ typeAttributes: { rowActions: actions, menuAlignment: 'right' },
38
+ },
39
+ ];
40
+
41
+ export default class DemoApp extends LightningElement {
42
+ data = data;
43
+ columns = columns;
44
+ defaultSortDirection = 'asc';
45
+ sortDirection = 'asc';
46
+ sortedBy;
47
+ loading = false;
48
+
49
+ // Used to sort the 'Age' column
50
+ sortBy(field, reverse, primer) {
51
+ const key = primer
52
+ ? function (x) {
53
+ return primer(x[field]);
54
+ }
55
+ : function (x) {
56
+ return x[field];
57
+ };
58
+
59
+ return function (a, b) {
60
+ a = key(a);
61
+ b = key(b);
62
+ return reverse * ((a > b) - (b > a));
63
+ };
64
+ }
65
+
66
+ onHandleSort(event) {
67
+ const { fieldName: sortedBy, sortDirection } = event.detail;
68
+ const cloneData = [...this.data];
69
+
70
+ cloneData.sort(this.sortBy(sortedBy, sortDirection === 'asc' ? 1 : -1));
71
+ this.data = cloneData;
72
+ this.sortDirection = sortDirection;
73
+ this.sortedBy = sortedBy;
74
+ }
75
+
76
+ handleLoadingClick() {
77
+ this.loading = !this.loading;
78
+ }
79
+
80
+ handleMoreRowsClick() {
81
+ const control = [
82
+ {
83
+ id: 20,
84
+ name: 'Jacqueline Palmer',
85
+ age: 60,
86
+ email: 'jacqueline@salesforce.com',
87
+ },
88
+ ];
89
+ this.data = this.data.concat(this.data).concat(control);
90
+ }
91
+ }
@@ -0,0 +1,189 @@
1
+ const Datatable = require('pageobjects/datatable');
2
+ const Button = require('pageobjects/button');
3
+
4
+ describe('datatable utam test', () => {
5
+ let root;
6
+
7
+ beforeEach(async () => {
8
+ await browser.url('/datatable/utam');
9
+ root = await $('datatable-utam');
10
+ await root.waitForDisplayed();
11
+ });
12
+ it('should get the cell value by row and column index', async () => {
13
+ const datatable = await utam.load(Datatable, {
14
+ element: await root.shadow$('lightning-datatable'),
15
+ });
16
+
17
+ const cellValue = await datatable.getCellValueByIndex(1, 2);
18
+ expect(cellValue).toBe('Billy Simmons');
19
+ });
20
+ it('should get the cell value by row index and column label', async () => {
21
+ const datatable = await utam.load(Datatable, {
22
+ element: await root.shadow$('lightning-datatable'),
23
+ });
24
+
25
+ const cellValue = await datatable.getCellValueByLabel(2, 'Age');
26
+ expect(cellValue).toBe('35');
27
+ });
28
+ it('should get the number of rows in the table', async () => {
29
+ const datatable = await utam.load(Datatable, {
30
+ element: await root.shadow$('lightning-datatable'),
31
+ });
32
+
33
+ const cellValue = await datatable.getNumRows();
34
+ expect(cellValue).toBe(4);
35
+ });
36
+ it('should tell if the table has any rows', async () => {
37
+ const datatable = await utam.load(Datatable, {
38
+ element: await root.shadow$('lightning-datatable'),
39
+ });
40
+
41
+ const cellValue = await datatable.hasRows();
42
+ expect(cellValue).toBe(true);
43
+ });
44
+ it('should toggle selection of row - comprehensive', async () => {
45
+ const datatable = await utam.load(Datatable, {
46
+ element: await root.shadow$('lightning-datatable'),
47
+ });
48
+
49
+ for (let i = 1; i <= 4; i++) {
50
+ expect(await datatable.isRowSelected(i)).toBe('false');
51
+ }
52
+
53
+ await datatable.toggleRowSelection(1);
54
+ expect(await datatable.isRowSelected(1)).toBe('true');
55
+ [2, 3, 4].forEach(async (i) => {
56
+ expect(await datatable.isRowSelected(i)).toBe('false');
57
+ });
58
+
59
+ await datatable.toggleRowSelection(2);
60
+ expect(await datatable.isRowSelected(2)).toBe('true');
61
+ [3, 4].forEach(async (i) => {
62
+ expect(await datatable.isRowSelected(i)).toBe('false');
63
+ });
64
+
65
+ await datatable.toggleRowSelection(3);
66
+ expect(await datatable.isRowSelected(3)).toBe('true');
67
+ expect(await datatable.isRowSelected(4)).toBe('false');
68
+
69
+ await datatable.toggleRowSelection(4);
70
+ expect(await datatable.isRowSelected(4)).toBe('true');
71
+ });
72
+ it('should toggle selection of row', async () => {
73
+ const datatable = await utam.load(Datatable, {
74
+ element: await root.shadow$('lightning-datatable'),
75
+ });
76
+
77
+ await datatable.toggleRowSelection(3);
78
+ expect(await datatable.isRowSelected(3)).toBe('true');
79
+
80
+ await datatable.toggleRowSelection(3);
81
+ expect(await datatable.isRowSelected(3)).toBe('false');
82
+ });
83
+ it('should get the number of selected rows when not all rows are selected', async () => {
84
+ const datatable = await utam.load(Datatable, {
85
+ element: await root.shadow$('lightning-datatable'),
86
+ });
87
+
88
+ await datatable.toggleRowSelection(3);
89
+ expect(await datatable.getNumSelectedRows()).toBe(1);
90
+
91
+ await datatable.toggleRowSelection(2);
92
+ expect(await datatable.getNumSelectedRows()).toBe(2);
93
+ });
94
+ it('should get the number of selected rows when all rows are selected', async () => {
95
+ const datatable = await utam.load(Datatable, {
96
+ element: await root.shadow$('lightning-datatable'),
97
+ });
98
+
99
+ await datatable.clickSelectAllCheckbox();
100
+ expect(await datatable.getNumSelectedRows()).toBe(4);
101
+ });
102
+ it('should get the number of columns in the table', async () => {
103
+ const datatable = await utam.load(Datatable, {
104
+ element: await root.shadow$('lightning-datatable'),
105
+ });
106
+
107
+ expect(await datatable.getNumColumns()).toBe(5);
108
+ });
109
+ it('should tell whether or not a column is sortable', async () => {
110
+ const datatable = await utam.load(Datatable, {
111
+ element: await root.shadow$('lightning-datatable'),
112
+ });
113
+
114
+ expect(await datatable.isSortableColumn('Age')).toBe(true);
115
+
116
+ // Need to speak to UTAM (about isPresent) or find a better way to write this method
117
+ // If column is not sortable, the test fails with the error:
118
+ // "Can't find elements with locator 'lightning-primitive-header-factory.slds-is-sortable' inside its scope element."
119
+ // expect(await datatable.isSortableColumn('Name')).toBe(false);
120
+ });
121
+ it('should tell whether or not the row is selectable', async () => {
122
+ const datatable = await utam.load(Datatable, {
123
+ element: await root.shadow$('lightning-datatable'),
124
+ });
125
+
126
+ expect(await datatable.isSelectableRow(1)).toBe(true);
127
+ });
128
+ it('should get the width of a column', async () => {
129
+ const datatable = await utam.load(Datatable, {
130
+ element: await root.shadow$('lightning-datatable'),
131
+ });
132
+
133
+ const dt = await root.shadow$('lightning-datatable');
134
+ const columnHeader = await dt.shadow$('thead > tr > th:nth-child(2)');
135
+ const expectedWidth = await columnHeader.getAttribute('style');
136
+ expect(await datatable.getWidth('Name')).toBe(expectedWidth);
137
+ });
138
+ it('should tell whether or not a column has header actions', async () => {
139
+ const datatable = await utam.load(Datatable, {
140
+ element: await root.shadow$('lightning-datatable'),
141
+ });
142
+
143
+ expect(await datatable.hasHeaderActions('Name')).toBe(true);
144
+ expect(await datatable.hasHeaderActions('Age')).toBe(true);
145
+ // false fails; need to check for true or null; check with UTAM if expected
146
+ expect(await datatable.hasHeaderActions('Email')).toBe(null);
147
+ });
148
+ it('should get the text of the rowheader cell of the specified row', async () => {
149
+ const datatable = await utam.load(Datatable, {
150
+ element: await root.shadow$('lightning-datatable'),
151
+ });
152
+
153
+ expect(await datatable.getRowHeaderText(2)).toBe('Kelsey Denesik');
154
+ });
155
+ it('should click column header of the sortable column', async () => {
156
+ const datatable = await utam.load(Datatable, {
157
+ element: await root.shadow$('lightning-datatable'),
158
+ });
159
+
160
+ let cellValue = await datatable.getCellValueByLabel(1, 'Age');
161
+ expect(cellValue).toBe('40');
162
+
163
+ await datatable.clickSortHeaderButton('Age');
164
+
165
+ cellValue = await datatable.getCellValueByLabel(1, 'Age');
166
+ expect(cellValue).toBe('35');
167
+ });
168
+ it('should tell whether the specified row has row actions or not', async () => {
169
+ const datatable = await utam.load(Datatable, {
170
+ element: await root.shadow$('lightning-datatable'),
171
+ });
172
+
173
+ expect(await datatable.hasRowActionInRow(2)).toBe(true);
174
+ });
175
+ it('should tell whether or not the datatable has the loading indicator visible', async () => {
176
+ const datatable = await utam.load(Datatable, {
177
+ element: await root.shadow$('lightning-datatable'),
178
+ });
179
+
180
+ expect(await datatable.isLoading()).toBe(false);
181
+
182
+ const button = await utam.load(Button, {
183
+ element: await root.shadow$('lightning-button'),
184
+ });
185
+ await button.click();
186
+
187
+ expect(await datatable.isLoading()).toBe(true);
188
+ });
189
+ });