@salesforcedevs/docs-components 1.3.221 → 1.3.227-dh-alpha1

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
@@ -17,6 +17,7 @@
17
17
  "doc/headingAnchor",
18
18
  "doc/overview",
19
19
  "doc/phase",
20
+ "doc/versionPicker",
20
21
  "doc/xmlContent",
21
22
  "docUtils/utils"
22
23
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforcedevs/docs-components",
3
- "version": "1.3.221",
3
+ "version": "1.3.227-dh-alpha1",
4
4
  "description": "Docs Lightning web components for DSC",
5
5
  "license": "MIT",
6
6
  "main": "index.js",
@@ -24,5 +24,5 @@
24
24
  "@types/lodash.orderby": "^4.6.7",
25
25
  "@types/lodash.uniqby": "^4.7.7"
26
26
  },
27
- "gitHead": "eca6f0494621686d4b7c408a316e8b230b09b6dc"
27
+ "gitHead": "4629fdd9ca18a13480044ad43515b91945d16aad"
28
28
  }
@@ -22,11 +22,3 @@ doc-phase:nth-child(2) {
22
22
  .api-documentation {
23
23
  margin-top: 48px;
24
24
  }
25
-
26
- .version-picker {
27
- margin-left: auto;
28
- }
29
-
30
- .version-picker-text {
31
- border-bottom: 1px dashed var(--dx-g-blue-vibrant-50);
32
- }
@@ -1,5 +1,6 @@
1
1
  <template>
2
2
  <doc-content-layout
3
+ if:true={isVersionFetched}
3
4
  use-old-sidebar={useOldSidebar}
4
5
  class="content-type content-type-reference"
5
6
  coveo-organization-id={coveoOrganizationId}
@@ -16,6 +17,8 @@
16
17
  toc-title={tocTitle}
17
18
  toc-options={tocOptions}
18
19
  enable-slot-change="true"
20
+ languages={languages}
21
+ language={language}
19
22
  >
20
23
  <doc-phase
21
24
  slot="doc-phase"
@@ -30,20 +33,14 @@
30
33
  dismissible="true"
31
34
  ondismissphase={handleDismissVersionBanner}
32
35
  ></doc-phase>
33
- <div slot="sidebar-header" class="version-picker">
34
- <template if:true={isVersionEnabled}>
35
- <dx-dropdown
36
- onchange={handleVersionChange}
37
- data-type="version"
38
- options={versions}
39
- value={selectedVersion.id}
40
- width="290px"
41
- >
42
- <dx-button variant="inline" class="version-picker-text">
43
- {selectedVersion.id}
44
- </dx-button>
45
- </dx-dropdown>
46
- </template>
36
+ <div if:true={isVersionEnabled} slot="sidebar-header">
37
+ <doc-version-picker
38
+ onchange={handleVersionChange}
39
+ data-type="version"
40
+ versions={versions}
41
+ selected-version={selectedVersion}
42
+ latest-version={latestVersion}
43
+ ></doc-version-picker>
47
44
  </div>
48
45
  <template if:false={showSpecBasedReference}>
49
46
  <slot></slot>
@@ -3,7 +3,8 @@ import { noCase } from "no-case";
3
3
  import { sentenceCase } from "sentence-case";
4
4
  import qs from "query-string";
5
5
  import { AmfModelParser } from "doc/amfModelParser";
6
- import { normalizeBoolean } from "dxUtils/normalizers";
6
+ import { normalizeBoolean, toJson } from "dxUtils/normalizers";
7
+ import type { OptionWithLink } from "typings/custom";
7
8
  import type {
8
9
  AmfConfig,
9
10
  AmfMetadataTopic,
@@ -43,14 +44,16 @@ export default class AmfReference extends LightningElement {
43
44
  @api coveoOrganizationId!: string;
44
45
  @api coveoPublicAccessToken!: string;
45
46
  @api coveoAnalyticsToken!: string;
46
- @api coveoAdvancedQueryConfig!: string;
47
47
  @api coveoSearchHub!: string;
48
48
  @api useOldSidebar: boolean = false;
49
49
  @api tocTitle?: string;
50
50
  @api tocOptions?: string;
51
+ @api languages!: OptionWithLink[];
52
+ @api language!: string;
51
53
  @track navigation = [] as NavigationItem[];
52
54
  @track versions: Array<ReferenceVersion> = [];
53
55
  @track showVersionBanner = false;
56
+ @track _coveoAdvancedQueryConfig!: { [key: string]: any };
54
57
 
55
58
  // Update this to update what component gets rendered in the content block
56
59
  @track
@@ -114,12 +117,16 @@ export default class AmfReference extends LightningElement {
114
117
  this.versions = this.getVersions();
115
118
  }
116
119
  this.selectedVersion = selectedVersion;
117
- if (
118
- this.isSpecBasedReference(this._currentReferenceId) &&
119
- this.oldVersionInfo
120
- ) {
121
- this.showVersionBanner = true;
120
+ if (this.isSpecBasedReference(this._currentReferenceId)) {
121
+ this.isVersionFetched = true;
122
+ if (this.oldVersionInfo) {
123
+ this.showVersionBanner = true;
124
+ } else {
125
+ this.latestVersion = true;
126
+ }
122
127
  }
128
+ } else {
129
+ this.isVersionFetched = true;
123
130
  }
124
131
 
125
132
  // This is to check if the url is hash based and redirect if needed
@@ -152,6 +159,31 @@ export default class AmfReference extends LightningElement {
152
159
  this._expandChildren = normalizeBoolean(value);
153
160
  }
154
161
 
162
+ /*
163
+ * The get coveoAdvancedQueryConfig() method returns this._coveoAdvancedQueryConfig,
164
+ * but before returning it, it checks if there are multiple versions (this.versions.length > 1)
165
+ * and if a version is selected (this.selectedVersion). If both conditions are met,
166
+ * it updates the version property of this._coveoAdvancedQueryConfig with the selected version.
167
+ */
168
+ @api
169
+ get coveoAdvancedQueryConfig(): { [key: string]: any } {
170
+ const coveoConfig = this._coveoAdvancedQueryConfig;
171
+ if (this.versions.length > 1 && this.selectedVersion) {
172
+ const currentGAVersionRef = this.versions[0];
173
+ if (this.selectedVersion.id !== currentGAVersionRef.id) {
174
+ // Currently Coveo only supports query without "v"
175
+ const version = this.selectedVersion.id.replace("v", "");
176
+ coveoConfig.version = version;
177
+ this._coveoAdvancedQueryConfig = coveoConfig;
178
+ }
179
+ }
180
+ return this._coveoAdvancedQueryConfig;
181
+ }
182
+
183
+ set coveoAdvancedQueryConfig(config) {
184
+ this._coveoAdvancedQueryConfig = toJson(config);
185
+ }
186
+
155
187
  // model
156
188
  protected _amfConfigList: AmfConfig[] = [];
157
189
  protected _amfConfigMap: Map<string, AmfConfig> = new Map();
@@ -172,6 +204,8 @@ export default class AmfReference extends LightningElement {
172
204
  private isParentLevelDocPhaseEnabled = false;
173
205
  private selectedReferenceDocPhase?: string | null = null;
174
206
  private _expandChildren?: boolean = false;
207
+ private isVersionFetched = false;
208
+ private latestVersion = false;
175
209
 
176
210
  /**
177
211
  * Key for storing the currently selected reference url. This will be used to save the
@@ -1282,8 +1316,11 @@ export default class AmfReference extends LightningElement {
1282
1316
  this.versions = this.getVersions();
1283
1317
  if (this.oldVersionInfo) {
1284
1318
  this.showVersionBanner = true;
1319
+ } else {
1320
+ this.latestVersion = true;
1285
1321
  }
1286
1322
 
1323
+ this.isVersionFetched = true;
1287
1324
  this.updateDocPhase();
1288
1325
  this.selectedSidebarValue = window.location.pathname;
1289
1326
  }
@@ -22,7 +22,7 @@ doc-breadcrumbs {
22
22
 
23
23
  dx-sidebar,
24
24
  dx-sidebar-old {
25
- --dx-c-sidebar-vertical-padding: var(--dx-c-content-vertical-spacing);
25
+ --dx-c-sidebar-vertical-padding: var(--dx-g-spacing-md);
26
26
 
27
27
  z-index: calc(var(--dx-g-z-index-100) + 5);
28
28
  }
@@ -54,6 +54,7 @@ dx-toc {
54
54
 
55
55
  .content-body-doc-phase-container {
56
56
  flex: 1;
57
+ border-left: 1px solid var(--dx-g-gray-90);
57
58
  }
58
59
 
59
60
  .content-body-container {
@@ -61,12 +62,16 @@ dx-toc {
61
62
  flex-direction: row;
62
63
  justify-content: center;
63
64
  max-width: var(--dx-g-doc-content-max-width);
65
+
66
+ /* Derived this manually by substracting (topHeader, doc header, banner and the content). */
67
+ min-height: 62vh;
64
68
  margin: auto;
65
69
  padding: 0 var(--dx-g-global-header-padding-horizontal);
70
+ margin-bottom: calc(2 * (var(--dx-g-spacing-5xl) + 4px));
66
71
  }
67
72
 
68
73
  .content-body {
69
- margin: var(--dx-g-spacing-sm) 0 var(--dx-g-spacing-xl);
74
+ margin: var(--dx-g-spacing-sm) 0 0;
70
75
  max-width: 900px;
71
76
  flex: 1;
72
77
  width: 0;
@@ -92,6 +97,10 @@ dx-toc {
92
97
  .content-body {
93
98
  margin-top: var(--dx-c-content-vertical-spacing);
94
99
  }
100
+
101
+ .content-body-doc-phase-container {
102
+ border-left: 0;
103
+ }
95
104
  }
96
105
 
97
106
  @media screen and (max-width: 768px) {
@@ -106,6 +115,7 @@ dx-toc {
106
115
  .content-body-container {
107
116
  padding-right: 0;
108
117
  overflow-x: auto;
118
+ margin-bottom: calc(var(--dx-g-spacing-5xl) + 4px);
109
119
  }
110
120
 
111
121
  .left-nav-bar {
@@ -7,8 +7,12 @@
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
- <slot name="sidebar-header" slot="header"></slot>
15
+ <slot name="sidebar-header" slot="version-picker"></slot>
12
16
  </dx-sidebar-old>
13
17
  </template>
14
18
  <template if:false={useOldSidebar}>
@@ -22,8 +26,12 @@
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
- <slot name="sidebar-header" slot="header"></slot>
34
+ <slot name="sidebar-header" slot="version-picker"></slot>
27
35
  </dx-sidebar>
28
36
  </template>
29
37
  <div class="content-body-doc-phase-container">
@@ -48,6 +56,9 @@
48
56
  ></dx-toc>
49
57
  </div>
50
58
  </div>
59
+ <div class="footer-container">
60
+ <dx-footer variant="no-signup"></dx-footer>
61
+ </div>
51
62
  </div>
52
63
  </div>
53
64
  </template>
@@ -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() {
@@ -16,44 +16,36 @@ dx-logo {
16
16
  );
17
17
  }
18
18
 
19
+ .has-brand.has-scoped-nav-items {
20
+ border-bottom: 1px solid var(--dx-g-gray-90);
21
+ border-top: 1px solid var(--dx-g-gray-90);
22
+ }
23
+
19
24
  .nav_menu-ctas {
20
25
  margin-right: var(--dx-g-spacing-sm);
21
26
  }
22
27
 
23
28
  header:not(.has-brand) > .header_l1 {
24
- background: var(--dx-g-brand-current-color-background);
29
+ background: white;
30
+ border-bottom: 1px solid var(--dx-g-gray-90);
25
31
  }
26
32
 
27
33
  header:not(.has-brand) > .header_l2 {
28
- background: var(--dx-g-brand-current-color-background-2);
34
+ border-bottom: 1px solid var(--dx-g-gray-90);
35
+ border-top: 1px solid var(--dx-g-gray-90);
29
36
  }
30
37
 
31
38
  .header_l2_group.header_l2_group-right-ctas {
32
39
  align-items: baseline;
33
40
  }
34
41
 
35
- .header_bail-link {
36
- --dx-c-button-horizontal-spacing: var(--dx-g-spacing-sm);
37
-
38
- margin-left: var(--dx-g-spacing-sm);
39
- }
40
-
41
- .header_lang-dropdown {
42
- --button-primary-color: var(--dx-g-blue-vibrant-40);
43
- --button-primary-color-hover: var(--dx-g-blue-vibrant-30);
44
- }
45
-
46
- .header_lang-dropdown > dx-button {
47
- --dx-c-button-primary-color: var(--button-primary-color);
48
- --dx-c-button-primary-color-hover: var(--button-primary-color-hover);
49
- --dx-c-slot-empty-width: min-content;
50
- --border-color: var(--button-primary-color);
51
-
52
- border-bottom: 1px dashed var(--border-color);
42
+ .has-brand .header_l2_group-title {
43
+ padding: var(--dx-g-spacing-smd) var(--dx-g-spacing-xl)
44
+ calc(var(--dx-g-spacing-smd - 1px)) 0;
53
45
  }
54
46
 
55
- .header_lang-dropdown > dx-button:hover {
56
- --border-color: var(--button-primary-color-hover);
47
+ .no-header-content {
48
+ border-top: 1px solid var(--dx-g-gray-90);
57
49
  }
58
50
 
59
51
  @media (max-width: 768px) {
@@ -71,37 +63,41 @@ header:not(.has-brand) > .header_l2 {
71
63
  width: 100%;
72
64
  }
73
65
 
66
+ .header_l2_group-title {
67
+ margin-right: 0;
68
+ padding: var(--dx-g-spacing-sm) 0 2px
69
+ var(--dx-g-global-header-padding-horizontal);
70
+ min-height: var(--dx-g-doc-header-main-nav-height);
71
+ }
72
+
74
73
  .header_l2_group-nav {
75
74
  height: var(--dx-g-spacing-3xl);
76
75
  padding: 0;
77
- padding-left: var(--dx-g-spacing-sm);
76
+ margin-top: calc(var(--dx-g-spacing-2xs) + 1px);
78
77
  }
79
78
 
80
79
  .header_l2_group-nav_overflow {
81
- height: 48px;
80
+ height: var(--dx-g-spacing-3xl);
82
81
  margin-right: var(--dx-g-spacing-sm);
83
82
  }
84
83
 
85
- .header_l2_group-title {
86
- margin-right: 0;
87
- padding: var(--dx-g-spacing-smd)
88
- var(--dx-g-global-header-padding-horizontal);
89
- min-height: var(--dx-g-doc-header-main-nav-height);
90
- }
91
-
92
- .header_l2_group-title .header_lang-dropdown {
93
- margin-left: auto;
84
+ .subtitle {
85
+ font-weight: var(--dx-g-font-demi);
86
+ letter-spacing: -0.08px;
94
87
  }
95
88
 
96
- .header_lang-dropdown > dx-button {
97
- padding: var(--dx-g-spacing-2xs) 0;
89
+ .has-brand .header_l2_group-title {
90
+ margin-right: 0;
91
+ padding: var(--dx-g-spacing-sm) 0 var(--dx-g-spacing-2xs)
92
+ var(--dx-g-global-header-padding-horizontal);
98
93
  }
99
94
 
100
95
  .has-scoped-nav-items > .header_l2 {
101
96
  height: unset;
102
97
  }
103
98
 
104
- .has-scoped-nav-items .header_l2_group-title {
105
- border-bottom: 1px solid var(--dx-g-brand-current-color-border-2);
99
+ header:not(.has-brand) > .header_l2 {
100
+ padding-bottom: 0;
101
+ border: 0;
106
102
  }
107
103
  }
@@ -14,28 +14,12 @@
14
14
  if:true={isValidBrand}
15
15
  sprite="salesforcebrand"
16
16
  symbol={brand}
17
- size="xlarge"
17
+ size="large"
18
18
  ></dx-icon>
19
- <span class="subtitle dx-text-display-6">
19
+ <span class="subtitle dx-text-display-7">
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,43 +36,11 @@
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>
93
42
  </template>
43
+ <template if:true={showDocDivider}>
44
+ <div class="no-header-content"></div>
45
+ </template>
94
46
  </template>
@@ -1,14 +1,11 @@
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
- const MOBILE_MATCH = "880px";
11
- const SMALL_MOBILE_MATCH = "768px";
8
+ const MOBILE_MATCH = "768px";
12
9
 
13
10
  export default class Header extends HeaderBase {
14
11
  @api langValuePath: string = "id"; // allows to override how language property is interpreted, follows valuePath dropdown api.
@@ -23,34 +20,11 @@ export default class Header extends HeaderBase {
23
20
  this._scopedNavItems = toJson(value);
24
21
  }
25
22
 
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
23
  private _scopedNavItems!: OptionWithNested[];
49
- private smallMobile = false;
50
- private smallMobileMatchMedia!: MediaQueryList;
51
24
  private tablet = false;
52
25
  private tabletMatchMedia!: MediaQueryList;
53
- private shouldRender = false;
26
+ private shouldRender: boolean = false;
27
+ private showDocDivider: boolean = false;
54
28
 
55
29
  protected mobileBreakpoint(): string {
56
30
  return MOBILE_MATCH;
@@ -60,24 +34,6 @@ export default class Header extends HeaderBase {
60
34
  return this.scopedNavItems && this.scopedNavItems.length > 0;
61
35
  }
62
36
 
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
37
  connectedCallback(): void {
82
38
  super.connectedCallback();
83
39
  this.tabletMatchMedia = window.matchMedia(
@@ -86,14 +42,6 @@ export default class Header extends HeaderBase {
86
42
  this.onTabletChange(this.tabletMatchMedia);
87
43
  this.tabletMatchMedia.addEventListener("change", this.onTabletChange);
88
44
 
89
- this.smallMobileMatchMedia = window.matchMedia(
90
- `(max-width: ${SMALL_MOBILE_MATCH})`
91
- );
92
- this.onSmallMobileChange(this.smallMobileMatchMedia);
93
- this.smallMobileMatchMedia.addEventListener(
94
- "change",
95
- this.onSmallMobileChange
96
- );
97
45
  if (
98
46
  (window.location.pathname.includes("/docs/") &&
99
47
  window.location.pathname !== "/docs/apis") ||
@@ -104,6 +52,13 @@ export default class Header extends HeaderBase {
104
52
  ) {
105
53
  this.shouldRender = true;
106
54
  }
55
+
56
+ if (this.shouldRender && window.location.pathname.includes("/docs/")) {
57
+ if (!this.brand && !this.mobile) {
58
+ this.shouldRender = false;
59
+ this.showDocDivider = true;
60
+ }
61
+ }
107
62
  }
108
63
 
109
64
  disconnectedCallback(): void {
@@ -112,53 +67,15 @@ export default class Header extends HeaderBase {
112
67
  "change",
113
68
  this.onTabletChange
114
69
  );
115
-
116
- this.smallMobileMatchMedia.removeEventListener(
117
- "change",
118
- this.onSmallMobileChange
119
- );
120
70
  }
121
71
 
122
72
  private onTabletChange = (e: MediaQueryListEvent | MediaQueryList) =>
123
73
  (this.tablet = e.matches);
124
74
 
125
- private onSmallMobileChange = (e: MediaQueryListEvent | MediaQueryList) =>
126
- (this.smallMobile = e.matches);
127
-
128
75
  protected additionalClasses(): string {
129
76
  return cx(
130
77
  this.brand && "has-brand",
131
78
  this.hasScopedNavItems && "has-scoped-nav-items"
132
79
  );
133
80
  }
134
-
135
- private onLangChange(event: CustomEvent<string>): void {
136
- const { detail } = event;
137
- this._language = detail;
138
-
139
- this.dispatchEvent(new CustomEvent("langchange", { detail }));
140
- }
141
-
142
- private handleBailClick(event: Event) {
143
- const payload = {
144
- click_text: "pdf",
145
- click_url: this.bailHref,
146
- element_title: "pdf",
147
- element_type: "link",
148
- content_category: "download"
149
- };
150
- track(event.target!, "custEv_pdfDownload", {
151
- ...payload,
152
- file_name: this.getFilename(this.bailHref!),
153
- file_extension: "pdf"
154
- });
155
-
156
- track(event.target!, "custEv_linkClick", {
157
- ...payload
158
- });
159
- }
160
-
161
- private getFilename = function (path: string) {
162
- return path.substring(path.lastIndexOf("/") + 1);
163
- };
164
81
  }
@@ -0,0 +1,64 @@
1
+ @import "dxHelpers/reset";
2
+
3
+ /* NOTE: doc-version-picker-width width variable is used by both dx-button and dx-dropdown to maintain a consistent width. */
4
+ :host {
5
+ --dx-c-dropdown-option-font-weight: normal;
6
+ --dx-c-dropdown-option-label-color: var(--dx-g-gray-10);
7
+ --popover-container-open-transform: translateY(4px);
8
+ }
9
+
10
+ .version-picker-container {
11
+ padding: 8px var(--dx-g-spacing-lg) 8px
12
+ var(--dx-g-global-header-padding-horizontal);
13
+ border-top: 1px solid var(--dx-g-gray-90);
14
+ border-bottom: 1px solid var(--dx-g-gray-90);
15
+ }
16
+
17
+ .version-picker-button {
18
+ display: flex;
19
+ width: var(--doc-version-picker-width, 296px);
20
+ }
21
+
22
+ .version-picker-button:hover,
23
+ .version-picker-button:active,
24
+ .version-picker-button:focus {
25
+ --dx-c-button-secondary-color-hover: var(--dx-g-cloud-blue-vibrant-95);
26
+ --dx-c-button-primary-color: var(--dx-g-blue-vibrant-40);
27
+ }
28
+
29
+ /**
30
+ * NOTE: This CSS ensures the span inside the button stays within the parent's width, avoiding overflow.
31
+ * Not keeping this in common component to ensure that existing functionality works as it is.
32
+ */
33
+ dx-button::part(content) {
34
+ width: inherit;
35
+ overflow: hidden;
36
+ }
37
+
38
+ .selected-version {
39
+ display: flex;
40
+ flex-direction: row;
41
+ align-items: center;
42
+ }
43
+
44
+ .selected-version-label {
45
+ flex: 1;
46
+ overflow: hidden;
47
+ text-align: left;
48
+ text-overflow: ellipsis;
49
+ white-space: nowrap;
50
+ }
51
+
52
+ dx-type-badge.latest-badge {
53
+ --dx-c-type-badge-color: var(--dx-g-green-vibrant-40);
54
+ --dx-c-type-badge-background: var(--dx-g-green-vibrant-95);
55
+
56
+ margin-left: var(--dx-g-spacing-sm);
57
+ }
58
+
59
+ dx-type-badge.not-latest-badge {
60
+ --dx-c-type-badge-color: var(--dx-g-red-vibrant-40);
61
+ --dx-c-type-badge-background: var(--dx-g-red-vibrant-95);
62
+
63
+ margin-left: var(--dx-g-spacing-sm);
64
+ }
@@ -0,0 +1,37 @@
1
+ <template>
2
+ <div if:true={showVersionPicker} class="version-picker-container">
3
+ <dx-dropdown
4
+ options={versions}
5
+ value={selectedVersion.id}
6
+ width="var(--doc-version-picker-width)"
7
+ >
8
+ <dx-button
9
+ class="version-picker-button"
10
+ variant="tertiary"
11
+ size="small"
12
+ icon-symbol="chevrondown"
13
+ icon-size="medium"
14
+ >
15
+ <div class="selected-version">
16
+ <p class="selected-version-label">
17
+ {selectedVersion.label}
18
+ </p>
19
+ <template if:false={hideBadge}>
20
+ <dx-type-badge
21
+ class="latest-badge"
22
+ if:true={latestVersion}
23
+ value="Latest"
24
+ size="small"
25
+ ></dx-type-badge>
26
+ <dx-type-badge
27
+ class="not-latest-badge"
28
+ if:false={latestVersion}
29
+ value="Not Latest"
30
+ size="small"
31
+ ></dx-type-badge>
32
+ </template>
33
+ </div>
34
+ </dx-button>
35
+ </dx-dropdown>
36
+ </div>
37
+ </template>
@@ -0,0 +1,57 @@
1
+ import { LightningElement, api } from "lwc";
2
+
3
+ import { AnalyticsPayload, OptionWithNested } from "typings/custom";
4
+
5
+ import { toJson, normalizeBoolean } from "dxUtils/normalizers";
6
+
7
+ export default class VersionPicker extends LightningElement {
8
+ @api analyticsEvent?: string;
9
+ @api analyticsPayload?: AnalyticsPayload;
10
+
11
+ private _versions!: OptionWithNested[];
12
+ private _selectedVersion?: OptionWithNested;
13
+ private _latestVersion: boolean = false;
14
+ private _hideBadge: boolean = false;
15
+
16
+ @api
17
+ get versions() {
18
+ return this._versions;
19
+ }
20
+
21
+ set versions(value: OptionWithNested[]) {
22
+ this._versions = toJson(value);
23
+ }
24
+
25
+ @api
26
+ get selectedVersion(): OptionWithNested | undefined {
27
+ return this._selectedVersion || this.versions[0];
28
+ }
29
+
30
+ set selectedVersion(value: OptionWithNested) {
31
+ if (value) {
32
+ this._selectedVersion = toJson(value);
33
+ }
34
+ }
35
+
36
+ @api
37
+ get latestVersion() {
38
+ return this._latestVersion;
39
+ }
40
+
41
+ set latestVersion(value) {
42
+ this._latestVersion = normalizeBoolean(value);
43
+ }
44
+
45
+ @api
46
+ get hideBadge() {
47
+ return this._hideBadge;
48
+ }
49
+
50
+ set hideBadge(value) {
51
+ this._hideBadge = normalizeBoolean(value);
52
+ }
53
+
54
+ private get showVersionPicker() {
55
+ return this._versions && this._versions.length !== 0;
56
+ }
57
+ }
@@ -61,12 +61,15 @@ export type ApiDocLanguage = {
61
61
 
62
62
  export interface Header extends Element {
63
63
  subtitle: string;
64
+ headerHref: string;
65
+ }
66
+
67
+ export type SiderbarFooter = {
64
68
  bailHref: string;
65
69
  bailLabel: string;
66
70
  languages: Array<DocLanguage>;
67
71
  language?: string;
68
- headerHref: string;
69
- }
72
+ };
70
73
 
71
74
  export type ApiNavItem = {
72
75
  children: Array<ApiNavItem>;
@@ -4,17 +4,8 @@
4
4
  }
5
5
 
6
6
  doc-content-layout {
7
- --dx-c-content-sidebar-sticky-top: calc(
8
- var(--dx-g-global-header-height) +
9
- var(--dx-g-doc-header-main-nav-height)
10
- );
11
- --dx-c-sidebar-height: calc(
12
- 100vh -
13
- calc(
14
- var(--dx-g-global-header-height) +
15
- var(--dx-g-doc-header-main-nav-height)
16
- )
17
- );
7
+ --dx-c-content-sidebar-sticky-top: var(--dx-g-global-header-height);
8
+ --dx-c-sidebar-height: calc(100vh - var(--dx-g-global-header-height));
18
9
  }
19
10
 
20
11
  doc-breadcrumbs {
@@ -40,13 +31,24 @@ dx-dropdown > dx-button:hover {
40
31
  --border-color: var(--button-primary-color-hover);
41
32
  }
42
33
 
43
- .document-pickers {
44
- margin-left: auto;
45
- margin-right: var(--dx-g-spacing-sm);
46
- }
47
-
48
34
  doc-phase {
49
- --doc-c-phase-top: calc(
50
- var(--dx-g-global-header-height) + var(--dx-g-doc-header-height)
51
- );
35
+ --doc-c-phase-top: var(--dx-g-global-header-height);
36
+ }
37
+
38
+ @media screen and (max-width: 768px) {
39
+ doc-content-layout {
40
+ --dx-g-doc-header-main-nav-height: 41px;
41
+ --dx-g-doc-header-height: calc(
42
+ var(--dx-g-doc-header-main-nav-height) + 40px
43
+ );
44
+ --dx-c-content-sidebar-sticky-top: calc(
45
+ var(--dx-g-global-header-height) + var(--dx-g-doc-header-height)
46
+ );
47
+ }
48
+
49
+ doc-phase {
50
+ --doc-c-phase-top: calc(
51
+ var(--dx-g-global-header-height) + var(--dx-g-doc-header-height)
52
+ );
53
+ }
52
54
  }
@@ -6,11 +6,16 @@
6
6
  coveo-analytics-token={coveoAnalyticsToken}
7
7
  coveo-search-hub={coveoSearchHub}
8
8
  coveo-advanced-query-config={coveoAdvancedQueryConfig}
9
- sidebar-header="Pages"
9
+ sidebar-header={docTitle}
10
10
  sidebar-content={sidebarContent}
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"
@@ -20,19 +25,16 @@
20
25
  dismissible="true"
21
26
  ondismissphase={handleDismissVersionBanner}
22
27
  ></doc-phase>
23
- <div slot="sidebar-header" class="document-pickers">
24
- <dx-dropdown
28
+ <div if:false={disableVersion} slot="sidebar-header">
29
+ <doc-version-picker
25
30
  data-type="version"
26
31
  analytics-event="custEv_ctaLinkClick"
27
32
  analytics-payload={ANALYTICS_PAYLOAD}
28
- options={versionOptions}
29
- value={version.id}
30
- width="290px"
31
- >
32
- <dx-button variant="inline" disabled={disableVersion}>
33
- {version.releaseVersion}
34
- </dx-button>
35
- </dx-dropdown>
33
+ versions={versionOptions}
34
+ selected-version={version}
35
+ latest-version={latestVersion}
36
+ hide-badge={previewVersion}
37
+ ></doc-version-picker>
36
38
  </div>
37
39
  <doc-breadcrumbs
38
40
  if:true={showBreadcrumbs}
@@ -8,6 +8,7 @@ import {
8
8
  DocVersion,
9
9
  TreeNode,
10
10
  Header,
11
+ SiderbarFooter,
11
12
  HistoryState,
12
13
  PageReference,
13
14
  TocMap
@@ -26,6 +27,12 @@ const PIXEL_PER_CHARACTER_MAP: { [key: string]: number } = {
26
27
  "ja-jp": 12.5
27
28
  };
28
29
 
30
+ const defaultSidebarFooter: SiderbarFooter = {
31
+ bailHref: "",
32
+ bailLabel: "",
33
+ languages: [],
34
+ language: ""
35
+ };
29
36
  export default class DocXmlContent extends LightningElementWithState<{
30
37
  isFetchingDocument: boolean;
31
38
  isFetchingContent: boolean;
@@ -64,15 +71,18 @@ export default class DocXmlContent extends LightningElementWithState<{
64
71
  private docContent = "";
65
72
  private language?: DocLanguage | null = null;
66
73
  private loaded = false;
74
+ private _pageHeader?: Header;
67
75
  private pdfUrl = "";
68
76
  private tocMap: TocMap = {};
69
77
  private sidebarContent: Array<TreeNode> | null = null;
70
78
  private version: DocVersion | null = null;
71
79
  private docTitle = "";
72
80
  private _pathName = "";
73
- private _pageHeader?: Header;
74
81
  private listenerAttached = false;
75
82
  private _enableCoveo?: boolean = false;
83
+ private sidebarFooterContent: SiderbarFooter = { ...defaultSidebarFooter };
84
+ private latestVersion = false;
85
+ private previewVersion = false;
76
86
 
77
87
  private searchSyncer = new SearchSyncer({
78
88
  callbacks: {
@@ -127,6 +137,10 @@ export default class DocXmlContent extends LightningElementWithState<{
127
137
  try {
128
138
  if (parseFloat(this.version.id) < parseFloat(versionNo)) {
129
139
  info = oldVersionDocInfo(currentGAVersion.link.href);
140
+ } else if (
141
+ parseFloat(this.version.id) > parseFloat(versionNo)
142
+ ) {
143
+ this.previewVersion = true;
130
144
  }
131
145
  } catch (exception) {
132
146
  /* Ideally this use case should not happen, but just added to not to break the page*/
@@ -214,13 +228,6 @@ export default class DocXmlContent extends LightningElementWithState<{
214
228
  disconnectedCallback(): void {
215
229
  window.removeEventListener("popstate", this.handlePopState);
216
230
  this.searchSyncer.dispose();
217
- if (this.listenerAttached) {
218
- this.pageHeader.removeEventListener(
219
- "langchange",
220
- this.handleLanguageChange
221
- );
222
- this.listenerAttached = false;
223
- }
224
231
  }
225
232
 
226
233
  private get languageId(): string | undefined {
@@ -414,12 +421,8 @@ export default class DocXmlContent extends LightningElementWithState<{
414
421
  }
415
422
 
416
423
  getReferenceFromUrl(): PageReference {
417
- const [
418
- page,
419
- docId,
420
- deliverable,
421
- contentDocumentId
422
- ] = window.location.pathname.substr(1).split("/");
424
+ const [page, docId, deliverable, contentDocumentId] =
425
+ window.location.pathname.substr(1).split("/");
423
426
 
424
427
  const { origin: domain, hash, search } = window.location;
425
428
 
@@ -469,7 +472,7 @@ export default class DocXmlContent extends LightningElementWithState<{
469
472
  this.availableVersions = data.availableVersions;
470
473
  this.pdfUrl = data.pdfUrl;
471
474
 
472
- this.updateHeader();
475
+ this.updateHeaderAndSidebarFooter();
473
476
 
474
477
  this.buildBreadcrumbs();
475
478
 
@@ -480,6 +483,8 @@ export default class DocXmlContent extends LightningElementWithState<{
480
483
 
481
484
  if (this.oldVersionInfo) {
482
485
  this.showVersionBanner = true;
486
+ } else {
487
+ this.latestVersion = true;
483
488
  }
484
489
 
485
490
  if (
@@ -533,7 +538,7 @@ export default class DocXmlContent extends LightningElementWithState<{
533
538
  });
534
539
  }
535
540
 
536
- updateHeader(): void {
541
+ updateHeaderAndSidebarFooter(): void {
537
542
  if (!this.pageHeader) {
538
543
  return;
539
544
  }
@@ -543,20 +548,12 @@ export default class DocXmlContent extends LightningElementWithState<{
543
548
  }
544
549
 
545
550
  if (this.pdfUrl) {
546
- this.pageHeader.bailHref = this.pdfUrl;
547
- this.pageHeader.bailLabel = "PDF";
551
+ this.sidebarFooterContent.bailHref = this.pdfUrl;
552
+ this.sidebarFooterContent.bailLabel = "PDF";
548
553
  }
549
554
 
550
- if (!this.listenerAttached) {
551
- this.pageHeader.addEventListener(
552
- "langchange",
553
- this.handleLanguageChange
554
- );
555
- this.listenerAttached = true;
556
- }
557
-
558
- this.pageHeader.languages = this.availableLanguages;
559
- this.pageHeader.language = this.language?.id;
555
+ this.sidebarFooterContent.languages = this.availableLanguages;
556
+ this.sidebarFooterContent.language = this.language?.id;
560
557
 
561
558
  if (this.pageReference) {
562
559
  const { docId, deliverable, page } = this.pageReference;
@@ -581,20 +578,14 @@ export default class DocXmlContent extends LightningElementWithState<{
581
578
  }
582
579
 
583
580
  private updateSearchInput(searchParam: string): void {
584
- (this.template.querySelector(
585
- "doc-content-layout"
586
- ) as any)?.setSidebarInputValue(searchParam);
581
+ (
582
+ this.template.querySelector("doc-content-layout") as any
583
+ )?.setSidebarInputValue(searchParam);
587
584
  }
588
585
 
589
586
  private pageReferenceToString(reference: PageReference): string {
590
- const {
591
- page,
592
- docId,
593
- deliverable,
594
- contentDocumentId,
595
- hash,
596
- search
597
- } = reference;
587
+ const { page, docId, deliverable, contentDocumentId, hash, search } =
588
+ reference;
598
589
  return `/${page}/${docId}/${deliverable}/${contentDocumentId}${this.normalizeSearch(
599
590
  search!
600
591
  )}${this.normalizeHash(hash)}`;
package/LICENSE DELETED
@@ -1,12 +0,0 @@
1
- Copyright (c) 2020, Salesforce.com, Inc.
2
- All rights reserved.
3
-
4
- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5
-
6
- * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7
-
8
- * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9
-
10
- * Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
11
-
12
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.