@salesforcedevs/docs-components 0.0.1 → 0.0.2-edit
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 +11 -2
- package/package.json +13 -12
- package/src/modules/doc/{amfReference/utils.ts → amfModelParser/amfModelParser.ts} +10 -5
- package/src/modules/doc/amfReference/amfReference.css +23 -3
- package/src/modules/doc/amfReference/amfReference.html +34 -21
- package/src/modules/doc/amfReference/amfReference.ts +225 -92
- package/src/modules/doc/amfReference/types.ts +3 -12
- package/src/modules/doc/amfTopic/amfTopic.css +20 -0
- package/src/modules/doc/amfTopic/amfTopic.ts +35 -18
- package/src/modules/doc/amfTopic/types.ts +15 -13
- package/src/modules/doc/amfTopic/utils.ts +12 -6
- package/src/modules/doc/breadcrumbItem/breadcrumbItem.ts +17 -10
- package/src/modules/doc/breadcrumbs/breadcrumbs.html +7 -9
- package/src/modules/doc/breadcrumbs/breadcrumbs.ts +30 -34
- package/src/modules/doc/chat/README.md +179 -0
- package/src/modules/doc/chat/chat.css +818 -0
- package/src/modules/doc/chat/chat.html +241 -0
- package/src/modules/doc/chat/chat.ts +586 -0
- package/src/modules/doc/componentPlayground/componentPlayground.css +22 -0
- package/src/modules/doc/componentPlayground/componentPlayground.html +20 -0
- package/src/modules/doc/componentPlayground/componentPlayground.ts +29 -0
- package/src/modules/doc/content/content.css +70 -76
- package/src/modules/doc/content/content.html +1 -0
- package/src/modules/doc/content/content.ts +24 -45
- package/src/modules/doc/contentCallout/contentCallout.css +10 -7
- package/src/modules/doc/contentCallout/contentCallout.html +11 -4
- package/src/modules/doc/contentCallout/contentCallout.ts +8 -1
- package/src/modules/doc/contentLayout/contentLayout.css +1 -98
- package/src/modules/doc/contentLayout/contentLayout.html +41 -19
- package/src/modules/doc/contentLayout/contentLayout.ts +298 -89
- package/src/modules/doc/doDont/doDont.css +47 -0
- package/src/modules/doc/doDont/doDont.html +27 -0
- package/src/modules/doc/doDont/doDont.ts +17 -0
- package/src/modules/doc/editFile/editFile.css +514 -0
- package/src/modules/doc/editFile/editFile.html +164 -0
- package/src/modules/doc/editFile/editFile.ts +213 -0
- package/src/modules/doc/header/header.css +65 -36
- package/src/modules/doc/header/header.html +41 -139
- package/src/modules/doc/header/header.ts +54 -76
- package/src/modules/doc/heading/heading.css +16 -37
- package/src/modules/doc/heading/heading.html +4 -4
- package/src/modules/doc/heading/heading.ts +12 -10
- package/src/modules/doc/headingAnchor/headingAnchor.css +2 -2
- package/src/modules/doc/headingAnchor/headingAnchor.ts +2 -2
- package/src/modules/doc/headingContent/headingContent.css +1 -1
- package/src/modules/doc/headingContent/headingContent.html +2 -2
- package/src/modules/doc/headingContent/headingContent.ts +2 -2
- package/src/modules/doc/lwcContentLayout/lwcContentLayout.css +1 -0
- package/src/modules/doc/lwcContentLayout/lwcContentLayout.html +68 -0
- package/src/modules/doc/lwcContentLayout/lwcContentLayout.ts +168 -0
- package/src/modules/doc/overview/overview.css +40 -0
- package/src/modules/doc/overview/overview.html +34 -0
- package/src/modules/doc/overview/overview.ts +12 -0
- package/src/modules/doc/phase/phase.css +18 -3
- package/src/modules/doc/phase/phase.html +12 -2
- package/src/modules/doc/phase/phase.ts +44 -8
- package/src/modules/doc/specificationContent/specificationContent.css +36 -0
- package/src/modules/doc/specificationContent/specificationContent.html +171 -0
- package/src/modules/doc/specificationContent/specificationContent.ts +127 -0
- package/src/modules/doc/sprigSurvey/sprigSurvey.html +20 -0
- package/src/modules/doc/sprigSurvey/sprigSurvey.scoped.css +16 -0
- package/src/modules/doc/sprigSurvey/sprigSurvey.ts +16 -0
- package/src/modules/doc/toc/toc.html +1 -3
- package/src/modules/doc/toc/toc.ts +1 -1
- package/src/modules/doc/toolbar/toolbar.ts +6 -6
- package/src/modules/doc/versionPicker/versionPicker.css +64 -0
- package/src/modules/doc/versionPicker/versionPicker.html +38 -0
- package/src/modules/doc/versionPicker/versionPicker.ts +65 -0
- package/src/modules/doc/xmlContent/types.ts +9 -3
- package/src/modules/doc/xmlContent/utils.ts +3 -1
- package/src/modules/doc/xmlContent/xmlContent.css +26 -4
- package/src/modules/doc/xmlContent/xmlContent.html +29 -17
- package/src/modules/doc/xmlContent/xmlContent.ts +212 -79
- package/src/modules/docHelpers/amfStyle/amfStyle.css +6 -6
- package/src/modules/docHelpers/contentLayoutStyle/contentLayoutStyle.css +131 -0
- package/src/modules/docHelpers/imgStyle/imgStyle.css +59 -0
- package/src/modules/docHelpers/status/status.css +1 -1
- package/src/modules/docUtils/{SearchSyncer/SearchSyncer.ts → searchSyncer/searchSyncer.ts} +1 -0
- package/src/modules/docUtils/utils/__mocks__/coveo.analytics.ts +16 -0
- package/src/modules/docUtils/utils/coveo.analytics.d.ts +10 -0
- package/src/modules/docUtils/utils/utils.ts +32 -0
- package/src/modules/docBaseElements/lightningElementWithState/lightningElementWithState.ts +0 -93
- package/src/modules/docHelpers/phaseContentLayout/phaseContentLayout.css +0 -39
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Json } from "typings/custom";
|
|
1
|
+
import { Json, DocPhaseInfo } from "typings/custom";
|
|
2
2
|
|
|
3
3
|
export interface AmfTopicType {
|
|
4
4
|
referenceId: string;
|
|
@@ -21,7 +21,6 @@ export interface AmfMetaTopicType extends AmfTopicType {
|
|
|
21
21
|
export interface NavItem {
|
|
22
22
|
name: string;
|
|
23
23
|
label: string;
|
|
24
|
-
// TODO: Better type here
|
|
25
24
|
children?: ({
|
|
26
25
|
id: string;
|
|
27
26
|
label?: string;
|
|
@@ -47,14 +46,6 @@ export interface AmfModelRecord {
|
|
|
47
46
|
parsedModel: Json;
|
|
48
47
|
}
|
|
49
48
|
|
|
50
|
-
export type DocPhase = "pilot" | "dev-preview" | "beta";
|
|
51
|
-
|
|
52
|
-
export type DocPhaseEntry = {
|
|
53
|
-
phase: DocPhase;
|
|
54
|
-
title: string;
|
|
55
|
-
body: string;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
49
|
export type ReferenceType = "markdown" | "rest-raml" | "rest-oa2" | "rest-oa3";
|
|
59
50
|
|
|
60
51
|
/**
|
|
@@ -74,7 +65,7 @@ export interface ParsedMarkdownTopic {
|
|
|
74
65
|
export interface AmfConfig {
|
|
75
66
|
id: string;
|
|
76
67
|
version?: string;
|
|
77
|
-
docPhase?:
|
|
68
|
+
docPhase?: DocPhaseInfo;
|
|
78
69
|
title: string;
|
|
79
70
|
href: string;
|
|
80
71
|
referenceType: ReferenceType;
|
|
@@ -104,7 +95,7 @@ export interface ParsedTopicModel {
|
|
|
104
95
|
export interface TopicModel {
|
|
105
96
|
id: string;
|
|
106
97
|
type: string;
|
|
107
|
-
amf:
|
|
98
|
+
amf: string;
|
|
108
99
|
parser: AmfParser;
|
|
109
100
|
}
|
|
110
101
|
|
|
@@ -1 +1,21 @@
|
|
|
1
1
|
@import "docHelpers/amfStyle";
|
|
2
|
+
|
|
3
|
+
:host {
|
|
4
|
+
--reference-container-margin-top: var(--dx-g-spacing-sm);
|
|
5
|
+
--api-documentation-margin-top: var(--dx-g-spacing-3xl);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 1. We need to scroll to top from the tablet size as side nav bar and content in side by side from tablet size
|
|
10
|
+
* 2. Consider global nav height, doc header height and content margins to scroll to the right position
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
@media screen and (min-width: 769px) {
|
|
14
|
+
.topic-container {
|
|
15
|
+
scroll-margin-top: calc(
|
|
16
|
+
var(--dx-g-global-header-height) + var(--dx-g-doc-header-height) +
|
|
17
|
+
var(--reference-container-margin-top) +
|
|
18
|
+
var(--api-documentation-margin-top)
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -8,14 +8,17 @@ import {
|
|
|
8
8
|
createTypeElement
|
|
9
9
|
} from "./utils";
|
|
10
10
|
import type { TopicModel } from "./types";
|
|
11
|
+
import { Json } from "typings/custom";
|
|
12
|
+
|
|
13
|
+
const TABLE_SIZE_MATCH = "769px";
|
|
11
14
|
|
|
12
15
|
export default class AmfTopic extends LightningElement {
|
|
13
|
-
private _model;
|
|
14
|
-
private amf;
|
|
15
|
-
private type;
|
|
16
|
+
private _model: TopicModel | undefined;
|
|
17
|
+
private amf: Json;
|
|
18
|
+
private type: string | undefined;
|
|
16
19
|
|
|
17
20
|
@api
|
|
18
|
-
get model(): TopicModel {
|
|
21
|
+
get model(): TopicModel | undefined {
|
|
19
22
|
return this._model;
|
|
20
23
|
}
|
|
21
24
|
|
|
@@ -24,13 +27,17 @@ export default class AmfTopic extends LightningElement {
|
|
|
24
27
|
!this.amf ||
|
|
25
28
|
(value && this._model && value.amf !== this._model?.amf)
|
|
26
29
|
) {
|
|
27
|
-
|
|
30
|
+
try {
|
|
31
|
+
this.amf = value && JSON.parse(value.amf);
|
|
32
|
+
} catch (error) {
|
|
33
|
+
console.error(`Error parsing amf model: ${error}`);
|
|
34
|
+
}
|
|
28
35
|
}
|
|
29
36
|
if (
|
|
30
37
|
!this.type ||
|
|
31
38
|
(value && this._model && value.type !== this._model?.type)
|
|
32
39
|
) {
|
|
33
|
-
this.type = value &&
|
|
40
|
+
this.type = value && value.type;
|
|
34
41
|
}
|
|
35
42
|
|
|
36
43
|
this._model = value;
|
|
@@ -41,7 +48,11 @@ export default class AmfTopic extends LightningElement {
|
|
|
41
48
|
}
|
|
42
49
|
|
|
43
50
|
update(): void {
|
|
44
|
-
|
|
51
|
+
if (!this.model) {
|
|
52
|
+
throw new Error("Amf TopicModel undefined when trying to update");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const container = this.template.querySelector(".topic-container")!;
|
|
45
56
|
const { id } = this.model;
|
|
46
57
|
const type = this.type;
|
|
47
58
|
const amf = this.amf;
|
|
@@ -76,19 +87,25 @@ export default class AmfTopic extends LightningElement {
|
|
|
76
87
|
element = createDocumentationElement(amf, docsModel);
|
|
77
88
|
}
|
|
78
89
|
|
|
79
|
-
if (container
|
|
90
|
+
if (container?.firstChild) {
|
|
80
91
|
container.firstChild.remove();
|
|
81
92
|
}
|
|
82
|
-
container
|
|
93
|
+
container?.appendChild(element as Node);
|
|
94
|
+
|
|
95
|
+
const isTabletOrDesktop = window.matchMedia(
|
|
96
|
+
`(min-width: ${TABLE_SIZE_MATCH})`
|
|
97
|
+
).matches;
|
|
98
|
+
|
|
99
|
+
if (isTabletOrDesktop) {
|
|
100
|
+
window.scrollTo(0, 0);
|
|
101
|
+
}
|
|
83
102
|
}
|
|
84
|
-
}
|
|
85
103
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
return JSON.parse(JSON.stringify(value));
|
|
104
|
+
renderedCallback(): void {
|
|
105
|
+
try {
|
|
106
|
+
this.update();
|
|
107
|
+
} catch (error) {
|
|
108
|
+
console.error(error);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
94
111
|
}
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import { Json } from "typings/custom";
|
|
2
|
+
import { AmfModelParser } from "doc/amfModelParser";
|
|
3
|
+
import {
|
|
4
|
+
DomainElement,
|
|
5
|
+
EndPoint,
|
|
6
|
+
Operation,
|
|
7
|
+
Shape
|
|
8
|
+
} from "@api-components/amf-helper-mixin";
|
|
2
9
|
|
|
3
10
|
export type ApiSummaryElement = HTMLElement & {
|
|
4
11
|
amf: Json;
|
|
@@ -11,44 +18,39 @@ export type ApiEndpointElement = HTMLElement & {
|
|
|
11
18
|
inlineMethods: boolean;
|
|
12
19
|
noNavigation: boolean;
|
|
13
20
|
selected: string;
|
|
14
|
-
endpoint:
|
|
21
|
+
endpoint: EndPoint;
|
|
15
22
|
noTryIt: boolean;
|
|
16
23
|
};
|
|
17
24
|
|
|
18
25
|
export type ApiMethodElement = HTMLElement & {
|
|
19
26
|
amf: Json;
|
|
20
27
|
noNavigation: boolean;
|
|
21
|
-
endpoint:
|
|
22
|
-
method:
|
|
28
|
+
endpoint: EndPoint | undefined;
|
|
29
|
+
method: Operation | undefined;
|
|
23
30
|
noTryIt: boolean;
|
|
24
31
|
};
|
|
25
32
|
|
|
26
33
|
export type ApiSecurityElement = HTMLElement & {
|
|
27
34
|
amf: Json;
|
|
28
|
-
security:
|
|
35
|
+
security: DomainElement | undefined;
|
|
29
36
|
};
|
|
30
37
|
|
|
31
38
|
export type ApiTypeElement = HTMLElement & {
|
|
32
39
|
amf: Json;
|
|
33
|
-
type
|
|
40
|
+
type?: Shape;
|
|
34
41
|
mediaTypes: Json;
|
|
35
42
|
};
|
|
36
43
|
|
|
37
44
|
export type ApiDocElement = HTMLElement & {
|
|
38
45
|
amf: Json;
|
|
39
|
-
shape:
|
|
46
|
+
shape: DomainElement | undefined;
|
|
40
47
|
};
|
|
41
48
|
|
|
42
49
|
export type AmfModel = Json;
|
|
43
50
|
|
|
44
|
-
export interface AmfParser {
|
|
45
|
-
parse(): void;
|
|
46
|
-
parsedModel: any;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
51
|
export interface TopicModel {
|
|
50
52
|
id: string;
|
|
51
53
|
type: string;
|
|
52
|
-
amf:
|
|
53
|
-
parser:
|
|
54
|
+
amf: string;
|
|
55
|
+
parser: AmfModelParser;
|
|
54
56
|
}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DomainElement,
|
|
3
|
+
EndPoint,
|
|
4
|
+
Operation,
|
|
5
|
+
Shape
|
|
6
|
+
} from "@api-components/amf-helper-mixin";
|
|
1
7
|
import type {
|
|
2
8
|
ApiDocElement,
|
|
3
9
|
ApiEndpointElement,
|
|
@@ -37,7 +43,7 @@ export function createSummaryElement(amf: Json): HTMLElement {
|
|
|
37
43
|
*/
|
|
38
44
|
export function createEndpointElement(
|
|
39
45
|
amf: Json,
|
|
40
|
-
endpointModel:
|
|
46
|
+
endpointModel: EndPoint,
|
|
41
47
|
selected: string
|
|
42
48
|
): HTMLElement {
|
|
43
49
|
const el: ApiEndpointElement = document.createElement(
|
|
@@ -57,8 +63,8 @@ export function createEndpointElement(
|
|
|
57
63
|
*/
|
|
58
64
|
export function createMethodElement(
|
|
59
65
|
amf: Json,
|
|
60
|
-
endpointMethodModel:
|
|
61
|
-
methodModel:
|
|
66
|
+
endpointMethodModel: EndPoint | undefined,
|
|
67
|
+
methodModel: Operation | undefined
|
|
62
68
|
): HTMLElement {
|
|
63
69
|
const el: ApiMethodElement = document.createElement(
|
|
64
70
|
"api-method-documentation"
|
|
@@ -79,7 +85,7 @@ export function createMethodElement(
|
|
|
79
85
|
*/
|
|
80
86
|
export function createSecurityElement(
|
|
81
87
|
amf: Json,
|
|
82
|
-
securityModel:
|
|
88
|
+
securityModel: DomainElement | undefined
|
|
83
89
|
): HTMLElement {
|
|
84
90
|
const el: ApiSecurityElement = document.createElement(
|
|
85
91
|
"api-security-documentation"
|
|
@@ -98,7 +104,7 @@ export function createSecurityElement(
|
|
|
98
104
|
*/
|
|
99
105
|
export function createTypeElement(
|
|
100
106
|
amf: Json,
|
|
101
|
-
typeModel:
|
|
107
|
+
typeModel: Shape | undefined,
|
|
102
108
|
mediaTypes: Json
|
|
103
109
|
): HTMLElement {
|
|
104
110
|
const el: ApiTypeElement = document.createElement(
|
|
@@ -119,7 +125,7 @@ export function createTypeElement(
|
|
|
119
125
|
*/
|
|
120
126
|
export function createDocumentationElement(
|
|
121
127
|
amf: Json,
|
|
122
|
-
docsModel:
|
|
128
|
+
docsModel: DomainElement | undefined
|
|
123
129
|
): HTMLElement {
|
|
124
130
|
const el: ApiDocElement = document.createElement(
|
|
125
131
|
"api-documentation-document"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { track } from "dxUtils/analytics";
|
|
2
2
|
import { LightningElement, api } from "lwc";
|
|
3
|
-
import {
|
|
3
|
+
import { BreadcrumbItemVariant } from "typings/custom";
|
|
4
4
|
|
|
5
5
|
const BREADCRUMB_LONG = "breadcrumb_long";
|
|
6
6
|
const BREADCRUMB_BACK_ARROW = "breadcrumb_back-arrow";
|
|
@@ -8,8 +8,8 @@ const BREADCRUMB_BACK_ARROW = "breadcrumb_back-arrow";
|
|
|
8
8
|
const LONG_LABEL_NUMBER = 30;
|
|
9
9
|
export default class BreadcrumbItem extends LightningElement {
|
|
10
10
|
@api href?: string;
|
|
11
|
-
@api
|
|
12
|
-
@api
|
|
11
|
+
@api level?: string;
|
|
12
|
+
@api breadcrumbLabels?: string;
|
|
13
13
|
|
|
14
14
|
@api
|
|
15
15
|
get label() {
|
|
@@ -51,14 +51,21 @@ export default class BreadcrumbItem extends LightningElement {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
private onLinkClick(event: Event): void {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
track(event.target!, "custEv_breadcrumbClick", {
|
|
55
|
+
click_text: this.label,
|
|
56
|
+
click_url: `${window.location.origin}${this.href}`,
|
|
57
|
+
element_type: "link",
|
|
58
|
+
nav_type: "breadcrumb",
|
|
59
|
+
nav_level: this.level ? this.level + 1 : 1,
|
|
60
|
+
nav_item: this.breadcrumbLabels
|
|
61
|
+
});
|
|
57
62
|
|
|
58
|
-
track(event.target!,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
track(event.target!, "custEv_linkClick", {
|
|
64
|
+
click_text: this.label,
|
|
65
|
+
click_url: `${window.location.origin}${this.href}`,
|
|
66
|
+
element_title: this.label,
|
|
67
|
+
element_type: "link",
|
|
68
|
+
content_category: "cta"
|
|
62
69
|
});
|
|
63
70
|
}
|
|
64
71
|
}
|
|
@@ -3,21 +3,19 @@
|
|
|
3
3
|
<template if:true={displayCrumbs}>
|
|
4
4
|
<template if:false={renderSmallVariant}>
|
|
5
5
|
<doc-breadcrumb-item
|
|
6
|
-
analytics-event={analyticsEventName}
|
|
7
|
-
analytics-base-payload={analyticsBasePayload}
|
|
8
6
|
href={firstCrumb.href}
|
|
9
7
|
label={firstCrumb.label}
|
|
8
|
+
breadcrumb-labels={breadcrumbLabels}
|
|
10
9
|
></doc-breadcrumb-item>
|
|
11
10
|
<span class="breadcrumb-item_slash">/</span>
|
|
12
11
|
<template if:true={renderDropdown}>
|
|
13
12
|
<dx-dropdown
|
|
13
|
+
analytics-event="custEv_breadcrumbClick"
|
|
14
|
+
analytics-payload={ANALYTICS_PAYLOAD}
|
|
14
15
|
if:true={renderDropdown}
|
|
15
|
-
analytics-event={analyticsEventName}
|
|
16
|
-
analytics-base-payload={analyticsBasePayload}
|
|
17
16
|
options={dropdownOptions}
|
|
18
17
|
open-on-hover
|
|
19
18
|
placement="bottom"
|
|
20
|
-
suppress-gtm-nav-headings
|
|
21
19
|
variant="indented"
|
|
22
20
|
width="fit-content"
|
|
23
21
|
>
|
|
@@ -32,11 +30,11 @@
|
|
|
32
30
|
</template>
|
|
33
31
|
<template for:each={breadcrumbItems} for:item="breadcrumb">
|
|
34
32
|
<doc-breadcrumb-item
|
|
35
|
-
analytics-event={analyticsEventName}
|
|
36
|
-
analytics-base-payload={analyticsBasePayload}
|
|
37
33
|
href={breadcrumb.href}
|
|
38
34
|
key={breadcrumb.id}
|
|
39
35
|
label={breadcrumb.label}
|
|
36
|
+
level={breadcrumb.level}
|
|
37
|
+
breadcrumb-labels={breadcrumbLabels}
|
|
40
38
|
></doc-breadcrumb-item>
|
|
41
39
|
<span class="breadcrumb-item_slash" key={breadcrumb.label}>
|
|
42
40
|
/
|
|
@@ -44,14 +42,14 @@
|
|
|
44
42
|
</template>
|
|
45
43
|
<doc-breadcrumb-item
|
|
46
44
|
label={lastCrumb.label}
|
|
45
|
+
breadcrumb-labels={breadcrumbLabels}
|
|
47
46
|
></doc-breadcrumb-item>
|
|
48
47
|
</template>
|
|
49
48
|
<template if:true={renderSmallVariant}>
|
|
50
49
|
<doc-breadcrumb-item
|
|
51
|
-
analytics-event={analyticsEventName}
|
|
52
|
-
analytics-base-payload={analyticsBasePayload}
|
|
53
50
|
href={lastLinkCrump.href}
|
|
54
51
|
label={lastLinkCrump.label}
|
|
52
|
+
breadcrumb-labels={breadcrumbLabels}
|
|
55
53
|
variant="back-arrow"
|
|
56
54
|
></doc-breadcrumb-item>
|
|
57
55
|
</template>
|
|
@@ -17,13 +17,6 @@ const CONSTANTS = {
|
|
|
17
17
|
dropdownWidth: 32
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
export const ANALYTICS_EVENT_NAME = "custEv_breadcrumbClick";
|
|
21
|
-
export const ANALYTICS_BASE_PAYLOAD = {
|
|
22
|
-
elementType: "breadcrumb",
|
|
23
|
-
locationOnPage: "breadcrumb",
|
|
24
|
-
ctaClick: true
|
|
25
|
-
};
|
|
26
|
-
|
|
27
20
|
export default class Breadcrumbs extends LightningElement {
|
|
28
21
|
@api ariaLabel: string = "Documentation Breadcrumbs";
|
|
29
22
|
|
|
@@ -35,8 +28,8 @@ export default class Breadcrumbs extends LightningElement {
|
|
|
35
28
|
set breadcrumbs(value) {
|
|
36
29
|
this.normalizeAndAssignBreadcrumbs(value);
|
|
37
30
|
this.calculateBreadcrumbsConfigs();
|
|
38
|
-
if (this.
|
|
39
|
-
this.
|
|
31
|
+
if (this.isRendered) {
|
|
32
|
+
this.onWidthOrContentChange();
|
|
40
33
|
}
|
|
41
34
|
}
|
|
42
35
|
|
|
@@ -52,9 +45,9 @@ export default class Breadcrumbs extends LightningElement {
|
|
|
52
45
|
private _breadcrumbs: Breadcrumb[] = [];
|
|
53
46
|
private _pixelPerCharacter = CONSTANTS.pixelPerCharacter;
|
|
54
47
|
private navWidth = 0;
|
|
55
|
-
private observer: ResizeObserver | null = null;
|
|
56
48
|
private breadcrumbConfigs: BreadcrumbConfig[] = [];
|
|
57
49
|
private dropdownOptionAmount? = 0;
|
|
50
|
+
private isRendered = false;
|
|
58
51
|
|
|
59
52
|
private get renderSmallVariant(): boolean {
|
|
60
53
|
return (
|
|
@@ -100,38 +93,38 @@ export default class Breadcrumbs extends LightningElement {
|
|
|
100
93
|
return this.breadcrumbs[0];
|
|
101
94
|
}
|
|
102
95
|
|
|
103
|
-
private get
|
|
104
|
-
return this.breadcrumbs
|
|
96
|
+
private get breadcrumbLabels(): string {
|
|
97
|
+
return this.breadcrumbs.map((crumb) => crumb.label).join(":");
|
|
105
98
|
}
|
|
106
99
|
|
|
107
|
-
private get
|
|
108
|
-
return
|
|
100
|
+
private get lastCrumb(): Breadcrumb {
|
|
101
|
+
return this.breadcrumbs[this.breadcrumbs.length - 1];
|
|
109
102
|
}
|
|
110
103
|
|
|
111
|
-
|
|
104
|
+
// this payload is only used for breadcrumb dropdown
|
|
105
|
+
private get ANALYTICS_PAYLOAD() {
|
|
112
106
|
return {
|
|
113
|
-
|
|
114
|
-
|
|
107
|
+
element_type: "link",
|
|
108
|
+
nav_type: "breadcrumb",
|
|
109
|
+
nav_level: 1
|
|
115
110
|
};
|
|
116
111
|
}
|
|
117
112
|
|
|
113
|
+
private onWidthOrContentChange = () => {
|
|
114
|
+
this.navWidth = this.template
|
|
115
|
+
.querySelector("nav")!
|
|
116
|
+
.getBoundingClientRect().width;
|
|
117
|
+
this.updateDropdownOptionAmount();
|
|
118
|
+
};
|
|
119
|
+
|
|
118
120
|
renderedCallback(): void {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
if (this.navWidth === nav.contentRect.width) {
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
this.navWidth = nav.contentRect.width;
|
|
126
|
-
this.updateDropdownOptionAmount();
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
this.observer.observe(this.template.querySelector("nav")!);
|
|
130
|
-
}
|
|
121
|
+
this.isRendered = true;
|
|
122
|
+
this.onWidthOrContentChange();
|
|
123
|
+
window.addEventListener("resize", this.onWidthOrContentChange);
|
|
131
124
|
}
|
|
132
125
|
|
|
133
126
|
disconnectedCallback(): void {
|
|
134
|
-
this.
|
|
127
|
+
window.removeEventListener("resize", this.onWidthOrContentChange);
|
|
135
128
|
}
|
|
136
129
|
|
|
137
130
|
private normalizeAndAssignBreadcrumbs(breadcrumbs?: Breadcrumb[] | string) {
|
|
@@ -139,10 +132,13 @@ export default class Breadcrumbs extends LightningElement {
|
|
|
139
132
|
return;
|
|
140
133
|
}
|
|
141
134
|
|
|
142
|
-
this._breadcrumbs = toJson(breadcrumbs).map(
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
135
|
+
this._breadcrumbs = toJson(breadcrumbs).map(
|
|
136
|
+
(crumb: Breadcrumb, index: number) => ({
|
|
137
|
+
...crumb,
|
|
138
|
+
id: crumb.id || crumb.href,
|
|
139
|
+
level: index
|
|
140
|
+
})
|
|
141
|
+
);
|
|
146
142
|
}
|
|
147
143
|
|
|
148
144
|
private updateDropdownOptionAmount(): void {
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Sliding Chat Component (doc-chat)
|
|
2
|
+
|
|
3
|
+
A self-contained sliding chat component with a floating trigger button that can be embedded in any layout, perfect for customer support, documentation help, or any conversational interface.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🎯 **Sliding Component**: Slides in/out with smooth animations
|
|
8
|
+
- 🔘 **Floating Trigger**: Built-in floating button to open chat (bottom-right corner)
|
|
9
|
+
- 💬 **Real-time Chat**: Interactive messaging with typing indicators
|
|
10
|
+
- 🎨 **Modern Design**: Clean, responsive interface with subtle animations
|
|
11
|
+
- ⚙️ **Configurable**: Customizable title, placeholder, and assistant name
|
|
12
|
+
- 📱 **Mobile Friendly**: Full-width on mobile devices
|
|
13
|
+
- ♿ **Accessible**: ARIA labels and keyboard navigation
|
|
14
|
+
- 🎭 **Storybook Ready**: Multiple story variations for testing
|
|
15
|
+
|
|
16
|
+
## Basic Usage
|
|
17
|
+
|
|
18
|
+
The component is completely self-contained with a built-in floating trigger button:
|
|
19
|
+
|
|
20
|
+
```html
|
|
21
|
+
<doc-chat
|
|
22
|
+
title="Customer Support"
|
|
23
|
+
placeholder="How can we help you today?"
|
|
24
|
+
assistant-name="Support Bot"
|
|
25
|
+
is-open="false"
|
|
26
|
+
show-timestamp="true"
|
|
27
|
+
></doc-chat>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
That's it! The component will automatically show a floating chat button in the bottom-right corner when closed, and slide in the chat interface when opened.
|
|
31
|
+
|
|
32
|
+
## Properties
|
|
33
|
+
|
|
34
|
+
| Property | Type | Default | Description |
|
|
35
|
+
|----------|------|---------|-------------|
|
|
36
|
+
| `title` | String | `"Chat"` | Title displayed in the chat header |
|
|
37
|
+
| `placeholder` | String | `"Type your message..."` | Placeholder text for input field |
|
|
38
|
+
| `assistant-name` | String | `"Assistant"` | Name of the assistant/bot |
|
|
39
|
+
| `disabled` | Boolean | `false` | Disables the chat functionality |
|
|
40
|
+
| `show-timestamp` | Boolean | `false` | Shows timestamps on messages |
|
|
41
|
+
| `is-open` | Boolean | `false` | Controls sidebar visibility |
|
|
42
|
+
|
|
43
|
+
## Methods
|
|
44
|
+
|
|
45
|
+
| Method | Description |
|
|
46
|
+
|--------|-------------|
|
|
47
|
+
| `openChat()` | Opens the chat sidebar |
|
|
48
|
+
| `closeChat()` | Closes the chat sidebar |
|
|
49
|
+
|
|
50
|
+
## Events
|
|
51
|
+
|
|
52
|
+
| Event | Description | Detail |
|
|
53
|
+
|-------|-------------|--------|
|
|
54
|
+
| `chatopened` | Fired when chat is opened | `{ opened: true }` |
|
|
55
|
+
| `chatclosed` | Fired when chat is closed | `{ closed: true }` |
|
|
56
|
+
|
|
57
|
+
## Integration Example
|
|
58
|
+
|
|
59
|
+
### Simple Integration (Self-Contained)
|
|
60
|
+
```html
|
|
61
|
+
<!-- The component includes its own trigger button -->
|
|
62
|
+
<doc-chat
|
|
63
|
+
title="Customer Support"
|
|
64
|
+
placeholder="How can we help you today?"
|
|
65
|
+
assistant-name="Support Bot"
|
|
66
|
+
show-timestamp="true"
|
|
67
|
+
is-open="false"
|
|
68
|
+
></doc-chat>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Advanced Integration (With Custom Triggers)
|
|
72
|
+
```html
|
|
73
|
+
<!-- Optional: Custom trigger button -->
|
|
74
|
+
<button id="chat-trigger" onclick="openSupportChat()">
|
|
75
|
+
💬 Need Help?
|
|
76
|
+
</button>
|
|
77
|
+
|
|
78
|
+
<!-- Chat component -->
|
|
79
|
+
<doc-chat
|
|
80
|
+
id="support-chat"
|
|
81
|
+
title="Customer Support"
|
|
82
|
+
placeholder="How can we help you today?"
|
|
83
|
+
assistant-name="Support Bot"
|
|
84
|
+
show-timestamp="true"
|
|
85
|
+
is-open="false"
|
|
86
|
+
></doc-chat>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### JavaScript
|
|
90
|
+
```javascript
|
|
91
|
+
// Optional: Custom trigger function
|
|
92
|
+
function openSupportChat() {
|
|
93
|
+
const chat = document.getElementById('support-chat');
|
|
94
|
+
chat.openChat();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Listen for chat events
|
|
98
|
+
document.getElementById('support-chat').addEventListener('chatclosed', (event) => {
|
|
99
|
+
console.log('Chat was closed');
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
document.getElementById('support-chat').addEventListener('chatopened', (event) => {
|
|
103
|
+
console.log('Chat was opened');
|
|
104
|
+
});
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Styling
|
|
108
|
+
|
|
109
|
+
The component uses CSS custom properties for easy theming:
|
|
110
|
+
|
|
111
|
+
```css
|
|
112
|
+
doc-chat {
|
|
113
|
+
--chat-width: 400px;
|
|
114
|
+
--chat-z-index: 1000;
|
|
115
|
+
--chat-transition-duration: 0.3s;
|
|
116
|
+
--chat-header-bg: #f8f9fa;
|
|
117
|
+
--chat-primary-color: #0066cc;
|
|
118
|
+
--chat-border-color: #e0e0e0;
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Responsive Behavior
|
|
123
|
+
|
|
124
|
+
- **Desktop**: Fixed width component (400px)
|
|
125
|
+
- **Tablet**: Full width component
|
|
126
|
+
- **Mobile**: Full width component
|
|
127
|
+
|
|
128
|
+
## Accessibility
|
|
129
|
+
|
|
130
|
+
- ARIA labels for screen readers
|
|
131
|
+
- Keyboard navigation support
|
|
132
|
+
- High contrast mode support
|
|
133
|
+
- Reduced motion preferences respected
|
|
134
|
+
|
|
135
|
+
## Assistant Response Simulation
|
|
136
|
+
|
|
137
|
+
The component includes a built-in response simulation system that responds to:
|
|
138
|
+
|
|
139
|
+
- **Greetings**: "Hello", "Hi" → Friendly greeting
|
|
140
|
+
- **Help requests**: "Help" → Assistance offer
|
|
141
|
+
- **Documentation**: "Documentation", "Docs" → Navigation help
|
|
142
|
+
- **General messages**: Contextual responses
|
|
143
|
+
|
|
144
|
+
### Replacing with Real API
|
|
145
|
+
|
|
146
|
+
To integrate with a real chat API, replace the `simulateAssistantResponse` method:
|
|
147
|
+
|
|
148
|
+
```javascript
|
|
149
|
+
// Replace this method in your extended component
|
|
150
|
+
simulateAssistantResponse(userMessage) {
|
|
151
|
+
// Call your chat API
|
|
152
|
+
fetch('/api/chat', {
|
|
153
|
+
method: 'POST',
|
|
154
|
+
headers: { 'Content-Type': 'application/json' },
|
|
155
|
+
body: JSON.stringify({ message: userMessage })
|
|
156
|
+
})
|
|
157
|
+
.then(response => response.json())
|
|
158
|
+
.then(data => {
|
|
159
|
+
this.addMessage(data.response, 'assistant');
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Browser Support
|
|
165
|
+
|
|
166
|
+
- Chrome 80+
|
|
167
|
+
- Firefox 72+
|
|
168
|
+
- Safari 13+
|
|
169
|
+
- Edge 80+
|
|
170
|
+
|
|
171
|
+
## Examples
|
|
172
|
+
|
|
173
|
+
Check out the Storybook examples for various use cases:
|
|
174
|
+
|
|
175
|
+
- **Default**: Basic chat setup
|
|
176
|
+
- **With Timestamps**: Shows message timestamps
|
|
177
|
+
- **Interactive Demo**: Fully functional example
|
|
178
|
+
- **Mobile View**: Mobile device simulation
|
|
179
|
+
- **Chat Trigger Example**: Integration patterns
|