@salesforcedevs/dx-components 1.3.210-lang5-alpha → 1.3.210-lang6-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.
@@ -11,94 +11,129 @@
11
11
  <div class="dx-search-header-container">
12
12
  <p class="dx-search-header-title">
13
13
  <span class="dx-search-header-title-results">{title}</span>
14
+ &nbsp;
15
+ <strong lwc:if={hasNoResults}>0</strong>
14
16
  &nbsp;results for
15
17
  </p>
16
18
  <p class="dx-search-header-query">&ldquo;{query}&rdquo;</p>
17
19
  </div>
18
20
  </div>
19
21
  <div class="coveo-main-section">
20
- <div class="coveo-facet-column">
21
- <div class="dx-facet-column-header">
22
- <span class="dx-facet-column-header-title">Filters</span>
23
- <template if:true={hasFilters}>
24
- <dx-button onclick={clearFilters} variant="inline">
25
- Clear
26
- </dx-button>
27
- </template>
28
- </div>
29
- <div
30
- class="CoveoDynamicFacetManager"
31
- data-enable-reorder="false"
32
- >
33
- <div
34
- class="CoveoDynamicFacet"
35
- data-title="Content Type"
36
- data-field="@commonsource"
37
- data-tab="All"
38
- data-enable-facet-search="false"
39
- ></div>
40
- <div
41
- class="CoveoDynamicFacet"
42
- data-title="Language"
43
- data-field="@language"
44
- data-tab="All"
45
- data-enable-facet-search="false"
46
- ></div>
47
- </div>
48
- <div class="dx-facet-column-footer">
49
- <dx-button onclick={dismissFiltersOverlay}>
50
- View {title} results
51
- </dx-button>
22
+ <div class="no-results" lwc:if={hasNoResults}>
23
+ <img
24
+ src="https://a.sfdcstatic.com/developer-website/images/binary-cloud-circle-small.svg"
25
+ alt="purple cloud with floating binary numbers above"
26
+ />
27
+ <div class="no-results-info">
28
+ <p class="dx-text-display-8">
29
+ Sorry, no results were found for your search
30
+ &ldquo;{query}&rdquo;
31
+ </p>
32
+ <p class="dx-text-display-8 tip">Search Tips:</p>
33
+ <ul>
34
+ <li>Please consider misspellings</li>
35
+ <li>Try different search keywords</li>
36
+ </ul>
37
+ <dx-hr no-padding="true"></dx-hr>
38
+ <p class="dx-text-display-8 tip">
39
+ Still not finding what you're looking for? Consider
40
+ asking in the&nbsp;
41
+ <a
42
+ class="link"
43
+ href="https://trailhead.salesforce.com/trailblazer-community/feed"
44
+ >
45
+ Trailblazer Community
46
+ </a>
47
+ !
48
+ </p>
52
49
  </div>
53
50
  </div>
54
- <div class="coveo-results-column">
55
- <div class="CoveoShareQuery"></div>
56
- <div class="CoveoExportToExcel"></div>
57
- <div class="CoveoPreferencesPanel">
58
- <div class="CoveoResultsPreferences"></div>
59
- <div class="CoveoResultsFiltersPreferences"></div>
60
- </div>
61
- <div class="CoveoDidYouMean"></div>
62
- <div class="coveo-results-header">
63
- <div class="coveo-summary-section"></div>
64
- <div class="coveo-sort-section" role="radiogroup">
65
- <span
66
- class="CoveoSort"
67
- data-sort-criteria="relevancy"
68
- data-caption="Sorted by Relevance"
69
- ></span>
51
+ <template lwc:if={hasResults}>
52
+ <div class="coveo-facet-column">
53
+ <div class="dx-facet-column-header">
54
+ <span class="dx-facet-column-header-title">
55
+ Filters
56
+ </span>
57
+ <template if:true={hasFilters}>
58
+ <dx-button onclick={clearFilters} variant="inline">
59
+ Clear
60
+ </dx-button>
61
+ </template>
70
62
  </div>
71
- <div>
63
+ <div
64
+ class="CoveoDynamicFacetManager"
65
+ data-enable-reorder="false"
66
+ >
67
+ <div
68
+ class="CoveoDynamicFacet"
69
+ data-title="Content Type"
70
+ data-field="@commonsource"
71
+ data-tab="All"
72
+ data-enable-facet-search="false"
73
+ ></div>
72
74
  <div
73
- class="CoveoSearchbox"
74
- data-enable-omnibox="false"
75
- data-add-search-button="false"
76
- aria-hidden="true"
75
+ class="CoveoDynamicFacet"
76
+ data-title="Language"
77
+ data-field="@language"
78
+ data-tab="All"
79
+ data-enable-facet-search="false"
77
80
  ></div>
78
81
  </div>
82
+ <div class="dx-facet-column-footer">
83
+ <dx-button onclick={dismissFiltersOverlay}>
84
+ View {title} results
85
+ </dx-button>
86
+ </div>
79
87
  </div>
80
- <div class="CoveoBreadcrumb"></div>
81
- <div class="CoveoHiddenQuery"></div>
82
- <div class="CoveoErrorReport"></div>
83
- <div
84
- class="CoveoResultList"
85
- data-layout="list"
86
- data-wait-animation="fade"
87
- data-auto-select-fields-to-include="true"
88
- lwc:dom="manual"
89
- ></div>
90
- <div class="coveo-results-footer" aria-hidden="true">
91
- <div class="CoveoPager"></div>
92
- </div>
93
- <div class="pagination-container">
94
- <dx-pagination
95
- current-page={currentPage}
96
- total-pages={totalPages}
97
- onpagechange={goToPage}
98
- pages-to-show="5"
99
- ></dx-pagination>
88
+ <div class="coveo-results-column">
89
+ <div class="CoveoShareQuery"></div>
90
+ <div class="CoveoExportToExcel"></div>
91
+ <div class="CoveoPreferencesPanel">
92
+ <div class="CoveoResultsPreferences"></div>
93
+ <div class="CoveoResultsFiltersPreferences"></div>
94
+ </div>
95
+ <div class="CoveoDidYouMean"></div>
96
+ <div class="coveo-results-header">
97
+ <div class="coveo-summary-section"></div>
98
+ <div class="coveo-sort-section" role="radiogroup">
99
+ <span
100
+ class="CoveoSort"
101
+ data-sort-criteria="relevancy"
102
+ data-caption="Sorted by Relevance"
103
+ ></span>
104
+ </div>
105
+ <div>
106
+ <div
107
+ class="CoveoSearchbox"
108
+ data-enable-omnibox="false"
109
+ data-add-search-button="false"
110
+ aria-hidden="true"
111
+ ></div>
112
+ </div>
113
+ </div>
114
+ <div class="CoveoBreadcrumb"></div>
115
+ <div class="CoveoHiddenQuery"></div>
116
+ <div class="CoveoErrorReport"></div>
117
+ <div
118
+ class="CoveoResultList"
119
+ data-layout="list"
120
+ data-wait-animation="fade"
121
+ data-auto-select-fields-to-include="true"
122
+ lwc:dom="manual"
123
+ ></div>
124
+ <div class="coveo-results-footer" aria-hidden="true">
125
+ <div class="CoveoPager"></div>
126
+ </div>
127
+ <div class="pagination-container">
128
+ <dx-pagination
129
+ current-page={currentPage}
130
+ total-pages={totalPages}
131
+ onpagechange={goToPage}
132
+ pages-to-show="5"
133
+ ></dx-pagination>
134
+ </div>
100
135
  </div>
101
- </div>
136
+ </template>
102
137
  </div>
103
138
  </div>
104
139
  </template>
@@ -118,11 +118,16 @@ export default class SearchResults extends LightningElement {
118
118
 
119
119
  private query: string = "";
120
120
  private hasFilters: boolean = false;
121
+ private hasResults: boolean = true;
121
122
 
122
123
  private get hasQuery(): boolean {
123
124
  return this.query !== "";
124
125
  }
125
126
 
127
+ private get hasNoResults(): boolean {
128
+ return this.hasQuery && !this.hasResults;
129
+ }
130
+
126
131
  private updateSearchQuery() {
127
132
  Coveo.state(this.root!, "q", this._query);
128
133
  }
@@ -185,12 +190,18 @@ export default class SearchResults extends LightningElement {
185
190
  this.currentPage = currentPage;
186
191
  this.totalPages = numberOfPages;
187
192
  this.totalResults = event.detail.results.totalCount;
193
+
194
+ if (!this.totalResults) {
195
+ this.hasResults = false;
196
+ }
197
+
188
198
  this.query = event.detail.query.q ?? "";
189
199
  this.hasFilters = event.detail.query.facets.some((f: any) => {
190
200
  return f.currentValues.some((cv: any) => {
191
201
  return cv.state === "selected";
192
202
  });
193
203
  });
204
+
194
205
  this.trackSearchResults(event, this.query, this.totalResults);
195
206
  });
196
207
  }
@@ -199,6 +210,7 @@ export default class SearchResults extends LightningElement {
199
210
  this.root = this.template.querySelector(".CoveoSearchInterface")!;
200
211
 
201
212
  const resultsList = this.template.querySelector(".CoveoResultList");
213
+
202
214
  if (resultsList) {
203
215
  resultsList.innerHTML = resultsTemplatesInnerHtml;
204
216
  }
@@ -1,8 +1,14 @@
1
1
  @import "dxHelpers/commonSidebar";
2
2
 
3
3
  dx-empty-state {
4
- --dx-c-empty-state-background: var(--sds-g-gray-2);
4
+ --dx-c-empty-state-background-alt: var(--sds-g-gray-1);
5
5
  --dx-c-empty-state-image-width: 400px;
6
+ --dx-c-font-title-alt-size: 18px;
7
+ --dx-c-font-title-alt-margin-top: var(--dx-g-spacing-md);
8
+ --dx-c-font-body-alt-size: var(--dx-g-text-xs);
9
+ --dx-c-font-body-alt-margin-top: 0;
10
+ --dx-c-container-alt-padding: var(--dx-g-spacing-2xl) 37px;
11
+ --dx-c-font-suggestion-alt-size: 10px;
6
12
 
7
13
  display: none;
8
14
  }
@@ -75,8 +75,11 @@
75
75
  ></dx-sidebar-search-result>
76
76
  </template>
77
77
  <dx-empty-state
78
+ variant="alt"
78
79
  class="padding-horizontal"
79
80
  title="No Results"
81
+ body={emptyStateBody}
82
+ suggestions={emptyStateSuggestions}
80
83
  size="small"
81
84
  ></dx-empty-state>
82
85
  </div>
@@ -95,23 +98,23 @@
95
98
 
96
99
  <template if:false={mobile}>
97
100
  <div if:true={hasSidebarFooter} class="footer-nav">
98
- <doc-sidebar-footer-nav
101
+ <dx-sidebar-footer-nav
99
102
  lang-value-path={langValuePath}
100
103
  language={language}
101
104
  languages={languages}
102
105
  bail-href={bailHref}
103
106
  bail-label={bailLabel}
104
- ></doc-sidebar-footer-nav>
107
+ ></dx-sidebar-footer-nav>
105
108
  </div>
106
109
  </template>
107
110
 
108
111
  <template if:true={mobile}>
109
112
  <div if:true={hasMobileSidebarFooter} class="footer-nav">
110
- <doc-sidebar-footer-nav
113
+ <dx-sidebar-footer-nav
111
114
  lang-value-path={langValuePath}
112
115
  language={language}
113
116
  languages={languages}
114
- ></doc-sidebar-footer-nav>
117
+ ></dx-sidebar-footer-nav>
115
118
  </div>
116
119
  </template>
117
120
  </div>
@@ -5,7 +5,6 @@ import { getSidebarSearchParams } from "dxUtils/coveo";
5
5
  import { toJson } from "dxUtils/normalizers";
6
6
  import SidebarSearch from "dx/sidebarSearch";
7
7
  import { SidebarBase } from "dxBaseElements/sidebarBase";
8
- import type { OptionWithLink } from "typings/custom";
9
8
 
10
9
  const MOBILE_SIZE_MATCH = "768px";
11
10
 
@@ -15,19 +14,6 @@ export default class Sidebar extends SidebarBase {
15
14
  @api coveoSearchHub!: string;
16
15
  @api coveoAdvancedQueryConfig!: string;
17
16
  @api header: string = "";
18
- @api langValuePath: string = "id";
19
- @api language!: string;
20
- @api bailHref!: string;
21
- @api bailLabel!: string;
22
-
23
- @api
24
- get value() {
25
- return this._value;
26
- }
27
-
28
- set value(value) {
29
- this._value = value;
30
- }
31
17
 
32
18
  @api
33
19
  get trees() {
@@ -48,15 +34,6 @@ export default class Sidebar extends SidebarBase {
48
34
  }));
49
35
  }
50
36
 
51
- @api
52
- get languages() {
53
- return this._languages;
54
- }
55
-
56
- set languages(value) {
57
- this._languages = toJson(value);
58
- }
59
-
60
37
  @api
61
38
  setInputValue(searchTerm: string) {
62
39
  (
@@ -66,23 +43,16 @@ export default class Sidebar extends SidebarBase {
66
43
  )?.setInputValue(searchTerm);
67
44
  }
68
45
 
69
- private expanded: boolean = true;
70
- private _value?: string = undefined;
71
-
72
46
  @track
73
47
  private _trees!: Array<TreeNode>;
74
-
75
- private mobile: boolean = true;
76
48
  private matchMedia!: MediaQueryList;
77
49
  private valueToLabel: { [key: string]: string } = {};
78
-
79
50
  private isSearchLoading: boolean = false;
80
51
  private searchValue: string | null = null;
81
52
  private searchResults: SidebarSearchResult[] = [];
82
53
  private scrollToSelectedSearchResult: boolean = false;
83
54
  private selectedSearchResultIndex: number = -1;
84
55
  private requestedFetchMoreResults: boolean = false;
85
- private _languages!: OptionWithLink[];
86
56
 
87
57
  private get areResultsEmpty(): boolean {
88
58
  return (
@@ -110,6 +80,17 @@ export default class Sidebar extends SidebarBase {
110
80
  );
111
81
  }
112
82
 
83
+ private get emptyStateBody(): string {
84
+ return "Search Tips:";
85
+ }
86
+
87
+ private get emptyStateSuggestions(): string {
88
+ return JSON.stringify([
89
+ "Please consider misspellings",
90
+ "Try different search keywords"
91
+ ]);
92
+ }
93
+
113
94
  private get isNearBottomOfSearchResults(): boolean {
114
95
  const scrollArea = this.template.querySelector(
115
96
  ".sidebar-content-search"
@@ -175,32 +156,6 @@ export default class Sidebar extends SidebarBase {
175
156
  this.matchMedia.removeEventListener("change", this.onMediaChange);
176
157
  }
177
158
 
178
- private onMediaChange = (event: MediaQueryListEvent | MediaQueryList) => {
179
- this.mobile = event.matches;
180
- this.expanded = !this.mobile;
181
- };
182
-
183
- private onSelect(event: CustomEvent) {
184
- this._value = event.detail.name;
185
-
186
- if (this.mobile) {
187
- this.onToggleClick();
188
- }
189
- }
190
-
191
- private onToggleClick() {
192
- this.expanded = !this.expanded;
193
- this.dispatchEvent(
194
- new CustomEvent("togglesidebar", {
195
- detail: {
196
- open: this.expanded,
197
- bubbles: true,
198
- composed: true
199
- }
200
- })
201
- );
202
- }
203
-
204
159
  private makeKey(): string {
205
160
  return Math.random().toString(36).substring(7);
206
161
  }
@@ -271,12 +226,4 @@ export default class Sidebar extends SidebarBase {
271
226
  this.template.querySelector("dx-sidebar-search") as any
272
227
  )?.requestOpenDropdown(false);
273
228
  }
274
-
275
- private get hasMobileSidebarFooter(): boolean {
276
- return this.mobile && this.languages?.length > 1 && this.expanded;
277
- }
278
-
279
- private get hasSidebarFooter(): boolean {
280
- return this.languages?.length > 1 || Boolean(this.bailHref);
281
- }
282
229
  }
@@ -0,0 +1,52 @@
1
+ @import "dxHelpers/reset";
2
+
3
+ :host {
4
+ --button-primary-color: var(--dx-g-blue-vibrant-50);
5
+ --button-primary-color-hover: var(--dx-g-cloud-blue-vibrant-95);
6
+ --popover-container-open-transform: translateX(-4px) translateY(-8px);
7
+ --popover-transition: none;
8
+ --dx-c-dropdown-option-font-weight: normal;
9
+ --dx-c-dropdown-option-label-color: var(--dx-g-gray-10);
10
+ }
11
+
12
+ .footer-display {
13
+ display: flex;
14
+ }
15
+
16
+ .footer_lang-dropdown {
17
+ --dx-c-button-primary-color: var(--button-primary-color);
18
+ --border-color: var(--button-primary-color);
19
+
20
+ display: flex;
21
+ padding: 0 var(--dx-g-spacing-md);
22
+ margin-left: var(--dx-g-spacing-sm);
23
+ height: var(--dx-g-spacing-xl);
24
+ border-radius: var(--dx-g-spacing-xs);
25
+ align-items: center;
26
+ }
27
+
28
+ .footer_lang-dropdown[aria-expanded="true"] {
29
+ background-color: var(--dx-g-cloud-blue-vibrant-95);
30
+
31
+ --border-color: var(--dx-g-cloud-blue-vibrant-95);
32
+ }
33
+
34
+ .footer_lang-dropdown:hover,
35
+ .footer_lang-dropdown:active,
36
+ .footer_lang-dropdown:focus,
37
+ .pdf_bail-link:hover {
38
+ background-color: var(--button-primary-color-hover);
39
+
40
+ --border-color: var(--button-primary-color-hover);
41
+ }
42
+
43
+ .pdf_bail-link {
44
+ --dx-c-button-horizontal-spacing: var(--dx-g-spacing-sm);
45
+ --dx-c-button-priamry-color-hover: var(--dx-g-cloud-blue-vibrant-95);
46
+
47
+ padding: 0 var(--dx-g-spacing-md);
48
+ border-radius: var(--dx-g-spacing-xs);
49
+ display: flex;
50
+ height: var(--dx-g-spacing-xl);
51
+ align-items: center;
52
+ }
@@ -0,0 +1,55 @@
1
+ <template>
2
+ <div if:false={mobile} class="footer-display">
3
+ <dx-button
4
+ if:true={hasBailLink}
5
+ aria-label={bailLabel}
6
+ class="pdf_bail-link"
7
+ href={bailHref}
8
+ onclick={handleBailClick}
9
+ variant="inline"
10
+ icon-size="medium"
11
+ icon-symbol="new_window"
12
+ target="_blank"
13
+ >
14
+ {bailLabel}
15
+ </dx-button>
16
+ <dx-dropdown
17
+ if:true={hasLanguages}
18
+ options={languages}
19
+ small
20
+ value-path={langValuePath}
21
+ value={language}
22
+ onchange={onLangChange}
23
+ >
24
+ <dx-button
25
+ class="footer_lang-dropdown"
26
+ aria-label="Select Language"
27
+ variant="inline"
28
+ icon-size="medium"
29
+ icon-symbol="world"
30
+ >
31
+ {languageLabel}
32
+ </dx-button>
33
+ </dx-dropdown>
34
+ </div>
35
+ <div if:true={mobile} class="footer-display">
36
+ <dx-dropdown
37
+ if:true={hasLanguages}
38
+ options={languages}
39
+ small
40
+ value-path={langValuePath}
41
+ value={language}
42
+ onchange={onLangChange}
43
+ >
44
+ <dx-button
45
+ class="footer_lang-dropdown"
46
+ aria-label="Select Language"
47
+ variant="inline"
48
+ icon-size="small"
49
+ icon-symbol="world"
50
+ >
51
+ {languageLabel}
52
+ </dx-button>
53
+ </dx-dropdown>
54
+ </div>
55
+ </template>
@@ -0,0 +1,106 @@
1
+ /* eslint-disable @lwc/lwc/no-document-query */
2
+ import { LightningElement, api } from "lwc";
3
+ import type { OptionWithLink } from "typings/custom";
4
+ import { toJson } from "dxUtils/normalizers";
5
+ import get from "lodash.get";
6
+ import { track } from "dxUtils/analytics";
7
+
8
+ const MOBILE_SIZE_MATCH = "768px";
9
+
10
+ export default class SidebarFooterNav extends LightningElement {
11
+ @api langValuePath: string = "id";
12
+ @api bailHref?: string | null = null;
13
+ @api bailLabel?: string | null = null;
14
+
15
+ @api
16
+ get languages() {
17
+ return this._languages;
18
+ }
19
+
20
+ set languages(value) {
21
+ this._languages = toJson(value);
22
+ }
23
+
24
+ @api
25
+ get language() {
26
+ return this._language;
27
+ }
28
+
29
+ set language(value) {
30
+ this._language = value;
31
+ }
32
+
33
+ private _languages!: OptionWithLink[];
34
+ private _language: string | null = null;
35
+ private mobile: boolean = false;
36
+ private matchMedia!: MediaQueryList;
37
+
38
+ private get hasLanguages(): boolean {
39
+ return this.languages?.length > 1;
40
+ }
41
+
42
+ private get languageLabel(): string {
43
+ const matchingLanguageData = this.language
44
+ ? this.languages.find(
45
+ (lang) => get(lang, this.langValuePath) === this.language
46
+ )
47
+ : null;
48
+ return matchingLanguageData?.label || this.languages[0].label;
49
+ }
50
+
51
+ get hasBailLink(): boolean {
52
+ return !!(this.bailHref && this.bailLabel);
53
+ }
54
+
55
+ private onLangChange(event: CustomEvent<string>): void {
56
+ const { detail } = event;
57
+ this._language = detail;
58
+
59
+ this.dispatchEvent(
60
+ new CustomEvent("langchange", {
61
+ detail,
62
+ bubbles: true,
63
+ composed: true
64
+ })
65
+ );
66
+ }
67
+
68
+ private getFilename = function (path: string) {
69
+ return path.substring(path.lastIndexOf("/") + 1);
70
+ };
71
+
72
+ private handleBailClick(event: Event) {
73
+ const payload = {
74
+ click_text: "pdf",
75
+ click_url: this.bailHref,
76
+ element_title: "pdf",
77
+ element_type: "link",
78
+ content_category: "download"
79
+ };
80
+ track(event.target!, "custEv_pdfDownload", {
81
+ ...payload,
82
+ file_name: this.getFilename(this.bailHref!),
83
+ file_extension: "pdf"
84
+ });
85
+
86
+ track(event.target!, "custEv_linkClick", {
87
+ ...payload
88
+ });
89
+ }
90
+
91
+ connectedCallback() {
92
+ this.matchMedia = window.matchMedia(
93
+ `(max-width: ${MOBILE_SIZE_MATCH})`
94
+ );
95
+ this.onMediaChange(this.matchMedia);
96
+ this.matchMedia.addEventListener("change", this.onMediaChange);
97
+ }
98
+
99
+ disconnectedCallback() {
100
+ this.matchMedia.removeEventListener("change", this.onMediaChange);
101
+ }
102
+
103
+ private onMediaChange = (event: MediaQueryListEvent | MediaQueryList) => {
104
+ this.mobile = event.matches;
105
+ };
106
+ }
@@ -5,8 +5,14 @@
5
5
  }
6
6
 
7
7
  dx-empty-state {
8
- --dx-c-empty-state-background: var(--sds-g-gray-2);
8
+ --dx-c-empty-state-background-alt: var(--sds-g-gray-1);
9
9
  --dx-c-empty-state-image-width: 400px;
10
+ --dx-c-font-title-alt-size: 18px;
11
+ --dx-c-font-title-alt-margin-top: var(--dx-g-spacing-md);
12
+ --dx-c-font-body-alt-size: var(--dx-g-text-xs);
13
+ --dx-c-font-body-alt-margin-top: 0;
14
+ --dx-c-container-alt-padding: var(--dx-g-spacing-2xl) 37px;
15
+ --dx-c-font-suggestion-alt-size: 10px;
10
16
 
11
17
  padding-bottom: var(--dx-g-spacing-md);
12
18
  }