Reference
@ledable/sdk/graphics
The JSX elements and functions that draw frames.
Generated from the types of the SDK. Import from @ledable/sdk/graphics; an editor shows the same declarations and comments as you type.
Elements
Circle
function Circle(props: CircleProps): LedElementEllipse
function Ellipse(props: EllipseProps): LedElementFrame
function Frame(props: FrameProps): LedElementGroup
function Group(props: GroupProps): LedElementLayer
function Layer(props: LayerProps): LedElementLine
function Line(props: LineProps): LedElementLinearGradient
function LinearGradient(props: LinearGradientProps): LedElementPixel
function Pixel(props: PixelProps): LedElementPixelMap
function PixelMap(props: PixelMapProps): LedElementPolygon
function Polygon(props: PolygonProps): LedElementRadialGradient
function RadialGradient(props: RadialGradientProps): LedElementRect
function Rect(props: RectProps): LedElementSprite
function Sprite(props: SpriteProps): LedElementStop
function Stop(props: StopProps): LedElementText
function Text(props: TextProps): LedElementFunctions
anchorOffset
Offset of the block's top-left from the anchor point, in output px.
function anchorOffset(anchor: TextAnchor, layout: TextLayout): AnchorOffsetblit
function blit(dst: Framebuffer, src: Framebuffer, dx: number, dy: number): voidbrightenColor
Raise dark LED text toward the legacy sRGB luminance threshold, preserving hue.
function brightenColor(color: Color, threshold = 150): Colorclamp
function clamp(value: number, min: number, max: number): numberclamp01
function clamp01(value: number): numbercloneFramebuffer
function cloneFramebuffer(fb: Framebuffer): FramebuffercompositeFramebuffer
Draw a bitmap at an integer offset, clipping its edges and preserving alpha.
function compositeFramebuffer(
dst: Framebuffer,
src: Framebuffer,
dx: number,
dy: number,
): voidcontainRgb
RGB contain with the Pillow 11 Lanczos kernel and 22-bit integer coefficients. Alpha is discarded before filtering, matching source.convert("RGB"). https://github.com/python-pillow/Pillow/blob/11.0.0/src/libImaging/Resample.c
function containRgb(source: Framebuffer, maxWidth: number, maxHeight: number): FramebuffercreateFramebuffer
function createFramebuffer(width: number, height: number): FramebuffercreateFrameContext
Loop progress is frame / frameCount — never frame / (frameCount - 1) — so a looping animation does not store duplicate first/last endpoints.
function createFrameContext(frame: number, options: AnimationOptions): FrameContextdecodeBitmapFont
Decode a `.ledfont` asset: the magic `LEDF`, a format version byte, a little-endian u16 header length, the JSON header (name, size, ascent, descent, lineRef) and the glyph table the bake pipeline writes. Glyphs are decoded lazily on first use and kept for the font's lifetime.
function decodeBitmapFont(bytes: Uint8Array): BitmapFonteaseInCubic
function easeInCubic(t: number): numbereaseInOutCubic
function easeInOutCubic(t: number): numbereaseInOutQuad
function easeInOutQuad(t: number): numbereaseInQuad
function easeInQuad(t: number): numbereaseOutCubic
function easeOutCubic(t: number): numbereaseOutQuad
function easeOutQuad(t: number): numberevaluateElement
Expand function components and fragments into a tree of intrinsic nodes.
function evaluateElement(
element: LedElement,
limits: EvaluateLimits = DEFAULT_LIMITS,
): IntrinsicNodeevaluateToNodes
Like evaluateElement but allows fragments/components producing several nodes.
function evaluateToNodes(
element: LedElement,
limits: EvaluateLimits = DEFAULT_LIMITS,
): IntrinsicNode[]fillFramebuffer
function fillFramebuffer(fb: Framebuffer, color: RGBA): voidframebufferToText
Render the framebuffer as text for golden tests. The legend maps a single character to an opaque color; pixels not matching any legend color become "?" so unexpected output is visible in the diff.
function framebufferToText(
fb: Framebuffer,
legend: Readonly<Record<string, Color>>,
): stringframesToSheet
Pack equally sized frames into one row-major sheet. Unused trailing slots stay transparent black.
function framesToSheet(
frames: readonly Framebuffer[],
options: SpriteSheetOptions = {},
): FramebuffergetPixel
function getPixel(fb: Framebuffer, x: number, y: number): RGBAglyphBit
function glyphBit(glyph: Glyph, x: number, y: number): booleanhalfBrightness
Pillow's `ImageEnhance.Brightness(0.5)` on an RGBA image: RGB is blended halfway with black, which Pillow special-cases as an integer average, so each colour channel becomes `floor(v / 2)`; the enhancer puts the original alpha back, so alpha is untouched.
function halfBrightness(fb: Framebuffer): FramebufferisBitmapFont
function isBitmapFont(value: unknown): value is BitmapFontisLedElement
function isLedElement(value: unknown): value is LedElementlayoutText
function layoutText(
font: BitmapFont,
text: string,
options: TextLayoutOptions = {},
): TextLayoutlerp
function lerp(a: number, b: number, t: number): numbermeasureText
function measureText(
font: BitmapFont,
text: string,
options: TextLayoutOptions = {},
): TextMetricsmeasureTextBounds
Visible glyph bounds, retaining empty lines when measuring a scrolling text canvas.
function measureTextBounds(
font: BitmapFont,
text: string,
options: TextLayoutOptions = {},
): { readonly top: number; readonly bottom: number; readonly height: number }parseColor
function parseColor(value: Color): RGBArenderAnimation
function renderAnimation(render: RenderFunction, options: AnimationOptions): Framebuffer[]renderFrame
function renderFrame(element: LedElement, options: RenderOptions = {}): FramebufferrenderLedPreview
Expand each logical pixel into a square or circular LED emitter with a configurable gap, mirroring ledable/cloud's led_sim preview.
function renderLedPreview(fb: Framebuffer, options: LedPreviewOptions = {}): Framebufferrgba
function rgba(r: number, g: number, b: number, a = 255): RGBAscaleNearest
Nearest-neighbor integer enlargement for previews.
function scaleNearest(fb: Framebuffer, factor: number): FramebuffersetPixel
function setPixel(fb: Framebuffer, x: number, y: number, color: RGBA): voidtextPixels
Lit pixel [x, y] pairs for a laid-out block, origin at the block top-left.
function textPixels(layout: TextLayout): Array<readonly [number, number]>withAlpha
function withAlpha(color: RGBA, alpha: number): RGBAConstants
DEFAULT_LIMITS
const DEFAULT_LIMITS: EvaluateLimits = { maxNodes: 20000, maxDepth: 128 }Fragment
const Fragment = "led:fragment"MAX_TEXT_LENGTH
const MAX_TEXT_LENGTH = 4096NOTDEF_CODEPOINT
Sentinel codepoint for the .notdef (missing glyph) entry in baked data.
const NOTDEF_CODEPOINT = 0x110000Classes
LedError
class LedError extends ErrorInterfaces
AnimationOptions
interface AnimationOptions {
readonly frameCount: number;
readonly fps: number;
readonly width?: number;
readonly height?: number;
readonly limits?: EvaluateLimits;
}BitmapFont
interface BitmapFont {
readonly $$ledFont: true;
readonly name: string;
readonly size: number;
readonly ascent: number;
readonly descent: number;
readonly lineRef: number;
glyphCount(): number;
/** Glyph for a codepoint, falling back to .notdef; null if neither exists. */
glyph(codepoint: number): Glyph | null;
has(codepoint: number): boolean;
}CircleProps
interface CircleProps extends CommonPaintProps {
readonly x: number;
readonly y: number;
readonly diameter: number;
}ClipRect
interface ClipRect {
readonly x: number;
readonly y: number;
readonly width: number;
readonly height: number;
}CommonPaintProps
interface CommonPaintProps {
readonly fill?: Fill;
readonly stroke?: Fill;
readonly strokeWidth?: number;
readonly opacity?: number;
readonly blendMode?: BlendMode;
readonly name?: string;
}EllipseProps
interface EllipseProps extends CommonPaintProps {
readonly x: number;
readonly y: number;
readonly width: number;
readonly height: number;
}EvaluateLimits
interface EvaluateLimits {
readonly maxNodes: number;
readonly maxDepth: number;
}Framebuffer
interface Framebuffer {
readonly width: number;
readonly height: number;
/** Non-premultiplied RGBA, row-major. */
readonly data: Uint8ClampedArray;
}FrameContext
interface FrameContext {
readonly width: number;
readonly height: number;
readonly frame: number;
readonly frameCount: number;
readonly fps: number;
readonly timeMs: number;
readonly progress: number;
}FrameProps
interface FrameProps {
readonly width: number;
readonly height: number;
readonly background?: Color;
readonly children?: LedChild;
}Glyph
interface Glyph {
/** Horizontal advance in 26.6 fixed point (1/64 px). */
readonly adv64: number;
/** Ink offset from the pen position (left/ascender-top origin). */
readonly x0: number;
readonly y0: number;
readonly w: number;
readonly h: number;
/** Row-major 1-bit bitmap, MSB first, bit index = y * w + x. */
readonly bits: Uint8Array;
}GroupProps
interface GroupProps {
readonly x?: number;
readonly y?: number;
/** Box width for flip/rotate. Required when flipX/flipY/rotate is used. */
readonly width?: number;
/** Box height for flip/rotate. Required when flipX/flipY/rotate is used. */
readonly height?: number;
readonly flipX?: boolean;
readonly flipY?: boolean;
readonly rotate?: 0 | 90 | 180 | 270;
/** Integer nearest-neighbor scale factor. */
readonly scale?: number;
/** Clip rect in the group's inner (children) coordinate space. */
readonly clip?: ClipRect;
readonly name?: string;
readonly children?: LedChild;
}IntrinsicNode
interface IntrinsicNode {
readonly kind: string;
readonly props: Readonly<Record<string, unknown>>;
readonly children: readonly IntrinsicNode[];
}LayerProps
interface LayerProps {
readonly opacity?: number;
readonly blendMode?: BlendMode;
readonly mask?: LedElement;
readonly name?: string;
readonly children?: LedChild;
}LedNode
interface LedNode {
readonly $$led: true;
readonly type: string | LedComponent;
readonly props: Readonly<Record<string, unknown>>;
readonly key: string | number | undefined;
}LedPreviewOptions
interface LedPreviewOptions {
/** Emitter size in output pixels. */
readonly size?: number;
/** Dark gap between emitters in output pixels. */
readonly gap?: number;
readonly shape?: "square" | "circle";
readonly background?: Color;
}LinearGradientProps
interface LinearGradientProps {
readonly from: Point;
readonly to: Point;
readonly space?: GradientSpace;
readonly children?: LedChild;
}LineProps
interface LineProps {
readonly from: Point;
readonly to: Point;
readonly color: Color;
readonly opacity?: number;
readonly blendMode?: BlendMode;
readonly name?: string;
}PixelMapProps
interface PixelMapProps {
readonly x?: number;
readonly y?: number;
readonly color: Color;
readonly pixels: readonly Point[];
readonly opacity?: number;
readonly blendMode?: BlendMode;
readonly name?: string;
}PixelProps
interface PixelProps {
readonly x: number;
readonly y: number;
readonly color: Color;
readonly opacity?: number;
readonly blendMode?: BlendMode;
readonly name?: string;
}PolygonProps
interface PolygonProps extends CommonPaintProps {
readonly points: readonly Point[];
}RadialGradientProps
interface RadialGradientProps {
readonly center: Point;
readonly radius: number;
readonly space?: GradientSpace;
readonly children?: LedChild;
}RectProps
interface RectProps extends CommonPaintProps {
readonly x: number;
readonly y: number;
readonly width: number;
readonly height: number;
}RenderOptions
interface RenderOptions {
readonly limits?: EvaluateLimits | undefined;
}RGBA
interface RGBA {
readonly r: number;
readonly g: number;
readonly b: number;
readonly a: number;
}SpriteProps
interface SpriteProps {
readonly x?: number;
readonly y?: number;
/** Single-character keys; null means transparent. */
readonly palette: Readonly<Record<string, Color | null>>;
readonly rows: readonly string[];
readonly opacity?: number;
readonly blendMode?: BlendMode;
readonly name?: string;
}SpriteSheetOptions
interface SpriteSheetOptions {
readonly columns?: number;
}StopProps
interface StopProps {
readonly offset: number;
readonly color: Color;
}TextLayout
interface TextLayout {
readonly placed: readonly PlacedGlyph[];
/** Block dimensions in output px. */
readonly width: number;
readonly height: number;
readonly lines: readonly string[];
readonly scale: number;
readonly ascentPx: number;
}TextLayoutOptions
interface TextLayoutOptions {
/** Output size in px; must be a positive integer multiple of font.size. */
readonly size?: number | undefined;
/** Wrap lines to this many output px (UAX#14 subset line breaking). */
readonly maxWidth?: number | undefined;
/** Extra px between lines in output px (PIL default: 4). */
readonly lineSpacing?: number | undefined;
readonly align?: TextAlign | undefined;
}TextMetrics
interface TextMetrics {
/** Width of the widest line in output px. */
readonly width: number;
/** Total block height in output px. */
readonly height: number;
readonly lines: readonly string[];
}TextProps
interface TextProps {
readonly x: number;
readonly y: number;
readonly text: string;
/** A BitmapFont decoded from a `.ledfont` asset (see decodeBitmapFont). */
readonly font: unknown;
readonly color: Color;
/** Output size in px; must be a positive integer multiple of the font's native size. */
readonly size?: number;
/** PIL-style 2-char anchor (l|m|r + a|t|m|s|b|d). Default "la". */
readonly anchor?: string;
/** Wrap lines to this many px using UAX#14-subset line breaking. */
readonly maxWidth?: number;
readonly align?: "left" | "center" | "right";
/** Extra px between lines. Default 4 (PIL's default). */
readonly lineSpacing?: number;
readonly opacity?: number;
readonly blendMode?: BlendMode;
readonly name?: string;
}Types
BlendMode
type BlendMode = "normal" | "multiply" | "screen" | "add";Color
type Color = string;Fill
type Fill = Color | LedElement;GradientSpace
type GradientSpace = "bounds" | "canvas";LedChild
type LedChild = LedElement | null | undefined | boolean | readonly LedChild[];LedComponent
type LedComponent<P = any> = (props: P) => LedElement | null;LedElement
type LedElement = LedNode;Point
type Point = readonly [number, number];RenderFunction
type RenderFunction = (ctx: FrameContext) => LedElement;TextAlign
type TextAlign = "left" | "center" | "right";TextAnchor
Two-character anchor following PIL's scheme: horizontal l|m|r plus vertical a|t|m|s|b|d ("t" equals "a" and "b" equals "d" for our single-metric fonts). Extensions "i" and "j" align visible ink top and bottom (Pillow's "t" and "b").
type TextAnchor = `${"l" | "m" | "r"}${"a" | "t" | "i" | "j" | "m" | "s" | "b" | "d"}`;