@salesforcedevs/docs-components 1.3.199-alpha → 1.3.199-langpicker2-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.
package/lwc.config.json CHANGED
@@ -18,6 +18,7 @@
18
18
  "doc/overview",
19
19
  "doc/phase",
20
20
  "doc/xmlContent",
21
+ "doc/sidebarFooterNav",
21
22
  "docUtils/utils"
22
23
  ]
23
24
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforcedevs/docs-components",
3
- "version": "1.3.199-alpha",
3
+ "version": "1.3.199-langpicker2-alpha",
4
4
  "description": "Docs Lightning web components for DSC",
5
5
  "license": "MIT",
6
6
  "main": "index.js",
@@ -16,6 +16,8 @@
16
16
  toc-title={tocTitle}
17
17
  toc-options={tocOptions}
18
18
  enable-slot-change="true"
19
+ languages={languages}
20
+ language={language}
19
21
  >
20
22
  <doc-phase
21
23
  slot="doc-phase"
@@ -4,6 +4,7 @@ import { sentenceCase } from "sentence-case";
4
4
  import qs from "query-string";
5
5
  import { AmfModelParser } from "doc/amfModelParser";
6
6
  import { normalizeBoolean } from "dxUtils/normalizers";
7
+ import type { OptionWithLink } from "typings/custom";
7
8
  import type {
8
9
  AmfConfig,
9
10
  AmfMetadataTopic,
@@ -48,6 +49,8 @@ export default class AmfReference extends LightningElement {
48
49
  @api useOldSidebar: boolean = false;
49
50
  @api tocTitle?: string;
50
51
  @api tocOptions?: string;
52
+ @api languages!: OptionWithLink[];
53
+ @api language!: string;
51
54
  @track navigation = [] as NavigationItem[];
52
55
  @track versions: Array<ReferenceVersion> = [];
53
56
  @track showVersionBanner = false;
@@ -7,6 +7,10 @@
7
7
  value={sidebarValue}
8
8
  header={sidebarHeader}
9
9
  ontogglesidebar={onToggleSidebar}
10
+ languages={languages}
11
+ language={language}
12
+ bail-href={bailHref}
13
+ bail-label={bailLabel}
10
14
  >
11
15
  <slot name="sidebar-header" slot="header"></slot>
12
16
  </dx-sidebar-old>
@@ -22,6 +26,10 @@
22
26
  coveo-search-hub={coveoSearchHub}
23
27
  coveo-advanced-query-config={coveoAdvancedQueryConfig}
24
28
  ontogglesidebar={onToggleSidebar}
29
+ languages={languages}
30
+ language={language}
31
+ bail-href={bailHref}
32
+ bail-label={bailLabel}
25
33
  >
26
34
  <slot name="sidebar-header" slot="header"></slot>
27
35
  </dx-sidebar>
@@ -4,6 +4,7 @@ import { closest } from "kagekiri";
4
4
  import { toJson } from "dxUtils/normalizers";
5
5
  import { highlightTerms } from "dxUtils/highlight";
6
6
  import { SearchSyncer } from "docUtils/searchSyncer";
7
+ import type { OptionWithLink } from "typings/custom";
7
8
 
8
9
  type AnchorMap = { [key: string]: { intersect: boolean; id: string } };
9
10
 
@@ -36,6 +37,10 @@ export default class ContentLayout extends LightningElement {
36
37
  @api coveoSearchHub!: string;
37
38
  @api coveoAdvancedQueryConfig!: string;
38
39
  @api useOldSidebar?: boolean = false;
40
+ @api languages!: OptionWithLink[];
41
+ @api language!: string;
42
+ @api bailHref!: string;
43
+ @api bailLabel!: string;
39
44
 
40
45
  @api
41
46
  get breadcrumbs() {
@@ -48,24 +48,6 @@ header:not(.has-brand) > .header_l2 {
48
48
  margin-left: var(--dx-g-spacing-sm);
49
49
  }
50
50
 
51
- .header_lang-dropdown {
52
- --button-primary-color: var(--dx-g-blue-vibrant-40);
53
- --button-primary-color-hover: var(--dx-g-blue-vibrant-30);
54
- }
55
-
56
- .header_lang-dropdown > dx-button {
57
- --dx-c-button-primary-color: var(--button-primary-color);
58
- --dx-c-button-primary-color-hover: var(--button-primary-color-hover);
59
- --dx-c-slot-empty-width: min-content;
60
- --border-color: var(--button-primary-color);
61
-
62
- border-bottom: 1px dashed var(--border-color);
63
- }
64
-
65
- .header_lang-dropdown > dx-button:hover {
66
- --border-color: var(--button-primary-color-hover);
67
- }
68
-
69
51
  .has-brand .header_l2_group-title {
70
52
  padding-bottom: calc(var(--dx-g-spacing-md) + 2px);
71
53
  }
@@ -20,22 +20,6 @@
20
20
  {subtitle}
21
21
  </span>
22
22
  </a>
23
- <dx-dropdown
24
- if:true={showMobileLanguages}
25
- class="header_lang-dropdown"
26
- options={languages}
27
- small
28
- value={language}
29
- value-path={langValuePath}
30
- onchange={onLangChange}
31
- >
32
- <dx-button
33
- aria-label="Select Language"
34
- variant="inline"
35
- icon-size="large"
36
- icon-symbol="world"
37
- ></dx-button>
38
- </dx-dropdown>
39
23
  </div>
40
24
  <div
41
25
  if:true={hasScopedNavItems}
@@ -52,41 +36,6 @@
52
36
  ></dx-header-nav>
53
37
  </div>
54
38
  </div>
55
- <div
56
- if:false={smallMobile}
57
- class="header_l2_group header_l2_group-right-ctas"
58
- >
59
- <dx-dropdown
60
- if:true={hasLanguages}
61
- class="header_lang-dropdown"
62
- options={languages}
63
- small
64
- value-path={langValuePath}
65
- value={language}
66
- onchange={onLangChange}
67
- >
68
- <dx-button
69
- aria-label="Select Language"
70
- variant="inline"
71
- icon-size="small"
72
- icon-symbol="world"
73
- >
74
- {languageLabel}
75
- </dx-button>
76
- </dx-dropdown>
77
- <dx-button
78
- if:true={hasBailLink}
79
- aria-label={bailLabel}
80
- class="header_bail-link"
81
- href={bailHref}
82
- onclick={handleBailClick}
83
- variant="tertiary"
84
- icon-symbol="new_window"
85
- target="_blank"
86
- >
87
- {bailLabel}
88
- </dx-button>
89
- </div>
90
39
  </div>
91
40
  </header>
92
41
  </dx-brand-theme-provider>
@@ -1,10 +1,8 @@
1
1
  import { api } from "lwc";
2
2
  import cx from "classnames";
3
- import type { OptionWithNested, OptionWithLink } from "typings/custom";
3
+ import type { OptionWithNested } from "typings/custom";
4
4
  import { HeaderBase } from "dxBaseElements/headerBase";
5
5
  import { toJson } from "dxUtils/normalizers";
6
- import get from "lodash.get";
7
- import { track } from "dxUtils/analytics";
8
6
 
9
7
  const TABLET_MATCH = "980px";
10
8
  const MOBILE_MATCH = "880px";
@@ -23,28 +21,6 @@ export default class Header extends HeaderBase {
23
21
  this._scopedNavItems = toJson(value);
24
22
  }
25
23
 
26
- @api
27
- get languages() {
28
- return this._languages;
29
- }
30
-
31
- set languages(value) {
32
- this._languages = toJson(value);
33
- }
34
-
35
- @api
36
- get language() {
37
- return this._language;
38
- }
39
-
40
- set language(value) {
41
- if (this._language !== value) {
42
- this._language = value;
43
- }
44
- }
45
-
46
- private _language: string | null = null;
47
- private _languages!: OptionWithLink[];
48
24
  private _scopedNavItems!: OptionWithNested[];
49
25
  private smallMobile = false;
50
26
  private smallMobileMatchMedia!: MediaQueryList;
@@ -60,24 +36,6 @@ export default class Header extends HeaderBase {
60
36
  return this.scopedNavItems && this.scopedNavItems.length > 0;
61
37
  }
62
38
 
63
- private get hasLanguages(): boolean {
64
- return !!(this.languages && this.languages.length);
65
- }
66
-
67
- private get showMobileLanguages(): boolean {
68
- return this.smallMobile && this.hasLanguages;
69
- }
70
-
71
- private get languageLabel(): string {
72
- return (
73
- (this.language &&
74
- this.languages.find(
75
- (lang) => get(lang, this.langValuePath) === this.language
76
- )?.label) ||
77
- this.languages[0].label
78
- );
79
- }
80
-
81
39
  connectedCallback(): void {
82
40
  super.connectedCallback();
83
41
  this.tabletMatchMedia = window.matchMedia(
@@ -129,34 +87,4 @@ export default class Header extends HeaderBase {
129
87
  this.hasScopedNavItems && "has-scoped-nav-items"
130
88
  );
131
89
  }
132
-
133
- private onLangChange(event: CustomEvent<string>): void {
134
- const { detail } = event;
135
- this._language = detail;
136
-
137
- this.dispatchEvent(new CustomEvent("langchange", { detail }));
138
- }
139
-
140
- private handleBailClick(event: Event) {
141
- const payload = {
142
- click_text: "pdf",
143
- click_url: this.bailHref,
144
- element_title: "pdf",
145
- element_type: "link",
146
- content_category: "download"
147
- };
148
- track(event.target!, "custEv_pdfDownload", {
149
- ...payload,
150
- file_name: this.getFilename(this.bailHref!),
151
- file_extension: "pdf"
152
- });
153
-
154
- track(event.target!, "custEv_linkClick", {
155
- ...payload
156
- });
157
- }
158
-
159
- private getFilename = function (path: string) {
160
- return path.substring(path.lastIndexOf("/") + 1);
161
- };
162
90
  }
@@ -0,0 +1,34 @@
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
+ }
7
+
8
+ .footer-display {
9
+ display: flex;
10
+ }
11
+
12
+ .footer_lang-dropdown {
13
+ padding: var(--dx-g-spacing-2xs) var(--dx-g-spacing-md);
14
+ margin-left: var(--dx-g-spacing-sm);
15
+ }
16
+
17
+ .footer_lang-dropdown > dx-button {
18
+ --dx-c-button-primary-color: var(--button-primary-color);
19
+ --dx-c-slot-empty-width: min-content;
20
+ --border-color: var(--button-primary-color);
21
+ }
22
+
23
+ .footer_lang-dropdown:hover,
24
+ .footer_lang-dropdown:active,
25
+ .footer_lang-dropdown:focus,
26
+ .header_bail-link:hover {
27
+ background-color: var(--button-primary-color-hover);
28
+
29
+ --border-color: var(--button-primary-color-hover);
30
+ }
31
+
32
+ .header_bail-link {
33
+ --dx-c-button-horizontal-spacing: var(--dx-g-spacing-sm);
34
+ }
@@ -0,0 +1,56 @@
1
+ <template>
2
+ <div if:false={mobile} class="footer-display">
3
+ <dx-button
4
+ if:true={hasBailLink}
5
+ aria-label={bailLabel}
6
+ class="header_bail-link"
7
+ href={bailHref}
8
+ onclick={handleBailClick}
9
+ variant="tertiary"
10
+ icon-symbol="new_window"
11
+ target="_blank"
12
+ >
13
+ {bailLabel}
14
+ </dx-button>
15
+ <dx-dropdown
16
+ if:true={hasLanguages}
17
+ class="footer_lang-dropdown"
18
+ options={languages}
19
+ small
20
+ value-path={langValuePath}
21
+ value={language}
22
+ onchange={onLangChange}
23
+ variant="docoption"
24
+ >
25
+ <dx-button
26
+ aria-label="Select Language"
27
+ variant="inline"
28
+ icon-size="large"
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
+ class="footer_lang-dropdown"
39
+ options={languages}
40
+ small
41
+ value-path={langValuePath}
42
+ value={language}
43
+ onchange={onLangChange}
44
+ variant="docoption"
45
+ >
46
+ <dx-button
47
+ aria-label="Select Language"
48
+ variant="inline"
49
+ icon-size="small"
50
+ icon-symbol="world"
51
+ >
52
+ {languageLabel}
53
+ </dx-button>
54
+ </dx-dropdown>
55
+ </div>
56
+ </template>
@@ -0,0 +1,109 @@
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 ContentLayout 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
+ if (this._language !== value) {
31
+ this._language = value;
32
+ }
33
+ }
34
+
35
+ private _languages!: OptionWithLink[];
36
+ private _language: string | null = null;
37
+ private mobile: boolean = false;
38
+ private matchMedia!: MediaQueryList;
39
+
40
+ private get hasLanguages(): boolean {
41
+ return !!(this.languages && this.languages.length > 1);
42
+ }
43
+
44
+ private get languageLabel(): string {
45
+ return (
46
+ (this.language &&
47
+ this.languages.find(
48
+ (lang) => get(lang, this.langValuePath) === this.language
49
+ )?.label) ||
50
+ this.languages[0].label
51
+ );
52
+ }
53
+
54
+ get hasBailLink(): boolean {
55
+ return !!(this.bailHref && this.bailLabel);
56
+ }
57
+
58
+ private onLangChange(event: CustomEvent<string>): void {
59
+ const { detail } = event;
60
+ this._language = detail;
61
+
62
+ this.dispatchEvent(
63
+ new CustomEvent("langchange", {
64
+ detail,
65
+ bubbles: true,
66
+ composed: true
67
+ })
68
+ );
69
+ }
70
+
71
+ private getFilename = function (path: string) {
72
+ return path.substring(path.lastIndexOf("/") + 1);
73
+ };
74
+
75
+ private handleBailClick(event: Event) {
76
+ const payload = {
77
+ click_text: "pdf",
78
+ click_url: this.bailHref,
79
+ element_title: "pdf",
80
+ element_type: "link",
81
+ content_category: "download"
82
+ };
83
+ track(event.target!, "custEv_pdfDownload", {
84
+ ...payload,
85
+ file_name: this.getFilename(this.bailHref!),
86
+ file_extension: "pdf"
87
+ });
88
+
89
+ track(event.target!, "custEv_linkClick", {
90
+ ...payload
91
+ });
92
+ }
93
+
94
+ connectedCallback() {
95
+ this.matchMedia = window.matchMedia(
96
+ `(max-width: ${MOBILE_SIZE_MATCH})`
97
+ );
98
+ this.onMediaChange(this.matchMedia);
99
+ this.matchMedia.addEventListener("change", this.onMediaChange);
100
+ }
101
+
102
+ disconnectedCallback() {
103
+ this.matchMedia.removeEventListener("change", this.onMediaChange);
104
+ }
105
+
106
+ private onMediaChange = (event: MediaQueryListEvent | MediaQueryList) => {
107
+ this.mobile = event.matches;
108
+ };
109
+ }
@@ -59,14 +59,14 @@ export type ApiDocLanguage = {
59
59
  url: string;
60
60
  };
61
61
 
62
- export interface Header extends Element {
62
+ export type SiderbarFooter = {
63
63
  subtitle: string;
64
64
  bailHref: string;
65
65
  bailLabel: string;
66
66
  languages: Array<DocLanguage>;
67
67
  language?: string;
68
68
  headerHref: string;
69
- }
69
+ };
70
70
 
71
71
  export type ApiNavItem = {
72
72
  children: Array<ApiNavItem>;
@@ -11,6 +11,11 @@
11
11
  sidebar-value={sidebarValue}
12
12
  onselect={handleSelect}
13
13
  use-old-sidebar={useOldSidebar}
14
+ onlangchange={handleLanguageChange}
15
+ languages={sidebarFooterContent.languages}
16
+ language={sidebarFooterContent.language}
17
+ bail-href={sidebarFooterContent.bailHref}
18
+ bail-label={sidebarFooterContent.bailLabel}
14
19
  >
15
20
  <doc-phase
16
21
  slot="version-banner"
@@ -7,7 +7,7 @@ import {
7
7
  DocLanguage,
8
8
  DocVersion,
9
9
  TreeNode,
10
- Header,
10
+ SiderbarFooter,
11
11
  HistoryState,
12
12
  PageReference,
13
13
  TocMap
@@ -16,7 +16,6 @@ import { SearchSyncer } from "docUtils/searchSyncer";
16
16
  import { LightningElementWithState } from "dxBaseElements/lightningElementWithState";
17
17
  import { logCoveoPageView, oldVersionDocInfo } from "docUtils/utils";
18
18
  import { Breadcrumb, DocPhaseInfo, Language } from "typings/custom";
19
- import { track as trackGTM } from "dxUtils/analytics";
20
19
 
21
20
  // TODO: Imitating from actual implementation as doc-content use it like this. We should refactor it later.
22
21
  const handleContentError = (error: any): void => console.log(error);
@@ -26,6 +25,14 @@ const PIXEL_PER_CHARACTER_MAP: { [key: string]: number } = {
26
25
  "ja-jp": 12.5
27
26
  };
28
27
 
28
+ const defaultSidebarFooter: SiderbarFooter = {
29
+ subtitle: "",
30
+ bailHref: "",
31
+ bailLabel: "",
32
+ languages: [],
33
+ language: "",
34
+ headerHref: ""
35
+ };
29
36
  export default class DocXmlContent extends LightningElementWithState<{
30
37
  isFetchingDocument: boolean;
31
38
  isFetchingContent: boolean;
@@ -70,9 +77,9 @@ export default class DocXmlContent extends LightningElementWithState<{
70
77
  private version: DocVersion | null = null;
71
78
  private docTitle = "";
72
79
  private _pathName = "";
73
- private _pageHeader?: Header;
74
80
  private listenerAttached = false;
75
81
  private _enableCoveo?: boolean = false;
82
+ private sidebarFooterContent: SiderbarFooter = { ...defaultSidebarFooter };
76
83
 
77
84
  private searchSyncer = new SearchSyncer({
78
85
  callbacks: {
@@ -214,13 +221,6 @@ export default class DocXmlContent extends LightningElementWithState<{
214
221
  disconnectedCallback(): void {
215
222
  window.removeEventListener("popstate", this.handlePopState);
216
223
  this.searchSyncer.dispose();
217
- if (this.listenerAttached) {
218
- this.pageHeader.removeEventListener(
219
- "langchange",
220
- this.handleLanguageChange
221
- );
222
- this.listenerAttached = false;
223
- }
224
224
  }
225
225
 
226
226
  private get languageId(): string | undefined {
@@ -268,14 +268,6 @@ export default class DocXmlContent extends LightningElementWithState<{
268
268
  return config;
269
269
  }
270
270
 
271
- private get pageHeader(): Header {
272
- if (!this._pageHeader) {
273
- this._pageHeader = document.querySelector("doc-header")!;
274
- }
275
-
276
- return this._pageHeader;
277
- }
278
-
279
271
  private get sidebarValue(): string {
280
272
  if (this.pageReference?.contentDocumentId) {
281
273
  const hashedUri = `${
@@ -371,17 +363,6 @@ export default class DocXmlContent extends LightningElementWithState<{
371
363
  ({ id }) => id === event.detail
372
364
  );
373
365
  this.pageReference.docId = this.language!.url;
374
-
375
- trackGTM(event.target!, "custEv_ctaLinkClick", {
376
- click_text: event.detail,
377
- element_title: "language selector",
378
- click_url: `${window.location.origin}${this.pageReferenceToString(
379
- this.pageReference
380
- )}`,
381
- element_type: "link",
382
- content_category: "cta"
383
- });
384
-
385
366
  this.updateUrl();
386
367
  this.fetchDocument();
387
368
  };
@@ -469,7 +450,7 @@ export default class DocXmlContent extends LightningElementWithState<{
469
450
  this.availableVersions = data.availableVersions;
470
451
  this.pdfUrl = data.pdfUrl;
471
452
 
472
- this.updateHeader();
453
+ this.updateSidebarFooter();
473
454
 
474
455
  this.buildBreadcrumbs();
475
456
 
@@ -533,34 +514,22 @@ export default class DocXmlContent extends LightningElementWithState<{
533
514
  });
534
515
  }
535
516
 
536
- updateHeader(): void {
537
- if (!this.pageHeader) {
538
- return;
539
- }
540
-
517
+ updateSidebarFooter(): void {
541
518
  if (this.docTitle) {
542
- this.pageHeader.subtitle = this.docTitle;
519
+ this.sidebarFooterContent.subtitle = this.docTitle;
543
520
  }
544
521
 
545
522
  if (this.pdfUrl) {
546
- this.pageHeader.bailHref = this.pdfUrl;
547
- this.pageHeader.bailLabel = "PDF";
548
- }
549
-
550
- if (!this.listenerAttached) {
551
- this.pageHeader.addEventListener(
552
- "langchange",
553
- this.handleLanguageChange
554
- );
555
- this.listenerAttached = true;
523
+ this.sidebarFooterContent.bailHref = this.pdfUrl;
524
+ this.sidebarFooterContent.bailLabel = "PDF";
556
525
  }
557
526
 
558
- this.pageHeader.languages = this.availableLanguages;
559
- this.pageHeader.language = this.language?.id;
527
+ this.sidebarFooterContent.languages = this.availableLanguages;
528
+ this.sidebarFooterContent.language = this.language?.id;
560
529
 
561
530
  if (this.pageReference) {
562
531
  const { docId, deliverable, page } = this.pageReference;
563
- this.pageHeader.headerHref = `/${page}/${docId}/${deliverable}/`;
532
+ this.sidebarFooterContent.headerHref = `/${page}/${docId}/${deliverable}/`;
564
533
  }
565
534
  }
566
535