import React, { type PropsWithChildren, type Ref } from 'react'; import type { Except } from 'type-fest'; import type { DOMElement } from '../core/dom.js'; import type { ClickEvent } from '../core/events/click-event.js'; import type { FocusEvent } from '../core/events/focus-event.js'; import type { KeyboardEvent } from '../core/events/keyboard-event.js'; import type { Styles } from '../core/styles.js'; import * as warn from '../core/warn.js'; export type Props = Except & { ref?: Ref; /** * Tab order index. Nodes with `tabIndex >= 0` participate in * Tab/Shift+Tab cycling; `-1` means programmatically focusable only. */ tabIndex?: number; /** * Focus this element when it mounts. Like the HTML `autofocus` * attribute — the FocusManager calls `focus(node)` during the * reconciler's `commitMount` phase. */ autoFocus?: boolean; /** * Fired on left-button click (press + release without drag). Only works * inside `` where mouse tracking is enabled — no-op * otherwise. The event bubbles from the deepest hit Box up through * ancestors; call `event.stopImmediatePropagation()` to stop bubbling. */ onClick?: (event: ClickEvent) => void; onFocus?: (event: FocusEvent) => void; onFocusCapture?: (event: FocusEvent) => void; onBlur?: (event: FocusEvent) => void; onBlurCapture?: (event: FocusEvent) => void; onKeyDown?: (event: KeyboardEvent) => void; onKeyDownCapture?: (event: KeyboardEvent) => void; /** * Fired when the mouse moves into this Box's rendered rect. Like DOM * `mouseenter`, does NOT bubble — moving between children does not * re-fire on the parent. Only works inside `` where * mode-1003 mouse tracking is enabled. */ onMouseEnter?: () => void; /** Fired when the mouse moves out of this Box's rendered rect. */ onMouseLeave?: () => void; }; /** * `` is an essential Ink component to build your layout. It's like `
` in the browser. */ function Box({ children, flexWrap = 'nowrap', flexDirection = 'row', flexGrow = 0, flexShrink = 1, ref, tabIndex, autoFocus, onClick, onFocus, onFocusCapture, onBlur, onBlurCapture, onMouseEnter, onMouseLeave, onKeyDown, onKeyDownCapture, ...style }: PropsWithChildren): React.ReactNode { // Warn if spacing values are not integers to prevent fractional layout dimensions warn.ifNotInteger(style.margin, 'margin'); warn.ifNotInteger(style.marginX, 'marginX'); warn.ifNotInteger(style.marginY, 'marginY'); warn.ifNotInteger(style.marginTop, 'marginTop'); warn.ifNotInteger(style.marginBottom, 'marginBottom'); warn.ifNotInteger(style.marginLeft, 'marginLeft'); warn.ifNotInteger(style.marginRight, 'marginRight'); warn.ifNotInteger(style.padding, 'padding'); warn.ifNotInteger(style.paddingX, 'paddingX'); warn.ifNotInteger(style.paddingY, 'paddingY'); warn.ifNotInteger(style.paddingTop, 'paddingTop'); warn.ifNotInteger(style.paddingBottom, 'paddingBottom'); warn.ifNotInteger(style.paddingLeft, 'paddingLeft'); warn.ifNotInteger(style.paddingRight, 'paddingRight'); warn.ifNotInteger(style.gap, 'gap'); warn.ifNotInteger(style.columnGap, 'columnGap'); warn.ifNotInteger(style.rowGap, 'rowGap'); return ( ) => void} onFocusCapture={onFocusCapture as unknown as (event: React.FocusEvent) => void} onBlur={onBlur as unknown as (event: React.FocusEvent) => void} onBlurCapture={onBlurCapture as unknown as (event: React.FocusEvent) => void} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} onKeyDown={onKeyDown as unknown as (event: React.KeyboardEvent) => void} onKeyDownCapture={onKeyDownCapture as unknown as (event: React.KeyboardEvent) => void} style={{ flexWrap, flexDirection, flexGrow, flexShrink, ...style, overflowX: style.overflowX ?? style.overflow ?? 'visible', overflowY: style.overflowY ?? style.overflow ?? 'visible', }} > {children} ); } export default Box;