@docusaurus/theme-classic 0.0.0-4235 → 0.0.0-4242

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.
Files changed (47) hide show
  1. package/lib/index.js +4 -1
  2. package/lib/theme/DocCard/index.js +84 -0
  3. package/lib/theme/DocCard/styles.module.css +43 -0
  4. package/lib/theme/DocCardList/index.js +28 -0
  5. package/lib/theme/DocCategoryGeneratedIndexPage/index.js +57 -0
  6. package/lib/theme/DocCategoryGeneratedIndexPage/styles.module.css +18 -0
  7. package/lib/theme/DocItem/index.js +6 -7
  8. package/lib/theme/DocPage/index.js +16 -9
  9. package/lib/theme/DocPaginator/index.js +6 -7
  10. package/lib/theme/DocSidebar/index.js +10 -1
  11. package/lib/theme/DocSidebarItem/index.js +64 -30
  12. package/lib/theme/DocSidebarItem/styles.module.css +4 -0
  13. package/lib/theme/DocVersionBadge/index.js +34 -0
  14. package/lib/theme/DocVersionBanner/index.js +8 -8
  15. package/lib/theme-classic.d.ts +5 -4
  16. package/lib-next/index.js +5 -1
  17. package/lib-next/theme/DocCard/index.js +80 -0
  18. package/lib-next/theme/DocCard/styles.module.css +43 -0
  19. package/lib-next/theme/DocCardList/index.js +19 -0
  20. package/lib-next/theme/DocCategoryGeneratedIndexPage/index.js +49 -0
  21. package/lib-next/theme/DocCategoryGeneratedIndexPage/styles.module.css +18 -0
  22. package/lib-next/theme/DocItem/index.js +5 -12
  23. package/lib-next/theme/DocPage/index.js +31 -14
  24. package/lib-next/theme/DocPaginator/index.js +7 -11
  25. package/lib-next/theme/DocSidebar/index.js +10 -1
  26. package/lib-next/theme/DocSidebarItem/index.js +78 -37
  27. package/lib-next/theme/DocSidebarItem/styles.module.css +4 -0
  28. package/lib-next/theme/DocVersionBadge/index.js +27 -0
  29. package/lib-next/theme/DocVersionBanner/index.js +12 -5
  30. package/lib-next/theme-classic.d.ts +5 -4
  31. package/package.json +16 -16
  32. package/src/index.ts +9 -4
  33. package/src/theme/DocCard/index.tsx +100 -0
  34. package/src/theme/DocCard/styles.module.css +43 -0
  35. package/src/theme/DocCardList/index.tsx +27 -0
  36. package/src/theme/DocCategoryGeneratedIndexPage/index.tsx +53 -0
  37. package/src/theme/DocCategoryGeneratedIndexPage/styles.module.css +18 -0
  38. package/src/theme/DocItem/index.tsx +5 -12
  39. package/src/theme/DocPage/index.tsx +28 -12
  40. package/src/theme/DocPaginator/index.tsx +9 -13
  41. package/src/theme/DocSidebar/index.tsx +9 -1
  42. package/src/theme/DocSidebarItem/index.tsx +77 -38
  43. package/src/theme/DocSidebarItem/styles.module.css +4 -0
  44. package/src/theme/DocVersionBadge/index.tsx +30 -0
  45. package/src/theme/DocVersionBanner/index.tsx +23 -7
  46. package/src/theme-classic.d.ts +5 -4
  47. package/src/translations.ts +2 -0
@@ -5,17 +5,19 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import React, {useEffect, memo} from 'react';
8
+ import React, {useEffect, memo, useMemo} from 'react';
9
9
  import clsx from 'clsx';
10
10
  import {
11
- isSamePath,
11
+ isActiveSidebarItem,
12
12
  usePrevious,
13
13
  Collapsible,
14
14
  useCollapsible,
15
+ findFirstCategoryLink,
15
16
  ThemeClassNames,
16
17
  } from '@docusaurus/theme-common';
17
18
  import Link from '@docusaurus/Link';
18
19
  import isInternalUrl from '@docusaurus/isInternalUrl';
20
+ import {translate} from '@docusaurus/Translate';
19
21
  import IconExternalLink from '@theme/IconExternalLink';
20
22
 
21
23
  import type {Props, DocSidebarItemsProps} from '@theme/DocSidebarItem';
@@ -25,21 +27,7 @@ import type {
25
27
  } from '@docusaurus/plugin-content-docs';
26
28
 
27
29
  import styles from './styles.module.css';
28
-
29
- const isActiveSidebarItem = (
30
- item: Props['item'],
31
- activePath: string,
32
- ): boolean => {
33
- if (item.type === 'link') {
34
- return isSamePath(item.href, activePath);
35
- }
36
- if (item.type === 'category') {
37
- return item.items.some((subItem) =>
38
- isActiveSidebarItem(subItem, activePath),
39
- );
40
- }
41
- return false;
42
- };
30
+ import useIsBrowser from '@docusaurus/useIsBrowser';
43
31
 
44
32
  // Optimize sidebar at each "level"
45
33
  // TODO this item should probably not receive the "activePath" props
@@ -93,6 +81,28 @@ function useAutoExpandActiveCategory({
93
81
  }, [isActive, wasActive, collapsed, setCollapsed]);
94
82
  }
95
83
 
84
+ // When a collapsible category has no link, we still link it to its first child during SSR as a temporary fallback
85
+ // This allows to be able to navigate inside the category even when JS fails to load, is delayed or simply disabled
86
+ // React hydration becomes an optional progressive enhancement
87
+ // see https://github.com/facebookincubator/infima/issues/36#issuecomment-772543188
88
+ // see https://github.com/facebook/docusaurus/issues/3030
89
+ function useCategoryHrefWithSSRFallback(
90
+ item: PropSidebarItemCategory,
91
+ ): string | undefined {
92
+ const isBrowser = useIsBrowser();
93
+ return useMemo(() => {
94
+ if (item.href) {
95
+ return item.href;
96
+ }
97
+ // In these cases, it's not necessary to render a fallback
98
+ // We skip the "findFirstCategoryLink" computation
99
+ if (isBrowser || !item.collapsible) {
100
+ return undefined;
101
+ }
102
+ return findFirstCategoryLink(item);
103
+ }, [item, isBrowser]);
104
+ }
105
+
96
106
  function DocSidebarItemCategory({
97
107
  item,
98
108
  onItemClick,
@@ -100,7 +110,8 @@ function DocSidebarItemCategory({
100
110
  level,
101
111
  ...props
102
112
  }: Props & {item: PropSidebarItemCategory}) {
103
- const {items, label, collapsible, className} = item;
113
+ const {items, label, collapsible, className, href} = item;
114
+ const hrefWithSSRFallback = useCategoryHrefWithSSRFallback(item);
104
115
 
105
116
  const isActive = isActiveSidebarItem(item, activePath);
106
117
 
@@ -128,25 +139,53 @@ function DocSidebarItemCategory({
128
139
  },
129
140
  className,
130
141
  )}>
131
- {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
132
- <a
133
- className={clsx('menu__link', {
134
- 'menu__link--sublist': collapsible,
135
- 'menu__link--active': collapsible && isActive,
136
- [styles.menuLinkText]: !collapsible,
137
- })}
138
- onClick={
139
- collapsible
140
- ? (e) => {
141
- e.preventDefault();
142
- toggleCollapsed();
143
- }
144
- : undefined
145
- }
146
- href={collapsible ? '#' : undefined}
147
- {...props}>
148
- {label}
149
- </a>
142
+ <div className="menu__list-item-collapsible">
143
+ <Link
144
+ className={clsx('menu__link', {
145
+ 'menu__link--sublist': collapsible && !href,
146
+ 'menu__link--active': isActive,
147
+ [styles.menuLinkText]: !collapsible,
148
+ [styles.hasHref]: !!hrefWithSSRFallback,
149
+ })}
150
+ onClick={
151
+ collapsible
152
+ ? (e) => {
153
+ onItemClick?.(item);
154
+ if (href) {
155
+ setCollapsed(false);
156
+ } else {
157
+ e.preventDefault();
158
+ toggleCollapsed();
159
+ }
160
+ }
161
+ : () => {
162
+ onItemClick?.(item);
163
+ }
164
+ }
165
+ href={collapsible ? hrefWithSSRFallback ?? '#' : hrefWithSSRFallback}
166
+ {...props}>
167
+ {label}
168
+ </Link>
169
+ {href && collapsible && (
170
+ <button
171
+ aria-label={translate(
172
+ {
173
+ id: 'theme.DocSidebarItem.toggleCollapsedCategoryAriaLabel',
174
+ message: "Toggle the collapsible sidebar category '{label}'",
175
+ description:
176
+ 'The ARIA label to toggle the collapsible sidebar category',
177
+ },
178
+ {label},
179
+ )}
180
+ type="button"
181
+ className="clean-btn menu__caret"
182
+ onClick={(e) => {
183
+ e.preventDefault();
184
+ toggleCollapsed();
185
+ }}
186
+ />
187
+ )}
188
+ </div>
150
189
 
151
190
  <Collapsible lazy as="ul" className="menu__list" collapsed={collapsed}>
152
191
  <DocSidebarItems
@@ -186,7 +225,7 @@ function DocSidebarItemLink({
186
225
  aria-current={isActive ? 'page' : undefined}
187
226
  to={href}
188
227
  {...(isInternalUrl(href) && {
189
- onClick: onItemClick,
228
+ onClick: onItemClick ? () => onItemClick(item) : undefined,
190
229
  })}
191
230
  {...props}>
192
231
  {isInternalUrl(href) ? (
@@ -12,4 +12,8 @@
12
12
  .menuLinkText:hover {
13
13
  background: none;
14
14
  }
15
+
16
+ .menuLinkText.hasHref {
17
+ cursor: pointer;
18
+ }
15
19
  }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ import React from 'react';
9
+ import {ThemeClassNames, useDocsVersion} from '@docusaurus/theme-common';
10
+ import clsx from 'clsx';
11
+ import type {Props} from '@theme/DocVersionBadge';
12
+
13
+ export default function DocVersionBadge({
14
+ className,
15
+ }: Props): JSX.Element | null {
16
+ const versionMetadata = useDocsVersion();
17
+ if (versionMetadata.badge) {
18
+ return (
19
+ <span
20
+ className={clsx(
21
+ className,
22
+ ThemeClassNames.docs.docVersionBadge,
23
+ 'badge badge--secondary',
24
+ )}>
25
+ Version: {versionMetadata.label}
26
+ </span>
27
+ );
28
+ }
29
+ return null;
30
+ }
@@ -17,15 +17,19 @@ import {
17
17
  import {
18
18
  ThemeClassNames,
19
19
  useDocsPreferredVersion,
20
+ useDocsVersion,
20
21
  } from '@docusaurus/theme-common';
21
22
 
22
23
  import type {Props} from '@theme/DocVersionBanner';
23
24
  import clsx from 'clsx';
24
- import type {VersionBanner} from '@docusaurus/plugin-content-docs';
25
+ import type {
26
+ VersionBanner,
27
+ PropVersionMetadata,
28
+ } from '@docusaurus/plugin-content-docs';
25
29
 
26
30
  type BannerLabelComponentProps = {
27
31
  siteTitle: string;
28
- versionMetadata: Props['versionMetadata'];
32
+ versionMetadata: PropVersionMetadata;
29
33
  };
30
34
 
31
35
  function UnreleasedVersionLabel({
@@ -114,7 +118,12 @@ function LatestVersionSuggestionLabel({
114
118
  );
115
119
  }
116
120
 
117
- function DocVersionBannerEnabled({versionMetadata}: Props): JSX.Element {
121
+ function DocVersionBannerEnabled({
122
+ className,
123
+ versionMetadata,
124
+ }: Props & {
125
+ versionMetadata: PropVersionMetadata;
126
+ }): JSX.Element {
118
127
  const {
119
128
  siteConfig: {title: siteTitle},
120
129
  } = useDocusaurusContext();
@@ -136,6 +145,7 @@ function DocVersionBannerEnabled({versionMetadata}: Props): JSX.Element {
136
145
  return (
137
146
  <div
138
147
  className={clsx(
148
+ className,
139
149
  ThemeClassNames.docs.docVersionBanner,
140
150
  'alert alert--warning margin-bottom--md',
141
151
  )}
@@ -154,11 +164,17 @@ function DocVersionBannerEnabled({versionMetadata}: Props): JSX.Element {
154
164
  );
155
165
  }
156
166
 
157
- function DocVersionBanner({versionMetadata}: Props): JSX.Element | null {
167
+ export default function DocVersionBanner({
168
+ className,
169
+ }: Props): JSX.Element | null {
170
+ const versionMetadata = useDocsVersion();
158
171
  if (versionMetadata.banner) {
159
- return <DocVersionBannerEnabled versionMetadata={versionMetadata} />;
172
+ return (
173
+ <DocVersionBannerEnabled
174
+ className={className}
175
+ versionMetadata={versionMetadata}
176
+ />
177
+ );
160
178
  }
161
179
  return null;
162
180
  }
163
-
164
- export default DocVersionBanner;
@@ -107,11 +107,12 @@ declare module '@theme/CodeBlock' {
107
107
  }
108
108
 
109
109
  declare module '@theme/DocPaginator' {
110
+ import type {PropNavigation} from '@docusaurus/plugin-content-docs';
111
+
110
112
  type PageInfo = {readonly permalink: string; readonly title: string};
111
113
 
112
- export interface Props {
113
- readonly metadata: {readonly previous?: PageInfo; readonly next?: PageInfo};
114
- }
114
+ // May be simpler to provide a {navigation: PropNavigation} prop?
115
+ export interface Props extends PropNavigation {}
115
116
 
116
117
  const DocPaginator: (props: Props) => JSX.Element;
117
118
  export default DocPaginator;
@@ -138,7 +139,7 @@ declare module '@theme/DocSidebarItem' {
138
139
 
139
140
  type DocSidebarPropsBase = {
140
141
  readonly activePath: string;
141
- readonly onItemClick?: () => void;
142
+ readonly onItemClick?: (item: PropSidebarItem) => void;
142
143
  readonly level: number;
143
144
  readonly tabIndex?: number;
144
145
  };
@@ -151,6 +151,8 @@ export function translateThemeConfig({
151
151
  themeConfig,
152
152
  translationFiles,
153
153
  }: {
154
+ // Why partial? To make TS correctly figure out the contravariance in parameter.
155
+ // In practice it's always normalized
154
156
  themeConfig: ThemeConfig;
155
157
  translationFiles: TranslationFile[];
156
158
  }): ThemeConfig {