@mui/internal-docs-infra 0.11.1-canary.9 → 0.11.1
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/ChunkProvider/ChunkContext.d.mts +10 -0
- package/ChunkProvider/ChunkContext.mjs +15 -0
- package/ChunkProvider/ChunkProvider.d.mts +14 -0
- package/ChunkProvider/ChunkProvider.mjs +38 -0
- package/ChunkProvider/PreloadContext.d.mts +14 -0
- package/ChunkProvider/PreloadContext.mjs +18 -0
- package/ChunkProvider/PreloadProvider.d.mts +13 -0
- package/ChunkProvider/PreloadProvider.mjs +33 -0
- package/ChunkProvider/index.d.mts +7 -0
- package/ChunkProvider/index.mjs +7 -0
- package/ChunkProvider/types.d.mts +23 -0
- package/ChunkProvider/types.mjs +1 -0
- package/ChunkProvider/usePreload.d.mts +8 -0
- package/ChunkProvider/usePreload.mjs +21 -0
- package/CodeControllerContext/CodeControllerContext.d.mts +11 -0
- package/CodeControllerContext/CodeControllerContext.mjs +2 -1
- package/CodeHighlighter/CodeHighlighter.d.mts +15 -1
- package/CodeHighlighter/CodeHighlighter.mjs +97 -319
- package/CodeHighlighter/CodeHighlighterChunk.d.mts +42 -0
- package/CodeHighlighter/CodeHighlighterChunk.mjs +77 -0
- package/CodeHighlighter/CodeHighlighterClient.mjs +597 -128
- package/CodeHighlighter/CodeHighlighterContext.d.mts +57 -1
- package/CodeHighlighter/CodeHighlighterFallbackContext.d.mts +14 -2
- package/CodeHighlighter/CodeHighlighterFallbackContext.mjs +1 -3
- package/CodeHighlighter/CodeInitialSourceLoader.d.mts +10 -0
- package/CodeHighlighter/CodeInitialSourceLoader.mjs +108 -0
- package/CodeHighlighter/CodeSourceLoader.d.mts +11 -0
- package/CodeHighlighter/CodeSourceLoader.mjs +128 -0
- package/CodeHighlighter/buildCodeHighlighterChunkProps.d.mts +47 -0
- package/CodeHighlighter/buildCodeHighlighterChunkProps.mjs +61 -0
- package/CodeHighlighter/buildStringFallback.d.mts +29 -0
- package/CodeHighlighter/buildStringFallback.mjs +42 -0
- package/CodeHighlighter/codeToFallbackProps.d.mts +31 -2
- package/CodeHighlighter/codeToFallbackProps.mjs +347 -42
- package/CodeHighlighter/createClientProps.d.mts +17 -0
- package/CodeHighlighter/createClientProps.mjs +78 -0
- package/CodeHighlighter/errors.d.mts +6 -0
- package/CodeHighlighter/errors.mjs +10 -0
- package/CodeHighlighter/fallbackCompression.d.mts +96 -0
- package/CodeHighlighter/fallbackCompression.mjs +253 -0
- package/CodeHighlighter/fallbackFormat.d.mts +137 -0
- package/CodeHighlighter/fallbackFormat.mjs +422 -0
- package/CodeHighlighter/index.d.mts +4 -1
- package/CodeHighlighter/index.mjs +3 -1
- package/CodeHighlighter/mergeComments.d.mts +38 -0
- package/CodeHighlighter/mergeComments.mjs +80 -0
- package/CodeHighlighter/prepareInitialSource.d.mts +42 -0
- package/CodeHighlighter/prepareInitialSource.mjs +292 -0
- package/CodeHighlighter/resolveFallbackCritical.d.mts +23 -0
- package/CodeHighlighter/resolveFallbackCritical.mjs +44 -0
- package/CodeHighlighter/types.d.mts +272 -8
- package/CodeHighlighter/useCodeFallback.d.mts +94 -0
- package/CodeHighlighter/useCodeFallback.mjs +204 -0
- package/CodeHighlighter/useGrammarsReady.d.mts +18 -0
- package/CodeHighlighter/useGrammarsReady.mjs +45 -0
- package/CodeHighlighter/useSpeculativeCodePreload.d.mts +26 -0
- package/CodeHighlighter/useSpeculativeCodePreload.mjs +40 -0
- package/CodeHighlighter/useSpeculativeEditingPreload.d.mts +33 -0
- package/CodeHighlighter/useSpeculativeEditingPreload.mjs +58 -0
- package/CodeHighlighter/useSpeculativeGrammarPreload.d.mts +23 -0
- package/CodeHighlighter/useSpeculativeGrammarPreload.mjs +31 -0
- package/CodeHighlighter/useSpeculativeUseCodePreload.d.mts +22 -0
- package/CodeHighlighter/useSpeculativeUseCodePreload.mjs +41 -0
- package/CodeProvider/CodeContext.d.mts +47 -12
- package/CodeProvider/CodeContext.mjs +7 -0
- package/CodeProvider/CodeProvider.d.mts +4 -2
- package/CodeProvider/CodeProvider.mjs +40 -102
- package/CodeProvider/CodeProviderLazy.d.mts +40 -0
- package/CodeProvider/CodeProviderLazy.mjs +96 -0
- package/CodeProvider/constants.d.mts +26 -0
- package/CodeProvider/constants.mjs +24 -0
- package/CodeProvider/createParseSourceWorkerClient.d.mts +6 -0
- package/CodeProvider/createParseSourceWorkerClient.mjs +22 -2
- package/CodeProvider/index.d.mts +2 -1
- package/CodeProvider/index.mjs +9 -1
- package/CodeProvider/parseSourceWorker.mjs +33 -0
- package/CodeProvider/useCodeProviderValue.d.mts +54 -0
- package/CodeProvider/useCodeProviderValue.mjs +188 -0
- package/CoordinatedLazy/ChunkServerLoader.d.mts +25 -0
- package/CoordinatedLazy/ChunkServerLoader.mjs +97 -0
- package/CoordinatedLazy/CoordinatedContentContext.d.mts +15 -0
- package/CoordinatedLazy/CoordinatedContentContext.mjs +22 -0
- package/CoordinatedLazy/CoordinatedFallbackContext.d.mts +11 -0
- package/CoordinatedLazy/CoordinatedFallbackContext.mjs +13 -0
- package/CoordinatedLazy/CoordinatedGateContext.d.mts +14 -0
- package/CoordinatedLazy/CoordinatedGateContext.mjs +19 -0
- package/CoordinatedLazy/CoordinatedLazy.d.mts +14 -0
- package/CoordinatedLazy/CoordinatedLazy.mjs +86 -0
- package/CoordinatedLazy/CoordinatedLazyClient.d.mts +24 -0
- package/CoordinatedLazy/CoordinatedLazyClient.mjs +65 -0
- package/CoordinatedLazy/LazyContent.d.mts +26 -0
- package/CoordinatedLazy/LazyContent.mjs +80 -0
- package/CoordinatedLazy/LazyContentServer.d.mts +18 -0
- package/CoordinatedLazy/LazyContentServer.mjs +25 -0
- package/CoordinatedLazy/buildChunkRenderInputs.d.mts +8 -0
- package/CoordinatedLazy/buildChunkRenderInputs.mjs +35 -0
- package/CoordinatedLazy/createCoordinatedLazy.d.mts +32 -0
- package/CoordinatedLazy/createCoordinatedLazy.mjs +127 -0
- package/CoordinatedLazy/index.d.mts +14 -0
- package/CoordinatedLazy/index.mjs +18 -0
- package/CoordinatedLazy/resolveChunkRender.d.mts +26 -0
- package/CoordinatedLazy/resolveChunkRender.mjs +73 -0
- package/CoordinatedLazy/types.d.mts +408 -0
- package/CoordinatedLazy/types.mjs +1 -0
- package/CoordinatedLazy/useChunk.d.mts +30 -0
- package/CoordinatedLazy/useChunk.mjs +135 -0
- package/CoordinatedLazy/useCoordinatedFallback.d.mts +12 -0
- package/CoordinatedLazy/useCoordinatedFallback.mjs +40 -0
- package/CoordinatedLazy/useCoordinatedSwap.d.mts +16 -0
- package/CoordinatedLazy/useCoordinatedSwap.mjs +124 -0
- package/LICENSE +1 -1
- package/abstractCreateDemo/abstractCreateDemo.d.mts +54 -3
- package/abstractCreateDemo/abstractCreateDemo.mjs +47 -7
- package/abstractCreateDemo/resolveDemoFlag.d.mts +20 -0
- package/abstractCreateDemo/resolveDemoFlag.mjs +25 -0
- package/abstractCreateStream/abstractCreateStream.d.mts +18 -0
- package/abstractCreateStream/abstractCreateStream.mjs +45 -0
- package/abstractCreateStream/index.d.mts +2 -0
- package/abstractCreateStream/index.mjs +1 -0
- package/abstractCreateStream/types.d.mts +34 -0
- package/abstractCreateStream/types.mjs +1 -0
- package/abstractCreateTypes/TypeCode.mjs +12 -11
- package/abstractCreateTypes/typesToJsx.mjs +30 -9
- package/cli/ensureDemoClients.mjs +4 -148
- package/cli/ensureDemoPages.d.mts +45 -0
- package/cli/ensureDemoPages.mjs +99 -0
- package/cli/fileUtils/index.d.mts +11 -0
- package/cli/fileUtils/index.mjs +48 -0
- package/cli/findDemoIndexFiles.d.mts +15 -0
- package/cli/findDemoIndexFiles.mjs +121 -0
- package/cli/index.mjs +1 -1
- package/cli/loadNextConfig.d.mts +25 -0
- package/cli/loadNextConfig.mjs +60 -1
- package/cli/runBrowser.mjs +1 -1
- package/cli/runValidate.mjs +44 -1
- package/package.json +84 -4
- package/pipeline/enhanceCodeEmphasis/enhanceCodeEmphasis.mjs +30 -0
- package/pipeline/enhanceCodeEmphasis/enhanceCodeEmphasisLazy.d.mts +17 -0
- package/pipeline/enhanceCodeEmphasis/enhanceCodeEmphasisLazy.mjs +52 -0
- package/pipeline/hastUtils/frameFallbackFromSpans.d.mts +18 -0
- package/pipeline/hastUtils/frameFallbackFromSpans.mjs +24 -0
- package/pipeline/hastUtils/hast.d.mts +27 -0
- package/pipeline/hastUtils/hastCompression.d.mts +3 -1
- package/pipeline/hastUtils/hastCompression.mjs +9 -1
- package/pipeline/hastUtils/hastDecompress.mjs +10 -4
- package/pipeline/hastUtils/hastDictionary.mjs +9 -0
- package/pipeline/hastUtils/hastUtils.d.mts +4 -3
- package/pipeline/hastUtils/hastUtils.mjs +24 -12
- package/pipeline/hastUtils/index.d.mts +2 -1
- package/pipeline/hastUtils/index.mjs +2 -1
- package/pipeline/hastUtils/stripHighlightingSpans.d.mts +6 -2
- package/pipeline/hastUtils/stripHighlightingSpans.mjs +22 -10
- package/pipeline/lintJavascriptDemoFocus/lintJavascriptDemoFocus.mjs +10 -7
- package/pipeline/loadIsomorphicCodeVariant/applyCodeTransform.d.mts +31 -13
- package/pipeline/loadIsomorphicCodeVariant/applyCodeTransform.mjs +50 -55
- package/pipeline/loadIsomorphicCodeVariant/applyCodeTransformWithComments.d.mts +78 -0
- package/pipeline/loadIsomorphicCodeVariant/applyCodeTransformWithComments.mjs +405 -0
- package/pipeline/loadIsomorphicCodeVariant/computeHastDeltas.d.mts +5 -5
- package/pipeline/loadIsomorphicCodeVariant/computeHastDeltas.mjs +36 -66
- package/pipeline/loadIsomorphicCodeVariant/decodeHastSource.d.mts +23 -0
- package/pipeline/loadIsomorphicCodeVariant/decodeHastSource.mjs +92 -0
- package/pipeline/loadIsomorphicCodeVariant/decodeSource.d.mts +19 -0
- package/pipeline/loadIsomorphicCodeVariant/decodeSource.mjs +25 -0
- package/pipeline/loadIsomorphicCodeVariant/decodeSourceToText.d.mts +17 -0
- package/pipeline/loadIsomorphicCodeVariant/decodeSourceToText.mjs +26 -0
- package/pipeline/loadIsomorphicCodeVariant/diffHast.d.mts +26 -2
- package/pipeline/loadIsomorphicCodeVariant/diffHast.mjs +563 -19
- package/pipeline/loadIsomorphicCodeVariant/embedTransforms.d.mts +49 -0
- package/pipeline/loadIsomorphicCodeVariant/embedTransforms.mjs +152 -0
- package/pipeline/loadIsomorphicCodeVariant/findExpandingRanges.d.mts +51 -0
- package/pipeline/loadIsomorphicCodeVariant/findExpandingRanges.mjs +161 -0
- package/pipeline/loadIsomorphicCodeVariant/flattenCodeVariant.mjs +6 -3
- package/pipeline/loadIsomorphicCodeVariant/getAvailableTransforms.d.mts +12 -0
- package/pipeline/loadIsomorphicCodeVariant/getAvailableTransforms.mjs +44 -0
- package/pipeline/loadIsomorphicCodeVariant/getInitialVisibleSourceLines.d.mts +16 -0
- package/pipeline/loadIsomorphicCodeVariant/getInitialVisibleSourceLines.mjs +74 -0
- package/pipeline/loadIsomorphicCodeVariant/loadCodeFallback.mjs +17 -5
- package/pipeline/loadIsomorphicCodeVariant/loadIsomorphicCodeVariant.mjs +229 -15
- package/pipeline/loadIsomorphicCodeVariant/transformSource.d.mts +2 -2
- package/pipeline/loadIsomorphicCodeVariant/transformSource.mjs +56 -22
- package/pipeline/loadPrecomputedCodeHighlighter/loadPrecomputedCodeHighlighter.d.mts +18 -0
- package/pipeline/loadPrecomputedCodeHighlighter/loadPrecomputedCodeHighlighter.mjs +11 -7
- package/pipeline/loadServerTypes/hastTypeUtils.d.mts +2 -2
- package/pipeline/loadServerTypes/hastTypeUtils.mjs +4 -4
- package/pipeline/loadServerTypes/loadServerTypes.mjs +1 -1
- package/pipeline/loadServerTypesMeta/extractJSDocText.d.mts +14 -0
- package/pipeline/loadServerTypesMeta/extractJSDocText.mjs +60 -0
- package/pipeline/loadServerTypesMeta/processTypes.mjs +43 -46
- package/pipeline/loadServerTypesText/order.mjs +1 -1
- package/pipeline/loadServerTypesText/parseTypesMarkdown.mjs +3 -1
- package/pipeline/loaderUtils/index.d.mts +0 -1
- package/pipeline/loaderUtils/index.mjs +0 -1
- package/pipeline/loaderUtils/parseImportsAndComments.d.mts +5 -1
- package/pipeline/loaderUtils/parseImportsAndComments.mjs +19 -9
- package/pipeline/loaderUtils/resolveModulePath.mjs +23 -1
- package/pipeline/parseCreateFactoryCall/parseCreateFactoryCall.d.mts +12 -0
- package/pipeline/parseCreateFactoryCall/parseCreateFactoryCall.mjs +17 -13
- package/pipeline/parseSource/addLineGutters.mjs +45 -11
- package/pipeline/parseSource/calculateFrameRanges.d.mts +22 -0
- package/pipeline/parseSource/calculateFrameRanges.mjs +69 -25
- package/pipeline/parseSource/detectGrammarScopes.d.mts +13 -0
- package/pipeline/parseSource/detectGrammarScopes.mjs +35 -0
- package/pipeline/parseSource/extendSyntaxTokens.mjs +501 -43
- package/pipeline/parseSource/frameVisibility.d.mts +47 -0
- package/pipeline/parseSource/frameVisibility.mjs +114 -0
- package/pipeline/parseSource/grammarCache.d.mts +33 -0
- package/pipeline/parseSource/grammarCache.mjs +73 -0
- package/pipeline/parseSource/grammarLoaders.d.mts +14 -0
- package/pipeline/parseSource/grammarLoaders.mjs +24 -0
- package/pipeline/parseSource/grammarMaps.d.mts +21 -1
- package/pipeline/parseSource/grammarMaps.mjs +36 -0
- package/pipeline/parseSource/isFrameSpan.d.mts +19 -0
- package/pipeline/parseSource/isFrameSpan.mjs +24 -0
- package/pipeline/parseSource/parseSource.d.mts +41 -6
- package/pipeline/parseSource/parseSource.mjs +184 -36
- package/pipeline/parseSource/redistributeFrameFallbacks.d.mts +40 -0
- package/pipeline/parseSource/redistributeFrameFallbacks.mjs +138 -0
- package/pipeline/parseSource/restructureFrames.d.mts +5 -0
- package/pipeline/parseSource/restructureFrames.mjs +179 -16
- package/pipeline/syncPageIndex/metadataToMarkdown.mjs +6 -2
- package/pipeline/transformHtmlCodeBlock/transformHtmlCodeBlock.d.mts +26 -0
- package/pipeline/transformHtmlCodeBlock/transformHtmlCodeBlock.mjs +181 -114
- package/pipeline/transformHtmlCodeInline/removeSuffixFromHighlightedNodes.d.mts +12 -0
- package/pipeline/transformHtmlCodeInline/removeSuffixFromHighlightedNodes.mjs +52 -0
- package/pipeline/transformHtmlCodeInline/transformHtmlCodeInline.mjs +22 -1
- package/pipeline/transformTypescriptToJavascript/removeTypes.d.mts +5 -8
- package/pipeline/transformTypescriptToJavascript/removeTypes.mjs +27 -93
- package/useCode/EditableEngine.d.mts +233 -0
- package/useCode/EditableEngine.mjs +1712 -0
- package/useCode/EditingEngine.d.mts +13 -0
- package/useCode/EditingEngine.mjs +14 -0
- package/useCode/Pre.browser.mjs +5 -1
- package/useCode/Pre.d.mts +127 -1
- package/useCode/Pre.mjs +417 -165
- package/useCode/SourceEditingEngine.d.mts +50 -0
- package/useCode/SourceEditingEngine.mjs +461 -0
- package/useCode/TransformEngine.d.mts +39 -0
- package/useCode/TransformEngine.mjs +208 -0
- package/useCode/editingEngineCache.d.mts +29 -0
- package/useCode/editingEngineCache.mjs +68 -0
- package/useCode/sourceLineCounts.d.mts +80 -0
- package/useCode/sourceLineCounts.mjs +284 -0
- package/useCode/subscribeToggleNudge.d.mts +3 -0
- package/useCode/subscribeToggleNudge.mjs +95 -0
- package/useCode/transformEngineCache.d.mts +21 -0
- package/useCode/transformEngineCache.mjs +60 -0
- package/useCode/useCode.d.mts +140 -1
- package/useCode/useCode.mjs +250 -19
- package/useCode/useCodeUtils.d.mts +131 -20
- package/useCode/useCodeUtils.mjs +267 -194
- package/useCode/useCopyFunctionality.d.mts +13 -1
- package/useCode/useCopyFunctionality.mjs +39 -9
- package/useCode/useEditable.browser.mjs +10 -2
- package/useCode/useEditable.d.mts +27 -106
- package/useCode/useEditable.integration.browser.d.mts +1 -0
- package/useCode/useEditable.integration.browser.mjs +870 -0
- package/useCode/useEditable.mjs +198 -1247
- package/useCode/useEditableUtils.d.mts +50 -1
- package/useCode/useEditableUtils.mjs +29 -0
- package/useCode/useFileNavigation.d.mts +91 -3
- package/useCode/useFileNavigation.mjs +201 -41
- package/useCode/useHighlightGate.d.mts +17 -0
- package/useCode/useHighlightGate.mjs +147 -0
- package/useCode/useSourceEditing.d.mts +8 -0
- package/useCode/useSourceEditing.mjs +158 -314
- package/useCode/useSourceEnhancing.d.mts +5 -1
- package/useCode/useSourceEnhancing.mjs +22 -36
- package/useCode/useTransformManagement.d.mts +93 -5
- package/useCode/useTransformManagement.mjs +496 -28
- package/useCode/useTransitionPhase.d.mts +24 -0
- package/useCode/useTransitionPhase.mjs +49 -0
- package/useCode/useUIState.d.mts +2 -2
- package/useCode/useUIState.mjs +8 -8
- package/useCode/useVariantSelection.d.mts +130 -6
- package/useCode/useVariantSelection.mjs +529 -93
- package/useCodeWindow/useCodeWindow.d.mts +19 -2
- package/useCodeWindow/useCodeWindow.mjs +98 -71
- package/useCoordinated/coordinatePreference.d.mts +439 -0
- package/useCoordinated/coordinatePreference.mjs +951 -0
- package/useCoordinated/coordinatePreference.testUtils.d.mts +21 -0
- package/useCoordinated/coordinatePreference.testUtils.mjs +69 -0
- package/useCoordinated/createSettleGate.d.mts +96 -0
- package/useCoordinated/createSettleGate.mjs +171 -0
- package/useCoordinated/index.d.mts +8 -0
- package/useCoordinated/index.mjs +8 -0
- package/useCoordinated/layoutShiftGate.d.mts +24 -0
- package/useCoordinated/layoutShiftGate.mjs +79 -0
- package/useCoordinated/pageSettleGate.d.mts +11 -0
- package/useCoordinated/pageSettleGate.mjs +13 -0
- package/useCoordinated/scheduleTasks.d.mts +23 -0
- package/useCoordinated/scheduleTasks.mjs +45 -0
- package/useCoordinated/useCoordinated.d.mts +193 -0
- package/useCoordinated/useCoordinated.mjs +469 -0
- package/useCoordinated/useCoordinatedLazy.d.mts +17 -0
- package/useCoordinated/useCoordinatedLazy.mjs +38 -0
- package/useCoordinated/useCoordinatedLocalStorage.d.mts +16 -0
- package/useCoordinated/useCoordinatedLocalStorage.mjs +22 -0
- package/useCoordinated/useCoordinatedPreference.d.mts +20 -0
- package/useCoordinated/useCoordinatedPreference.mjs +26 -0
- package/useCoordinated/useSettleGate.d.mts +11 -0
- package/useCoordinated/useSettleGate.mjs +34 -0
- package/useDemo/exportVariant.d.mts +12 -5
- package/useDemo/exportVariant.mjs +59 -5
- package/useDemo/useDemo.d.mts +5 -2
- package/useScrollAnchor/useScrollAnchor.mjs +28 -5
- package/useStream/index.d.mts +6 -0
- package/useStream/index.mjs +6 -0
- package/useStream/streamChunks.d.mts +23 -0
- package/useStream/streamChunks.mjs +85 -0
- package/useStream/types.d.mts +45 -0
- package/useStream/types.mjs +1 -0
- package/useStream/useStream.d.mts +57 -0
- package/useStream/useStream.mjs +119 -0
- package/useStream/useStreamController.d.mts +15 -0
- package/useStream/useStreamController.mjs +90 -0
- package/withDocsInfra/withDocsInfra.d.mts +19 -0
- package/withDocsInfra/withDocsInfra.mjs +13 -5
- package/pipeline/loaderUtils/convertCommentsToOneIndexed.d.mts +0 -8
- package/pipeline/loaderUtils/convertCommentsToOneIndexed.mjs +0 -16
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reset all module state between test cases. Production callers never
|
|
3
|
+
* need this; channels self-dispose when their last peer unregisters.
|
|
4
|
+
*/
|
|
5
|
+
export declare function resetCoordinatorsForTests(): void;
|
|
6
|
+
/**
|
|
7
|
+
* Snapshot of channel/peer/barrier counts across all channels.
|
|
8
|
+
* Useful for asserting cleanup in tests.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getCoordinatorStatsForTests(): {
|
|
11
|
+
channelCount: number;
|
|
12
|
+
totalPeers: number;
|
|
13
|
+
totalPendingBarriers: number;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Override the target encoder. Returns a function that restores the
|
|
17
|
+
* previous encoder. Useful when the value type contains unstable
|
|
18
|
+
* references that the default `JSON.stringify`-based encoder cannot
|
|
19
|
+
* key deterministically.
|
|
20
|
+
*/
|
|
21
|
+
export declare function setTargetEncoderForTests(impl: (value: unknown) => string): () => void;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test-only affordances for `coordinatePreference`. Kept in a sibling
|
|
3
|
+
* file so the production module's public surface (`registerPeer`,
|
|
4
|
+
* `announceTarget`, `reportValue`, `hasEverAnnounced`,
|
|
5
|
+
* `getBarrierAnnounceTime`) stays free of helpers that should never
|
|
6
|
+
* be reachable from runtime code or re-exported from the package
|
|
7
|
+
* entry.
|
|
8
|
+
*
|
|
9
|
+
* The implementation here reaches into `__testInternals` from
|
|
10
|
+
* `coordinatePreference.ts`. That export is the only sanctioned
|
|
11
|
+
* channel into module-private state and is marked `__`-prefixed so
|
|
12
|
+
* accidental imports are obvious in code review.
|
|
13
|
+
*/
|
|
14
|
+
import { __testInternals } from "./coordinatePreference.mjs";
|
|
15
|
+
const {
|
|
16
|
+
channels,
|
|
17
|
+
setTargetEncoder
|
|
18
|
+
} = __testInternals;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Reset all module state between test cases. Production callers never
|
|
22
|
+
* need this; channels self-dispose when their last peer unregisters.
|
|
23
|
+
*/
|
|
24
|
+
export function resetCoordinatorsForTests() {
|
|
25
|
+
for (const channel of channels.values()) {
|
|
26
|
+
for (const barrier of channel.pendingBarriers.values()) {
|
|
27
|
+
clearTimeout(barrier.minWaitTimer);
|
|
28
|
+
clearTimeout(barrier.waitingForPeersTimer);
|
|
29
|
+
clearTimeout(barrier.ultimateTimer);
|
|
30
|
+
for (const waiter of barrier.waiters.values()) {
|
|
31
|
+
waiter.abort.abort();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
for (const peer of channel.peers.values()) {
|
|
35
|
+
for (const controller of peer.lazyInFlight.keys()) {
|
|
36
|
+
controller.abort();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
channels.clear();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Snapshot of channel/peer/barrier counts across all channels.
|
|
45
|
+
* Useful for asserting cleanup in tests.
|
|
46
|
+
*/
|
|
47
|
+
export function getCoordinatorStatsForTests() {
|
|
48
|
+
let totalPeers = 0;
|
|
49
|
+
let totalPendingBarriers = 0;
|
|
50
|
+
for (const channel of channels.values()) {
|
|
51
|
+
totalPeers += channel.peers.size;
|
|
52
|
+
totalPendingBarriers += channel.pendingBarriers.size;
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
channelCount: channels.size,
|
|
56
|
+
totalPeers,
|
|
57
|
+
totalPendingBarriers
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Override the target encoder. Returns a function that restores the
|
|
63
|
+
* previous encoder. Useful when the value type contains unstable
|
|
64
|
+
* references that the default `JSON.stringify`-based encoder cannot
|
|
65
|
+
* key deterministically.
|
|
66
|
+
*/
|
|
67
|
+
export function setTargetEncoderForTests(impl) {
|
|
68
|
+
return setTargetEncoder(impl);
|
|
69
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fallback ceiling for {@link createSettleGate}: if a registered source never
|
|
3
|
+
* settles (its swap errored or hung), the gate opens anyway after this many
|
|
4
|
+
* milliseconds so coordination can never be blocked forever. Matches the
|
|
5
|
+
* coordinator's default `ultimateTimeoutMs` and the value the module-global
|
|
6
|
+
* `layoutShiftGate` shipped with.
|
|
7
|
+
*/
|
|
8
|
+
export declare const SETTLE_SAFETY_TIMEOUT_MS = 10000;
|
|
9
|
+
/**
|
|
10
|
+
* A reusable "all sources settled" gate.
|
|
11
|
+
*
|
|
12
|
+
* The module-global page-wide layout-shift gate (`layoutShiftGate`) is one
|
|
13
|
+
* instance; each `StreamController` and `CoordinatedLazy` swap registers with
|
|
14
|
+
* one too. The behavior is the original layout-shift gate's, plus two opt-in
|
|
15
|
+
* completion signals (`expect` / `markLast`) for sources that arrive over time
|
|
16
|
+
* (chunks streaming in across ticks) rather than all within the initial
|
|
17
|
+
* hydration commit.
|
|
18
|
+
*
|
|
19
|
+
* Lifecycle: a source `register()`s and later calls the returned settle
|
|
20
|
+
* function when it reaches its stable state. The gate opens once every
|
|
21
|
+
* registered source has settled (and any completion constraint is met). It
|
|
22
|
+
* opens **once** and never re-closes - a source that registers after the gate
|
|
23
|
+
* has opened adopts the open state rather than re-closing it for everyone
|
|
24
|
+
* ("all sources" means "all present by the initial settle").
|
|
25
|
+
*/
|
|
26
|
+
export interface SettleGate {
|
|
27
|
+
/**
|
|
28
|
+
* Register a pending source. Returns an idempotent settle function; call it
|
|
29
|
+
* when the source reaches its stable state. Calling it more than once is a
|
|
30
|
+
* no-op. Registering after the gate has already opened returns a no-op settle
|
|
31
|
+
* and does not re-close the gate.
|
|
32
|
+
*/
|
|
33
|
+
register(): () => void;
|
|
34
|
+
/**
|
|
35
|
+
* `true` before any source registers (nothing to wait for) and once every
|
|
36
|
+
* registered source has settled and any completion constraint is met.
|
|
37
|
+
*/
|
|
38
|
+
isSettled(): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Resolves once {@link isSettled} is `true`. Returns `null` synchronously
|
|
41
|
+
* when already settled so callers can take a fast path (mirrors the original
|
|
42
|
+
* `whenLayoutShiftsSettled`). Rejects with an `AbortError` if `signal` aborts
|
|
43
|
+
* first, so a superseding wait can be abandoned.
|
|
44
|
+
*/
|
|
45
|
+
whenSettled(signal?: AbortSignal): Promise<void> | null;
|
|
46
|
+
/**
|
|
47
|
+
* Declare how many sources will register in total. The gate then holds until
|
|
48
|
+
* at least `count` sources have registered (and all have settled), so it
|
|
49
|
+
* won't open during a momentary lull while later sources are still arriving -
|
|
50
|
+
* e.g. chunks streaming in across separate ticks. This is **known-count**
|
|
51
|
+
* completion.
|
|
52
|
+
*
|
|
53
|
+
* Pass a non-finite value (e.g. `Number.POSITIVE_INFINITY`) to hold the gate
|
|
54
|
+
* open-indefinitely for an unknown-count stream, then call {@link markLast}
|
|
55
|
+
* when the stream ends.
|
|
56
|
+
*/
|
|
57
|
+
expect(count: number): void;
|
|
58
|
+
/**
|
|
59
|
+
* Terminal signal for **last-chunk** completion. Once called, the gate opens
|
|
60
|
+
* as soon as every outstanding source has settled, regardless of any `expect`
|
|
61
|
+
* count. Use it to end an unknown-count stream held open via
|
|
62
|
+
* `expect(Infinity)`, or to finish early before an `expect(n)` count is
|
|
63
|
+
* reached. Standalone - it does not require `expect` to have been called.
|
|
64
|
+
*/
|
|
65
|
+
markLast(): void;
|
|
66
|
+
/** Reset all state to the initial unarmed gate. Test-only. */
|
|
67
|
+
reset(): void;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Options for {@link createSettleGate}.
|
|
71
|
+
*/
|
|
72
|
+
export interface CreateSettleGateOptions {
|
|
73
|
+
/**
|
|
74
|
+
* Fallback ceiling (ms): open the gate even if a registered source never
|
|
75
|
+
* settles.
|
|
76
|
+
* @default SETTLE_SAFETY_TIMEOUT_MS
|
|
77
|
+
*/
|
|
78
|
+
safetyTimeoutMs?: number;
|
|
79
|
+
/**
|
|
80
|
+
* Schedule the deferred settle check. Defaults to `queueMicrotask`, which
|
|
81
|
+
* batches a burst of same-tick registrations before declaring the gate
|
|
82
|
+
* settled. Injectable so tests can drive the check synchronously.
|
|
83
|
+
*/
|
|
84
|
+
scheduleCheck?: (callback: () => void) => void;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Create an independent "all sources settled" gate. See {@link SettleGate} for
|
|
88
|
+
* the contract.
|
|
89
|
+
*
|
|
90
|
+
* Isomorphic - it touches only `setTimeout` and the injectable `scheduleCheck`
|
|
91
|
+
* (default `queueMicrotask`), so it runs in tests and during SSR without the
|
|
92
|
+
* DOM. Client-only consumers are responsible for never registering during SSR
|
|
93
|
+
* (the page-wide layout-shift gate is only ever touched on the client for this
|
|
94
|
+
* reason).
|
|
95
|
+
*/
|
|
96
|
+
export declare function createSettleGate(options?: CreateSettleGateOptions): SettleGate;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fallback ceiling for {@link createSettleGate}: if a registered source never
|
|
3
|
+
* settles (its swap errored or hung), the gate opens anyway after this many
|
|
4
|
+
* milliseconds so coordination can never be blocked forever. Matches the
|
|
5
|
+
* coordinator's default `ultimateTimeoutMs` and the value the module-global
|
|
6
|
+
* `layoutShiftGate` shipped with.
|
|
7
|
+
*/
|
|
8
|
+
export const SETTLE_SAFETY_TIMEOUT_MS = 10_000;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A reusable "all sources settled" gate.
|
|
12
|
+
*
|
|
13
|
+
* The module-global page-wide layout-shift gate (`layoutShiftGate`) is one
|
|
14
|
+
* instance; each `StreamController` and `CoordinatedLazy` swap registers with
|
|
15
|
+
* one too. The behavior is the original layout-shift gate's, plus two opt-in
|
|
16
|
+
* completion signals (`expect` / `markLast`) for sources that arrive over time
|
|
17
|
+
* (chunks streaming in across ticks) rather than all within the initial
|
|
18
|
+
* hydration commit.
|
|
19
|
+
*
|
|
20
|
+
* Lifecycle: a source `register()`s and later calls the returned settle
|
|
21
|
+
* function when it reaches its stable state. The gate opens once every
|
|
22
|
+
* registered source has settled (and any completion constraint is met). It
|
|
23
|
+
* opens **once** and never re-closes - a source that registers after the gate
|
|
24
|
+
* has opened adopts the open state rather than re-closing it for everyone
|
|
25
|
+
* ("all sources" means "all present by the initial settle").
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Options for {@link createSettleGate}.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Create an independent "all sources settled" gate. See {@link SettleGate} for
|
|
34
|
+
* the contract.
|
|
35
|
+
*
|
|
36
|
+
* Isomorphic - it touches only `setTimeout` and the injectable `scheduleCheck`
|
|
37
|
+
* (default `queueMicrotask`), so it runs in tests and during SSR without the
|
|
38
|
+
* DOM. Client-only consumers are responsible for never registering during SSR
|
|
39
|
+
* (the page-wide layout-shift gate is only ever touched on the client for this
|
|
40
|
+
* reason).
|
|
41
|
+
*/
|
|
42
|
+
export function createSettleGate(options = {}) {
|
|
43
|
+
const safetyTimeoutMs = options.safetyTimeoutMs ?? SETTLE_SAFETY_TIMEOUT_MS;
|
|
44
|
+
const scheduleCheck = options.scheduleCheck ?? (typeof queueMicrotask === 'function' ? queueMicrotask : callback => {
|
|
45
|
+
Promise.resolve().then(callback);
|
|
46
|
+
});
|
|
47
|
+
let pendingCount = 0;
|
|
48
|
+
let registeredCount = 0;
|
|
49
|
+
// `true` once at least one source has registered - until then there is
|
|
50
|
+
// nothing to wait for and the gate reports settled.
|
|
51
|
+
let armed = false;
|
|
52
|
+
let settled = false;
|
|
53
|
+
let checkScheduled = false;
|
|
54
|
+
// Completion constraints layered on top of "every source settled":
|
|
55
|
+
// `expectedCount` holds the gate until that many sources have registered
|
|
56
|
+
// (known-count); `sawLast` is the standalone terminal that opens on the next
|
|
57
|
+
// pending-zero regardless of the count (last-chunk).
|
|
58
|
+
let expectedCount = null;
|
|
59
|
+
let sawLast = false;
|
|
60
|
+
let safetyTimer = null;
|
|
61
|
+
const settleListeners = new Set();
|
|
62
|
+
function isComplete() {
|
|
63
|
+
if (sawLast) {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
if (expectedCount !== null) {
|
|
67
|
+
return registeredCount >= expectedCount;
|
|
68
|
+
}
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
function openGate() {
|
|
72
|
+
if (settled) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
settled = true;
|
|
76
|
+
if (safetyTimer !== null) {
|
|
77
|
+
clearTimeout(safetyTimer);
|
|
78
|
+
safetyTimer = null;
|
|
79
|
+
}
|
|
80
|
+
const listeners = Array.from(settleListeners);
|
|
81
|
+
settleListeners.clear();
|
|
82
|
+
for (const listener of listeners) {
|
|
83
|
+
listener();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function scheduleSettleCheck() {
|
|
87
|
+
if (settled || checkScheduled) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
checkScheduled = true;
|
|
91
|
+
// Defer past the current tick so a burst of same-tick registrations - or an
|
|
92
|
+
// early settle that precedes a sibling's registration - all land before we
|
|
93
|
+
// declare the gate settled.
|
|
94
|
+
scheduleCheck(() => {
|
|
95
|
+
checkScheduled = false;
|
|
96
|
+
if (!settled && armed && pendingCount === 0 && isComplete()) {
|
|
97
|
+
openGate();
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
register() {
|
|
103
|
+
if (settled) {
|
|
104
|
+
return () => {};
|
|
105
|
+
}
|
|
106
|
+
armed = true;
|
|
107
|
+
pendingCount += 1;
|
|
108
|
+
registeredCount += 1;
|
|
109
|
+
if (safetyTimer === null && typeof setTimeout === 'function') {
|
|
110
|
+
safetyTimer = setTimeout(openGate, safetyTimeoutMs);
|
|
111
|
+
}
|
|
112
|
+
let done = false;
|
|
113
|
+
return () => {
|
|
114
|
+
if (done) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
done = true;
|
|
118
|
+
pendingCount -= 1;
|
|
119
|
+
scheduleSettleCheck();
|
|
120
|
+
};
|
|
121
|
+
},
|
|
122
|
+
isSettled() {
|
|
123
|
+
return settled || !armed;
|
|
124
|
+
},
|
|
125
|
+
whenSettled(signal) {
|
|
126
|
+
if (settled || !armed) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
return new Promise((resolve, reject) => {
|
|
130
|
+
const onSettle = () => {
|
|
131
|
+
signal?.removeEventListener('abort', onAbort);
|
|
132
|
+
resolve();
|
|
133
|
+
};
|
|
134
|
+
function onAbort() {
|
|
135
|
+
settleListeners.delete(onSettle);
|
|
136
|
+
reject(new DOMException('Settle gate wait aborted', 'AbortError'));
|
|
137
|
+
}
|
|
138
|
+
if (signal) {
|
|
139
|
+
if (signal.aborted) {
|
|
140
|
+
reject(new DOMException('Settle gate wait aborted', 'AbortError'));
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
signal.addEventListener('abort', onAbort);
|
|
144
|
+
}
|
|
145
|
+
settleListeners.add(onSettle);
|
|
146
|
+
});
|
|
147
|
+
},
|
|
148
|
+
expect(count) {
|
|
149
|
+
expectedCount = count;
|
|
150
|
+
scheduleSettleCheck();
|
|
151
|
+
},
|
|
152
|
+
markLast() {
|
|
153
|
+
sawLast = true;
|
|
154
|
+
scheduleSettleCheck();
|
|
155
|
+
},
|
|
156
|
+
reset() {
|
|
157
|
+
pendingCount = 0;
|
|
158
|
+
registeredCount = 0;
|
|
159
|
+
armed = false;
|
|
160
|
+
settled = false;
|
|
161
|
+
checkScheduled = false;
|
|
162
|
+
expectedCount = null;
|
|
163
|
+
sawLast = false;
|
|
164
|
+
if (safetyTimer !== null) {
|
|
165
|
+
clearTimeout(safetyTimer);
|
|
166
|
+
safetyTimer = null;
|
|
167
|
+
}
|
|
168
|
+
settleListeners.clear();
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { useCoordinated, type UseCoordinatedOptions, type UseCoordinatedExtras } from "./useCoordinated.mjs";
|
|
2
|
+
export { useCoordinatedLocalStorage } from "./useCoordinatedLocalStorage.mjs";
|
|
3
|
+
export { useCoordinatedPreference } from "./useCoordinatedPreference.mjs";
|
|
4
|
+
export { registerLayoutShiftSource, whenLayoutShiftsSettled, layoutShiftsSettled } from "./layoutShiftGate.mjs";
|
|
5
|
+
export { useCoordinatedLazy } from "./useCoordinatedLazy.mjs";
|
|
6
|
+
export { createSettleGate, SETTLE_SAFETY_TIMEOUT_MS, type SettleGate, type CreateSettleGateOptions } from "./createSettleGate.mjs";
|
|
7
|
+
export { pageSettleGate } from "./pageSettleGate.mjs";
|
|
8
|
+
export { useSettleGate } from "./useSettleGate.mjs";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { useCoordinated } from "./useCoordinated.mjs";
|
|
2
|
+
export { useCoordinatedLocalStorage } from "./useCoordinatedLocalStorage.mjs";
|
|
3
|
+
export { useCoordinatedPreference } from "./useCoordinatedPreference.mjs";
|
|
4
|
+
export { registerLayoutShiftSource, whenLayoutShiftsSettled, layoutShiftsSettled } from "./layoutShiftGate.mjs";
|
|
5
|
+
export { useCoordinatedLazy } from "./useCoordinatedLazy.mjs";
|
|
6
|
+
export { createSettleGate, SETTLE_SAFETY_TIMEOUT_MS } from "./createSettleGate.mjs";
|
|
7
|
+
export { pageSettleGate } from "./pageSettleGate.mjs";
|
|
8
|
+
export { useSettleGate } from "./useSettleGate.mjs";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Register a source that may cause a layout shift once it settles. Call the
|
|
3
|
+
* returned function when the source has reached its stable post-hydration
|
|
4
|
+
* layout. Idempotent — calling it more than once is a no-op.
|
|
5
|
+
*/
|
|
6
|
+
export declare function registerLayoutShiftSource(): () => void;
|
|
7
|
+
/**
|
|
8
|
+
* Whether the page's initial layout-shifting swaps have settled. `true` before
|
|
9
|
+
* any source registers (nothing to wait for) and once every registered source
|
|
10
|
+
* has settled.
|
|
11
|
+
*/
|
|
12
|
+
export declare function layoutShiftsSettled(): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Resolves once {@link layoutShiftsSettled} is `true`. Returns `null`
|
|
15
|
+
* synchronously when already settled so callers can take a fast path (mirrors
|
|
16
|
+
* `useHighlightGate`). Rejects with an `AbortError` if `signal` aborts first,
|
|
17
|
+
* so a superseding coordination announce can abandon the wait.
|
|
18
|
+
*/
|
|
19
|
+
export declare function whenLayoutShiftsSettled(signal?: AbortSignal): Promise<void> | null;
|
|
20
|
+
/**
|
|
21
|
+
* Reset all gate state. Test-only — there is no production reason to reopen a
|
|
22
|
+
* settled gate.
|
|
23
|
+
*/
|
|
24
|
+
export declare function resetLayoutShiftGate(): void;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Process-global, client-only gate that holds coordinated **layout-shifting**
|
|
5
|
+
* changes until the page has finished its initial hydration swaps.
|
|
6
|
+
*
|
|
7
|
+
* On hydration, anything that may shift layout once it settles — a code block
|
|
8
|
+
* swapping from its plain fallback to highlighted (and focus-collapsed) output,
|
|
9
|
+
* say — calls {@link registerLayoutShiftSource} and invokes the returned
|
|
10
|
+
* `settle` when it reaches its stable layout. `useCoordinated` consumers
|
|
11
|
+
* `await` {@link whenLayoutShiftsSettled} inside their existing `preload` slot,
|
|
12
|
+
* so the coordination barrier defers a layout-shifting commit until the gate
|
|
13
|
+
* opens. The upshot: the first transform/variant change lands as a single
|
|
14
|
+
* unified update across every block, instead of a cascade as blocks swap in at
|
|
15
|
+
* staggered idle times.
|
|
16
|
+
*
|
|
17
|
+
* Deliberately **not** a React context: registration happens in
|
|
18
|
+
* `CodeHighlighterClient` and is read deep inside `useCoordinated`, with no
|
|
19
|
+
* natural shared ancestor to thread a provider through. This mirrors the
|
|
20
|
+
* module-global design of `coordinatePreference`. It is client-only and never
|
|
21
|
+
* touched during SSR, so the shared module state cannot leak across server
|
|
22
|
+
* requests.
|
|
23
|
+
*
|
|
24
|
+
* The gate opens **once**, and it coordinates only the *initial hydration
|
|
25
|
+
* cohort* — every source present by the first settle. A source that registers
|
|
26
|
+
* after the page has already settled (e.g. a block streamed in and hydrated
|
|
27
|
+
* late, or a block mounted later on a client-side SPA navigation) registers
|
|
28
|
+
* into the already-settled gate: {@link whenLayoutShiftsSettled} resolves
|
|
29
|
+
* immediately, so it adopts the current coordinated value rather than
|
|
30
|
+
* re-closing the gate for everyone — "all sources" means "all present by the
|
|
31
|
+
* initial settle". This is by design: a client-side navigation does **not**
|
|
32
|
+
* re-coordinate a fresh cohort, and there is no production path that reopens a
|
|
33
|
+
* settled gate.
|
|
34
|
+
*
|
|
35
|
+
* The mechanism is the generic {@link createSettleGate}; this module wraps the
|
|
36
|
+
* shared {@link pageSettleGate} (the same instance generic `CoordinatedLazy`
|
|
37
|
+
* swaps register with by default) with the named functions preserved for
|
|
38
|
+
* existing callers. The layout-shift use case never needs the `expect` /
|
|
39
|
+
* `markLast` completion signals (sources are a fixed set present by the initial
|
|
40
|
+
* commit), so they are intentionally not re-exported here.
|
|
41
|
+
*/
|
|
42
|
+
import { pageSettleGate } from "./pageSettleGate.mjs";
|
|
43
|
+
const gate = pageSettleGate;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Register a source that may cause a layout shift once it settles. Call the
|
|
47
|
+
* returned function when the source has reached its stable post-hydration
|
|
48
|
+
* layout. Idempotent — calling it more than once is a no-op.
|
|
49
|
+
*/
|
|
50
|
+
export function registerLayoutShiftSource() {
|
|
51
|
+
return gate.register();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Whether the page's initial layout-shifting swaps have settled. `true` before
|
|
56
|
+
* any source registers (nothing to wait for) and once every registered source
|
|
57
|
+
* has settled.
|
|
58
|
+
*/
|
|
59
|
+
export function layoutShiftsSettled() {
|
|
60
|
+
return gate.isSettled();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Resolves once {@link layoutShiftsSettled} is `true`. Returns `null`
|
|
65
|
+
* synchronously when already settled so callers can take a fast path (mirrors
|
|
66
|
+
* `useHighlightGate`). Rejects with an `AbortError` if `signal` aborts first,
|
|
67
|
+
* so a superseding coordination announce can abandon the wait.
|
|
68
|
+
*/
|
|
69
|
+
export function whenLayoutShiftsSettled(signal) {
|
|
70
|
+
return gate.whenSettled(signal);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Reset all gate state. Test-only — there is no production reason to reopen a
|
|
75
|
+
* settled gate.
|
|
76
|
+
*/
|
|
77
|
+
export function resetLayoutShiftGate() {
|
|
78
|
+
gate.reset();
|
|
79
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The process-global default settle gate that page-level `CoordinatedLazy`
|
|
3
|
+
* swaps register with when no explicit gate is supplied. The page-wide
|
|
4
|
+
* layout-shift coordination (`layoutShiftGate`) aliases this same instance, so
|
|
5
|
+
* a demo's fallback->content swap and a code block's highlight swap both feed
|
|
6
|
+
* one "page initial swaps settled" signal that `useCoordinated` can await.
|
|
7
|
+
*
|
|
8
|
+
* Inert until a client hook registers with it; nothing registers during SSR, so
|
|
9
|
+
* the shared module state cannot leak across server requests.
|
|
10
|
+
*/
|
|
11
|
+
export declare const pageSettleGate: import("./createSettleGate.mjs").SettleGate;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createSettleGate } from "./createSettleGate.mjs";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The process-global default settle gate that page-level `CoordinatedLazy`
|
|
5
|
+
* swaps register with when no explicit gate is supplied. The page-wide
|
|
6
|
+
* layout-shift coordination (`layoutShiftGate`) aliases this same instance, so
|
|
7
|
+
* a demo's fallback->content swap and a code block's highlight swap both feed
|
|
8
|
+
* one "page initial swaps settled" signal that `useCoordinated` can await.
|
|
9
|
+
*
|
|
10
|
+
* Inert until a client hook registers with it; nothing registers during SSR, so
|
|
11
|
+
* the shared module state cannot leak across server requests.
|
|
12
|
+
*/
|
|
13
|
+
export const pageSettleGate = createSettleGate();
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Yield the current task back to the browser so it can paint and process input
|
|
3
|
+
* before the awaited continuation runs.
|
|
4
|
+
*
|
|
5
|
+
* Uses `scheduler.yield()` when available (modern Chromium) for better priority
|
|
6
|
+
* handling; falls back to `setTimeout(_, 0)`, which macrotask-defers in every
|
|
7
|
+
* browser, in Node/SSR, and in fake-timer test environments.
|
|
8
|
+
*/
|
|
9
|
+
export declare function yieldToMain(): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* Run `task` during the browser's first idle period, falling back to
|
|
12
|
+
* `setTimeout(task, 0)` where `requestIdleCallback` is unavailable (Safari,
|
|
13
|
+
* Node/SSR, fake timers). Use this for genuinely deferrable background work
|
|
14
|
+
* (e.g. stale-while-revalidate refreshes, the `idle` highlight/enhance swap)
|
|
15
|
+
* that should wait for the main thread to be free.
|
|
16
|
+
*
|
|
17
|
+
* @param options.timeout forwarded to `requestIdleCallback` so the task still
|
|
18
|
+
* runs even if the browser never goes idle.
|
|
19
|
+
* @returns a function that cancels the task if it has not run yet.
|
|
20
|
+
*/
|
|
21
|
+
export declare function requestIdle(task: () => void, options?: {
|
|
22
|
+
timeout?: number;
|
|
23
|
+
}): () => void;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Internal task-scheduling primitives shared by the coordination/render-timing
|
|
2
|
+
// code (and a few consumers that gate heavy work off the critical path). Kept
|
|
3
|
+
// here rather than in a `*Utils` barrel so it stays an internal helper, not a
|
|
4
|
+
// published API surface. Not re-exported from `index.ts`.
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Yield the current task back to the browser so it can paint and process input
|
|
8
|
+
* before the awaited continuation runs.
|
|
9
|
+
*
|
|
10
|
+
* Uses `scheduler.yield()` when available (modern Chromium) for better priority
|
|
11
|
+
* handling; falls back to `setTimeout(_, 0)`, which macrotask-defers in every
|
|
12
|
+
* browser, in Node/SSR, and in fake-timer test environments.
|
|
13
|
+
*/
|
|
14
|
+
export function yieldToMain() {
|
|
15
|
+
const {
|
|
16
|
+
scheduler
|
|
17
|
+
} = globalThis;
|
|
18
|
+
if (typeof scheduler?.yield === 'function') {
|
|
19
|
+
return scheduler.yield();
|
|
20
|
+
}
|
|
21
|
+
return new Promise(resolve => {
|
|
22
|
+
setTimeout(resolve, 0);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Run `task` during the browser's first idle period, falling back to
|
|
28
|
+
* `setTimeout(task, 0)` where `requestIdleCallback` is unavailable (Safari,
|
|
29
|
+
* Node/SSR, fake timers). Use this for genuinely deferrable background work
|
|
30
|
+
* (e.g. stale-while-revalidate refreshes, the `idle` highlight/enhance swap)
|
|
31
|
+
* that should wait for the main thread to be free.
|
|
32
|
+
*
|
|
33
|
+
* @param options.timeout forwarded to `requestIdleCallback` so the task still
|
|
34
|
+
* runs even if the browser never goes idle.
|
|
35
|
+
* @returns a function that cancels the task if it has not run yet.
|
|
36
|
+
*/
|
|
37
|
+
export function requestIdle(task, options) {
|
|
38
|
+
const idleGlobals = globalThis;
|
|
39
|
+
if (idleGlobals.requestIdleCallback) {
|
|
40
|
+
const handle = idleGlobals.requestIdleCallback(task, options);
|
|
41
|
+
return () => idleGlobals.cancelIdleCallback?.(handle);
|
|
42
|
+
}
|
|
43
|
+
const handle = setTimeout(task, 0);
|
|
44
|
+
return () => clearTimeout(handle);
|
|
45
|
+
}
|