next-live-docusaurus 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # next-live-docusaurus
2
+
3
+ Docusaurus plugin that turns ` ```tsx live ` fences into editable next-live previews.
4
+
5
+ ## Requirements
6
+
7
+ - React 19+
8
+ - Docusaurus 3.7+ with `@docusaurus/core` and `@docusaurus/theme-common` installed in your site
9
+ - [next-live](https://www.npmjs.com/package/next-live) ^1
10
+ - `prism-react-renderer` (required by `next-live/editor`)
11
+
12
+ ## Compatibility
13
+
14
+ The theme uses `@docusaurus/theme-common/internal` for metastring parsing (same pattern as `@docusaurus/theme-live-codeblock`). Peer range `^3.7` plus the CI Docusaurus smoke test cover breakage across Docusaurus minors.
15
+
16
+ ## Setup
17
+
18
+ ```js
19
+ // docusaurus.config.js
20
+ import nextLivePlugin from 'next-live-docusaurus';
21
+
22
+ export default {
23
+ plugins: [
24
+ [
25
+ nextLivePlugin,
26
+ {
27
+ modules: './src/live-modules.ts',
28
+ },
29
+ ],
30
+ ],
31
+ };
32
+ ```
33
+
34
+ Mark a fence as live with a `live` metastring token:
35
+
36
+ ````mdx
37
+ ```tsx live
38
+ export default function Demo() {
39
+ return <button>Hello</button>;
40
+ }
41
+ ```
42
+ ````
43
+
44
+ ## Module registry
45
+
46
+ Export components from the file passed to `modules`. They are available as `@next-live-docusaurus/modules` inside live snippets.
@@ -0,0 +1,6 @@
1
+ // src/constants.ts
2
+ var MODULES_ID = "@next-live-docusaurus/modules";
3
+
4
+ export {
5
+ MODULES_ID
6
+ };
@@ -0,0 +1,4 @@
1
+ /** Webpack alias target for the host's module registry. */
2
+ declare const MODULES_ID = "@next-live-docusaurus/modules";
3
+
4
+ export { MODULES_ID };
@@ -0,0 +1,6 @@
1
+ import {
2
+ MODULES_ID
3
+ } from "./chunk-UNPZ2LML.js";
4
+ export {
5
+ MODULES_ID
6
+ };
@@ -0,0 +1,10 @@
1
+ import { LoadContext, Plugin } from '@docusaurus/types';
2
+ export { MODULES_ID } from './constants.js';
3
+
4
+ interface NextLivePluginOptions {
5
+ /** Path to a module registry file aliased as `@next-live-docusaurus/modules`. */
6
+ modules?: string;
7
+ }
8
+ declare function nextLivePlugin(context: LoadContext, options?: NextLivePluginOptions): Plugin;
9
+
10
+ export { type NextLivePluginOptions, nextLivePlugin as default };
package/dist/index.js ADDED
@@ -0,0 +1,40 @@
1
+ import {
2
+ MODULES_ID
3
+ } from "./chunk-UNPZ2LML.js";
4
+
5
+ // src/index.ts
6
+ import path from "path";
7
+ import { fileURLToPath } from "url";
8
+ function nextLivePlugin(context, options = {}) {
9
+ const distDir = path.dirname(fileURLToPath(import.meta.url));
10
+ const packageRoot = path.join(distDir, "..");
11
+ const themeDir = path.join(packageRoot, "lib", "theme");
12
+ const tsThemeDir = path.join(packageRoot, "src", "theme");
13
+ return {
14
+ name: "next-live-docusaurus",
15
+ configureWebpack() {
16
+ const stub = path.join(distDir, "modules-stub.js");
17
+ const resolved = options.modules ? path.resolve(context.siteDir, options.modules) : stub;
18
+ return {
19
+ resolve: {
20
+ alias: {
21
+ [MODULES_ID]: resolved
22
+ }
23
+ }
24
+ };
25
+ },
26
+ getThemePath() {
27
+ return themeDir;
28
+ },
29
+ getTypeScriptThemePath() {
30
+ return tsThemeDir;
31
+ },
32
+ getClientModules() {
33
+ return [path.join(packageRoot, "lib", "theme", "live-block.css")];
34
+ }
35
+ };
36
+ }
37
+ export {
38
+ MODULES_ID,
39
+ nextLivePlugin as default
40
+ };
@@ -0,0 +1,4 @@
1
+ /** Default stub when no `modules` path is configured in the plugin. */
2
+ declare const _default: {};
3
+
4
+ export { _default as default };
@@ -0,0 +1,5 @@
1
+ // src/modules-stub.ts
2
+ var modules_stub_default = {};
3
+ export {
4
+ modules_stub_default as default
5
+ };
@@ -0,0 +1,52 @@
1
+ "use client";
2
+
3
+ // src/theme/CodeBlock/LiveBlock.tsx
4
+ import CodeBlock from "@theme-init/CodeBlock";
5
+ import { LiveProvider, LivePreview, LiveError } from "next-live";
6
+ import { LiveEditor } from "next-live/editor";
7
+ import { usePrismTheme } from "@docusaurus/theme-common";
8
+ import { MODULES_ID } from "next-live-docusaurus/constants";
9
+ import * as liveModules from "@next-live-docusaurus/modules";
10
+ import { jsx, jsxs } from "react/jsx-runtime";
11
+ function LiveBlock({
12
+ code,
13
+ language,
14
+ title,
15
+ showLineNumbers,
16
+ highlightLines
17
+ }) {
18
+ const prismTheme = usePrismTheme();
19
+ return /* @__PURE__ */ jsx(
20
+ LiveProvider,
21
+ {
22
+ code,
23
+ modules: { [MODULES_ID]: liveModules },
24
+ language,
25
+ children: /* @__PURE__ */ jsxs("div", { className: "next-live-block", "data-testid": "next-live-block", children: [
26
+ title ? /* @__PURE__ */ jsx("div", { className: "next-live-block__filename", "data-testid": "next-live-block-title", children: title }) : null,
27
+ /* @__PURE__ */ jsxs("div", { className: "next-live-block__body", children: [
28
+ /* @__PURE__ */ jsxs("section", { className: "next-live-block__pane next-live-block__preview-pane", children: [
29
+ /* @__PURE__ */ jsx("p", { className: "next-live-block__pane-label", children: "Preview" }),
30
+ /* @__PURE__ */ jsx("div", { className: "next-live-block__preview", "data-testid": "next-live-preview", children: /* @__PURE__ */ jsx("div", { className: "next-live-block__preview-inner", children: /* @__PURE__ */ jsx(LivePreview, { fallback: /* @__PURE__ */ jsx(CodeBlock, { language, children: code }) }) }) }),
31
+ /* @__PURE__ */ jsx(LiveError, { className: "next-live-block__error", as: "div" })
32
+ ] }),
33
+ /* @__PURE__ */ jsxs("section", { className: "next-live-block__pane next-live-block__editor-pane", children: [
34
+ /* @__PURE__ */ jsx("p", { className: "next-live-block__pane-label", children: "Source (editable)" }),
35
+ /* @__PURE__ */ jsx("div", { className: "next-live-block__editor", children: /* @__PURE__ */ jsx(
36
+ LiveEditor,
37
+ {
38
+ theme: prismTheme,
39
+ lineNumbers: showLineNumbers,
40
+ highlightLines,
41
+ className: "next-live-editor-root"
42
+ }
43
+ ) })
44
+ ] })
45
+ ] })
46
+ ] })
47
+ }
48
+ );
49
+ }
50
+ export {
51
+ LiveBlock as default
52
+ };
@@ -0,0 +1,55 @@
1
+ "use client";
2
+
3
+ // src/theme/CodeBlock/index.tsx
4
+ import { lazy, Suspense } from "react";
5
+ import BrowserOnly from "@docusaurus/BrowserOnly";
6
+ import CodeBlock from "@theme-init/CodeBlock";
7
+ import {
8
+ containsLineNumbers,
9
+ parseCodeBlockTitle
10
+ } from "@docusaurus/theme-common/internal";
11
+
12
+ // src/theme/CodeBlock/metastring.ts
13
+ function stripQuotedStrings(metastring) {
14
+ return metastring.replace(/"(?:\\.|[^"\\])*"/g, " ").replace(/'(?:\\.|[^'\\])*'/g, " ");
15
+ }
16
+ function isLiveBlock(metastring) {
17
+ if (!metastring) return false;
18
+ return stripQuotedStrings(metastring).split(/\s+/).includes("live");
19
+ }
20
+
21
+ // src/theme/CodeBlock/index.tsx
22
+ import { jsx } from "react/jsx-runtime";
23
+ var LiveBlock = lazy(() => import("./LiveBlock.js"));
24
+ function languageFromClassName(className) {
25
+ const match = className?.match(/language-(\w+)/);
26
+ return match?.[1] ?? "tsx";
27
+ }
28
+ function highlightFromMetastring(metastring) {
29
+ if (!metastring) return void 0;
30
+ const match = /\{([\d,\s-]+)\}/.exec(metastring);
31
+ return match?.[1];
32
+ }
33
+ function CodeBlockWithLive(props) {
34
+ if (!isLiveBlock(props.metastring)) {
35
+ return /* @__PURE__ */ jsx(CodeBlock, { ...props });
36
+ }
37
+ const code = String(props.children ?? "").replace(/\n$/, "");
38
+ const language = languageFromClassName(props.className);
39
+ const title = parseCodeBlockTitle(props.metastring) || props.title;
40
+ const showLineNumbers = props.showLineNumbers ?? containsLineNumbers(props.metastring);
41
+ const highlightLines = highlightFromMetastring(props.metastring);
42
+ return /* @__PURE__ */ jsx(BrowserOnly, { fallback: /* @__PURE__ */ jsx(CodeBlock, { ...props }), children: () => /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(CodeBlock, { ...props }), children: /* @__PURE__ */ jsx(
43
+ LiveBlock,
44
+ {
45
+ code,
46
+ language,
47
+ title,
48
+ showLineNumbers,
49
+ highlightLines
50
+ }
51
+ ) }) });
52
+ }
53
+ export {
54
+ CodeBlockWithLive as default
55
+ };
@@ -0,0 +1,99 @@
1
+ /* Matches playground LiveDemo. Works in light and dark via --next-live-* tokens. */
2
+ .next-live-block {
3
+ --nl-border: var(--next-live-border, var(--ifm-color-emphasis-300));
4
+ --nl-card: var(--next-live-card, var(--ifm-background-color));
5
+ --nl-background: var(--next-live-background, var(--ifm-background-color));
6
+ --nl-muted-fg: var(--next-live-muted-foreground, var(--ifm-color-emphasis-700));
7
+ --nl-radius: var(--next-live-radius, 0.75rem);
8
+ --nl-radius-inner: var(--next-live-radius-inner, 0.5rem);
9
+ --nl-destructive: var(--next-live-destructive, var(--ifm-color-danger));
10
+ --nl-shadow: var(--next-live-shadow, 0 1px 2px rgb(0 0 0 / 6%));
11
+
12
+ width: 100%;
13
+ margin: 1.25rem 0 0;
14
+ border: 1px solid var(--nl-border);
15
+ border-radius: var(--nl-radius);
16
+ background: var(--nl-card);
17
+ box-shadow: var(--nl-shadow);
18
+ overflow: hidden;
19
+ }
20
+
21
+ .next-live-block__filename {
22
+ display: flex;
23
+ align-items: center;
24
+ gap: 0.5rem;
25
+ padding: 0.625rem 1rem;
26
+ border-bottom: 1px solid var(--nl-border);
27
+ font-size: 0.8125rem;
28
+ font-weight: 500;
29
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
30
+ color: var(--nl-muted-fg);
31
+ background: color-mix(in srgb, var(--nl-border) 12%, var(--nl-card));
32
+ }
33
+
34
+ .next-live-block__body {
35
+ display: grid;
36
+ gap: 0.75rem;
37
+ padding: 1rem;
38
+ }
39
+
40
+ @media (min-width: 768px) {
41
+ .next-live-block__body {
42
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
43
+ }
44
+ }
45
+
46
+ .next-live-block__pane {
47
+ display: grid;
48
+ gap: 0.5rem;
49
+ min-width: 0;
50
+ }
51
+
52
+ .next-live-block__pane-label {
53
+ margin: 0;
54
+ font-size: 0.75rem;
55
+ font-weight: 500;
56
+ letter-spacing: 0.04em;
57
+ text-transform: uppercase;
58
+ color: var(--nl-muted-fg);
59
+ }
60
+
61
+ .next-live-block__preview {
62
+ min-height: 10rem;
63
+ padding: 1.25rem;
64
+ border: 1px solid var(--nl-border);
65
+ border-radius: var(--nl-radius-inner);
66
+ background: var(--nl-background);
67
+ }
68
+
69
+ .next-live-block__preview-inner {
70
+ width: 100%;
71
+ }
72
+
73
+ .next-live-block__editor-pane {
74
+ border-top: 1px solid var(--nl-border);
75
+ padding-top: 0.75rem;
76
+ }
77
+
78
+ @media (min-width: 768px) {
79
+ .next-live-block__editor-pane {
80
+ border-top: none;
81
+ border-left: 1px solid var(--nl-border);
82
+ padding-top: 0;
83
+ padding-left: 0.75rem;
84
+ }
85
+ }
86
+
87
+ .next-live-block__editor .next-live-editor-root {
88
+ min-height: 10rem;
89
+ overflow: hidden;
90
+ border: 1px solid var(--nl-border) !important;
91
+ border-radius: var(--nl-radius-inner) !important;
92
+ }
93
+
94
+ .next-live-block__error {
95
+ margin: 0;
96
+ font-size: 0.8125rem;
97
+ line-height: 1.5;
98
+ color: var(--nl-destructive);
99
+ }
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "next-live-docusaurus",
3
+ "version": "1.0.0",
4
+ "description": "Docusaurus plugin for live TSX/JSX blocks powered by next-live",
5
+ "license": "MIT",
6
+ "author": "Khaled Oghli",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/khaledOghli/next-live.git",
10
+ "directory": "packages/next-live-docusaurus"
11
+ },
12
+ "publishConfig": {
13
+ "access": "public",
14
+ "provenance": true
15
+ },
16
+ "type": "module",
17
+ "main": "./dist/index.js",
18
+ "types": "./dist/index.d.ts",
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "import": "./dist/index.js",
23
+ "default": "./dist/index.js"
24
+ },
25
+ "./constants": {
26
+ "types": "./dist/constants.d.ts",
27
+ "import": "./dist/constants.js",
28
+ "default": "./dist/constants.js"
29
+ }
30
+ },
31
+ "files": [
32
+ "dist",
33
+ "lib",
34
+ "src/theme"
35
+ ],
36
+ "scripts": {
37
+ "build": "tsup && cp src/theme/live-block.css lib/theme/live-block.css",
38
+ "test": "vitest run",
39
+ "typecheck": "tsc --noEmit",
40
+ "check:package": "npm run build && publint"
41
+ },
42
+ "engines": {
43
+ "node": ">=20.9"
44
+ },
45
+ "peerDependencies": {
46
+ "@docusaurus/core": "^3.7.0",
47
+ "@docusaurus/theme-common": "^3.7.0",
48
+ "next-live": "^1",
49
+ "prism-react-renderer": ">=2",
50
+ "react": ">=19",
51
+ "react-dom": ">=19"
52
+ },
53
+ "peerDependenciesMeta": {
54
+ "@docusaurus/core": { "optional": true },
55
+ "@docusaurus/theme-common": { "optional": true }
56
+ },
57
+ "devDependencies": {
58
+ "@docusaurus/module-type-aliases": "^3.7.0",
59
+ "@docusaurus/theme-common": "^3.7.0",
60
+ "@docusaurus/types": "^3.7.0",
61
+ "@types/node": "^22",
62
+ "next-live": "*",
63
+ "publint": "^0.3.12",
64
+ "react": "^19.2.8",
65
+ "tsup": "^8.5.1",
66
+ "typescript": "^5.9.3",
67
+ "vitest": "^3.2.4"
68
+ }
69
+ }
@@ -0,0 +1,66 @@
1
+ 'use client';
2
+
3
+ import React from 'react';
4
+ import CodeBlock from '@theme-init/CodeBlock';
5
+ import { LiveProvider, LivePreview, LiveError } from 'next-live';
6
+ import { LiveEditor } from 'next-live/editor';
7
+ import { usePrismTheme } from '@docusaurus/theme-common';
8
+ import { MODULES_ID } from 'next-live-docusaurus/constants';
9
+
10
+ import * as liveModules from '@next-live-docusaurus/modules';
11
+
12
+ export interface LiveBlockProps {
13
+ code: string;
14
+ language: string;
15
+ title?: string;
16
+ showLineNumbers?: boolean;
17
+ highlightLines?: string;
18
+ }
19
+
20
+ export default function LiveBlock({
21
+ code,
22
+ language,
23
+ title,
24
+ showLineNumbers,
25
+ highlightLines,
26
+ }: LiveBlockProps): React.ReactElement {
27
+ const prismTheme = usePrismTheme();
28
+
29
+ return (
30
+ <LiveProvider
31
+ code={code}
32
+ modules={{ [MODULES_ID]: liveModules }}
33
+ language={language}
34
+ >
35
+ <div className="next-live-block" data-testid="next-live-block">
36
+ {title ? (
37
+ <div className="next-live-block__filename" data-testid="next-live-block-title">
38
+ {title}
39
+ </div>
40
+ ) : null}
41
+ <div className="next-live-block__body">
42
+ <section className="next-live-block__pane next-live-block__preview-pane">
43
+ <p className="next-live-block__pane-label">Preview</p>
44
+ <div className="next-live-block__preview" data-testid="next-live-preview">
45
+ <div className="next-live-block__preview-inner">
46
+ <LivePreview fallback={<CodeBlock language={language}>{code}</CodeBlock>} />
47
+ </div>
48
+ </div>
49
+ <LiveError className="next-live-block__error" as="div" />
50
+ </section>
51
+ <section className="next-live-block__pane next-live-block__editor-pane">
52
+ <p className="next-live-block__pane-label">Source (editable)</p>
53
+ <div className="next-live-block__editor">
54
+ <LiveEditor
55
+ theme={prismTheme}
56
+ lineNumbers={showLineNumbers}
57
+ highlightLines={highlightLines}
58
+ className="next-live-editor-root"
59
+ />
60
+ </div>
61
+ </section>
62
+ </div>
63
+ </div>
64
+ </LiveProvider>
65
+ );
66
+ }
@@ -0,0 +1,52 @@
1
+ 'use client';
2
+
3
+ import React, { lazy, Suspense } from 'react';
4
+ import BrowserOnly from '@docusaurus/BrowserOnly';
5
+ import CodeBlock from '@theme-init/CodeBlock';
6
+ import type { Props } from '@theme/CodeBlock';
7
+ import {
8
+ containsLineNumbers,
9
+ parseCodeBlockTitle,
10
+ } from '@docusaurus/theme-common/internal';
11
+ import { isLiveBlock } from './metastring';
12
+
13
+ const LiveBlock = lazy(() => import('./LiveBlock'));
14
+
15
+ function languageFromClassName(className?: string): string {
16
+ const match = className?.match(/language-(\w+)/);
17
+ return match?.[1] ?? 'tsx';
18
+ }
19
+
20
+ function highlightFromMetastring(metastring?: string): string | undefined {
21
+ if (!metastring) return undefined;
22
+ const match = /\{([\d,\s-]+)\}/.exec(metastring);
23
+ return match?.[1];
24
+ }
25
+
26
+ export default function CodeBlockWithLive(props: Props): React.ReactElement {
27
+ if (!isLiveBlock(props.metastring)) {
28
+ return <CodeBlock {...props} />;
29
+ }
30
+
31
+ const code = String(props.children ?? '').replace(/\n$/, '');
32
+ const language = languageFromClassName(props.className);
33
+ const title = parseCodeBlockTitle(props.metastring) || props.title;
34
+ const showLineNumbers = props.showLineNumbers ?? containsLineNumbers(props.metastring);
35
+ const highlightLines = highlightFromMetastring(props.metastring);
36
+
37
+ return (
38
+ <BrowserOnly fallback={<CodeBlock {...props} />}>
39
+ {() => (
40
+ <Suspense fallback={<CodeBlock {...props} />}>
41
+ <LiveBlock
42
+ code={code}
43
+ language={language}
44
+ title={title}
45
+ showLineNumbers={showLineNumbers}
46
+ highlightLines={highlightLines}
47
+ />
48
+ </Suspense>
49
+ )}
50
+ </BrowserOnly>
51
+ );
52
+ }
@@ -0,0 +1,11 @@
1
+ /** Strip quoted metastring segments so `title="live demo"` / `title='live demo'` do not match `live`. */
2
+ export function stripQuotedStrings(metastring: string): string {
3
+ return metastring
4
+ .replace(/"(?:\\.|[^"\\])*"/g, ' ')
5
+ .replace(/'(?:\\.|[^'\\])*'/g, ' ');
6
+ }
7
+
8
+ export function isLiveBlock(metastring?: string): boolean {
9
+ if (!metastring) return false;
10
+ return stripQuotedStrings(metastring).split(/\s+/).includes('live');
11
+ }
@@ -0,0 +1,99 @@
1
+ /* Matches playground LiveDemo. Works in light and dark via --next-live-* tokens. */
2
+ .next-live-block {
3
+ --nl-border: var(--next-live-border, var(--ifm-color-emphasis-300));
4
+ --nl-card: var(--next-live-card, var(--ifm-background-color));
5
+ --nl-background: var(--next-live-background, var(--ifm-background-color));
6
+ --nl-muted-fg: var(--next-live-muted-foreground, var(--ifm-color-emphasis-700));
7
+ --nl-radius: var(--next-live-radius, 0.75rem);
8
+ --nl-radius-inner: var(--next-live-radius-inner, 0.5rem);
9
+ --nl-destructive: var(--next-live-destructive, var(--ifm-color-danger));
10
+ --nl-shadow: var(--next-live-shadow, 0 1px 2px rgb(0 0 0 / 6%));
11
+
12
+ width: 100%;
13
+ margin: 1.25rem 0 0;
14
+ border: 1px solid var(--nl-border);
15
+ border-radius: var(--nl-radius);
16
+ background: var(--nl-card);
17
+ box-shadow: var(--nl-shadow);
18
+ overflow: hidden;
19
+ }
20
+
21
+ .next-live-block__filename {
22
+ display: flex;
23
+ align-items: center;
24
+ gap: 0.5rem;
25
+ padding: 0.625rem 1rem;
26
+ border-bottom: 1px solid var(--nl-border);
27
+ font-size: 0.8125rem;
28
+ font-weight: 500;
29
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
30
+ color: var(--nl-muted-fg);
31
+ background: color-mix(in srgb, var(--nl-border) 12%, var(--nl-card));
32
+ }
33
+
34
+ .next-live-block__body {
35
+ display: grid;
36
+ gap: 0.75rem;
37
+ padding: 1rem;
38
+ }
39
+
40
+ @media (min-width: 768px) {
41
+ .next-live-block__body {
42
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
43
+ }
44
+ }
45
+
46
+ .next-live-block__pane {
47
+ display: grid;
48
+ gap: 0.5rem;
49
+ min-width: 0;
50
+ }
51
+
52
+ .next-live-block__pane-label {
53
+ margin: 0;
54
+ font-size: 0.75rem;
55
+ font-weight: 500;
56
+ letter-spacing: 0.04em;
57
+ text-transform: uppercase;
58
+ color: var(--nl-muted-fg);
59
+ }
60
+
61
+ .next-live-block__preview {
62
+ min-height: 10rem;
63
+ padding: 1.25rem;
64
+ border: 1px solid var(--nl-border);
65
+ border-radius: var(--nl-radius-inner);
66
+ background: var(--nl-background);
67
+ }
68
+
69
+ .next-live-block__preview-inner {
70
+ width: 100%;
71
+ }
72
+
73
+ .next-live-block__editor-pane {
74
+ border-top: 1px solid var(--nl-border);
75
+ padding-top: 0.75rem;
76
+ }
77
+
78
+ @media (min-width: 768px) {
79
+ .next-live-block__editor-pane {
80
+ border-top: none;
81
+ border-left: 1px solid var(--nl-border);
82
+ padding-top: 0;
83
+ padding-left: 0.75rem;
84
+ }
85
+ }
86
+
87
+ .next-live-block__editor .next-live-editor-root {
88
+ min-height: 10rem;
89
+ overflow: hidden;
90
+ border: 1px solid var(--nl-border) !important;
91
+ border-radius: var(--nl-radius-inner) !important;
92
+ }
93
+
94
+ .next-live-block__error {
95
+ margin: 0;
96
+ font-size: 0.8125rem;
97
+ line-height: 1.5;
98
+ color: var(--nl-destructive);
99
+ }