@salesforcedevs/dx-components 1.40.4 → 1.40.5-topic-alpha.2
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 +24 -16
- package/src/modules/dx/dropdown/dropdown.html +3 -1
- package/src/modules/dx/dropdown/dropdown.ts +19 -2
- package/src/modules/dx/dropdownOption/dropdownOption.css +34 -34
- package/src/modules/dx/dropdownOption/dropdownOption.html +4 -4
- package/src/modules/dx/dropdownOption/dropdownOption.ts +5 -4
- 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/commonSidebar/commonSidebar.css +8 -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.2",
|
|
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 {
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
@import "dxHelpers/reset";
|
|
2
2
|
|
|
3
|
+
/* Options run edge to edge; the menu adds space above the first and below
|
|
4
|
+
the last. */
|
|
5
|
+
dx-popover {
|
|
6
|
+
--dx-c-popover-padding: var(--dx-g-spacing-sm) 0;
|
|
7
|
+
}
|
|
8
|
+
|
|
3
9
|
.menu-nested:not(.menu-fit-content)::part(content) {
|
|
4
10
|
padding-top: var(--dx-g-spacing-sm);
|
|
5
11
|
width: 354px;
|
|
@@ -14,12 +20,22 @@
|
|
|
14
20
|
display: none;
|
|
15
21
|
}
|
|
16
22
|
|
|
23
|
+
/* fit-content and fit-end: the menu is as wide as its longest label. */
|
|
17
24
|
.menu-fit-content {
|
|
18
25
|
--dx-c-popover-width: max-content;
|
|
19
|
-
--dx-c-popover-padding: var(--dx-g-spacing-sm) 0;
|
|
20
26
|
}
|
|
21
27
|
|
|
22
|
-
|
|
28
|
+
/* fit-end also stops at --dx-c-dropdown-menu-max-width. Labels wrap only once
|
|
29
|
+
the menu reaches that width. */
|
|
30
|
+
.menu-fit-end::part(content) {
|
|
31
|
+
box-sizing: border-box;
|
|
32
|
+
max-width: var(
|
|
33
|
+
--dx-c-dropdown-menu-max-width,
|
|
34
|
+
calc(100vw - var(--dx-g-spacing-lg))
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.menu-fit-content.menu-nested .menu_list {
|
|
23
39
|
width: 100%;
|
|
24
40
|
align-items: flex-start;
|
|
25
41
|
gap: var(--dx-g-spacing-sm);
|
|
@@ -31,15 +47,6 @@
|
|
|
31
47
|
padding-top: var(--dx-g-spacing-sm);
|
|
32
48
|
}
|
|
33
49
|
|
|
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);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
50
|
@media screen and (max-width: 1000px) {
|
|
44
51
|
.menu-nested .menu_option:not(:first-child) {
|
|
45
52
|
border-top: var(--border);
|
|
@@ -91,12 +98,13 @@
|
|
|
91
98
|
|
|
92
99
|
.menu_heading {
|
|
93
100
|
display: block;
|
|
94
|
-
|
|
95
|
-
|
|
101
|
+
margin: 0;
|
|
102
|
+
padding: var(--dx-g-spacing-smd) var(--dx-g-spacing-lg);
|
|
103
|
+
color: var(--dx-g-gray-10);
|
|
104
|
+
font-family: var(--dx-g-font-sans);
|
|
96
105
|
font-size: var(--dx-g-text-sm);
|
|
97
106
|
font-weight: bold;
|
|
98
|
-
|
|
99
|
-
margin: var(--dx-g-spacing-sm);
|
|
107
|
+
line-height: var(--dx-g-spacing-mlg);
|
|
100
108
|
}
|
|
101
109
|
|
|
102
110
|
.callout_link {
|
|
@@ -105,7 +113,7 @@
|
|
|
105
113
|
display: block;
|
|
106
114
|
padding-top: var(--dx-g-spacing-xl);
|
|
107
115
|
margin-top: auto;
|
|
108
|
-
margin-left: var(--dx-g-spacing-
|
|
116
|
+
margin-left: var(--dx-g-spacing-lg);
|
|
109
117
|
}
|
|
110
118
|
|
|
111
119
|
.empty {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
open-on-hover={openOnHover}
|
|
10
10
|
open={open}
|
|
11
11
|
page-padding={pagePadding}
|
|
12
|
-
placement={
|
|
12
|
+
placement={effectivePlacement}
|
|
13
13
|
small={small}
|
|
14
14
|
width={effectiveWidth}
|
|
15
15
|
>
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
nav-item-label={navItemLabel}
|
|
36
36
|
variant={variant}
|
|
37
37
|
width-mode={widthMode}
|
|
38
|
+
show-icon={showOptionIcons}
|
|
38
39
|
></dx-dropdown-option>
|
|
39
40
|
<div
|
|
40
41
|
key={option.id}
|
|
@@ -55,6 +56,7 @@
|
|
|
55
56
|
option={suboption}
|
|
56
57
|
nav-item-label={navItemLabel}
|
|
57
58
|
width-mode={widthMode}
|
|
59
|
+
show-icon={showOptionIcons}
|
|
58
60
|
></dx-dropdown-option>
|
|
59
61
|
</template>
|
|
60
62
|
<dx-button
|
|
@@ -39,6 +39,7 @@ export default class Dropdown extends LightningElement {
|
|
|
39
39
|
@api navItemLabel: string | null = null;
|
|
40
40
|
@api variant: DropdownVariant = "base";
|
|
41
41
|
@api widthMode: DropdownWidthMode = "fixed";
|
|
42
|
+
@api showOptionIcons?: boolean = false; // right-aligned option icons (opt-in)
|
|
42
43
|
|
|
43
44
|
// props forwarded to dropdown option
|
|
44
45
|
@api analyticsEvent?: string;
|
|
@@ -82,20 +83,35 @@ export default class Dropdown extends LightningElement {
|
|
|
82
83
|
return this.areOptionsEmpty ? null : "menu";
|
|
83
84
|
}
|
|
84
85
|
|
|
86
|
+
// "fit-end" is fit-content, aligned to the trigger's end edge.
|
|
87
|
+
// "full" matches the trigger width. "fixed" and "fit-content" are unchanged.
|
|
85
88
|
private get isFitContent() {
|
|
86
|
-
return this.widthMode === "fit-content";
|
|
89
|
+
return this.widthMode === "fit-content" || this.widthMode === "fit-end";
|
|
87
90
|
}
|
|
88
91
|
|
|
92
|
+
private get effectivePlacement(): PopperPlacement | undefined {
|
|
93
|
+
return this.widthMode === "fit-end" ? "bottom-end" : this.placement;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// fit-content takes precedence; the misuse is surfaced in className() below.
|
|
89
97
|
private get effectiveWidth() {
|
|
90
98
|
return this.isFitContent ? null : this.width;
|
|
91
99
|
}
|
|
92
100
|
|
|
93
101
|
private get effectiveFullWidth() {
|
|
102
|
+
if (this.widthMode === "full") {
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
94
105
|
return this.isFitContent ? false : this.fullWidth;
|
|
95
106
|
}
|
|
96
107
|
|
|
97
108
|
private get className() {
|
|
98
109
|
const fitContent = this.isFitContent;
|
|
110
|
+
if (fitContent && (this.width || this.fullWidth)) {
|
|
111
|
+
console.error(
|
|
112
|
+
'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.'
|
|
113
|
+
);
|
|
114
|
+
}
|
|
99
115
|
return cx(
|
|
100
116
|
this.isNested && "menu-nested",
|
|
101
117
|
this.isNested &&
|
|
@@ -104,7 +120,8 @@ export default class Dropdown extends LightningElement {
|
|
|
104
120
|
"menu-nested-2-col",
|
|
105
121
|
this.offset && `menu-offset-${this.offset}`,
|
|
106
122
|
this.areOptionsEmpty && "menu-hidden",
|
|
107
|
-
fitContent && "menu-fit-content"
|
|
123
|
+
fitContent && "menu-fit-content",
|
|
124
|
+
this.widthMode === "fit-end" && "menu-fit-end"
|
|
108
125
|
);
|
|
109
126
|
}
|
|
110
127
|
|
|
@@ -25,8 +25,12 @@
|
|
|
25
25
|
display: flex;
|
|
26
26
|
font-family: var(--dx-g-font-sans);
|
|
27
27
|
width: 100%;
|
|
28
|
-
padding: var(
|
|
28
|
+
padding: var(
|
|
29
|
+
--dx-c-dropdown-option-padding,
|
|
30
|
+
var(--dx-g-spacing-sm) var(--dx-g-spacing-lg)
|
|
31
|
+
);
|
|
29
32
|
font-size: var(--dx-g-text-sm);
|
|
33
|
+
border-radius: var(--dx-c-dropdown-option-border-radius, 0);
|
|
30
34
|
transition: var(--dx-g-transition-hue-1x);
|
|
31
35
|
align-items: center;
|
|
32
36
|
outline: none !important;
|
|
@@ -56,6 +60,10 @@
|
|
|
56
60
|
display: flex;
|
|
57
61
|
flex-direction: column;
|
|
58
62
|
justify-content: center;
|
|
63
|
+
align-items: flex-start;
|
|
64
|
+
gap: var(--dx-g-spacing-sm);
|
|
65
|
+
flex: 1;
|
|
66
|
+
min-width: 0;
|
|
59
67
|
font-family: var(--dx-g-font-sans);
|
|
60
68
|
font-size: var(--dx-g-text-sm);
|
|
61
69
|
text-align: left;
|
|
@@ -64,14 +72,29 @@
|
|
|
64
72
|
.option-indented .option_details {
|
|
65
73
|
align-items: center;
|
|
66
74
|
flex-direction: row;
|
|
75
|
+
gap: 0;
|
|
67
76
|
}
|
|
68
77
|
|
|
69
78
|
.option_label {
|
|
70
|
-
color: var(--dx-c-dropdown-option-label-color, var(--dx-g-
|
|
71
|
-
|
|
79
|
+
color: var(--dx-c-dropdown-option-label-color, var(--dx-g-gray-10));
|
|
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
|
-
font-weight: var(
|
|
84
|
+
font-weight: var(
|
|
85
|
+
--dx-c-dropdown-option-font-weight,
|
|
86
|
+
var(--dx-g-font-normal)
|
|
87
|
+
);
|
|
74
88
|
font-size: var(--dx-c-dropdown-option-font-size, var(--dx-g-text-base));
|
|
89
|
+
line-height: var(--dx-g-spacing-lg);
|
|
90
|
+
|
|
91
|
+
/* Opt-in truncation: consumers set --dx-c-dropdown-option-white-space:
|
|
92
|
+
nowrap to truncate labels with an ellipsis instead of wrapping.
|
|
93
|
+
Defaults preserve today's wrapping behavior. */
|
|
94
|
+
white-space: var(--dx-c-dropdown-option-white-space, normal);
|
|
95
|
+
overflow: var(--dx-c-dropdown-option-overflow, visible);
|
|
96
|
+
overflow-wrap: var(--dx-c-dropdown-option-overflow-wrap, normal);
|
|
97
|
+
text-overflow: var(--dx-c-dropdown-option-text-overflow, clip);
|
|
75
98
|
}
|
|
76
99
|
|
|
77
100
|
.option-indented .option_label {
|
|
@@ -88,13 +111,17 @@
|
|
|
88
111
|
|
|
89
112
|
.option_description {
|
|
90
113
|
color: var(--dx-g-gray-30);
|
|
91
|
-
margin-top: var(--dx-g-spacing-xs);
|
|
92
114
|
line-height: 18px;
|
|
93
115
|
}
|
|
94
116
|
|
|
117
|
+
/* Only rendered when the dropdown sets show-option-icons. */
|
|
95
118
|
.option_icon {
|
|
96
|
-
|
|
119
|
+
--dx-c-icon-size: var(--dx-g-icon-size-md);
|
|
120
|
+
--dx-c-icon-color: var(--dx-g-gray-50);
|
|
121
|
+
|
|
122
|
+
order: 1;
|
|
97
123
|
flex-shrink: 0;
|
|
124
|
+
margin-left: var(--dx-g-spacing-2xl);
|
|
98
125
|
}
|
|
99
126
|
|
|
100
127
|
.option-indented {
|
|
@@ -102,46 +129,19 @@
|
|
|
102
129
|
padding-bottom: var(--dx-g-spacing-xs);
|
|
103
130
|
}
|
|
104
131
|
|
|
132
|
+
/* fit-content (toolbar): one line per label, truncated with an ellipsis. */
|
|
105
133
|
.option-fit-content {
|
|
106
134
|
min-width: 0;
|
|
107
|
-
padding: var(--dx-g-spacing-sm) var(--dx-g-spacing-lg);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
.option-fit-content .option_details {
|
|
111
|
-
align-items: flex-start;
|
|
112
|
-
gap: var(--dx-g-spacing-sm);
|
|
113
|
-
min-width: 0;
|
|
114
|
-
flex: 1;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
.option-fit-content .option_description {
|
|
118
|
-
margin-top: 0;
|
|
119
135
|
}
|
|
120
136
|
|
|
121
137
|
.option-fit-content .option_label {
|
|
122
138
|
display: block;
|
|
123
|
-
color: var(--dx-g-gray-10);
|
|
124
|
-
font-weight: var(--dx-g-font-normal);
|
|
125
|
-
line-height: var(--dx-g-spacing-lg);
|
|
126
139
|
white-space: nowrap;
|
|
127
140
|
overflow: hidden;
|
|
128
141
|
text-overflow: ellipsis;
|
|
129
142
|
max-width: calc(100vw - var(--dx-g-spacing-lg) * 4);
|
|
130
143
|
}
|
|
131
144
|
|
|
132
|
-
.option-fit-content.option-active .option_label {
|
|
133
|
-
color: var(--dx-g-blue-vibrant-50);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
.option-fit-content .option_icon {
|
|
137
|
-
--dx-c-icon-size: var(--dx-g-icon-size-md);
|
|
138
|
-
--dx-c-icon-color: var(--dx-g-gray-50);
|
|
139
|
-
|
|
140
|
-
order: 1;
|
|
141
|
-
margin-right: 0;
|
|
142
|
-
margin-left: var(--dx-g-spacing-2xl);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
145
|
.option-indented:not([data-index="0"]) {
|
|
146
146
|
--base-indentation: calc(var(--dx-g-spacing-md) + var(--shape-width));
|
|
147
147
|
--shape-width: 8px;
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
class="option_icon"
|
|
15
15
|
symbol={option.iconSymbol}
|
|
16
16
|
sprite={option.iconSprite}
|
|
17
|
-
if
|
|
18
|
-
size=
|
|
17
|
+
lwc:if={renderIcon}
|
|
18
|
+
size="override"
|
|
19
19
|
></dx-icon>
|
|
20
20
|
<div class="option_details">
|
|
21
21
|
<div if:true={renderIndentedShape} class="indented-shape"></div>
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
symbol={option.iconSymbol}
|
|
45
45
|
sprite={option.iconSprite}
|
|
46
46
|
color={option.iconColor}
|
|
47
|
-
if
|
|
48
|
-
size=
|
|
47
|
+
lwc:if={renderIcon}
|
|
48
|
+
size="override"
|
|
49
49
|
></dx-icon>
|
|
50
50
|
<div class="option_details">
|
|
51
51
|
<div if:true={renderIndentedShape} class="indented-shape"></div>
|
|
@@ -4,8 +4,7 @@ import {
|
|
|
4
4
|
OptionWithNested,
|
|
5
5
|
AnalyticsPayload,
|
|
6
6
|
DropdownVariant,
|
|
7
|
-
DropdownWidthMode
|
|
8
|
-
IconSize
|
|
7
|
+
DropdownWidthMode
|
|
9
8
|
} from "typings/custom";
|
|
10
9
|
import { track } from "dxUtils/analytics";
|
|
11
10
|
|
|
@@ -19,6 +18,7 @@ export default class DropdownOption extends LightningElement {
|
|
|
19
18
|
@api indexPosition: number = 0;
|
|
20
19
|
@api variant: DropdownVariant = "base";
|
|
21
20
|
@api widthMode: DropdownWidthMode = "fixed";
|
|
21
|
+
@api showIcon: boolean = false;
|
|
22
22
|
|
|
23
23
|
@api focus() {
|
|
24
24
|
const option = this.template.querySelector(".option");
|
|
@@ -41,8 +41,9 @@ export default class DropdownOption extends LightningElement {
|
|
|
41
41
|
return this.variant === "indented" && this.indexPosition >= 1;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
// Icons are opt-in (right-aligned); without show-icon there is no icon or spacing.
|
|
45
|
+
private get renderIcon() {
|
|
46
|
+
return this.showIcon && !!this.option.iconSymbol;
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
private onClick(e: PointerEvent) {
|
|
@@ -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"
|