jsx-runtime.d.ts

/** biome-ignore-all lint/correctness/noUnusedVariables: consumed by JSX transform */
/** biome-ignore-all lint/complexity/noBannedTypes: required by JSX spec */

import type { Element as SolidElement } from "solid-js";
import type { AshlarColorInput } from "./src/core/terminal-palette.ts";
import type { TermNode } from "./src/renderer/term-node.ts";

export namespace JSX {
	// Solid 2.0's control-flow components (`Show`, `For`, …) are typed to
	// return Solid's universal `Element` (nodes, arrays, strings, null,
	// undefined). `JSX.Element` must accept that union for them to be valid
	// JSX components; concrete nodes still flow through `TermNode`.
	type Element = SolidElement;
	type ChildNode =
		| Element
		| Element[]
		| ChildNode[]
		| string
		| number
		| null
		| undefined;

	interface IntrinsicElements {
		box: {
			ref?: TermNode | ((node: TermNode) => void);
			role?: string;
			flexDirection?: "row" | "column" | "row-reverse" | "column-reverse";
			flexGrow?: number;
			flexShrink?: number;
			flexBasis?: number | string;
			flexWrap?: "nowrap" | "wrap" | "wrap-reverse";
			alignItems?:
				| "flex-start"
				| "center"
				| "flex-end"
				| "stretch"
				| "baseline";
			alignSelf?:
				| "auto"
				| "flex-start"
				| "center"
				| "flex-end"
				| "stretch"
				| "baseline";
			justifyContent?:
				| "flex-start"
				| "center"
				| "flex-end"
				| "space-between"
				| "space-around"
				| "space-evenly";
			width?: number | string;
			height?: number | string;
			minWidth?: number | string;
			minHeight?: number | string;
			maxWidth?: number | string;
			maxHeight?: number | string;
			position?: "relative" | "absolute";
			top?: number | string;
			right?: number | string;
			bottom?: number | string;
			left?: number | string;
			padding?: number;
			paddingTop?: number;
			paddingBottom?: number;
			paddingLeft?: number;
			paddingRight?: number;
			margin?: number;
			marginTop?: number;
			marginBottom?: number;
			marginLeft?: number;
			marginRight?: number;
			gap?: number;
			borderStyle?:
				| "single"
				| "double"
				| "round"
				| "bold"
				| "horizontal"
				| "none";
			/** Background color */
			bg?: AshlarColorInput;
			/** Border color */
			color?: AshlarColorInput;
			/** Dim every glyph already painted beneath this box. Useful for modal scrims. */
			dimContent?: boolean;
			/**
			 * Internal paint-time color filter: recolors every glyph cell in this
			 * box's region after its subtree paints, mapping local (x, y) within a
			 * width×height box to a packed 24-bit fg (or `undefined` to leave it).
			 * Set by `<Animated>` (`ashlar/animation`) — not meant for direct use.
			 */
			colorField?: (
				x: number,
				y: number,
				width: number,
				height: number,
			) => number | undefined;
			display?: "flex" | "none";
			overflow?: "visible" | "hidden" | "scroll";
			/** Click handler (mouse up on this node) */
			onClick?: (
				event: import("./src/input/parse-mouse.ts").RawMouseEvent,
			) => void;
			/** Mouse enter handler */
			onMouseEnter?: (
				event: import("./src/input/parse-mouse.ts").RawMouseEvent,
			) => void;
			/** Mouse leave handler */
			onMouseLeave?: (
				event: import("./src/input/parse-mouse.ts").RawMouseEvent,
			) => void;
			/** Scroll handler (mouse wheel on this node) */
			onScroll?: (
				event: import("./src/input/parse-mouse.ts").RawMouseEvent,
			) => void;
			children?: ChildNode | ChildNode[];
		};
		hyperlink: {
			ref?: TermNode | ((node: TermNode) => void);
			/** URL to link to (file://, https://, etc.) */
			href: string;
			color?: AshlarColorInput;
			bg?: AshlarColorInput;
			bold?: boolean;
			italic?: boolean;
			underline?: boolean;
			strikethrough?: boolean;
			dim?: boolean;
			children?: string | number | (string | number)[] | null | undefined;
		};
		input: {
			ref?: TermNode | ((node: TermNode) => void);
			/** Current value (controlled) */
			value?: string;
			/** Placeholder text when empty */
			placeholder?: string;
			/** Called when value changes */
			onChange?: (value: string) => void;
			/** Called when Enter is pressed */
			onSubmit?: (value: string) => void;
			/** Text color */
			color?: AshlarColorInput;
			/** Background color */
			bg?: AshlarColorInput;
			/** Placeholder text color */
			placeholderColor?: AshlarColorInput;
			/** Whether the input is focused and accepting keys */
			focused?: boolean;
			/** Enable multi-line editing (Enter inserts newline, Ctrl+Enter submits). Default: false (Enter submits). */
			multiline?: boolean;
			/** In multiline mode, Enter submits and Shift+Enter inserts a newline. */
			submitOnEnter?: boolean;
			/** Cursor character (default: block via inverse) */
			cursorChar?: string;
			width?: number | string;
			height?: number | string;
		};
		text: {
			ref?: TermNode | ((node: TermNode) => void);
			color?: AshlarColorInput;
			bg?: AshlarColorInput;
			bold?: boolean;
			italic?: boolean;
			underline?: boolean;
			strikethrough?: boolean;
			dim?: boolean;
			inverse?: boolean;
			wrap?:
				| "word"
				| "truncate"
				| "truncate-end"
				| "truncate-middle"
				| "truncate-start";
			onClick?: (
				event: import("./src/input/parse-mouse.ts").RawMouseEvent,
			) => void;
			onMouseEnter?: (
				event: import("./src/input/parse-mouse.ts").RawMouseEvent,
			) => void;
			onMouseLeave?: (
				event: import("./src/input/parse-mouse.ts").RawMouseEvent,
			) => void;
			children?: string | number | (string | number)[] | null | undefined;
		};
	}

	interface ElementChildrenAttribute {
		children: {};
	}
}