@bendyline/squisq-editor-react 1.6.0 → 1.6.2
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 +57 -10
- package/dist/index.d.ts +476 -105
- package/dist/index.js +8703 -6741
- package/dist/index.js.map +1 -1
- package/dist/styles/fa-brands-400-AHOAZHCU.woff2 +0 -0
- package/dist/styles/fa-regular-400-VRZYIBIZ.woff2 +0 -0
- package/dist/styles/fa-solid-900-MDEYK55F.woff2 +0 -0
- package/dist/styles/fa-v4compatibility-ETEVP6IB.woff2 +0 -0
- package/dist/styles/index.css +14617 -0
- package/package.json +15 -7
- package/src/BlockPropertiesPopover.tsx +23 -7
- package/src/EditorContext.tsx +22 -16
- package/src/EditorShell.tsx +121 -35
- package/src/MediaBin.tsx +171 -28
- package/src/OutlinePanel.tsx +26 -4
- package/src/PreviewControls.tsx +475 -145
- package/src/PreviewPanel.tsx +17 -9
- package/src/RawEditor.tsx +10 -4
- package/src/TemplateAnnotation.ts +22 -7
- package/src/TemplateContentPreview.tsx +56 -0
- package/src/TemplatePicker.tsx +295 -128
- package/src/ThemeCustomizerPanel.tsx +22 -15
- package/src/Toolbar.tsx +547 -217
- package/src/TransitionPicker.tsx +8 -1
- package/src/VersionHistoryPanel.tsx +2 -2
- package/src/ViewSwitcher.tsx +4 -4
- package/src/WysiwygEditor.tsx +45 -3
- package/src/__tests__/buildPreviewDocTransition.test.ts +1 -2
- package/src/__tests__/codeContextSectionView.test.tsx +95 -0
- package/src/__tests__/codeContextZoneManager.test.ts +127 -0
- package/src/__tests__/diffContextSections.test.ts +39 -0
- package/src/__tests__/editorShellCodeContext.test.tsx +86 -0
- package/src/__tests__/editorShellProps.test.tsx +363 -0
- package/src/__tests__/headingTransition.test.ts +59 -9
- package/src/__tests__/imageEditorShell.test.tsx +23 -0
- package/src/__tests__/mediaReferences.test.ts +82 -0
- package/src/__tests__/previewControls.test.tsx +163 -0
- package/src/__tests__/templateAnnotationRoundTrip.test.ts +23 -2
- package/src/__tests__/templateContentPreview.test.ts +101 -0
- package/src/__tests__/tiptapBridge.test.ts +47 -0
- package/src/__tests__/useJsonEditorTokens.test.ts +59 -0
- package/src/__tests__/useMediaRecorder.test.ts +17 -0
- package/src/codeContext/CodeContextSectionView.tsx +124 -0
- package/src/codeContext/CodeContextZoneManager.ts +149 -0
- package/src/codeContext/CodeContextZones.tsx +121 -0
- package/src/codeContext/diffContextSections.ts +38 -0
- package/src/codeContext/types.ts +75 -0
- package/src/diagram/DiagramWidget.tsx +6 -4
- package/src/headingTransition.ts +96 -21
- package/src/index.ts +34 -2
- package/src/jsonEditor/useJsonEditorTokens.ts +13 -43
- package/src/mediaReferences.ts +299 -0
- package/src/recorder/hooks/useMediaRecorder.ts +9 -10
- package/src/scene/Scene.tsx +53 -7
- package/src/scene/SceneBlockWidget.tsx +6 -3
- package/src/scene/SceneSelection.tsx +19 -15
- package/src/scene/SceneSideToolbar.tsx +89 -0
- package/src/scene/layers/DiagramEdges.tsx +4 -3
- package/src/scene/layers/edgeGeometry.ts +23 -4
- package/src/scene/scene.css +142 -2
- package/src/scene/tools/ConnectTool.ts +113 -24
- package/src/scene/tools/DrawingConnectTool.ts +86 -16
- package/src/scene/tools/SceneTool.ts +2 -0
- package/src/styles/code-context.css +155 -0
- package/src/styles/editor.css +991 -84
- package/src/styles/index.css +1 -0
- package/src/templateContentPreviewResolver.ts +353 -0
- package/src/tiptapBridge.ts +60 -33
package/src/PreviewPanel.tsx
CHANGED
|
@@ -48,6 +48,8 @@ export function PreviewPanel({ basePath = '/', className, workspaceContainer }:
|
|
|
48
48
|
activeTheme,
|
|
49
49
|
activeTransformStyle,
|
|
50
50
|
activeCaptionStyle,
|
|
51
|
+
activeCaptionsEnabled,
|
|
52
|
+
activeCoverSlide,
|
|
51
53
|
} = usePreviewSettings();
|
|
52
54
|
|
|
53
55
|
// Build the player-ready Doc whenever the parsed doc changes.
|
|
@@ -108,10 +110,15 @@ export function PreviewPanel({ basePath = '/', className, workspaceContainer }:
|
|
|
108
110
|
);
|
|
109
111
|
}
|
|
110
112
|
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
// The public DisplayMode values predate the current labels: raw `page`
|
|
114
|
+
// is the plain Document preview, while raw `linear` is the styled Page view.
|
|
115
|
+
const isDocumentMode = activeDisplayMode === 'page';
|
|
116
|
+
const isPageMode = activeDisplayMode === 'linear';
|
|
117
|
+
|
|
118
|
+
// Document mode renders directly from markdown — it doesn't depend on the
|
|
119
|
+
// parsed Doc tree or the player preview build, so let it fall through even
|
|
120
|
+
// when those aren't ready yet.
|
|
121
|
+
if (!previewDoc && !isDocumentMode) {
|
|
115
122
|
return (
|
|
116
123
|
<div className={`squisq-preview-status ${className || ''}`} data-testid="preview-panel">
|
|
117
124
|
<p>No content to preview. Start typing in the editor.</p>
|
|
@@ -119,8 +126,7 @@ export function PreviewPanel({ basePath = '/', className, workspaceContainer }:
|
|
|
119
126
|
);
|
|
120
127
|
}
|
|
121
128
|
|
|
122
|
-
const fillsContainer =
|
|
123
|
-
activeDisplayMode === 'linear' || activeDisplayMode === 'page' ? 'stretch' : 'center';
|
|
129
|
+
const fillsContainer = isDocumentMode || isPageMode ? 'stretch' : 'center';
|
|
124
130
|
|
|
125
131
|
return (
|
|
126
132
|
<div
|
|
@@ -147,7 +153,7 @@ export function PreviewPanel({ basePath = '/', className, workspaceContainer }:
|
|
|
147
153
|
minHeight: 0,
|
|
148
154
|
}}
|
|
149
155
|
>
|
|
150
|
-
{
|
|
156
|
+
{isDocumentMode ? (
|
|
151
157
|
<PlainHtmlPreview
|
|
152
158
|
markdown={markdownSource}
|
|
153
159
|
title={(doc?.frontmatter?.title as string | undefined) ?? undefined}
|
|
@@ -155,7 +161,7 @@ export function PreviewPanel({ basePath = '/', className, workspaceContainer }:
|
|
|
155
161
|
mediaRevision={mediaRevision}
|
|
156
162
|
theme={activeTheme}
|
|
157
163
|
/>
|
|
158
|
-
) :
|
|
164
|
+
) : isPageMode ? (
|
|
159
165
|
<LinearDocView
|
|
160
166
|
doc={doc!}
|
|
161
167
|
basePath={basePath}
|
|
@@ -164,7 +170,7 @@ export function PreviewPanel({ basePath = '/', className, workspaceContainer }:
|
|
|
164
170
|
/>
|
|
165
171
|
) : (
|
|
166
172
|
<DocPlayer
|
|
167
|
-
|
|
173
|
+
doc={previewDoc!}
|
|
168
174
|
basePath={basePath}
|
|
169
175
|
showControls
|
|
170
176
|
muted
|
|
@@ -172,6 +178,8 @@ export function PreviewPanel({ basePath = '/', className, workspaceContainer }:
|
|
|
172
178
|
displayMode={activeDisplayMode}
|
|
173
179
|
theme={activeTheme}
|
|
174
180
|
captionStyle={activeCaptionStyle}
|
|
181
|
+
captionsEnabled={activeCaptionsEnabled}
|
|
182
|
+
showCoverSlide={activeCoverSlide}
|
|
175
183
|
/>
|
|
176
184
|
)}
|
|
177
185
|
</div>
|
package/src/RawEditor.tsx
CHANGED
|
@@ -56,8 +56,14 @@ const SQUISQ_THEMES: Record<string, string> = {
|
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
export interface RawEditorProps {
|
|
59
|
-
/**
|
|
60
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Monaco editor theme name (default: `'vs'`). Accepts Monaco's built-in
|
|
61
|
+
* theme ids (`'vs'`, `'vs-dark'`, `'hc-black'`) — which are transparently
|
|
62
|
+
* mapped to the Squisq-tinted variants — or any custom theme registered
|
|
63
|
+
* via `monaco.editor.defineTheme`. This is the *code editor* color
|
|
64
|
+
* theme, distinct from the shell's light/dark `colorScheme`.
|
|
65
|
+
*/
|
|
66
|
+
monacoTheme?: string;
|
|
61
67
|
/** Show minimap (default: false) */
|
|
62
68
|
minimap?: boolean;
|
|
63
69
|
/** Font size in pixels (default: 14) */
|
|
@@ -80,7 +86,7 @@ export interface RawEditorProps {
|
|
|
80
86
|
* Binds to the shared EditorContext for source synchronization.
|
|
81
87
|
*/
|
|
82
88
|
export function RawEditor({
|
|
83
|
-
|
|
89
|
+
monacoTheme = 'vs',
|
|
84
90
|
minimap = false,
|
|
85
91
|
fontSize = 14,
|
|
86
92
|
wordWrap = 'on',
|
|
@@ -640,7 +646,7 @@ export function RawEditor({
|
|
|
640
646
|
}
|
|
641
647
|
}, [editorSource, language, monacoNs]);
|
|
642
648
|
|
|
643
|
-
const effectiveTheme = SQUISQ_THEMES[
|
|
649
|
+
const effectiveTheme = SQUISQ_THEMES[monacoTheme] ?? monacoTheme;
|
|
644
650
|
|
|
645
651
|
// Wait for the lazy monaco namespace + `loader.config()` to settle
|
|
646
652
|
// before mounting `<Editor>`. Without this gate, the @monaco-editor/
|
|
@@ -63,10 +63,10 @@ export const HeadingWithTemplate = Heading.extend({
|
|
|
63
63
|
(HTMLAttributes['data-template-params'] as string | undefined) ?? null,
|
|
64
64
|
);
|
|
65
65
|
|
|
66
|
-
// Render heading with a trailing badge span. The badge
|
|
67
|
-
// content —
|
|
68
|
-
//
|
|
69
|
-
//
|
|
66
|
+
// Render heading with a trailing badge span. The badge and its inner core
|
|
67
|
+
// have no real text content — labels/braces are painted via CSS so the
|
|
68
|
+
// template name never becomes part of serialized heading text (which
|
|
69
|
+
// would leak into markdown on round-trip).
|
|
70
70
|
//
|
|
71
71
|
// When no template is set we still render a subtle "empty" badge so
|
|
72
72
|
// authors have a visible affordance for opening the template picker
|
|
@@ -86,10 +86,17 @@ export const HeadingWithTemplate = Heading.extend({
|
|
|
86
86
|
role: 'button',
|
|
87
87
|
tabindex: '0',
|
|
88
88
|
'aria-haspopup': 'listbox',
|
|
89
|
-
title: 'Change block
|
|
89
|
+
title: 'Change block type',
|
|
90
90
|
'data-template': templateName,
|
|
91
|
-
'data-template-label': templateLabel(templateName),
|
|
92
91
|
},
|
|
92
|
+
[
|
|
93
|
+
'span',
|
|
94
|
+
{
|
|
95
|
+
class: 'squisq-template-badge-core',
|
|
96
|
+
'data-template-label': templateLabel(templateName),
|
|
97
|
+
'aria-hidden': 'true',
|
|
98
|
+
},
|
|
99
|
+
],
|
|
93
100
|
],
|
|
94
101
|
propsBadgeSpec(propsSummary),
|
|
95
102
|
];
|
|
@@ -107,8 +114,16 @@ export const HeadingWithTemplate = Heading.extend({
|
|
|
107
114
|
role: 'button',
|
|
108
115
|
tabindex: '0',
|
|
109
116
|
'aria-haspopup': 'listbox',
|
|
110
|
-
title: 'Choose block
|
|
117
|
+
title: 'Choose block type',
|
|
111
118
|
},
|
|
119
|
+
[
|
|
120
|
+
'span',
|
|
121
|
+
{
|
|
122
|
+
class: 'squisq-template-badge-core',
|
|
123
|
+
'data-template-label': 'Block',
|
|
124
|
+
'aria-hidden': 'true',
|
|
125
|
+
},
|
|
126
|
+
],
|
|
112
127
|
],
|
|
113
128
|
propsBadgeSpec(propsSummary),
|
|
114
129
|
];
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { BlockRenderer, MediaContext } from '@bendyline/squisq-react';
|
|
3
|
+
import {
|
|
4
|
+
resolveTemplateContentPreviewResult,
|
|
5
|
+
type TemplatePreviewSource,
|
|
6
|
+
} from './templateContentPreviewResolver';
|
|
7
|
+
|
|
8
|
+
export interface TemplateContentPreviewProps {
|
|
9
|
+
templateName: string;
|
|
10
|
+
source?: TemplatePreviewSource;
|
|
11
|
+
fallback: JSX.Element;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function TemplateContentPreview({
|
|
15
|
+
templateName,
|
|
16
|
+
source,
|
|
17
|
+
fallback,
|
|
18
|
+
}: TemplateContentPreviewProps) {
|
|
19
|
+
const preview = useMemo(
|
|
20
|
+
() => (source ? resolveTemplateContentPreviewResult(templateName, source) : null),
|
|
21
|
+
[templateName, source],
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
if (!source) return fallback;
|
|
25
|
+
|
|
26
|
+
if (!preview?.visual) {
|
|
27
|
+
if (!preview?.warning) return fallback;
|
|
28
|
+
return (
|
|
29
|
+
<div
|
|
30
|
+
className="squisq-template-gallery-content-preview squisq-template-gallery-content-preview--fallback"
|
|
31
|
+
style={{ aspectRatio: `${source.viewport.width} / ${source.viewport.height}` }}
|
|
32
|
+
aria-hidden="true"
|
|
33
|
+
>
|
|
34
|
+
<div className="squisq-template-gallery-content-preview-fallback">{fallback}</div>
|
|
35
|
+
<span className="squisq-template-gallery-content-preview-warning">{preview.warning}</span>
|
|
36
|
+
</div>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<div
|
|
42
|
+
className="squisq-template-gallery-content-preview"
|
|
43
|
+
style={{ aspectRatio: `${source.viewport.width} / ${source.viewport.height}` }}
|
|
44
|
+
aria-hidden="true"
|
|
45
|
+
>
|
|
46
|
+
<MediaContext.Provider value={source.mediaProvider ?? null}>
|
|
47
|
+
<BlockRenderer
|
|
48
|
+
block={preview.visual}
|
|
49
|
+
blockTime={0}
|
|
50
|
+
basePath={source.basePath ?? '/'}
|
|
51
|
+
viewport={source.viewport}
|
|
52
|
+
/>
|
|
53
|
+
</MediaContext.Provider>
|
|
54
|
+
</div>
|
|
55
|
+
);
|
|
56
|
+
}
|