@bendyline/squisq-editor-react 0.1.1 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/EditorContext.d.ts +75 -0
- package/dist/EditorContext.d.ts.map +1 -0
- package/dist/EditorContext.js +158 -0
- package/dist/EditorContext.js.map +1 -0
- package/dist/EditorShell.d.ts +34 -0
- package/dist/EditorShell.d.ts.map +1 -0
- package/dist/EditorShell.js +59 -0
- package/dist/EditorShell.js.map +1 -0
- package/dist/PreviewPanel.d.ts +33 -0
- package/dist/PreviewPanel.d.ts.map +1 -0
- package/dist/PreviewPanel.js +385 -0
- package/dist/PreviewPanel.js.map +1 -0
- package/dist/RawEditor.d.ts +25 -0
- package/dist/RawEditor.d.ts.map +1 -0
- package/dist/RawEditor.js +100 -0
- package/dist/RawEditor.js.map +1 -0
- package/dist/StatusBar.d.ts +15 -0
- package/dist/StatusBar.d.ts.map +1 -0
- package/dist/StatusBar.js +24 -0
- package/dist/StatusBar.js.map +1 -0
- package/dist/TemplateAnnotation.d.ts +20 -0
- package/dist/TemplateAnnotation.d.ts.map +1 -0
- package/dist/TemplateAnnotation.js +69 -0
- package/dist/TemplateAnnotation.js.map +1 -0
- package/dist/Toolbar.d.ts +19 -0
- package/dist/Toolbar.d.ts.map +1 -0
- package/dist/Toolbar.js +350 -0
- package/dist/Toolbar.js.map +1 -0
- package/dist/ViewSwitcher.d.ts +14 -0
- package/dist/ViewSwitcher.d.ts.map +1 -0
- package/dist/ViewSwitcher.js +20 -0
- package/dist/ViewSwitcher.js.map +1 -0
- package/dist/WysiwygEditor.d.ts +28 -0
- package/dist/WysiwygEditor.d.ts.map +1 -0
- package/dist/WysiwygEditor.js +111 -0
- package/dist/WysiwygEditor.js.map +1 -0
- package/dist/index.d.ts +36 -268
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -3824
- package/dist/index.js.map +1 -1
- package/dist/tiptapBridge.d.ts +24 -0
- package/dist/tiptapBridge.d.ts.map +1 -0
- package/dist/tiptapBridge.js +358 -0
- package/dist/tiptapBridge.js.map +1 -0
- package/package.json +4 -5
- package/src/Toolbar.tsx +50 -45
- package/src/styles/editor.css +21 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EditorContext
|
|
3
|
+
*
|
|
4
|
+
* Shared React context that synchronizes state across all three editor views
|
|
5
|
+
* (Raw/Monaco, WYSIWYG/Tiptap, Preview/DocPlayer). When any view modifies the
|
|
6
|
+
* markdown source, the context re-parses and regenerates the MarkdownDocument
|
|
7
|
+
* and Doc so all views stay in sync.
|
|
8
|
+
*/
|
|
9
|
+
import { type ReactNode } from 'react';
|
|
10
|
+
import type { Doc } from '@bendyline/squisq/schemas';
|
|
11
|
+
import type { MarkdownDocument } from '@bendyline/squisq/markdown';
|
|
12
|
+
import type { Editor as TiptapEditor } from '@tiptap/core';
|
|
13
|
+
import type { editor as MonacoEditorNs } from 'monaco-editor';
|
|
14
|
+
/** Monaco standalone code editor instance type */
|
|
15
|
+
type MonacoEditor = MonacoEditorNs.IStandaloneCodeEditor;
|
|
16
|
+
export type EditorView = 'raw' | 'wysiwyg' | 'preview';
|
|
17
|
+
export type EditorTheme = 'light' | 'dark';
|
|
18
|
+
export interface EditorState {
|
|
19
|
+
/** Raw markdown source string */
|
|
20
|
+
markdownSource: string;
|
|
21
|
+
/** Parsed markdown document (JSON DOM) */
|
|
22
|
+
markdownDoc: MarkdownDocument | null;
|
|
23
|
+
/** Generated Doc (block hierarchy) */
|
|
24
|
+
doc: Doc | null;
|
|
25
|
+
/** Currently active editor view */
|
|
26
|
+
activeView: EditorView;
|
|
27
|
+
/** Parse error, if any */
|
|
28
|
+
parseError: string | null;
|
|
29
|
+
/** Whether a parse is pending */
|
|
30
|
+
isParsing: boolean;
|
|
31
|
+
/** Current color theme */
|
|
32
|
+
theme: EditorTheme;
|
|
33
|
+
}
|
|
34
|
+
export interface EditorActions {
|
|
35
|
+
/** Set markdown source and trigger re-parse */
|
|
36
|
+
setMarkdownSource: (source: string) => void;
|
|
37
|
+
/** Set markdown from a MarkdownDocument (e.g. from WYSIWYG) */
|
|
38
|
+
setMarkdownDoc: (doc: MarkdownDocument) => void;
|
|
39
|
+
/** Switch the active view */
|
|
40
|
+
setActiveView: (view: EditorView) => void;
|
|
41
|
+
/** Register / unregister the Tiptap editor instance (called by WysiwygEditor) */
|
|
42
|
+
setTiptapEditor: (editor: TiptapEditor | null) => void;
|
|
43
|
+
/** Register / unregister the Monaco editor instance (called by RawEditor) */
|
|
44
|
+
setMonacoEditor: (editor: MonacoEditor | null) => void;
|
|
45
|
+
/** Set the color theme */
|
|
46
|
+
setTheme: (theme: EditorTheme) => void;
|
|
47
|
+
}
|
|
48
|
+
export interface EditorContextValue extends EditorState, EditorActions {
|
|
49
|
+
/** The live Tiptap editor instance (null when WYSIWYG is not mounted) */
|
|
50
|
+
tiptapEditor: TiptapEditor | null;
|
|
51
|
+
/** The live Monaco editor instance (null when Raw is not mounted) */
|
|
52
|
+
monacoEditor: MonacoEditor | null;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Hook to access the editor context. Must be used within an EditorProvider.
|
|
56
|
+
*/
|
|
57
|
+
export declare function useEditorContext(): EditorContextValue;
|
|
58
|
+
export interface EditorProviderProps {
|
|
59
|
+
/** Initial markdown content */
|
|
60
|
+
initialMarkdown?: string;
|
|
61
|
+
/** Initial active view */
|
|
62
|
+
initialView?: EditorView;
|
|
63
|
+
/** Article ID used when generating the Doc */
|
|
64
|
+
articleId?: string;
|
|
65
|
+
/** Color theme */
|
|
66
|
+
theme?: EditorTheme;
|
|
67
|
+
children: ReactNode;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Provides shared editor state to all child components.
|
|
71
|
+
* Automatically parses markdown and generates a Doc whenever the source changes.
|
|
72
|
+
*/
|
|
73
|
+
export declare function EditorProvider({ initialMarkdown, initialView, articleId, theme: initialTheme, children, }: EditorProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
74
|
+
export {};
|
|
75
|
+
//# sourceMappingURL=EditorContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EditorContext.d.ts","sourceRoot":"","sources":["../src/EditorContext.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAGnE,OAAO,KAAK,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,MAAM,IAAI,cAAc,EAAE,MAAM,eAAe,CAAC;AAE9D,kDAAkD;AAClD,KAAK,YAAY,GAAG,cAAc,CAAC,qBAAqB,CAAC;AAIzD,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,SAAS,GAAG,SAAS,CAAC;AACvD,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;AAE3C,MAAM,WAAW,WAAW;IAC1B,iCAAiC;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,0CAA0C;IAC1C,WAAW,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACrC,sCAAsC;IACtC,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC;IAChB,mCAAmC;IACnC,UAAU,EAAE,UAAU,CAAC;IACvB,0BAA0B;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,iCAAiC;IACjC,SAAS,EAAE,OAAO,CAAC;IACnB,0BAA0B;IAC1B,KAAK,EAAE,WAAW,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,+CAA+C;IAC/C,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,+DAA+D;IAC/D,cAAc,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAChD,6BAA6B;IAC7B,aAAa,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IAC1C,iFAAiF;IACjF,eAAe,EAAE,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,KAAK,IAAI,CAAC;IACvD,6EAA6E;IAC7E,eAAe,EAAE,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,KAAK,IAAI,CAAC;IACvD,0BAA0B;IAC1B,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;CACxC;AAED,MAAM,WAAW,kBAAmB,SAAQ,WAAW,EAAE,aAAa;IACpE,yEAAyE;IACzE,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,qEAAqE;IACrE,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;CACnC;AAMD;;GAEG;AAEH,wBAAgB,gBAAgB,IAAI,kBAAkB,CAMrD;AAID,MAAM,WAAW,mBAAmB;IAClC,+BAA+B;IAC/B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,0BAA0B;IAC1B,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB;IAClB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAC7B,eAAoB,EACpB,WAAmB,EACnB,SAAsB,EACtB,KAAK,EAAE,YAAsB,EAC7B,QAAQ,GACT,EAAE,mBAAmB,2CAyIrB"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* EditorContext
|
|
4
|
+
*
|
|
5
|
+
* Shared React context that synchronizes state across all three editor views
|
|
6
|
+
* (Raw/Monaco, WYSIWYG/Tiptap, Preview/DocPlayer). When any view modifies the
|
|
7
|
+
* markdown source, the context re-parses and regenerates the MarkdownDocument
|
|
8
|
+
* and Doc so all views stay in sync.
|
|
9
|
+
*/
|
|
10
|
+
import { createContext, useContext, useState, useCallback, useMemo, useRef, useEffect, } from 'react';
|
|
11
|
+
import { parseMarkdown, stringifyMarkdown } from '@bendyline/squisq/markdown';
|
|
12
|
+
import { markdownToDoc } from '@bendyline/squisq/doc';
|
|
13
|
+
// ─── Context ─────────────────────────────────────────────
|
|
14
|
+
const EditorContext = createContext(null);
|
|
15
|
+
/**
|
|
16
|
+
* Hook to access the editor context. Must be used within an EditorProvider.
|
|
17
|
+
*/
|
|
18
|
+
// eslint-disable-next-line react-refresh/only-export-components
|
|
19
|
+
export function useEditorContext() {
|
|
20
|
+
const ctx = useContext(EditorContext);
|
|
21
|
+
if (!ctx) {
|
|
22
|
+
throw new Error('useEditorContext must be used within an <EditorProvider>');
|
|
23
|
+
}
|
|
24
|
+
return ctx;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Provides shared editor state to all child components.
|
|
28
|
+
* Automatically parses markdown and generates a Doc whenever the source changes.
|
|
29
|
+
*/
|
|
30
|
+
export function EditorProvider({ initialMarkdown = '', initialView = 'raw', articleId = 'untitled', theme: initialTheme = 'light', children, }) {
|
|
31
|
+
const [markdownSource, setMarkdownSourceRaw] = useState(initialMarkdown);
|
|
32
|
+
const [markdownDoc, setMarkdownDocState] = useState(null);
|
|
33
|
+
const [doc, setDoc] = useState(null);
|
|
34
|
+
const [activeView, setActiveView] = useState(initialView);
|
|
35
|
+
const [parseError, setParseError] = useState(null);
|
|
36
|
+
const [isParsing, setIsParsing] = useState(false);
|
|
37
|
+
const [theme, setTheme] = useState(initialTheme);
|
|
38
|
+
const [tiptapEditor, setTiptapEditor] = useState(null);
|
|
39
|
+
const [monacoEditor, setMonacoEditor] = useState(null);
|
|
40
|
+
const articleIdRef = useRef(articleId);
|
|
41
|
+
articleIdRef.current = articleId;
|
|
42
|
+
// Sync theme when prop changes
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
setTheme(initialTheme);
|
|
45
|
+
}, [initialTheme]);
|
|
46
|
+
// Debounced parse on markdown source change
|
|
47
|
+
const parseTimeoutRef = useRef(null);
|
|
48
|
+
const doParse = useCallback((source) => {
|
|
49
|
+
setIsParsing(true);
|
|
50
|
+
try {
|
|
51
|
+
const parsed = parseMarkdown(source);
|
|
52
|
+
setMarkdownDocState(parsed);
|
|
53
|
+
setParseError(null);
|
|
54
|
+
// Generate Doc from parsed markdown
|
|
55
|
+
try {
|
|
56
|
+
const generatedDoc = markdownToDoc(parsed, {
|
|
57
|
+
articleId: articleIdRef.current,
|
|
58
|
+
});
|
|
59
|
+
setDoc(generatedDoc);
|
|
60
|
+
}
|
|
61
|
+
catch (docErr) {
|
|
62
|
+
// Doc generation can fail but markdown parse succeeded
|
|
63
|
+
setDoc(null);
|
|
64
|
+
console.warn('Doc generation failed:', docErr instanceof Error ? docErr.message : docErr);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
setParseError(err instanceof Error ? err.message : 'Parse error');
|
|
69
|
+
setMarkdownDocState(null);
|
|
70
|
+
setDoc(null);
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
setIsParsing(false);
|
|
74
|
+
}
|
|
75
|
+
}, []);
|
|
76
|
+
// Parse on source changes with debounce
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
if (parseTimeoutRef.current) {
|
|
79
|
+
clearTimeout(parseTimeoutRef.current);
|
|
80
|
+
}
|
|
81
|
+
parseTimeoutRef.current = setTimeout(() => {
|
|
82
|
+
doParse(markdownSource);
|
|
83
|
+
}, 150);
|
|
84
|
+
return () => {
|
|
85
|
+
if (parseTimeoutRef.current) {
|
|
86
|
+
clearTimeout(parseTimeoutRef.current);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
}, [markdownSource, doParse]);
|
|
90
|
+
// Initial parse
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
if (initialMarkdown) {
|
|
93
|
+
doParse(initialMarkdown);
|
|
94
|
+
}
|
|
95
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
96
|
+
}, []);
|
|
97
|
+
const setMarkdownSource = useCallback((source) => {
|
|
98
|
+
setMarkdownSourceRaw(source);
|
|
99
|
+
}, []);
|
|
100
|
+
const setMarkdownDoc = useCallback((newDoc) => {
|
|
101
|
+
setMarkdownDocState(newDoc);
|
|
102
|
+
// Stringify to update the raw source
|
|
103
|
+
try {
|
|
104
|
+
const newSource = stringifyMarkdown(newDoc);
|
|
105
|
+
setMarkdownSourceRaw(newSource);
|
|
106
|
+
setParseError(null);
|
|
107
|
+
// Generate Doc
|
|
108
|
+
try {
|
|
109
|
+
const generatedDoc = markdownToDoc(newDoc, {
|
|
110
|
+
articleId: articleIdRef.current,
|
|
111
|
+
});
|
|
112
|
+
setDoc(generatedDoc);
|
|
113
|
+
}
|
|
114
|
+
catch (docErr) {
|
|
115
|
+
setDoc(null);
|
|
116
|
+
console.warn('Doc generation failed:', docErr instanceof Error ? docErr.message : docErr);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
setParseError(err instanceof Error ? err.message : 'Stringify error');
|
|
121
|
+
}
|
|
122
|
+
}, []);
|
|
123
|
+
const value = useMemo(() => ({
|
|
124
|
+
markdownSource,
|
|
125
|
+
markdownDoc,
|
|
126
|
+
doc,
|
|
127
|
+
activeView,
|
|
128
|
+
parseError,
|
|
129
|
+
isParsing,
|
|
130
|
+
theme,
|
|
131
|
+
tiptapEditor,
|
|
132
|
+
monacoEditor,
|
|
133
|
+
setMarkdownSource,
|
|
134
|
+
setMarkdownDoc,
|
|
135
|
+
setActiveView,
|
|
136
|
+
setTiptapEditor,
|
|
137
|
+
setMonacoEditor,
|
|
138
|
+
setTheme,
|
|
139
|
+
}), [
|
|
140
|
+
markdownSource,
|
|
141
|
+
markdownDoc,
|
|
142
|
+
doc,
|
|
143
|
+
activeView,
|
|
144
|
+
parseError,
|
|
145
|
+
isParsing,
|
|
146
|
+
theme,
|
|
147
|
+
tiptapEditor,
|
|
148
|
+
monacoEditor,
|
|
149
|
+
setMarkdownSource,
|
|
150
|
+
setMarkdownDoc,
|
|
151
|
+
setActiveView,
|
|
152
|
+
setTiptapEditor,
|
|
153
|
+
setMonacoEditor,
|
|
154
|
+
setTheme,
|
|
155
|
+
]);
|
|
156
|
+
return _jsx(EditorContext.Provider, { value: value, children: children });
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=EditorContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EditorContext.js","sourceRoot":"","sources":["../src/EditorContext.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EditorShell
|
|
3
|
+
*
|
|
4
|
+
* Top-level shell component that composes the Toolbar, ViewSwitcher, editor
|
|
5
|
+
* views, and StatusBar into a complete editing experience. Wraps everything
|
|
6
|
+
* in an EditorProvider for shared state.
|
|
7
|
+
*/
|
|
8
|
+
import { type EditorView } from './EditorContext';
|
|
9
|
+
export type { EditorTheme } from './EditorContext';
|
|
10
|
+
export interface EditorShellProps {
|
|
11
|
+
/** Initial markdown content */
|
|
12
|
+
initialMarkdown?: string;
|
|
13
|
+
/** Initial active view */
|
|
14
|
+
/** Initial active view (default: 'wysiwyg') */
|
|
15
|
+
initialView?: EditorView;
|
|
16
|
+
/** Article ID for Doc generation */
|
|
17
|
+
articleId?: string;
|
|
18
|
+
/** Base path for media URLs in preview */
|
|
19
|
+
basePath?: string;
|
|
20
|
+
/** Called when markdown source changes */
|
|
21
|
+
onChange?: (source: string) => void;
|
|
22
|
+
/** Color theme: 'light' or 'dark' (default: 'light') */
|
|
23
|
+
theme?: 'light' | 'dark';
|
|
24
|
+
/** Additional class name */
|
|
25
|
+
className?: string;
|
|
26
|
+
/** CSS height for the shell container (default: '100vh') */
|
|
27
|
+
height?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Complete markdown editor shell with toolbar, view switcher, and three
|
|
31
|
+
* editing modes: Raw (Monaco), WYSIWYG (Tiptap), and Preview.
|
|
32
|
+
*/
|
|
33
|
+
export declare function EditorShell({ initialMarkdown, initialView, articleId, basePath, onChange, theme, className, height, }: EditorShellProps): import("react/jsx-runtime").JSX.Element;
|
|
34
|
+
//# sourceMappingURL=EditorShell.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EditorShell.d.ts","sourceRoot":"","sources":["../src/EditorShell.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAoC,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAOpF,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,MAAM,WAAW,gBAAgB;IAC/B,+BAA+B;IAC/B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,0BAA0B;IAC1B,+CAA+C;IAC/C,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,wDAAwD;IACxD,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACzB,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAC1B,eAAoB,EACpB,WAAuB,EACvB,SAAsB,EACtB,QAAc,EACd,QAAQ,EACR,KAAe,EACf,SAAS,EACT,MAAgB,GACjB,EAAE,gBAAgB,2CAgBlB"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* EditorShell
|
|
4
|
+
*
|
|
5
|
+
* Top-level shell component that composes the Toolbar, ViewSwitcher, editor
|
|
6
|
+
* views, and StatusBar into a complete editing experience. Wraps everything
|
|
7
|
+
* in an EditorProvider for shared state.
|
|
8
|
+
*/
|
|
9
|
+
import { useEffect } from 'react';
|
|
10
|
+
import { EditorProvider, useEditorContext } from './EditorContext';
|
|
11
|
+
import { Toolbar } from './Toolbar';
|
|
12
|
+
import { StatusBar } from './StatusBar';
|
|
13
|
+
import { RawEditor } from './RawEditor';
|
|
14
|
+
import { WysiwygEditor } from './WysiwygEditor';
|
|
15
|
+
import { PreviewPanel } from './PreviewPanel';
|
|
16
|
+
/**
|
|
17
|
+
* Complete markdown editor shell with toolbar, view switcher, and three
|
|
18
|
+
* editing modes: Raw (Monaco), WYSIWYG (Tiptap), and Preview.
|
|
19
|
+
*/
|
|
20
|
+
export function EditorShell({ initialMarkdown = '', initialView = 'wysiwyg', articleId = 'untitled', basePath = '/', onChange, theme = 'light', className, height = '100vh', }) {
|
|
21
|
+
return (_jsx(EditorProvider, { initialMarkdown: initialMarkdown, initialView: initialView, articleId: articleId, theme: theme, children: _jsx(EditorShellInner, { basePath: basePath, onChange: onChange, className: className, height: height }) }));
|
|
22
|
+
}
|
|
23
|
+
function EditorShellInner({ basePath, onChange, className, height }) {
|
|
24
|
+
const { activeView, markdownSource, theme } = useEditorContext();
|
|
25
|
+
// Notify parent of changes
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
onChange?.(markdownSource);
|
|
28
|
+
}, [markdownSource, onChange]);
|
|
29
|
+
// Keyboard shortcuts for view switching
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
const handler = (e) => {
|
|
32
|
+
if (e.ctrlKey || e.metaKey) {
|
|
33
|
+
switch (e.key) {
|
|
34
|
+
case '1':
|
|
35
|
+
e.preventDefault();
|
|
36
|
+
document.querySelector('[data-view="wysiwyg"]')?.click();
|
|
37
|
+
break;
|
|
38
|
+
case '2':
|
|
39
|
+
e.preventDefault();
|
|
40
|
+
document.querySelector('[data-view="raw"]')?.click();
|
|
41
|
+
break;
|
|
42
|
+
case '3':
|
|
43
|
+
e.preventDefault();
|
|
44
|
+
document.querySelector('[data-view="preview"]')?.click();
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
window.addEventListener('keydown', handler);
|
|
50
|
+
return () => window.removeEventListener('keydown', handler);
|
|
51
|
+
}, []);
|
|
52
|
+
return (_jsxs("div", { className: `squisq-editor-shell ${className || ''}`, "data-theme": theme, style: {
|
|
53
|
+
display: 'flex',
|
|
54
|
+
flexDirection: 'column',
|
|
55
|
+
height,
|
|
56
|
+
overflow: 'hidden',
|
|
57
|
+
}, children: [_jsx("div", { className: "squisq-editor-header", children: _jsx(Toolbar, {}) }), _jsxs("div", { className: "squisq-editor-content", style: { flex: 1, overflow: 'hidden', position: 'relative' }, children: [activeView === 'raw' && _jsx(RawEditor, { theme: theme === 'dark' ? 'vs-dark' : 'vs' }), activeView === 'wysiwyg' && _jsx(WysiwygEditor, {}), activeView === 'preview' && _jsx(PreviewPanel, { basePath: basePath })] }), _jsx(StatusBar, {})] }));
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=EditorShell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EditorShell.js","sourceRoot":"","sources":["../src/EditorShell.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PreviewPanel
|
|
3
|
+
*
|
|
4
|
+
* Renders a live preview of the current markdown document as a slideshow
|
|
5
|
+
* using the DocPlayer component from @bendyline/squisq-react.
|
|
6
|
+
*
|
|
7
|
+
* The markdown-derived Doc (from markdownToDoc) contains hierarchical blocks
|
|
8
|
+
* with template names, heading text, and body content — but no audio or
|
|
9
|
+
* visual layers. This component bridges the gap by:
|
|
10
|
+
*
|
|
11
|
+
* 1. Flattening the block tree into a linear slide sequence
|
|
12
|
+
* 2. Converting each block into a TemplateBlock-compatible object
|
|
13
|
+
* (mapping heading text → title, templateOverrides → template fields)
|
|
14
|
+
* 3. Synthesizing a dummy audio segment so DocPlayer's timing works
|
|
15
|
+
* (the player enters fallback-timer mode when audio can't load)
|
|
16
|
+
* 4. Passing the prepared Doc to DocPlayer for SVG-based rendering
|
|
17
|
+
*/
|
|
18
|
+
export interface PreviewPanelProps {
|
|
19
|
+
/** Base path for resolving media URLs in DocPlayer */
|
|
20
|
+
basePath?: string;
|
|
21
|
+
/** Additional class name for the container */
|
|
22
|
+
className?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Live preview panel that renders the current document as a slideshow.
|
|
26
|
+
* Uses DocPlayer from @bendyline/squisq-react for SVG block rendering
|
|
27
|
+
* with template expansion, transitions, and playback controls.
|
|
28
|
+
*
|
|
29
|
+
* Includes a viewport format dropdown above the player. The default
|
|
30
|
+
* format can be hinted via YAML frontmatter `document-render-as:`.
|
|
31
|
+
*/
|
|
32
|
+
export declare function PreviewPanel({ basePath, className }: PreviewPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
33
|
+
//# sourceMappingURL=PreviewPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PreviewPanel.d.ts","sourceRoot":"","sources":["../src/PreviewPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAcH,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA+OD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,EAAE,QAAc,EAAE,SAAS,EAAE,EAAE,iBAAiB,2CAuR5E"}
|