feat(markdown): add MARKDOWN tool, toolbar button, and m/6 shortcuts

This commit is contained in:
Hiren Kangad
2026-03-13 11:21:28 +05:30
parent 2d5396ef09
commit 6118193f19
2 changed files with 65 additions and 0 deletions
+52
View File
@@ -22,6 +22,7 @@ export enum ToolType {
TEXT = 'TEXT',
ERASER = 'ERASER',
STICKY = 'STICKY',
MARKDOWN = 'MARKDOWN',
}
export interface ToolOptions {
@@ -61,6 +62,8 @@ export interface ToolContext {
switchToSelect?: () => void;
/** When true, destructive/creative tool clicks (TEXT, ERASER) are suppressed. */
reviewMode?: boolean;
/** Called after a new markdown card is created, to immediately enter edit mode. */
onMarkdownCreated?: (id: string) => void;
}
export function activateTool(
@@ -390,6 +393,53 @@ export function activateTool(
};
}
case ToolType.MARKDOWN: {
container.style.cursor = 'crosshair';
const onClick = (e: PointerEvent) => {
if (ctx.reviewMode) return;
const rect = container.getBoundingClientRect();
const world = viewport.toWorld(e.clientX - rect.left, e.clientY - rect.top);
const mdData = {
id: crypto.randomUUID(),
type: 'markdown' as const,
x: world.x - 225,
y: world.y - 20,
w: 450,
h: 60,
sx: 1,
sy: 1,
angle: 0,
z: scene.nextZ(),
opacity: 1,
locked: false,
name: '',
visible: true,
content: '',
bgColor: '#232336',
textColor: '#e0e0e0',
accentColor: '#7950f2',
padding: 16,
cornerRadius: 10,
};
scene._createItem(mdData, true);
scene._applyZOrder();
ctx.broadcastElements?.([mdData.id]);
ctx.onChange();
ctx.switchToSelect?.();
ctx.onMarkdownCreated?.(mdData.id);
container.removeEventListener('pointerdown', onClick);
};
container.addEventListener('pointerdown', onClick);
return () => {
container.removeEventListener('pointerdown', onClick);
};
}
default:
return null;
}
@@ -400,8 +450,10 @@ export const toolShortcuts: Record<string, ToolType> = {
p: ToolType.PEN,
t: ToolType.TEXT,
s: ToolType.STICKY,
m: ToolType.MARKDOWN,
'1': ToolType.SELECT,
'3': ToolType.PEN,
'4': ToolType.TEXT,
'5': ToolType.STICKY,
'6': ToolType.MARKDOWN,
};
+13
View File
@@ -72,6 +72,18 @@ function IconSticky() {
);
}
function IconMarkdown() {
return (
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round">
<rect x="2" y="1" width="14" height="16" rx="2" />
<path d="M5 5h8" />
<path d="M5 8h6" />
<path d="M5 11h4" />
<circle cx="13" cy="13" r="2" fill="currentColor" stroke="none" />
</svg>
);
}
function IconReview() {
return (
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5">
@@ -124,6 +136,7 @@ const toolButtons: { tool: ToolType; label: string; shortcut: string; numKey: st
{ tool: ToolType.PEN, label: 'Draw', shortcut: 'P', numKey: '3', Icon: IconPen, hint: 'Click and drag to draw freehand' },
{ tool: ToolType.TEXT, label: 'Text', shortcut: 'T', numKey: '4', Icon: IconText, hint: 'Click on the canvas to place text' },
{ tool: ToolType.STICKY, label: 'Sticky', shortcut: 'S', numKey: '5', Icon: IconSticky, hint: 'Click on the canvas to place a sticky note' },
{ tool: ToolType.MARKDOWN, label: 'Markdown', shortcut: 'M', numKey: '6', Icon: IconMarkdown, hint: 'Click on the canvas to place a markdown card' },
];
const REVIEW_HINT = 'Click an object to place a comment pin. Press . to toggle.';