UNPKG

@teaui/react

Version:

React Reconciler and renderer for TeaUI

407 lines 20.9 kB
import React, { forwardRef, useCallback, useMemo, useState } from 'react'; import { isMouseClicked } from '@teaui/core'; export { FontStyle } from './components/FontStyle.js'; export const Align = forwardRef(function Align({ children, ...props }, ref) { return (React.createElement("tui-align", { ref: ref, ...props }, children)); }); Align.down = forwardRef(function AlignDown({ children, ...props }, ref) { return (React.createElement("tui-align", { ref: ref, direction: "down", ...props }, children)); }); Align.up = forwardRef(function AlignUp({ children, ...props }, ref) { return (React.createElement("tui-align", { ref: ref, direction: "up", ...props }, children)); }); Align.right = forwardRef(function AlignRight({ children, ...props }, ref) { return (React.createElement("tui-align", { ref: ref, direction: "right", ...props }, children)); }); Align.left = forwardRef(function AlignLeft({ children, ...props }, ref) { return (React.createElement("tui-align", { ref: ref, direction: "left", ...props }, children)); }); Align.column = Align.right; Align.Row = function AlignRow({ children, ...props }) { return React.createElement("tui-align-row", { ...props }, children); }; Align.Column = Align.Row; export function Br() { return React.createElement("tui-br", null); } export const Badge = forwardRef(function Badge(reactProps, ref) { return React.createElement("tui-badge", { ref: ref, ...reactProps }); }); export const Breadcrumb = forwardRef(function Breadcrumb(reactProps, ref) { return React.createElement("tui-breadcrumb", { ref: ref, ...reactProps }); }); export const Calendar = forwardRef(function Calendar(reactProps, ref) { return React.createElement("tui-calendar", { ref: ref, ...reactProps }); }); export const Canvas = forwardRef(function Canvas(reactProps, ref) { return React.createElement("tui-canvas", { ref: ref, ...reactProps }); }); export const Checkbox = forwardRef(function Checkbox(reactProps, ref) { return React.createElement("tui-checkbox", { ref: ref, ...reactProps }); }); export const Toggle = forwardRef(function Toggle(reactProps, ref) { return React.createElement("tui-toggle", { ref: ref, ...reactProps }); }); export const CollapsibleText = forwardRef(function CollapsibleText(reactProps, ref) { return React.createElement("tui-collapsible-text", { ref: ref, ...reactProps }); }); export const ConsoleLog = forwardRef(function ConsoleLog(reactProps, ref) { return React.createElement("tui-console", { ref: ref, ...reactProps }); }); export const Digits = forwardRef(function Digits(reactProps, ref) { return React.createElement("tui-digits", { ref: ref, ...reactProps }); }); export function Dropdown(reactProps) { return React.createElement("tui-dropdown", { ...reactProps }); } export const HotKey = forwardRef(function HotKey(reactProps, ref) { return React.createElement("tui-hotkey", { ref: ref, ...reactProps }); }); export const Keyboard = forwardRef(function Keyboard({ children, ...props }, ref) { return (React.createElement("tui-keyboard", { ref: ref, ...props }, children)); }); export const Mouse = forwardRef(function Mouse({ children, ...props }, ref) { return (React.createElement("tui-mouse", { ref: ref, ...props }, children)); }); export const H1 = forwardRef(function H1({ children, ...reactProps }, ref) { return React.createElement("tui-h1", { ref: ref, text: children ?? reactProps.text, ...reactProps }); }); export const H2 = forwardRef(function H2({ children, ...reactProps }, ref) { return React.createElement("tui-h2", { ref: ref, text: children ?? reactProps.text, ...reactProps }); }); export const H3 = forwardRef(function H3({ children, ...reactProps }, ref) { return React.createElement("tui-h3", { ref: ref, text: children ?? reactProps.text, ...reactProps }); }); export const H4 = forwardRef(function H4({ children, ...reactProps }, ref) { return React.createElement("tui-h4", { ref: ref, text: children ?? reactProps.text, ...reactProps }); }); export const H5 = forwardRef(function H5({ children, ...reactProps }, ref) { return React.createElement("tui-h5", { ref: ref, text: children ?? reactProps.text, ...reactProps }); }); export const H6 = forwardRef(function H6({ children, ...reactProps }, ref) { return React.createElement("tui-h6", { ref: ref, text: children ?? reactProps.text, ...reactProps }); }); export const Input = forwardRef(function Input(reactProps, ref) { return React.createElement("tui-input", { ref: ref, ...reactProps }); }); export const Legend = forwardRef(function Legend(reactProps, ref) { return React.createElement("tui-legend", { ref: ref, ...reactProps }); }); export const AutoLegend = forwardRef(function AutoLegend(reactProps, ref) { return React.createElement("tui-auto-legend", { ref: ref, ...reactProps }); }); export const Progress = forwardRef(function Progress(reactProps, ref) { return React.createElement("tui-progress", { ref: ref, ...reactProps }); }); export const Separator = forwardRef(function Separator(reactProps, ref) { return React.createElement("tui-separator", { ref: ref, ...reactProps }); }); Separator.horizontal = forwardRef(function SeparatorHorizontal(reactProps, ref) { return React.createElement("tui-separator", { ref: ref, direction: "horizontal", ...reactProps }); }); Separator.vertical = forwardRef(function SeparatorVertical(reactProps, ref) { return React.createElement("tui-separator", { ref: ref, direction: "vertical", ...reactProps }); }); export const Slider = forwardRef(function Slider(reactProps, ref) { return React.createElement("tui-slider", { ref: ref, ...reactProps }); }); Slider.horizontal = forwardRef(function SliderHorizontal(reactProps, ref) { return React.createElement("tui-slider", { ref: ref, direction: "horizontal", ...reactProps }); }); Slider.vertical = forwardRef(function SliderVertical(reactProps, ref) { return React.createElement("tui-slider", { ref: ref, direction: "vertical", ...reactProps }); }); export const Space = forwardRef(function Space(reactProps, ref) { return React.createElement("tui-space", { ref: ref, ...reactProps }); }); export const Spinner = forwardRef(function Spinner(reactProps, ref) { return React.createElement("tui-spinner", { ref: ref, ...reactProps }); }); export const Logo = forwardRef(function Logo(reactProps, ref) { return React.createElement("tui-logo", { ref: ref, ...reactProps }); }); export const ZStack = forwardRef(function ZStack(reactProps, ref) { return React.createElement("tui-zstack", { ref: ref, ...reactProps }); }); export const At = forwardRef(function At({ children, ...props }, ref) { return (React.createElement("tui-at", { ref: ref, ...props }, children)); }); At.topLeft = forwardRef(function AtTopLeft({ children, ...props }, ref) { return (React.createElement("tui-at", { ref: ref, location: "top-left", ...props }, children)); }); At.topCenter = forwardRef(function AtTopCenter({ children, ...props }, ref) { return (React.createElement("tui-at", { ref: ref, location: "top-center", ...props }, children)); }); At.topRight = forwardRef(function AtTopRight({ children, ...props }, ref) { return (React.createElement("tui-at", { ref: ref, location: "top-right", ...props }, children)); }); At.left = forwardRef(function AtLeft({ children, ...props }, ref) { return (React.createElement("tui-at", { ref: ref, location: "left", ...props }, children)); }); At.center = forwardRef(function AtCenter({ children, ...props }, ref) { return (React.createElement("tui-at", { ref: ref, location: "center", ...props }, children)); }); At.right = forwardRef(function AtRight({ children, ...props }, ref) { return (React.createElement("tui-at", { ref: ref, location: "right", ...props }, children)); }); At.bottomLeft = forwardRef(function AtBottomLeft({ children, ...props }, ref) { return (React.createElement("tui-at", { ref: ref, location: "bottom-left", ...props }, children)); }); At.bottomCenter = forwardRef(function AtBottomCenter({ children, ...props }, ref) { return (React.createElement("tui-at", { ref: ref, location: "bottom-center", ...props }, children)); }); At.bottomRight = forwardRef(function AtBottomRight({ children, ...props }, ref) { return (React.createElement("tui-at", { ref: ref, location: "bottom-right", ...props }, children)); }); export const ToggleGroup = forwardRef(function ToggleGroup(reactProps, ref) { return React.createElement("tui-toggle-group", { ref: ref, ...reactProps }); }); function TreeItems({ items, render, getChildren, expanded, toggle, prefix, ancestors, }) { return (React.createElement(React.Fragment, null, items.map((item, index) => { const path = `${prefix}.${index}`; const children = getChildren?.(item); const hasChildren = children != null && children.length > 0; const isExpanded = expanded.has(path); const isLast = index === items.length - 1; let line = ''; for (const ancestor of ancestors) { line += ancestor.isLast ? ' ' : TREE_VLINE; } if (hasChildren) { line += isLast ? TREE_LAST_BRANCH : TREE_BRANCH; line += isExpanded ? TREE_EXPANDED : TREE_COLLAPSED; } else { line += isLast ? TREE_LAST_LEAF : TREE_LEAF; } return (React.createElement(React.Fragment, { key: path }, React.createElement("tui-mouse", { mouse: "mouse.button.left", onMouse: event => { if (hasChildren && isMouseClicked(event)) { toggle(path); } } }, React.createElement("tui-stack", { direction: "right" }, React.createElement("tui-text", null, line), render(item))), isExpanded && hasChildren && children && (React.createElement(TreeItems, { items: children, render: render, getChildren: getChildren, expanded: expanded, toggle: toggle, prefix: path, ancestors: [...ancestors, { isLast }] })))); }))); } const TREE_VLINE = '│ '; const TREE_BRANCH = '├'; const TREE_LAST_BRANCH = '└'; const TREE_LEAF = '├──╴'; const TREE_LAST_LEAF = '└──╴'; const TREE_COLLAPSED = '─╴▹'; const TREE_EXPANDED = '─╴▿'; export function Tree(reactProps) { const { title, data, render, getChildren, ...viewProps } = reactProps; const [expanded, setExpanded] = useState(new Set()); const toggle = useCallback((path) => { setExpanded(prev => { const next = new Set(prev); if (next.has(path)) { next.delete(path); } else { next.add(path); } return next; }); }, []); return (React.createElement("tui-stack", { direction: "down", ...viewProps }, typeof title === 'string' ? React.createElement("tui-text", null, title) : title, React.createElement(TreeItems, { items: data, render: render, getChildren: getChildren, expanded: expanded, toggle: toggle, prefix: "", ancestors: [] }))); } export const Modal = forwardRef(function Modal({ children, ...props }, ref) { return (React.createElement("tui-modal", { ref: ref, ...props }, children)); }); //// /// "Simple" containers // export function Alert({ children, ...props }) { return React.createElement("tui-alert", { ...props }, children); } export const Callout = forwardRef(function Callout({ children, ...props }, ref) { return (React.createElement("tui-callout", { ref: ref, ...props }, children)); }); export const Box = forwardRef(function Box({ children, ...props }, ref) { return (React.createElement("tui-box", { ref: ref, ...props }, children)); }); export const Button = forwardRef(function Button({ children, ...props }, ref) { return (React.createElement("tui-button", { ref: ref, ...props }, children)); }); export const Collapsible = forwardRef(function Collapsible({ collapsed, expanded, ...props }, ref) { return (React.createElement("tui-collapsible", { ref: ref, ...props }, collapsed, expanded)); }); export const Stack = forwardRef(function Stack({ children, ...props }, ref) { return (React.createElement("tui-stack", { ref: ref, ...props }, children)); }); Stack.down = forwardRef(function StackDown({ children, ...props }, ref) { return (React.createElement("tui-stack", { ref: ref, direction: "down", ...props }, children)); }); Stack.up = forwardRef(function StackUp({ children, ...props }, ref) { return (React.createElement("tui-stack", { ref: ref, direction: "up", ...props }, children)); }); Stack.right = forwardRef(function StackRight({ children, ...props }, ref) { return (React.createElement("tui-stack", { ref: ref, direction: "right", ...props }, children)); }); Stack.left = forwardRef(function StackLeft({ children, ...props }, ref) { return (React.createElement("tui-stack", { ref: ref, direction: "left", ...props }, children)); }); export const Geometry = forwardRef(function Geometry({ children, ...props }, ref) { return (React.createElement("tui-geometry", { ref: ref, ...props }, children)); }); export const Scrollable = forwardRef(function Scrollable({ children, ...props }, ref) { return (React.createElement("tui-scrollable", { ref: ref, ...props }, children)); }); Scrollable.down = forwardRef(function ScrollableDown({ children, ...props }, ref) { return (React.createElement("tui-scrollable", { ref: ref, direction: "down", ...props }, children)); }); Scrollable.up = forwardRef(function ScrollableUp({ children, ...props }, ref) { return (React.createElement("tui-scrollable", { ref: ref, direction: "up", ...props }, children)); }); Scrollable.right = forwardRef(function ScrollableRight({ children, ...props }, ref) { return (React.createElement("tui-scrollable", { ref: ref, direction: "right", ...props }, children)); }); Scrollable.left = forwardRef(function ScrollableLeft({ children, ...props }, ref) { return (React.createElement("tui-scrollable", { ref: ref, direction: "left", ...props }, children)); }); /** * <Style /> is similar to <Text/> but only allows inline styles (bold, etc). * Does not support align or wrap (block styles). Does not support 'font', because * font is not encodable via SGR codes (and that's how I'm styling and * concatenating the text nodes). */ export const Style = forwardRef(function Style(reactProps, ref) { return React.createElement("tui-style", { ref: ref, ...reactProps }); }); /** * <Text /> is a container that sets the text properties of child TextLiterals * (font, style) and TextContainers (wrap, alignment) */ export const Text = forwardRef(function Text(reactProps, ref) { return React.createElement("tui-text", { ref: ref, ...reactProps }); }); /** * List component with virtualized row rendering via React children. * * Similar to Table, this accepts a `renderItem` callback that returns JSX. * The core List handles scrolling, keyboard/mouse navigation, and selection * highlighting, while React renders each visible item. * * ```tsx * <List * data={items} * renderItem={(item, index) => <Text>{item.name}</Text>} * onSelect={(item) => console.info('Selected:', item)} * /> * ``` */ export function ScrollableList(reactProps) { const { data, renderItem, filter, ...props } = reactProps; const filteredData = useMemo(() => (filter ? data.filter(filter) : data), [data, filter]); // The React List omits renderItem from the core props. Instead, it renders // data items as React children. The core List detects the missing renderItem // and renders its Container children by index, which the reconciler manages. return (React.createElement("tui-list", { data: filteredData, ...props }, filteredData.map((item, index) => (React.createElement(React.Fragment, { key: index }, renderItem(item, index)))))); } /** * Table component with optional virtualized row rendering. * * When `renderItem` is provided, only visible rows are rendered as React children, * enabling efficient rendering of large datasets. The Geometry component measures * available space, and only the visible slice of data is passed through the reconciler. * * When only `format` is provided, the core Table handles all rendering directly * (no virtualization needed since cells are plain strings). */ export function Table(reactProps) { const { data, columns, renderItem, format, ...props } = reactProps; if (!renderItem) { // Simple mode: core Table handles everything via format callback return (React.createElement("tui-table", { data: data, columns: columns, format: format ?? (() => ''), ...props })); } // Virtualized mode: React renders only visible rows. // Geometry measures available space so we can pass the visible slice through // the reconciler while the core Table renders the header/chrome and handles // row highlighting. const [bodyHeight, setBodyHeight] = useState(20); const handleLayout = useCallback((size) => { // Table uses 2 rows for header + separator. setBodyHeight(Math.max(0, size.height - 2)); }, []); const selectedIndex = props.selectedIndex ?? 0; const scrollOffset = useMemo(() => { const halfHeight = Math.floor(bodyHeight / 2); let offset = 0; if (selectedIndex > halfHeight && selectedIndex < data.length - halfHeight) { offset = selectedIndex - halfHeight; } else if (selectedIndex >= bodyHeight) { offset = selectedIndex - bodyHeight + 1; } return Math.max(0, Math.min(data.length - bodyHeight, offset)); }, [selectedIndex, bodyHeight, data.length]); const visibleStart = scrollOffset; const visibleEnd = Math.min(data.length, scrollOffset + bodyHeight); const visibleData = data.slice(visibleStart, visibleEnd); // Use format as a pass-through since child rows provide the row content. const formatFn = format ?? (() => ''); return (React.createElement("tui-geometry", { onLayout: handleLayout }, React.createElement("tui-table", { data: data, columns: columns, format: formatFn, childOffset: visibleStart, ...props }, visibleData.map((item, index) => (React.createElement(React.Fragment, { key: visibleStart + index }, renderItem(item, visibleStart + index))))))); } export const Accordion = forwardRef(function Accordion({ children, ...props }, ref) { return (React.createElement("tui-accordion", { ref: ref, ...props }, children)); }); Accordion.Section = forwardRef(function AccordionSection({ children, ...props }, ref) { return (React.createElement("tui-accordion-section", { ref: ref, ...props }, children)); }); export const Page = forwardRef(function Page({ children, ...props }, ref) { return (React.createElement("tui-page", { ref: ref, ...props }, children)); }); Page.Section = forwardRef(function PageSection({ children, ...props }, ref) { return (React.createElement("tui-page-section", { ref: ref, ...props }, children)); }); export const Pane = forwardRef(function Pane({ children, ...props }, ref) { return (React.createElement("tui-pane", { ref: ref, ...props }, children)); }); export const Drawer = forwardRef(function Drawer({ children, content, drawer, ...props }, ref) { return (React.createElement("tui-drawer", { ref: ref, ...props }, content, drawer, children)); }); Drawer.top = forwardRef(function DrawerTop({ children, content, drawer, ...props }, ref) { return (React.createElement("tui-drawer", { ref: ref, location: "top", ...props }, content, drawer, children)); }); Drawer.right = forwardRef(function DrawerRight({ children, content, drawer, ...props }, ref) { return (React.createElement("tui-drawer", { ref: ref, location: "right", ...props }, content, drawer, children)); }); Drawer.bottom = forwardRef(function DrawerBottom({ children, content, drawer, ...props }, ref) { return (React.createElement("tui-drawer", { ref: ref, location: "bottom", ...props }, content, drawer, children)); }); Drawer.left = forwardRef(function DrawerLeft({ children, content, drawer, ...props }, ref) { return (React.createElement("tui-drawer", { ref: ref, location: "left", ...props }, content, drawer, children)); }); export const Tabs = forwardRef(function Tabs({ children, ...props }, ref) { return (React.createElement("tui-tabs", { ref: ref, ...props }, children)); }); Tabs.Section = forwardRef(function TabsSection({ children, ...props }, ref) { return (React.createElement("tui-tabs-section", { ref: ref, ...props }, children)); }); //# sourceMappingURL=components.js.map