@salesforcedevs/dx-components 1.40.4 → 1.40.5-topic-alpha.1
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 +1 -0
- package/package.json +2 -3
- package/src/modules/dx/button/button.css +2 -2
- package/src/modules/dx/dropdown/dropdown.css +22 -22
- package/src/modules/dx/dropdown/dropdown.html +1 -1
- package/src/modules/dx/dropdown/dropdown.ts +16 -1
- package/src/modules/dx/dropdownOption/dropdownOption.css +21 -2
- package/src/modules/dx/popover/popover.ts +15 -3
- package/src/modules/dx/tree/treeHandler.ts +77 -10
- package/src/modules/dx/treeItem/treeItem.css +27 -0
- package/src/modules/dx/treeItem/treeItem.html +16 -2
- package/src/modules/dx/treeItem/treeItem.ts +91 -6
- package/src/modules/dx/treeTile/treeTile.css +4 -0
- package/src/modules/dx/treeTile/treeTile.ts +7 -1
- package/src/modules/dx/typeBadge/typeBadge.ts +23 -2
- package/src/modules/dxHelpers/commonTreeItem/commonTreeItem.css +4 -0
- package/src/modules/dxHelpers/typeBadge/typeBadge.css +22 -0
- package/src/modules/dxUtils/topicVersion/topicVersion.ts +467 -0
- package/LICENSE +0 -12
- package/src/modules/dx/searchResults/coveo.css +0 -18001
- package/src/modules/dx/tooltip/microtip.css +0 -269
package/lwc.config.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforcedevs/dx-components",
|
|
3
|
-
"version": "1.40.
|
|
3
|
+
"version": "1.40.5-topic-alpha.1",
|
|
4
4
|
"description": "DX Lightning web components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"engines": {
|
|
@@ -43,6 +43,5 @@
|
|
|
43
43
|
"eventsourcemock": "2.0.0",
|
|
44
44
|
"luxon": "3.4.4",
|
|
45
45
|
"msw": "^2.12.4"
|
|
46
|
-
}
|
|
47
|
-
"gitHead": "37647f2998066bc5a3e345e3bfdbd70dfefa5adc"
|
|
46
|
+
}
|
|
48
47
|
}
|
|
@@ -86,11 +86,11 @@
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
.button.icon-right:not(.slot-empty) > *:nth-child(2) {
|
|
89
|
-
margin-left: var(--dx-g-spacing-sm);
|
|
89
|
+
margin-left: var(--dx-c-button-icon-gap, var(--dx-g-spacing-sm));
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
.button.icon-left:not(.slot-empty) > *:nth-child(2) {
|
|
93
|
-
margin-right: var(--dx-g-spacing-sm);
|
|
93
|
+
margin-right: var(--dx-c-button-icon-gap, var(--dx-g-spacing-sm));
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
.button.style-icon.slot-empty {
|
|
@@ -14,30 +14,30 @@
|
|
|
14
14
|
display: none;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
/* Opt-in fit-content menu: hugs the labels (so it can be as narrow as the
|
|
18
|
+
shortest one) and stops at --dx-c-dropdown-menu-max-width. Defaults still
|
|
19
|
+
truncate; set --dx-c-dropdown-fit-white-space: normal to wrap instead. */
|
|
20
|
+
.menu-fit-content::part(content) {
|
|
21
|
+
box-sizing: border-box;
|
|
22
|
+
width: max-content;
|
|
23
|
+
max-width: var(
|
|
24
|
+
--dx-c-dropdown-menu-max-width,
|
|
25
|
+
calc(100vw - var(--dx-g-spacing-lg))
|
|
26
|
+
);
|
|
20
27
|
}
|
|
21
28
|
|
|
22
|
-
.menu-fit-content
|
|
23
|
-
width:
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
.menu-fit-content .menu_heading {
|
|
35
|
-
margin: 0;
|
|
36
|
-
padding: var(--dx-g-spacing-smd) var(--dx-g-spacing-lg);
|
|
37
|
-
font-family: var(--dx-g-font-sans);
|
|
38
|
-
line-height: var(--dx-g-spacing-mlg);
|
|
39
|
-
text-transform: none;
|
|
40
|
-
color: var(--dx-g-gray-10);
|
|
29
|
+
.menu-fit-content {
|
|
30
|
+
--dx-c-dropdown-option-min-width: 0;
|
|
31
|
+
--dx-c-dropdown-option-label-display: block;
|
|
32
|
+
--dx-c-dropdown-option-white-space: var(
|
|
33
|
+
--dx-c-dropdown-fit-white-space,
|
|
34
|
+
nowrap
|
|
35
|
+
);
|
|
36
|
+
--dx-c-dropdown-option-overflow: var(--dx-c-dropdown-fit-overflow, hidden);
|
|
37
|
+
--dx-c-dropdown-option-text-overflow: var(
|
|
38
|
+
--dx-c-dropdown-fit-text-overflow,
|
|
39
|
+
ellipsis
|
|
40
|
+
);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
@media screen and (max-width: 1000px) {
|
|
@@ -82,20 +82,35 @@ export default class Dropdown extends LightningElement {
|
|
|
82
82
|
return this.areOptionsEmpty ? null : "menu";
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
// "fit-end" is fit-content, aligned to the trigger's end edge.
|
|
86
|
+
// "full" matches the trigger width. "fixed" and "fit-content" are unchanged.
|
|
85
87
|
private get isFitContent() {
|
|
86
|
-
return this.widthMode === "fit-content";
|
|
88
|
+
return this.widthMode === "fit-content" || this.widthMode === "fit-end";
|
|
87
89
|
}
|
|
88
90
|
|
|
91
|
+
private get effectivePlacement(): PopperPlacement | undefined {
|
|
92
|
+
return this.widthMode === "fit-end" ? "bottom-end" : this.placement;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// fit-content takes precedence; the misuse is surfaced in className() below.
|
|
89
96
|
private get effectiveWidth() {
|
|
90
97
|
return this.isFitContent ? null : this.width;
|
|
91
98
|
}
|
|
92
99
|
|
|
93
100
|
private get effectiveFullWidth() {
|
|
101
|
+
if (this.widthMode === "full") {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
94
104
|
return this.isFitContent ? false : this.fullWidth;
|
|
95
105
|
}
|
|
96
106
|
|
|
97
107
|
private get className() {
|
|
98
108
|
const fitContent = this.isFitContent;
|
|
109
|
+
if (fitContent && (this.width || this.fullWidth)) {
|
|
110
|
+
console.error(
|
|
111
|
+
'The "width-mode=fit-content" and "width"/"full-width" properties cannot be provided simultaneously. "width-mode=fit-content" is prioritized; "width"/"full-width" are ignored.'
|
|
112
|
+
);
|
|
113
|
+
}
|
|
99
114
|
return cx(
|
|
100
115
|
this.isNested && "menu-nested",
|
|
101
116
|
this.isNested &&
|
|
@@ -25,8 +25,14 @@
|
|
|
25
25
|
display: flex;
|
|
26
26
|
font-family: var(--dx-g-font-sans);
|
|
27
27
|
width: 100%;
|
|
28
|
-
|
|
28
|
+
|
|
29
|
+
/* Opt-in hooks; defaults preserve today's look. */
|
|
30
|
+
padding: var(--dx-c-dropdown-option-padding, var(--dx-g-spacing-sm));
|
|
29
31
|
font-size: var(--dx-g-text-sm);
|
|
32
|
+
border-radius: var(
|
|
33
|
+
--dx-c-dropdown-option-border-radius,
|
|
34
|
+
var(--dx-g-spacing-xs)
|
|
35
|
+
);
|
|
30
36
|
transition: var(--dx-g-transition-hue-1x);
|
|
31
37
|
align-items: center;
|
|
32
38
|
outline: none !important;
|
|
@@ -59,6 +65,9 @@
|
|
|
59
65
|
font-family: var(--dx-g-font-sans);
|
|
60
66
|
font-size: var(--dx-g-text-sm);
|
|
61
67
|
text-align: left;
|
|
68
|
+
|
|
69
|
+
/* Opt-in: set to 0 to let a long label truncate instead of overflow. */
|
|
70
|
+
min-width: var(--dx-c-dropdown-option-min-width, auto);
|
|
62
71
|
}
|
|
63
72
|
|
|
64
73
|
.option-indented .option_details {
|
|
@@ -68,10 +77,20 @@
|
|
|
68
77
|
|
|
69
78
|
.option_label {
|
|
70
79
|
color: var(--dx-c-dropdown-option-label-color, var(--dx-g-blue-vibrant-50));
|
|
71
|
-
|
|
80
|
+
|
|
81
|
+
/* Opt-in: set to block so text-overflow:ellipsis applies (ignored on flex). */
|
|
82
|
+
display: var(--dx-c-dropdown-option-label-display, flex);
|
|
72
83
|
align-items: center;
|
|
73
84
|
font-weight: var(--dx-c-dropdown-option-font-weight, var(--dx-g-font-bold));
|
|
74
85
|
font-size: var(--dx-c-dropdown-option-font-size, var(--dx-g-text-base));
|
|
86
|
+
|
|
87
|
+
/* Opt-in truncation: consumers set --dx-c-dropdown-option-white-space:
|
|
88
|
+
nowrap to truncate labels with an ellipsis instead of wrapping.
|
|
89
|
+
Defaults preserve today's wrapping behavior. */
|
|
90
|
+
white-space: var(--dx-c-dropdown-option-white-space, normal);
|
|
91
|
+
overflow: var(--dx-c-dropdown-option-overflow, visible);
|
|
92
|
+
overflow-wrap: var(--dx-c-dropdown-option-overflow-wrap, normal);
|
|
93
|
+
text-overflow: var(--dx-c-dropdown-option-text-overflow, clip);
|
|
75
94
|
}
|
|
76
95
|
|
|
77
96
|
.option-indented .option_label {
|
|
@@ -106,7 +106,11 @@ export default class Popover extends LightningElement {
|
|
|
106
106
|
if (this.control) {
|
|
107
107
|
this.control.setAttribute("aria-expanded", "false");
|
|
108
108
|
}
|
|
109
|
-
document.removeEventListener(
|
|
109
|
+
document.removeEventListener(
|
|
110
|
+
"click",
|
|
111
|
+
this.interactOutsideListener,
|
|
112
|
+
true
|
|
113
|
+
);
|
|
110
114
|
document.removeEventListener("focusout", this.interactOutsideListener);
|
|
111
115
|
if (this.openOnHover) {
|
|
112
116
|
document.removeEventListener(
|
|
@@ -132,7 +136,11 @@ export default class Popover extends LightningElement {
|
|
|
132
136
|
// LIFECYCLE METHODS
|
|
133
137
|
|
|
134
138
|
disconnectedCallback() {
|
|
135
|
-
document.removeEventListener(
|
|
139
|
+
document.removeEventListener(
|
|
140
|
+
"click",
|
|
141
|
+
this.interactOutsideListener,
|
|
142
|
+
true
|
|
143
|
+
);
|
|
136
144
|
document.removeEventListener("mousemove", this.interactOutsideListener);
|
|
137
145
|
document.removeEventListener("focusout", this.interactOutsideListener);
|
|
138
146
|
this.removeControlListeners();
|
|
@@ -295,7 +303,11 @@ export default class Popover extends LightningElement {
|
|
|
295
303
|
}
|
|
296
304
|
|
|
297
305
|
private attachListenersTopopover() {
|
|
298
|
-
|
|
306
|
+
// Capture so a click still counts as outside when a descendant
|
|
307
|
+
// calls stopPropagation (topic version pickers do, so the tree row
|
|
308
|
+
// does not navigate). Without this, opening a second picker leaves
|
|
309
|
+
// the first menu open.
|
|
310
|
+
document.addEventListener("click", this.interactOutsideListener, true);
|
|
299
311
|
document.addEventListener("focusout", this.interactOutsideListener);
|
|
300
312
|
if (this.openOnHover) {
|
|
301
313
|
document.addEventListener(
|
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
import type { InternalTreeNode, TreeNode } from "typings/custom";
|
|
2
|
+
import type { TopicVersionOption } from "dxUtils/topicVersion";
|
|
3
|
+
import {
|
|
4
|
+
applyVersionToHref,
|
|
5
|
+
normalizePath,
|
|
6
|
+
resolveSelectedVersion
|
|
7
|
+
} from "dxUtils/topicVersion";
|
|
8
|
+
|
|
9
|
+
type VersionedTreeNode = TreeNode & { versions?: TopicVersionOption[] };
|
|
10
|
+
type VersionedInternalTreeNode = InternalTreeNode & {
|
|
11
|
+
versions?: TopicVersionOption[];
|
|
12
|
+
};
|
|
13
|
+
|
|
2
14
|
type MapItem = {
|
|
3
|
-
node:
|
|
15
|
+
node: VersionedInternalTreeNode;
|
|
4
16
|
parent?: MapItem;
|
|
5
17
|
setExpanded?: Function;
|
|
6
18
|
};
|
|
@@ -21,7 +33,10 @@ export class TreeHandler {
|
|
|
21
33
|
}
|
|
22
34
|
|
|
23
35
|
getKeyByName(name: string): string | undefined {
|
|
24
|
-
|
|
36
|
+
if (!name) {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
return this._nameKeyMap[name] || this._nameKeyMap[normalizePath(name)];
|
|
25
40
|
}
|
|
26
41
|
|
|
27
42
|
initialize(treeRoot: TreeNode): InternalTreeNode {
|
|
@@ -48,12 +63,41 @@ export class TreeHandler {
|
|
|
48
63
|
}
|
|
49
64
|
|
|
50
65
|
private convert(
|
|
51
|
-
node:
|
|
66
|
+
node: VersionedTreeNode,
|
|
52
67
|
level: number = 0,
|
|
53
68
|
parent?: MapItem,
|
|
54
|
-
position?: number
|
|
55
|
-
|
|
56
|
-
|
|
69
|
+
position?: number,
|
|
70
|
+
ancestorVersion?: {
|
|
71
|
+
selected: TopicVersionOption;
|
|
72
|
+
versions: TopicVersionOption[];
|
|
73
|
+
}
|
|
74
|
+
): VersionedInternalTreeNode {
|
|
75
|
+
const ownSelected = node.versions?.length
|
|
76
|
+
? resolveSelectedVersion(node)
|
|
77
|
+
: undefined;
|
|
78
|
+
const versionContext =
|
|
79
|
+
ownSelected && node.versions
|
|
80
|
+
? { selected: ownSelected, versions: node.versions }
|
|
81
|
+
: ancestorVersion;
|
|
82
|
+
|
|
83
|
+
let link = node.link;
|
|
84
|
+
if (
|
|
85
|
+
versionContext &&
|
|
86
|
+
!node.versions?.length &&
|
|
87
|
+
link?.href &&
|
|
88
|
+
link.target !== "_blank"
|
|
89
|
+
) {
|
|
90
|
+
const rewritten = applyVersionToHref(
|
|
91
|
+
link.href,
|
|
92
|
+
versionContext.selected,
|
|
93
|
+
versionContext.versions
|
|
94
|
+
);
|
|
95
|
+
if (rewritten && rewritten !== link.href) {
|
|
96
|
+
link = { ...link, href: rewritten };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const convertedNode: VersionedInternalTreeNode = {
|
|
57
101
|
label: node.label,
|
|
58
102
|
name: node.name,
|
|
59
103
|
key: this.calculateKey(
|
|
@@ -63,24 +107,47 @@ export class TreeHandler {
|
|
|
63
107
|
level: level,
|
|
64
108
|
isExpanded: node.isExpanded || false,
|
|
65
109
|
isChildrenLoading: node.isChildrenLoading || false,
|
|
66
|
-
link
|
|
110
|
+
link,
|
|
67
111
|
method: node.method,
|
|
68
112
|
showForwardArrow: node.showForwardArrow,
|
|
69
|
-
|
|
113
|
+
versions: node.versions
|
|
70
114
|
};
|
|
71
115
|
|
|
72
116
|
const mapItem = { node: convertedNode, parent };
|
|
73
117
|
if (node.children && node.children.length > 0) {
|
|
74
118
|
convertedNode.children = node.children.map((child, index) =>
|
|
75
|
-
this.convert(child, level + 1, mapItem, index)
|
|
119
|
+
this.convert(child, level + 1, mapItem, index, versionContext)
|
|
76
120
|
);
|
|
77
121
|
}
|
|
78
122
|
|
|
79
123
|
this._nodeMap[convertedNode.key] = mapItem;
|
|
80
|
-
this.
|
|
124
|
+
this.indexName(convertedNode.name, convertedNode.key);
|
|
125
|
+
this.indexName(convertedNode.link?.href, convertedNode.key);
|
|
126
|
+
// Index this topic's own versioned URLs only. Parent-only switching
|
|
127
|
+
// URLs point at a child with content and must not steal that child's
|
|
128
|
+
// selection.
|
|
129
|
+
if (node.name && node.versions) {
|
|
130
|
+
for (const version of node.versions) {
|
|
131
|
+
this.indexName(
|
|
132
|
+
applyVersionToHref(node.name, version, node.versions),
|
|
133
|
+
convertedNode.key
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
81
137
|
return convertedNode;
|
|
82
138
|
}
|
|
83
139
|
|
|
140
|
+
private indexName(name: string | undefined, key: string): void {
|
|
141
|
+
if (!name) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
this._nameKeyMap[name] = key;
|
|
145
|
+
const normalized = normalizePath(name);
|
|
146
|
+
if (normalized && normalized !== name) {
|
|
147
|
+
this._nameKeyMap[normalized] = key;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
84
151
|
private calculateKey(parentKey: string, position?: number): string {
|
|
85
152
|
if (position === undefined) {
|
|
86
153
|
return parentKey;
|
|
@@ -4,6 +4,33 @@
|
|
|
4
4
|
display: block;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
+
/* Lift this row above later sibling pickers while its menu is open. */
|
|
8
|
+
:host(:focus-within) {
|
|
9
|
+
position: relative;
|
|
10
|
+
z-index: 2;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.tree-item-row {
|
|
14
|
+
display: flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
min-width: 0;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.tree-item-row dx-tree-tile {
|
|
20
|
+
flex: 1;
|
|
21
|
+
min-width: 0;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.tree-item-version-picker {
|
|
25
|
+
flex: 0 0 auto;
|
|
26
|
+
margin-right: var(--dx-g-spacing-lg);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.tree-item-row-selected {
|
|
30
|
+
background: var(--dx-g-cloud-blue-vibrant-95);
|
|
31
|
+
box-shadow: inset var(--dx-g-spacing-xs) 0 0 0 var(--dx-g-blue-vibrant-40);
|
|
32
|
+
}
|
|
33
|
+
|
|
7
34
|
button {
|
|
8
35
|
width: 100%;
|
|
9
36
|
text-align: left;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
2
|
+
<div class={rowClass}>
|
|
3
3
|
<dx-tree-tile
|
|
4
4
|
href={href}
|
|
5
5
|
is-root={isRoot}
|
|
@@ -7,12 +7,26 @@
|
|
|
7
7
|
is-expanded={isExpanded}
|
|
8
8
|
has-children={hasChildren}
|
|
9
9
|
is-selected={isSelected}
|
|
10
|
+
is-contained-selection={isContainedSelection}
|
|
10
11
|
oniconclick={onIconClick}
|
|
11
12
|
show-arrow={isParent}
|
|
12
13
|
target={target}
|
|
13
14
|
is-external-link={isExternalLink}
|
|
15
|
+
has-version-picker={showVersionPicker}
|
|
16
|
+
onclick={onLinkClick}
|
|
14
17
|
></dx-tree-tile>
|
|
15
|
-
|
|
18
|
+
<doc-version-picker
|
|
19
|
+
if:true={showVersionPicker}
|
|
20
|
+
class="tree-item-version-picker"
|
|
21
|
+
small="true"
|
|
22
|
+
versions={versionPickerOptions}
|
|
23
|
+
selected-version={selectedVersion}
|
|
24
|
+
latest-version={isLatestVersion}
|
|
25
|
+
onchange={onVersionChange}
|
|
26
|
+
onclick={onVersionPickerClick}
|
|
27
|
+
onmousedown={onVersionPickerClick}
|
|
28
|
+
></doc-version-picker>
|
|
29
|
+
</div>
|
|
16
30
|
<img
|
|
17
31
|
if:true={showChildrenLoading}
|
|
18
32
|
class="tree-children-loading"
|
|
@@ -2,9 +2,24 @@ import { LightningElement, api } from "lwc";
|
|
|
2
2
|
import { InternalTreeNode } from "typings/custom";
|
|
3
3
|
import { track } from "dxUtils/analytics";
|
|
4
4
|
import { isInViewport } from "dxUtils/browser";
|
|
5
|
+
import type { TopicVersionOption } from "dxUtils/topicVersion";
|
|
6
|
+
import {
|
|
7
|
+
firstContentNode,
|
|
8
|
+
getTopicVersionKey,
|
|
9
|
+
getVersionPickerOptions,
|
|
10
|
+
isParentOnlyTopic,
|
|
11
|
+
normalizePath,
|
|
12
|
+
persistTopicVersion,
|
|
13
|
+
resolveSelectedVersion,
|
|
14
|
+
shouldShowTopicVersionPicker
|
|
15
|
+
} from "dxUtils/topicVersion";
|
|
5
16
|
|
|
6
17
|
const DEFAULT_TARGET = "_self";
|
|
7
18
|
|
|
19
|
+
type VersionedInternalTreeNode = InternalTreeNode & {
|
|
20
|
+
versions?: TopicVersionOption[];
|
|
21
|
+
};
|
|
22
|
+
|
|
8
23
|
export default class TreeItem extends LightningElement {
|
|
9
24
|
@api selectedKey?: string;
|
|
10
25
|
@api isRoot: boolean = false;
|
|
@@ -20,7 +35,7 @@ export default class TreeItem extends LightningElement {
|
|
|
20
35
|
this.isChildrenLoading = (node && node.isChildrenLoading) || false;
|
|
21
36
|
}
|
|
22
37
|
|
|
23
|
-
private _treeNode!:
|
|
38
|
+
private _treeNode!: VersionedInternalTreeNode;
|
|
24
39
|
private isExpanded: boolean = false;
|
|
25
40
|
private isChildrenLoading: boolean = false;
|
|
26
41
|
private rootParentLabel: string = "";
|
|
@@ -30,9 +45,22 @@ export default class TreeItem extends LightningElement {
|
|
|
30
45
|
}
|
|
31
46
|
|
|
32
47
|
private get isSelected(): boolean {
|
|
48
|
+
if (isParentOnlyTopic(this._treeNode)) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
33
51
|
return this._treeNode.key === this.selectedKey && !this.isExternalLink;
|
|
34
52
|
}
|
|
35
53
|
|
|
54
|
+
private get rowClass(): string {
|
|
55
|
+
return this.isSelected && this.showVersionPicker
|
|
56
|
+
? "tree-item-row tree-item-row-selected"
|
|
57
|
+
: "tree-item-row";
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
private get isContainedSelection(): boolean {
|
|
61
|
+
return this.isSelected && this.showVersionPicker;
|
|
62
|
+
}
|
|
63
|
+
|
|
36
64
|
private get hasChildren(): boolean {
|
|
37
65
|
return !!(
|
|
38
66
|
this.treeNode &&
|
|
@@ -83,8 +111,44 @@ export default class TreeItem extends LightningElement {
|
|
|
83
111
|
return `${parentLabels.reverse().join(":")}:${this.treeNode.label}`;
|
|
84
112
|
}
|
|
85
113
|
|
|
114
|
+
private get versions(): TopicVersionOption[] | undefined {
|
|
115
|
+
return this._treeNode?.versions;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private get versionPickerOptions(): TopicVersionOption[] | undefined {
|
|
119
|
+
return getVersionPickerOptions(this._treeNode);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
private get showVersionPicker(): boolean {
|
|
123
|
+
return shouldShowTopicVersionPicker(
|
|
124
|
+
this.versions,
|
|
125
|
+
this._treeNode?.showForwardArrow
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private get selectedVersion(): TopicVersionOption | undefined {
|
|
130
|
+
return resolveSelectedVersion(this._treeNode);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
private get isLatestVersion(): boolean {
|
|
134
|
+
return (
|
|
135
|
+
!!this.selectedVersion &&
|
|
136
|
+
this.selectedVersion.id === this.versions?.[0]?.id
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
86
140
|
private get href(): string | undefined {
|
|
141
|
+
if (isParentOnlyTopic(this._treeNode)) {
|
|
142
|
+
const contentNode = firstContentNode(this._treeNode);
|
|
143
|
+
return (
|
|
144
|
+
contentNode?.link?.href ||
|
|
145
|
+
contentNode?.name ||
|
|
146
|
+
this.selectedVersion?.link?.href ||
|
|
147
|
+
""
|
|
148
|
+
);
|
|
149
|
+
}
|
|
87
150
|
return (
|
|
151
|
+
this.selectedVersion?.link?.href ||
|
|
88
152
|
(this._treeNode.link && this._treeNode.link.href) ||
|
|
89
153
|
this._treeNode.name ||
|
|
90
154
|
""
|
|
@@ -104,6 +168,23 @@ export default class TreeItem extends LightningElement {
|
|
|
104
168
|
setExpanded: this.setExpanded.bind(this)
|
|
105
169
|
});
|
|
106
170
|
}
|
|
171
|
+
|
|
172
|
+
// Remember this topic's resolved version (own URL, descendant URL, or
|
|
173
|
+
// session) so sibling pickers stay independent for the tab.
|
|
174
|
+
const selected = resolveSelectedVersion(this._treeNode);
|
|
175
|
+
const topicKey = getTopicVersionKey(this._treeNode);
|
|
176
|
+
if (this.versions?.length && selected && topicKey) {
|
|
177
|
+
persistTopicVersion(topicKey, selected.id);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private onVersionChange(event: CustomEvent): void {
|
|
182
|
+
event.stopPropagation();
|
|
183
|
+
persistTopicVersion(getTopicVersionKey(this._treeNode), event.detail);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private onVersionPickerClick(event: Event): void {
|
|
187
|
+
event.stopPropagation();
|
|
107
188
|
}
|
|
108
189
|
|
|
109
190
|
renderedCallback(): void {
|
|
@@ -134,8 +215,8 @@ export default class TreeItem extends LightningElement {
|
|
|
134
215
|
private preventDefaultLinkBehavior(event: Event) {
|
|
135
216
|
// prevent page refresh if href isn't present or link is already active
|
|
136
217
|
if (
|
|
137
|
-
!this.
|
|
138
|
-
this.
|
|
218
|
+
!this.href ||
|
|
219
|
+
normalizePath(this.href) === normalizePath(window.location.pathname)
|
|
139
220
|
) {
|
|
140
221
|
event.preventDefault();
|
|
141
222
|
}
|
|
@@ -167,8 +248,12 @@ export default class TreeItem extends LightningElement {
|
|
|
167
248
|
}
|
|
168
249
|
|
|
169
250
|
this.sendGtm(event);
|
|
251
|
+
const contentNode = isParentOnlyTopic(this._treeNode)
|
|
252
|
+
? firstContentNode(this._treeNode)
|
|
253
|
+
: undefined;
|
|
170
254
|
this.fireEvent("tileselected", {
|
|
171
|
-
name: this._treeNode.name,
|
|
255
|
+
name: contentNode?.name || this._treeNode.name,
|
|
256
|
+
...(contentNode?.key ? { key: contentNode.key } : {}),
|
|
172
257
|
isExternalLink: this.isExternalLink
|
|
173
258
|
});
|
|
174
259
|
}
|
|
@@ -186,8 +271,8 @@ export default class TreeItem extends LightningElement {
|
|
|
186
271
|
this.dispatchEvent(
|
|
187
272
|
new CustomEvent(type, {
|
|
188
273
|
detail: {
|
|
189
|
-
|
|
190
|
-
|
|
274
|
+
key: this._treeNode.key,
|
|
275
|
+
...detail
|
|
191
276
|
},
|
|
192
277
|
bubbles: true,
|
|
193
278
|
composed: true
|
|
@@ -28,10 +28,12 @@ export default class TreeTile extends LightningElement {
|
|
|
28
28
|
@api isExpanded = false;
|
|
29
29
|
@api hasChildren = false;
|
|
30
30
|
@api isSelected = false;
|
|
31
|
+
@api isContainedSelection = false;
|
|
31
32
|
@api href!: string;
|
|
32
33
|
@api showArrow = false;
|
|
33
34
|
@api target!: string;
|
|
34
35
|
@api isExternalLink = false;
|
|
36
|
+
@api hasVersionPicker = false;
|
|
35
37
|
|
|
36
38
|
get tileAriaLevel() {
|
|
37
39
|
return this.treeNode.level + 2;
|
|
@@ -101,7 +103,11 @@ export default class TreeTile extends LightningElement {
|
|
|
101
103
|
"tile-root": this.isRoot,
|
|
102
104
|
"tile-with-children": !this.isRoot && this.hasChildren,
|
|
103
105
|
"tile-root-with-child": this.isRoot && this.showArrow,
|
|
104
|
-
"sidebar-item-selected":
|
|
106
|
+
"sidebar-item-selected":
|
|
107
|
+
this.isSelected && !this.isContainedSelection,
|
|
108
|
+
"sidebar-item-selected-text":
|
|
109
|
+
this.isSelected && this.isContainedSelection,
|
|
110
|
+
"tile-with-version-picker": this.hasVersionPicker
|
|
105
111
|
});
|
|
106
112
|
}
|
|
107
113
|
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
IconSprite,
|
|
8
8
|
IconData,
|
|
9
9
|
IconSymbol,
|
|
10
|
+
StatusBadgeVariant,
|
|
10
11
|
TypeBadgeSize
|
|
11
12
|
} from "typings/custom";
|
|
12
13
|
import { colorToDxColors, buildStyleColorVariables } from "dxUtils/css";
|
|
@@ -20,9 +21,16 @@ import {
|
|
|
20
21
|
getContentTypeColorVariables
|
|
21
22
|
} from "dxUtils/contentTypes";
|
|
22
23
|
|
|
24
|
+
// Opt-in solid status variants (status-success/-warning/-error).
|
|
25
|
+
export const STATUS_BADGE_VARIANTS: StatusBadgeVariant[] = [
|
|
26
|
+
"status-success",
|
|
27
|
+
"status-warning",
|
|
28
|
+
"status-error"
|
|
29
|
+
];
|
|
30
|
+
|
|
23
31
|
export default class TypeBadge extends LightningElement {
|
|
24
32
|
@api size: TypeBadgeSize = "default";
|
|
25
|
-
@api variant: Brand | ContentType = "default";
|
|
33
|
+
@api variant: Brand | ContentType | StatusBadgeVariant = "default";
|
|
26
34
|
@api color?: Color;
|
|
27
35
|
@api dark?: false;
|
|
28
36
|
|
|
@@ -87,11 +95,24 @@ export default class TypeBadge extends LightningElement {
|
|
|
87
95
|
return isContentType(this.variant);
|
|
88
96
|
}
|
|
89
97
|
|
|
98
|
+
private get isStatus(): boolean {
|
|
99
|
+
return STATUS_BADGE_VARIANTS.includes(
|
|
100
|
+
this.variant as StatusBadgeVariant
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
90
104
|
private get className(): string {
|
|
91
|
-
return cx(
|
|
105
|
+
return cx(
|
|
106
|
+
"dx-badge",
|
|
107
|
+
`size-${this.size}`,
|
|
108
|
+
this.isStatus && this.variant
|
|
109
|
+
);
|
|
92
110
|
}
|
|
93
111
|
|
|
94
112
|
private get style(): string {
|
|
113
|
+
if (this.isStatus) {
|
|
114
|
+
return "";
|
|
115
|
+
}
|
|
95
116
|
if (this.dark) {
|
|
96
117
|
return buildStyleColorVariables({
|
|
97
118
|
background: "--dx-g-purple-vibrant-40",
|