@conduction/docusaurus-preset 3.9.0 → 3.10.0
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/components/Clients/Clients.jsx +2 -4
- package/src/components/HexRain/HexRain.jsx +11 -14
- package/src/components/PlatformDiagram/PlatformDiagram.jsx +9 -10
- package/src/components/PlatformOverview/PlatformOverview.jsx +3 -9
- package/src/theme/Footer/index.jsx +15 -17
- package/src/utils/lazyStylesheet.js +42 -0
package/package.json
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
import React from 'react';
|
|
23
|
-
import
|
|
23
|
+
import {useLazyStylesheet} from '../../utils/lazyStylesheet';
|
|
24
24
|
import SectionHead from '../primitives/SectionHead';
|
|
25
25
|
import {useLazyScript} from '../../utils/lazyScript';
|
|
26
26
|
import styles from './Clients.module.css';
|
|
@@ -121,6 +121,7 @@ function splitIntoRows(items, rowCount) {
|
|
|
121
121
|
function ClientsMarquee({head, clients, title, className}) {
|
|
122
122
|
useLazyScript(LOGO_MEMORY_BASE + '/clients-flow.js', 'clients-flow');
|
|
123
123
|
useLazyScript(LOGO_MEMORY_BASE + '/logo-memory.js', 'logo-memory');
|
|
124
|
+
useLazyStylesheet(LOGO_MEMORY_BASE + '/logo-memory.css', 'logo-memory');
|
|
124
125
|
React.useEffect(() => {
|
|
125
126
|
if (window.ConductionClientsFlow?.hydrate) window.ConductionClientsFlow.hydrate();
|
|
126
127
|
if (window.LogoMemory?.hydrate) window.LogoMemory.hydrate();
|
|
@@ -128,9 +129,6 @@ function ClientsMarquee({head, clients, title, className}) {
|
|
|
128
129
|
const clientsJson = React.useMemo(() => JSON.stringify(clients), [clients]);
|
|
129
130
|
return (
|
|
130
131
|
<>
|
|
131
|
-
<Head>
|
|
132
|
-
<link rel="stylesheet" href={LOGO_MEMORY_BASE + '/logo-memory.css'} />
|
|
133
|
-
</Head>
|
|
134
132
|
<section
|
|
135
133
|
className={[styles.section, className].filter(Boolean).join(' ')}
|
|
136
134
|
data-logo-memory
|
|
@@ -33,9 +33,9 @@
|
|
|
33
33
|
*/
|
|
34
34
|
|
|
35
35
|
import React, {useEffect, useRef} from 'react';
|
|
36
|
-
import Head from '@docusaurus/Head';
|
|
37
36
|
import useIsBrowser from '@docusaurus/useIsBrowser';
|
|
38
37
|
import {useLazyScript} from '../../utils/lazyScript';
|
|
38
|
+
import {useLazyStylesheet} from '../../utils/lazyStylesheet';
|
|
39
39
|
|
|
40
40
|
const ASSET_BASE = '/lib';
|
|
41
41
|
|
|
@@ -43,10 +43,12 @@ export default function HexRain({ariaLabel = 'Twelve apps mini-game, click each
|
|
|
43
43
|
const isBrowser = useIsBrowser();
|
|
44
44
|
const ref = useRef(null);
|
|
45
45
|
|
|
46
|
-
/* hex-rain.js
|
|
47
|
-
DOM mutations
|
|
48
|
-
utils/lazyScript.js
|
|
46
|
+
/* hex-rain.{js,css} are loaded post-hydration so neither the
|
|
47
|
+
runtime's DOM mutations trip React's hydration mismatch nor the
|
|
48
|
+
stylesheet blocks first paint. See utils/lazyScript.js and
|
|
49
|
+
utils/lazyStylesheet.js. */
|
|
49
50
|
useLazyScript(ASSET_BASE + '/hex-rain.js', 'hex-rain');
|
|
51
|
+
useLazyStylesheet(ASSET_BASE + '/hex-rain.css', 'hex-rain');
|
|
50
52
|
|
|
51
53
|
/* The runtime exposes window.HexRain.hydrate() once it has registered
|
|
52
54
|
itself. Poll one rAF tick per frame until it's there, then call it
|
|
@@ -67,15 +69,10 @@ export default function HexRain({ariaLabel = 'Twelve apps mini-game, click each
|
|
|
67
69
|
}, [isBrowser]);
|
|
68
70
|
|
|
69
71
|
return (
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
ref={ref}
|
|
76
|
-
className={['hex-rain', className].filter(Boolean).join(' ')}
|
|
77
|
-
aria-label={ariaLabel}
|
|
78
|
-
/>
|
|
79
|
-
</>
|
|
72
|
+
<div
|
|
73
|
+
ref={ref}
|
|
74
|
+
className={['hex-rain', className].filter(Boolean).join(' ')}
|
|
75
|
+
aria-label={ariaLabel}
|
|
76
|
+
/>
|
|
80
77
|
);
|
|
81
78
|
}
|
|
@@ -44,25 +44,24 @@
|
|
|
44
44
|
*/
|
|
45
45
|
|
|
46
46
|
import React from 'react';
|
|
47
|
-
import Head from '@docusaurus/Head';
|
|
48
47
|
import {useLazyScript} from '../../utils/lazyScript';
|
|
48
|
+
import {useLazyStylesheet} from '../../utils/lazyStylesheet';
|
|
49
49
|
|
|
50
50
|
const ASSET_BASE = '/lib';
|
|
51
51
|
|
|
52
52
|
export default function PlatformDiagram({workspace, lists = [], flows = []}) {
|
|
53
|
-
/* platform-diagram.js
|
|
54
|
-
a custom-element definition that upgrades any
|
|
55
|
-
element on the page; running it after React
|
|
56
|
-
custom-element constructor from mutating the
|
|
57
|
-
producing #418 / #423 warnings.
|
|
53
|
+
/* platform-diagram.{js,css} are loaded post-hydration. The runtime
|
|
54
|
+
registers a custom-element definition that upgrades any
|
|
55
|
+
<platform-diagram> element on the page; running it after React
|
|
56
|
+
hydration prevents the custom-element constructor from mutating the
|
|
57
|
+
DOM mid-hydration and producing #418 / #423 warnings. The matching
|
|
58
|
+
stylesheet is held off the render path so its 19 KB doesn't block
|
|
59
|
+
LCP on pages that render this component. */
|
|
58
60
|
useLazyScript(ASSET_BASE + '/platform-diagram.js', 'platform-diagram');
|
|
61
|
+
useLazyStylesheet(ASSET_BASE + '/platform-diagram.css', 'platform-diagram');
|
|
59
62
|
|
|
60
63
|
return (
|
|
61
64
|
<>
|
|
62
|
-
<Head>
|
|
63
|
-
<link rel="stylesheet" href={ASSET_BASE + '/platform-diagram.css'} />
|
|
64
|
-
</Head>
|
|
65
|
-
|
|
66
65
|
<platform-diagram>
|
|
67
66
|
{workspace && (
|
|
68
67
|
<pd-workspace
|
|
@@ -6,22 +6,16 @@
|
|
|
6
6
|
* "section-head" pattern (eyebrow + h2 + lede) above the diagram.
|
|
7
7
|
*
|
|
8
8
|
* The platform-diagram custom element is registered by
|
|
9
|
-
* /lib/platform-diagram.js
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* /lib/platform-diagram.js and styled by /lib/platform-diagram.css.
|
|
10
|
+
* Both are loaded post-hydration by the <PlatformDiagram /> component;
|
|
11
|
+
* sites no longer need to inject anything in <Head> manually.
|
|
12
12
|
*
|
|
13
13
|
* Mirrors the .platform section in preview/pages/landing.html.
|
|
14
14
|
*
|
|
15
15
|
* Usage in MDX:
|
|
16
16
|
*
|
|
17
|
-
* import Head from '@docusaurus/Head';
|
|
18
17
|
* import {PlatformOverview} from '@conduction/docusaurus-preset/components';
|
|
19
18
|
*
|
|
20
|
-
* <Head>
|
|
21
|
-
* <link rel="stylesheet" href="/lib/platform-diagram.css" />
|
|
22
|
-
* <script src="/lib/platform-diagram.js" defer />
|
|
23
|
-
* </Head>
|
|
24
|
-
*
|
|
25
19
|
* <PlatformOverview
|
|
26
20
|
* eyebrow="The platform"
|
|
27
21
|
* title={<>Five components.<br/>Twenty-four apps. One <span className="next-blue">Nextcloud</span> workspace.</>}
|
|
@@ -20,12 +20,12 @@
|
|
|
20
20
|
|
|
21
21
|
import React, {useEffect} from 'react';
|
|
22
22
|
import Link from '@docusaurus/Link';
|
|
23
|
-
import Head from '@docusaurus/Head';
|
|
24
23
|
import {useLocation} from '@docusaurus/router';
|
|
25
24
|
import {useThemeConfig} from '@docusaurus/theme-common';
|
|
26
25
|
import useIsBrowser from '@docusaurus/useIsBrowser';
|
|
27
26
|
import {brandFor} from '../brand.jsx';
|
|
28
27
|
import {useLazyScript} from '../../utils/lazyScript';
|
|
28
|
+
import {useLazyStylesheet} from '../../utils/lazyStylesheet';
|
|
29
29
|
import GameModal from '../../components/GameModal/GameModal';
|
|
30
30
|
|
|
31
31
|
function FooterLink({label, href, to}) {
|
|
@@ -95,20 +95,23 @@ export default function Footer() {
|
|
|
95
95
|
const wordmark = brand ? brand.wordmark : defaultWordmark;
|
|
96
96
|
const brandRow = !brand && Array.isArray(footerBrand?.brands) ? footerBrand.brands : null;
|
|
97
97
|
|
|
98
|
-
/* canal-footer.js
|
|
99
|
-
(filling .skyline, animating boats) don't trip React
|
|
100
|
-
mismatches
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
98
|
+
/* canal-footer.{js,css} are loaded post-hydration. The script's DOM
|
|
99
|
+
mutations (filling .skyline, animating boats) don't trip React
|
|
100
|
+
hydration mismatches, and the stylesheet doesn't block first paint.
|
|
101
|
+
See docs in utils/lazyScript.js and utils/lazyStylesheet.js. We
|
|
102
|
+
always load canal-footer.{js,css} even when minigames are off,
|
|
103
|
+
because the same script populates the static skyline and the same
|
|
104
|
+
stylesheet styles the canal frame. */
|
|
104
105
|
useLazyScript('/lib/canal-footer.js', 'canal-footer');
|
|
106
|
+
useLazyStylesheet('/lib/canal-footer.css', 'canal-footer');
|
|
105
107
|
|
|
106
|
-
/* kade-cyclist.js
|
|
107
|
-
canal script
|
|
108
|
-
opts out of minigames we feed
|
|
109
|
-
the load. The
|
|
110
|
-
|
|
108
|
+
/* kade-cyclist.{js,css} are the second hidden footer minigame. Unlike
|
|
109
|
+
the canal script they have no static side-effects, so when a product
|
|
110
|
+
page opts out of minigames we feed both hooks a falsy value to skip
|
|
111
|
+
the load. The hooks still run unconditionally — rules-of-hooks stays
|
|
112
|
+
compliant. */
|
|
111
113
|
useLazyScript(minigamesOn ? '/lib/kade-cyclist.js' : null, 'kade-cyclist');
|
|
114
|
+
useLazyStylesheet(minigamesOn ? '/lib/kade-cyclist.css' : null, 'kade-cyclist');
|
|
112
115
|
|
|
113
116
|
/* Re-hydrate the canal-footer + kade-cyclist runtimes on every mount,
|
|
114
117
|
including SPA route changes that re-render this Footer component.
|
|
@@ -143,11 +146,6 @@ export default function Footer() {
|
|
|
143
146
|
|
|
144
147
|
return (
|
|
145
148
|
<>
|
|
146
|
-
<Head>
|
|
147
|
-
<link rel="stylesheet" href="/lib/canal-footer.css" />
|
|
148
|
-
<link rel="stylesheet" href="/lib/kade-cyclist.css" />
|
|
149
|
-
</Head>
|
|
150
|
-
|
|
151
149
|
<footer className="canal-footer" aria-label="Site footer">
|
|
152
150
|
{/* Skyline placeholder — canal-footer.js fills it with cloned house templates */}
|
|
153
151
|
<div className="skyline" role="presentation" />
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useLazyStylesheet: load a runtime stylesheet after React hydration.
|
|
3
|
+
*
|
|
4
|
+
* Mirror of useLazyScript for CSS. The preset's heavier decorative
|
|
5
|
+
* stylesheets (canal-footer, kade-cyclist, hex-rain, logo-memory,
|
|
6
|
+
* platform-diagram) were injected via `<Head><link rel="stylesheet" />`,
|
|
7
|
+
* which Docusaurus SSGs into the rendered `<head>` and the browser
|
|
8
|
+
* treats as render-blocking. With five of these on a site that loads
|
|
9
|
+
* any landing page, LCP and TBT both regress past the "good" CWV
|
|
10
|
+
* threshold (LCP < 2.5s, INP < 200ms).
|
|
11
|
+
*
|
|
12
|
+
* Injecting via useEffect moves the load past hydration, so the
|
|
13
|
+
* stylesheet downloads in parallel with first paint instead of
|
|
14
|
+
* blocking it. Trade-off: a brief style-less flash before the CSS
|
|
15
|
+
* applies. Mitigated for above-fold callers by inlining the small
|
|
16
|
+
* structural rules into brand.css and only lazy-loading the
|
|
17
|
+
* decorative parts.
|
|
18
|
+
*
|
|
19
|
+
* The injected link has data-lazy-stylesheet="<key>" so SPA route
|
|
20
|
+
* changes don't double-inject, mirroring useLazyScript's idempotency.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import {useEffect} from 'react';
|
|
24
|
+
import useIsBrowser from '@docusaurus/useIsBrowser';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Pass a falsy `href` to skip the load entirely. The hook still runs
|
|
28
|
+
* unconditionally so call sites stay rules-of-hooks-compliant.
|
|
29
|
+
*/
|
|
30
|
+
export function useLazyStylesheet(href, key) {
|
|
31
|
+
const isBrowser = useIsBrowser();
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (!isBrowser) return;
|
|
34
|
+
if (!href) return;
|
|
35
|
+
if (document.querySelector(`link[data-lazy-stylesheet="${key}"]`)) return;
|
|
36
|
+
const link = document.createElement('link');
|
|
37
|
+
link.rel = 'stylesheet';
|
|
38
|
+
link.href = href;
|
|
39
|
+
link.dataset.lazyStylesheet = key;
|
|
40
|
+
document.head.appendChild(link);
|
|
41
|
+
}, [isBrowser, href, key]);
|
|
42
|
+
}
|