@salesforcedevs/docs-components 1.35.0-ver-picker-1 → 1.40.0-docs-feedback-3
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/package.json +1 -1
- package/src/modules/doc/header/header.ts +14 -3
- package/src/modules/doc/unifiedContentLayout/unifiedContentLayout.ts +46 -8
- package/src/modules/doc/versionPicker/versionPicker.css +0 -114
- package/src/modules/doc/versionPicker/versionPicker.html +0 -37
- package/src/modules/doc/versionPicker/versionPicker.ts +0 -42
package/package.json
CHANGED
|
@@ -74,6 +74,13 @@ export default class Header extends HeaderBase {
|
|
|
74
74
|
return (this.hideDocHeader && !this.mobile) || this.showDocDivider;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
private get isDocsPath(): boolean {
|
|
78
|
+
return (
|
|
79
|
+
window.location.pathname.includes("/docs/") &&
|
|
80
|
+
window.location.pathname !== "/docs/apis"
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
77
84
|
connectedCallback(): void {
|
|
78
85
|
super.connectedCallback();
|
|
79
86
|
this.tabletMatchMedia = window.matchMedia(
|
|
@@ -83,9 +90,7 @@ export default class Header extends HeaderBase {
|
|
|
83
90
|
this.tabletMatchMedia.addEventListener("change", this.onTabletChange);
|
|
84
91
|
|
|
85
92
|
if (
|
|
86
|
-
(!this.shouldHideHeader &&
|
|
87
|
-
window.location.pathname.includes("/docs/") &&
|
|
88
|
-
window.location.pathname !== "/docs/apis") ||
|
|
93
|
+
(!this.shouldHideHeader && this.isDocsPath) ||
|
|
89
94
|
window.location.pathname ===
|
|
90
95
|
"/tableau/embedding-playground/overview" ||
|
|
91
96
|
isStorybook()
|
|
@@ -109,6 +114,12 @@ export default class Header extends HeaderBase {
|
|
|
109
114
|
);
|
|
110
115
|
}
|
|
111
116
|
|
|
117
|
+
renderedCallback(): void {
|
|
118
|
+
if (this.hideDocHeader) {
|
|
119
|
+
this.shouldRender = !this.shouldHideHeader && this.isDocsPath;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
112
123
|
private onTabletChange = (e: MediaQueryListEvent | MediaQueryList) =>
|
|
113
124
|
(this.tablet = e.matches);
|
|
114
125
|
|
|
@@ -10,11 +10,38 @@ import type { OptionWithLink, TreeNode } from "typings/custom";
|
|
|
10
10
|
*/
|
|
11
11
|
const TOPIC_TYPE_SPEC = "spec";
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Walks down the first-child chain and returns the first markdown content
|
|
15
|
+
* page found, descending through nested content-less parents. Returns
|
|
16
|
+
* undefined if the chain breaks on a spec or external link before reaching a
|
|
17
|
+
* content page.
|
|
18
|
+
*/
|
|
19
|
+
function firstChildContentPage(node: TreeNode): TreeNode | undefined {
|
|
20
|
+
const firstChild = node.children?.[0];
|
|
21
|
+
if (!firstChild) {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const isSpec =
|
|
26
|
+
(firstChild as { topicType?: string }).topicType === TOPIC_TYPE_SPEC;
|
|
27
|
+
const isExternal = firstChild.link?.target === "_blank";
|
|
28
|
+
if (isSpec || isExternal) {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (firstChild.link?.href) {
|
|
33
|
+
return firstChild;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return firstChildContentPage(firstChild);
|
|
37
|
+
}
|
|
38
|
+
|
|
13
39
|
/**
|
|
14
40
|
* Translates per-topic `topicType` into the generic `showForwardArrow` flag
|
|
15
|
-
* that `dx-tree-tile` reads (spec topics get the forward arrow icon for Redoc)
|
|
41
|
+
* that `dx-tree-tile` reads (spec topics get the forward arrow icon for Redoc),
|
|
42
|
+
* and redirects content-less parent topics whose first child is a content page
|
|
16
43
|
*/
|
|
17
|
-
function
|
|
44
|
+
function decorateTopics(
|
|
18
45
|
topics: Array<TreeNode & { topicType?: string }> | undefined
|
|
19
46
|
): TreeNode[] | undefined {
|
|
20
47
|
return topics?.map((topic) => {
|
|
@@ -23,10 +50,23 @@ function decorateTopicsWithForwardArrow(
|
|
|
23
50
|
decorated.showForwardArrow = true;
|
|
24
51
|
}
|
|
25
52
|
if (decorated.children) {
|
|
26
|
-
decorated.children =
|
|
27
|
-
decorated.children
|
|
28
|
-
);
|
|
53
|
+
decorated.children = decorateTopics(decorated.children);
|
|
29
54
|
}
|
|
55
|
+
|
|
56
|
+
/** Redirect a parent that has no content of its own to its first child
|
|
57
|
+
* but only when that first child is itself a content page
|
|
58
|
+
*/
|
|
59
|
+
const isContentlessParent =
|
|
60
|
+
!!decorated.children?.length && !decorated.link?.href;
|
|
61
|
+
|
|
62
|
+
if (isContentlessParent) {
|
|
63
|
+
decorated.redirectToChild = true;
|
|
64
|
+
const firstChild = firstChildContentPage(topic);
|
|
65
|
+
if (firstChild?.link) {
|
|
66
|
+
decorated.link = { ...firstChild.link };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
30
70
|
return decorated;
|
|
31
71
|
});
|
|
32
72
|
}
|
|
@@ -77,9 +117,7 @@ export default class UnifiedContentLayout extends LightningElement {
|
|
|
77
117
|
}
|
|
78
118
|
|
|
79
119
|
set sidebarContent(value: string) {
|
|
80
|
-
this._sidebarContent =
|
|
81
|
-
toJson(value)?.topics
|
|
82
|
-
);
|
|
120
|
+
this._sidebarContent = decorateTopics(toJson(value)?.topics);
|
|
83
121
|
}
|
|
84
122
|
|
|
85
123
|
private get enableFooter(): boolean {
|
|
@@ -62,117 +62,3 @@ dx-type-badge.not-latest-badge {
|
|
|
62
62
|
|
|
63
63
|
margin-left: var(--dx-g-spacing-sm);
|
|
64
64
|
}
|
|
65
|
-
|
|
66
|
-
/* ------------------------------------------------------------------ *
|
|
67
|
-
* Small "dot" variant (opt-in via `small`). Additive
|
|
68
|
-
* ------------------------------------------------------------------ */
|
|
69
|
-
|
|
70
|
-
/* Scoped hooks so the shared dx-popover/dx-dropdown-option keep their defaults. */
|
|
71
|
-
.version-picker-dropdown-small {
|
|
72
|
-
--dx-c-dropdown-option-font-size: var(--dx-g-text-xs);
|
|
73
|
-
--dx-c-dropdown-option-padding: var(--dx-g-spacing-sm)
|
|
74
|
-
var(--dx-g-spacing-lg);
|
|
75
|
-
--dx-c-dropdown-option-border-radius: 0;
|
|
76
|
-
--dx-c-popover-border: none;
|
|
77
|
-
--dx-c-popover-padding: var(--dx-g-spacing-sm) 0;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
.version-picker-button-small {
|
|
81
|
-
display: flex;
|
|
82
|
-
width: fit-content;
|
|
83
|
-
max-width: 104px;
|
|
84
|
-
border-radius: var(--dx-g-spacing-xs);
|
|
85
|
-
|
|
86
|
-
--dx-c-button-font-size: var(--dx-g-text-xs);
|
|
87
|
-
--dx-c-button-font-weight: var(--dx-g-font-normal);
|
|
88
|
-
--dx-c-button-line-height: 18px;
|
|
89
|
-
--dx-g-button-icon-color: var(--dx-g-gray-50);
|
|
90
|
-
--dx-g-spacing-sm: var(--dx-g-spacing-2xs);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/* min-width: 0 on each flex ancestor lets the label truncate: a flex item's
|
|
94
|
-
default min-width: auto refuses to shrink below its content and overrides the
|
|
95
|
-
host's max-width, so without this the trigger overflows instead. */
|
|
96
|
-
.version-picker-button-small::part(content) {
|
|
97
|
-
display: flex;
|
|
98
|
-
flex: 1;
|
|
99
|
-
min-width: 0;
|
|
100
|
-
width: auto;
|
|
101
|
-
overflow: hidden;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/* Border is an inset box-shadow, not a real border, so thickening it on
|
|
105
|
-
hover/focus doesn't widen the fit-content box (no horizontal shift). */
|
|
106
|
-
.version-picker-button-small::part(container) {
|
|
107
|
-
box-sizing: border-box;
|
|
108
|
-
|
|
109
|
-
/* width:100% re-ties to the 104px-capped host (container is width:inherit,
|
|
110
|
-
which copies width but not max-width). */
|
|
111
|
-
width: 100%;
|
|
112
|
-
height: 24px;
|
|
113
|
-
padding: 0 var(--dx-g-spacing-xs);
|
|
114
|
-
border-radius: var(--dx-g-spacing-xs);
|
|
115
|
-
background: #fff;
|
|
116
|
-
box-shadow: inset 0 0 0 1px var(--dx-g-gray-50);
|
|
117
|
-
color: var(--dx-g-gray-10);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
.version-picker-button-small::part(container):hover {
|
|
121
|
-
background: var(--dx-g-blue-vibrant-95);
|
|
122
|
-
box-shadow: inset 0 0 0 2px var(--dx-g-blue-vibrant-20);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
.version-picker-button-small:hover,
|
|
126
|
-
.version-picker-button-small:focus-within,
|
|
127
|
-
.version-picker-button-small[aria-expanded="true"] {
|
|
128
|
-
--dx-g-button-icon-color: var(--dx-g-blue-vibrant-20);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/* Also matches aria-expanded so the ring stays while the menu is open (opening
|
|
132
|
-
moves focus into the menu, which would otherwise drop :focus-within). */
|
|
133
|
-
.version-picker-button-small:focus-within::part(container),
|
|
134
|
-
.version-picker-button-small[aria-expanded="true"]::part(container) {
|
|
135
|
-
background: var(--dx-g-blue-vibrant-95);
|
|
136
|
-
box-shadow: inset 0 0 0 2px var(--dx-g-blue-vibrant-20), 0 0 0 2px #fff,
|
|
137
|
-
0 0 0 4px var(--dx-g-blue-vibrant-60);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
.selected-version-small {
|
|
141
|
-
flex: 1;
|
|
142
|
-
min-width: 0;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
.version-picker-dot {
|
|
146
|
-
flex: 0 0 auto;
|
|
147
|
-
width: 8px;
|
|
148
|
-
height: 8px;
|
|
149
|
-
margin-right: var(--dx-g-spacing-xs);
|
|
150
|
-
border-radius: 50%;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
.version-picker-dot-latest {
|
|
154
|
-
background: var(--dx-g-green-vibrant-60);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
.version-picker-dot-not-latest {
|
|
158
|
-
background: var(--dx-g-yellow-vibrant-80);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
.version-picker-readonly-small {
|
|
162
|
-
display: inline-flex;
|
|
163
|
-
align-items: center;
|
|
164
|
-
box-sizing: border-box;
|
|
165
|
-
width: fit-content;
|
|
166
|
-
max-width: 104px;
|
|
167
|
-
height: 24px;
|
|
168
|
-
margin: 0;
|
|
169
|
-
padding: 0 var(--dx-g-spacing-xs);
|
|
170
|
-
border: 1px solid var(--dx-g-gray-80);
|
|
171
|
-
border-radius: var(--dx-g-spacing-xs);
|
|
172
|
-
overflow: hidden;
|
|
173
|
-
color: var(--dx-g-gray-10);
|
|
174
|
-
text-overflow: ellipsis;
|
|
175
|
-
white-space: nowrap;
|
|
176
|
-
font: var(--dx-g-font-normal) var(--dx-g-text-xs) / 18px
|
|
177
|
-
var(--dx-g-font-sans), sans-serif;
|
|
178
|
-
}
|
|
@@ -1,43 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div lwc:if={showVersionPicker} class="version-picker-container">
|
|
3
|
-
<!-- Small read-only: plain value, no dropdown -->
|
|
4
|
-
<p lwc:if={readOnly} class="version-picker-readonly-small">
|
|
5
|
-
{selectedVersion.label}
|
|
6
|
-
</p>
|
|
7
|
-
|
|
8
|
-
<!-- Small "dot" variant -->
|
|
9
3
|
<dx-dropdown
|
|
10
|
-
lwc:elseif={small}
|
|
11
|
-
class="version-picker-dropdown-small"
|
|
12
|
-
options={versions}
|
|
13
|
-
analytics-event="custEv_docVersionSelect"
|
|
14
|
-
analytics-payload={analyticsPayload}
|
|
15
|
-
value={selectedVersion.id}
|
|
16
|
-
onchange={onVersionChange}
|
|
17
|
-
>
|
|
18
|
-
<dx-button
|
|
19
|
-
class="version-picker-button version-picker-button-small"
|
|
20
|
-
variant="tertiary"
|
|
21
|
-
size="small"
|
|
22
|
-
font="sans"
|
|
23
|
-
icon-symbol="chevrondown"
|
|
24
|
-
icon-size="xsmall"
|
|
25
|
-
aria-label={smallTriggerAriaLabel}
|
|
26
|
-
>
|
|
27
|
-
<div class="selected-version selected-version-small">
|
|
28
|
-
<template lwc:if={showLatestTag}>
|
|
29
|
-
<span class={dotClass} aria-hidden="true"></span>
|
|
30
|
-
</template>
|
|
31
|
-
<p class="selected-version-label">
|
|
32
|
-
{selectedVersion.label}
|
|
33
|
-
</p>
|
|
34
|
-
</div>
|
|
35
|
-
</dx-button>
|
|
36
|
-
</dx-dropdown>
|
|
37
|
-
|
|
38
|
-
<!-- Default (existing) -->
|
|
39
|
-
<dx-dropdown
|
|
40
|
-
lwc:else
|
|
41
4
|
options={versions}
|
|
42
5
|
analytics-event="custEv_docVersionSelect"
|
|
43
6
|
analytics-payload={analyticsPayload}
|
|
@@ -12,8 +12,6 @@ export default class VersionPicker extends LightningElement {
|
|
|
12
12
|
private _selectedVersion?: OptionWithNested;
|
|
13
13
|
private _latestVersion: boolean = false;
|
|
14
14
|
private _hideBadge: boolean = false;
|
|
15
|
-
private _small: boolean = false;
|
|
16
|
-
private _readOnly: boolean = false;
|
|
17
15
|
|
|
18
16
|
@api
|
|
19
17
|
get versions() {
|
|
@@ -53,27 +51,6 @@ export default class VersionPicker extends LightningElement {
|
|
|
53
51
|
this._hideBadge = normalizeBoolean(value);
|
|
54
52
|
}
|
|
55
53
|
|
|
56
|
-
// Opt-in compact "dot" variant (24px, abbreviated label). Off by default so
|
|
57
|
-
// existing consumers render the default trigger unchanged.
|
|
58
|
-
@api
|
|
59
|
-
get small() {
|
|
60
|
-
return this._small;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
set small(value) {
|
|
64
|
-
this._small = normalizeBoolean(value);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Opt-in read-only state: plain value, no dropdown menu.
|
|
68
|
-
@api
|
|
69
|
-
get readOnly() {
|
|
70
|
-
return this._readOnly;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
set readOnly(value) {
|
|
74
|
-
this._readOnly = normalizeBoolean(value);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
54
|
private get showVersionPicker() {
|
|
78
55
|
return this._versions && this._versions.length !== 0;
|
|
79
56
|
}
|
|
@@ -82,25 +59,6 @@ export default class VersionPicker extends LightningElement {
|
|
|
82
59
|
return !this.hideBadge;
|
|
83
60
|
}
|
|
84
61
|
|
|
85
|
-
private get dotClass(): string {
|
|
86
|
-
return `version-picker-dot ${
|
|
87
|
-
this.latestVersion
|
|
88
|
-
? "version-picker-dot-latest"
|
|
89
|
-
: "version-picker-dot-not-latest"
|
|
90
|
-
}`;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Accessible name for the small trigger: includes the latest state so it
|
|
94
|
-
// isn't conveyed by the dot's color alone (WCAG 1.4.1). Omits the state
|
|
95
|
-
// when the indicator is hidden.
|
|
96
|
-
private get smallTriggerAriaLabel(): string {
|
|
97
|
-
const label = this.selectedVersion?.label ?? "";
|
|
98
|
-
if (!this.showLatestTag) {
|
|
99
|
-
return label;
|
|
100
|
-
}
|
|
101
|
-
return `${label}, ${this.latestVersion ? "Latest" : "Not Latest"}`;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
62
|
private onVersionChange(e: CustomEvent) {
|
|
105
63
|
this.dispatchEvent(new CustomEvent("change", { detail: e.detail }));
|
|
106
64
|
}
|