@brett_lamy/docstream-editor 0.3.2 → 0.3.4
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 +30 -0
- package/package.json +24 -2
- package/src/editor/ReactDemoEditor.tsx +1 -1
- package/src/editor/SourceFileEditor.tsx +83 -0
- package/src/editor/convert.ts +20 -0
- package/src/editor/nodes.tsx +52 -1
- package/src/index.ts +2 -0
- package/src/styles.css +75 -16
package/README.md
CHANGED
|
@@ -13,6 +13,7 @@ TipTap editor components for Docstream GitBook-style markdown documents.
|
|
|
13
13
|
- Code block support through `lowlight`.
|
|
14
14
|
- Table, task list, heading, quote, and inline formatting support.
|
|
15
15
|
- Preserves Docstream/GitBook block semantics when converting back to markdown.
|
|
16
|
+
- Preserves mounted source-file/export provenance and can write edits to the real file through Vite.
|
|
16
17
|
|
|
17
18
|
## Installation
|
|
18
19
|
|
|
@@ -97,12 +98,39 @@ The editor supports common ProseMirror/TipTap content plus GitBook-flavored bloc
|
|
|
97
98
|
- Steppers
|
|
98
99
|
- Embeds
|
|
99
100
|
- Content references
|
|
101
|
+
- Component and Storybook source references
|
|
100
102
|
- Columns
|
|
101
103
|
- Figures and images
|
|
102
104
|
- OpenAPI operation placeholders
|
|
103
105
|
|
|
104
106
|
Some blocks are intentionally represented as structured nodes rather than fully bespoke editing controls. They are preserved through parse, edit, and serialize flows so the document can continue to round-trip as GitBook-style markdown.
|
|
105
107
|
|
|
108
|
+
## Edit a referenced source file
|
|
109
|
+
|
|
110
|
+
`GitbookEditor` edits the Markdown composition, including a structured
|
|
111
|
+
`source-ref` node. `SourceFileEditor` edits the real file behind that node:
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
import { createViteSourceClient, type SourceRefNode } from "@brett_lamy/docstream"
|
|
115
|
+
import { SourceFileEditor } from "@brett_lamy/docstream-editor"
|
|
116
|
+
|
|
117
|
+
const client = createViteSourceClient()
|
|
118
|
+
const reference: SourceRefNode = {
|
|
119
|
+
type: "source-ref",
|
|
120
|
+
mount: "ui",
|
|
121
|
+
path: "Button.stories.tsx",
|
|
122
|
+
exportName: "Primary",
|
|
123
|
+
kind: "story",
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
<SourceFileEditor reference={reference} client={client} />
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Saving calls the Docstream Vite plugin, writes the mounted file, returns its
|
|
130
|
+
provenance, and refreshes the live component/story preview. Configure the mount
|
|
131
|
+
with `docstreamSources()` from `@brett_lamy/docstream/vite` as shown in the
|
|
132
|
+
Docstream README.
|
|
133
|
+
|
|
106
134
|
## Slash Menu
|
|
107
135
|
|
|
108
136
|
The editor includes a slash menu extension for inserting supported block structures. Type `/` in an empty paragraph to open block insertion options.
|
|
@@ -127,6 +155,8 @@ Exports:
|
|
|
127
155
|
- `astToTiptap`
|
|
128
156
|
- `tiptapToAst`
|
|
129
157
|
- `PMNode`
|
|
158
|
+
- `SourceFileEditor`
|
|
159
|
+
- `SourceFileEditorProps`
|
|
130
160
|
|
|
131
161
|
## Styling and Theming
|
|
132
162
|
|
package/package.json
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brett_lamy/docstream-editor",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"description": "TipTap editor for Docstream GitBook-style markdown documents.",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
8
|
+
"test": "vitest run"
|
|
9
|
+
},
|
|
6
10
|
"main": "./src/index.ts",
|
|
7
11
|
"types": "./src/index.ts",
|
|
8
12
|
"files": [
|
|
@@ -20,7 +24,7 @@
|
|
|
20
24
|
"./styles.css": "./src/styles.css"
|
|
21
25
|
},
|
|
22
26
|
"dependencies": {
|
|
23
|
-
"@brett_lamy/docstream": "0.3.
|
|
27
|
+
"@brett_lamy/docstream": "0.3.7",
|
|
24
28
|
"lowlight": "^3.3.0",
|
|
25
29
|
"lucide-react": "^1.17.0"
|
|
26
30
|
},
|
|
@@ -39,5 +43,23 @@
|
|
|
39
43
|
"repository": {
|
|
40
44
|
"type": "git",
|
|
41
45
|
"url": "git+https://github.com/BLamy/docstream-editor.git"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@agent-wasm/core": "^0.4.0",
|
|
49
|
+
"@tiptap/core": "^3.26.1",
|
|
50
|
+
"@tiptap/extension-code-block-lowlight": "^3.26.1",
|
|
51
|
+
"@tiptap/extension-list": "^3.26.1",
|
|
52
|
+
"@tiptap/extension-placeholder": "^3.26.1",
|
|
53
|
+
"@tiptap/extension-table": "^3.26.1",
|
|
54
|
+
"@tiptap/pm": "^3.26.1",
|
|
55
|
+
"@tiptap/react": "^3.26.1",
|
|
56
|
+
"@tiptap/starter-kit": "^3.26.1",
|
|
57
|
+
"@tiptap/suggestion": "^3.26.1",
|
|
58
|
+
"@types/react": "^19.0.0",
|
|
59
|
+
"@types/react-dom": "^19.0.0",
|
|
60
|
+
"react": "^19",
|
|
61
|
+
"react-dom": "^19",
|
|
62
|
+
"typescript": "^5.6.0",
|
|
63
|
+
"vitest": "^3.2.4"
|
|
42
64
|
}
|
|
43
65
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useEffect, useState } from "react"
|
|
2
2
|
import { FileCode2, Play } from "lucide-react"
|
|
3
3
|
|
|
4
|
-
import { ReactCodePreview } from "@brett_lamy/docstream"
|
|
4
|
+
import { ReactCodePreview } from "@brett_lamy/docstream/playground"
|
|
5
5
|
|
|
6
6
|
export interface ReactDemoEditorProps {
|
|
7
7
|
/** Source files keyed by their project-relative or absolute paths. */
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { useEffect, useState } from "react"
|
|
2
|
+
import { FileCode2, Save } from "lucide-react"
|
|
3
|
+
import { SourcePreview, type SourceFileSnapshot, type SourceReferenceClient } from "@brett_lamy/docstream/source"
|
|
4
|
+
import type { SourceRefNode } from "@brett_lamy/docstream/gitbook"
|
|
5
|
+
|
|
6
|
+
export interface SourceFileEditorProps {
|
|
7
|
+
reference: SourceRefNode
|
|
8
|
+
client: SourceReferenceClient
|
|
9
|
+
className?: string
|
|
10
|
+
preview?: boolean
|
|
11
|
+
onSaved?: (snapshot: SourceFileSnapshot) => void
|
|
12
|
+
onError?: (error: Error) => void
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function asError(cause: unknown): Error {
|
|
16
|
+
return cause instanceof Error ? cause : new Error(String(cause))
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Edit the real file behind a Markdown source reference and preview its export. */
|
|
20
|
+
export function SourceFileEditor({ reference, client, className, preview = true, onSaved, onError }: SourceFileEditorProps) {
|
|
21
|
+
const [content, setContent] = useState("")
|
|
22
|
+
const [savedContent, setSavedContent] = useState("")
|
|
23
|
+
const [revision, setRevision] = useState(0)
|
|
24
|
+
const [status, setStatus] = useState<"loading" | "ready" | "saving" | "error">("loading")
|
|
25
|
+
const [error, setError] = useState<string | null>(null)
|
|
26
|
+
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
let cancelled = false
|
|
29
|
+
setStatus("loading")
|
|
30
|
+
setError(null)
|
|
31
|
+
void client.read(reference).then(
|
|
32
|
+
(snapshot) => {
|
|
33
|
+
if (cancelled) return
|
|
34
|
+
setContent(snapshot.content)
|
|
35
|
+
setSavedContent(snapshot.content)
|
|
36
|
+
setStatus("ready")
|
|
37
|
+
},
|
|
38
|
+
(cause: unknown) => {
|
|
39
|
+
if (cancelled) return
|
|
40
|
+
const next = asError(cause)
|
|
41
|
+
setError(next.message)
|
|
42
|
+
setStatus("error")
|
|
43
|
+
onError?.(next)
|
|
44
|
+
},
|
|
45
|
+
)
|
|
46
|
+
return () => {
|
|
47
|
+
cancelled = true
|
|
48
|
+
}
|
|
49
|
+
}, [client, onError, reference])
|
|
50
|
+
|
|
51
|
+
const save = async () => {
|
|
52
|
+
setStatus("saving")
|
|
53
|
+
setError(null)
|
|
54
|
+
try {
|
|
55
|
+
const snapshot = await client.write(reference, content)
|
|
56
|
+
setSavedContent(snapshot.content)
|
|
57
|
+
setStatus("ready")
|
|
58
|
+
setRevision((value) => value + 1)
|
|
59
|
+
onSaved?.(snapshot)
|
|
60
|
+
} catch (cause) {
|
|
61
|
+
const next = asError(cause)
|
|
62
|
+
setError(next.message)
|
|
63
|
+
setStatus("error")
|
|
64
|
+
onError?.(next)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const wrapper = className ? `gb-source-file-editor ${className}` : "gb-source-file-editor"
|
|
69
|
+
return (
|
|
70
|
+
<section className={wrapper} data-docstream-source-file-editor="">
|
|
71
|
+
<header className="gb-source-file-editor-header">
|
|
72
|
+
<FileCode2 className="size-4" />
|
|
73
|
+
<code>{reference.mount}:{reference.path}#{reference.exportName}</code>
|
|
74
|
+
<button type="button" disabled={status === "loading" || status === "saving" || content === savedContent} onClick={() => void save()}>
|
|
75
|
+
<Save className="size-3.5" /> {status === "saving" ? "Saving…" : "Save file"}
|
|
76
|
+
</button>
|
|
77
|
+
</header>
|
|
78
|
+
{error ? <pre className="gb-source-file-editor-error">{error}</pre> : null}
|
|
79
|
+
<textarea value={content} onChange={(event) => setContent(event.target.value)} disabled={status === "loading"} spellCheck={false} aria-label={`Edit ${reference.path}`} />
|
|
80
|
+
{preview ? <SourcePreview key={revision} reference={reference} client={client} /> : null}
|
|
81
|
+
</section>
|
|
82
|
+
)
|
|
83
|
+
}
|
package/src/editor/convert.ts
CHANGED
|
@@ -110,6 +110,17 @@ function blockToPM(b: Block): PMNode {
|
|
|
110
110
|
}
|
|
111
111
|
case "content-ref":
|
|
112
112
|
return { type: "gbContentRef", attrs: { url: b.url, label: plainText(b.children) } }
|
|
113
|
+
case "source-ref":
|
|
114
|
+
return {
|
|
115
|
+
type: "gbSourceRef",
|
|
116
|
+
attrs: {
|
|
117
|
+
mount: b.mount,
|
|
118
|
+
path: b.path,
|
|
119
|
+
exportName: b.exportName,
|
|
120
|
+
kind: b.kind,
|
|
121
|
+
title: b.title ?? "",
|
|
122
|
+
},
|
|
123
|
+
}
|
|
113
124
|
case "columns":
|
|
114
125
|
return {
|
|
115
126
|
type: "gbColumns",
|
|
@@ -282,6 +293,15 @@ function pmToBlock(n: PMNode): Block | null {
|
|
|
282
293
|
url: String(n.attrs?.url ?? ""),
|
|
283
294
|
children: [{ type: "text", text: String(n.attrs?.label ?? "") }],
|
|
284
295
|
}
|
|
296
|
+
case "gbSourceRef":
|
|
297
|
+
return {
|
|
298
|
+
type: "source-ref",
|
|
299
|
+
mount: String(n.attrs?.mount ?? "source"),
|
|
300
|
+
path: String(n.attrs?.path ?? ""),
|
|
301
|
+
exportName: String(n.attrs?.exportName ?? "default"),
|
|
302
|
+
kind: n.attrs?.kind === "story" ? "story" : "component",
|
|
303
|
+
...(n.attrs?.title ? { title: String(n.attrs.title) } : {}),
|
|
304
|
+
}
|
|
285
305
|
case "gbColumns":
|
|
286
306
|
return {
|
|
287
307
|
type: "columns",
|
package/src/editor/nodes.tsx
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
ChevronDown,
|
|
14
14
|
Info,
|
|
15
15
|
Link2,
|
|
16
|
+
FileCode2,
|
|
16
17
|
Plus,
|
|
17
18
|
X,
|
|
18
19
|
XCircle,
|
|
@@ -21,7 +22,8 @@ import {
|
|
|
21
22
|
import { resolveAsset } from "@brett_lamy/docstream/assets"
|
|
22
23
|
import { OpenApiOperation } from "@brett_lamy/docstream/openapi"
|
|
23
24
|
import type { HintStyle } from "@brett_lamy/docstream/gitbook"
|
|
24
|
-
import { ReplayPreview,
|
|
25
|
+
import { ReplayPreview, isReplayQaUrl } from "@brett_lamy/docstream/replay"
|
|
26
|
+
import { VideoEmbed } from "@brett_lamy/docstream/video"
|
|
25
27
|
|
|
26
28
|
// ---------- Hint ----------
|
|
27
29
|
|
|
@@ -425,6 +427,54 @@ export const GbContentRef = Node.create({
|
|
|
425
427
|
},
|
|
426
428
|
})
|
|
427
429
|
|
|
430
|
+
// ---------- Source ref ----------
|
|
431
|
+
|
|
432
|
+
function SourceRefView({ node, updateAttributes, editor }: NodeViewProps) {
|
|
433
|
+
const editable = editor.isEditable
|
|
434
|
+
return (
|
|
435
|
+
<NodeViewWrapper className="gb-source-ref" contentEditable={false}>
|
|
436
|
+
<FileCode2 className="size-4 shrink-0" />
|
|
437
|
+
{editable ? (
|
|
438
|
+
<>
|
|
439
|
+
<input className="gb-inline-input gb-source-ref-mount" value={node.attrs.mount} placeholder="mount" onChange={(event) => updateAttributes({ mount: event.target.value })} />
|
|
440
|
+
<input className="gb-inline-input gb-source-ref-path" value={node.attrs.path} placeholder="src/Button.tsx" onChange={(event) => updateAttributes({ path: event.target.value })} />
|
|
441
|
+
<input className="gb-inline-input gb-source-ref-export" value={node.attrs.exportName} placeholder="Button" onChange={(event) => updateAttributes({ exportName: event.target.value })} />
|
|
442
|
+
<select className="gb-source-ref-kind" value={node.attrs.kind} onChange={(event) => updateAttributes({ kind: event.target.value })}>
|
|
443
|
+
<option value="component">component</option>
|
|
444
|
+
<option value="story">story</option>
|
|
445
|
+
</select>
|
|
446
|
+
</>
|
|
447
|
+
) : (
|
|
448
|
+
<span>{node.attrs.title || `${node.attrs.path}#${node.attrs.exportName}`}</span>
|
|
449
|
+
)}
|
|
450
|
+
</NodeViewWrapper>
|
|
451
|
+
)
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
export const GbSourceRef = Node.create({
|
|
455
|
+
name: "gbSourceRef",
|
|
456
|
+
group: "block",
|
|
457
|
+
atom: true,
|
|
458
|
+
addAttributes() {
|
|
459
|
+
return {
|
|
460
|
+
mount: { default: "source" },
|
|
461
|
+
path: { default: "" },
|
|
462
|
+
exportName: { default: "default" },
|
|
463
|
+
kind: { default: "component" },
|
|
464
|
+
title: { default: "" },
|
|
465
|
+
}
|
|
466
|
+
},
|
|
467
|
+
parseHTML() {
|
|
468
|
+
return [{ tag: "div[data-gb-source-ref]" }]
|
|
469
|
+
},
|
|
470
|
+
renderHTML({ HTMLAttributes, node }) {
|
|
471
|
+
return ["div", mergeAttributes(HTMLAttributes, { "data-gb-source-ref": `${node.attrs.mount}:${node.attrs.path}` })]
|
|
472
|
+
},
|
|
473
|
+
addNodeView() {
|
|
474
|
+
return ReactNodeViewRenderer(SourceRefView)
|
|
475
|
+
},
|
|
476
|
+
})
|
|
477
|
+
|
|
428
478
|
// ---------- Columns ----------
|
|
429
479
|
|
|
430
480
|
export const GbColumns = Node.create({
|
|
@@ -790,6 +840,7 @@ export const gitbookNodes = [
|
|
|
790
840
|
GbStep,
|
|
791
841
|
GbEmbed,
|
|
792
842
|
GbContentRef,
|
|
843
|
+
GbSourceRef,
|
|
793
844
|
GbColumns,
|
|
794
845
|
GbColumn,
|
|
795
846
|
GbFigure,
|
package/src/index.ts
CHANGED
|
@@ -12,3 +12,5 @@ export { SlashMenu, createSlashMenu, SLASH_ITEMS } from "./editor/slash-menu"
|
|
|
12
12
|
export type { SlashItem } from "./editor/slash-menu"
|
|
13
13
|
export { ReactDemoEditor } from "./editor/ReactDemoEditor"
|
|
14
14
|
export type { ReactDemoEditorProps } from "./editor/ReactDemoEditor"
|
|
15
|
+
export { SourceFileEditor } from "./editor/SourceFileEditor"
|
|
16
|
+
export type { SourceFileEditorProps } from "./editor/SourceFileEditor"
|
package/src/styles.css
CHANGED
|
@@ -48,6 +48,65 @@
|
|
|
48
48
|
color: var(--gb-text);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
.gb-source-ref,
|
|
52
|
+
.gb-source-file-editor-header {
|
|
53
|
+
display: flex;
|
|
54
|
+
align-items: center;
|
|
55
|
+
gap: 0.5rem;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.gb-source-ref {
|
|
59
|
+
border: 1px solid var(--gb-border);
|
|
60
|
+
border-radius: var(--gb-radius);
|
|
61
|
+
padding: 0.65rem 0.8rem;
|
|
62
|
+
background: var(--gb-muted);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.gb-source-ref-path {
|
|
66
|
+
flex: 1;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.gb-source-ref-mount,
|
|
70
|
+
.gb-source-ref-export {
|
|
71
|
+
width: 8rem;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.gb-source-file-editor {
|
|
75
|
+
border: 1px solid var(--gb-border);
|
|
76
|
+
border-radius: var(--gb-radius);
|
|
77
|
+
overflow: hidden;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.gb-source-file-editor-header {
|
|
81
|
+
padding: 0.55rem 0.7rem;
|
|
82
|
+
background: var(--gb-muted);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.gb-source-file-editor-header button {
|
|
86
|
+
margin-left: auto;
|
|
87
|
+
display: inline-flex;
|
|
88
|
+
align-items: center;
|
|
89
|
+
gap: 0.35rem;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.gb-source-file-editor > textarea {
|
|
93
|
+
box-sizing: border-box;
|
|
94
|
+
width: 100%;
|
|
95
|
+
min-height: 16rem;
|
|
96
|
+
border: 0;
|
|
97
|
+
border-top: 1px solid var(--gb-border);
|
|
98
|
+
border-bottom: 1px solid var(--gb-border);
|
|
99
|
+
padding: 0.8rem;
|
|
100
|
+
resize: vertical;
|
|
101
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.gb-source-file-editor-error {
|
|
105
|
+
color: var(--gb-danger-foreground, #b42318);
|
|
106
|
+
padding: 0.6rem 0.8rem;
|
|
107
|
+
white-space: pre-wrap;
|
|
108
|
+
}
|
|
109
|
+
|
|
51
110
|
/* lucide icon sizing (the node views use size-* utility classes) */
|
|
52
111
|
.gb .size-3 { width: 12px; height: 12px; }
|
|
53
112
|
.gb .size-3\.5 { width: 14px; height: 14px; }
|
|
@@ -559,9 +618,9 @@
|
|
|
559
618
|
|
|
560
619
|
.gb-react-demo-editor {
|
|
561
620
|
overflow: hidden;
|
|
562
|
-
border: 1px solid var(--gb-border, var(--border));
|
|
621
|
+
border: 1px solid var(--gb-border, var(--border, #e4e4e7));
|
|
563
622
|
border-radius: 12px;
|
|
564
|
-
background: var(--gb-panel, var(--card));
|
|
623
|
+
background: var(--gb-panel, var(--card, #ffffff));
|
|
565
624
|
}
|
|
566
625
|
.gb-react-demo-editor-source {
|
|
567
626
|
display: grid;
|
|
@@ -569,8 +628,8 @@
|
|
|
569
628
|
min-height: 260px;
|
|
570
629
|
}
|
|
571
630
|
.gb-react-demo-files {
|
|
572
|
-
border-right: 1px solid var(--gb-border, var(--border));
|
|
573
|
-
background: var(--gb-muted, var(--muted));
|
|
631
|
+
border-right: 1px solid var(--gb-border, var(--border, #e4e4e7));
|
|
632
|
+
background: var(--gb-muted, var(--muted, #f4f4f5));
|
|
574
633
|
}
|
|
575
634
|
.gb-react-demo-files-header,
|
|
576
635
|
.gb-react-demo-editor-toolbar {
|
|
@@ -579,19 +638,19 @@
|
|
|
579
638
|
gap: 8px;
|
|
580
639
|
min-height: 40px;
|
|
581
640
|
padding: 8px 10px;
|
|
582
|
-
border-bottom: 1px solid var(--gb-border, var(--border));
|
|
641
|
+
border-bottom: 1px solid var(--gb-border, var(--border, #e4e4e7));
|
|
583
642
|
font-size: 12px;
|
|
584
643
|
}
|
|
585
644
|
.gb-react-demo-files-header svg {
|
|
586
645
|
margin-left: auto;
|
|
587
|
-
color: var(--gb-muted-foreground, var(--muted-foreground));
|
|
646
|
+
color: var(--gb-muted-foreground, var(--muted-foreground, #71717a));
|
|
588
647
|
}
|
|
589
648
|
.gb-react-demo-file {
|
|
590
649
|
display: block;
|
|
591
650
|
width: 100%;
|
|
592
651
|
padding: 8px 10px;
|
|
593
652
|
overflow: hidden;
|
|
594
|
-
color: var(--gb-muted-foreground, var(--muted-foreground));
|
|
653
|
+
color: var(--gb-muted-foreground, var(--muted-foreground, #71717a));
|
|
595
654
|
font-family: ui-monospace, Menlo, monospace;
|
|
596
655
|
font-size: 11px;
|
|
597
656
|
text-align: left;
|
|
@@ -599,8 +658,8 @@
|
|
|
599
658
|
white-space: nowrap;
|
|
600
659
|
}
|
|
601
660
|
.gb-react-demo-file-active {
|
|
602
|
-
color: var(--gb-panel-foreground, var(--foreground));
|
|
603
|
-
background: var(--gb-panel, var(--card));
|
|
661
|
+
color: var(--gb-panel-foreground, var(--foreground, #18181b));
|
|
662
|
+
background: var(--gb-panel, var(--card, #ffffff));
|
|
604
663
|
}
|
|
605
664
|
.gb-react-demo-editor-pane {
|
|
606
665
|
display: flex;
|
|
@@ -609,7 +668,7 @@
|
|
|
609
668
|
}
|
|
610
669
|
.gb-react-demo-editor-toolbar code {
|
|
611
670
|
overflow: hidden;
|
|
612
|
-
color: var(--gb-muted-foreground, var(--muted-foreground));
|
|
671
|
+
color: var(--gb-muted-foreground, var(--muted-foreground, #71717a));
|
|
613
672
|
text-overflow: ellipsis;
|
|
614
673
|
white-space: nowrap;
|
|
615
674
|
}
|
|
@@ -618,10 +677,10 @@
|
|
|
618
677
|
align-items: center;
|
|
619
678
|
gap: 5px;
|
|
620
679
|
margin-left: auto;
|
|
621
|
-
border: 1px solid var(--gb-border, var(--border));
|
|
680
|
+
border: 1px solid var(--gb-border, var(--border, #e4e4e7));
|
|
622
681
|
border-radius: 6px;
|
|
623
682
|
padding: 4px 8px;
|
|
624
|
-
color: var(--gb-panel-foreground, var(--foreground));
|
|
683
|
+
color: var(--gb-panel-foreground, var(--foreground, #18181b));
|
|
625
684
|
font-size: 11px;
|
|
626
685
|
}
|
|
627
686
|
.gb-react-demo-preview-button:disabled { opacity: 0.5; }
|
|
@@ -633,15 +692,15 @@
|
|
|
633
692
|
border: 0;
|
|
634
693
|
padding: 14px;
|
|
635
694
|
outline: none;
|
|
636
|
-
color: var(--gb-panel-foreground, var(--foreground));
|
|
637
|
-
background: var(--gb-panel, var(--card));
|
|
695
|
+
color: var(--gb-panel-foreground, var(--foreground, #18181b));
|
|
696
|
+
background: var(--gb-panel, var(--card, #ffffff));
|
|
638
697
|
font-family: ui-monospace, Menlo, monospace;
|
|
639
698
|
font-size: 12px;
|
|
640
699
|
line-height: 1.6;
|
|
641
700
|
}
|
|
642
701
|
.gb-react-demo-editor-empty {
|
|
643
702
|
padding: 18px;
|
|
644
|
-
color: var(--gb-muted-foreground, var(--muted-foreground));
|
|
703
|
+
color: var(--gb-muted-foreground, var(--muted-foreground, #71717a));
|
|
645
704
|
font-size: 12px;
|
|
646
705
|
text-align: center;
|
|
647
706
|
}
|
|
@@ -651,7 +710,7 @@
|
|
|
651
710
|
display: flex;
|
|
652
711
|
overflow-x: auto;
|
|
653
712
|
border-right: 0;
|
|
654
|
-
border-bottom: 1px solid var(--gb-border, var(--border));
|
|
713
|
+
border-bottom: 1px solid var(--gb-border, var(--border, #e4e4e7));
|
|
655
714
|
}
|
|
656
715
|
.gb-react-demo-files-header { flex: 0 0 auto; border-bottom: 0; }
|
|
657
716
|
.gb-react-demo-file { width: auto; flex: 0 0 auto; }
|