lightning-base-components 1.18.4-alpha → 1.18.6-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/metadata/raptor.json +21 -0
  2. package/package.json +4 -2
  3. package/src/lightning/baseCombobox/baseCombobox.js +20 -14
  4. package/src/lightning/button/button.js +3 -2
  5. package/src/lightning/buttonIcon/buttonIcon.js +19 -16
  6. package/src/lightning/combobox/combobox.js +17 -16
  7. package/src/lightning/f6Controller/f6Controller.js +49 -3
  8. package/src/lightning/formattedRichText/formatted-rich-text.slds.css +1 -1
  9. package/src/lightning/formattedRichText/formattedRichText.css +1 -0
  10. package/src/lightning/formattedRichText/formattedRichText.html +1 -1
  11. package/src/lightning/formattedRichText/formattedRichText.js +1 -0
  12. package/src/lightning/layout/layout.js +2 -0
  13. package/src/lightning/layoutItem/layoutItem.js +2 -0
  14. package/src/lightning/primitiveButton/primitiveButton.js +8 -8
  15. package/src/lightning/sldsCommon/sldsCommon.css +14 -6
  16. package/src/lightning/sldsUtilsPosition/sldsUtilsPosition.css +4 -4
  17. package/src/lightning/sldsUtilsThemes/sldsUtilsThemes.css +50 -19
  18. package/src/lightning/spinner/spinner.js +7 -3
  19. package/src/lightning/toast/button-icon.slds.css +909 -0
  20. package/src/lightning/toast/formatted-rich-text.slds.css +230 -0
  21. package/src/lightning/toast/icon.slds.css +209 -0
  22. package/src/lightning/toast/toast.css +22 -6
  23. package/src/lightning/toast/toast.html +1 -1
  24. package/src/lightning/toast/toast.js +9 -7
  25. package/src/lightning/toast/toast.slds.css +97 -0
  26. package/src/lightning/toastContainer/toast.slds.css +97 -0
  27. package/src/lightning/toastContainer/toastContainer.css +17 -6
  28. package/src/lightning/toastContainer/toastContainer.js +4 -0
  29. package/src/lightning/utilsPrivate/url.js +4 -1
  30. package/src/lightning/utilsPrivate/utilsPrivate.js +8 -4
  31. package/src/lightning/button/__wdio__/utam/utam.html +0 -3
  32. package/src/lightning/button/__wdio__/utam/utam.js +0 -3
  33. package/src/lightning/button/__wdio__/utam/utam.spec.js +0 -20
  34. package/src/lightning/datatable/__wdio__/utam/utam.html +0 -32
  35. package/src/lightning/datatable/__wdio__/utam/utam.js +0 -91
  36. package/src/lightning/datatable/__wdio__/utam/utam.spec.js +0 -214
@@ -0,0 +1,97 @@
1
+
2
+ :host([data-render-mode="shadow"]) .slds-notify_toast {
3
+ display: inline-flex;
4
+ align-items: center;
5
+ position: relative;
6
+ background: none;
7
+ background-color: var(--slds-c-toast-color-background, var(--sds-g-color-neutral-base-50, #747474));
8
+ color: var(--slds-c-toast-text-color, var(--sds-g-color-neutral-base-100, #ffffff));
9
+ border-radius: var(--slds-c-toast-radius-border, var(--sds-g-radius-border-2, 0.25rem));
10
+ margin: var(--sds-g-spacing-2, 0.5rem);
11
+ padding-block-start: var(--slds-c-toast-spacing-block-start, var(--sds-g-spacing-3, 0.75rem));
12
+ padding-inline-end: var(--slds-c-toast-spacing-inline-end, var(--sds-g-spacing-8, 3rem));
13
+ padding-block-end: var(--slds-c-toast-spacing-block-end, var(--sds-g-spacing-3, 0.75rem));
14
+ padding-inline-start: var(--slds-c-toast-spacing-inline-start, var(--sds-g-spacing-5, 1.5rem));
15
+ min-width: var(--slds-c-toast-sizing-min-width, var(--sds-g-sizing-16, 30rem));
16
+ text-align: left;
17
+ justify-content: flex-start;
18
+ }
19
+
20
+ :host([data-render-mode="shadow"]) .slds-notify_toast a {
21
+ color: currentColor;
22
+ border: var(--sds-g-sizing-border-1, 1px) solid transparent;
23
+ border-radius: var(--sds-g-radius-border-2, 0.25rem);
24
+ }
25
+
26
+ :host([data-render-mode="shadow"]) .slds-notify_toast a:hover,:host([data-render-mode="shadow"])
27
+ .slds-notify_toast a:focus {
28
+ text-decoration: none;
29
+ outline: 0;
30
+ }
31
+
32
+ :host([data-render-mode="shadow"]) .slds-notify_toast a:focus {
33
+ box-shadow: 0 0 3px var(--sds-g-color-neutral-base-95, #f3f3f3);
34
+ border: var(--sds-g-sizing-border-1, 1px) solid var(--slds-g-color-neutral-base-100, var(--sds-g-color-neutral-base-100, #ffffff));
35
+ }
36
+
37
+ :host([data-render-mode="shadow"]) .slds-notify_toast a:active {
38
+ color: var(--slds-g-color-neutral-100-opacity-50, rgba(255, 255, 255, 0.5));
39
+ }
40
+
41
+ :host([data-render-mode="shadow"]) .slds-notify_toast a[disabled] {
42
+ color: var(--slds-g-color-neutral-100-opacity-10, rgba(255, 255, 255, 0.15));
43
+ }
44
+
45
+ :host([data-render-mode="shadow"]) .slds-notify_toast .slds-notify__close {
46
+ float: right;
47
+ position: absolute;
48
+ top: var(--sds-g-spacing-3, 0.75rem);
49
+ right: var(--sds-g-spacing-3, 0.75rem);
50
+ margin-inline-start: var(--sds-g-spacing-1, 0.25rem);
51
+ transform: translateY(-0.125rem);
52
+ }
53
+
54
+ :host([data-render-mode="shadow"]) .slds-region_narrow .slds-notify_toast {
55
+ min-width: auto;
56
+ width: 100%;
57
+ margin-inline-start: 0;
58
+ }
59
+
60
+ /* TODO W-12674349: remove after name-value-list utils are added */
61
+
62
+ :host([data-render-mode="shadow"]) .slds-list--inline {
63
+ display: inline-flex;
64
+ max-width: 100%;
65
+ }
66
+
67
+ /* TODO W-12674349: remove after assistive text util is added */
68
+
69
+ :host([data-render-mode="shadow"]) .slds-assistive-text {
70
+ position: absolute !important;
71
+ margin: -1px !important;
72
+ border: 0 !important;
73
+ padding: 0 !important;
74
+ width: 1px !important;
75
+ height: 1px !important;
76
+ overflow: hidden !important;
77
+ clip: rect(0 0 0 0) !important;
78
+ text-transform: none !important;
79
+ white-space: nowrap !important;
80
+ }
81
+
82
+ /* TODO W-12674349: remove after text utils are added */
83
+
84
+ :host([data-render-mode="shadow"]) .slds-text-heading_small {
85
+ font-size: var(--sds-g-font-size-base, 1rem);
86
+ line-height: var(--sds-g-font-lineheight-2, 1.25);
87
+ }
88
+
89
+ /* TODO W-12674349: remove after alert is added */
90
+
91
+ :host([data-render-mode="shadow"]) .slds-notify__close {
92
+ position: absolute;
93
+ top: 50%;
94
+ right: var(--sds-g-spacing-3, 0.75rem);
95
+ margin-inline-start: var(--sds-g-spacing-1, 0.25rem);
96
+ transform: translateY(-50%);
97
+ }
@@ -1,30 +1,41 @@
1
- .top {
1
+ @import 'lightning/sldsCommon';
2
+ @import './toast.slds.css';
3
+ @import 'lightning/sldsUtilsPosition';
4
+ @import 'lightning/sldsUtilsGrid';
5
+
6
+ .top,
7
+ :host([data-render-mode="shadow"]) .top {
2
8
  top: 0;
3
9
  bottom: unset;
4
10
  }
5
11
 
6
- .bottom {
12
+ .bottom,
13
+ :host([data-render-mode="shadow"]) .bottom {
7
14
  bottom: 0;
8
15
  top: unset;
9
16
  }
10
17
 
11
- .left {
18
+ .left,
19
+ :host([data-render-mode="shadow"]) .left {
12
20
  left: 0;
13
21
  right: auto;
14
22
  }
15
23
 
16
- .right {
24
+ .right,
25
+ :host([data-render-mode="shadow"]) .right {
17
26
  left: auto;
18
27
  right: 0;
19
28
  }
20
29
 
21
- .center {
30
+ .center,
31
+ :host([data-render-mode="shadow"]) .center {
22
32
  transform: translate(50%);
23
33
  right: 50%;
24
34
  }
25
35
 
26
36
  @media (max-width: 30rem) {
27
- .center {
37
+ .center,
38
+ :host([data-render-mode="shadow"]) .center {
28
39
  transform: none;
29
40
  right: 0;
30
41
  left: 0;
@@ -172,6 +172,10 @@ export default class ToastContainer extends LightningOverlay {
172
172
 
173
173
  // private functions
174
174
  connectedCallback() {
175
+ // Set `data-render-mode` attribute in native shadow mode
176
+ if (!this.template.synthetic) {
177
+ this.setAttribute('data-render-mode', 'shadow');
178
+ }
175
179
  if (globalContainer.length < MAX_NUM_GLOBAL_TOAST_CONTAINER) {
176
180
  this._showToastHandler = this.handleShowToast.bind(this);
177
181
  document.body.addEventListener(
@@ -1,11 +1,14 @@
1
+ import { isCSR } from './ssr';
2
+
1
3
  const URL_CHECK_REGEX = /^(\/+|\.+|ftp|http(s?):\/\/)/i;
4
+ const SSR_PROTOCOL = 'https:'; // For LWR (SSR), the protocol will always be HTTPS. See TD-0141280.
2
5
 
3
6
  export function isAbsoluteUrl(url) {
4
7
  return URL_CHECK_REGEX.test(url);
5
8
  }
6
9
 
7
10
  export function makeAbsoluteUrl(url) {
8
- const protocol = window.location.protocol;
11
+ const protocol = isCSR ? window.location.protocol : SSR_PROTOCOL;
9
12
  return isAbsoluteUrl(url) ? url : `${protocol}//${url}`;
10
13
  }
11
14
 
@@ -162,10 +162,14 @@ const DEFAULT_ZINDEX_BASELINE = DEFAULT_MODAL_ZINDEX + DEFAULT_ZINDEX_OFFSET;
162
162
  export function getZIndexBaseline() {
163
163
  // When SLDS styles are present, typically on Core
164
164
  // this currently resolves to: '9000' (string)
165
- const modalZindexValueLwc = (
166
- window.getComputedStyle(document.documentElement) ||
167
- document.documentElement.style
168
- ).getPropertyValue('--lwc-zIndexModal');
165
+ // If function is called in server context, use default as window and document are not available.
166
+ const isCSR = typeof window !== 'undefined';
167
+ const modalZindexValueLwc = isCSR
168
+ ? (
169
+ window.getComputedStyle(document.documentElement) ||
170
+ document.documentElement.style
171
+ ).getPropertyValue('--lwc-zIndexModal')
172
+ : DEFAULT_MODAL_ZINDEX;
169
173
 
170
174
  const baseZindexModalLwc = parseInt(modalZindexValueLwc, 10);
171
175
 
@@ -1,3 +0,0 @@
1
- <template>
2
- <lightning-button label="Click me" variant="brand"></lightning-button>
3
- </template>
@@ -1,3 +0,0 @@
1
- import { LightningElement } from 'lwc';
2
-
3
- export default class ButtonUtam extends LightningElement {}
@@ -1,20 +0,0 @@
1
- const Button = require('pageobjects/button');
2
-
3
- describe('button utam test', () => {
4
- let root;
5
-
6
- beforeEach(async () => {
7
- await browser.url('/button/utam');
8
- root = await $('button-utam');
9
- await root.waitForDisplayed();
10
- });
11
-
12
- it('should get the button name', async () => {
13
- const button = await utam.load(Button, {
14
- element: await root.shadow$('lightning-button'),
15
- });
16
-
17
- const label = await button.getButtonName();
18
- expect(label).toBe('Click me');
19
- });
20
- });
@@ -1,32 +0,0 @@
1
- <template>
2
- <div style="height:160px">
3
- <lightning-datatable
4
- data-render-mode="default"
5
- key-field="id"
6
- columns={columns}
7
- data={data}
8
- default-sort-direction={defaultSortDirection}
9
- sorted-direction={sortDirection}
10
- sorted-by={sortedBy}
11
- onsort={onHandleSort}
12
- is-loading={loading}>
13
- </lightning-datatable>
14
- </div>
15
- <div style="height:160px">
16
- <lightning-datatable
17
- data-render-mode="role-based"
18
- key-field="id"
19
- columns={columns}
20
- data={data}
21
- default-sort-direction={defaultSortDirection}
22
- sorted-direction={sortDirection}
23
- sorted-by={sortedBy}
24
- onsort={onHandleSort}
25
- is-loading={loading}
26
- render-mode="role-based">
27
- </lightning-datatable>
28
- </div>
29
-
30
- <lightning-button label="Enable Loading State" onclick={handleLoadingClick}></lightning-button>
31
- <lightning-button label="Add More Rows" onclick={handleMoreRowsClick}></lightning-button>
32
- </template>
@@ -1,91 +0,0 @@
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
- }
@@ -1,214 +0,0 @@
1
- const Datatable = require('pageobjects/datatable');
2
- const Button = require('pageobjects/button');
3
-
4
- const tableTypes = {
5
- default: '[data-render-mode="default"]',
6
- roleBased: '[data-render-mode="role-based"]',
7
- };
8
-
9
- describe('Datatable UTAM Page Object Tests', () => {
10
- Object.keys(tableTypes).forEach((type) => {
11
- describe(`${type} table`, () => {
12
- const TABLE_SELECTOR = tableTypes[type];
13
-
14
- let root;
15
-
16
- beforeEach(async () => {
17
- await browser.url('/datatable/utam');
18
- root = await $('datatable-utam');
19
- await root.waitForDisplayed();
20
- });
21
-
22
- it('should get the cell value by row and column index', async () => {
23
- const datatable = await utam.load(Datatable, {
24
- element: await root.shadow$(TABLE_SELECTOR),
25
- });
26
-
27
- const cellValue = await datatable.getCellValueByIndex(1, 2);
28
- expect(cellValue).toBe('Billy Simmons');
29
- });
30
- it('should get the cell value by row index and column label', async () => {
31
- const datatable = await utam.load(Datatable, {
32
- element: await root.shadow$(TABLE_SELECTOR),
33
- });
34
-
35
- const cellValue = await datatable.getCellValueByLabel(2, 'Age');
36
- expect(cellValue).toBe('35');
37
- });
38
- it('should get the number of rows in the table', async () => {
39
- const datatable = await utam.load(Datatable, {
40
- element: await root.shadow$(TABLE_SELECTOR),
41
- });
42
-
43
- const cellValue = await datatable.getNumRows();
44
- expect(cellValue).toBe(4);
45
- });
46
- it('should tell if the table has any rows', async () => {
47
- const datatable = await utam.load(Datatable, {
48
- element: await root.shadow$(TABLE_SELECTOR),
49
- });
50
-
51
- const cellValue = await datatable.hasRows();
52
- expect(cellValue).toBe(true);
53
- });
54
- it('should toggle selection of row - comprehensive', async () => {
55
- const datatable = await utam.load(Datatable, {
56
- element: await root.shadow$(TABLE_SELECTOR),
57
- });
58
-
59
- for (let i = 1; i <= 4; i++) {
60
- expect(await datatable.isRowSelected(i)).toBe('false');
61
- }
62
-
63
- await datatable.toggleRowSelection(1);
64
- expect(await datatable.isRowSelected(1)).toBe('true');
65
- [2, 3, 4].forEach(async (i) => {
66
- expect(await datatable.isRowSelected(i)).toBe('false');
67
- });
68
-
69
- await datatable.toggleRowSelection(2);
70
- expect(await datatable.isRowSelected(2)).toBe('true');
71
- [3, 4].forEach(async (i) => {
72
- expect(await datatable.isRowSelected(i)).toBe('false');
73
- });
74
-
75
- await datatable.toggleRowSelection(3);
76
- expect(await datatable.isRowSelected(3)).toBe('true');
77
- expect(await datatable.isRowSelected(4)).toBe('false');
78
-
79
- await datatable.toggleRowSelection(4);
80
- expect(await datatable.isRowSelected(4)).toBe('true');
81
- });
82
- it('should toggle selection of row', async () => {
83
- const datatable = await utam.load(Datatable, {
84
- element: await root.shadow$(TABLE_SELECTOR),
85
- });
86
-
87
- await datatable.toggleRowSelection(3);
88
- expect(await datatable.isRowSelected(3)).toBe('true');
89
-
90
- await datatable.toggleRowSelection(3);
91
- expect(await datatable.isRowSelected(3)).toBe('false');
92
- });
93
- it('should get the number of selected rows when not all rows are selected', async () => {
94
- const datatable = await utam.load(Datatable, {
95
- element: await root.shadow$(TABLE_SELECTOR),
96
- });
97
-
98
- await datatable.toggleRowSelection(3);
99
- expect(await datatable.getNumSelectedRows()).toBe(1);
100
-
101
- await datatable.toggleRowSelection(2);
102
- expect(await datatable.getNumSelectedRows()).toBe(2);
103
- });
104
- it('should get the number of selected rows when all rows are selected', async () => {
105
- const datatable = await utam.load(Datatable, {
106
- element: await root.shadow$(TABLE_SELECTOR),
107
- });
108
-
109
- await datatable.clickSelectAllCheckbox();
110
- expect(await datatable.getNumSelectedRows()).toBe(4);
111
- });
112
- it('should get the number of columns in the table', async () => {
113
- const datatable = await utam.load(Datatable, {
114
- element: await root.shadow$(TABLE_SELECTOR),
115
- });
116
-
117
- expect(await datatable.getNumColumns()).toBe(5);
118
- });
119
- it('should tell whether or not a column is sortable', async () => {
120
- const datatable = await utam.load(Datatable, {
121
- element: await root.shadow$(TABLE_SELECTOR),
122
- });
123
-
124
- expect(await datatable.isSortableColumn('Age')).toBe(true);
125
-
126
- // Need to speak to UTAM (about isPresent) or find a better way to write this method
127
- // If column is not sortable, the test fails with the error:
128
- // "Can't find elements with locator 'lightning-primitive-header-factory.slds-is-sortable' inside its scope element."
129
- // expect(await datatable.isSortableColumn('Name')).toBe(false);
130
- });
131
- it('should tell whether or not the row is selectable', async () => {
132
- const datatable = await utam.load(Datatable, {
133
- element: await root.shadow$(TABLE_SELECTOR),
134
- });
135
-
136
- expect(await datatable.isSelectableRow(1)).toBe(true);
137
- });
138
- it('should get the width of a column', async () => {
139
- const datatable = await utam.load(Datatable, {
140
- element: await root.shadow$(TABLE_SELECTOR),
141
- });
142
-
143
- const datatableElement = await root.shadow$(
144
- 'lightning-datatable'
145
- );
146
- const columnHeader = await datatableElement.shadow$(
147
- '[aria-label="Name"]'
148
- );
149
-
150
- // Remove intermediate white spaces
151
- let expectedWidth = await columnHeader.getAttribute('style');
152
- expectedWidth = expectedWidth.replace(/\s/g, '');
153
- let actualWidth = await datatable.getWidth('Name');
154
- actualWidth = actualWidth.replace(/\s/g, '');
155
-
156
- // Using indexOf in case of presence of ';'
157
- expect(actualWidth.indexOf(expectedWidth) >= 0).toBe(true);
158
- });
159
- it('should tell whether or not a column has header actions', async () => {
160
- const datatable = await utam.load(Datatable, {
161
- element: await root.shadow$(TABLE_SELECTOR),
162
- });
163
-
164
- expect(await datatable.hasHeaderActions('Name')).toBe(true);
165
- expect(await datatable.hasHeaderActions('Age')).toBe(true);
166
- // false fails; need to check for true or null; check with UTAM if expected
167
- expect(await datatable.hasHeaderActions('Email')).toBe(null);
168
- });
169
- it('should get the text of the rowheader cell of the specified row', async () => {
170
- const datatable = await utam.load(Datatable, {
171
- element: await root.shadow$(TABLE_SELECTOR),
172
- });
173
-
174
- expect(await datatable.getRowHeaderText(2)).toBe(
175
- 'Kelsey Denesik'
176
- );
177
- });
178
- it('should click column header of the sortable column', async () => {
179
- const datatable = await utam.load(Datatable, {
180
- element: await root.shadow$(TABLE_SELECTOR),
181
- });
182
-
183
- let cellValue = await datatable.getCellValueByLabel(1, 'Age');
184
- expect(cellValue).toBe('40');
185
-
186
- await datatable.clickSortHeaderButton('Age');
187
-
188
- cellValue = await datatable.getCellValueByLabel(1, 'Age');
189
- expect(cellValue).toBe('35');
190
- });
191
- it('should tell whether the specified row has row actions or not', async () => {
192
- const datatable = await utam.load(Datatable, {
193
- element: await root.shadow$(TABLE_SELECTOR),
194
- });
195
-
196
- expect(await datatable.hasRowActionInRow(2)).toBe(true);
197
- });
198
- it('should tell whether or not the datatable has the loading indicator visible', async () => {
199
- const datatable = await utam.load(Datatable, {
200
- element: await root.shadow$(TABLE_SELECTOR),
201
- });
202
-
203
- expect(await datatable.isLoading()).toBe(false);
204
-
205
- const button = await utam.load(Button, {
206
- element: await root.shadow$('lightning-button'),
207
- });
208
- await button.click();
209
-
210
- expect(await datatable.isLoading()).toBe(true);
211
- });
212
- });
213
- });
214
- });