@salesforcedevs/docs-components 0.0.1-edit → 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 (41) hide show
  1. package/lwc.config.json +2 -1
  2. package/package.json +29 -28
  3. package/src/modules/doc/amfReference/amfReference.css +0 -12
  4. package/src/modules/doc/amfReference/amfReference.html +2 -6
  5. package/src/modules/doc/amfReference/amfReference.ts +48 -37
  6. package/src/modules/doc/amfTopic/amfTopic.ts +24 -0
  7. package/src/modules/doc/breadcrumbs/breadcrumbs.html +0 -1
  8. package/src/modules/doc/componentPlayground/componentPlayground.css +11 -3
  9. package/src/modules/doc/componentPlayground/componentPlayground.html +4 -4
  10. package/src/modules/doc/componentPlayground/componentPlayground.ts +69 -1
  11. package/src/modules/doc/content/content.ts +0 -1
  12. package/src/modules/doc/contentCallout/contentCallout.css +1 -0
  13. package/src/modules/doc/contentLayout/contentLayout.html +53 -56
  14. package/src/modules/doc/contentLayout/contentLayout.ts +82 -43
  15. package/src/modules/doc/contentMedia/contentMedia.css +1 -1
  16. package/src/modules/doc/header/header.html +5 -1
  17. package/src/modules/doc/header/header.ts +10 -0
  18. package/src/modules/doc/lwcContentLayout/lwcContentLayout.css +8 -0
  19. package/src/modules/doc/lwcContentLayout/lwcContentLayout.html +38 -42
  20. package/src/modules/doc/lwcContentLayout/lwcContentLayout.ts +116 -15
  21. package/src/modules/doc/phase/phase.css +0 -7
  22. package/src/modules/doc/redocReference/redocReference.css +7 -0
  23. package/src/modules/doc/redocReference/redocReference.html +13 -0
  24. package/src/modules/doc/redocReference/redocReference.ts +425 -0
  25. package/src/modules/doc/specificationContent/specificationContent.html +15 -9
  26. package/src/modules/doc/specificationContent/specificationContent.ts +39 -0
  27. package/src/modules/doc/superscriptSubscript/superscriptSubscript.html +8 -0
  28. package/src/modules/doc/superscriptSubscript/superscriptSubscript.ts +16 -0
  29. package/src/modules/doc/versionPicker/versionPicker.html +2 -0
  30. package/src/modules/doc/xmlContent/xmlContent.css +0 -10
  31. package/src/modules/doc/xmlContent/xmlContent.html +11 -8
  32. package/src/modules/doc/xmlContent/xmlContent.ts +95 -53
  33. package/src/modules/docHelpers/amfStyle/amfStyle.css +0 -2
  34. package/src/modules/docHelpers/contentLayoutStyle/contentLayoutStyle.css +32 -1
  35. package/src/modules/doc/chat/README.md +0 -179
  36. package/src/modules/doc/chat/chat.css +0 -818
  37. package/src/modules/doc/chat/chat.html +0 -241
  38. package/src/modules/doc/chat/chat.ts +0 -586
  39. package/src/modules/doc/editFile/editFile.css +0 -514
  40. package/src/modules/doc/editFile/editFile.html +0 -164
  41. package/src/modules/doc/editFile/editFile.ts +0 -213
@@ -0,0 +1,425 @@
1
+ /* eslint-disable @lwc/lwc/no-document-query */
2
+ import { createElement, LightningElement, api } from "lwc";
3
+ import DocPhase from "doc/phase";
4
+ import DxFooter from "dx/footer";
5
+ import SprigSurvey from "doc/sprigSurvey";
6
+ import { throttle } from "throttle-debounce";
7
+ import { pollUntil } from "dxUtils/async";
8
+
9
+ declare global {
10
+ interface Window {
11
+ Redoc: any;
12
+ }
13
+ }
14
+
15
+ declare const Sprig: (eventType: string, eventName: string) => void;
16
+
17
+ type ReferenceItem = {
18
+ source: string;
19
+ href: string;
20
+ isSelected?: boolean;
21
+ docPhase?: string | null;
22
+ };
23
+
24
+ type ReferenceConfig = {
25
+ refList: ReferenceItem[];
26
+ };
27
+
28
+ const SCROLL_THROTTLE_DELAY = 50;
29
+ const ELEMENT_TIMEOUT = 10000;
30
+ const ELEMENT_CHECK_INTERVAL = 100;
31
+
32
+ export default class RedocReference extends LightningElement {
33
+ private _referenceConfig: ReferenceConfig = { refList: [] };
34
+ private _parentDocPhaseInfo: string | null = null;
35
+ private redocInitialized = false;
36
+
37
+ private docHeaderElement: Element | null = null;
38
+ private docPhaseWrapperElement: Element | null = null;
39
+ private lastSidebarTop = 0;
40
+
41
+ showError = false;
42
+
43
+ @api
44
+ get referenceConfig(): ReferenceConfig {
45
+ return this._referenceConfig;
46
+ }
47
+
48
+ set referenceConfig(value: string | ReferenceConfig) {
49
+ try {
50
+ const refConfig =
51
+ typeof value === "string" ? JSON.parse(value) : value;
52
+ this._referenceConfig = refConfig;
53
+ } catch (error) {
54
+ this._referenceConfig = { refList: [] };
55
+ this.showErrorUI(
56
+ "Failed to parse reference configuration data",
57
+ error
58
+ );
59
+ }
60
+ }
61
+
62
+ @api
63
+ get docPhaseInfo(): string | null {
64
+ return this._parentDocPhaseInfo;
65
+ }
66
+
67
+ set docPhaseInfo(value: string) {
68
+ this._parentDocPhaseInfo = value;
69
+ }
70
+
71
+ connectedCallback(): void {
72
+ window.addEventListener("scroll", this.handleScrollAndResize);
73
+ window.addEventListener("resize", this.handleScrollAndResize);
74
+ }
75
+
76
+ renderedCallback(): void {
77
+ if (!this.redocInitialized) {
78
+ this.redocInitialized = true;
79
+ this.initializeRedoc();
80
+ }
81
+ }
82
+
83
+ disconnectedCallback(): void {
84
+ window.removeEventListener("scroll", this.handleScrollAndResize);
85
+ window.removeEventListener("resize", this.handleScrollAndResize);
86
+
87
+ this.handleScrollAndResize?.cancel?.();
88
+
89
+ // Clean up cached DOM element references to prevent memory leaks
90
+ this.docHeaderElement = null;
91
+ this.docPhaseWrapperElement = null;
92
+ }
93
+
94
+ // Displays error UI and logs error message for debugging
95
+ private showErrorUI(message: string, error?: any): void {
96
+ this.showError = true;
97
+ console.error(message, error);
98
+ }
99
+
100
+ private getRedocContainer(): HTMLElement | null {
101
+ return document.querySelector(".redoc-container");
102
+ }
103
+
104
+ private getSelectedReference(): ReferenceItem | null {
105
+ return (
106
+ this._referenceConfig?.refList?.find((ref) => ref.isSelected) ||
107
+ this._referenceConfig?.refList?.[0]
108
+ );
109
+ }
110
+
111
+ private getDocPhaseInfo(): string | null {
112
+ if (this._parentDocPhaseInfo) {
113
+ return this._parentDocPhaseInfo;
114
+ }
115
+ const selectedRef = this.getSelectedReference();
116
+ return selectedRef?.docPhase
117
+ ? JSON.stringify(selectedRef.docPhase)
118
+ : null;
119
+ }
120
+
121
+ // Extracts numeric value from CSS custom properties
122
+ private getGlobalCSSVariableValue(variableName: string): number {
123
+ const value = getComputedStyle(
124
+ document.documentElement
125
+ ).getPropertyValue(variableName);
126
+ return parseInt(value, 10) || 0;
127
+ }
128
+
129
+ /*
130
+ ** Since we could not use --dx-g-global-header-height as getPropertyValue returns a calc expression,
131
+ ** we are using the respective CSS variables to calculate the height.
132
+ */
133
+ private getGlobalHeaderHeight(): number {
134
+ const rowHeight = this.getGlobalCSSVariableValue(
135
+ "--dx-g-global-header-nav-row-height"
136
+ );
137
+ const rowCount = this.getGlobalCSSVariableValue(
138
+ "--dx-g-global-header-nav-row-count"
139
+ );
140
+ return rowHeight * rowCount;
141
+ }
142
+
143
+ // Gets doc header height with element caching for performance
144
+ private getDocHeaderHeight(): number {
145
+ if (!this.docHeaderElement) {
146
+ this.docHeaderElement =
147
+ document.querySelector(".sticky-doc-header");
148
+ }
149
+ return this.docHeaderElement?.getBoundingClientRect()?.height || 0;
150
+ }
151
+
152
+ // Gets doc phase wrapper height with element caching for performance
153
+ private getDocPhaseWrapperHeight(): number {
154
+ if (!this.docPhaseWrapperElement) {
155
+ this.docPhaseWrapperElement =
156
+ document.querySelector(".doc-phase-wrapper");
157
+ }
158
+ return (
159
+ this.docPhaseWrapperElement?.getBoundingClientRect()?.height || 0
160
+ );
161
+ }
162
+
163
+ calculateHeaderOffset = () => {
164
+ const globalHeaderHeight = this.getGlobalHeaderHeight();
165
+ const docHeaderHeight = this.getDocHeaderHeight();
166
+ return globalHeaderHeight + docHeaderHeight;
167
+ };
168
+
169
+ // Dynamic scroll offset calculation that Redoc will call
170
+ calculateScrollYOffset = () => {
171
+ const headerOffset = this.calculateHeaderOffset();
172
+ const phaseHeight = this.getDocPhaseWrapperHeight();
173
+ return headerOffset + phaseHeight;
174
+ };
175
+
176
+ // Updates sidebar positioning based on current header heights
177
+ private updateSidebarPosition = () => {
178
+ requestAnimationFrame(() => {
179
+ const redocContainer = this.getRedocContainer();
180
+ if (!redocContainer) {
181
+ return;
182
+ }
183
+
184
+ const currentSidebarTop = this.calculateHeaderOffset();
185
+ if (currentSidebarTop === this.lastSidebarTop) {
186
+ return;
187
+ }
188
+
189
+ const sidebarTopValue = `${currentSidebarTop}px`;
190
+ this.template.host.style.setProperty(
191
+ "--doc-c-redoc-sidebar-top",
192
+ sidebarTopValue
193
+ );
194
+ this.lastSidebarTop = currentSidebarTop;
195
+ });
196
+ };
197
+
198
+ // Updates browser URL while preserving query params and hash
199
+ private updateUrlWithReference(selectedRef: ReferenceItem): void {
200
+ if (selectedRef?.href) {
201
+ const parentReferencePath = selectedRef.href;
202
+ const currentUrl = window.location;
203
+ const existingParams = currentUrl.search + currentUrl.hash;
204
+
205
+ window.history.pushState(
206
+ {},
207
+ "",
208
+ `${parentReferencePath}${existingParams}`
209
+ );
210
+ }
211
+ }
212
+
213
+ private handleScrollAndResize = throttle(
214
+ SCROLL_THROTTLE_DELAY,
215
+ () => !this.showError && this.updateSidebarPosition()
216
+ );
217
+
218
+ // Initializes Redoc library with selected reference configuration
219
+ private async initializeRedoc(): Promise<void> {
220
+ try {
221
+ await this.waitForRedoc();
222
+
223
+ const redocContainer = this.getRedocContainer();
224
+ if (!redocContainer) {
225
+ this.showErrorUI("Redoc container is not found.");
226
+ return;
227
+ }
228
+
229
+ const selectedRef = this.getSelectedReference();
230
+ if (selectedRef) {
231
+ this.updateUrlWithReference(selectedRef);
232
+
233
+ const specUrl = selectedRef.source;
234
+ if (!specUrl) {
235
+ this.showErrorUI("Spec URL not found.");
236
+ return;
237
+ }
238
+
239
+ window.Redoc.init(
240
+ specUrl,
241
+ {
242
+ // Dynamic scroll offset to account for headers
243
+ scrollYOffset: this.calculateScrollYOffset
244
+ },
245
+ redocContainer,
246
+ (error: any) => {
247
+ if (error) {
248
+ this.showErrorUI(
249
+ "Failed to show Reference UI using Redoc: ",
250
+ error
251
+ );
252
+ } else {
253
+ this.integrateCustomComponents();
254
+ }
255
+ }
256
+ );
257
+ }
258
+ } catch (error) {
259
+ this.showErrorUI("Failed to load Redoc library:", error);
260
+ }
261
+ }
262
+
263
+ // Polls for Redoc library availability with timeout
264
+ private async waitForRedoc(timeout = ELEMENT_TIMEOUT): Promise<void> {
265
+ const success = await pollUntil(
266
+ () => !!window.Redoc,
267
+ ELEMENT_CHECK_INTERVAL,
268
+ timeout
269
+ );
270
+
271
+ if (!success) {
272
+ throw new Error(
273
+ "Redoc library failed to load within timeout period"
274
+ );
275
+ }
276
+ }
277
+
278
+ // Integrates custom elements (doc phase, footer, survey) into Redoc container
279
+ private async integrateCustomComponents(): Promise<void> {
280
+ try {
281
+ const redocContainer = this.getRedocContainer();
282
+ if (!redocContainer) {
283
+ return;
284
+ }
285
+
286
+ const apiContentDiv = await this.waitForApiContent(redocContainer);
287
+ apiContentDiv.setAttribute("lwc:dom", "manual");
288
+
289
+ const docPhaseInfo = this.getDocPhaseInfo();
290
+ if (docPhaseInfo) {
291
+ this.insertDocPhase(apiContentDiv, docPhaseInfo);
292
+ }
293
+
294
+ if (typeof Sprig !== "undefined") {
295
+ this.insertSprigSurvey(apiContentDiv);
296
+ }
297
+
298
+ this.insertFooter(apiContentDiv);
299
+
300
+ // Wait for footer to be rendered before updating styles
301
+ requestAnimationFrame(() => {
302
+ this.updateRedocThirdColumnStyle(redocContainer);
303
+
304
+ // Fix initial hash scroll after doc phase insertion
305
+ this.handleInitialHashScrollFix();
306
+ });
307
+ } catch (error) {
308
+ this.showErrorUI("Failed to integrate custom components:", error);
309
+ }
310
+ }
311
+
312
+ // Waits for Redoc's API content element to be rendered
313
+ private async waitForApiContent(
314
+ container: HTMLElement
315
+ ): Promise<HTMLElement> {
316
+ const success = await pollUntil(
317
+ () => !!container.querySelector(".api-content"),
318
+ ELEMENT_CHECK_INTERVAL,
319
+ ELEMENT_TIMEOUT
320
+ );
321
+
322
+ if (!success) {
323
+ throw new Error(
324
+ "Redoc API content element not found within timeout period"
325
+ );
326
+ }
327
+
328
+ return container.querySelector<HTMLElement>(".api-content")!;
329
+ }
330
+
331
+ // Creates and inserts doc phase component at container start
332
+ private insertDocPhase(container: HTMLElement, docPhaseInfo: string): void {
333
+ const wrapper = document.createElement("div");
334
+ wrapper.className = "doc-phase-wrapper";
335
+ container.insertBefore(wrapper, container.firstChild);
336
+
337
+ const docPhaseElement = createElement("doc-phase", { is: DocPhase });
338
+ Object.assign(docPhaseElement, { docPhaseInfo });
339
+ wrapper.appendChild(docPhaseElement);
340
+ }
341
+
342
+ // Appends footer component to container
343
+ private insertFooter(container: HTMLElement): void {
344
+ const footerElement = createElement("dx-footer", { is: DxFooter });
345
+ Object.assign(footerElement, { variant: "no-signup" });
346
+ container.appendChild(footerElement);
347
+ }
348
+
349
+ // Appends Sprig survey component to container
350
+ private insertSprigSurvey(container: HTMLElement): void {
351
+ const wrapper = document.createElement("div");
352
+ wrapper.className = "sprig-survey-wrapper";
353
+ container.appendChild(wrapper);
354
+
355
+ const feedbackElement = createElement("doc-sprig-survey", {
356
+ is: SprigSurvey
357
+ });
358
+ wrapper.appendChild(feedbackElement);
359
+ }
360
+
361
+ // Adjusts third column bottom position to prevent footer overlap
362
+ private updateRedocThirdColumnStyle(redocContainer: HTMLElement): void {
363
+ const footer = redocContainer.querySelector(
364
+ ".redoc-wrap .api-content dx-footer"
365
+ ) as HTMLElement;
366
+ if (!footer) {
367
+ console.warn(
368
+ "Footer element not found, skipping third column styling"
369
+ );
370
+ return;
371
+ }
372
+
373
+ const redocThirdColumnElement = redocContainer.querySelector(
374
+ ".redoc-wrap > div:last-child"
375
+ ) as HTMLElement;
376
+ if (!redocThirdColumnElement) {
377
+ console.warn(
378
+ "Third column element not found, skipping third column styling"
379
+ );
380
+ return;
381
+ }
382
+
383
+ const footerHeight = footer.getBoundingClientRect()?.height || 0;
384
+ const footerMarginTop = parseInt(
385
+ getComputedStyle(this.template.host).getPropertyValue(
386
+ "--dx-footer-margin-top"
387
+ ),
388
+ 10
389
+ );
390
+
391
+ redocThirdColumnElement.style.setProperty(
392
+ "bottom",
393
+ `${footerHeight + footerMarginTop}px`
394
+ );
395
+ }
396
+
397
+ // Fixes initial hash scroll positioning after doc phase insertion
398
+ private handleInitialHashScrollFix(): void {
399
+ const hash = window.location.hash;
400
+ if (!hash || hash.length <= 1) {
401
+ return;
402
+ }
403
+
404
+ // Small delay to ensure all components are fully rendered
405
+ requestAnimationFrame(() => {
406
+ const targetId = hash.substring(1);
407
+ const targetElement = document.getElementById(targetId);
408
+
409
+ if (!targetElement) {
410
+ return;
411
+ }
412
+
413
+ const elementTop =
414
+ (targetElement.getBoundingClientRect()?.top || 0) +
415
+ window.pageYOffset;
416
+ const scrollOffset = this.calculateScrollYOffset();
417
+ const correctedScrollPosition = elementTop - scrollOffset;
418
+
419
+ window.scrollTo({
420
+ top: correctedScrollPosition,
421
+ behavior: "smooth"
422
+ });
423
+ });
424
+ }
425
+ }
@@ -7,6 +7,11 @@
7
7
  if:true={isLoading}
8
8
  ></dx-spinner>
9
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>
10
15
  <template lwc:if={hasAttributes}>
11
16
  <doc-heading
12
17
  header="Attributes"
@@ -29,7 +34,12 @@
29
34
  <tr key={attribute.name}>
30
35
  <td>
31
36
  <span class="code">
32
- {attribute.nameInKebabCase}
37
+ <template lwc:if={isModelAura}>
38
+ {attribute.name}
39
+ </template>
40
+ <template lwc:else>
41
+ {attribute.nameInKebabCase}
42
+ </template>
33
43
  </span>
34
44
  </td>
35
45
  <td>{attribute.description}</td>
@@ -73,9 +83,7 @@
73
83
  <template lwc:if={method.firstArgument}>
74
84
  <tr key={method.name}>
75
85
  <td rowspan={method.arguments.length}>
76
- <span class="code">
77
- {method.nameInKebabCase}
78
- </span>
86
+ <span class="code">{method.name}</span>
79
87
  </td>
80
88
  <td rowspan={method.arguments.length}>
81
89
  {method.description}
@@ -100,9 +108,7 @@
100
108
  <template lwc:else>
101
109
  <tr key={method.name}>
102
110
  <td>
103
- <span class="code">
104
- {method.nameInKebabCase}
105
- </span>
111
+ <span class="code">{method.name}</span>
106
112
  </td>
107
113
  <td>{method.description}</td>
108
114
  <td colspan="3"></td>
@@ -154,11 +160,11 @@
154
160
  </tr>
155
161
  </thead>
156
162
  <tbody>
157
- <template for:each={events} for:item="event">
163
+ <template for:each={processedEvents} for:item="event">
158
164
  <tr key={event.name}>
159
165
  <td>
160
166
  <span class="code">
161
- {event.nameInKebabCase}
167
+ {event.nameCapitalized}
162
168
  </span>
163
169
  </td>
164
170
  <td>{event.description}</td>
@@ -17,6 +17,7 @@ export default class SpecificationContent extends LightningElement {
17
17
  private methods: Method[] = [];
18
18
  private slots: Specification[] = [];
19
19
  private events: Specification[] = [];
20
+ private _processedEvents: Specification[] = [];
20
21
 
21
22
  /* TODO: For now setting the timeout to 300ms,
22
23
  * post integration with CX-Router API will test and change if required.
@@ -60,6 +61,20 @@ export default class SpecificationContent extends LightningElement {
60
61
  slots: this.slots,
61
62
  events: this.events
62
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
+ : [];
63
78
  }
64
79
  } catch (error) {
65
80
  this.data = {};
@@ -92,6 +107,15 @@ export default class SpecificationContent extends LightningElement {
92
107
  });
93
108
  }
94
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
+
95
119
  get hasAttributes() {
96
120
  return this.attributes?.length > 0;
97
121
  }
@@ -108,6 +132,21 @@ export default class SpecificationContent extends LightningElement {
108
132
  return this.events?.length > 0;
109
133
  }
110
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
+
111
150
  renderedCallback(): void {
112
151
  if (this.data) {
113
152
  this.debouncedNotifyDataRendered();
@@ -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
+ }
@@ -2,6 +2,8 @@
2
2
  <div lwc:if={showVersionPicker} class="version-picker-container">
3
3
  <dx-dropdown
4
4
  options={versions}
5
+ analytics-event="custEv_docVersionSelect"
6
+ analytics-payload={analyticsPayload}
5
7
  value={selectedVersion.id}
6
8
  width="var(--doc-version-picker-width)"
7
9
  onchange={onVersionChange}
@@ -31,10 +31,6 @@ dx-dropdown > dx-button:hover {
31
31
  --border-color: var(--button-primary-color-hover);
32
32
  }
33
33
 
34
- doc-phase {
35
- --doc-c-phase-top: var(--dx-g-global-header-height);
36
- }
37
-
38
34
  @media screen and (max-width: 768px) {
39
35
  doc-content-layout {
40
36
  --dx-g-doc-header-main-nav-height: 41px;
@@ -45,10 +41,4 @@ doc-phase {
45
41
  var(--dx-g-global-header-height) + var(--dx-g-doc-header-height)
46
42
  );
47
43
  }
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
- }
54
44
  }
@@ -1,23 +1,18 @@
1
1
  <template>
2
2
  <doc-content-layout
3
- lwc:if={loaded}
3
+ lwc:if={displayContent}
4
4
  lwc:ref="docContentLayout"
5
- coveo-organization-id={coveoOrganizationId}
6
- coveo-public-access-token={coveoPublicAccessToken}
7
- coveo-analytics-token={coveoAnalyticsToken}
8
- coveo-search-hub={coveoSearchHub}
9
- coveo-advanced-query-config={coveoAdvancedQueryConfig}
10
5
  sidebar-header={docTitle}
11
6
  sidebar-content={sidebarContent}
12
7
  sidebar-value={sidebarValue}
13
8
  onselect={handleSelect}
14
- use-old-sidebar={useOldSidebar}
15
9
  onlangchange={handleLanguageChange}
16
10
  languages={sidebarFooterContent.languages}
17
11
  language={sidebarFooterContent.language}
18
12
  bail-href={sidebarFooterContent.bailHref}
19
13
  bail-label={sidebarFooterContent.bailLabel}
20
14
  show-footer={enableFooter}
15
+ reading-time={computedReadingTime}
21
16
  >
22
17
  <doc-phase
23
18
  slot="version-banner"
@@ -30,7 +25,7 @@
30
25
  <div lwc:if={showVersionPicker} slot="sidebar-header">
31
26
  <doc-version-picker
32
27
  data-type="version"
33
- analytics-event="custEv_ctaLinkClick"
28
+ analytics-event="custEv_linkClick"
34
29
  analytics-payload={ANALYTICS_PAYLOAD}
35
30
  versions={versionOptions}
36
31
  selected-version={version}
@@ -49,4 +44,12 @@
49
44
  onnavclick={handleNavClick}
50
45
  ></doc-content>
51
46
  </doc-content-layout>
47
+ <div lwc:if={display404}>
48
+ <dx-error
49
+ image="https://a.sfdcstatic.com/developer-website/prod/images/404.svg"
50
+ code="404"
51
+ header="Beep boop. That did not compute."
52
+ subtitle="The document you're looking for doesn't seem to exist."
53
+ ></dx-error>
54
+ </div>
52
55
  </template>