@salesforcedevs/docs-components 0.0.0 → 0.0.1-superscript

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.
Files changed (83) hide show
  1. package/lwc.config.json +12 -2
  2. package/package.json +29 -27
  3. package/src/modules/doc/{amfReference/utils.ts → amfModelParser/amfModelParser.ts} +10 -5
  4. package/src/modules/doc/amfReference/amfReference.css +11 -3
  5. package/src/modules/doc/amfReference/amfReference.html +35 -26
  6. package/src/modules/doc/amfReference/amfReference.ts +239 -95
  7. package/src/modules/doc/amfReference/types.ts +3 -11
  8. package/src/modules/doc/amfTopic/amfTopic.css +20 -0
  9. package/src/modules/doc/amfTopic/amfTopic.ts +59 -18
  10. package/src/modules/doc/amfTopic/types.ts +15 -13
  11. package/src/modules/doc/amfTopic/utils.ts +12 -6
  12. package/src/modules/doc/breadcrumbItem/breadcrumbItem.ts +17 -10
  13. package/src/modules/doc/breadcrumbs/breadcrumbs.html +6 -9
  14. package/src/modules/doc/breadcrumbs/breadcrumbs.ts +30 -34
  15. package/src/modules/doc/componentPlayground/componentPlayground.css +30 -0
  16. package/src/modules/doc/componentPlayground/componentPlayground.html +20 -0
  17. package/src/modules/doc/componentPlayground/componentPlayground.ts +97 -0
  18. package/src/modules/doc/content/content.css +70 -76
  19. package/src/modules/doc/content/content.html +1 -0
  20. package/src/modules/doc/content/content.ts +24 -46
  21. package/src/modules/doc/contentCallout/contentCallout.css +11 -7
  22. package/src/modules/doc/contentCallout/contentCallout.html +11 -4
  23. package/src/modules/doc/contentCallout/contentCallout.ts +8 -1
  24. package/src/modules/doc/contentLayout/contentLayout.css +1 -98
  25. package/src/modules/doc/contentLayout/contentLayout.html +46 -31
  26. package/src/modules/doc/contentLayout/contentLayout.ts +337 -89
  27. package/src/modules/doc/contentMedia/contentMedia.css +1 -1
  28. package/src/modules/doc/doDont/doDont.css +47 -0
  29. package/src/modules/doc/doDont/doDont.html +27 -0
  30. package/src/modules/doc/doDont/doDont.ts +17 -0
  31. package/src/modules/doc/header/header.css +65 -36
  32. package/src/modules/doc/header/header.html +44 -138
  33. package/src/modules/doc/header/header.ts +62 -74
  34. package/src/modules/doc/heading/heading.css +16 -37
  35. package/src/modules/doc/heading/heading.html +4 -4
  36. package/src/modules/doc/heading/heading.ts +12 -10
  37. package/src/modules/doc/headingAnchor/headingAnchor.css +2 -2
  38. package/src/modules/doc/headingAnchor/headingAnchor.ts +2 -2
  39. package/src/modules/doc/headingContent/headingContent.css +1 -1
  40. package/src/modules/doc/headingContent/headingContent.html +2 -2
  41. package/src/modules/doc/headingContent/headingContent.ts +2 -2
  42. package/src/modules/doc/lwcContentLayout/lwcContentLayout.css +9 -0
  43. package/src/modules/doc/lwcContentLayout/lwcContentLayout.html +64 -0
  44. package/src/modules/doc/lwcContentLayout/lwcContentLayout.ts +269 -0
  45. package/src/modules/doc/overview/overview.css +40 -0
  46. package/src/modules/doc/overview/overview.html +34 -0
  47. package/src/modules/doc/overview/overview.ts +12 -0
  48. package/src/modules/doc/phase/phase.css +11 -3
  49. package/src/modules/doc/phase/phase.html +12 -2
  50. package/src/modules/doc/phase/phase.ts +44 -8
  51. package/src/modules/doc/redocReference/redocReference.css +7 -0
  52. package/src/modules/doc/redocReference/redocReference.html +13 -0
  53. package/src/modules/doc/redocReference/redocReference.ts +425 -0
  54. package/src/modules/doc/specificationContent/specificationContent.css +36 -0
  55. package/src/modules/doc/specificationContent/specificationContent.html +177 -0
  56. package/src/modules/doc/specificationContent/specificationContent.ts +166 -0
  57. package/src/modules/doc/sprigSurvey/sprigSurvey.html +20 -0
  58. package/src/modules/doc/sprigSurvey/sprigSurvey.scoped.css +16 -0
  59. package/src/modules/doc/sprigSurvey/sprigSurvey.ts +16 -0
  60. package/src/modules/doc/superscriptSubscript/superscriptSubscript.html +8 -0
  61. package/src/modules/doc/superscriptSubscript/superscriptSubscript.ts +16 -0
  62. package/src/modules/doc/toc/toc.html +1 -3
  63. package/src/modules/doc/toc/toc.ts +1 -1
  64. package/src/modules/doc/toolbar/toolbar.ts +6 -6
  65. package/src/modules/doc/versionPicker/versionPicker.css +64 -0
  66. package/src/modules/doc/versionPicker/versionPicker.html +40 -0
  67. package/src/modules/doc/versionPicker/versionPicker.ts +65 -0
  68. package/src/modules/doc/xmlContent/types.ts +9 -3
  69. package/src/modules/doc/xmlContent/utils.ts +3 -1
  70. package/src/modules/doc/xmlContent/xmlContent.css +16 -4
  71. package/src/modules/doc/xmlContent/xmlContent.html +36 -21
  72. package/src/modules/doc/xmlContent/xmlContent.ts +295 -120
  73. package/src/modules/docHelpers/amfStyle/amfStyle.css +6 -8
  74. package/src/modules/docHelpers/contentLayoutStyle/contentLayoutStyle.css +162 -0
  75. package/src/modules/docHelpers/imgStyle/imgStyle.css +59 -0
  76. package/src/modules/docHelpers/status/status.css +1 -1
  77. package/src/modules/docUtils/{SearchSyncer/SearchSyncer.ts → searchSyncer/searchSyncer.ts} +1 -0
  78. package/src/modules/docUtils/utils/__mocks__/coveo.analytics.ts +16 -0
  79. package/src/modules/docUtils/utils/coveo.analytics.d.ts +10 -0
  80. package/src/modules/docUtils/utils/utils.ts +32 -0
  81. package/LICENSE +0 -12
  82. package/src/modules/docBaseElements/lightningElementWithState/lightningElementWithState.ts +0 -93
  83. package/src/modules/docHelpers/phaseContentLayout/phaseContentLayout.css +0 -39
@@ -0,0 +1,177 @@
1
+ <template>
2
+ <div class="specification-properties">
3
+ <dx-spinner
4
+ size="large"
5
+ variant="brand"
6
+ class="loader"
7
+ if:true={isLoading}
8
+ ></dx-spinner>
9
+ <dx-error-fallback lwc:if={showError}></dx-error-fallback>
10
+ <dx-error-fallback
11
+ lwc:if={showNoSpecifications}
12
+ title="No specifications to show"
13
+ description="No specifications are available for this component or API module. When specifications are defined, they'll appear here."
14
+ ></dx-error-fallback>
15
+ <template lwc:if={hasAttributes}>
16
+ <doc-heading
17
+ header="Attributes"
18
+ hash="attributes"
19
+ aria-level="2"
20
+ id="attributes"
21
+ ></doc-heading>
22
+ <table>
23
+ <thead>
24
+ <tr>
25
+ <th>Name</th>
26
+ <th>Description</th>
27
+ <th>Type</th>
28
+ <th>Default</th>
29
+ <th>Required</th>
30
+ </tr>
31
+ </thead>
32
+ <tbody>
33
+ <template for:each={attributes} for:item="attribute">
34
+ <tr key={attribute.name}>
35
+ <td>
36
+ <span class="code">
37
+ <template lwc:if={isModelAura}>
38
+ {attribute.name}
39
+ </template>
40
+ <template lwc:else>
41
+ {attribute.nameInKebabCase}
42
+ </template>
43
+ </span>
44
+ </td>
45
+ <td>{attribute.description}</td>
46
+ <td>{attribute.type}</td>
47
+ <td>{attribute.default}</td>
48
+ <td class="icon-cell">
49
+ <template lwc:if={attribute.required}>
50
+ <dx-icon
51
+ symbol="success"
52
+ size="large"
53
+ color="green-vibrant-65"
54
+ class="icon"
55
+ ></dx-icon>
56
+ </template>
57
+ </td>
58
+ </tr>
59
+ </template>
60
+ </tbody>
61
+ </table>
62
+ </template>
63
+
64
+ <template lwc:if={hasMethods}>
65
+ <doc-heading
66
+ header="Methods"
67
+ hash="methods"
68
+ aria-level="2"
69
+ id="methods"
70
+ ></doc-heading>
71
+ <table>
72
+ <thead>
73
+ <tr>
74
+ <th>Name</th>
75
+ <th>Description</th>
76
+ <th>Argument Name</th>
77
+ <th>Argument Type</th>
78
+ <th>Argument Description</th>
79
+ </tr>
80
+ </thead>
81
+ <tbody>
82
+ <template for:each={processedMethods} for:item="method">
83
+ <template lwc:if={method.firstArgument}>
84
+ <tr key={method.name}>
85
+ <td rowspan={method.arguments.length}>
86
+ <span class="code">{method.name}</span>
87
+ </td>
88
+ <td rowspan={method.arguments.length}>
89
+ {method.description}
90
+ </td>
91
+ <td class={method.cssForMultipleArguments}>
92
+ {method.firstArgument.name}
93
+ </td>
94
+ <td>{method.firstArgument.type}</td>
95
+ <td>{method.firstArgument.description}</td>
96
+ </tr>
97
+ <template
98
+ for:each={method.remainingArguments}
99
+ for:item="arg"
100
+ >
101
+ <tr key={arg.name}>
102
+ <td>{arg.name}</td>
103
+ <td>{arg.type}</td>
104
+ <td>{arg.description}</td>
105
+ </tr>
106
+ </template>
107
+ </template>
108
+ <template lwc:else>
109
+ <tr key={method.name}>
110
+ <td>
111
+ <span class="code">{method.name}</span>
112
+ </td>
113
+ <td>{method.description}</td>
114
+ <td colspan="3"></td>
115
+ </tr>
116
+ </template>
117
+ </template>
118
+ </tbody>
119
+ </table>
120
+ </template>
121
+
122
+ <template lwc:if={hasSlots}>
123
+ <doc-heading
124
+ header="Slots"
125
+ hash="slots"
126
+ aria-level="2"
127
+ id="slots"
128
+ ></doc-heading>
129
+ <table>
130
+ <thead>
131
+ <tr>
132
+ <th>Name</th>
133
+ <th>Description</th>
134
+ </tr>
135
+ </thead>
136
+ <tbody>
137
+ <template for:each={slots} for:item="slot">
138
+ <tr key={slot.name}>
139
+ <td>
140
+ <span class="code">{slot.nameInKebabCase}</span>
141
+ </td>
142
+ <td>{slot.description}</td>
143
+ </tr>
144
+ </template>
145
+ </tbody>
146
+ </table>
147
+ </template>
148
+
149
+ <template lwc:if={hasEvents}>
150
+ <doc-heading
151
+ header="Events"
152
+ hash="events"
153
+ aria-level="2"
154
+ ></doc-heading>
155
+ <table>
156
+ <thead>
157
+ <tr>
158
+ <th>Name</th>
159
+ <th>Description</th>
160
+ </tr>
161
+ </thead>
162
+ <tbody>
163
+ <template for:each={processedEvents} for:item="event">
164
+ <tr key={event.name}>
165
+ <td>
166
+ <span class="code">
167
+ {event.nameCapitalized}
168
+ </span>
169
+ </td>
170
+ <td>{event.description}</td>
171
+ </tr>
172
+ </template>
173
+ </tbody>
174
+ </table>
175
+ </template>
176
+ </div>
177
+ </template>
@@ -0,0 +1,166 @@
1
+ import { LightningElement, track, api } from "lwc";
2
+ import { Method, Specification } from "typings/custom";
3
+ import debounce from "debounce";
4
+
5
+ const CX_ROUTER_API: string = "/cx-router/components";
6
+ export default class SpecificationContent extends LightningElement {
7
+ @track data: any;
8
+
9
+ @api component!: string;
10
+ @api model!: string;
11
+ @api namespace!: string;
12
+
13
+ isLoading: boolean = true;
14
+ showError: boolean = false;
15
+
16
+ private attributes: Specification[] = [];
17
+ private methods: Method[] = [];
18
+ private slots: Specification[] = [];
19
+ private events: Specification[] = [];
20
+ private _processedEvents: Specification[] = [];
21
+
22
+ /* TODO: For now setting the timeout to 300ms,
23
+ * post integration with CX-Router API will test and change if required.
24
+ */
25
+ private debouncedNotifyDataRendered = debounce(() => {
26
+ this.notifySpecificationDataRendered();
27
+ }, 300);
28
+
29
+ connectedCallback() {
30
+ this.fetchComponentMetadata();
31
+ }
32
+
33
+ async fetchComponentMetadata() {
34
+ const componentQueryParams = {
35
+ model: this.model,
36
+ namespace: this.namespace,
37
+ component: this.component
38
+ };
39
+
40
+ const queryString = new URLSearchParams(
41
+ componentQueryParams
42
+ ).toString();
43
+ const url = `${CX_ROUTER_API}?${queryString}`;
44
+
45
+ try {
46
+ const response = await fetch(url);
47
+
48
+ if (!response.ok) {
49
+ // TODO: Will add loader and show error as follow-up
50
+ throw new Error(`Failed to fetch: ${response.statusText}`);
51
+ }
52
+
53
+ const result = await response.json();
54
+
55
+ // Due to middleware the data is sent as part of response now.
56
+ this.data = result?.response;
57
+ if (this.data) {
58
+ ({
59
+ attributes: this.attributes,
60
+ methods: this.methods,
61
+ slots: this.slots,
62
+ events: this.events
63
+ } = this.data);
64
+
65
+ // Process events once when data is set
66
+ this._processedEvents = this.events
67
+ ? this.events.map((event) => {
68
+ const capitalizedName = event.name
69
+ ? event.name.charAt(0).toUpperCase() +
70
+ event.name.slice(1)
71
+ : "";
72
+ return {
73
+ ...event,
74
+ nameCapitalized: capitalizedName
75
+ };
76
+ })
77
+ : [];
78
+ }
79
+ } catch (error) {
80
+ this.data = {};
81
+ this.showError = true;
82
+ console.error("fetchComponentMetadata() failed:", error);
83
+ } finally {
84
+ this.isLoading = false;
85
+ }
86
+ }
87
+
88
+ /**
89
+ * This getter is to preprocess the methods for easier rendering in the template.
90
+ * Each method is augmented with additional properties:
91
+ * - `firstArgument`: The first argument (if any).
92
+ * - `remainingArguments`: All other arguments (if any).
93
+ * - `hasArguments`: A boolean indicating whether the method has arguments or not.
94
+ */
95
+ get processedMethods(): Method[] {
96
+ return this.methods.map((method) => {
97
+ const [firstArgument, ...remainingArguments] =
98
+ method.arguments || [];
99
+ return {
100
+ ...method,
101
+ firstArgument,
102
+ remainingArguments,
103
+ hasArguments: method.arguments && method.arguments.length > 0,
104
+ cssForMultipleArguments:
105
+ remainingArguments.length > 0 ? "left-border" : ""
106
+ };
107
+ });
108
+ }
109
+
110
+ /**
111
+ * Returns the preprocessed events for easier rendering in the template.
112
+ * Each event is augmented with a capitalized name property that capitalizes the first letter
113
+ * while maintaining camelCase format.
114
+ */
115
+ get processedEvents(): Specification[] {
116
+ return this._processedEvents;
117
+ }
118
+
119
+ get hasAttributes() {
120
+ return this.attributes?.length > 0;
121
+ }
122
+
123
+ get hasMethods() {
124
+ return this.methods?.length > 0;
125
+ }
126
+
127
+ get hasSlots() {
128
+ return this.slots?.length > 0;
129
+ }
130
+
131
+ get hasEvents() {
132
+ return this.events?.length > 0;
133
+ }
134
+
135
+ get showNoSpecifications() {
136
+ return (
137
+ !this.showError &&
138
+ !this.isLoading &&
139
+ !this.hasAttributes &&
140
+ !this.hasMethods &&
141
+ !this.hasSlots &&
142
+ !this.hasEvents
143
+ );
144
+ }
145
+
146
+ get isModelAura() {
147
+ return this.model === "aura";
148
+ }
149
+
150
+ renderedCallback(): void {
151
+ if (this.data) {
152
+ this.debouncedNotifyDataRendered();
153
+ }
154
+ }
155
+
156
+ notifySpecificationDataRendered() {
157
+ // Dispatch a custom event to notify the specification tab has rendered.
158
+ this.dispatchEvent(
159
+ new CustomEvent("specificationdatarendered", {
160
+ detail: { name: "doc-specification-content" },
161
+ bubbles: true,
162
+ composed: true
163
+ })
164
+ );
165
+ }
166
+ }
@@ -0,0 +1,20 @@
1
+ <template lwc:render-mode="light">
2
+ <dx-hr no-padding spacing="md"></dx-hr>
3
+ <div class="survey-container">
4
+ <div class="text-container">
5
+ <b>DID THIS ARTICLE SOLVE YOUR ISSUE?</b>
6
+ <br />
7
+ Let us know so we can improve!
8
+ </div>
9
+ <div class="btn-container">
10
+ <dx-button
11
+ variant="secondary"
12
+ aria-label="Share Your Feedback"
13
+ onclick={openSurvey}
14
+ >
15
+ Share your feedback
16
+ </dx-button>
17
+ </div>
18
+ </div>
19
+ <dx-hr no-padding spacing="md"></dx-hr>
20
+ </template>
@@ -0,0 +1,16 @@
1
+ :host .survey-container {
2
+ align-items: center;
3
+ align-content: center;
4
+ width: 100%;
5
+ display: flex;
6
+ flex-direction: row;
7
+ margin: 20px 0;
8
+ }
9
+
10
+ dx-hr:first-of-type::part(hr) {
11
+ margin-top: var(--dx-g-spacing-2xl);
12
+ }
13
+
14
+ .text-container {
15
+ width: 100%;
16
+ }
@@ -0,0 +1,16 @@
1
+ import { LightningElement } from "lwc";
2
+ import cx from "classnames";
3
+
4
+ declare const Sprig: (eventType: string, eventNme: string) => void;
5
+
6
+ export default class Phase extends LightningElement {
7
+ static renderMode = "light";
8
+
9
+ get className() {
10
+ return cx("container");
11
+ }
12
+
13
+ openSurvey() {
14
+ Sprig("track", "ProvideFeedback");
15
+ }
16
+ }
@@ -0,0 +1,8 @@
1
+ <template>
2
+ <template lwc:if={isSuper}>
3
+ <sup>{value}</sup>
4
+ </template>
5
+ <template lwc:else>
6
+ <sub>{value}</sub>
7
+ </template>
8
+ </template>
@@ -0,0 +1,16 @@
1
+ import { LightningElement, api } from "lwc";
2
+ import { normalizeBoolean } from "dxUtils/normalizers";
3
+
4
+ export default class SuperscriptSubscript extends LightningElement {
5
+ _isSuper: boolean = true;
6
+ @api value: string | null = null;
7
+
8
+ @api
9
+ get isSuper(): boolean {
10
+ return this._isSuper;
11
+ }
12
+
13
+ set isSuper(value) {
14
+ this._isSuper = normalizeBoolean(value);
15
+ }
16
+ }
@@ -96,9 +96,7 @@
96
96
  <a
97
97
  href={child5.a_attr.href}
98
98
  data-id={child5.id}
99
- class="
100
- nav1
101
- "
99
+ class="nav1"
102
100
  onclick={handleNavClick}
103
101
  >
104
102
  {child5.text}
@@ -11,7 +11,7 @@ export default class Toc extends LightningElement {
11
11
  const newPageReference = { ...this.pageReference };
12
12
  // When moving to the new navigation component
13
13
  //const target = event.detail.name.split('-')
14
- const target = event.currentTarget.dataset.id.split("-");
14
+ const target = (event.currentTarget as any).dataset.id.split("-");
15
15
  newPageReference.contentDocumentId = target[0] + ".htm";
16
16
  newPageReference.hash = target[1];
17
17
  this.dispatchEvent(
@@ -40,9 +40,9 @@ export default class Toolbar extends LightningElement {
40
40
  "select[name=languages]"
41
41
  ) as HTMLSelectElement;
42
42
  if (languageEl) {
43
- const languageValue = (
44
- languageEl[languageEl.selectedIndex] as HTMLOptionElement
45
- ).value;
43
+ const languageValue = (languageEl[
44
+ languageEl.selectedIndex
45
+ ] as HTMLOptionElement).value;
46
46
  this.dispatchEvent(
47
47
  new CustomEvent("languageselected", {
48
48
  detail: {
@@ -61,9 +61,9 @@ export default class Toolbar extends LightningElement {
61
61
  "select[name=versions]"
62
62
  ) as HTMLSelectElement;
63
63
  if (versionEl) {
64
- const versionValue = (
65
- versionEl[versionEl.selectedIndex] as HTMLOptionElement
66
- ).value;
64
+ const versionValue = (versionEl[
65
+ versionEl.selectedIndex
66
+ ] as HTMLOptionElement).value;
67
67
  this.dispatchEvent(
68
68
  new CustomEvent("versionselected", {
69
69
  detail: {
@@ -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,40 @@
1
+ <template>
2
+ <div lwc:if={showVersionPicker} class="version-picker-container">
3
+ <dx-dropdown
4
+ options={versions}
5
+ analytics-event="custEv_docVersionSelect"
6
+ analytics-payload={analyticsPayload}
7
+ value={selectedVersion.id}
8
+ width="var(--doc-version-picker-width)"
9
+ onchange={onVersionChange}
10
+ >
11
+ <dx-button
12
+ class="version-picker-button"
13
+ variant="tertiary"
14
+ size="small"
15
+ icon-symbol="chevrondown"
16
+ icon-size="medium"
17
+ >
18
+ <div class="selected-version">
19
+ <p class="selected-version-label">
20
+ {selectedVersion.label}
21
+ </p>
22
+ <template lwc:if={showLatestTag}>
23
+ <dx-type-badge
24
+ class="latest-badge"
25
+ lwc:if={latestVersion}
26
+ value="Latest"
27
+ size="small"
28
+ ></dx-type-badge>
29
+ <dx-type-badge
30
+ class="not-latest-badge"
31
+ lwc:else
32
+ value="Not Latest"
33
+ size="small"
34
+ ></dx-type-badge>
35
+ </template>
36
+ </div>
37
+ </dx-button>
38
+ </dx-dropdown>
39
+ </div>
40
+ </template>
@@ -0,0 +1,65 @@
1
+ import { LightningElement, api, track } 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
+ @track 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
+
58
+ private get showLatestTag(): boolean {
59
+ return !this.hideBadge;
60
+ }
61
+
62
+ private onVersionChange(e: CustomEvent) {
63
+ this.dispatchEvent(new CustomEvent("change", { detail: e.detail }));
64
+ }
65
+ }
@@ -35,6 +35,9 @@ type DropdownOption = {
35
35
  export type DocVersion = DropdownOption & {
36
36
  releaseVersion: string;
37
37
  url: string;
38
+ link?: {
39
+ href: string;
40
+ };
38
41
  };
39
42
 
40
43
  export type DocLanguage = DropdownOption & {
@@ -58,12 +61,15 @@ export type ApiDocLanguage = {
58
61
 
59
62
  export interface Header extends Element {
60
63
  subtitle: string;
64
+ headerHref: string;
65
+ }
66
+
67
+ export type SiderbarFooter = {
61
68
  bailHref: string;
62
69
  bailLabel: string;
63
70
  languages: Array<DocLanguage>;
64
- language: string;
65
- headerHref: string;
66
- }
71
+ language?: string;
72
+ };
67
73
 
68
74
  export type ApiNavItem = {
69
75
  children: Array<ApiNavItem>;
@@ -87,7 +87,9 @@ export class FetchContent {
87
87
  return json;
88
88
  }
89
89
 
90
- private normalizeToc(apiToc: Array<ApiNavItem>): {
90
+ private normalizeToc(
91
+ apiToc: Array<ApiNavItem>
92
+ ): {
91
93
  tocMap: { [key: string]: TreeNode };
92
94
  normalizedToc: Array<TreeNode>;
93
95
  } {