@docusaurus/theme-live-codeblock 3.9.2 → 3.10.1-canary-6591

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 (32) hide show
  1. package/README.md +1 -1
  2. package/lib/client/context.d.ts +16 -0
  3. package/lib/client/context.js +20 -0
  4. package/lib/client/index.d.ts +7 -0
  5. package/lib/client/index.js +7 -0
  6. package/lib/theme/CodeBlock/index.js +5 -1
  7. package/lib/theme/Playground/Buttons/ResetButton/index.d.ts +9 -0
  8. package/lib/theme/Playground/Buttons/ResetButton/index.js +45 -0
  9. package/lib/theme/Playground/Buttons/ResetButton/styles.module.css +36 -0
  10. package/lib/theme/Playground/Editor/index.js +2 -1
  11. package/lib/theme/Playground/Header/index.d.ts +2 -3
  12. package/lib/theme/Playground/Header/index.js +9 -2
  13. package/lib/theme/Playground/Header/styles.module.css +11 -3
  14. package/lib/theme/Playground/Layout/index.d.ts +2 -1
  15. package/lib/theme/Playground/Layout/index.js +4 -3
  16. package/lib/theme/Playground/Provider/index.d.ts +1 -1
  17. package/lib/theme/Playground/Provider/index.js +13 -2
  18. package/lib/theme/Playground/index.d.ts +1 -1
  19. package/lib/theme/Playground/index.js +7 -2
  20. package/package.json +24 -12
  21. package/src/client/context.tsx +36 -0
  22. package/src/client/index.ts +8 -0
  23. package/src/theme/CodeBlock/index.tsx +8 -2
  24. package/src/theme/Playground/Buttons/ResetButton/index.tsx +51 -0
  25. package/src/theme/Playground/Buttons/ResetButton/styles.module.css +36 -0
  26. package/src/theme/Playground/Editor/index.tsx +2 -2
  27. package/src/theme/Playground/Header/index.tsx +11 -4
  28. package/src/theme/Playground/Header/styles.module.css +11 -3
  29. package/src/theme/Playground/Layout/index.tsx +5 -3
  30. package/src/theme/Playground/Provider/index.tsx +15 -7
  31. package/src/theme/Playground/index.tsx +2 -1
  32. package/src/theme-live-codeblock.d.ts +43 -8
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Docusaurus Live Codeblock
1
+ # `@docusaurus/theme-live-codeblock`
2
2
 
3
3
  You can create live code editors with a code block `live` meta string.
4
4
 
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import { type ReactNode } from 'react';
8
+ type PlaygroundContextValue = {
9
+ reset: () => void;
10
+ };
11
+ export declare function PlaygroundProvider({ value, children, }: {
12
+ value: PlaygroundContextValue;
13
+ children: ReactNode;
14
+ }): ReactNode;
15
+ export declare function usePlayground(): PlaygroundContextValue;
16
+ export {};
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import { createContext, useContext } from 'react';
8
+ const PlaygroundContext = createContext(null);
9
+ export function PlaygroundProvider({ value, children, }) {
10
+ return (<PlaygroundContext.Provider value={value}>
11
+ {children}
12
+ </PlaygroundContext.Provider>);
13
+ }
14
+ export function usePlayground() {
15
+ const context = useContext(PlaygroundContext);
16
+ if (!context) {
17
+ throw new Error('usePlayground must be used within PlaygroundProvider');
18
+ }
19
+ return context;
20
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ export { usePlayground, PlaygroundProvider } from './context';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ export { usePlayground, PlaygroundProvider } from './context';
@@ -8,7 +8,11 @@ import React from 'react';
8
8
  import OriginalCodeBlock from '@theme-init/CodeBlock';
9
9
  import LiveCodeBlock from '@theme/LiveCodeBlock';
10
10
  function isLiveCodeBlock(props) {
11
- return !!props.live;
11
+ return (
12
+ !!props.live &&
13
+ (typeof props.children === 'undefined' ||
14
+ typeof props.children === 'string')
15
+ );
12
16
  }
13
17
  export default function CodeBlockEnhancer(props) {
14
18
  return isLiveCodeBlock(props) ? (
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import type { ReactNode } from 'react';
8
+ import type { Props } from '@theme/Playground/Buttons/ResetButton';
9
+ export default function ResetButton({ className }: Props): ReactNode;
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import clsx from 'clsx';
8
+ import Translate from '@docusaurus/Translate';
9
+ import {usePlayground} from '@docusaurus/theme-live-codeblock/client';
10
+ import styles from './styles.module.css';
11
+ function Icon() {
12
+ return (
13
+ <svg
14
+ className={styles.resetButtonIcon}
15
+ viewBox="0 0 16 16"
16
+ fill="currentColor"
17
+ aria-hidden="true">
18
+ <path d="M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2v1z" />
19
+ <path d="M8 4.466V.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466z" />
20
+ </svg>
21
+ );
22
+ }
23
+ function Label() {
24
+ return (
25
+ <Translate
26
+ id="theme.Playground.buttons.reset"
27
+ description="The reset button label for live code blocks">
28
+ Reset
29
+ </Translate>
30
+ );
31
+ }
32
+ export default function ResetButton({className}) {
33
+ const {reset} = usePlayground();
34
+ return (
35
+ <button
36
+ type="button"
37
+ aria-label="Reset code to original"
38
+ title="Reset"
39
+ className={clsx('clean-btn', className, styles.resetButton)}
40
+ onClick={() => reset()}>
41
+ <Icon />
42
+ <Label />
43
+ </button>
44
+ );
45
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ .resetButton {
9
+ display: inline-flex;
10
+ align-items: center;
11
+ gap: 0.25rem;
12
+ padding: 0.25rem 0.5rem;
13
+ font-size: 0.875rem;
14
+ line-height: 1.5;
15
+ border: 1px solid var(--ifm-color-emphasis-300);
16
+ border-radius: var(--ifm-global-radius);
17
+ background: var(--ifm-button-background-color);
18
+ color: var(--ifm-font-color-base);
19
+ cursor: pointer;
20
+ transition: all var(--ifm-transition-fast);
21
+ }
22
+
23
+ .resetButton:hover {
24
+ background: var(--ifm-color-emphasis-200);
25
+ border-color: var(--ifm-color-emphasis-400);
26
+ }
27
+
28
+ .resetButton:active {
29
+ background: var(--ifm-color-emphasis-300);
30
+ }
31
+
32
+ .resetButtonIcon {
33
+ width: 1rem;
34
+ height: 1rem;
35
+ flex-shrink: 0;
36
+ }
@@ -9,12 +9,13 @@ import {LiveEditor} from 'react-live';
9
9
  import useIsBrowser from '@docusaurus/useIsBrowser';
10
10
  import Translate from '@docusaurus/Translate';
11
11
  import PlaygroundHeader from '@theme/Playground/Header';
12
+ import ResetButton from '@theme/Playground/Buttons/ResetButton';
12
13
  import styles from './styles.module.css';
13
14
  export default function PlaygroundEditor() {
14
15
  const isBrowser = useIsBrowser();
15
16
  return (
16
17
  <>
17
- <PlaygroundHeader>
18
+ <PlaygroundHeader buttons={<ResetButton />}>
18
19
  <Translate
19
20
  id="theme.Playground.liveEditor"
20
21
  description="The live editor label of the live codeblocks">
@@ -5,6 +5,5 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import { type ReactNode } from 'react';
8
- export default function PlaygroundHeader({ children, }: {
9
- children: ReactNode;
10
- }): ReactNode;
8
+ import type { Props } from '@theme/Playground/Header';
9
+ export default function PlaygroundHeader({ children, buttons, }: Props): ReactNode;
@@ -7,6 +7,13 @@
7
7
  import React from 'react';
8
8
  import clsx from 'clsx';
9
9
  import styles from './styles.module.css';
10
- export default function PlaygroundHeader({children}) {
11
- return <div className={clsx(styles.playgroundHeader)}>{children}</div>;
10
+ export default function PlaygroundHeader({children, buttons}) {
11
+ return (
12
+ <div className={clsx(styles.playgroundHeader)}>
13
+ <div className={styles.playgroundHeaderContent}>{children}</div>
14
+ {buttons && (
15
+ <div className={styles.playgroundHeaderButtons}>{buttons}</div>
16
+ )}
17
+ </div>
18
+ );
12
19
  }
@@ -6,6 +6,9 @@
6
6
  */
7
7
 
8
8
  .playgroundHeader {
9
+ display: flex;
10
+ justify-content: space-between;
11
+ align-items: center;
9
12
  letter-spacing: 0.08rem;
10
13
  padding: 0.75rem;
11
14
  text-transform: uppercase;
@@ -15,7 +18,12 @@
15
18
  font-size: var(--ifm-code-font-size);
16
19
  }
17
20
 
18
- .playgroundHeader:first-of-type {
19
- background: var(--ifm-color-emphasis-700);
20
- color: var(--ifm-color-content-inverse);
21
+ .playgroundHeaderContent {
22
+ font-weight: var(--ifm-font-weight-bold);
23
+ font-size: 0.875rem;
24
+ }
25
+
26
+ .playgroundHeaderButtons {
27
+ display: flex;
28
+ gap: 0.5rem;
21
29
  }
@@ -5,4 +5,5 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import { type ReactNode } from 'react';
8
- export default function PlaygroundLayout(): ReactNode;
8
+ import type { Props } from '@theme/Playground/Layout';
9
+ export default function PlaygroundLayout(props: Props): ReactNode;
@@ -12,11 +12,12 @@ function useLiveCodeBlockThemeConfig() {
12
12
  const themeConfig = useThemeConfig();
13
13
  return themeConfig.liveCodeBlock;
14
14
  }
15
- export default function PlaygroundLayout() {
16
- const {playgroundPosition} = useLiveCodeBlockThemeConfig();
15
+ export default function PlaygroundLayout(props) {
16
+ const themeConfig = useLiveCodeBlockThemeConfig();
17
+ const position = props.position ?? themeConfig.playgroundPosition;
17
18
  return (
18
19
  <>
19
- {playgroundPosition === 'top' ? (
20
+ {position === 'top' ? (
20
21
  <>
21
22
  <PlaygroundPreview />
22
23
  <PlaygroundEditor />
@@ -6,4 +6,4 @@
6
6
  */
7
7
  import { type ReactNode } from 'react';
8
8
  import type { Props } from '@theme/Playground/Provider';
9
- export default function PlaygroundProvider({ code, children, ...props }: Props): ReactNode;
9
+ export default function PlaygroundProvider(props: Props): ReactNode;
@@ -4,13 +4,14 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- import React from 'react';
7
+ import React, {useCallback, useMemo, useState} from 'react';
8
8
  import {LiveProvider} from 'react-live';
9
+ import {PlaygroundProvider as PlaygroundProviderComponent} from '@docusaurus/theme-live-codeblock/client';
9
10
  import {usePrismTheme} from '@docusaurus/theme-common';
10
11
  // this should rather be a stable function
11
12
  // see https://github.com/facebook/docusaurus/issues/9630#issuecomment-1855682643
12
13
  const DEFAULT_TRANSFORM_CODE = (code) => `${code};`;
13
- export default function PlaygroundProvider({code, children, ...props}) {
14
+ function LiveProviderComponent({code, children, ...props}) {
14
15
  const prismTheme = usePrismTheme();
15
16
  const noInline = props.metastring?.includes('noInline') ?? false;
16
17
  return (
@@ -24,3 +25,13 @@ export default function PlaygroundProvider({code, children, ...props}) {
24
25
  </LiveProvider>
25
26
  );
26
27
  }
28
+ export default function PlaygroundProvider(props) {
29
+ const [resetKey, setResetKey] = useState(0);
30
+ const reset = useCallback(() => setResetKey((prev) => prev + 1), []);
31
+ const value = useMemo(() => ({reset}), [reset]);
32
+ return (
33
+ <PlaygroundProviderComponent key={resetKey} value={value}>
34
+ <LiveProviderComponent {...props} />
35
+ </PlaygroundProviderComponent>
36
+ );
37
+ }
@@ -6,4 +6,4 @@
6
6
  */
7
7
  import { type ReactNode } from 'react';
8
8
  import type { Props } from '@theme/Playground';
9
- export default function Playground({ children, transformCode, ...props }: Props): ReactNode;
9
+ export default function Playground({ children, transformCode, position, ...props }: Props): ReactNode;
@@ -8,11 +8,16 @@ import React from 'react';
8
8
  import PlaygroundProvider from '@theme/Playground/Provider';
9
9
  import PlaygroundContainer from '@theme/Playground/Container';
10
10
  import PlaygroundLayout from '@theme/Playground/Layout';
11
- export default function Playground({children, transformCode, ...props}) {
11
+ export default function Playground({
12
+ children,
13
+ transformCode,
14
+ position,
15
+ ...props
16
+ }) {
12
17
  return (
13
18
  <PlaygroundContainer>
14
19
  <PlaygroundProvider code={children} {...props}>
15
- <PlaygroundLayout />
20
+ <PlaygroundLayout position={position} />
16
21
  </PlaygroundProvider>
17
22
  </PlaygroundContainer>
18
23
  );
package/package.json CHANGED
@@ -1,12 +1,24 @@
1
1
  {
2
2
  "name": "@docusaurus/theme-live-codeblock",
3
- "version": "3.9.2",
3
+ "version": "3.10.1-canary-6591",
4
4
  "description": "Docusaurus live code block component.",
5
5
  "main": "lib/index.js",
6
6
  "types": "src/theme-live-codeblock.d.ts",
7
7
  "sideEffects": [
8
8
  "lib/theme/Playground/*"
9
9
  ],
10
+ "exports": {
11
+ "./lib/*": "./lib/*",
12
+ "./src/*": "./src/*",
13
+ "./client": {
14
+ "type": "./lib/client/index.d.ts",
15
+ "default": "./lib/client/index.js"
16
+ },
17
+ ".": {
18
+ "types": "./src/theme-live-codeblock.d.ts",
19
+ "default": "./lib/index.js"
20
+ }
21
+ },
10
22
  "publishConfig": {
11
23
  "access": "public"
12
24
  },
@@ -23,26 +35,26 @@
23
35
  },
24
36
  "license": "MIT",
25
37
  "dependencies": {
26
- "@docusaurus/core": "3.9.2",
27
- "@docusaurus/theme-common": "3.9.2",
28
- "@docusaurus/theme-translations": "3.9.2",
29
- "@docusaurus/utils-validation": "3.9.2",
38
+ "@docusaurus/core": "3.10.1-canary-6591",
39
+ "@docusaurus/theme-common": "3.10.1-canary-6591",
40
+ "@docusaurus/theme-translations": "3.10.1-canary-6591",
41
+ "@docusaurus/utils-validation": "3.10.1-canary-6591",
30
42
  "@philpl/buble": "^0.19.7",
31
43
  "clsx": "^2.0.0",
32
- "fs-extra": "^11.1.1",
33
- "react-live": "^4.1.6",
44
+ "fs-extra": "^11.2.0",
45
+ "react-live": "^4.1.8",
34
46
  "tslib": "^2.6.0"
35
47
  },
36
48
  "devDependencies": {
37
- "@docusaurus/types": "3.9.2",
49
+ "@docusaurus/types": "3.10.1-canary-6591",
38
50
  "@types/buble": "^0.20.1"
39
51
  },
40
52
  "peerDependencies": {
41
- "react": "^18.0.0 || ^19.0.0",
42
- "react-dom": "^18.0.0 || ^19.0.0"
53
+ "react": "^19.2.5",
54
+ "react-dom": "^19.2.5"
43
55
  },
44
56
  "engines": {
45
- "node": ">=20.0"
57
+ "node": ">=24.14"
46
58
  },
47
- "gitHead": "abfbe5621b08407bc3dcbe6111ff118d4c22f7a1"
59
+ "gitHead": "0a37b4e95aa595949734a1cb72d13305bbacb822"
48
60
  }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ import {createContext, useContext, type ReactNode} from 'react';
9
+
10
+ type PlaygroundContextValue = {
11
+ reset: () => void;
12
+ };
13
+
14
+ const PlaygroundContext = createContext<PlaygroundContextValue | null>(null);
15
+
16
+ export function PlaygroundProvider({
17
+ value,
18
+ children,
19
+ }: {
20
+ value: PlaygroundContextValue;
21
+ children: ReactNode;
22
+ }): ReactNode {
23
+ return (
24
+ <PlaygroundContext.Provider value={value}>
25
+ {children}
26
+ </PlaygroundContext.Provider>
27
+ );
28
+ }
29
+
30
+ export function usePlayground(): PlaygroundContextValue {
31
+ const context = useContext(PlaygroundContext);
32
+ if (!context) {
33
+ throw new Error('usePlayground must be used within PlaygroundProvider');
34
+ }
35
+ return context;
36
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ export {usePlayground, PlaygroundProvider} from './context';
@@ -19,8 +19,14 @@ declare module '@theme/CodeBlock' {
19
19
  }
20
20
  }
21
21
 
22
- function isLiveCodeBlock(props: CodeBlockProps): boolean {
23
- return !!props.live;
22
+ function isLiveCodeBlock(
23
+ props: CodeBlockProps,
24
+ ): props is {live: true; children: string | undefined} {
25
+ return (
26
+ !!props.live &&
27
+ (typeof props.children === 'undefined' ||
28
+ typeof props.children === 'string')
29
+ );
24
30
  }
25
31
 
26
32
  export default function CodeBlockEnhancer(props: CodeBlockProps): ReactNode {
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ import type {ReactNode} from 'react';
9
+ import clsx from 'clsx';
10
+ import Translate from '@docusaurus/Translate';
11
+ import {usePlayground} from '@docusaurus/theme-live-codeblock/client';
12
+ import type {Props} from '@theme/Playground/Buttons/ResetButton';
13
+ import styles from './styles.module.css';
14
+
15
+ function Icon() {
16
+ return (
17
+ <svg
18
+ className={styles.resetButtonIcon}
19
+ viewBox="0 0 16 16"
20
+ fill="currentColor"
21
+ aria-hidden="true">
22
+ <path d="M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2v1z" />
23
+ <path d="M8 4.466V.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466z" />
24
+ </svg>
25
+ );
26
+ }
27
+
28
+ function Label() {
29
+ return (
30
+ <Translate
31
+ id="theme.Playground.buttons.reset"
32
+ description="The reset button label for live code blocks">
33
+ Reset
34
+ </Translate>
35
+ );
36
+ }
37
+
38
+ export default function ResetButton({className}: Props): ReactNode {
39
+ const {reset} = usePlayground();
40
+ return (
41
+ <button
42
+ type="button"
43
+ aria-label="Reset code to original"
44
+ title="Reset"
45
+ className={clsx('clean-btn', className, styles.resetButton)}
46
+ onClick={() => reset()}>
47
+ <Icon />
48
+ <Label />
49
+ </button>
50
+ );
51
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ .resetButton {
9
+ display: inline-flex;
10
+ align-items: center;
11
+ gap: 0.25rem;
12
+ padding: 0.25rem 0.5rem;
13
+ font-size: 0.875rem;
14
+ line-height: 1.5;
15
+ border: 1px solid var(--ifm-color-emphasis-300);
16
+ border-radius: var(--ifm-global-radius);
17
+ background: var(--ifm-button-background-color);
18
+ color: var(--ifm-font-color-base);
19
+ cursor: pointer;
20
+ transition: all var(--ifm-transition-fast);
21
+ }
22
+
23
+ .resetButton:hover {
24
+ background: var(--ifm-color-emphasis-200);
25
+ border-color: var(--ifm-color-emphasis-400);
26
+ }
27
+
28
+ .resetButton:active {
29
+ background: var(--ifm-color-emphasis-300);
30
+ }
31
+
32
+ .resetButtonIcon {
33
+ width: 1rem;
34
+ height: 1rem;
35
+ flex-shrink: 0;
36
+ }
@@ -10,14 +10,14 @@ import {LiveEditor} from 'react-live';
10
10
  import useIsBrowser from '@docusaurus/useIsBrowser';
11
11
  import Translate from '@docusaurus/Translate';
12
12
  import PlaygroundHeader from '@theme/Playground/Header';
13
-
13
+ import ResetButton from '@theme/Playground/Buttons/ResetButton';
14
14
  import styles from './styles.module.css';
15
15
 
16
16
  export default function PlaygroundEditor(): ReactNode {
17
17
  const isBrowser = useIsBrowser();
18
18
  return (
19
19
  <>
20
- <PlaygroundHeader>
20
+ <PlaygroundHeader buttons={<ResetButton />}>
21
21
  <Translate
22
22
  id="theme.Playground.liveEditor"
23
23
  description="The live editor label of the live codeblocks">
@@ -7,13 +7,20 @@
7
7
 
8
8
  import React, {type ReactNode} from 'react';
9
9
  import clsx from 'clsx';
10
+ import type {Props} from '@theme/Playground/Header';
10
11
 
11
12
  import styles from './styles.module.css';
12
13
 
13
14
  export default function PlaygroundHeader({
14
15
  children,
15
- }: {
16
- children: ReactNode;
17
- }): ReactNode {
18
- return <div className={clsx(styles.playgroundHeader)}>{children}</div>;
16
+ buttons,
17
+ }: Props): ReactNode {
18
+ return (
19
+ <div className={clsx(styles.playgroundHeader)}>
20
+ <div className={styles.playgroundHeaderContent}>{children}</div>
21
+ {buttons && (
22
+ <div className={styles.playgroundHeaderButtons}>{buttons}</div>
23
+ )}
24
+ </div>
25
+ );
19
26
  }
@@ -6,6 +6,9 @@
6
6
  */
7
7
 
8
8
  .playgroundHeader {
9
+ display: flex;
10
+ justify-content: space-between;
11
+ align-items: center;
9
12
  letter-spacing: 0.08rem;
10
13
  padding: 0.75rem;
11
14
  text-transform: uppercase;
@@ -15,7 +18,12 @@
15
18
  font-size: var(--ifm-code-font-size);
16
19
  }
17
20
 
18
- .playgroundHeader:first-of-type {
19
- background: var(--ifm-color-emphasis-700);
20
- color: var(--ifm-color-content-inverse);
21
+ .playgroundHeaderContent {
22
+ font-weight: var(--ifm-font-weight-bold);
23
+ font-size: 0.875rem;
24
+ }
25
+
26
+ .playgroundHeaderButtons {
27
+ display: flex;
28
+ gap: 0.5rem;
21
29
  }
@@ -9,6 +9,7 @@ import React, {type ReactNode} from 'react';
9
9
  import {useThemeConfig} from '@docusaurus/theme-common';
10
10
  import PlaygroundPreview from '@theme/Playground/Preview';
11
11
  import PlaygroundEditor from '@theme/Playground/Editor';
12
+ import type {Props} from '@theme/Playground/Layout';
12
13
 
13
14
  import type {ThemeConfig} from '@docusaurus/theme-live-codeblock';
14
15
 
@@ -17,11 +18,12 @@ function useLiveCodeBlockThemeConfig() {
17
18
  return themeConfig.liveCodeBlock;
18
19
  }
19
20
 
20
- export default function PlaygroundLayout(): ReactNode {
21
- const {playgroundPosition} = useLiveCodeBlockThemeConfig();
21
+ export default function PlaygroundLayout(props: Props): ReactNode {
22
+ const themeConfig = useLiveCodeBlockThemeConfig();
23
+ const position = props.position ?? themeConfig.playgroundPosition;
22
24
  return (
23
25
  <>
24
- {playgroundPosition === 'top' ? (
26
+ {position === 'top' ? (
25
27
  <>
26
28
  <PlaygroundPreview />
27
29
  <PlaygroundEditor />
@@ -5,21 +5,17 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import React, {type ReactNode} from 'react';
8
+ import React, {type ReactNode, useCallback, useMemo, useState} from 'react';
9
9
  import {LiveProvider} from 'react-live';
10
+ import {PlaygroundProvider as PlaygroundProviderComponent} from '@docusaurus/theme-live-codeblock/client';
10
11
  import {usePrismTheme} from '@docusaurus/theme-common';
11
-
12
12
  import type {Props} from '@theme/Playground/Provider';
13
13
 
14
14
  // this should rather be a stable function
15
15
  // see https://github.com/facebook/docusaurus/issues/9630#issuecomment-1855682643
16
16
  const DEFAULT_TRANSFORM_CODE = (code: string) => `${code};`;
17
17
 
18
- export default function PlaygroundProvider({
19
- code,
20
- children,
21
- ...props
22
- }: Props): ReactNode {
18
+ function LiveProviderComponent({code, children, ...props}: Props): ReactNode {
23
19
  const prismTheme = usePrismTheme();
24
20
  const noInline = props.metastring?.includes('noInline') ?? false;
25
21
  return (
@@ -33,3 +29,15 @@ export default function PlaygroundProvider({
33
29
  </LiveProvider>
34
30
  );
35
31
  }
32
+
33
+ export default function PlaygroundProvider(props: Props): ReactNode {
34
+ const [resetKey, setResetKey] = useState(0);
35
+ const reset = useCallback(() => setResetKey((prev) => prev + 1), []);
36
+ const value = useMemo(() => ({reset}), [reset]);
37
+
38
+ return (
39
+ <PlaygroundProviderComponent key={resetKey} value={value}>
40
+ <LiveProviderComponent {...props} />
41
+ </PlaygroundProviderComponent>
42
+ );
43
+ }
@@ -15,12 +15,13 @@ import type {Props} from '@theme/Playground';
15
15
  export default function Playground({
16
16
  children,
17
17
  transformCode,
18
+ position,
18
19
  ...props
19
20
  }: Props): ReactNode {
20
21
  return (
21
22
  <PlaygroundContainer>
22
23
  <PlaygroundProvider code={children} {...props}>
23
- <PlaygroundLayout />
24
+ <PlaygroundLayout position={position} />
24
25
  </PlaygroundProvider>
25
26
  </PlaygroundContainer>
26
27
  );
@@ -9,17 +9,24 @@
9
9
  /// <reference types="@docusaurus/module-type-aliases" />
10
10
 
11
11
  declare module '@docusaurus/theme-live-codeblock' {
12
+ import type {PlaygroundPosition} from '@theme/Playground';
13
+
12
14
  export type ThemeConfig = {
13
15
  liveCodeBlock: {
14
- playgroundPosition: 'top' | 'bottom';
16
+ playgroundPosition: PlaygroundPosition;
15
17
  };
16
18
  };
17
19
  }
18
20
 
19
21
  declare module '@theme/LiveCodeBlock' {
22
+ import type {ReactNode} from 'react';
20
23
  import type {Props as BaseProps} from '@theme/CodeBlock';
21
24
 
22
- export interface Props extends BaseProps {}
25
+ type CodeBlockProps = Omit<BaseProps, 'children'>;
26
+
27
+ export interface Props extends CodeBlockProps {
28
+ children?: string;
29
+ }
23
30
 
24
31
  export default function LiveCodeBlock(props: Props): ReactNode;
25
32
  }
@@ -29,14 +36,21 @@ declare module '@theme/Playground' {
29
36
  import type {Props as BaseProps} from '@theme/CodeBlock';
30
37
  import type {LiveProvider} from 'react-live';
31
38
 
32
- type CodeBlockProps = Omit<BaseProps, 'className' | 'language' | 'title'>;
39
+ type CodeBlockProps = Omit<
40
+ BaseProps,
41
+ 'children' | 'className' | 'language' | 'title'
42
+ >;
33
43
  type LiveProviderProps = React.ComponentProps<typeof LiveProvider>;
34
44
 
45
+ export type PlaygroundPosition = 'top' | 'bottom';
46
+
35
47
  export interface Props extends CodeBlockProps, LiveProviderProps {
36
48
  // Allow empty live playgrounds
37
49
  children?: string;
50
+ position?: PlaygroundPosition;
38
51
  }
39
- export default function Playground(props: LiveProviderProps): ReactNode;
52
+
53
+ export default function Playground(props: Props): ReactNode;
40
54
  }
41
55
 
42
56
  declare module '@theme/Playground/Provider' {
@@ -48,6 +62,13 @@ declare module '@theme/Playground/Provider' {
48
62
  children: ReactNode;
49
63
  }
50
64
 
65
+ export interface ResetContextValue {
66
+ resetKey: number;
67
+ reset: () => void;
68
+ }
69
+
70
+ export const PlaygroundResetContext: React.Context<ResetContextValue | null>;
71
+ export function usePlaygroundReset(): ResetContextValue;
51
72
  export default function PlaygroundProvider(props: Props): ReactNode;
52
73
  }
53
74
 
@@ -63,9 +84,11 @@ declare module '@theme/Playground/Container' {
63
84
 
64
85
  declare module '@theme/Playground/Layout' {
65
86
  import type {ReactNode} from 'react';
87
+ import type {PlaygroundPosition} from '@theme/Playground';
66
88
 
67
- // eslint-disable-next-line @typescript-eslint/no-empty-interface
68
- export interface Props {}
89
+ export interface Props {
90
+ position?: PlaygroundPosition;
91
+ }
69
92
 
70
93
  export default function PlaygroundLayout(props: Props): ReactNode;
71
94
  }
@@ -91,12 +114,24 @@ declare module '@theme/Playground/Editor' {
91
114
  declare module '@theme/Playground/Header' {
92
115
  import type {ReactNode} from 'react';
93
116
 
94
- // eslint-disable-next-line @typescript-eslint/no-empty-interface
95
- export interface Props {}
117
+ export interface Props {
118
+ children: ReactNode;
119
+ buttons?: ReactNode;
120
+ }
96
121
 
97
122
  export default function PlaygroundHeader(props: Props): ReactNode;
98
123
  }
99
124
 
125
+ declare module '@theme/Playground/Buttons/ResetButton' {
126
+ import type {ReactNode} from 'react';
127
+
128
+ export interface Props {
129
+ className?: string;
130
+ }
131
+
132
+ export default function ResetButton(props: Props): ReactNode;
133
+ }
134
+
100
135
  declare module '@theme/ReactLiveScope' {
101
136
  type Scope = {
102
137
  [key: string]: unknown;