@bendyline/squisq-editor-react 1.6.0 → 1.6.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/README.md +57 -10
- package/dist/index.d.ts +401 -76
- package/dist/index.js +1334 -930
- 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 +13867 -0
- package/package.json +15 -7
- package/src/EditorContext.tsx +22 -16
- package/src/EditorShell.tsx +68 -27
- package/src/OutlinePanel.tsx +26 -4
- package/src/PreviewControls.tsx +338 -141
- package/src/PreviewPanel.tsx +15 -9
- package/src/RawEditor.tsx +10 -4
- package/src/Toolbar.tsx +21 -11
- package/src/VersionHistoryPanel.tsx +2 -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 +96 -0
- package/src/__tests__/previewControls.test.tsx +70 -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/index.ts +32 -1
- package/src/jsonEditor/useJsonEditorTokens.ts +13 -43
- package/src/recorder/hooks/useMediaRecorder.ts +9 -10
- package/src/styles/code-context.css +155 -0
- package/src/styles/editor.css +149 -3
- package/src/styles/index.css +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bendyline/squisq-editor-react",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.1",
|
|
4
4
|
"description": "React editor shell with raw/WYSIWYG/preview modes for Squisq documents",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Bendyline",
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
"types": "./dist/index.d.ts",
|
|
35
35
|
"import": "./dist/index.js"
|
|
36
36
|
},
|
|
37
|
-
"./styles": "./
|
|
37
|
+
"./styles": "./dist/styles/index.css"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
|
-
"build": "tsup",
|
|
40
|
+
"build": "tsup && node ../../scripts/build-styles.mjs",
|
|
41
41
|
"dev": "concurrently -n js,dts -c blue,gray -r \"tsup --watch --no-dts --no-clean\" \"tsup --watch --dts-only --no-clean\"",
|
|
42
42
|
"typecheck": "tsc --noEmit"
|
|
43
43
|
},
|
|
@@ -46,10 +46,15 @@
|
|
|
46
46
|
"react": "^18.0.0 || ^19.0.0",
|
|
47
47
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
48
48
|
},
|
|
49
|
+
"peerDependenciesMeta": {
|
|
50
|
+
"monaco-editor": {
|
|
51
|
+
"optional": true
|
|
52
|
+
}
|
|
53
|
+
},
|
|
49
54
|
"dependencies": {
|
|
50
|
-
"@bendyline/squisq": "1.5.
|
|
51
|
-
"@bendyline/squisq-formats": "1.4.
|
|
52
|
-
"@bendyline/squisq-react": "1.4.
|
|
55
|
+
"@bendyline/squisq": "1.5.1",
|
|
56
|
+
"@bendyline/squisq-formats": "1.4.1",
|
|
57
|
+
"@bendyline/squisq-react": "1.4.1",
|
|
53
58
|
"@fortawesome/fontawesome-free": "7.2.0",
|
|
54
59
|
"@monaco-editor/react": "4.7.0",
|
|
55
60
|
"@tiptap/extension-image": "2.27.2",
|
|
@@ -74,5 +79,8 @@
|
|
|
74
79
|
"react-dom": "18.3.1",
|
|
75
80
|
"tsup": "8.5.1",
|
|
76
81
|
"typescript": "5.9.3"
|
|
77
|
-
}
|
|
82
|
+
},
|
|
83
|
+
"sideEffects": [
|
|
84
|
+
"**/*.css"
|
|
85
|
+
]
|
|
78
86
|
}
|
package/src/EditorContext.tsx
CHANGED
|
@@ -91,7 +91,13 @@ export type DocumentLinkProvider = (query: string) => Promise<DocumentLinkCandid
|
|
|
91
91
|
// ─── Types ───────────────────────────────────────────────
|
|
92
92
|
|
|
93
93
|
export type EditorView = 'raw' | 'wysiwyg' | 'preview';
|
|
94
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Light/dark chrome mode for the editor shell (toolbar, tabs, status bar,
|
|
96
|
+
* side panes). This is the editor's *UI color scheme* — distinct from a
|
|
97
|
+
* Squisq `Theme` object, which styles the rendered document. Renamed from
|
|
98
|
+
* the former `EditorTheme` to remove that ambiguity.
|
|
99
|
+
*/
|
|
100
|
+
export type EditorColorScheme = 'light' | 'dark';
|
|
95
101
|
/**
|
|
96
102
|
* Document layout mode. `'document'` shows the whole markdown document in
|
|
97
103
|
* the active view (the historical behavior). `'block'` is the
|
|
@@ -128,8 +134,8 @@ export interface EditorState {
|
|
|
128
134
|
parseError: string | null;
|
|
129
135
|
/** Whether a parse is pending */
|
|
130
136
|
isParsing: boolean;
|
|
131
|
-
/** Current color
|
|
132
|
-
|
|
137
|
+
/** Current light/dark chrome color scheme for the editor shell. */
|
|
138
|
+
colorScheme: EditorColorScheme;
|
|
133
139
|
/** Operating mode — 'markdown' for the full shell, 'code' for Monaco-only. */
|
|
134
140
|
editorMode: EditorMode;
|
|
135
141
|
/** Monaco language ID for the Raw editor. */
|
|
@@ -240,8 +246,8 @@ export interface EditorActions {
|
|
|
240
246
|
setTiptapEditor: (editor: TiptapEditor | null) => void;
|
|
241
247
|
/** Register / unregister the Monaco editor instance (called by RawEditor) */
|
|
242
248
|
setMonacoEditor: (editor: MonacoEditor | null) => void;
|
|
243
|
-
/** Set the color
|
|
244
|
-
|
|
249
|
+
/** Set the light/dark chrome color scheme for the editor shell. */
|
|
250
|
+
setColorScheme: (colorScheme: EditorColorScheme) => void;
|
|
245
251
|
/** Show or hide the inline preview gutter at runtime (driven by the View menu). */
|
|
246
252
|
setInlinePreviewVisible: (visible: boolean) => void;
|
|
247
253
|
/** Show or hide the bottom status bar at runtime (driven by the View menu). */
|
|
@@ -360,8 +366,8 @@ export interface EditorProviderProps {
|
|
|
360
366
|
initialView?: EditorView;
|
|
361
367
|
/** Article ID used when generating the Doc */
|
|
362
368
|
articleId?: string;
|
|
363
|
-
/**
|
|
364
|
-
|
|
369
|
+
/** Light/dark chrome color scheme for the editor shell. */
|
|
370
|
+
colorScheme?: EditorColorScheme;
|
|
365
371
|
/**
|
|
366
372
|
* Workspace-scoped `ContentContainer` for this document — the folder
|
|
367
373
|
* holding the doc, its `_files/` sidecar, sibling documents, and any
|
|
@@ -509,7 +515,7 @@ export function EditorProvider({
|
|
|
509
515
|
initialMarkdown = '',
|
|
510
516
|
initialView = 'raw',
|
|
511
517
|
articleId = 'untitled',
|
|
512
|
-
|
|
518
|
+
colorScheme: initialColorScheme = 'light',
|
|
513
519
|
workspaceContainer = null,
|
|
514
520
|
allowVersioning = false,
|
|
515
521
|
versionBasename,
|
|
@@ -570,7 +576,7 @@ export function EditorProvider({
|
|
|
570
576
|
);
|
|
571
577
|
const [parseError, setParseError] = useState<string | null>(null);
|
|
572
578
|
const [isParsing, setIsParsing] = useState(false);
|
|
573
|
-
const [
|
|
579
|
+
const [colorScheme, setColorScheme] = useState<EditorColorScheme>(initialColorScheme);
|
|
574
580
|
const [inlinePreviewVisible, setInlinePreviewVisibleRaw] =
|
|
575
581
|
useState<boolean>(effectiveInlinePreview);
|
|
576
582
|
// Sync visibility when the host changes the prop (e.g., toggle from outside).
|
|
@@ -731,10 +737,10 @@ export function EditorProvider({
|
|
|
731
737
|
const articleIdRef = useRef(articleId);
|
|
732
738
|
articleIdRef.current = articleId;
|
|
733
739
|
|
|
734
|
-
// Sync
|
|
740
|
+
// Sync color scheme when prop changes
|
|
735
741
|
useEffect(() => {
|
|
736
|
-
|
|
737
|
-
}, [
|
|
742
|
+
setColorScheme(initialColorScheme);
|
|
743
|
+
}, [initialColorScheme]);
|
|
738
744
|
|
|
739
745
|
// Debounced parse on markdown source change
|
|
740
746
|
const parseTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
@@ -971,7 +977,7 @@ export function EditorProvider({
|
|
|
971
977
|
activeView,
|
|
972
978
|
parseError,
|
|
973
979
|
isParsing,
|
|
974
|
-
|
|
980
|
+
colorScheme,
|
|
975
981
|
editorMode,
|
|
976
982
|
language: resolvedLanguage,
|
|
977
983
|
inlinePreviewVisible,
|
|
@@ -1009,7 +1015,7 @@ export function EditorProvider({
|
|
|
1009
1015
|
setActiveView,
|
|
1010
1016
|
setTiptapEditor,
|
|
1011
1017
|
setMonacoEditor,
|
|
1012
|
-
|
|
1018
|
+
setColorScheme,
|
|
1013
1019
|
setInlinePreviewVisible,
|
|
1014
1020
|
setStatusBarVisible,
|
|
1015
1021
|
setOutlineVisible,
|
|
@@ -1028,7 +1034,7 @@ export function EditorProvider({
|
|
|
1028
1034
|
activeView,
|
|
1029
1035
|
parseError,
|
|
1030
1036
|
isParsing,
|
|
1031
|
-
|
|
1037
|
+
colorScheme,
|
|
1032
1038
|
editorMode,
|
|
1033
1039
|
resolvedLanguage,
|
|
1034
1040
|
inlinePreviewVisible,
|
|
@@ -1063,7 +1069,7 @@ export function EditorProvider({
|
|
|
1063
1069
|
setActiveView,
|
|
1064
1070
|
setTiptapEditor,
|
|
1065
1071
|
setMonacoEditor,
|
|
1066
|
-
|
|
1072
|
+
setColorScheme,
|
|
1067
1073
|
setInlinePreviewVisible,
|
|
1068
1074
|
setStatusBarVisible,
|
|
1069
1075
|
setOutlineVisible,
|
package/src/EditorShell.tsx
CHANGED
|
@@ -23,7 +23,9 @@ import { RawEditor } from './RawEditor';
|
|
|
23
23
|
import { WysiwygEditor } from './WysiwygEditor';
|
|
24
24
|
import { InlinePreviewGutter } from './InlinePreviewGutter';
|
|
25
25
|
import { BlockPreviewPanel } from './BlockPreviewPanel';
|
|
26
|
-
import { OutlinePanel } from './OutlinePanel';
|
|
26
|
+
import { OutlinePanel, OUTLINE_RESPONSIVE_WIDTH } from './OutlinePanel';
|
|
27
|
+
import { CodeContextZones } from './codeContext/CodeContextZones';
|
|
28
|
+
import type { CodeContext } from './codeContext/types';
|
|
27
29
|
import { BlockCardView } from './BlockCardView';
|
|
28
30
|
import { TimelineTrack } from './TimelineTrack';
|
|
29
31
|
import { PreviewPanel } from './PreviewPanel';
|
|
@@ -32,6 +34,8 @@ import { ImageEditor } from './ImageEditor';
|
|
|
32
34
|
import {
|
|
33
35
|
PreviewSettingsProvider,
|
|
34
36
|
PreviewToolbarControls,
|
|
37
|
+
PreviewModeSwitch,
|
|
38
|
+
PreviewFormatSwitch,
|
|
35
39
|
ThemeDesignerDock,
|
|
36
40
|
} from './PreviewControls';
|
|
37
41
|
import { CustomThemeProvider, useDocCustomThemes } from './customThemes';
|
|
@@ -56,7 +60,7 @@ import {
|
|
|
56
60
|
import type { PrunePolicy, SaveVersionResult } from '@bendyline/squisq/versions';
|
|
57
61
|
import type { CSSProperties, ReactNode } from 'react';
|
|
58
62
|
|
|
59
|
-
export type {
|
|
63
|
+
export type { EditorColorScheme } from './EditorContext';
|
|
60
64
|
|
|
61
65
|
export interface EditorShellProps {
|
|
62
66
|
/** Initial markdown content */
|
|
@@ -70,8 +74,13 @@ export interface EditorShellProps {
|
|
|
70
74
|
basePath?: string;
|
|
71
75
|
/** Called when markdown source changes */
|
|
72
76
|
onChange?: (source: string) => void;
|
|
73
|
-
/**
|
|
74
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Light/dark chrome color scheme for the editor shell — toolbar, tabs,
|
|
79
|
+
* status bar, and side panes (default: `'light'`). This is the editor's
|
|
80
|
+
* UI mode, **not** a Squisq `Theme` object; the rendered document's
|
|
81
|
+
* styling is controlled separately via `themeOverride` / `Doc.themeId`.
|
|
82
|
+
*/
|
|
83
|
+
colorScheme?: 'light' | 'dark';
|
|
75
84
|
/** Additional class name */
|
|
76
85
|
className?: string;
|
|
77
86
|
/** CSS height for the shell container (default: '100vh') */
|
|
@@ -166,6 +175,13 @@ export interface EditorShellProps {
|
|
|
166
175
|
* (Slack, Discord). When omitted, the editor behaves normally.
|
|
167
176
|
*/
|
|
168
177
|
submitOnEnter?: () => void;
|
|
178
|
+
/**
|
|
179
|
+
* Host-supplied context dictionary rendered inside the Monaco (raw / code)
|
|
180
|
+
* surface: collapsible markdown sections injected above anchor lines, plus
|
|
181
|
+
* an optional file-top summary. See {@link CodeContext}. Ignored in
|
|
182
|
+
* WYSIWYG / preview / image surfaces.
|
|
183
|
+
*/
|
|
184
|
+
codeContext?: CodeContext;
|
|
169
185
|
/**
|
|
170
186
|
* Let the WYSIWYG editing surface fill its container instead of rendering
|
|
171
187
|
* as a centered 800px "page" column. Useful when embedding in chat
|
|
@@ -324,9 +340,11 @@ export interface EditorShellProps {
|
|
|
324
340
|
*/
|
|
325
341
|
outline?: boolean;
|
|
326
342
|
/**
|
|
327
|
-
*
|
|
328
|
-
*
|
|
329
|
-
*
|
|
343
|
+
* Fixed width in pixels for the outline pane. When omitted, the pane sizes
|
|
344
|
+
* responsively — never narrower than 260px, growing with the window and
|
|
345
|
+
* capped at 460px — so it stretches out when there's horizontal space to
|
|
346
|
+
* spare. Only takes effect when {@link EditorShellProps.outline} is true (or
|
|
347
|
+
* the View menu has toggled it on).
|
|
330
348
|
*/
|
|
331
349
|
outlineWidth?: number;
|
|
332
350
|
/**
|
|
@@ -378,7 +396,7 @@ export function EditorShell({
|
|
|
378
396
|
articleId = 'untitled',
|
|
379
397
|
basePath = '/',
|
|
380
398
|
onChange,
|
|
381
|
-
|
|
399
|
+
colorScheme = 'light',
|
|
382
400
|
className,
|
|
383
401
|
height = '100vh',
|
|
384
402
|
minHeight,
|
|
@@ -397,6 +415,7 @@ export function EditorShell({
|
|
|
397
415
|
toolbarSlotRight,
|
|
398
416
|
showPlayTab = true,
|
|
399
417
|
submitOnEnter,
|
|
418
|
+
codeContext,
|
|
400
419
|
fullWidth = false,
|
|
401
420
|
uxFont,
|
|
402
421
|
thinMargins = false,
|
|
@@ -417,7 +436,7 @@ export function EditorShell({
|
|
|
417
436
|
inlinePreview = false,
|
|
418
437
|
inlinePreviewWidth = 320,
|
|
419
438
|
outline = false,
|
|
420
|
-
outlineWidth
|
|
439
|
+
outlineWidth,
|
|
421
440
|
blockTags = true,
|
|
422
441
|
themeInheritance = 'fonts',
|
|
423
442
|
viewPreferences,
|
|
@@ -449,7 +468,7 @@ export function EditorShell({
|
|
|
449
468
|
initialMarkdown={initialMarkdown}
|
|
450
469
|
initialView={effectiveInitialView}
|
|
451
470
|
articleId={articleId}
|
|
452
|
-
|
|
471
|
+
colorScheme={colorScheme}
|
|
453
472
|
workspaceContainer={effectiveContainer}
|
|
454
473
|
allowVersioning={allowVersioning}
|
|
455
474
|
versionBasename={versionBasename}
|
|
@@ -487,6 +506,7 @@ export function EditorShell({
|
|
|
487
506
|
toolbarSlotRight={toolbarSlotRight}
|
|
488
507
|
showPlayTab={showPlayTab}
|
|
489
508
|
submitOnEnter={submitOnEnter}
|
|
509
|
+
codeContext={codeContext}
|
|
490
510
|
fullWidth={fullWidth}
|
|
491
511
|
uxFont={uxFont}
|
|
492
512
|
thinMargins={thinMargins}
|
|
@@ -522,6 +542,7 @@ interface EditorShellInnerProps {
|
|
|
522
542
|
toolbarSlotRight?: ReactNode;
|
|
523
543
|
showPlayTab: boolean;
|
|
524
544
|
submitOnEnter?: () => void;
|
|
545
|
+
codeContext?: CodeContext;
|
|
525
546
|
fullWidth: boolean;
|
|
526
547
|
uxFont?: string;
|
|
527
548
|
thinMargins: boolean;
|
|
@@ -534,7 +555,7 @@ interface EditorShellInnerProps {
|
|
|
534
555
|
allowVersioning: boolean;
|
|
535
556
|
versioningAutoSaveIdleMs?: number;
|
|
536
557
|
inlinePreviewWidth: number;
|
|
537
|
-
outlineWidth
|
|
558
|
+
outlineWidth?: number;
|
|
538
559
|
themeOverride: Theme | null;
|
|
539
560
|
}
|
|
540
561
|
|
|
@@ -554,6 +575,7 @@ function EditorShellInner({
|
|
|
554
575
|
toolbarSlotRight,
|
|
555
576
|
showPlayTab,
|
|
556
577
|
submitOnEnter,
|
|
578
|
+
codeContext,
|
|
557
579
|
fullWidth,
|
|
558
580
|
uxFont,
|
|
559
581
|
thinMargins,
|
|
@@ -573,7 +595,7 @@ function EditorShellInner({
|
|
|
573
595
|
activeView,
|
|
574
596
|
markdownSource,
|
|
575
597
|
doc,
|
|
576
|
-
|
|
598
|
+
colorScheme,
|
|
577
599
|
editorMode,
|
|
578
600
|
insertAtCursor,
|
|
579
601
|
replaceAll,
|
|
@@ -620,7 +642,7 @@ function EditorShellInner({
|
|
|
620
642
|
imageEditFallbackContainerRef.current = new MemoryContentContainer();
|
|
621
643
|
}
|
|
622
644
|
const imageEditFallbackContainer = imageEditFallbackContainerRef.current;
|
|
623
|
-
const isDark =
|
|
645
|
+
const isDark = colorScheme === 'dark';
|
|
624
646
|
|
|
625
647
|
const handleToggleFiles = useCallback(() => {
|
|
626
648
|
setShowFiles((prev) => !prev);
|
|
@@ -761,7 +783,7 @@ function EditorShellInner({
|
|
|
761
783
|
return (
|
|
762
784
|
<div
|
|
763
785
|
className={`squisq-editor-shell ${className || ''}`}
|
|
764
|
-
data-theme={
|
|
786
|
+
data-theme={colorScheme}
|
|
765
787
|
data-full-width={fullWidth ? 'true' : undefined}
|
|
766
788
|
data-thin-margins={thinMargins ? 'true' : undefined}
|
|
767
789
|
data-outline-visible={isMarkdownMode && outlineVisible ? 'true' : undefined}
|
|
@@ -775,13 +797,16 @@ function EditorShellInner({
|
|
|
775
797
|
// tabs, status bar) consume `--squisq-ux-font` as their
|
|
776
798
|
// `font-family`, falling back to the system stack when unset.
|
|
777
799
|
...(uxFont ? ({ '--squisq-ux-font': uxFont } as CSSProperties) : {}),
|
|
778
|
-
// Exposed so the toolbar's view-tabs section
|
|
779
|
-
//
|
|
780
|
-
// outline's right edge.
|
|
781
|
-
//
|
|
782
|
-
// `data-outline-visible` gate above keeps the
|
|
783
|
-
// scoped to the case where alignment matters.
|
|
784
|
-
...({
|
|
800
|
+
// Exposed so the toolbar's view-tabs section AND the outline pane read
|
|
801
|
+
// one shared width, lining up the view-tabs' right-edge separator with
|
|
802
|
+
// the outline's right edge. A fixed `outlineWidth` pins it to px;
|
|
803
|
+
// otherwise it's the responsive clamp so the pane stretches when
|
|
804
|
+
// there's room. The `data-outline-visible` gate above keeps the
|
|
805
|
+
// toolbar override scoped to the case where alignment matters.
|
|
806
|
+
...({
|
|
807
|
+
'--squisq-outline-width':
|
|
808
|
+
outlineWidth != null ? `${outlineWidth}px` : OUTLINE_RESPONSIVE_WIDTH,
|
|
809
|
+
} as CSSProperties),
|
|
785
810
|
}}
|
|
786
811
|
{...containerProps}
|
|
787
812
|
>
|
|
@@ -804,6 +829,16 @@ function EditorShellInner({
|
|
|
804
829
|
showFiles={showFiles}
|
|
805
830
|
onToggleFiles={!isCodeMode && filesToggleEnabled ? handleToggleFiles : undefined}
|
|
806
831
|
slotLeft={toolbarSlotLeft}
|
|
832
|
+
slotAfterTabs={
|
|
833
|
+
!isCodeMode &&
|
|
834
|
+
isPreview && (
|
|
835
|
+
<div className="squisq-preview-left-controls">
|
|
836
|
+
<PreviewModeSwitch />
|
|
837
|
+
<span className="squisq-preview-seg-divider" aria-hidden="true" />
|
|
838
|
+
<PreviewFormatSwitch />
|
|
839
|
+
</div>
|
|
840
|
+
)
|
|
841
|
+
}
|
|
807
842
|
slotAfterActions={
|
|
808
843
|
<>
|
|
809
844
|
{toolbarSlotAfterActions}
|
|
@@ -847,7 +882,7 @@ function EditorShellInner({
|
|
|
847
882
|
onExport={onImageExport}
|
|
848
883
|
/>
|
|
849
884
|
) : (
|
|
850
|
-
<ImageViewer src={imageSrc} alt={imageAlt} theme={
|
|
885
|
+
<ImageViewer src={imageSrc} alt={imageAlt} theme={colorScheme} />
|
|
851
886
|
))}
|
|
852
887
|
{/* Raw (Monaco) view. Always wrapped in `.squisq-editor-with-gutter`
|
|
853
888
|
so toggling a pane on/off doesn't change the editor's tree
|
|
@@ -870,7 +905,7 @@ function EditorShellInner({
|
|
|
870
905
|
>
|
|
871
906
|
<div key="raw-editor" className="squisq-raw-editor-container">
|
|
872
907
|
<RawEditor
|
|
873
|
-
|
|
908
|
+
monacoTheme={colorScheme === 'dark' ? 'vs-dark' : 'vs'}
|
|
874
909
|
submitOnEnter={submitOnEnter}
|
|
875
910
|
readOnly={readOnly}
|
|
876
911
|
/>
|
|
@@ -879,12 +914,18 @@ function EditorShellInner({
|
|
|
879
914
|
) : (
|
|
880
915
|
<div key="raw-editor" className="squisq-raw-editor-container">
|
|
881
916
|
<RawEditor
|
|
882
|
-
|
|
917
|
+
monacoTheme={colorScheme === 'dark' ? 'vs-dark' : 'vs'}
|
|
883
918
|
submitOnEnter={submitOnEnter}
|
|
884
919
|
readOnly={readOnly}
|
|
885
920
|
/>
|
|
886
921
|
</div>
|
|
887
922
|
)}
|
|
923
|
+
{/* Renders nothing in normal flow — portals context
|
|
924
|
+
sections into Monaco view zones via the context's
|
|
925
|
+
monacoEditor. Code mode only. */}
|
|
926
|
+
{isCodeMode && codeContext && (
|
|
927
|
+
<CodeContextZones key="code-context" options={codeContext} />
|
|
928
|
+
)}
|
|
888
929
|
{isMarkdownMode && isCardMode && inlinePreviewVisible && (
|
|
889
930
|
<BlockPreviewPanel key="block-preview" basePath={basePath} />
|
|
890
931
|
)}
|
|
@@ -1006,7 +1047,7 @@ function EditorShellInner({
|
|
|
1006
1047
|
}}
|
|
1007
1048
|
allowVersioning={allowVersioning}
|
|
1008
1049
|
versioningAutoSaveIdleMs={versioningAutoSaveIdleMs}
|
|
1009
|
-
shellTheme={
|
|
1050
|
+
shellTheme={colorScheme}
|
|
1010
1051
|
/>
|
|
1011
1052
|
)}
|
|
1012
1053
|
</div>
|
|
@@ -1031,8 +1072,8 @@ interface ImageEditModalProps {
|
|
|
1031
1072
|
onSaved: () => void;
|
|
1032
1073
|
allowVersioning: boolean;
|
|
1033
1074
|
versioningAutoSaveIdleMs?: number;
|
|
1034
|
-
/** EditorShell's `
|
|
1035
|
-
* the image editor chrome matches the host shell. */
|
|
1075
|
+
/** EditorShell's `colorScheme` prop — 'light' or 'dark'. Threaded through
|
|
1076
|
+
* so the image editor chrome matches the host shell. */
|
|
1036
1077
|
shellTheme?: 'light' | 'dark';
|
|
1037
1078
|
}
|
|
1038
1079
|
|
package/src/OutlinePanel.tsx
CHANGED
|
@@ -17,14 +17,30 @@ import { templateLabel } from './TemplatePicker';
|
|
|
17
17
|
import { useHeadingLayout } from './useHeadingLayout';
|
|
18
18
|
import { usePreviewSettingsOptional } from './PreviewControls';
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Responsive default width for the outline pane, used when no fixed `width`
|
|
22
|
+
* (or `--squisq-outline-width`) is supplied: never narrower than 260px, grows
|
|
23
|
+
* with the viewport so it stretches out to fill horizontal space when there's
|
|
24
|
+
* room, and caps at 460px so it never dominates the editor. A viewport unit
|
|
25
|
+
* (rather than
|
|
26
|
+
* a container unit) keeps the pane and the toolbar's view-tabs — which read the
|
|
27
|
+
* same value — resolving to an identical width, so their right edges stay
|
|
28
|
+
* aligned.
|
|
29
|
+
*/
|
|
30
|
+
export const OUTLINE_RESPONSIVE_WIDTH = 'clamp(260px, 30vw, 460px)';
|
|
31
|
+
|
|
20
32
|
export interface OutlinePanelProps {
|
|
21
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* Fixed width of the pane in pixels. When omitted, the pane sizes
|
|
35
|
+
* responsively from `--squisq-outline-width` (falling back to
|
|
36
|
+
* {@link OUTLINE_RESPONSIVE_WIDTH}) so it stretches on wider screens.
|
|
37
|
+
*/
|
|
22
38
|
width?: number;
|
|
23
39
|
/** Optional CSS class for the outer container. */
|
|
24
40
|
className?: string;
|
|
25
41
|
}
|
|
26
42
|
|
|
27
|
-
export function OutlinePanel({ width
|
|
43
|
+
export function OutlinePanel({ width, className }: OutlinePanelProps) {
|
|
28
44
|
const {
|
|
29
45
|
doc,
|
|
30
46
|
markdownSource,
|
|
@@ -88,9 +104,15 @@ export function OutlinePanel({ width = 240, className }: OutlinePanelProps) {
|
|
|
88
104
|
const accentColor = previewSettings?.activeTheme?.colors?.primary;
|
|
89
105
|
|
|
90
106
|
const isEmpty = !doc || doc.blocks.length === 0 || !hasAnyHeading(doc.blocks);
|
|
107
|
+
// Fixed px when a width is supplied; otherwise size from the shared
|
|
108
|
+
// `--squisq-outline-width` variable (the shell sets it, and the toolbar's
|
|
109
|
+
// view-tabs read the same value so their right edges stay aligned). The
|
|
110
|
+
// clamp fallback lets a standalone OutlinePanel stretch on wide screens too.
|
|
111
|
+
const basis =
|
|
112
|
+
width != null ? `${width}px` : `var(--squisq-outline-width, ${OUTLINE_RESPONSIVE_WIDTH})`;
|
|
91
113
|
const paneStyle: CSSProperties = {
|
|
92
|
-
width:
|
|
93
|
-
flex: `0 0 ${
|
|
114
|
+
width: basis,
|
|
115
|
+
flex: `0 0 ${basis}`,
|
|
94
116
|
overflow: 'auto',
|
|
95
117
|
...(accentColor
|
|
96
118
|
? ({ ['--squisq-outline-accent' as string]: accentColor } as CSSProperties)
|