feat(markdown): add contextual toolbar for background color, accent color, and width presets

This commit is contained in:
Hiren Kangad
2026-03-13 11:21:28 +05:30
parent aa3112a5bc
commit dfdfd07a1d
2 changed files with 198 additions and 0 deletions
+38
View File
@@ -44,6 +44,7 @@ import * as ops from '../canvas/operations';
import ReactDOM from 'react-dom';
import MarkdownReadView from '../components/MarkdownReadView';
import PasteChoicePopup from '../components/PasteChoicePopup';
import MarkdownFormatToolbar from '../components/MarkdownFormatToolbar';
const LazyMarkdownEditView = React.lazy(() => import('../components/MarkdownEditView'));
// Hooks
@@ -133,6 +134,7 @@ export default function Editor({ isPublicView }: EditorProps) {
>(null);
const [videoCtrl, setVideoCtrl] = useState<{ videoSprite: VideoSprite; screenRect: { x: number; y: number; w: number; h: number } } | null>(null);
const [pastePopup, setPastePopup] = useState<{ x: number; y: number; text: string; html: string; hasImage: boolean } | null>(null);
const [mdToolbar, setMdToolbar] = useState<{ x: number; y: number; item: SceneItem } | null>(null);
const [showMinimap, setShowMinimap] = useState(true);
const [minimapData, setMinimapData] = useState<{ items: any[]; viewportBounds: any; contentBounds: any }>({
items: [], viewportBounds: { x: 0, y: 0, w: 1, h: 1 }, contentBounds: { x: 0, y: 0, w: 1, h: 1 },
@@ -708,6 +710,17 @@ export default function Editor({ isPublicView }: EditorProps) {
setTextToolbar(null);
}
// Markdown format toolbar: show when exactly one markdown card is selected
const mdItems = items.filter((it) => it.type === 'markdown');
if (mdItems.length === 1 && items.length === 1) {
const b = getItemWorldBounds(mdItems[0]);
const screenTL = vp.toScreen(b.x, b.y);
const screenTR = vp.toScreen(b.x + b.w, b.y);
setMdToolbar({ x: (screenTL.x + screenTR.x) / 2, y: screenTL.y, item: mdItems[0] });
} else {
setMdToolbar(null);
}
if (items.length < 2) { setSelToolbar(null); } else {
// Compute world bounding box of selection
let minX = Infinity, minY = Infinity, maxX = -Infinity;
@@ -1066,6 +1079,31 @@ export default function Editor({ isPublicView }: EditorProps) {
/>
)}
{/* Markdown format toolbar */}
{mdToolbar && activeTool === ToolType.SELECT && !contextMenu && !editingMdId && (
<MarkdownFormatToolbar
x={mdToolbar.x}
y={mdToolbar.y}
bgColor={(mdToolbar.item.data as MarkdownObject).bgColor}
accentColor={(mdToolbar.item.data as MarkdownObject).accentColor}
width={mdToolbar.item.data.w}
onBgColorChange={(color) => {
(mdToolbar.item.data as MarkdownObject).bgColor = color;
onCanvasChange([mdToolbar.item.id]);
}}
onAccentColorChange={(color) => {
(mdToolbar.item.data as MarkdownObject).accentColor = color;
onCanvasChange([mdToolbar.item.id]);
}}
onWidthChange={(w) => {
mdToolbar.item.data.w = w;
onCanvasChange([mdToolbar.item.id]);
mdOverlay?.measureHeight(mdToolbar.item.id);
selectionRef.current?.transformBox.update([mdToolbar.item]);
}}
/>
)}
{/* Video controls (floating, below selected video) */}
{videoCtrl && activeTool === ToolType.SELECT && !contextMenu && (
<VideoControls