@mui/internal-docs-infra 0.12.1-canary.2 → 0.12.1-canary.21

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 (221) hide show
  1. package/ChunkProvider/PreloadProvider.mjs +1 -2
  2. package/ChunkProvider/usePreload.d.mts +1 -1
  3. package/ChunkProvider/usePreload.mjs +0 -1
  4. package/CodeControllerContext/CodeControllerContext.d.mts +45 -10
  5. package/CodeControllerContext/CodeControllerContext.mjs +15 -1
  6. package/CodeHighlighter/CodeHighlighterClient.d.mts +3 -2
  7. package/CodeHighlighter/CodeHighlighterClient.mjs +113 -18
  8. package/CodeHighlighter/CodeHighlighterContext.d.mts +9 -3
  9. package/CodeHighlighter/buildStringFallback.d.mts +1 -1
  10. package/CodeHighlighter/codeToFallbackProps.d.mts +1 -1
  11. package/CodeHighlighter/createClientProps.mjs +3 -0
  12. package/CodeHighlighter/fallbackCompression.d.mts +1 -1
  13. package/CodeHighlighter/parseControlledCode.d.mts +13 -4
  14. package/CodeHighlighter/parseControlledCode.mjs +41 -49
  15. package/CodeHighlighter/types.d.mts +21 -0
  16. package/CodeHighlighter/useGrammarsReady.mjs +44 -9
  17. package/CodeProvider/CodeProvider.d.mts +1 -1
  18. package/CodeProvider/CodeProviderLazy.d.mts +1 -1
  19. package/CodeProvider/createParseSourceWorkerClient.d.mts +6 -0
  20. package/CodeProvider/createParseSourceWorkerClient.mjs +83 -15
  21. package/CodeProvider/useCodeProviderValue.mjs +50 -4
  22. package/abstractCreateDemo/abstractCreateDemo.d.mts +15 -1
  23. package/abstractCreateDemo/abstractCreateDemo.mjs +8 -0
  24. package/abstractCreateDemoClient/abstractCreateDemoClient.mjs +4 -0
  25. package/abstractCreateTypes/abstractCreateTypes.d.mts +12 -1
  26. package/abstractCreateTypes/abstractCreateTypes.mjs +4 -0
  27. package/abstractCreateTypes/typesToJsx.d.mts +8 -0
  28. package/abstractCreateTypes/typesToJsx.mjs +2 -1
  29. package/cli/loadNextConfig.d.mts +9 -0
  30. package/cli/loadNextConfig.mjs +11 -2
  31. package/cli/runValidate.mjs +15 -7
  32. package/cli/validateWorker.d.mts +1 -0
  33. package/cli/validateWorker.mjs +2 -1
  34. package/createDemoData/createDemoData.d.mts +1 -1
  35. package/package.json +34 -5
  36. package/pipeline/cacheUtils/constants.d.mts +5 -0
  37. package/pipeline/cacheUtils/constants.mjs +5 -0
  38. package/pipeline/cacheUtils/hashCacheContent.d.mts +5 -0
  39. package/pipeline/cacheUtils/hashCacheContent.mjs +9 -0
  40. package/pipeline/cacheUtils/index.d.mts +9 -0
  41. package/pipeline/cacheUtils/index.mjs +7 -0
  42. package/pipeline/cacheUtils/loadFileCache.d.mts +13 -0
  43. package/pipeline/cacheUtils/loadFileCache.mjs +20 -0
  44. package/pipeline/cacheUtils/loadFileCacheEntry.d.mts +13 -0
  45. package/pipeline/cacheUtils/loadFileCacheEntry.mjs +47 -0
  46. package/pipeline/cacheUtils/resolveCachePath.d.mts +16 -0
  47. package/pipeline/cacheUtils/resolveCachePath.mjs +24 -0
  48. package/pipeline/cacheUtils/saveFileCache.d.mts +17 -0
  49. package/pipeline/cacheUtils/saveFileCache.mjs +54 -0
  50. package/pipeline/cacheUtils/types.d.mts +23 -0
  51. package/pipeline/cacheUtils/types.mjs +1 -0
  52. package/pipeline/cacheUtils/withFileCache.d.mts +40 -0
  53. package/pipeline/cacheUtils/withFileCache.mjs +81 -0
  54. package/pipeline/hastUtils/hastUtils.d.mts +1 -1
  55. package/pipeline/hastUtils/hastUtils.mjs +0 -1
  56. package/pipeline/loadIsomorphicCodeSource/loadIsomorphicCodeSource.d.mts +1 -1
  57. package/pipeline/loadIsomorphicCodeSource/loadIsomorphicCodeSource.mjs +1 -1
  58. package/pipeline/loadIsomorphicCodeVariant/applyCodeTransform.mjs +0 -1
  59. package/pipeline/loadIsomorphicCodeVariant/diffHast.d.mts +1 -1
  60. package/pipeline/loadIsomorphicCodeVariant/hasAllCodeVariants.d.mts +1 -1
  61. package/pipeline/loadIsomorphicCodeVariant/maybeCodeInitialData.d.mts +1 -1
  62. package/pipeline/loadPrecomputedSitemap/loadPrecomputedSitemap.d.mts +6 -0
  63. package/pipeline/loadPrecomputedSitemap/loadPrecomputedSitemap.mjs +2 -1
  64. package/pipeline/loadPrecomputedTypes/loadPrecomputedTypes.d.mts +6 -0
  65. package/pipeline/loadPrecomputedTypes/loadPrecomputedTypes.mjs +5 -1
  66. package/pipeline/loadServerCodeMeta/resolveModulePathWithFs.d.mts +1 -1
  67. package/pipeline/loadServerCodeMeta/resolveModulePathWithFs.mjs +0 -1
  68. package/pipeline/loadServerPageIndex/enrichPageIndex.d.mts +15 -0
  69. package/pipeline/loadServerPageIndex/enrichPageIndex.mjs +50 -0
  70. package/pipeline/loadServerPageIndex/extractPrefixAndTitle.d.mts +19 -0
  71. package/pipeline/loadServerPageIndex/extractPrefixAndTitle.mjs +80 -0
  72. package/pipeline/loadServerPageIndex/index.d.mts +5 -2
  73. package/pipeline/loadServerPageIndex/index.mjs +4 -1
  74. package/pipeline/loadServerPageIndex/loadServerPageIndex.d.mts +13 -22
  75. package/pipeline/loadServerPageIndex/loadServerPageIndex.mjs +32 -124
  76. package/pipeline/loadServerPageIndex/resolvePageIndexCacheKey.d.mts +13 -0
  77. package/pipeline/loadServerPageIndex/resolvePageIndexCacheKey.mjs +23 -0
  78. package/pipeline/loadServerTypes/highlightTypes.d.mts +3 -3
  79. package/pipeline/loadServerTypes/highlightTypesMeta.d.mts +4 -4
  80. package/pipeline/loadServerTypes/loadServerTypes.d.mts +2 -2
  81. package/pipeline/loadServerTypes/loadServerTypes.mjs +67 -7
  82. package/pipeline/loadServerTypesMeta/createOptimizedProgram.d.mts +2 -1
  83. package/pipeline/loadServerTypesMeta/formatClass.d.mts +2 -2
  84. package/pipeline/loadServerTypesMeta/formatComponent.d.mts +2 -2
  85. package/pipeline/loadServerTypesMeta/formatFunction.d.mts +2 -2
  86. package/pipeline/loadServerTypesMeta/formatHook.d.mts +2 -2
  87. package/pipeline/loadServerTypesMeta/formatRaw.d.mts +2 -2
  88. package/pipeline/loadServerTypesMeta/formatType.d.mts +1 -1
  89. package/pipeline/loadServerTypesMeta/loadServerTypesMeta.d.mts +7 -7
  90. package/pipeline/loadServerTypesMeta/loadServerTypesMeta.mjs +1 -1
  91. package/pipeline/loadServerTypesMeta/processTypes.d.mts +2 -2
  92. package/pipeline/loadServerTypesMeta/worker.d.mts +1 -1
  93. package/pipeline/loadServerTypesText/loadServerTypesText.d.mts +16 -2
  94. package/pipeline/loadServerTypesText/loadServerTypesText.mjs +30 -8
  95. package/pipeline/loadServerTypesText/normalizeTypesSourceDataForCache.d.mts +2 -0
  96. package/pipeline/loadServerTypesText/normalizeTypesSourceDataForCache.mjs +144 -0
  97. package/pipeline/loadServerTypesText/resolveTypesCacheKey.d.mts +19 -0
  98. package/pipeline/loadServerTypesText/resolveTypesCacheKey.mjs +29 -0
  99. package/pipeline/loaderUtils/parseImportsAndComments.d.mts +5 -3
  100. package/pipeline/loaderUtils/parseImportsAndComments.mjs +284 -40
  101. package/pipeline/parseCreateFactoryCall/parseCreateFactoryCall.d.mts +2 -2
  102. package/pipeline/parseCreateFactoryCall/parseCreateFactoryCall.mjs +2 -3
  103. package/pipeline/parseSource/detectFileTypes.d.mts +16 -0
  104. package/pipeline/parseSource/detectFileTypes.mjs +44 -0
  105. package/pipeline/syncPageIndex/mergeMetadataMarkdown.d.mts +25 -1
  106. package/pipeline/syncPageIndex/mergeMetadataMarkdown.mjs +79 -49
  107. package/pipeline/syncPageIndex/metadataToMarkdown.d.mts +15 -1
  108. package/pipeline/syncPageIndex/metadataToMarkdown.mjs +32 -10
  109. package/pipeline/syncPageIndex/syncPageIndex.d.mts +12 -0
  110. package/pipeline/syncPageIndex/syncPageIndex.mjs +154 -40
  111. package/pipeline/syncTypes/generateTypesMarkdown.d.mts +2 -2
  112. package/pipeline/syncTypes/syncTypes.d.mts +7 -0
  113. package/pipeline/syncTypes/syncTypes.mjs +31 -1
  114. package/pipeline/transformHtmlCodeBlock/transformHtmlCodeBlock.mjs +1 -1
  115. package/pipeline/transformMarkdownCode/transformMarkdownCode.mjs +25 -15
  116. package/pipeline/transformMarkdownMetadata/transformMarkdownMetadata.mjs +3 -0
  117. package/pipeline/transformMarkdownMetadata/types.d.mts +8 -1
  118. package/useCode/EditableEngine.d.mts +1 -1
  119. package/useCode/Pre.d.mts +9 -2
  120. package/useCode/Pre.mjs +4 -3
  121. package/useCode/TransformEngine.d.mts +1 -1
  122. package/useCode/useCode.d.mts +17 -1
  123. package/useCode/useCode.mjs +22 -1
  124. package/useCode/useCopyFunctionality.d.mts +2 -2
  125. package/useCode/useEditable.browser.mjs +0 -1
  126. package/useCode/useFileNavigation.d.mts +3 -0
  127. package/useCode/useFileNavigation.mjs +3 -1
  128. package/useCode/useSourceEditing.mjs +45 -10
  129. package/useCode/useSourceEnhancing.mjs +41 -9
  130. package/useCode/useTransformManagement.d.mts +2 -2
  131. package/useCode/useTransformManagement.mjs +19 -3
  132. package/useCode/useUIState.d.mts +4 -0
  133. package/useCode/useUIState.mjs +8 -1
  134. package/useCode/useVariantSelection.d.mts +1 -1
  135. package/useCoordinated/useCoordinated.d.mts +1 -1
  136. package/useCoordinated/useCoordinatedLocalStorage.d.mts +1 -1
  137. package/useCoordinated/useCoordinatedLocalStorage.mjs +0 -1
  138. package/useCoordinated/useCoordinatedPreference.d.mts +1 -1
  139. package/useCoordinated/useCoordinatedPreference.mjs +0 -1
  140. package/useCrossTabState/index.d.mts +2 -0
  141. package/useCrossTabState/index.mjs +2 -0
  142. package/useCrossTabState/useCrossTabMirror.d.mts +26 -0
  143. package/useCrossTabState/useCrossTabMirror.mjs +108 -0
  144. package/useCrossTabState/useCrossTabState.d.mts +21 -0
  145. package/useCrossTabState/useCrossTabState.mjs +31 -0
  146. package/useDemo/exportVariant.mjs +2 -4
  147. package/useDemo/exportVariantAsCra.d.mts +1 -1
  148. package/useDemo/exportVariantAsCra.mjs +0 -1
  149. package/useDemo/useDemo.d.mts +4 -1
  150. package/useDemo/useDemo.mjs +5 -0
  151. package/useDemoController/BuildEngine.d.mts +2 -0
  152. package/useDemoController/BuildEngine.mjs +10 -0
  153. package/useDemoController/DemoRunner.d.mts +34 -0
  154. package/useDemoController/DemoRunner.mjs +83 -0
  155. package/useDemoController/ErrorBoundary.d.mts +34 -0
  156. package/useDemoController/ErrorBoundary.mjs +49 -0
  157. package/useDemoController/Runner.d.mts +44 -0
  158. package/useDemoController/Runner.mjs +71 -0
  159. package/useDemoController/absolutizeImports.d.mts +13 -0
  160. package/useDemoController/absolutizeImports.mjs +73 -0
  161. package/useDemoController/buildScope.d.mts +48 -0
  162. package/useDemoController/buildScope.mjs +270 -0
  163. package/useDemoController/collectSources.d.mts +67 -0
  164. package/useDemoController/collectSources.mjs +92 -0
  165. package/useDemoController/compileCssModule.d.mts +64 -0
  166. package/useDemoController/compileCssModule.mjs +40 -0
  167. package/useDemoController/compileCssWithPostcss.d.mts +17 -0
  168. package/useDemoController/compileCssWithPostcss.mjs +89 -0
  169. package/useDemoController/compileModule.d.mts +14 -0
  170. package/useDemoController/compileModule.mjs +17 -0
  171. package/useDemoController/constants.d.mts +13 -0
  172. package/useDemoController/constants.mjs +13 -0
  173. package/useDemoController/createRequire.d.mts +10 -0
  174. package/useDemoController/createRequire.mjs +17 -0
  175. package/useDemoController/createTranspileWorkerClient.d.mts +27 -0
  176. package/useDemoController/createTranspileWorkerClient.mjs +139 -0
  177. package/useDemoController/cssModules.d.mts +47 -0
  178. package/useDemoController/currentBrowserTarget.d.mts +16 -0
  179. package/useDemoController/currentBrowserTarget.mjs +36 -0
  180. package/useDemoController/evalCode.d.mts +12 -0
  181. package/useDemoController/evalCode.mjs +35 -0
  182. package/useDemoController/generateCssModuleSource.d.mts +11 -0
  183. package/useDemoController/generateCssModuleSource.mjs +55 -0
  184. package/useDemoController/generateElement.d.mts +21 -0
  185. package/useDemoController/generateElement.mjs +26 -0
  186. package/useDemoController/hashString.d.mts +11 -0
  187. package/useDemoController/hashString.mjs +20 -0
  188. package/useDemoController/importCode.d.mts +11 -0
  189. package/useDemoController/importCode.mjs +15 -0
  190. package/useDemoController/index.d.mts +1 -0
  191. package/useDemoController/index.mjs +1 -0
  192. package/useDemoController/instantiateElement.d.mts +24 -0
  193. package/useDemoController/instantiateElement.mjs +57 -0
  194. package/useDemoController/instantiateModule.d.mts +17 -0
  195. package/useDemoController/instantiateModule.mjs +24 -0
  196. package/useDemoController/resolveCssImports.d.mts +27 -0
  197. package/useDemoController/resolveCssImports.mjs +79 -0
  198. package/useDemoController/transformCode.d.mts +14 -0
  199. package/useDemoController/transformCode.mjs +42 -0
  200. package/useDemoController/transpileClientSingleton.d.mts +10 -0
  201. package/useDemoController/transpileClientSingleton.mjs +83 -0
  202. package/useDemoController/transpileSource.d.mts +29 -0
  203. package/useDemoController/transpileSource.mjs +36 -0
  204. package/useDemoController/transpileWorker.d.mts +14 -0
  205. package/useDemoController/transpileWorker.mjs +41 -0
  206. package/useDemoController/types.d.mts +30 -0
  207. package/useDemoController/types.mjs +1 -0
  208. package/useDemoController/useDemoController.d.mts +54 -0
  209. package/useDemoController/useDemoController.mjs +186 -0
  210. package/useDemoController/useRunner.d.mts +53 -0
  211. package/useDemoController/useRunner.mjs +118 -0
  212. package/useDemoController/useVariantBuilds.d.mts +31 -0
  213. package/useDemoController/useVariantBuilds.mjs +188 -0
  214. package/useSearch/types.d.mts +1 -1
  215. package/useType/TypesDataProvider.d.mts +1 -1
  216. package/useType/TypesDataProvider.mjs +1 -2
  217. package/useType/useType.d.mts +1 -1
  218. package/useType/useTypeProp.d.mts +1 -1
  219. package/withDocsInfra/withDeploymentConfig.mjs +57 -0
  220. package/withDocsInfra/withDocsInfra.d.mts +14 -0
  221. package/withDocsInfra/withDocsInfra.mjs +25 -11
@@ -0,0 +1,186 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import { useCodeExternals } from '@mui/internal-docs-infra/CodeExternalsContext';
5
+ import { getTranspile } from "./transpileClientSingleton.mjs";
6
+ import { useVariantBuilds } from "./useVariantBuilds.mjs";
7
+
8
+ // The live runtime is loaded LAZILY in two chunks, warmed when a demo activates for
9
+ // editing (via `onActivate` below) or, failing that, on the first build:
10
+ // - `BuildEngine` — the build half (`buildScope`) + render half (`DemoRunner` + the
11
+ // react-runner reimplementation), bundled together (see `BuildEngine.ts`).
12
+ // - `compileCss` — the PostCSS toolchain, only needed for demos with CSS files.
13
+ // Keeping them out of the eager `useDemoController` chunk means a reader who never edits
14
+ // never fetches them. `DemoRunner` is lazy, so the host must render the returned
15
+ // `components` under a `Suspense` boundary — `CodeHighlighterClient` does, falling back to
16
+ // the build-time render while the chunk resolves (see the `components` return doc).
17
+
18
+ let buildEngineImport = null;
19
+ function preloadBuildEngine() {
20
+ if (!buildEngineImport) {
21
+ buildEngineImport = import("./BuildEngine.mjs");
22
+ }
23
+ return buildEngineImport;
24
+ }
25
+ let compileCssImport = null;
26
+ function preloadCompileCss() {
27
+ if (!compileCssImport) {
28
+ compileCssImport = import(/* webpackChunkName: "compileCss" */"./compileCssWithPostcss.mjs");
29
+ }
30
+ }
31
+ const DemoRunner = /*#__PURE__*/React.lazy(() => preloadBuildEngine().then(module => ({
32
+ default: module.DemoRunner
33
+ })));
34
+ /**
35
+ * Drives the live previews for a demo controller. Owns the controlled `code` state,
36
+ * transpiles each variant OFF the main thread (via a shared Web Worker, with a
37
+ * main-thread fallback) and renders the ready ones through {@link DemoRunner}, and
38
+ * collects the per-variant `errors` — returning exactly the `{ code, setCode,
39
+ * components, errors }` shape a `CodeControllerContext` provider expects, so a host
40
+ * wires it up in one line and reads results back through `useDemo`.
41
+ *
42
+ * Because transpilation is async, a variant joins `components` only once its build
43
+ * resolves; editing never blocks the UI thread, and an in-flight variant shows its
44
+ * fallback rather than a flash of empty preview. Keeping `code` unset until the
45
+ * first `setCode` lets the host serve its build-time/server render first.
46
+ *
47
+ * By default the controlled code is also mirrored across same-origin tabs of the same
48
+ * page (via the `crossTabSync` option), so a reader editing a demo in a Chrome split
49
+ * view sees it update in both panes.
50
+ */
51
+ export function useDemoController() {
52
+ const [code, setControlledCode] = React.useState(null);
53
+ // Build errors (transpile/CSS failures) and render errors (the entry throwing) live
54
+ // in SEPARATE maps so they never clobber each other: a build error is owned by
55
+ // `useVariantBuilds` (set on failure, cleared on the next good build); a render
56
+ // error is owned by the live `DemoRunner` (set while it throws, cleared when it
57
+ // renders cleanly). A CSS-only fix doesn't re-render the entry, so the build channel
58
+ // must clear itself rather than wait for the runner. They are merged below.
59
+ const [buildErrors, setBuildErrors] = React.useState({});
60
+ const [renderErrors, setRenderErrors] = React.useState({});
61
+ const [transpile, setTranspile] = React.useState(null);
62
+ const externalsContext = useCodeExternals();
63
+ const externals = React.useMemo(() => externalsContext?.externals ?? {
64
+ react: React
65
+ }, [externalsContext]);
66
+
67
+ // Identity-stable reporters; each dedups a no-op so it doesn't churn state. The
68
+ // `?? null` treats "never set" (undefined) and "cleared" (null) as equal, so
69
+ // clearing a variant that never errored is a no-op.
70
+ const reportBuildError = React.useCallback((variant, message) => {
71
+ setBuildErrors(previous => (previous[variant] ?? null) === message ? previous : {
72
+ ...previous,
73
+ [variant]: message
74
+ });
75
+ }, []);
76
+ const reportRenderError = React.useCallback((variant, message) => {
77
+ setRenderErrors(previous => (previous[variant] ?? null) === message ? previous : {
78
+ ...previous,
79
+ [variant]: message
80
+ });
81
+ }, []);
82
+
83
+ // Reset (the toolbar button clears `code` to `undefined`) must also drop any stale
84
+ // build/render error, so a prior syntax error's overlay doesn't linger over the
85
+ // restored original — nothing rebuilds after a reset to clear it otherwise. Do it in
86
+ // the setter that performs the reset rather than reacting to the `code` change in an
87
+ // effect; the length guards keep each clear a no-op once its map is empty.
88
+ const setCode = React.useCallback(action => {
89
+ setControlledCode(action);
90
+ // Drop stale errors alongside a reset (`code` cleared to `null`).
91
+ if (!action) {
92
+ setBuildErrors({});
93
+ setRenderErrors({});
94
+ }
95
+ }, [setControlledCode]);
96
+
97
+ // Resolve the page-shared transpile (worker, or main-thread fallback) into state once
98
+ // there's code to build — a local first edit, or a cross-tab edit that arrives without
99
+ // this tab engaging its own editor. `onActivate` below has usually already spun the
100
+ // worker up (so `getTranspile()` here resolves from cache), but this covers the
101
+ // passive/synced tab that never activates. Client-only, so the worker is never built
102
+ // on the server and the controller renders with no `components` until the client takes
103
+ // over.
104
+ React.useEffect(() => {
105
+ if (!code || transpile) {
106
+ return undefined;
107
+ }
108
+ let active = true;
109
+ getTranspile().then(resolved => {
110
+ if (active) {
111
+ setTranspile(() => resolved);
112
+ }
113
+ });
114
+ return () => {
115
+ active = false;
116
+ };
117
+ }, [code, transpile]);
118
+
119
+ // Warm the lazy engine modules the moment editing ACTIVATES (before the first
120
+ // keystroke), all kicked off here so they download in PARALLEL rather than
121
+ // waterfalling one inside another. The host passes which file kinds the demo spans, so
122
+ // a CSS-free demo never fetches the CSS toolchain and a reader who never activates
123
+ // fetches nothing. (If a host doesn't call this, each still loads on the first build,
124
+ // just a beat later.)
125
+ const onActivate = React.useCallback(deps => {
126
+ // The build + render engine — needed for any demo.
127
+ preloadBuildEngine();
128
+ // The transpile runs in a Web Worker; `getTranspile()` spins it up, loading sucrase
129
+ // OFF the main thread. (A direct `import('./transpileSource')` here would instead
130
+ // pull sucrase INTO the main bundle, defeating the worker.)
131
+ if (deps.js) {
132
+ getTranspile();
133
+ }
134
+ // The PostCSS toolchain — only for demos with CSS.
135
+ if (deps.css) {
136
+ preloadCompileCss();
137
+ }
138
+ }, []);
139
+ const built = useVariantBuilds(code, transpile, externals, reportBuildError);
140
+ const components = React.useMemo(() => {
141
+ if (!code) {
142
+ return undefined;
143
+ }
144
+ const result = {};
145
+ for (const variant of Object.keys(code)) {
146
+ const variantBuild = built[variant];
147
+ if (!variantBuild) {
148
+ continue; // first build still in flight — no component yet
149
+ }
150
+ // Render the lazy `DemoRunner` WITHOUT a per-variant Suspense here: the boundary
151
+ // belongs to the HOST, which can fall back to the BUILD-TIME render while the lazy
152
+ // chunk resolves. A `<Suspense fallback={null}>` here paints an empty frame on a
153
+ // NEWLY-MOUNTED boundary — the first edit after `reset()`, where `built` was cleared
154
+ // so no prior live frame exists for `startTransition` to hold — flashing blank.
155
+ // Bubbling to the host's boundary shows the original instead.
156
+ result[variant] = /*#__PURE__*/React.createElement(DemoRunner, {
157
+ key: variant,
158
+ runnerCode: variantBuild.runnerCode,
159
+ scope: variantBuild.scope,
160
+ css: variantBuild.css,
161
+ onError: message => reportRenderError(variant, message)
162
+ });
163
+ }
164
+ return Object.keys(result).length > 0 ? result : undefined;
165
+ }, [code, built, reportRenderError]);
166
+
167
+ // Merge the two channels: a build failure takes precedence (the preview is stale
168
+ // until it builds), otherwise the render error, else `null`.
169
+ const errors = React.useMemo(() => {
170
+ if (!code) {
171
+ return {};
172
+ }
173
+ const merged = {};
174
+ for (const variant of new Set([...Object.keys(buildErrors), ...Object.keys(renderErrors)])) {
175
+ merged[variant] = buildErrors[variant] || renderErrors[variant] || null;
176
+ }
177
+ return merged;
178
+ }, [code, buildErrors, renderErrors]);
179
+ return {
180
+ code,
181
+ setCode,
182
+ components,
183
+ errors,
184
+ onActivate
185
+ };
186
+ }
@@ -0,0 +1,53 @@
1
+ import * as React from 'react';
2
+ import type { Scope } from "./types.mjs";
3
+ export interface UseRunnerOptions {
4
+ /** Already-transpiled entry code to evaluate + render (see {@link Runner}). */
5
+ transpiledCode: string;
6
+ /** Identifiers (and an `import` registry) exposed to the evaluated entry. */
7
+ scope?: Scope;
8
+ /**
9
+ * When `true`, the preview clears on error instead of keeping the last
10
+ * successfully-rendered element. Defaults to `false`.
11
+ */
12
+ disableCache?: boolean;
13
+ /**
14
+ * Shown when the entry throws on a render BEFORE any successful one (so there is no
15
+ * last-good element to keep) — typically the host's build-time render, so a broken first
16
+ * edit shows the original instead of blanking. Ignored once a render has succeeded (the
17
+ * last-good element is kept instead) and when `disableCache` is set.
18
+ */
19
+ fallback?: React.ReactNode;
20
+ }
21
+ export interface UseRunnerResult {
22
+ /** The node to render — a `Runner`, the cached last-good one, the `fallback`, or `null`. */
23
+ element: React.ReactNode;
24
+ /** The current error message, or `null` when the code rendered cleanly. */
25
+ error: string | null;
26
+ }
27
+ /**
28
+ * Evaluates already-transpiled entry code and returns the element to render plus
29
+ * the current error message. Transpilation happens upstream (off the main thread);
30
+ * this hook owns only the synchronous evaluate + render + error bookkeeping.
31
+ *
32
+ * Errors are reported asynchronously (after the runner renders), so the hook keeps
33
+ * the last successfully-rendered element on screen while `error` is set — giving a
34
+ * stable preview as the source is edited into and out of broken states. The error
35
+ * is kept across edits and cleared only once a render succeeds, so a continuously-
36
+ * broken edit never flashes it off and back on. Pass `disableCache` to clear the
37
+ * preview on error instead.
38
+ *
39
+ * The live element and the inputs it was built from live in a SINGLE state object,
40
+ * not two `useState` hooks. The "adjust state during render" pattern issues a
41
+ * render-phase update; with the inputs and element split across two hooks, React
42
+ * could commit the input update while dropping the element one (e.g. when a parent
43
+ * re-render rebases the in-progress render), stranding a stale element that the
44
+ * adjust never rebuilt because the inputs already matched. Keeping them together
45
+ * makes the update atomic: if it is dropped, the inputs revert with it and the
46
+ * adjust simply re-fires on the next render.
47
+ */
48
+ export declare function useRunner({
49
+ transpiledCode,
50
+ scope,
51
+ disableCache,
52
+ fallback
53
+ }: UseRunnerOptions): UseRunnerResult;
@@ -0,0 +1,118 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import { Runner } from "./Runner.mjs";
5
+ /**
6
+ * Evaluates already-transpiled entry code and returns the element to render plus
7
+ * the current error message. Transpilation happens upstream (off the main thread);
8
+ * this hook owns only the synchronous evaluate + render + error bookkeeping.
9
+ *
10
+ * Errors are reported asynchronously (after the runner renders), so the hook keeps
11
+ * the last successfully-rendered element on screen while `error` is set — giving a
12
+ * stable preview as the source is edited into and out of broken states. The error
13
+ * is kept across edits and cleared only once a render succeeds, so a continuously-
14
+ * broken edit never flashes it off and back on. Pass `disableCache` to clear the
15
+ * preview on error instead.
16
+ *
17
+ * The live element and the inputs it was built from live in a SINGLE state object,
18
+ * not two `useState` hooks. The "adjust state during render" pattern issues a
19
+ * render-phase update; with the inputs and element split across two hooks, React
20
+ * could commit the input update while dropping the element one (e.g. when a parent
21
+ * re-render rebases the in-progress render), stranding a stale element that the
22
+ * adjust never rebuilt because the inputs already matched. Keeping them together
23
+ * makes the update atomic: if it is dropped, the inputs revert with it and the
24
+ * adjust simply re-fires on the next render.
25
+ */
26
+ export function useRunner({
27
+ transpiledCode,
28
+ scope,
29
+ disableCache,
30
+ fallback
31
+ }) {
32
+ const lastGoodElementRef = React.useRef(null);
33
+ // When an error swaps the preview back to the cached last-good element, that
34
+ // element re-renders cleanly and fires `onRendered` with no error. This flag
35
+ // tells that one "success" NOT to clear the error the swap just set.
36
+ const suppressErrorClearRef = React.useRef(false);
37
+ // `onRendered` is baked into the `Runner` element, which is only rebuilt when the
38
+ // code/scope/disableCache inputs change — so a `fallback` that changes on its own
39
+ // (e.g. the host's build-time render updating) wouldn't reach the closure. Read it
40
+ // through a ref kept current in an effect so the latest `fallback` is always used.
41
+ const fallbackRef = React.useRef(fallback);
42
+ React.useEffect(() => {
43
+ fallbackRef.current = fallback;
44
+ });
45
+ const [state, setState] = React.useState(() => ({
46
+ element: createRunnerElement(transpiledCode, scope),
47
+ error: null,
48
+ transpiledCode,
49
+ scope,
50
+ disableCache
51
+ }));
52
+
53
+ // Build a fresh live element whenever the inputs change, using React's supported
54
+ // "adjust state during render" pattern so an edit takes effect immediately. The
55
+ // prior error is KEPT here (not reset to null) so a continuously-broken edit
56
+ // doesn't flash the error off and back on; it's cleared only once a render
57
+ // actually succeeds (see `onRendered`).
58
+ if (state.transpiledCode !== transpiledCode || state.scope !== scope || state.disableCache !== disableCache) {
59
+ const element = createRunnerElement(transpiledCode, scope);
60
+ setState(previous => ({
61
+ element,
62
+ error: previous.error,
63
+ transpiledCode,
64
+ scope,
65
+ disableCache
66
+ }));
67
+ }
68
+ return {
69
+ element: state.element,
70
+ error: state.error
71
+ };
72
+
73
+ // Declared after the state above so it can reference `setState`; hoisting lets
74
+ // the `useState` initializer call it. The refs are only ever touched inside the
75
+ // async `onRendered` callback, never during render.
76
+ function createRunnerElement(nextCode, nextScope) {
77
+ const element = /*#__PURE__*/React.createElement(Runner, {
78
+ transpiledCode: nextCode,
79
+ scope: nextScope,
80
+ onRendered(error) {
81
+ if (error) {
82
+ // Keeping a cached element means it re-renders cleanly next and fires a
83
+ // no-error `onRendered`; mark that one success to be ignored so it
84
+ // doesn't wipe this error. Only when there actually IS a cached element
85
+ // to swap to — with `disableCache`, or before the first successful
86
+ // render, the preview falls back to `fallback`/`null` and no such
87
+ // re-render happens, so there is nothing to suppress (and suppressing
88
+ // would eat the real next success).
89
+ if (!disableCache && lastGoodElementRef.current !== null) {
90
+ suppressErrorClearRef.current = true;
91
+ }
92
+ setState(previous => ({
93
+ ...previous,
94
+ // Before any successful render there is no last-good element to keep, so show the
95
+ // host's build-time `fallback` (the original) rather than blanking. `disableCache`
96
+ // opts out and clears to `null`.
97
+ element: disableCache ? null : lastGoodElementRef.current ?? fallbackRef.current ?? null,
98
+ error: error.toString()
99
+ }));
100
+ } else if (suppressErrorClearRef.current) {
101
+ // The cached last-good element re-rendering after an error swap — keep
102
+ // the error, just remember the element.
103
+ suppressErrorClearRef.current = false;
104
+ lastGoodElementRef.current = element;
105
+ } else {
106
+ // A genuine clean render of the current code — cache it and clear any
107
+ // prior error.
108
+ lastGoodElementRef.current = element;
109
+ setState(previous => previous.error === null ? previous : {
110
+ ...previous,
111
+ error: null
112
+ });
113
+ }
114
+ }
115
+ });
116
+ return element;
117
+ }
118
+ }
@@ -0,0 +1,31 @@
1
+ import type { ControlledCode } from '@mui/internal-docs-infra/CodeHighlighter/types';
2
+ import type { Transpile } from "./transpileSource.mjs";
3
+ import type { Scope } from "./types.mjs";
4
+ /** A variant's transpiled, ready-to-render build. */
5
+ export interface VariantBuild {
6
+ /** The transpiled entry code for the runner to evaluate. */
7
+ runnerCode: string;
8
+ /** The built module registry the entry evaluates against. */
9
+ scope: Scope;
10
+ /** Compiled stylesheet text for the variant. */
11
+ css: string;
12
+ }
13
+ /**
14
+ * Builds each variant's scope OFF the main thread and exposes the ready ones. A
15
+ * variant appears in the returned map only once its (worker) transpile resolves —
16
+ * so a host can leave an in-flight variant showing its fallback rather than a
17
+ * loading state. On edit, a variant keeps its previous build until the new one
18
+ * resolves (and on a transpile error too, reported via `report`), so the preview
19
+ * never flashes.
20
+ *
21
+ * A variant's FIRST build is never cancelled. On the first edit the controller is
22
+ * seeded with the ORIGINAL source and the real edit follows; if that edit arrives
23
+ * before the seed's build settles, it is DEFERRED (not aborted) so the baseline
24
+ * always builds and renders before the edit lands — giving a broken edit a good
25
+ * preview to fall back to. Later edits abort the in-flight build as usual.
26
+ *
27
+ * Per-variant bookkeeping (request ids, abort controllers, last-built input, the
28
+ * first-build-done set, and the deferred edit) lives in refs since it never
29
+ * affects render; only the resolved `built` map is state.
30
+ */
31
+ export declare function useVariantBuilds(code: ControlledCode | null | undefined, transpile: Transpile | null, externals: Record<string, unknown>, report: (variant: string, message: string | null) => void): Record<string, VariantBuild>;
@@ -0,0 +1,188 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+
5
+ // The build half of the runtime (`buildScope` + its scope-assembly and eval machinery)
6
+ // is the bulk of this engine, but it's only needed once a demo is actually EDITED —
7
+ // before that the host shows the build-time render. So it's loaded LAZILY on the first
8
+ // build, from the shared `BuildEngine` chunk it shares with the render half (`DemoRunner`,
9
+ // loaded by `useDemoController`) — one chunk for the whole engine. The promise is
10
+ // module-level, so the chunk is fetched once and every later build reuses it; readers who
11
+ // never edit never fetch it.
12
+
13
+ let buildEnginePromise = null;
14
+ function loadBuildScope() {
15
+ if (!buildEnginePromise) {
16
+ buildEnginePromise = import("./BuildEngine.mjs").then(module => module.buildScope);
17
+ }
18
+ return buildEnginePromise;
19
+ }
20
+
21
+ /** A variant's transpiled, ready-to-render build. */
22
+
23
+ /**
24
+ * Builds each variant's scope OFF the main thread and exposes the ready ones. A
25
+ * variant appears in the returned map only once its (worker) transpile resolves —
26
+ * so a host can leave an in-flight variant showing its fallback rather than a
27
+ * loading state. On edit, a variant keeps its previous build until the new one
28
+ * resolves (and on a transpile error too, reported via `report`), so the preview
29
+ * never flashes.
30
+ *
31
+ * A variant's FIRST build is never cancelled. On the first edit the controller is
32
+ * seeded with the ORIGINAL source and the real edit follows; if that edit arrives
33
+ * before the seed's build settles, it is DEFERRED (not aborted) so the baseline
34
+ * always builds and renders before the edit lands — giving a broken edit a good
35
+ * preview to fall back to. Later edits abort the in-flight build as usual.
36
+ *
37
+ * Per-variant bookkeeping (request ids, abort controllers, last-built input, the
38
+ * first-build-done set, and the deferred edit) lives in refs since it never
39
+ * affects render; only the resolved `built` map is state.
40
+ */
41
+ export function useVariantBuilds(code, transpile, externals, report) {
42
+ const [built, setBuilt] = React.useState({});
43
+
44
+ // Per-variant async bookkeeping (render-irrelevant → refs, not state).
45
+ const requestIds = React.useRef(new Map());
46
+ const controllers = React.useRef(new Map());
47
+ // The exact input object a variant's latest build was STARTED from (not just
48
+ // resolved). Set when a build begins, so an unrelated re-render can't re-trigger
49
+ // a build of the same in-flight input (the controlled code is immutable, so an
50
+ // unchanged variant keeps its object identity).
51
+ const builtFrom = React.useRef(new Map());
52
+ // Variants whose FIRST build has settled (resolved or errored). Until then the
53
+ // build is never cancelled; a superseding edit waits in `deferred`.
54
+ const firstBuildDone = React.useRef(new Set());
55
+ const deferred = React.useRef(new Map());
56
+ React.useEffect(() => {
57
+ if (!code || !transpile) {
58
+ // Controller cleared (e.g. `reset()`): abort in-flight builds and forget all
59
+ // per-variant state, so the next edit is treated as a first build again
60
+ // (re-running the `.original` baseline branch). Drop the resolved `built` map
61
+ // too, so the re-edit starts from an EMPTY map — exactly like a true first
62
+ // edit — instead of briefly flashing the pre-reset build before the rebuilt
63
+ // baseline lands.
64
+ if (!code) {
65
+ for (const controller of controllers.current.values()) {
66
+ controller.abort();
67
+ }
68
+ controllers.current.clear();
69
+ requestIds.current.clear();
70
+ builtFrom.current.clear();
71
+ firstBuildDone.current.clear();
72
+ deferred.current.clear();
73
+ // One-shot reset, NOT a cascading render: `built` is not an effect dep, so
74
+ // clearing it doesn't re-run this effect, and once empty the updater is a
75
+ // no-op. Runs only when `code` is undefined, so it never touches an edit.
76
+ // eslint-disable-next-line react-hooks/set-state-in-effect -- one-shot reset on controller clear
77
+ setBuilt(previous => Object.keys(previous).length > 0 ? {} : previous);
78
+ }
79
+ return;
80
+ }
81
+ const startBuild = (variant, variantCode) => {
82
+ const {
83
+ source
84
+ } = variantCode;
85
+ if (!source) {
86
+ return;
87
+ }
88
+ builtFrom.current.set(variant, variantCode);
89
+ controllers.current.get(variant)?.abort();
90
+ const controller = new AbortController();
91
+ controllers.current.set(variant, controller);
92
+ const requestId = (requestIds.current.get(variant) ?? 0) + 1;
93
+ requestIds.current.set(variant, requestId);
94
+
95
+ // After this build settles, build any edit deferred while it ran.
96
+ const buildDeferred = () => {
97
+ const next = deferred.current.get(variant);
98
+ if (next) {
99
+ deferred.current.delete(variant);
100
+ startBuild(variant, next);
101
+ }
102
+ };
103
+ loadBuildScope().then(buildScope => buildScope({
104
+ extraFiles: variantCode.extraFiles,
105
+ externals,
106
+ mainCode: source,
107
+ transpile,
108
+ signal: controller.signal
109
+ })).then(result => {
110
+ if (requestIds.current.get(variant) !== requestId) {
111
+ return; // superseded by a newer edit
112
+ }
113
+ firstBuildDone.current.add(variant);
114
+ // The build is now valid — clear any prior build error. A render error (if
115
+ // the entry then throws) is a SEPARATE channel reported by the runner; this
116
+ // only clears the build error, which the runner can't clear itself (a
117
+ // CSS-only fix never re-renders the entry).
118
+ report(variant, null);
119
+ // Commit the freshly-built variant urgently (a transition here would let a later
120
+ // edit's commit supersede it before it paints, costing the runner its last-good).
121
+ // The `.original` baseline still renders first when the build is fast enough; when
122
+ // it isn't (a cold first edit, where React coalesces the baseline + edit commits and
123
+ // the baseline never paints), a render error in the edit falls back to the host's
124
+ // build-time render instead of blanking (see the runner's `fallback`).
125
+ setBuilt(previous => ({
126
+ ...previous,
127
+ [variant]: {
128
+ runnerCode: result.runnerCode ?? '',
129
+ scope: {
130
+ import: result.imports
131
+ },
132
+ css: result.css
133
+ }
134
+ }));
135
+ buildDeferred();
136
+ }).catch(thrown => {
137
+ if (requestIds.current.get(variant) !== requestId || controller.signal.aborted) {
138
+ return; // superseded / aborted
139
+ }
140
+ // The attempt finished (failed) — later edits may now cancel.
141
+ firstBuildDone.current.add(variant);
142
+ report(variant, thrown instanceof Error ? thrown.toString() : String(thrown));
143
+ buildDeferred();
144
+ });
145
+ };
146
+ for (const variant of Object.keys(code)) {
147
+ const variantCode = code[variant];
148
+ if (!variantCode || !variantCode.source) {
149
+ continue;
150
+ }
151
+ // First build of a variant that carries a baseline (`.original`, tagged on the
152
+ // FIRST edit): build the ORIGINAL inputs FIRST so the preview shows a good
153
+ // baseline before this (possibly broken) edit, then build the edit (which
154
+ // waits via the defer path below). Gated on `!controllers.has` so it fires
155
+ // exactly once — a re-render or a lingering `.original` never re-baselines.
156
+ const original = variantCode.original;
157
+ if (original?.source && !controllers.current.has(variant)) {
158
+ deferred.current.set(variant, variantCode);
159
+ startBuild(variant, {
160
+ source: original.source,
161
+ extraFiles: original.extraFiles
162
+ });
163
+ continue;
164
+ }
165
+ // Skip a variant whose exact input we already built — so editing one variant
166
+ // doesn't re-transpile and re-evaluate the others.
167
+ if (builtFrom.current.get(variant) === variantCode) {
168
+ continue;
169
+ }
170
+ // Never cancel a variant's FIRST build: while it's in flight, defer this edit
171
+ // (keeping only the latest) instead of aborting, so the baseline renders
172
+ // first. Later edits (first build done) abort the in-flight build as usual.
173
+ if (controllers.current.get(variant) && !firstBuildDone.current.has(variant)) {
174
+ deferred.current.set(variant, variantCode);
175
+ continue;
176
+ }
177
+ startBuild(variant, variantCode);
178
+ }
179
+ }, [code, transpile, externals, report]);
180
+
181
+ // Abort any in-flight builds on unmount.
182
+ React.useEffect(() => () => {
183
+ for (const controller of controllers.current.values()) {
184
+ controller.abort();
185
+ }
186
+ }, []);
187
+ return built;
188
+ }
@@ -1,4 +1,4 @@
1
- import { type ElapsedTime, type Orama, type Result, type SearchParams } from '@orama/orama';
1
+ import type { ElapsedTime, Orama, Result, SearchParams } from '@orama/orama';
2
2
  import type { Sitemap, SitemapPage, SitemapSection, SitemapPart, SitemapExport, SitemapSectionData } from "../createSitemap/types.mjs";
3
3
  /**
4
4
  * Base search result structure that can be extended by consumers
@@ -8,4 +8,4 @@ export declare function TypesDataProvider({
8
8
  children
9
9
  }: {
10
10
  children: React.ReactNode;
11
- }): import("react/jsx-runtime").JSX.Element;
11
+ }): React.JSX.Element;
@@ -2,13 +2,12 @@
2
2
 
3
3
  import * as React from 'react';
4
4
  import { TypesDataContext } from "./TypesDataContext.mjs";
5
-
5
+ import { jsx as _jsx } from "react/jsx-runtime";
6
6
  /**
7
7
  * Provider that collects type data from all `useTypes()` calls within its subtree.
8
8
  * This enables `useType(name)` to look up individual type data anywhere in the tree,
9
9
  * and `useTypeProp(typeName, propName)` to look up individual properties.
10
10
  */
11
- import { jsx as _jsx } from "react/jsx-runtime";
12
11
  export function TypesDataProvider({
13
12
  children
14
13
  }) {
@@ -1,5 +1,5 @@
1
1
  import type * as React from 'react';
2
- import { type TypeData } from "./TypesDataContext.mjs";
2
+ import type { TypeData } from "./TypesDataContext.mjs";
3
3
  /**
4
4
  * Props passed to the custom `typeRefComponent` element.
5
5
  */
@@ -1,5 +1,5 @@
1
1
  import type * as React from 'react';
2
- import { type TypePropData } from "./TypesDataContext.mjs";
2
+ import type { TypePropData } from "./TypesDataContext.mjs";
3
3
  /**
4
4
  * Props passed to the custom `typePropRefComponent` element.
5
5
  */