@salesforcedevs/dx-components 1.28.7-alpha.8 → 1.29.0-ssgalpha1
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/lwc.config.json +0 -1
- package/package.json +2 -3
- package/src/modules/dx/searchResults/searchResults.css +2 -52
- package/src/modules/dx/searchResults/searchResults.html +91 -84
- package/src/modules/dx/searchResults/searchResults.ts +478 -157
- package/src/modules/dx/sidebar/sidebar.html +4 -0
- package/src/modules/dx/sidebar/sidebar.ts +7 -7
- package/src/modules/dx/sidebarSearch/sidebarSearch.ts +347 -59
- package/src/modules/dx/sidebarSearchResult/sidebarSearchResult.ts +4 -4
- package/src/modules/dxUtils/shiki/shiki.ts +4 -2
- package/src/modules/dxUtils/shikiGrammars/shikiGrammars.ts +151 -41
- package/LICENSE +0 -12
- package/src/modules/dxUtils/dataCloudSearch/dataCloudSearch.ts +0 -100
|
@@ -48,6 +48,10 @@
|
|
|
48
48
|
<dx-sidebar-search
|
|
49
49
|
onchange={onSearchChange}
|
|
50
50
|
onloading={onSearchLoading}
|
|
51
|
+
coveo-organization-id={coveoOrganizationId}
|
|
52
|
+
coveo-public-access-token={coveoPublicAccessToken}
|
|
53
|
+
coveo-search-hub={coveoSearchHub}
|
|
54
|
+
coveo-advanced-query-config={coveoAdvancedQueryConfig}
|
|
51
55
|
></dx-sidebar-search>
|
|
52
56
|
</div>
|
|
53
57
|
<slot name="version-picker"></slot>
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import cx from "classnames";
|
|
2
2
|
import { api, track } from "lwc";
|
|
3
3
|
import { TreeNode, SidebarSearchResult } from "typings/custom";
|
|
4
|
+
import { getSidebarSearchParams } from "dxUtils/coveo";
|
|
4
5
|
import { toJson } from "dxUtils/normalizers";
|
|
5
6
|
import SidebarSearch from "dx/sidebarSearch";
|
|
6
7
|
import { SidebarBase } from "dxBaseElements/sidebarBase";
|
|
7
8
|
|
|
8
9
|
const MOBILE_SIZE_MATCH = "768px";
|
|
9
10
|
|
|
10
|
-
const getSearchQueryParam = (): string | null =>
|
|
11
|
-
typeof window !== "undefined"
|
|
12
|
-
? new URLSearchParams(window.location.search).get("q")
|
|
13
|
-
: null;
|
|
14
|
-
|
|
15
11
|
export default class Sidebar extends SidebarBase {
|
|
12
|
+
@api coveoOrganizationId!: string;
|
|
13
|
+
@api coveoPublicAccessToken!: string;
|
|
14
|
+
@api coveoSearchHub!: string;
|
|
15
|
+
@api coveoAdvancedQueryConfig!: string;
|
|
16
16
|
@api header: string = "";
|
|
17
17
|
|
|
18
18
|
@api
|
|
@@ -130,7 +130,7 @@ export default class Sidebar extends SidebarBase {
|
|
|
130
130
|
constructor() {
|
|
131
131
|
super();
|
|
132
132
|
|
|
133
|
-
if (
|
|
133
|
+
if (getSidebarSearchParams()) {
|
|
134
134
|
this.isSearchLoading = true;
|
|
135
135
|
this.scrollToSelectedSearchResult = true;
|
|
136
136
|
}
|
|
@@ -175,7 +175,7 @@ export default class Sidebar extends SidebarBase {
|
|
|
175
175
|
this.isSearchLoading = e.detail;
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
-
private onSidebarSearchContentScroll(scrollEvent
|
|
178
|
+
private onSidebarSearchContentScroll(scrollEvent) {
|
|
179
179
|
if (this.isSearchLoading) {
|
|
180
180
|
return;
|
|
181
181
|
}
|
|
@@ -1,27 +1,75 @@
|
|
|
1
1
|
import { LightningElement, api } from "lwc";
|
|
2
2
|
import debounce from "debounce";
|
|
3
3
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
Result,
|
|
5
|
+
ResultList,
|
|
6
|
+
Unsubscribe,
|
|
7
|
+
ResultsPerPage,
|
|
8
|
+
SearchBox,
|
|
9
|
+
buildInteractiveResult,
|
|
10
|
+
buildResultList,
|
|
11
|
+
buildResultsPerPage,
|
|
12
|
+
buildSearchBox,
|
|
13
|
+
loadAdvancedSearchQueryActions,
|
|
14
|
+
SearchEngine,
|
|
15
|
+
SearchAppState,
|
|
16
|
+
loadQueryActions
|
|
17
|
+
} from "@coveo/headless";
|
|
18
|
+
import { buildSearchEngine, getSidebarSearchParams } from "dxUtils/coveo";
|
|
7
19
|
import { RecentSearches } from "dxUtils/recentSearches";
|
|
20
|
+
import { toJson } from "dxUtils/normalizers";
|
|
8
21
|
import {
|
|
9
22
|
Option,
|
|
10
23
|
PopoverRequestCloseType,
|
|
11
24
|
SidebarSearchResult
|
|
12
25
|
} from "typings/custom";
|
|
13
26
|
|
|
27
|
+
const RESULT_CLICK_LOCAL_STORAGE_KEY = "dx-sidebar-search-result-click";
|
|
28
|
+
export const SESSION_KEY = "dx-sidebar-search-state";
|
|
29
|
+
|
|
30
|
+
const DEFAULT_RESULT_COUNT = 20;
|
|
14
31
|
const SEARCH_DEBOUNCE_DELAY = 1200;
|
|
15
32
|
|
|
16
33
|
const UserRecentSearches = new RecentSearches();
|
|
17
34
|
|
|
18
|
-
const
|
|
19
|
-
|
|
35
|
+
const normalizeCoveoAdvancedQueryValue = (version: string): string =>
|
|
36
|
+
version?.split(".").join("\\.");
|
|
20
37
|
|
|
21
38
|
export default class SidebarSearch extends LightningElement {
|
|
39
|
+
@api coveoOrganizationId!: string;
|
|
40
|
+
@api coveoPublicAccessToken!: string;
|
|
41
|
+
@api coveoSearchHub!: string;
|
|
42
|
+
@api
|
|
43
|
+
get coveoAdvancedQueryConfig(): { [key: string]: any } {
|
|
44
|
+
return this._coveoAdvancedQueryConfig;
|
|
45
|
+
}
|
|
46
|
+
set coveoAdvancedQueryConfig(value) {
|
|
47
|
+
const jsonValue = toJson(value);
|
|
48
|
+
const hasChanged =
|
|
49
|
+
this._coveoAdvancedQueryConfig &&
|
|
50
|
+
Object.entries(jsonValue).some(
|
|
51
|
+
([key, val]: [string, any]) =>
|
|
52
|
+
this._coveoAdvancedQueryConfig[key] !== val
|
|
53
|
+
);
|
|
54
|
+
this._coveoAdvancedQueryConfig = jsonValue;
|
|
55
|
+
|
|
56
|
+
if (hasChanged && this.engine && this.value !== "") {
|
|
57
|
+
this.dispatchOnLoading(true);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (hasChanged && this.engine) {
|
|
61
|
+
// set advanced filters needs access to the latest coveoAdvancedQueryConfig
|
|
62
|
+
this.setAdvancedFilters(this.engine);
|
|
63
|
+
this.submitSearch(true);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
22
67
|
@api
|
|
23
68
|
public fetchMoreResults() {
|
|
24
|
-
|
|
69
|
+
if (this.resultList?.state?.moreResultsAvailable) {
|
|
70
|
+
this.fetchingMoreResults = true;
|
|
71
|
+
this.resultList.fetchMoreResults();
|
|
72
|
+
}
|
|
25
73
|
}
|
|
26
74
|
|
|
27
75
|
@api
|
|
@@ -37,87 +85,313 @@ export default class SidebarSearch extends LightningElement {
|
|
|
37
85
|
this.dropdownRequestedOpen = value;
|
|
38
86
|
}
|
|
39
87
|
|
|
88
|
+
private _coveoAdvancedQueryConfig!: { [key: string]: any };
|
|
40
89
|
private dropdownRequestedOpen: boolean = false;
|
|
41
90
|
private recentSearches: Option[] = [];
|
|
42
|
-
private
|
|
91
|
+
private unsubscribeFromResultList: Unsubscribe = () => {};
|
|
92
|
+
private resultList: ResultList | null = null;
|
|
93
|
+
private resultsPerPage: ResultsPerPage | null = null;
|
|
94
|
+
private preloadedState?: SearchAppState;
|
|
95
|
+
private searchBox: SearchBox | null = null;
|
|
96
|
+
private value?: string = "";
|
|
97
|
+
private engine: SearchEngine | null = null;
|
|
98
|
+
private fetchingMoreResults: boolean = false;
|
|
43
99
|
private didRender = false;
|
|
44
|
-
|
|
100
|
+
|
|
101
|
+
private get hasCorrectCoveoConfig(): boolean {
|
|
102
|
+
const coveoConfigurations = [
|
|
103
|
+
this.coveoOrganizationId,
|
|
104
|
+
this.coveoPublicAccessToken,
|
|
105
|
+
this.coveoSearchHub,
|
|
106
|
+
this.coveoAdvancedQueryConfig
|
|
107
|
+
];
|
|
108
|
+
|
|
109
|
+
return coveoConfigurations.every(
|
|
110
|
+
(val) =>
|
|
111
|
+
!!val && (typeof val === "string" || typeof val === "object")
|
|
112
|
+
);
|
|
113
|
+
}
|
|
45
114
|
|
|
46
115
|
private get isDropdownOpen() {
|
|
47
116
|
return (
|
|
48
117
|
this.dropdownRequestedOpen &&
|
|
49
|
-
this.recentSearches
|
|
118
|
+
this.recentSearches &&
|
|
119
|
+
this.recentSearches.length > 0 &&
|
|
50
120
|
!this.value
|
|
51
121
|
);
|
|
52
122
|
}
|
|
53
123
|
|
|
54
124
|
constructor() {
|
|
55
125
|
super();
|
|
126
|
+
|
|
56
127
|
this.updateRecentSearches();
|
|
57
|
-
this.value =
|
|
128
|
+
this.value = getSidebarSearchParams() || "";
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
disconnectedCallback() {
|
|
132
|
+
this.unsubscribeFromResultList();
|
|
58
133
|
}
|
|
59
134
|
|
|
60
135
|
renderedCallback() {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
136
|
+
// in prod some of the critical coveo configuration attributes seem to arrive later
|
|
137
|
+
// so I needed to put this coveo startup flow here where we can wait for them to arrive
|
|
138
|
+
|
|
139
|
+
if (this.hasCorrectCoveoConfig && !this.engine) {
|
|
140
|
+
this.initializeUserSession();
|
|
141
|
+
this.initializeCoveo();
|
|
142
|
+
} else if (!this.hasCorrectCoveoConfig) {
|
|
143
|
+
console.error(
|
|
144
|
+
"Incorrect coveo search configuration provided. All coveo configuration attributes must be defined.",
|
|
145
|
+
{
|
|
146
|
+
coveoOrganizationId: this.coveoOrganizationId,
|
|
147
|
+
coveoPublicAccessToken: this.coveoPublicAccessToken,
|
|
148
|
+
coveoSearchHub: this.coveoSearchHub,
|
|
149
|
+
coveoAdvancedQueryConfig: this.coveoAdvancedQueryConfig
|
|
67
150
|
}
|
|
68
|
-
|
|
69
|
-
this.fetchDataCloudSearch();
|
|
70
|
-
} else {
|
|
71
|
-
this.dispatchOnLoading(false);
|
|
72
|
-
}
|
|
151
|
+
);
|
|
73
152
|
}
|
|
153
|
+
|
|
154
|
+
// If this is the first render and there is a search value, trigger
|
|
155
|
+
// term highlighting
|
|
74
156
|
if (!this.didRender && this.value) {
|
|
75
157
|
this.dispatchHighlightedTermChange();
|
|
76
158
|
}
|
|
159
|
+
|
|
77
160
|
this.didRender = true;
|
|
78
161
|
}
|
|
79
162
|
|
|
80
|
-
private
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
163
|
+
private initializeUserSession() {
|
|
164
|
+
const stringified = window.sessionStorage.getItem(SESSION_KEY);
|
|
165
|
+
|
|
166
|
+
if (!stringified) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
try {
|
|
171
|
+
const json = JSON.parse(stringified);
|
|
172
|
+
|
|
173
|
+
const hasSameConfig = Object.entries(
|
|
174
|
+
json.coveoAdvancedQueryConfig
|
|
175
|
+
).every(
|
|
176
|
+
([key, value]: [string, any]) =>
|
|
177
|
+
this.coveoAdvancedQueryConfig[key] === value
|
|
178
|
+
);
|
|
179
|
+
const hasSameQuery = json?.state?.query?.q === this.value;
|
|
180
|
+
|
|
181
|
+
if (hasSameConfig && hasSameQuery) {
|
|
182
|
+
this.preloadedState = json?.state;
|
|
183
|
+
} else {
|
|
184
|
+
window.sessionStorage.removeItem(SESSION_KEY);
|
|
185
|
+
}
|
|
186
|
+
} catch (e) {
|
|
187
|
+
console.error(e);
|
|
188
|
+
window.sessionStorage.removeItem(SESSION_KEY);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
private initializeCoveo = () => {
|
|
193
|
+
try {
|
|
194
|
+
this.engine = buildSearchEngine({
|
|
195
|
+
organizationId: this.coveoOrganizationId,
|
|
196
|
+
publicAccessToken: this.coveoPublicAccessToken,
|
|
197
|
+
searchHub: this.coveoSearchHub,
|
|
198
|
+
preloadedState: this.preloadedState
|
|
199
|
+
});
|
|
200
|
+
} catch (ex) {
|
|
201
|
+
console.error(`Coveo engine failed to initialize (${ex})`);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (!this.engine) {
|
|
205
|
+
console.error("Coveo engine failed to initialize!");
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (this.preloadedState) {
|
|
210
|
+
const actions = loadQueryActions(this.engine);
|
|
211
|
+
this.engine.dispatch(actions.updateQuery({ q: this.value || "" }));
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
this.resultList = buildResultList(this.engine, {
|
|
215
|
+
options: { fieldsToInclude: ["sfhtml_url__c"] }
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
this.resultsPerPage = buildResultsPerPage(this.engine, {
|
|
219
|
+
initialState: {
|
|
220
|
+
numberOfResults: DEFAULT_RESULT_COUNT
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
this.searchBox = buildSearchBox(this.engine, {
|
|
225
|
+
options: { numberOfSuggestions: 3 }
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
this.setAdvancedFilters(this.engine);
|
|
229
|
+
|
|
230
|
+
this.unsubscribeFromResultList = this.resultList?.subscribe(
|
|
231
|
+
this.onResultListChange
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
if (this.value) {
|
|
235
|
+
this.dispatchHighlightedTermChange();
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (!this.preloadedState) {
|
|
239
|
+
if (this.value) {
|
|
240
|
+
this.submitSearch();
|
|
241
|
+
} else {
|
|
242
|
+
this.dispatchOnLoading(false);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
this.syncAnalytics();
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
private syncAnalytics = () => {
|
|
250
|
+
const storedResult = window.localStorage.getItem(
|
|
251
|
+
RESULT_CLICK_LOCAL_STORAGE_KEY
|
|
252
|
+
);
|
|
253
|
+
if (storedResult) {
|
|
254
|
+
const interactiveResult = buildInteractiveResult(this.engine!, {
|
|
255
|
+
options: { result: JSON.parse(storedResult) }
|
|
256
|
+
});
|
|
257
|
+
interactiveResult.cancelPendingSelect();
|
|
258
|
+
interactiveResult.select();
|
|
259
|
+
window.localStorage.removeItem(RESULT_CLICK_LOCAL_STORAGE_KEY);
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
private onResultListChange = () => {
|
|
264
|
+
if (!this.resultList) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const { isLoading, firstSearchExecuted, results } =
|
|
269
|
+
this.resultList.state;
|
|
270
|
+
|
|
271
|
+
if ((!firstSearchExecuted && !isLoading) || !this.value) {
|
|
272
|
+
// coveo search is firing off some unwanted payloads on startup
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (!isLoading) {
|
|
277
|
+
this.dispatchOnChangeEvent(results);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (!this.fetchingMoreResults) {
|
|
281
|
+
this.dispatchOnLoading(isLoading);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (!isLoading && this.fetchingMoreResults) {
|
|
285
|
+
this.fetchingMoreResults = false;
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
private setAdvancedFilters(engine: SearchEngine) {
|
|
290
|
+
const aq = Object.entries(this.coveoAdvancedQueryConfig).reduce(
|
|
291
|
+
(result, [key, value]) =>
|
|
292
|
+
`${result}(@${key}=="${normalizeCoveoAdvancedQueryValue(
|
|
293
|
+
value
|
|
294
|
+
)}")`,
|
|
295
|
+
""
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
const registerSearchQueryAction = loadAdvancedSearchQueryActions(
|
|
299
|
+
engine
|
|
300
|
+
).registerAdvancedSearchQueries({
|
|
301
|
+
aq: aq
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
engine.dispatch(registerSearchQueryAction);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
private normalizeCoveoResult = (result: Result): SidebarSearchResult => {
|
|
308
|
+
const {
|
|
309
|
+
clickUri,
|
|
310
|
+
excerpt,
|
|
311
|
+
excerptHighlights,
|
|
312
|
+
raw: { sfhtml_url__c },
|
|
313
|
+
title,
|
|
314
|
+
titleHighlights,
|
|
315
|
+
uniqueId
|
|
316
|
+
} = result;
|
|
317
|
+
|
|
318
|
+
// discussion about this normalization here: https://salesforce-internal.slack.com/archives/C020S6784JX/p1639506238376600
|
|
319
|
+
|
|
320
|
+
let pathname, queryParam;
|
|
321
|
+
if (sfhtml_url__c) {
|
|
322
|
+
pathname = `/docs/${sfhtml_url__c}`;
|
|
323
|
+
} else {
|
|
324
|
+
const isNestedGuide = clickUri.includes("/guide/");
|
|
325
|
+
const url = new URL(clickUri);
|
|
326
|
+
const extension =
|
|
327
|
+
isNestedGuide && !url.pathname?.endsWith(".html")
|
|
328
|
+
? ".html"
|
|
329
|
+
: "";
|
|
330
|
+
pathname = `${url.pathname}${extension}`;
|
|
331
|
+
queryParam = url.search;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
let href;
|
|
335
|
+
let isSelected = false;
|
|
336
|
+
const isReferenceUrl = clickUri.includes("/references/");
|
|
337
|
+
if (isReferenceUrl) {
|
|
338
|
+
if (queryParam) {
|
|
339
|
+
href = `${pathname}${queryParam}&q=${this.value}`;
|
|
340
|
+
} else {
|
|
341
|
+
href = `${pathname}?q=${this.value}`;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
//NOTE: This is specific to references related comparison
|
|
345
|
+
const resultHrefWithMetaQuery = `${pathname}${queryParam}`;
|
|
346
|
+
|
|
347
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
348
|
+
const metaQueryParam = urlParams.get("meta");
|
|
349
|
+
|
|
350
|
+
let currentUrlPathWithQuery = window.location.pathname;
|
|
351
|
+
if (metaQueryParam) {
|
|
352
|
+
currentUrlPathWithQuery = `${currentUrlPathWithQuery}?meta=${metaQueryParam}`;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
isSelected = resultHrefWithMetaQuery === currentUrlPathWithQuery;
|
|
356
|
+
} else {
|
|
357
|
+
href = `${pathname}?q=${this.value}`;
|
|
358
|
+
isSelected = pathname === window.location.pathname;
|
|
359
|
+
}
|
|
360
|
+
|
|
90
361
|
return {
|
|
91
|
-
title
|
|
92
|
-
titleHighlights
|
|
93
|
-
excerpt
|
|
94
|
-
excerptHighlights
|
|
95
|
-
uniqueId
|
|
362
|
+
title,
|
|
363
|
+
titleHighlights,
|
|
364
|
+
excerpt,
|
|
365
|
+
excerptHighlights,
|
|
366
|
+
uniqueId,
|
|
96
367
|
href,
|
|
97
368
|
selected: isSelected,
|
|
98
|
-
select: () =>
|
|
369
|
+
select: () =>
|
|
370
|
+
window.localStorage.setItem(
|
|
371
|
+
RESULT_CLICK_LOCAL_STORAGE_KEY,
|
|
372
|
+
JSON.stringify(result)
|
|
373
|
+
)
|
|
99
374
|
};
|
|
100
375
|
};
|
|
101
376
|
|
|
102
|
-
private
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
this.
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
console.error("Data Cloud Search request failed", err);
|
|
111
|
-
this.dispatchChange([]);
|
|
112
|
-
} finally {
|
|
113
|
-
this.dispatchOnLoading(false);
|
|
114
|
-
}
|
|
377
|
+
private updateSessionStorage() {
|
|
378
|
+
window.sessionStorage.setItem(
|
|
379
|
+
SESSION_KEY,
|
|
380
|
+
JSON.stringify({
|
|
381
|
+
coveoAdvancedQueryConfig: this.coveoAdvancedQueryConfig,
|
|
382
|
+
state: this.engine?.state
|
|
383
|
+
})
|
|
384
|
+
);
|
|
115
385
|
}
|
|
116
386
|
|
|
117
|
-
private
|
|
387
|
+
private dispatchOnChangeEvent(results: Result[]) {
|
|
388
|
+
this.updateSessionStorage();
|
|
118
389
|
this.dispatchEvent(
|
|
119
390
|
new CustomEvent("change", {
|
|
120
|
-
detail: {
|
|
391
|
+
detail: {
|
|
392
|
+
results: results.map(this.normalizeCoveoResult),
|
|
393
|
+
value: this.value
|
|
394
|
+
}
|
|
121
395
|
})
|
|
122
396
|
);
|
|
123
397
|
}
|
|
@@ -153,12 +427,19 @@ export default class SidebarSearch extends LightningElement {
|
|
|
153
427
|
}
|
|
154
428
|
|
|
155
429
|
private submitSearch = debounce((isSyncingSearchValue = false) => {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
430
|
+
if (this.searchBox) {
|
|
431
|
+
UserRecentSearches.add(this.value);
|
|
432
|
+
this.updateRecentSearches();
|
|
433
|
+
|
|
434
|
+
// When `isSyncingSearchValue` is true, we are submitting in a case
|
|
435
|
+
// where the search box is already synced correctly.
|
|
436
|
+
if (!isSyncingSearchValue) {
|
|
437
|
+
this.dispatchSidebarSearchChange(this.value);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
this.searchBox.updateText(this.value || "");
|
|
441
|
+
this.searchBox.submit();
|
|
160
442
|
}
|
|
161
|
-
this.fetchDataCloudSearch();
|
|
162
443
|
}, SEARCH_DEBOUNCE_DELAY);
|
|
163
444
|
|
|
164
445
|
private onClickRecentSearch(e: CustomEvent) {
|
|
@@ -180,6 +461,7 @@ export default class SidebarSearch extends LightningElement {
|
|
|
180
461
|
|
|
181
462
|
private onInputChange(e: CustomEvent) {
|
|
182
463
|
this.value = e.detail;
|
|
464
|
+
|
|
183
465
|
this.handleValueChange(false);
|
|
184
466
|
this.dispatchHighlightedTermChange();
|
|
185
467
|
}
|
|
@@ -195,10 +477,16 @@ export default class SidebarSearch extends LightningElement {
|
|
|
195
477
|
private handleValueChange(isSyncingSearchValue = false) {
|
|
196
478
|
if (this.value) {
|
|
197
479
|
this.dispatchOnLoading(true);
|
|
198
|
-
this.
|
|
480
|
+
if (this.searchBox) {
|
|
481
|
+
this.submitSearch(isSyncingSearchValue);
|
|
482
|
+
}
|
|
199
483
|
} else {
|
|
484
|
+
// coveo's reaction to an empty value triggers a return of results
|
|
485
|
+
// bootlegging our own ux here`
|
|
200
486
|
this.dispatchOnLoading(false);
|
|
201
|
-
this.
|
|
487
|
+
this.dispatchOnChangeEvent([]);
|
|
488
|
+
// Empty search values are not submitted for search, so we need to manually
|
|
489
|
+
// trigger a search change on our own here
|
|
202
490
|
this.dispatchSidebarSearchChange(this.value);
|
|
203
491
|
}
|
|
204
492
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { LightningElement, api } from "lwc";
|
|
2
2
|
import cx from "classnames";
|
|
3
|
-
import {
|
|
3
|
+
import { CoveoHighlights } from "typings/custom";
|
|
4
4
|
|
|
5
|
-
const toChunks = (value: string, highlights:
|
|
5
|
+
const toChunks = (value: string, highlights: CoveoHighlights) => {
|
|
6
6
|
if (!highlights || highlights.length < 1) {
|
|
7
7
|
return [
|
|
8
8
|
{
|
|
@@ -51,11 +51,11 @@ const toChunks = (value: string, highlights: HighlightedSections) => {
|
|
|
51
51
|
|
|
52
52
|
export default class SidebarSearchResult extends LightningElement {
|
|
53
53
|
@api description!: string;
|
|
54
|
-
@api descriptionHighlights!:
|
|
54
|
+
@api descriptionHighlights!: CoveoHighlights;
|
|
55
55
|
@api href!: string;
|
|
56
56
|
@api selected!: boolean;
|
|
57
57
|
@api header!: string;
|
|
58
|
-
@api titleHighlights!:
|
|
58
|
+
@api titleHighlights!: CoveoHighlights;
|
|
59
59
|
@api select!: Function;
|
|
60
60
|
|
|
61
61
|
private get titleChunks() {
|
|
@@ -7,11 +7,13 @@ let bracketsModulePromise: Promise<
|
|
|
7
7
|
> | null = null;
|
|
8
8
|
|
|
9
9
|
async function getShiki() {
|
|
10
|
-
return (shikiModulePromise ??= import("shiki"));
|
|
10
|
+
return (shikiModulePromise ??= import("shiki/dist/index.mjs"));
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
async function getBrackets() {
|
|
14
|
-
return (bracketsModulePromise ??= import(
|
|
14
|
+
return (bracketsModulePromise ??= import(
|
|
15
|
+
"@shikijs/colorized-brackets/dist/index.mjs"
|
|
16
|
+
));
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
interface ShikiSingleton {
|