UNPKG

@types/react-blessed

Version:
291 lines (247 loc) 12.4 kB
import * as Blessed from "blessed"; import * as React from "react"; export {}; /* RENDERER *****************************************************************/ // eslint-disable-next-line @typescript-eslint/no-invalid-void-type export type Callback = () => void | null | undefined; export type renderer = (c: React.JSX.Element, s: Blessed.Widgets.Screen, callback?: Callback) => React.Component | null; export function render(c: React.JSX.Element, s: Blessed.Widgets.Screen, callback?: Callback): React.Component | null; export function createBlessedRenderer(bls: any): renderer; /* BLESSED ELEMENTS **********************************************************/ export type Element = Blessed.Widgets.BlessedElement; export type ScrollableBoxElement = Blessed.Widgets.ScrollableBoxElement; export type ScrollableTextElement = Blessed.Widgets.ScrollableTextElement; export type BoxElement = Blessed.Widgets.BoxElement; export type TextElement = Blessed.Widgets.TextElement; export type LineElement = Blessed.Widgets.LineElement; export type BigTextElement = Blessed.Widgets.BigTextElement; export type ListElement = Blessed.Widgets.ListElement; export type FileManagerElement = Blessed.Widgets.FileManagerElement; export type ListTableElement = Blessed.Widgets.ListTableElement; export type ListbarElement = Blessed.Widgets.ListbarElement; export type InputElement = Blessed.Widgets.InputElement; export type TextareaElement = Blessed.Widgets.TextareaElement; export type TextboxElement = Blessed.Widgets.TextboxElement; export type ButtonElement = Blessed.Widgets.ButtonElement; export type CheckboxElement = Blessed.Widgets.CheckboxElement; export type RadioSetElement = Blessed.Widgets.RadioSetElement; export type RadioButtonElement = Blessed.Widgets.RadioButtonElement; export type TableElement = Blessed.Widgets.TableElement; export type PromptElement = Blessed.Widgets.PromptElement; export type QuestionElement = Blessed.Widgets.QuestionElement; export type MessageElement = Blessed.Widgets.MessageElement; export type LoadingElement = Blessed.Widgets.LoadingElement; export type LogElement = Blessed.Widgets.Log; export type ProgressBarElement = Blessed.Widgets.ProgressBarElement; export type TerminalElement = Blessed.Widgets.TerminalElement; export type LayoutElement = Blessed.Widgets.LayoutElement; /* EVENTS *******************************************************************/ type Prefix<T extends string, P extends string> = `${T}${P}`; // create event handlers that map to 'blessed' events. see // https://github.com/Yomguithereal/react-blessed/blob/f5e1f791dea1788745695d557040b91f573f9ef5/src/fiber/events.js type EventHandlerProp<T extends string, E extends (...args: never) => void> = { [key in `on${Capitalize<T>}`]?: E; }; // 'react-blessed' handles 'blessed' events by matching event names to // handlers by prefixing event names with with "on" and camelCasing the // result. this cannot be fully recreated in TS so we must manually map them // here. type ScreenElement = "click" | "mouseover" | "mouseout" | "mouseup"; type ScreenElementPrefix = "element"; type ExludedScreenEventNames = Prefix<ScreenElementPrefix, Prefix<" ", ScreenElement>>; type CamelCasedScreenEventNames = Prefix<ScreenElementPrefix, Capitalize<ScreenElement>>; type ScreenEventNames = | Exclude<Blessed.Widgets.NodeScreenEventType, ExludedScreenEventNames> | CamelCasedScreenEventNames; type GenericContentPrefix = "set" | "parsed"; type GenericContent = "content"; type ExludedGenericEventNames = Prefix<GenericContentPrefix, Prefix<" ", GenericContent>>; type CamelCasedGenericEventNames = Prefix<GenericContentPrefix, Capitalize<GenericContent>>; type GenericEventNames = | Exclude<Blessed.Widgets.NodeGenericEventType, ExludedGenericEventNames> | CamelCasedGenericEventNames; type ProgressBarEventNames = Parameters<Blessed.Widgets.ProgressBarElement["on"]>[0]; type SpreadableArgs<T, K = T extends unknown[] ? T : [T]> = K; interface EventHandler<T> { (...args: SpreadableArgs<T>): void; } // event args need to be manually typed because Blessed.Widgets.NodeWithEvents // overloads the event handlers (making it impossible? to extract the // parameters with TS utils) and does not expose the event callbacks as // importable types export type ScreenEvent = Blessed.Widgets.Screen; export type ScreenEventHandler = EventHandler<ScreenEvent>; type ScreenEventProps = EventHandlerProp<ScreenEventNames, ScreenEventHandler>; export type MouseEvent = Blessed.Widgets.Events.IMouseEventArg; export type MouseEventHandler = EventHandler<MouseEvent>; type MouseEventProps = EventHandlerProp<Blessed.Widgets.NodeMouseEventType, MouseEventHandler>; export type GenericEvent = undefined; export type GenericEventHandler = EventHandler<GenericEvent>; type GenericEventProps = EventHandlerProp<GenericEventNames, GenericEventHandler>; export type KeyPressEvent = [key: any, event: Blessed.Widgets.Events.IKeyEventArg]; export type KeyPressEventHandler = EventHandler<KeyPressEvent>; type KeyPressEventProps = EventHandlerProp<"keypress", KeyPressEventHandler>; export type WarningEvent = string; export type WarningEventHandler = EventHandler<WarningEvent>; type WarningEventProps = EventHandlerProp<"warning", WarningEventHandler>; export type ProgressBarEvent = undefined; export type ProgressBarEventHandler = EventHandler<ProgressBarEvent>; type ProgressBarEventProps = EventHandlerProp<ProgressBarEventNames, ProgressBarEventHandler>; interface EventProps extends ScreenEventProps, GenericEventProps, MouseEventProps, KeyPressEventProps, WarningEventProps {} /* BLESSED-REACT LOCALLY DEFINED PROPS **************************************/ // @types/blessed defines 'styles' as 'any' but 'blessed' can only can only // take certain values. define them here. interface BorderStyle { type?: "line" | "bg"; ch?: string; bg?: string; fg?: string; bold?: boolean; underline?: boolean; } interface ItemStyle { bg?: string; fg?: string; bold?: boolean; underline?: boolean; blink?: boolean; inverse?: boolean; invisible?: boolean; } interface ListStyle extends ElementStyle { selected?: ItemStyle; item?: ItemStyle; } interface ProgressBarStyle extends ElementStyle { bar?: { bg?: string; fg?: string }; } interface ElementStyle extends ItemStyle { border?: BorderStyle; focus?: { bg?: string; fg?: string }; hover?: { bg?: string; fg?: string }; transparent?: boolean; scrollbar?: { bg?: string; fg?: string; track?: { bg?: string; fg?: string } }; } // remove indexers // https://stackoverflow.com/questions/51465182/how-to-remove-index-signature-using-mapped-types type KnownKeys<T> = { [K in keyof T as string extends K ? never : number extends K ? never : K]: T[K]; }; type WithClassProp<T, K = T | undefined | false | null> = T & { class?: K | K[] }; type ProgressBarProps<T> = T extends ProgressBarElement ? ProgressBarEventProps & { style?: ProgressBarStyle } : {}; type ListProps<T> = T extends ListElement ? ProgressBarEventProps & { style?: ListStyle; selected?: number } : {}; // layout does not require prop 'layout' in Blessed.Widgets.LayoutOptions--make it optional type LayoutProps<T> = T extends LayoutElement ? Partial<Blessed.Widgets.LayoutOptions> : {}; // remove {[key: string]: any} indexer defined in Blessed.Widgets.IOptions. // 'blessed' doesn't exist in a DOM so it probably doesn't make sense to allow any property type FilterOptions<T extends Record<any, any>> = Partial<Omit<KnownKeys<T>, "style" | "children">>; type ModifiedBlessedOptions<T extends Record<any, any>> = FilterOptions<T> & { children?: React.ReactNode; style?: ElementStyle; } & EventProps; /* REACT-BLESSED JSX ********************************************************/ /** * this type can be used to get props for 'react-blessed' elements in the same * manner that React.HTMLProps can be used to get DOM element props. e.g. * ```ts * import { FC } from 'react' * import { BlessedProps, BoxElement } from 'react-blessed'; * type MyBoxProps = BlessedProps<BoxElement>; * const MyBox: React.FC<MyBoxProps> = props => <box {...props} />; * ``` * @see DetailedBlessedProps * @see React.HTMLAttributes */ export type BlessedAttributes<E extends Element> = WithClassProp< ModifiedBlessedOptions<E["options"]> & ProgressBarProps<E> & ListProps<E> & LayoutProps<E> >; /** * mirrors react prop generation for HTML JSX.IntrinsicElements. * @see React.DetailedHTMLProps */ export type DetailedBlessedProps<E extends Element> = BlessedAttributes<E> & React.ClassAttributes<E>; export interface BlessedIntrinsicElements { element: DetailedBlessedProps<Element>; box: DetailedBlessedProps<BoxElement>; scrollablebox: DetailedBlessedProps<ScrollableBoxElement>; scrollabletext: DetailedBlessedProps<ScrollableTextElement>; bigtext: DetailedBlessedProps<BigTextElement>; list: DetailedBlessedProps<ListElement>; filemanager: DetailedBlessedProps<FileManagerElement>; listtable: DetailedBlessedProps<ListTableElement>; listbar: DetailedBlessedProps<ListbarElement>; textbox: DetailedBlessedProps<TextboxElement>; checkbox: DetailedBlessedProps<CheckboxElement>; radioset: DetailedBlessedProps<RadioSetElement>; radiobutton: DetailedBlessedProps<RadioButtonElement>; prompt: DetailedBlessedProps<PromptElement>; question: DetailedBlessedProps<QuestionElement>; message: DetailedBlessedProps<MessageElement>; loading: DetailedBlessedProps<LoadingElement>; log: DetailedBlessedProps<LogElement>; progressbar: DetailedBlessedProps<ProgressBarElement>; terminal: DetailedBlessedProps<Blessed.Widgets.TerminalElement>; layout: DetailedBlessedProps<Blessed.Widgets.LayoutElement>; // escape: Blessed.escape is not an element // program: Blessed.Widgets.Program is not an element } // 'react-blessed' accepts JSX with 'blessed' element names with and without // a 'blessed-' prefix. see // https://github.com/Yomguithereal/react-blessed/blob/f5e1f791dea1788745695d557040b91f573f9ef5/src/fiber/fiber.js#L49 export type BlessedIntrinsicElementsPrefixed = { [Key in keyof BlessedIntrinsicElements as Prefix<"blessed-", Key>]: BlessedIntrinsicElements[Key]; }; // it isn't possible to use the global JSX namespace because some 'blessed' // elements will collide with ones set in react defs. // augment react JSX when old JSX transform is used declare module "react" { namespace JSX { interface ButtonHTMLAttributes<T> extends HTMLAttributes<T>, Omit< DetailedBlessedProps<ButtonElement>, "draggable" | "onBlur" | "onClick" | "onFocus" | "onResize" | "ref" | "style" > {} interface TableHTMLAttributes<T> extends HTMLAttributes<T>, Omit< DetailedBlessedProps<TableElement>, "border" | "draggable" | "onBlur" | "onClick" | "onFocus" | "onResize" | "ref" | "style" > {} interface TextareaHTMLAttributes<T> extends HTMLAttributes<T>, Omit< DetailedBlessedProps<TextElement>, "draggable" | "fill" | "focusable" | "onBlur" | "onClick" | "onFocus" | "onResize" | "ref" | "style" > {} interface InputHTMLAttributes<T> extends HTMLAttributes<T>, Omit< DetailedBlessedProps<InputElement>, "draggable" | "onBlur" | "onClick" | "onFocus" | "onResize" | "ref" | "style" > {} interface SVGLineElementAttributes<T> extends SVGProps<T>, Omit< DetailedBlessedProps<LineElement>, "focusable" | "onBlur" | "onClick" | "onFocus" | "onResize" | "orientation" | "ref" | "style" > {} interface SVGTextElementAttributes<T> extends SVGProps<T>, Omit< DetailedBlessedProps<TextElement>, "fill" | "focusable" | "onBlur" | "onClick" | "onFocus" | "onResize" | "ref" | "style" > {} // set IntrinsicElements to 'react-blessed' elements both with and without // 'blessed-' prefix interface IntrinsicElements extends BlessedIntrinsicElementsPrefixed, BlessedIntrinsicElements {} } }