@salesforcedevs/dx-components 1.40.0-integration-alpha2 → 1.40.0-topic-alpha
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/dx/dropdown/dropdown.css +17 -5
- package/src/modules/dx/dropdown/dropdown.html +1 -1
- package/src/modules/dx/dropdown/dropdown.ts +10 -1
- package/src/modules/dx/dropdownOption/dropdownOption.css +1 -0
- package/src/modules/dx/popover/popover.ts +20 -4
- package/src/modules/dxUtils/topicVersion/topicVersion.ts +73 -16
package/package.json
CHANGED
|
@@ -14,18 +14,30 @@
|
|
|
14
14
|
display: none;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
/* Opt-in fit-content menu:
|
|
18
|
-
|
|
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. */
|
|
19
20
|
.menu-fit-content::part(content) {
|
|
21
|
+
box-sizing: border-box;
|
|
20
22
|
width: max-content;
|
|
23
|
+
max-width: var(
|
|
24
|
+
--dx-c-dropdown-menu-max-width,
|
|
25
|
+
calc(100vw - var(--dx-g-spacing-lg))
|
|
26
|
+
);
|
|
21
27
|
}
|
|
22
28
|
|
|
23
29
|
.menu-fit-content {
|
|
24
30
|
--dx-c-dropdown-option-min-width: 0;
|
|
25
31
|
--dx-c-dropdown-option-label-display: block;
|
|
26
|
-
--dx-c-dropdown-option-white-space:
|
|
27
|
-
|
|
28
|
-
|
|
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
|
+
);
|
|
29
41
|
}
|
|
30
42
|
|
|
31
43
|
@media screen and (max-width: 1000px) {
|
|
@@ -82,8 +82,14 @@ 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";
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private get effectivePlacement(): PopperPlacement | undefined {
|
|
92
|
+
return this.widthMode === "fit-end" ? "bottom-end" : this.placement;
|
|
87
93
|
}
|
|
88
94
|
|
|
89
95
|
// fit-content takes precedence; the misuse is surfaced in className() below.
|
|
@@ -92,6 +98,9 @@ export default class Dropdown extends LightningElement {
|
|
|
92
98
|
}
|
|
93
99
|
|
|
94
100
|
private get effectiveFullWidth() {
|
|
101
|
+
if (this.widthMode === "full") {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
95
104
|
return this.isFitContent ? false : this.fullWidth;
|
|
96
105
|
}
|
|
97
106
|
|
|
@@ -87,6 +87,7 @@
|
|
|
87
87
|
Defaults preserve today's wrapping behavior. */
|
|
88
88
|
white-space: var(--dx-c-dropdown-option-white-space, normal);
|
|
89
89
|
overflow: var(--dx-c-dropdown-option-overflow, visible);
|
|
90
|
+
overflow-wrap: var(--dx-c-dropdown-option-overflow-wrap, normal);
|
|
90
91
|
text-overflow: var(--dx-c-dropdown-option-text-overflow, clip);
|
|
91
92
|
}
|
|
92
93
|
|
|
@@ -80,7 +80,11 @@ export default class Popover extends LightningElement {
|
|
|
80
80
|
this.control.setAttribute("aria-expanded", "true");
|
|
81
81
|
|
|
82
82
|
if (this.popover) {
|
|
83
|
-
this.autoUpdateCleanup = autoUpdate(
|
|
83
|
+
this.autoUpdateCleanup = autoUpdate(
|
|
84
|
+
this.control,
|
|
85
|
+
this.popover,
|
|
86
|
+
this.setPosition
|
|
87
|
+
);
|
|
84
88
|
}
|
|
85
89
|
|
|
86
90
|
this.dispatchEvent(new CustomEvent("open"));
|
|
@@ -102,7 +106,11 @@ export default class Popover extends LightningElement {
|
|
|
102
106
|
if (this.control) {
|
|
103
107
|
this.control.setAttribute("aria-expanded", "false");
|
|
104
108
|
}
|
|
105
|
-
document.removeEventListener(
|
|
109
|
+
document.removeEventListener(
|
|
110
|
+
"click",
|
|
111
|
+
this.interactOutsideListener,
|
|
112
|
+
true
|
|
113
|
+
);
|
|
106
114
|
document.removeEventListener("focusout", this.interactOutsideListener);
|
|
107
115
|
if (this.openOnHover) {
|
|
108
116
|
document.removeEventListener(
|
|
@@ -128,7 +136,11 @@ export default class Popover extends LightningElement {
|
|
|
128
136
|
// LIFECYCLE METHODS
|
|
129
137
|
|
|
130
138
|
disconnectedCallback() {
|
|
131
|
-
document.removeEventListener(
|
|
139
|
+
document.removeEventListener(
|
|
140
|
+
"click",
|
|
141
|
+
this.interactOutsideListener,
|
|
142
|
+
true
|
|
143
|
+
);
|
|
132
144
|
document.removeEventListener("mousemove", this.interactOutsideListener);
|
|
133
145
|
document.removeEventListener("focusout", this.interactOutsideListener);
|
|
134
146
|
this.removeControlListeners();
|
|
@@ -291,7 +303,11 @@ export default class Popover extends LightningElement {
|
|
|
291
303
|
}
|
|
292
304
|
|
|
293
305
|
private attachListenersTopopover() {
|
|
294
|
-
|
|
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);
|
|
295
311
|
document.addEventListener("focusout", this.interactOutsideListener);
|
|
296
312
|
if (this.openOnHover) {
|
|
297
313
|
document.addEventListener(
|
|
@@ -378,31 +378,88 @@ export function getVersionPickerOptions(
|
|
|
378
378
|
}));
|
|
379
379
|
}
|
|
380
380
|
|
|
381
|
-
|
|
381
|
+
/**
|
|
382
|
+
* Version whose page (or a descendant of it) is the current URL.
|
|
383
|
+
* Ignores the session-stored picker selection, which can remember an older
|
|
384
|
+
* version while the reader is still on the latest page.
|
|
385
|
+
*/
|
|
386
|
+
export function versionForCurrentPage(
|
|
382
387
|
node: VersionedNode | undefined
|
|
383
388
|
): TopicVersionOption | undefined {
|
|
384
389
|
const versions = node?.versions;
|
|
385
|
-
if (!node || !versions?.length) {
|
|
390
|
+
if (!node || !versions?.length || !isBrowser()) {
|
|
386
391
|
return undefined;
|
|
387
392
|
}
|
|
388
393
|
|
|
389
|
-
const
|
|
390
|
-
|
|
394
|
+
const hrefs = collectSubtreeCanonicalHrefs(node);
|
|
395
|
+
const matches = (version: TopicVersionOption) =>
|
|
396
|
+
hrefMatchesCurrentPage(version.link?.href) ||
|
|
397
|
+
hrefs.some((href) => hrefMatchesVersion(href, version, versions));
|
|
398
|
+
|
|
399
|
+
// Older versions first so a rewritten child URL is not mistaken for latest.
|
|
400
|
+
const older = versions.find(
|
|
401
|
+
(version) => version.id !== versions[0].id && matches(version)
|
|
391
402
|
);
|
|
392
|
-
if (
|
|
393
|
-
return
|
|
403
|
+
if (older) {
|
|
404
|
+
return older;
|
|
394
405
|
}
|
|
395
406
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
407
|
+
return matches(versions[0]) ? versions[0] : undefined;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Deepest versioned topic that contains the current page, with the version
|
|
412
|
+
* the URL selects. Nested versioned topics own their pages.
|
|
413
|
+
*/
|
|
414
|
+
export function findTopicVersionForCurrentPage(
|
|
415
|
+
nodes: VersionedNode[] | undefined | null
|
|
416
|
+
): { node: VersionedNode; version: TopicVersionOption } | undefined {
|
|
417
|
+
let match: { node: VersionedNode; version: TopicVersionOption } | undefined;
|
|
418
|
+
const walk = (list?: VersionedNode[] | null) => {
|
|
419
|
+
for (const node of list || []) {
|
|
420
|
+
const version = versionForCurrentPage(node);
|
|
421
|
+
if (version) {
|
|
422
|
+
match = { node, version };
|
|
423
|
+
}
|
|
424
|
+
walk(node.children);
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
walk(nodes);
|
|
428
|
+
return match;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Current page rewritten onto the latest topic version. Falls back to the
|
|
433
|
+
* latest switching URL when the path delta cannot be applied.
|
|
434
|
+
*/
|
|
435
|
+
export function latestHrefForCurrentPage(
|
|
436
|
+
versions: TopicVersionOption[] | undefined
|
|
437
|
+
): string | undefined {
|
|
438
|
+
const latest = versions?.[0];
|
|
439
|
+
if (!latest) {
|
|
440
|
+
return undefined;
|
|
441
|
+
}
|
|
442
|
+
if (!isBrowser()) {
|
|
443
|
+
return latest.link?.href;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const canonical = toCanonicalHref(window.location.pathname, versions);
|
|
447
|
+
return applyVersionToHref(canonical, latest, versions) || latest.link?.href;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
export function resolveSelectedVersion(
|
|
451
|
+
node: VersionedNode | undefined
|
|
452
|
+
): TopicVersionOption | undefined {
|
|
453
|
+
const versions = node?.versions;
|
|
454
|
+
if (!node || !versions?.length) {
|
|
455
|
+
return undefined;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// The open page wins, including a canonical child opened from "View Latest".
|
|
459
|
+
// Session is only for a picker whose topic is not the current page.
|
|
460
|
+
const fromUrl = versionForCurrentPage(node);
|
|
461
|
+
if (fromUrl) {
|
|
462
|
+
return fromUrl;
|
|
406
463
|
}
|
|
407
464
|
|
|
408
465
|
const storedId = readTopicVersionSelections()[getTopicVersionKey(node)];
|