feat(markdown): add MarkdownSprite and register in SceneManager

Creates MarkdownSprite (Graphics-only background rect with header bar)
and wires it into SceneManager._createItem() under case 'markdown'.
This commit is contained in:
Hiren Kangad
2026-03-13 11:21:27 +05:30
parent f989a8111b
commit de527954da
2 changed files with 74 additions and 0 deletions
+7
View File
@@ -14,6 +14,7 @@ import { VideoSprite } from './sprites/VideoSprite';
import { DrawingSprite } from './sprites/DrawingSprite'; import { DrawingSprite } from './sprites/DrawingSprite';
import { FrameSprite } from './sprites/FrameSprite'; import { FrameSprite } from './sprites/FrameSprite';
import { StickySprite } from './sprites/StickySprite'; import { StickySprite } from './sprites/StickySprite';
import { MarkdownSprite } from './sprites/MarkdownSprite';
import { TextSprite } from './sprites/TextSprite'; import { TextSprite } from './sprites/TextSprite';
import { SpringManager, Spring, PRESETS } from './spring'; import { SpringManager, Spring, PRESETS } from './spring';
import { reparentGroupChildren } from './grouping'; import { reparentGroupChildren } from './grouping';
@@ -368,6 +369,12 @@ export class SceneManager {
break; break;
} }
case 'markdown': {
const mdData = data as MarkdownObject;
displayObject = new MarkdownSprite(mdData);
break;
}
default: default:
displayObject = new Container(); displayObject = new Container();
break; break;
@@ -0,0 +1,67 @@
/**
* MarkdownSprite — PixiJS background container for markdown cards.
*
* Renders only a colored background rectangle for canvas integration
* (hit-testing, selection, z-ordering). All markdown content is rendered
* as a DOM overlay by MarkdownOverlay, not by PixiJS.
*/
import { Container, Graphics } from 'pixi.js';
import type { MarkdownObject } from '../scene-format';
import {
MD_DEFAULT_BG,
MD_DEFAULT_CORNER_RADIUS,
MD_HEADER_BG,
} from '../markdownDefaults';
const HEADER_HEIGHT = 32;
export class MarkdownSprite extends Container {
private _bg: Graphics;
private _lastW = 0;
private _lastH = 0;
private _lastBgColor = '';
private _lastCornerRadius = 0;
constructor(data: MarkdownObject) {
super();
this._bg = new Graphics();
this.addChild(this._bg);
this._draw(data.w, data.h, data.bgColor || MD_DEFAULT_BG, data.cornerRadius ?? MD_DEFAULT_CORNER_RADIUS);
}
updateFromData(data: MarkdownObject): void {
const bgColor = data.bgColor || MD_DEFAULT_BG;
const cr = data.cornerRadius ?? MD_DEFAULT_CORNER_RADIUS;
if (data.w === this._lastW && data.h === this._lastH && bgColor === this._lastBgColor && cr === this._lastCornerRadius) {
return; // nothing changed
}
this._draw(data.w, data.h, bgColor, cr);
}
private _draw(w: number, h: number, bgColor: string, cornerRadius: number): void {
this._lastW = w;
this._lastH = h;
this._lastBgColor = bgColor;
this._lastCornerRadius = cornerRadius;
const g = this._bg;
g.clear();
// Card background
g.roundRect(0, 0, w, h, cornerRadius);
g.fill({ color: bgColor });
// Header bar
// Draw as a rect clipped to the top portion with rounded top corners
g.roundRect(0, 0, w, HEADER_HEIGHT, cornerRadius);
g.fill({ color: MD_HEADER_BG });
// Flat bottom edge of header: overwrite the bottom-rounded part
g.rect(0, HEADER_HEIGHT - cornerRadius, w, cornerRadius);
g.fill({ color: MD_HEADER_BG });
// Header bottom border
g.rect(0, HEADER_HEIGHT - 1, w, 1);
g.fill({ color: '#333333' });
}
}