CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-rax

A universal React-compatible render engine for building applications across multiple platforms

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

react-compatibility.mddocs/

React Compatibility Utilities

Additional utilities for React compatibility, including children manipulation, element validation, and element cloning functions. These utilities are provided through the compatibility layer and external packages to ensure full React API compatibility.

Capabilities

Children Utilities

Comprehensive utilities for working with component children, similar to React.Children.

/**
 * Children utility object with methods for manipulating component children
 */
const Children: {
  /**
   * Maps over children and returns a new array
   * @param children - Component children to map over
   * @param fn - Function to apply to each child
   * @param ctx - Optional context for the function call
   * @returns Array of mapped children
   */
  map(children: RaxNode, fn: (child: RaxNode, index: number) => RaxNode, ctx?: any): RaxNode[];
  
  /**
   * Iterates over children without returning anything
   * @param children - Component children to iterate over  
   * @param fn - Function to apply to each child
   * @param ctx - Optional context for the function call
   */
  forEach(children: RaxNode, fn: (child: RaxNode, index: number) => void, ctx?: any): void;
  
  /**
   * Counts the number of children
   * @param children - Component children to count
   * @returns Number of children
   */
  count(children: RaxNode): number;
  
  /**
   * Ensures children contains only one child and returns it
   * @param children - Component children (must be exactly one)
   * @returns The single child element
   * @throws Error if children count is not exactly 1
   */
  only(children: RaxNode): RaxElement;
  
  /**
   * Converts children to a flat array
   * @param children - Component children to convert
   * @returns Array representation of children
   */
  toArray(children: RaxNode): RaxNode[];
};

Usage Examples:

import { createElement, Children } from 'rax/src/compat';

function List({ children }) {
  // Map over children to add list item wrappers
  const listItems = Children.map(children, (child, index) => {
    return createElement('li', { key: index }, child);
  });

  return createElement('ul', null, ...listItems);
}

function TabContainer({ children }) {
  // Ensure only one active tab
  let activeChild = null;
  
  Children.forEach(children, (child) => {
    if (child.props && child.props.active) {
      activeChild = child;
    }
  });

  return createElement('div', { className: 'tab-container' },
    activeChild || Children.only(children)
  );
}

function ChildCounter({ children }) {
  const count = Children.count(children);
  const childArray = Children.toArray(children);
  
  return createElement('div', null,
    createElement('p', null, `This component has ${count} children`),
    createElement('div', null, ...childArray)
  );
}

// Usage
const app = createElement(List, null,
  createElement('span', null, 'Item 1'),
  createElement('span', null, 'Item 2'),
  createElement('span', null, 'Item 3')
);

Element Validation

Validates whether a value is a valid Rax element.

/**
 * Checks if a value is a valid Rax element
 * @param object - Value to check
 * @returns true if the value is a valid Rax element, false otherwise
 */
function isValidElement(object: any): boolean;

Usage Examples:

import { createElement, isValidElement } from 'rax/src/compat';

function SafeRender({ content }) {
  // Only render if content is a valid element
  if (isValidElement(content)) {
    return content;
  }
  
  // Fallback for non-element content
  if (typeof content === 'string' || typeof content === 'number') {
    return createElement('span', null, content);
  }
  
  return createElement('div', null, 'Invalid content');
}

function ElementChecker({ items }) {
  const validItems = items.filter(isValidElement);
  const invalidCount = items.length - validItems.length;
  
  return createElement('div', null,
    createElement('p', null, `Valid elements: ${validItems.length}`),
    createElement('p', null, `Invalid items: ${invalidCount}`),
    createElement('div', null, ...validItems)
  );
}

// Usage examples
const validElement = createElement('div', null, 'Hello');
const invalidElement = { notAnElement: true };

console.log(isValidElement(validElement)); // true
console.log(isValidElement(invalidElement)); // false
console.log(isValidElement('string')); // false
console.log(isValidElement(42)); // false

Element Factory

Creates a factory function for a specific element type, reducing the need to repeatedly specify the type.

/**
 * Creates a factory function for creating elements of a specific type
 * @param type - Element type (string for DOM elements, function/class for components)
 * @returns Factory function that creates elements of the specified type
 */
function createFactory(type: string | Function): Function;

Usage Examples:

import { createFactory } from 'rax/src/compat';

// Create factories for commonly used elements
const div = createFactory('div');
const span = createFactory('span');
const button = createFactory('button');

// Create factory for custom component
function CustomButton(props) {
  return button({ 
    className: 'custom-button',
    ...props 
  }, props.children);
}
const customButton = createFactory(CustomButton);

// Using factories (more concise than createElement)
function App() {
  return div({ className: 'app' },
    div({ className: 'header' },
      span(null, 'Welcome to the App')
    ),
    div({ className: 'content' },
      button({ 
        onClick: () => alert('Clicked!') 
      }, 'Click Me'),
      customButton({ 
        variant: 'primary' 
      }, 'Custom Button')
    )
  );
}

// Factory functions accept (props, ...children) just like createElement
const navigation = div({ className: 'nav' },
  button({ onClick: () => {} }, 'Home'),
  button({ onClick: () => {} }, 'About'),
  button({ onClick: () => {} }, 'Contact')
);

Element Cloning

Clones existing elements with modified props and/or children.

/**
 * Clones a Rax element with new props and/or children
 * @param element - Element to clone
 * @param props - New props to merge with existing props
 * @param children - New children to replace existing children
 * @returns New cloned element with merged props and new children
 */
function cloneElement(element: RaxElement, props?: Object, ...children: RaxNode[]): RaxElement;

Usage Examples:

import { createElement, cloneElement, Children } from 'rax/src/compat';

function EnhanceButton({ children, enhancement, ...props }) {
  // Clone each child button with enhanced props
  const enhancedChildren = Children.map(children, (child) => {
    if (child.type === 'button') {
      return cloneElement(child, {
        className: `${child.props.className || ''} enhanced`,
        'data-enhancement': enhancement,
        onClick: (e) => {
          // Call original onClick first
          if (child.props.onClick) {
            child.props.onClick(e);
          }
          // Add enhancement behavior
          console.log(`Enhanced click: ${enhancement}`);
        }
      });
    }
    return child;
  });

  return createElement('div', props, ...enhancedChildren);
}

function Modal({ isOpen, children }) {
  if (!isOpen) return null;

  // Clone children with modal-specific props
  const modalChildren = Children.map(children, (child) => {
    return cloneElement(child, {
      'data-in-modal': true,
      className: `${child.props.className || ''} modal-content`
    });
  });

  return createElement('div', { className: 'modal-overlay' },
    createElement('div', { className: 'modal' }, ...modalChildren)
  );
}

function FormField({ label, children }) {
  // Clone input element to add form-specific props
  const enhancedInput = cloneElement(children, {
    id: label.toLowerCase().replace(/\s+/g, '-'),
    'aria-label': label,
    className: `${children.props.className || ''} form-input`
  });

  return createElement('div', { className: 'form-field' },
    createElement('label', { 
      htmlFor: label.toLowerCase().replace(/\s+/g, '-') 
    }, label),
    enhancedInput
  );
}

// Usage
const originalButton = createElement('button', { 
  onClick: () => alert('Original') 
}, 'Click Me');

const enhancedForm = createElement(FormField, { label: 'Email Address' },
  createElement('input', { 
    type: 'email',
    placeholder: 'Enter email'
  })
);

Compatibility Layer Integration

The compatibility layer integrates all utilities into a single default export that mimics React's API:

/**
 * Default export that provides React-like API
 */
const Rax: {
  // All core Rax exports
  createElement: Function;
  render: Function;
  Component: ComponentConstructor;
  PureComponent: ComponentConstructor;
  // ... all other core exports
  
  // Additional compatibility utilities
  Children: ChildrenUtilities;
  isValidElement: Function;
  createFactory: Function;
  cloneElement: Function;
  
  // React compatibility flag
  Component.prototype.isReactComponent: {};
};

Full Compatibility Usage:

// Import as default to get React-like API
import Rax from 'rax/src/compat';

class ReactLikeComponent extends Rax.Component {
  render() {
    const { children } = this.props;
    
    // Use React-like APIs
    const validChildren = Rax.Children.toArray(children)
      .filter(Rax.isValidElement);
    
    const enhancedChildren = Rax.Children.map(validChildren, (child, index) => {
      return Rax.cloneElement(child, { key: index });
    });

    return Rax.createElement('div', null, ...enhancedChildren);
  }
}

// Component has React compatibility flag
console.log(ReactLikeComponent.prototype.isReactComponent); // {}

Types

// Children utilities type
interface ChildrenUtilities {
  map<T, C>(children: C, fn: (child: C, index: number) => T, ctx?: any): T[];
  forEach<C>(children: C, fn: (child: C, index: number) => void, ctx?: any): void;
  count(children: RaxNode): number;
  only(children: RaxNode): RaxElement;
  toArray(children: RaxNode): RaxNode[];
}

// Element validation type
type IsValidElementFunction = (object: any) => object is RaxElement;

// Factory function types
type ElementFactory<P = {}> = (props?: P, ...children: RaxNode[]) => RaxElement;
type CreateFactoryFunction = <P = {}>(type: string | ComponentType<P>) => ElementFactory<P>;

// Clone element types
type CloneElementFunction = <P = {}>(
  element: RaxElement<P>,
  props?: Partial<P>,
  ...children: RaxNode[]
) => RaxElement<P>;

// Compatibility layer type
interface RaxCompat {
  [key: string]: any;
  Children: ChildrenUtilities;
  isValidElement: IsValidElementFunction;
  createFactory: CreateFactoryFunction;
  cloneElement: CloneElementFunction;
}

// Node types (children can be various types)
type RaxNode = RaxElement | string | number | boolean | null | undefined | RaxNode[];

Install with Tessl CLI

npx tessl i tessl/npm-rax

docs

components.md

context.md

element-creation.md

hooks.md

index.md

react-compatibility.md

rendering.md

tile.json