lightning-base-components 1.13.9-alpha → 1.14.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 (41) hide show
  1. package/package.json +5 -1
  2. package/scopedImports/@salesforce-internal-core.appVersion.js +1 -1
  3. package/scopedImports/@salesforce-label-LightningLookup.recentItems.js +1 -0
  4. package/src/lightning/baseCombobox/baseCombobox.html +1 -0
  5. package/src/lightning/baseCombobox/baseCombobox.js +14 -1
  6. package/src/lightning/combobox/combobox.css +12 -0
  7. package/src/lightning/combobox/combobox.html +1 -0
  8. package/src/lightning/datatable/columnWidthManager.js +7 -3
  9. package/src/lightning/datatable/datatable.js +27 -18
  10. package/src/lightning/datatable/inlineEdit.js +15 -3
  11. package/src/lightning/datatable/keyboard.js +1077 -933
  12. package/src/lightning/datatable/resizer.js +91 -108
  13. package/src/lightning/datatable/state.js +0 -9
  14. package/src/lightning/datatable/templates/div/div.css +19 -0
  15. package/src/lightning/datatable/templates/div/div.html +5 -5
  16. package/src/lightning/datatable/templates/table/table.html +4 -4
  17. package/src/lightning/datatable/widthManagerShared.js +1 -1
  18. package/src/lightning/iconSvgTemplates/buildTemplates/templates.js +2 -1
  19. package/src/lightning/iconSvgTemplates/buildTemplates/utility/contract_alt.html +1 -2
  20. package/src/lightning/iconSvgTemplates/buildTemplates/utility/contract_doc.html +8 -0
  21. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/templates.js +2 -1
  22. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/contract_alt.html +1 -2
  23. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/contract_doc.html +8 -0
  24. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/templates.js +2 -1
  25. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/contract_alt.html +1 -2
  26. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/contract_doc.html +8 -0
  27. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/templates.js +2 -1
  28. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/contract_alt.html +1 -2
  29. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/contract_doc.html +8 -0
  30. package/src/lightning/input/input.html +0 -1
  31. package/src/lightning/input/input.js +21 -25
  32. package/src/lightning/primitiveDatatableIeditPanel/primitiveDatatableIeditPanel.js +20 -0
  33. package/src/lightning/primitiveDatatableIeditTypeFactory/primitiveDatatableIeditTypeFactory.js +10 -0
  34. package/src/lightning/primitiveHeaderFactory/nonsortableHeader.html +5 -4
  35. package/src/lightning/primitiveHeaderFactory/primitiveHeaderFactory.js +46 -46
  36. package/src/lightning/primitiveHeaderFactory/selectableHeader.html +25 -23
  37. package/src/lightning/primitiveHeaderFactory/sortableHeader.html +13 -9
  38. package/src/lightning/progressIndicator/progressIndicator.js +3 -5
  39. package/src/lightning/progressStep/progressStep.js +2 -1
  40. package/src/lightning/utilsPrivate/utilsPrivate.js +11 -1
  41. package/src/lightning/utilsPrivate/contentMutation.js +0 -295
@@ -181,44 +181,51 @@ export default class PrimitiveHeaderFactory extends PrimitiveDatatableCell {
181
181
  }
182
182
 
183
183
  /**
184
- * Determines if sort direction is set to ascending
184
+ * Computes an option name
185
185
  *
186
- * @return {boolean} Whether the sort direction is ascending
186
+ * @return {string} The computed option name
187
187
  */
188
- get isAscSorted() {
189
- return this.sortedDirection === 'asc';
188
+ get computedOptionName() {
189
+ return `${this.dtContextId}-options`;
190
190
  }
191
191
 
192
192
  /**
193
- * Determines if sort direction is set to descending
193
+ * Determines if the header has actions available
194
194
  *
195
- * @return {boolean} Whether the sort direction is descending
195
+ * @return {boolean} Whether the header has available actions
196
196
  */
197
- get isDescSorted() {
198
- return this.sortedDirection === 'desc';
197
+ get hasActions() {
198
+ return (
199
+ this.actions.customerActions.length > 0 ||
200
+ this.actions.internalActions.length > 0
201
+ );
199
202
  }
200
203
 
201
204
  /**
202
- * Returns the sort order label in the appropriate language
205
+ * Returns the header's aria role
203
206
  *
204
- * @return {string} Language-specific sort order label
207
+ * @return {string|boolean} The aria role for the header
205
208
  */
206
- get sortedOrderLabel() {
207
- if (this.sorted) {
208
- return this.sortedDirection === 'desc'
209
- ? i18n.sortDesc
210
- : i18n.sortAsc;
211
- }
212
- return i18n.sortNone;
209
+ get headerRole() {
210
+ return this.isResizable || this.sortable ? 'button' : false;
213
211
  }
214
212
 
215
213
  /**
216
- * Determines if the header is selectable
214
+ * Determines if sort direction is set to ascending
217
215
  *
218
- * @return {boolean} Whether the header is selectable
216
+ * @return {boolean} Whether the sort direction is ascending
219
217
  */
220
- get isSelectableHeader() {
221
- return this.def.type === 'SELECTABLE_CHECKBOX';
218
+ get isAscSorted() {
219
+ return this.sortedDirection === 'asc';
220
+ }
221
+
222
+ /**
223
+ * Determines if sort direction is set to descending
224
+ *
225
+ * @return {boolean} Whether the sort direction is descending
226
+ */
227
+ get isDescSorted() {
228
+ return this.sortedDirection === 'desc';
222
229
  }
223
230
 
224
231
  /**
@@ -239,6 +246,15 @@ export default class PrimitiveHeaderFactory extends PrimitiveDatatableCell {
239
246
  return this.resizable && this.def.resizable !== false;
240
247
  }
241
248
 
249
+ /**
250
+ * Determines if the header is selectable
251
+ *
252
+ * @return {boolean} Whether the header is selectable
253
+ */
254
+ get isSelectableHeader() {
255
+ return this.def.type === 'SELECTABLE_CHECKBOX';
256
+ }
257
+
242
258
  /**
243
259
  * Determines if the header is sortable
244
260
  *
@@ -257,15 +273,6 @@ export default class PrimitiveHeaderFactory extends PrimitiveDatatableCell {
257
273
  return i18n;
258
274
  }
259
275
 
260
- /**
261
- * Returns the header's aria role
262
- *
263
- * @return {string|boolean} The aria role for the header
264
- */
265
- get headerRole() {
266
- return this.isResizable || this.sortable ? 'button' : false;
267
- }
268
-
269
276
  /**
270
277
  * Returns the header's resize step
271
278
  *
@@ -276,24 +283,17 @@ export default class PrimitiveHeaderFactory extends PrimitiveDatatableCell {
276
283
  }
277
284
 
278
285
  /**
279
- * Computes an option name
280
- *
281
- * @return {string} The computed option name
282
- */
283
- get computedOptionName() {
284
- return `${this.dtContextId}-options`;
285
- }
286
-
287
- /**
288
- * Determines if the header has actions available
286
+ * Returns the sort order label in the appropriate language
289
287
  *
290
- * @return {boolean} Whether the header has available actions
288
+ * @return {string} Language-specific sort order label
291
289
  */
292
- get hasActions() {
293
- return (
294
- this.actions.customerActions.length > 0 ||
295
- this.actions.internalActions.length > 0
296
- );
290
+ get sortedOrderLabel() {
291
+ if (this.sorted) {
292
+ return this.sortedDirection === 'desc'
293
+ ? i18n.sortDesc
294
+ : i18n.sortAsc;
295
+ }
296
+ return i18n.sortNone;
297
297
  }
298
298
 
299
299
  /************************** LIFECYCLE HOOKS **************************/
@@ -1,30 +1,32 @@
1
1
  <template>
2
- <div class="slds-th__action slds-th__action_form slds-cell-fixed"
3
- style={columnStyles}>
2
+ <!-- Header Content -->
3
+ <div class="slds-th__action slds-th__action_form slds-cell-fixed" style={columnStyles}>
4
4
  <template if:true={showCheckbox}>
5
- <span class="slds-checkbox">
6
- <input
7
- type="checkbox"
8
- class="datatable-select-all"
9
- name={computedOptionName}
10
- id="lgt-dt-header-factory-id"
11
- onclick={handleSelectAllRows}
12
- tabindex={internalTabIndex}
13
- data-navigation="enable"
14
- disabled={def.isBulkSelectionDisabled}
15
- >
16
- <label class="slds-checkbox__label" for="lgt-dt-header-factory-id">
17
- <span class="slds-checkbox_faux"></span>
18
- <span class="slds-form-element__label slds-assistive-text">
19
- {i18n.selectAll}
20
- </span>
21
- </label>
22
- </span>
5
+ <span class="slds-checkbox">
6
+
7
+ <!-- Selectable Checkbox -->
8
+ <input
9
+ type="checkbox"
10
+ class="datatable-select-all"
11
+ name={computedOptionName}
12
+ id="lgt-dt-header-factory-id"
13
+ onclick={handleSelectAllRows}
14
+ tabindex={internalTabIndex}
15
+ data-navigation="enable"
16
+ disabled={def.isBulkSelectionDisabled}>
17
+
18
+ <label class="slds-checkbox__label" for="lgt-dt-header-factory-id">
19
+ <span class="slds-checkbox_faux"></span>
20
+ <span class="slds-form-element__label slds-assistive-text">
21
+ {i18n.selectAll}
22
+ </span>
23
+ </label>
24
+ </span>
23
25
  </template>
24
26
  <template if:false={showCheckbox}>
25
- <span id="column-group-header" class="slds-assistive-text" data-column-header>
26
- {i18n.chooseARow}
27
- </span>
27
+ <span id="column-group-header" class="slds-assistive-text" data-column-header>
28
+ {i18n.chooseARow}
29
+ </span>
28
30
  </template>
29
31
  </div>
30
32
  </template>
@@ -1,19 +1,19 @@
1
1
  <template>
2
- <span
3
- class={computedClass}
4
- tabindex={internalTabIndex}
5
- style={columnStyles}
6
- >
2
+ <!-- Header Content -->
3
+ <span class={computedClass} tabindex={internalTabIndex} style={columnStyles}>
4
+
7
5
  <a href="javascript:void(0);"
8
6
  class={computedSortClass}
9
7
  role={headerRole}
10
8
  tabindex={internalTabIndex}
11
9
  data-navigation="enable"
12
10
  onclick={handleSortingClick}
13
- style={columnStyles} data-action-triggers="enter">
11
+ style={columnStyles}
12
+ data-action-triggers="enter">
14
13
 
15
14
  <span class="slds-assistive-text">{i18n.sort}</span>
16
15
 
16
+ <!-- Icon to display to the left/start of the header text -->
17
17
  <template if:true={def.iconName}>
18
18
  <div class="slds-grid slds-grid_vertical-align-center slds-has-flexi-truncate">
19
19
  <lightning-icon icon-name={def.iconName} size="x-small" class="slds-icon_container slds-m-right_xx-small" alternative-text={def.label} title={def.label}></lightning-icon>
@@ -21,17 +21,18 @@
21
21
  <span class="slds-truncate">{def.label}</span>
22
22
  </template>
23
23
 
24
+ <!-- Arrow Icon - Rotates based on sorting direction -->
24
25
  <lightning-primitive-icon
25
26
  class="slds-icon_container"
26
27
  svg-class="slds-icon slds-icon-text-default slds-is-sortable__icon"
27
28
  icon-name="utility:arrowdown"
28
29
  size="x-small">
29
30
  </lightning-primitive-icon>
30
-
31
31
  </div>
32
32
  </template>
33
33
  <template if:false={def.iconName}>
34
34
  <span class="slds-truncate" title={def.label}>{def.label}</span>
35
+ <!-- Arrow Icon - Rotates based on sorting direction -->
35
36
  <lightning-primitive-icon
36
37
  class="slds-icon_container"
37
38
  svg-class="slds-icon slds-icon-text-default slds-is-sortable__icon"
@@ -41,17 +42,20 @@
41
42
  </template>
42
43
  </a>
43
44
 
45
+ <!-- Aria Live Region to announce sorting order -->
44
46
  <span class="slds-assistive-text" aria-live="polite" aria-atomic="true">{sortedOrderLabel}</span>
45
47
 
48
+ <!-- Header Actions -->
46
49
  <template if:true={hasActions}>
47
50
  <lightning-primitive-header-actions
48
51
  col-key-value={def.colKeyValue}
49
52
  actions={actions}
50
53
  tabindex={internalTabIndex}
51
- data-navigation="enable"
52
- ></lightning-primitive-header-actions>
54
+ data-navigation="enable">
55
+ </lightning-primitive-header-actions>
53
56
  </template>
54
57
 
58
+ <!-- Resize Handler -->
55
59
  <template if:true={isResizable}>
56
60
  <lightning-primitive-resize-handler
57
61
  value={columnWidth}
@@ -100,18 +100,16 @@ export default class LightningProgressIndicator extends LightningElement {
100
100
  const currentStepIndex = getCurrentStepIndex(steps, currentStep);
101
101
 
102
102
  let activeStepIndex = -1;
103
-
104
- // Set activeStep index to activeStep if provided.
103
+ // Set activeStepIndex to activeStep if provided.
105
104
  // This happens when focus is updated by user using arrow keys or clicking a progress step.
106
105
  // When component re-renders, active step is not passed from renderedCallback or handleSlotChange
107
106
  // In this scenario, use the privateActiveStepIndex to maintain the activeStep.
108
107
  // privateActiveStepInde will have the active step before the re-render
109
- // In case of initial render, privateActiveStepIndex is null. Use privateCurrentStep as activeStepIndex for fallback.
108
+ // In case of initial render, privateActiveStepIndex is undefined. Use privateCurrentStep as activeStepIndex for fallback.
110
109
  // activeStep is needed to set active class and proper tabIndex for the progress step
111
-
112
110
  if (activeStep) {
113
111
  activeStepIndex = getStepIndex(steps, activeStep);
114
- } else if (this.privateActiveStepIndex) {
112
+ } else if (this.privateActiveStepIndex !== undefined) {
115
113
  activeStepIndex = this.privateActiveStepIndex;
116
114
  } else {
117
115
  activeStepIndex = getStepIndex(steps, this.privateCurrentStep);
@@ -87,7 +87,8 @@ export default class LightningProgressStep extends LightningElement {
87
87
  'slds-is-completed': !isPath && status === 'completed',
88
88
  'slds-has-error': !isPath && status === 'error',
89
89
  'slds-is-active':
90
- isActive === true || (type === 'base' && status === 'current'),
90
+ (type !== 'base' && isActive === true) ||
91
+ (type === 'base' && status === 'current'),
91
92
  'slds-path__item': isPath,
92
93
  'slds-is-complete': isPath && status === 'completed',
93
94
  'slds-is-current':
@@ -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,14 @@ 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
+ return !String(cmp?.template?.constructor).includes(
222
+ 'function SyntheticShadowRoot'
223
+ );
224
+ }
@@ -1,295 +0,0 @@
1
- import { guid } from './guid';
2
- import { smartSetAttribute } from './smartSetAttribute';
3
-
4
- const CONTENT_SEPARATOR = '\n';
5
-
6
- /**
7
- <template>
8
- <span lwc:dom="manual" class="visually-hidden"></span>
9
- <input>
10
- </template>
11
-
12
- class Foo extends LightningElement {
13
- constructor() {
14
- super();
15
- this.ariaObserver = new ContentMutation(this);
16
- }
17
-
18
- connectedCallback() {
19
- if (!this.ariaObserver) {
20
- this.ariaObserver = new ContentMutation(this);
21
- }
22
- }
23
-
24
- disconnectedCallback() {
25
- if (this.ariaObserver) {
26
- this.ariaObserver.disconnect();
27
- this.ariaObserver = undefined;
28
- }
29
- }
30
-
31
- @track ariaLabeledbyValue = '';
32
-
33
- @api
34
- get ariaLabeledby() {
35
- return this.ariaLabeledbyValue; // whatever they set, is what they get back.
36
- }
37
- set ariaLabeledby(refs) {
38
- this.ariaLabeledbyValue = refs;
39
- this.ariaObserver.link('input', 'aria-labeledby', refs, 'span.visually-hidden');
40
- }
41
-
42
- renderedCallback() {
43
- this.ariaObserver.sync();
44
- }
45
- }
46
- **/
47
-
48
- function getAttr(elm, attr) {
49
- if (elm.tagName.match(/lightning/i)) {
50
- return elm[attr];
51
- }
52
- return elm.getAttribute(attr);
53
- }
54
-
55
- function extractElements(root, selector) {
56
- if (typeof selector !== 'string' || selector === '') {
57
- return [];
58
- }
59
- return [].slice.call(root.querySelectorAll(selector));
60
- }
61
-
62
- function extractContent(elements) {
63
- return elements
64
- .map((element) => element.textContent)
65
- .filter((text) => text.length)
66
- .join(CONTENT_SEPARATOR);
67
- }
68
-
69
- function splitIds(ids) {
70
- return (ids + '').trim().split(/\s+/);
71
- }
72
-
73
- function hashIds(ids) {
74
- return (ids + '')
75
- .trim()
76
- .split(/\s+/)
77
- .reduce((r, v) => {
78
- r[v] = 1;
79
- return r;
80
- }, {});
81
- }
82
-
83
- // this method should check each individual id from computedIds
84
- // against the existing value of the attrName on elm, and dupe
85
- // them, and add the new ones.
86
- function addAriaRefWhenNeeded(elm, attrName, computedIds) {
87
- const newIds = splitIds(computedIds);
88
- const oldIds = getAttr(elm, attrName) || '';
89
- const oldIdsHash = hashIds(oldIds);
90
- const suffix = [];
91
- for (let i = 0; i < newIds.length; i += 1) {
92
- if (!oldIdsHash[newIds[i]]) {
93
- suffix.push(newIds[i]);
94
- }
95
- }
96
-
97
- if (suffix.length !== 0) {
98
- smartSetAttribute(
99
- elm,
100
- attrName,
101
- oldIds + (oldIds.length === 0 ? '' : ' ') + suffix.join(' ')
102
- );
103
- }
104
- }
105
-
106
- // this method should check each individual id from computedIds
107
- // against the existing value of the attrName on elm, and remove
108
- // them when possible in preparation for some new values.
109
- function removeAriaRefWhenPossible(elm, attrName, computedIds) {
110
- const newIds = splitIds(computedIds);
111
- const oldIds = getAttr(elm, attrName) || '';
112
- const oldIdsHash = hashIds(oldIds);
113
- const newValues = [];
114
- for (let i = 0; i < newIds.length; i += 1) {
115
- if (!oldIdsHash[newIds[i]]) {
116
- newValues.push(newIds[i]);
117
- }
118
- }
119
- smartSetAttribute(elm, attrName, newValues.join(' '));
120
- }
121
-
122
- export class ContentMutation {
123
- constructor(component) {
124
- this.component = component;
125
- this.template = component.template;
126
- this.isNative = this.template.constructor
127
- .toString()
128
- .match(/\[native code\]/);
129
- this.state = {};
130
- this.liveIds = {};
131
- this.guid = guid();
132
- }
133
-
134
- connectLiveIdRef(refs, callback) {
135
- const selector = (refs + '')
136
- .trim()
137
- .split(/\s+/)
138
- .map((ref) => `[id*="${ref}"]`)
139
- .join(',');
140
- const liveId = { selector, callback };
141
- this.liveIds[refs] = liveId;
142
- }
143
-
144
- link(innerSelector, attrName, ids, placeholderContainerSelector) {
145
- let attrState = this.state[attrName];
146
- if (attrState) {
147
- // note: we don't support linking to a different innerSelector,
148
- // attrName, or placeholderContainerSelector
149
- if (!this.isNative) {
150
- const elm = this.template.querySelector(innerSelector);
151
- if (elm) {
152
- // removing the old ids if possible before setting the new ones
153
- removeAriaRefWhenPossible(elm, attrName, attrState.ids);
154
- }
155
- attrState.ids = ids;
156
- }
157
- } else {
158
- attrState = this.state[attrName] = {
159
- ids,
160
- innerSelector,
161
- placeholderContainerSelector,
162
- };
163
- }
164
- if (this.isNative) {
165
- attrState.outerSelector = (ids + '')
166
- .trim()
167
- .split(/\s+/)
168
- .map((ref) => `#${ref}`)
169
- .join(',');
170
- attrState.placeholder = document.createElement('span');
171
- attrState.placeholder.id = `auto-link-${attrName}-${this.guid}`;
172
- }
173
- if (this.component.isConnected) {
174
- this.privateUpdate(attrName);
175
- }
176
- }
177
-
178
- sync() {
179
- if (!this.component.isConnected) {
180
- throw new Error(
181
- `Invalid sync invocation. It can only be invoked during renderedCallback().`
182
- );
183
- }
184
- if (this.isNative && !this.mo) {
185
- this.privateConnect();
186
- }
187
- for (const attrName in this.state) {
188
- if (Object.prototype.hasOwnProperty.call(this.state, attrName)) {
189
- this.privateUpdate(attrName);
190
- }
191
- }
192
-
193
- // live idRef feature is a no-op in native
194
- if (!this.isNative) {
195
- this.privateUpdateLiveIds();
196
- }
197
- }
198
-
199
- privateExtractIds(elements) {
200
- return elements
201
- .map((el) => {
202
- return el.getAttribute('id');
203
- })
204
- .join(' ');
205
- }
206
-
207
- privateUpdateLiveIds() {
208
- const root = this.template.host.getRootNode();
209
-
210
- // if not connected do nothing
211
- if (!root) {
212
- return;
213
- }
214
- for (const liveId in this.liveIds) {
215
- if (Object.prototype.hasOwnProperty.call(this.liveIds, liveId)) {
216
- const thisId = this.liveIds[liveId];
217
- if (!thisId.elements) {
218
- // element refs are cached
219
- thisId.elements = Array.prototype.slice.call(
220
- root.querySelectorAll(thisId.selector)
221
- );
222
- }
223
- const newIds = this.privateExtractIds(thisId.elements);
224
- // only fire calback if the value changed
225
- if (newIds !== thisId.ids) {
226
- thisId.callback(newIds);
227
- thisId.ids = newIds;
228
- }
229
- }
230
- }
231
- }
232
-
233
- privateUpdate(attrName) {
234
- const { innerSelector } = this.state[attrName];
235
- const elm = this.template.querySelector(innerSelector);
236
- if (!elm) {
237
- return; // nothing to update
238
- }
239
- let computedIds;
240
- if (this.isNative) {
241
- const {
242
- outerSelector,
243
- content,
244
- placeholder,
245
- placeholderContainerSelector,
246
- } = this.state[attrName];
247
- const newContent = extractContent(
248
- extractElements(this.root, outerSelector)
249
- );
250
- if (content !== newContent) {
251
- this.state[attrName].content = placeholder.textContent =
252
- newContent;
253
- }
254
- if (!placeholder.parentNode) {
255
- // inserting the placeholder once
256
- const container = this.template.querySelector(
257
- placeholderContainerSelector
258
- );
259
- if (container) {
260
- container.appendChild(placeholder);
261
- }
262
- }
263
- computedIds = placeholder.id;
264
- } else {
265
- computedIds = this.state[attrName].ids;
266
- }
267
- addAriaRefWhenNeeded(elm, attrName, computedIds);
268
- }
269
-
270
- privateConnect() {
271
- // caching root ref
272
- this.root = this.template.host.getRootNode();
273
- // creating the observer once
274
- this.mo = new MutationObserver(() => {
275
- if (!this.component.isConnected) {
276
- return; // do nothing when the template is not connected
277
- }
278
- this.sync();
279
- });
280
- this.mo.observe(this.root, {
281
- characterData: true,
282
- childList: true,
283
- subtree: true,
284
- });
285
- }
286
-
287
- disconnect() {
288
- // MutationObservers must be disconnected manually when using @lwc/synthetic-shadow
289
- // https://lwc.dev/guide/composition#:~:text=memory%20leak
290
- if (this.mo) {
291
- this.mo.disconnect();
292
- this.mo = undefined;
293
- }
294
- }
295
- }