Commands, settings, SDK functions, anything in the docs.

Reference

@ledable/sdk/graphics

The JSX elements and functions that draw frames.

On this page

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): LedElement

Ellipse

function Ellipse(props: EllipseProps): LedElement

Frame

function Frame(props: FrameProps): LedElement

Group

function Group(props: GroupProps): LedElement

Layer

function Layer(props: LayerProps): LedElement

Line

function Line(props: LineProps): LedElement

LinearGradient

function LinearGradient(props: LinearGradientProps): LedElement

Pixel

function Pixel(props: PixelProps): LedElement

PixelMap

function PixelMap(props: PixelMapProps): LedElement

Polygon

function Polygon(props: PolygonProps): LedElement

RadialGradient

function RadialGradient(props: RadialGradientProps): LedElement

Rect

function Rect(props: RectProps): LedElement

Sprite

function Sprite(props: SpriteProps): LedElement

Stop

function Stop(props: StopProps): LedElement

Text

function Text(props: TextProps): LedElement

Functions

anchorOffset

Offset of the block's top-left from the anchor point, in output px.

function anchorOffset(anchor: TextAnchor, layout: TextLayout): AnchorOffset

blit

function blit(dst: Framebuffer, src: Framebuffer, dx: number, dy: number): void

brightenColor

Raise dark LED text toward the legacy sRGB luminance threshold, preserving hue.

function brightenColor(color: Color, threshold = 150): Color

clamp

function clamp(value: number, min: number, max: number): number

clamp01

function clamp01(value: number): number

cloneFramebuffer

function cloneFramebuffer(fb: Framebuffer): Framebuffer

compositeFramebuffer

Draw a bitmap at an integer offset, clipping its edges and preserving alpha.

function compositeFramebuffer(
  dst: Framebuffer,
  src: Framebuffer,
  dx: number,
  dy: number,
): void

containRgb

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): Framebuffer

createFramebuffer

function createFramebuffer(width: number, height: number): Framebuffer

createFrameContext

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): FrameContext

decodeBitmapFont

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): BitmapFont

easeInCubic

function easeInCubic(t: number): number

easeInOutCubic

function easeInOutCubic(t: number): number

easeInOutQuad

function easeInOutQuad(t: number): number

easeInQuad

function easeInQuad(t: number): number

easeOutCubic

function easeOutCubic(t: number): number

easeOutQuad

function easeOutQuad(t: number): number

evaluateElement

Expand function components and fragments into a tree of intrinsic nodes.

function evaluateElement(
  element: LedElement,
  limits: EvaluateLimits = DEFAULT_LIMITS,
): IntrinsicNode

evaluateToNodes

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): void

framebufferToText

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>>,
): string

framesToSheet

Pack equally sized frames into one row-major sheet. Unused trailing slots stay transparent black.

function framesToSheet(
  frames: readonly Framebuffer[],
  options: SpriteSheetOptions = {},
): Framebuffer

getPixel

function getPixel(fb: Framebuffer, x: number, y: number): RGBA

glyphBit

function glyphBit(glyph: Glyph, x: number, y: number): boolean

halfBrightness

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): Framebuffer

isBitmapFont

function isBitmapFont(value: unknown): value is BitmapFont

isLedElement

function isLedElement(value: unknown): value is LedElement

layoutText

function layoutText(
  font: BitmapFont,
  text: string,
  options: TextLayoutOptions = {},
): TextLayout

lerp

function lerp(a: number, b: number, t: number): number

measureText

function measureText(
  font: BitmapFont,
  text: string,
  options: TextLayoutOptions = {},
): TextMetrics

measureTextBounds

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): RGBA

renderAnimation

function renderAnimation(render: RenderFunction, options: AnimationOptions): Framebuffer[]

renderFrame

function renderFrame(element: LedElement, options: RenderOptions = {}): Framebuffer

renderLedPreview

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 = {}): Framebuffer

rgba

function rgba(r: number, g: number, b: number, a = 255): RGBA

scaleNearest

Nearest-neighbor integer enlargement for previews.

function scaleNearest(fb: Framebuffer, factor: number): Framebuffer

setPixel

function setPixel(fb: Framebuffer, x: number, y: number, color: RGBA): void

textPixels

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): RGBA

Constants

DEFAULT_LIMITS

const DEFAULT_LIMITS: EvaluateLimits = { maxNodes: 20000, maxDepth: 128 }

Fragment

const Fragment = "led:fragment"

MAX_TEXT_LENGTH

const MAX_TEXT_LENGTH = 4096

NOTDEF_CODEPOINT

Sentinel codepoint for the .notdef (missing glyph) entry in baked data.

const NOTDEF_CODEPOINT = 0x110000

Classes

LedError

class LedError extends Error

Interfaces

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"}`;