@salesforcedevs/docs-components 1.34.3-fix-alpha → 1.34.3-fix-redoc-topic-v-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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforcedevs/docs-components",
3
- "version": "1.34.3-fix-alpha",
3
+ "version": "1.34.3-fix-redoc-topic-v-2",
4
4
  "description": "Docs Lightning web components for DSC",
5
5
  "license": "MIT",
6
6
  "main": "index.js",
@@ -25,5 +25,6 @@
25
25
  "@types/lodash.orderby": "4.6.9",
26
26
  "@types/lodash.uniqby": "4.7.9"
27
27
  },
28
- "gitHead": "4629fdd9ca18a13480044ad43515b91945d16aad"
28
+ "gitHead": "4629fdd9ca18a13480044ad43515b91945d16aad",
29
+ "stableVersion": "1.34.3"
29
30
  }
@@ -21,7 +21,6 @@ nav {
21
21
 
22
22
  dx-dropdown {
23
23
  --dx-c-dropdown-option-font-size: var(--dx-g-text-sm);
24
- --dx-c-dropdown-option-font-weight: var(--dx-g-font-bold);
25
24
  --dx-c-dropdown-option-label-color: var(
26
25
  --dx-c-breadcrumbs-breadcrumb-color
27
26
  );
@@ -127,26 +127,26 @@ export default class ContentActionToolbar extends LightningElement {
127
127
  {
128
128
  id: ACTION_COPY_MARKDOWN,
129
129
  label: COPY_MARKDOWN_LABEL,
130
- endIconSprite: "utility",
131
- endIconSymbol: "copy"
130
+ iconSprite: "utility",
131
+ iconSymbol: "copy"
132
132
  },
133
133
  {
134
134
  id: ACTION_VIEW_MARKDOWN,
135
135
  label: VIEW_MARKDOWN_LABEL,
136
- endIconSprite: "utility",
137
- endIconSymbol: "new_window"
136
+ iconSprite: "utility",
137
+ iconSymbol: "new_window"
138
138
  },
139
139
  {
140
140
  id: ACTION_COPY_MARKDOWN_URL,
141
141
  label: COPY_MARKDOWN_URL_LABEL,
142
- endIconSprite: "utility",
143
- endIconSymbol: "link"
142
+ iconSprite: "utility",
143
+ iconSymbol: "link"
144
144
  },
145
145
  ...AI_ASSISTANTS.map(({ action, label }) => ({
146
146
  id: action,
147
147
  label,
148
- endIconSprite: "utility",
149
- endIconSymbol: "new_window"
148
+ iconSprite: "utility",
149
+ iconSymbol: "new_window"
150
150
  }))
151
151
  ]
152
152
  });
@@ -159,14 +159,14 @@ export default class ContentActionToolbar extends LightningElement {
159
159
  {
160
160
  id: ACTION_VIEW_LLMS,
161
161
  label: VIEW_LLMS_LABEL,
162
- endIconSprite: "utility",
163
- endIconSymbol: "new_window"
162
+ iconSprite: "utility",
163
+ iconSymbol: "new_window"
164
164
  },
165
165
  {
166
166
  id: ACTION_COPY_LLMS_URL,
167
167
  label: COPY_LLMS_URL_LABEL,
168
- endIconSprite: "utility",
169
- endIconSymbol: "link"
168
+ iconSprite: "utility",
169
+ iconSymbol: "link"
170
170
  }
171
171
  ]
172
172
  });
@@ -8,7 +8,7 @@
8
8
  }
9
9
 
10
10
  dx-sidebar {
11
- --dx-c-sidebar-content-width: unset;
11
+ --dx-c-sidebar-width: unset;
12
12
 
13
13
  display: block;
14
14
  }
@@ -10,6 +10,15 @@ import { throttle } from "throttle-debounce";
10
10
  import { pollUntil } from "dxUtils/async";
11
11
  import { toJson } from "dxUtils/normalizers";
12
12
  import { oldVersionDocInfo } from "docUtils/utils";
13
+ import {
14
+ applyVersionToHref,
15
+ collectSubtreeCanonicalHrefs,
16
+ normalizePath,
17
+ getTopicVersionKey,
18
+ persistTopicVersion,
19
+ toCanonicalHref
20
+ } from "dxUtils/topicVersion";
21
+ import type { VersionedNode } from "dxUtils/topicVersion";
13
22
  import type { DocPhaseInfo, OptionWithLink } from "typings/custom";
14
23
 
15
24
  declare global {
@@ -47,6 +56,8 @@ type ReferenceVersion = {
47
56
  type ReferenceConfig = {
48
57
  refList: ReferenceItem[];
49
58
  versions?: ReferenceVersion[];
59
+ /** Sidebar topic name. Sidebar stores the selected version under this key. */
60
+ versionTopicKey?: string;
50
61
  };
51
62
 
52
63
  const SCROLL_THROTTLE_DELAY = 50;
@@ -129,6 +140,30 @@ export default class RedocReference extends LightningElement {
129
140
  */
130
141
  @api headerHref: string | null = null;
131
142
 
143
+ /**
144
+ * Versioned topic that owns this spec, including its children.
145
+ * Href matches this page, so an older version still has its version
146
+ * in the path.
147
+ */
148
+ @api
149
+ set parentTopicFamily(value: string | { topics?: VersionedNode[] } | null) {
150
+ try {
151
+ const parsed = toJson(value) as { topics?: VersionedNode[] } | null;
152
+ this._parentTopicFamilyNode = parsed?.topics?.[0] ?? null;
153
+ } catch (error) {
154
+ this._parentTopicFamilyNode = null;
155
+ console.error("Failed to parse parent topic family", error);
156
+ }
157
+ }
158
+
159
+ get parentTopicFamily(): { topics?: VersionedNode[] } | null {
160
+ return this._parentTopicFamilyNode
161
+ ? { topics: [this._parentTopicFamilyNode] }
162
+ : null;
163
+ }
164
+
165
+ private _parentTopicFamilyNode: VersionedNode | null = null;
166
+
132
167
  @api
133
168
  get contentType(): string {
134
169
  return this._contentType;
@@ -233,13 +268,64 @@ export default class RedocReference extends LightningElement {
233
268
  private onBackClick = (event: Event): void => {
234
269
  event.preventDefault();
235
270
 
236
- const target = this.getTranslatedBackTarget() ?? this.headerHref;
271
+ const target = this.getVersionedBackTarget() ?? this.headerHref;
237
272
 
238
273
  if (target) {
239
274
  window.location.assign(target);
240
275
  }
241
276
  };
242
277
 
278
+ /**
279
+ * When the back target is in this spec's topic, return it on the
280
+ * selected version. With no back target, do the same for the header
281
+ * link when that link is the versioned parent.
282
+ */
283
+ private getVersionedBackTarget(): string | null {
284
+ const stored = this.getTranslatedBackTarget();
285
+ const selectedVersion = this.selectedVersion;
286
+ const target = stored ?? this.headerHref;
287
+ if (!target || !selectedVersion) {
288
+ return stored;
289
+ }
290
+
291
+ let targetUrl: URL;
292
+ try {
293
+ targetUrl = new URL(target, window.location.origin);
294
+ } catch {
295
+ return target;
296
+ }
297
+
298
+ // Family hrefs match this page's version. Compare them without
299
+ // the version segment. Rewrite only the pathname so the target's
300
+ // query and hash survive.
301
+ const familyHrefs = this._parentTopicFamilyNode
302
+ ? collectSubtreeCanonicalHrefs(this._parentTopicFamilyNode).map(
303
+ (href) => toCanonicalHref(href, this.versions)
304
+ )
305
+ : [];
306
+
307
+ const canonicalTarget = toCanonicalHref(
308
+ targetUrl.pathname,
309
+ this.versions
310
+ );
311
+ const inFamily = familyHrefs.some(
312
+ (href) => normalizePath(href) === normalizePath(canonicalTarget)
313
+ );
314
+ if (!inFamily) {
315
+ return target;
316
+ }
317
+
318
+ const versioned = applyVersionToHref(
319
+ canonicalTarget,
320
+ selectedVersion,
321
+ this.versions
322
+ );
323
+ if (!versioned) {
324
+ return target;
325
+ }
326
+ return `${versioned}${targetUrl.search}${targetUrl.hash}`;
327
+ }
328
+
243
329
  private getTranslatedBackTarget(): string | null {
244
330
  const stored = this.getBackTargetFromSession();
245
331
  if (stored) {
@@ -362,6 +448,13 @@ export default class RedocReference extends LightningElement {
362
448
  // Track the back target, preserving it across locale switches
363
449
  this.trackBackTarget();
364
450
 
451
+ // Remember the selected version for the sidebar. Changing version
452
+ // reloads this page.
453
+ const topicKey = this.getParentTopicVersionKey();
454
+ if (topicKey && this.selectedVersion) {
455
+ persistTopicVersion(topicKey, this.selectedVersion.id);
456
+ }
457
+
365
458
  window.addEventListener("scroll", this.handleScrollAndResize);
366
459
  window.addEventListener("resize", this.handleScrollAndResize);
367
460
  }
@@ -670,6 +763,18 @@ export default class RedocReference extends LightningElement {
670
763
  return wrapper;
671
764
  }
672
765
 
766
+ /**
767
+ * Key the sidebar uses for this topic's selected version.
768
+ * Missing `versionTopicKey` returns null so nothing is written.
769
+ */
770
+ private getParentTopicVersionKey(): string | null {
771
+ const versionTopicKey = this._referenceConfig?.versionTopicKey;
772
+ if (!versionTopicKey) {
773
+ return null;
774
+ }
775
+ return getTopicVersionKey({ name: versionTopicKey }) || null;
776
+ }
777
+
673
778
  /** Stashes the current view (URL hash) before the version link navigates. */
674
779
  private onVersionChange = (): void => {
675
780
  sessionStorage.setItem(
@@ -1,12 +1,12 @@
1
1
  @import "dxHelpers/reset";
2
2
 
3
- /* The large picker fills its row (the sidebar sets the row padding). The small
4
- menu stops at --doc-version-picker-width, which the sidebar sets. */
3
+ /* NOTE: doc-version-picker-width width variable is used by both dx-button and dx-dropdown to maintain a consistent width. */
5
4
  :host {
6
- display: block;
7
-
8
- /* Menu labels wrap; break long unspaced labels instead of overflowing. */
9
- --dx-c-dropdown-option-overflow-wrap: anywhere;
5
+ --dx-c-dropdown-option-font-weight: normal;
6
+ --dx-c-dropdown-option-label-color: var(--dx-g-gray-10);
7
+ --dx-c-dropdown-option-padding: var(--dx-g-spacing-sm)
8
+ var(--dx-g-spacing-lg);
9
+ --dx-c-popover-padding: var(--dx-g-spacing-sm) 0;
10
10
  --popover-container-open-transform: translateY(4px);
11
11
  }
12
12
 
@@ -47,31 +47,16 @@
47
47
 
48
48
  .version-picker-button {
49
49
  display: flex;
50
- width: 100%;
50
+ width: var(--doc-version-picker-width, 296px);
51
51
 
52
52
  --dx-c-button-horizontal-spacing: var(--dx-g-spacing-sm);
53
- --dx-c-button-icon-color: var(--dx-g-gray-50);
54
-
55
- /* A real 1px border at rest. Hover and the open menu turn it dark blue and
56
- add a 1px inset shadow, so the edge looks 2px without resizing. */
57
- --dx-c-button-custom-color: var(--dx-g-gray-10);
58
- --dx-c-button-custom-color-hover: var(--dx-g-gray-10);
59
- --dx-c-button-custom-background: white;
60
- --dx-c-button-custom-background-hover: var(--dx-g-blue-vibrant-95);
61
- --dx-c-button-custom-border: var(--dx-g-gray-50);
62
- --dx-c-button-custom-border-hover: var(--dx-g-blue-vibrant-20);
63
- --dx-c-button-custom-border-shadow-hover: inset 0 0 0 1px
64
- var(--dx-g-blue-vibrant-20);
65
-
66
- /* Keyboard focus keeps the 2px edge inside the white band. */
67
- --dx-c-button-focus-shadow: inset 0 0 0 1px var(--dx-g-blue-vibrant-20),
68
- 0 0 0 2px white;
53
+ --dx-g-button-icon-color: var(--dx-g-gray-50);
69
54
  }
70
55
 
71
56
  .version-picker-button:hover,
72
57
  .version-picker-button:focus-within,
73
58
  .version-picker-button[aria-expanded="true"] {
74
- --dx-c-button-icon-color: var(--dx-g-blue-vibrant-20);
59
+ --dx-g-button-icon-color: var(--dx-g-blue-vibrant-20);
75
60
  }
76
61
 
77
62
  /**
@@ -83,6 +68,27 @@ dx-button::part(content) {
83
68
  overflow: hidden;
84
69
  }
85
70
 
71
+ /* The border is an inset box-shadow so thickening it on hover/focus doesn't
72
+ resize the small variant's fit-content box. */
73
+ .version-picker-button::part(container) {
74
+ background: white;
75
+ box-shadow: inset 0 0 0 1px var(--dx-g-gray-50);
76
+ color: var(--dx-g-gray-10);
77
+ }
78
+
79
+ .version-picker-button::part(container):hover {
80
+ background: var(--dx-g-blue-vibrant-95);
81
+ box-shadow: inset 0 0 0 2px var(--dx-g-blue-vibrant-20);
82
+ }
83
+
84
+ /* aria-expanded keeps the focus ring while the menu is open. */
85
+ .version-picker-button:focus-within::part(container),
86
+ .version-picker-button[aria-expanded="true"]::part(container) {
87
+ background: var(--dx-g-blue-vibrant-95);
88
+ box-shadow: inset 0 0 0 2px var(--dx-g-blue-vibrant-20), 0 0 0 2px white,
89
+ 0 0 0 4px var(--dx-g-blue-vibrant-60);
90
+ }
91
+
86
92
  .selected-version {
87
93
  display: flex;
88
94
  flex-direction: row;
@@ -106,11 +112,24 @@ dx-type-badge.not-latest-badge {
106
112
  * Small "dot" variant (opt-in via `small`). Additive
107
113
  * ------------------------------------------------------------------ */
108
114
 
109
- /* The small menu hugs its longest label but never grows wider than the sidebar
110
- content (--doc-version-picker-width, set by the sidebar). Labels wrap only at
111
- that width. The large menu always matches its trigger (width-mode="full"). */
115
+ /* Option padding is sm both axes: the small menu tracks the ~104px trigger, so
116
+ the default 24px horizontal would crowd the labels. */
112
117
  .version-picker-dropdown-small {
118
+ --dx-c-dropdown-option-font-size: var(--dx-g-text-xs);
119
+ --dx-c-dropdown-option-padding: var(--dx-g-spacing-sm)
120
+ var(--dx-g-spacing-sm);
121
+ --dx-c-dropdown-option-border-radius: 0;
122
+ --dx-c-popover-border: none;
123
+
124
+ /* Hug the labels (down to the shortest) but never wider than the ToC
125
+ content: 296px on desktop, and on the smallest breakpoint the sidebar
126
+ variable grows with the viewport up to 720px. Long labels wrap inside
127
+ that cap. */
113
128
  --dx-c-dropdown-menu-max-width: var(--doc-version-picker-width, 296px);
129
+ --dx-c-dropdown-fit-white-space: normal;
130
+ --dx-c-dropdown-fit-overflow: hidden;
131
+ --dx-c-dropdown-fit-text-overflow: clip;
132
+ --dx-c-dropdown-option-overflow-wrap: anywhere;
114
133
  }
115
134
 
116
135
  .version-picker-button-small {
@@ -135,8 +154,7 @@ dx-type-badge.not-latest-badge {
135
154
  }
136
155
 
137
156
  /* width:100% re-ties to the 104px-capped host (container is width:inherit,
138
- which copies width but not max-width). Border, fill, and states come from the
139
- dx-button hooks on .version-picker-button. */
157
+ which copies width but not max-width). Border/bg/states are shared above. */
140
158
  .version-picker-button-small::part(container) {
141
159
  width: 100%;
142
160
  height: var(--dx-g-spacing-lg);
@@ -168,7 +186,7 @@ dx-type-badge.not-latest-badge {
168
186
  .version-picker-readonly {
169
187
  box-sizing: border-box;
170
188
  display: inline-block;
171
- width: 100%;
189
+ width: var(--doc-version-picker-width, 296px);
172
190
  height: var(--dx-g-spacing-xl);
173
191
  margin: 0;
174
192
  padding: 0 var(--dx-g-spacing-sm);
@@ -21,7 +21,7 @@
21
21
  >
22
22
  <dx-button
23
23
  class={triggerClass}
24
- variant="custom"
24
+ variant="tertiary"
25
25
  size="small"
26
26
  font="sans"
27
27
  icon-symbol="chevrondown"