@salesforcedevs/dx-components 1.3.217 → 1.3.219
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforcedevs/dx-components",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.219",
|
|
4
4
|
"description": "DX Lightning web components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"engines": {
|
|
@@ -44,5 +44,5 @@
|
|
|
44
44
|
"volta": {
|
|
45
45
|
"node": "16.19.1"
|
|
46
46
|
},
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "c0f8f19b7bfc14f9a6ca02a2dc328f726d72270a"
|
|
48
48
|
}
|
|
@@ -164,12 +164,13 @@ export default class ScrollManager extends LightningElement {
|
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
saveScroll = throttle(100, () => {
|
|
167
|
+
const scrollingElement = document.scrollingElement || document.body;
|
|
167
168
|
window.history.replaceState(
|
|
168
169
|
{
|
|
169
170
|
...window.history.state,
|
|
170
171
|
scroll: {
|
|
171
|
-
value:
|
|
172
|
-
docSize:
|
|
172
|
+
value: scrollingElement.scrollTop,
|
|
173
|
+
docSize: scrollingElement.scrollHeight
|
|
173
174
|
}
|
|
174
175
|
},
|
|
175
176
|
"",
|
|
@@ -422,11 +422,17 @@ a.CoveoResultLink,
|
|
|
422
422
|
width: fit-content;
|
|
423
423
|
}
|
|
424
424
|
|
|
425
|
-
.dx-
|
|
426
|
-
display:
|
|
425
|
+
.dx-result-info {
|
|
426
|
+
display: flex;
|
|
427
|
+
gap: 12px;
|
|
427
428
|
margin-bottom: var(--dx-g-spacing-smd);
|
|
428
429
|
}
|
|
429
430
|
|
|
431
|
+
.breadcrumb {
|
|
432
|
+
color: #555;
|
|
433
|
+
font-size: var(--dx-g-text-xs);
|
|
434
|
+
}
|
|
435
|
+
|
|
430
436
|
.no-results {
|
|
431
437
|
display: flex;
|
|
432
438
|
justify-content: center;
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
CONTENT_TYPE_ICONS
|
|
7
7
|
} from "dxConstants/contentTypes";
|
|
8
8
|
import { getContentTypeColorVariables } from "dxUtils/contentTypes";
|
|
9
|
+
import { pollUntil } from "dxUtils/async";
|
|
9
10
|
|
|
10
11
|
interface CoveoSearch {
|
|
11
12
|
state: typeof CoveoSDK.state;
|
|
@@ -40,16 +41,27 @@ const resultsTemplatesInnerHtml = `
|
|
|
40
41
|
<script
|
|
41
42
|
id="myDocumentResultTemplate"
|
|
42
43
|
class="result-template"
|
|
43
|
-
type="text/
|
|
44
|
+
type="text/underscore"
|
|
44
45
|
data-field-publicurl=""
|
|
45
46
|
>
|
|
46
47
|
<div class="dx-result">
|
|
47
|
-
<
|
|
48
|
+
<div class="dx-result-info">
|
|
49
|
+
<span class="CoveoFieldValue" data-field="@content_type" data-helper="badge" data-html-value="true"></span>
|
|
50
|
+
<% if (!raw.breadcrumbs && !raw.metabreadcrumbs) { %>
|
|
51
|
+
<span class="CoveoFieldValue" data-field="@uri" data-helper="uriBreadcrumbs" data-html-value="true"></span>
|
|
52
|
+
<% } else { %>
|
|
53
|
+
<% if (raw.uri.includes('/references/')) { %>
|
|
54
|
+
<span class="CoveoFieldValue" data-field="@metabreadcrumbs" data-helper="metabreadcrumbs" data-html-value="true"></span>
|
|
55
|
+
<% } else { %>
|
|
56
|
+
<span class="CoveoFieldValue" data-field="@breadcrumbs" data-helper="breadcrumbs" data-html-value="true"></span>
|
|
57
|
+
<% } %>
|
|
58
|
+
<% } %>
|
|
59
|
+
</div>
|
|
48
60
|
<p class="dx-result-title">
|
|
49
|
-
<
|
|
61
|
+
<span
|
|
50
62
|
class="CoveoResultLink"
|
|
51
|
-
data-field="@
|
|
52
|
-
></
|
|
63
|
+
data-field="@uri"
|
|
64
|
+
></span>
|
|
53
65
|
</p>
|
|
54
66
|
<p class="dx-result-excerpt CoveoExcerpt"></p>
|
|
55
67
|
</div>
|
|
@@ -57,10 +69,21 @@ const resultsTemplatesInnerHtml = `
|
|
|
57
69
|
<script
|
|
58
70
|
id="myDefaultResultTemplate"
|
|
59
71
|
class="result-template"
|
|
60
|
-
type="text/
|
|
72
|
+
type="text/underscore"
|
|
61
73
|
>
|
|
62
74
|
<div class="dx-result">
|
|
63
|
-
<
|
|
75
|
+
<div class="dx-result-info">
|
|
76
|
+
<span class="CoveoFieldValue" data-field="@content_type" data-helper="badge" data-html-value="true"></span>
|
|
77
|
+
<% if (!raw.breadcrumbs && !raw.metabreadcrumbs) { %>
|
|
78
|
+
<span class="CoveoFieldValue" data-field="@uri" data-helper="uriBreadcrumbs" data-html-value="true"></span>
|
|
79
|
+
<% } else { %>
|
|
80
|
+
<% if (raw.uri.includes('/references/')) { %>
|
|
81
|
+
<span class="CoveoFieldValue" data-field="@metabreadcrumbs" data-helper="metabreadcrumbs" data-html-value="true"></span>
|
|
82
|
+
<% } else { %>
|
|
83
|
+
<span class="CoveoFieldValue" data-field="@breadcrumbs" data-helper="breadcrumbs" data-html-value="true"></span>
|
|
84
|
+
<% } %>
|
|
85
|
+
<% } %>
|
|
86
|
+
</div>
|
|
64
87
|
<p class="dx-result-title">
|
|
65
88
|
<a class="CoveoResultLink"></a>
|
|
66
89
|
</p>
|
|
@@ -69,6 +92,14 @@ const resultsTemplatesInnerHtml = `
|
|
|
69
92
|
</script>
|
|
70
93
|
`;
|
|
71
94
|
|
|
95
|
+
const isInternalDomain = (domain: string) =>
|
|
96
|
+
domain === "developer.salesforce.com" ||
|
|
97
|
+
domain === "developer-website-s.herokuapp.com";
|
|
98
|
+
|
|
99
|
+
const isTrailheadDomain = (domain: string) =>
|
|
100
|
+
domain === "trailhead.salesforce.com" ||
|
|
101
|
+
domain === "dev.trailhead.salesforce.com";
|
|
102
|
+
|
|
72
103
|
const buildTemplateHelperBadge = (value: keyof typeof CONTENT_TYPE_LABELS) => {
|
|
73
104
|
const style = getContentTypeColorVariables(value);
|
|
74
105
|
const label = CONTENT_TYPE_LABELS[value];
|
|
@@ -88,6 +119,107 @@ const buildTemplateHelperBadge = (value: keyof typeof CONTENT_TYPE_LABELS) => {
|
|
|
88
119
|
`;
|
|
89
120
|
};
|
|
90
121
|
|
|
122
|
+
const processParts = (parts: string[], internalFlag = false) => {
|
|
123
|
+
// filter /docs/ breadcrumb item from internal domains
|
|
124
|
+
const filterFn = internalFlag
|
|
125
|
+
? (part: string) => part !== "docs"
|
|
126
|
+
: (part: string) => part;
|
|
127
|
+
|
|
128
|
+
return parts.filter(filterFn).map((part) => {
|
|
129
|
+
// Remove special characters & .htm/.xml extension
|
|
130
|
+
part = part
|
|
131
|
+
.replace(/_/g, " ")
|
|
132
|
+
.replace(/-/g, " ")
|
|
133
|
+
.replace(/.html*/g, " ")
|
|
134
|
+
.replace(/.xml/g, " ")
|
|
135
|
+
.replace(/b2c/g, "B2C");
|
|
136
|
+
|
|
137
|
+
// Capitalize first letter of each word
|
|
138
|
+
part = part.replace(/\w\S*/g, (w) => {
|
|
139
|
+
return w.replace(/^\w/, (c) => c.toUpperCase());
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
return `<span class="breadcrumb-item">${decodeURI(part)}</span>`;
|
|
143
|
+
});
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const buildTemplateHelperUriBreadcrumbs = (value: string) => {
|
|
147
|
+
const url = new URL(value);
|
|
148
|
+
|
|
149
|
+
// exclude youtube links from breadcrumbs
|
|
150
|
+
const hostnamePattern = /^((www\.)?(youtube\.com|youtu\.be))$/;
|
|
151
|
+
|
|
152
|
+
// we don't want to show atlas docs because the url structure is mad ugly
|
|
153
|
+
if (hostnamePattern.test(url.hostname) || url.pathname.includes("atlas.")) {
|
|
154
|
+
return "";
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
let parts = url.pathname.split("/").filter((part) => part !== "");
|
|
158
|
+
|
|
159
|
+
// Remove language prefix from trailhead URLs
|
|
160
|
+
if (isTrailheadDomain(url.hostname)) {
|
|
161
|
+
parts = parts
|
|
162
|
+
.slice(1)
|
|
163
|
+
.filter((part) => part !== "content" && part !== "learn");
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const breadcrumbs = processParts(parts, isInternalDomain(url.hostname));
|
|
167
|
+
|
|
168
|
+
if (!isInternalDomain(url.hostname)) {
|
|
169
|
+
// Remove the first breadcrumb item if it's an internal domain (i.e drop developer.salesforce.com from developer.salesforce.com / B2C Commerce / Open Commerce API / Filtering)
|
|
170
|
+
breadcrumbs.unshift(
|
|
171
|
+
`<span class="breadcrumb-item">${url.hostname}</span>`
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
return `
|
|
175
|
+
<span class="breadcrumb">
|
|
176
|
+
${breadcrumbs.join(" / ")}
|
|
177
|
+
</span>
|
|
178
|
+
`;
|
|
179
|
+
} else if (breadcrumbs.length === 1) {
|
|
180
|
+
// Hide breadcrumbs if there is only one breadcrumb item
|
|
181
|
+
return "";
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// remove the last breadcrumb item (the search result title makes it redundant)
|
|
185
|
+
breadcrumbs.pop();
|
|
186
|
+
|
|
187
|
+
return `<span class="breadcrumb">/ ${breadcrumbs.join(" / ")} /</span>`;
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const buildTemplateHelperBreadcrumbs = (value: string) => {
|
|
191
|
+
const parts = value.split("/").filter((part) => part !== "");
|
|
192
|
+
|
|
193
|
+
// Don't show breadcrumbs if there's only one part
|
|
194
|
+
if (parts.length === 1) {
|
|
195
|
+
return "";
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const breadcrumbs = processParts(parts);
|
|
199
|
+
|
|
200
|
+
// remove last breadcrumb item
|
|
201
|
+
breadcrumbs.pop();
|
|
202
|
+
|
|
203
|
+
return `
|
|
204
|
+
<span class="breadcrumb">/ ${breadcrumbs.join(" / ")} /</span>
|
|
205
|
+
`;
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
const buildTemplateHelperMetaBreadcrumbs = (value: string) => {
|
|
209
|
+
const parts = value.split("/").filter((part) => part !== "");
|
|
210
|
+
|
|
211
|
+
// Don't show breadcrumbs if there's only one part
|
|
212
|
+
if (parts.length === 1) {
|
|
213
|
+
return "";
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const breadcrumbs = processParts(parts);
|
|
217
|
+
|
|
218
|
+
return `
|
|
219
|
+
<span class="breadcrumb">/ ${breadcrumbs.join(" / ")}</span>
|
|
220
|
+
`;
|
|
221
|
+
};
|
|
222
|
+
|
|
91
223
|
// @ts-ignore Dark Magic (TM) we are overriding the 'title' field with a custom getter. We should really stop doing this.
|
|
92
224
|
export default class SearchResults extends LightningElement {
|
|
93
225
|
@api coveoOrganizationId!: string;
|
|
@@ -139,9 +271,12 @@ export default class SearchResults extends LightningElement {
|
|
|
139
271
|
BreadcrumbManager.clearBreadcrumbs();
|
|
140
272
|
}
|
|
141
273
|
|
|
142
|
-
private currentPage: number =
|
|
274
|
+
private currentPage: number = 25;
|
|
143
275
|
private totalPages: number = 1;
|
|
144
276
|
|
|
277
|
+
private originalBreadcrumbs: string[] = [];
|
|
278
|
+
private initialWindowWidth = window.innerWidth;
|
|
279
|
+
|
|
145
280
|
private goToPage(e: CustomEvent) {
|
|
146
281
|
const page = e.detail;
|
|
147
282
|
const Pager = Coveo.get(
|
|
@@ -179,6 +314,7 @@ export default class SearchResults extends LightningElement {
|
|
|
179
314
|
if (Coveo.state(this.root!, "q") === "") {
|
|
180
315
|
Coveo.state(this.root!, "sort", "date descending");
|
|
181
316
|
}
|
|
317
|
+
|
|
182
318
|
this.isInitialized = true;
|
|
183
319
|
}
|
|
184
320
|
);
|
|
@@ -204,6 +340,110 @@ export default class SearchResults extends LightningElement {
|
|
|
204
340
|
|
|
205
341
|
this.trackSearchResults(event, this.query, this.totalResults);
|
|
206
342
|
});
|
|
343
|
+
|
|
344
|
+
Coveo.$$(root).on(Coveo.QueryEvents.deferredQuerySuccess, async () => {
|
|
345
|
+
// wait specified time to ensure breadcrumbs are rendered before processing them
|
|
346
|
+
await pollUntil(
|
|
347
|
+
() => {
|
|
348
|
+
const coveoResults =
|
|
349
|
+
this.root!.querySelector(".CoveoResult");
|
|
350
|
+
|
|
351
|
+
return Boolean(coveoResults);
|
|
352
|
+
},
|
|
353
|
+
20,
|
|
354
|
+
1000
|
|
355
|
+
);
|
|
356
|
+
|
|
357
|
+
this.processBreadcrumbs(this.root!);
|
|
358
|
+
|
|
359
|
+
window.onresize = () => this.processBreadcrumbs(root);
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// Checks if text is wrapping by comparing it with an element's text that doesn't wrap
|
|
364
|
+
private isTextWrapping = (
|
|
365
|
+
elementOne: HTMLElement,
|
|
366
|
+
elementTwo: HTMLElement
|
|
367
|
+
) => elementOne.offsetHeight > elementTwo.offsetHeight;
|
|
368
|
+
|
|
369
|
+
private truncateBreadcrumbText = (breadcrumbItems: HTMLElement[]) => {
|
|
370
|
+
breadcrumbItems.forEach((breadcrumbItem: HTMLElement) => {
|
|
371
|
+
const breadcrumbItemText = breadcrumbItem.textContent!;
|
|
372
|
+
if (breadcrumbItemText.length > 30) {
|
|
373
|
+
breadcrumbItem.textContent = `${breadcrumbItemText.substring(
|
|
374
|
+
0,
|
|
375
|
+
30
|
|
376
|
+
)}...`;
|
|
377
|
+
}
|
|
378
|
+
});
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
private addBreadcrumbEllipsis = (
|
|
382
|
+
breadcrumbItems: HTMLElement[],
|
|
383
|
+
breadcrumb: HTMLElement
|
|
384
|
+
) => {
|
|
385
|
+
for (let i = 1; i < breadcrumbItems.length; i++) {
|
|
386
|
+
if (this.isTextWrapping(breadcrumb, breadcrumbItems[0])) {
|
|
387
|
+
breadcrumbItems[i].textContent = "...";
|
|
388
|
+
} else {
|
|
389
|
+
break; // Exit the loop if the breadcrumb is no longer overflowing
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
private formatBreadcrumbs = (breadcrumbs: HTMLElement[]) => {
|
|
395
|
+
breadcrumbs?.forEach((breadcrumb: HTMLElement) => {
|
|
396
|
+
// Get all breadcrumb items that are separated by '/'
|
|
397
|
+
const breadcrumbItems: any =
|
|
398
|
+
breadcrumb.querySelectorAll(".breadcrumb-item");
|
|
399
|
+
|
|
400
|
+
// Check if the breadcrumb is overflowing by comparing it's height to the height of the first breadcrumb item
|
|
401
|
+
if (this.isTextWrapping(breadcrumb, breadcrumbItems[0])) {
|
|
402
|
+
// it is overflowing, so we need to truncate long titles to 30 characters
|
|
403
|
+
this.truncateBreadcrumbText(breadcrumbItems);
|
|
404
|
+
|
|
405
|
+
// Iteratively check if the breadcrumb is still overflowing and replace text with '...' starting from the second breadcrumb item
|
|
406
|
+
this.addBreadcrumbEllipsis(breadcrumbItems, breadcrumb);
|
|
407
|
+
|
|
408
|
+
// After processing all breadcrumb items, if it's still overflowing, hide the breadcrumb element
|
|
409
|
+
if (this.isTextWrapping(breadcrumb, breadcrumbItems[0])) {
|
|
410
|
+
breadcrumb.style.display = "none";
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
private restoreBreadcrumbs = (breadcrumbs: HTMLElement[]) => {
|
|
417
|
+
breadcrumbs.forEach((breadcrumb: HTMLElement, index: number) => {
|
|
418
|
+
// eslint-disable-next-line @lwc/lwc/no-inner-html
|
|
419
|
+
breadcrumb.innerHTML = this.originalBreadcrumbs[index];
|
|
420
|
+
});
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
private windowSizeIncreased = () =>
|
|
424
|
+
window.innerWidth > this.initialWindowWidth;
|
|
425
|
+
|
|
426
|
+
private processBreadcrumbs(root: HTMLElement) {
|
|
427
|
+
// Get all breadcrumbs from search results
|
|
428
|
+
const breadcrumbs = Array.from(
|
|
429
|
+
root.querySelectorAll(".breadcrumb")
|
|
430
|
+
) as HTMLElement[];
|
|
431
|
+
|
|
432
|
+
if (this.originalBreadcrumbs.length === 0) {
|
|
433
|
+
this.originalBreadcrumbs = breadcrumbs.map(
|
|
434
|
+
(breadcrumb) => breadcrumb.innerHTML
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
if (this.windowSizeIncreased()) {
|
|
439
|
+
/*
|
|
440
|
+
Reset the breadcrumbs to their original state and process them again.
|
|
441
|
+
The additional space means we can replace ellipsis with full text.
|
|
442
|
+
*/
|
|
443
|
+
this.restoreBreadcrumbs(breadcrumbs);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
this.formatBreadcrumbs(breadcrumbs);
|
|
207
447
|
}
|
|
208
448
|
|
|
209
449
|
private initializeCoveo() {
|
|
@@ -212,6 +452,7 @@ export default class SearchResults extends LightningElement {
|
|
|
212
452
|
const resultsList = this.template.querySelector(".CoveoResultList");
|
|
213
453
|
|
|
214
454
|
if (resultsList) {
|
|
455
|
+
// eslint-disable-next-line @lwc/lwc/no-inner-html
|
|
215
456
|
resultsList.innerHTML = resultsTemplatesInnerHtml;
|
|
216
457
|
}
|
|
217
458
|
|
|
@@ -227,6 +468,21 @@ export default class SearchResults extends LightningElement {
|
|
|
227
468
|
buildTemplateHelperBadge
|
|
228
469
|
);
|
|
229
470
|
|
|
471
|
+
Coveo.TemplateHelpers.registerTemplateHelper(
|
|
472
|
+
"breadcrumbs",
|
|
473
|
+
buildTemplateHelperBreadcrumbs
|
|
474
|
+
);
|
|
475
|
+
|
|
476
|
+
Coveo.TemplateHelpers.registerTemplateHelper(
|
|
477
|
+
"metabreadcrumbs",
|
|
478
|
+
buildTemplateHelperMetaBreadcrumbs
|
|
479
|
+
);
|
|
480
|
+
|
|
481
|
+
Coveo.TemplateHelpers.registerTemplateHelper(
|
|
482
|
+
"uriBreadcrumbs",
|
|
483
|
+
buildTemplateHelperUriBreadcrumbs
|
|
484
|
+
);
|
|
485
|
+
|
|
230
486
|
Coveo.init(this.root);
|
|
231
487
|
}
|
|
232
488
|
|
|
@@ -235,6 +491,7 @@ export default class SearchResults extends LightningElement {
|
|
|
235
491
|
if (Object.prototype.hasOwnProperty.call(window, "Coveo")) {
|
|
236
492
|
this.initializeCoveo();
|
|
237
493
|
} else {
|
|
494
|
+
// eslint-disable-next-line @lwc/lwc/no-document-query
|
|
238
495
|
const script = document.querySelector("script.coveo-script");
|
|
239
496
|
script?.addEventListener("load", () => {
|
|
240
497
|
this.initializeCoveo();
|
|
@@ -9,6 +9,7 @@ import cx from "classnames";
|
|
|
9
9
|
export default class StepSequence extends LightningElement {
|
|
10
10
|
@api animateTransitions = false;
|
|
11
11
|
@api communicateStepChanges = false;
|
|
12
|
+
@api containerScrollToId = "";
|
|
12
13
|
@api forceInitiallyVisible = false;
|
|
13
14
|
@api initialStepIndex: string | undefined;
|
|
14
15
|
@api optimizePositionAfterAnimation = false;
|
|
@@ -39,15 +40,9 @@ export default class StepSequence extends LightningElement {
|
|
|
39
40
|
|
|
40
41
|
if (this.useHistory) {
|
|
41
42
|
this.defaultScrollRestorationValue = history.scrollRestoration;
|
|
42
|
-
history.scrollRestoration = "manual";
|
|
43
|
-
history.replaceState(
|
|
44
|
-
{
|
|
45
|
-
...window.history.state,
|
|
46
|
-
currentStepIndex: this.currentStepIndex
|
|
47
|
-
},
|
|
48
|
-
""
|
|
49
|
-
);
|
|
43
|
+
history.scrollRestoration = "manual"; // Step component must override scroll behavior to work properly with history and maintain scrollTo behavior of component
|
|
50
44
|
window.addEventListener("popstate", this.handleHistoryPopstate);
|
|
45
|
+
window.addEventListener("hashchange", this.handleHashChange);
|
|
51
46
|
}
|
|
52
47
|
|
|
53
48
|
if (this.sessionStorageId) {
|
|
@@ -87,6 +82,7 @@ export default class StepSequence extends LightningElement {
|
|
|
87
82
|
|
|
88
83
|
disconnectedCallback() {
|
|
89
84
|
window.removeEventListener("popstate", this.handleHistoryPopstate);
|
|
85
|
+
window.removeEventListener("hashchange", this.handleHashChange);
|
|
90
86
|
this.removeEventListener("transitionend", this.handleTransitionEnd);
|
|
91
87
|
history.scrollRestoration = this.defaultScrollRestorationValue;
|
|
92
88
|
}
|
|
@@ -166,6 +162,17 @@ export default class StepSequence extends LightningElement {
|
|
|
166
162
|
}
|
|
167
163
|
|
|
168
164
|
if (this.useHistory && updateHistory) {
|
|
165
|
+
if (typeof history.state?.currentStepIndex !== "number") {
|
|
166
|
+
// This is a "new" interaction with the step component, so we store the current
|
|
167
|
+
// component state in history so that going back from the next step works right
|
|
168
|
+
history.pushState(
|
|
169
|
+
{
|
|
170
|
+
currentStepIndex: this.currentStepIndex
|
|
171
|
+
},
|
|
172
|
+
"",
|
|
173
|
+
this.containerScrollToId // update browser hash for correct "feel" to in-page navigation
|
|
174
|
+
);
|
|
175
|
+
}
|
|
169
176
|
history.pushState(
|
|
170
177
|
{
|
|
171
178
|
currentStepIndex: nextStepIndex
|
|
@@ -247,9 +254,34 @@ export default class StepSequence extends LightningElement {
|
|
|
247
254
|
}
|
|
248
255
|
|
|
249
256
|
handleHistoryPopstate = ({ state }: PopStateEvent) => {
|
|
250
|
-
if (
|
|
251
|
-
|
|
252
|
-
|
|
257
|
+
if (
|
|
258
|
+
typeof state?.currentStepIndex !== "number" ||
|
|
259
|
+
state.currentStepIndex === this.currentStepIndex
|
|
260
|
+
) {
|
|
261
|
+
// This history item is not a step change, so bail early.
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
this.remeasureSteps();
|
|
266
|
+
this.changeActiveStep(state.currentStepIndex, false);
|
|
267
|
+
this.scrollToStepTop();
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
handleHashChange = ({ newURL }: HashChangeEvent) => {
|
|
271
|
+
const newHash = new URL(newURL).hash;
|
|
272
|
+
const oldScrollValue = history.state?.scroll?.value;
|
|
273
|
+
|
|
274
|
+
if (typeof oldScrollValue === "number") {
|
|
275
|
+
window.scrollTo({
|
|
276
|
+
top: oldScrollValue
|
|
277
|
+
});
|
|
278
|
+
} else if (newHash) {
|
|
279
|
+
document.querySelector(newHash)?.scrollIntoView();
|
|
280
|
+
} else {
|
|
281
|
+
// No hash and no old scroll value means this was the initial history item
|
|
282
|
+
window.scrollTo({
|
|
283
|
+
top: 0
|
|
284
|
+
});
|
|
253
285
|
}
|
|
254
286
|
};
|
|
255
287
|
|