CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-snabbdom

A virtual DOM library with focus on simplicity, modularity, powerful features and performance.

Pending
Overview
Eval results
Files

jsx.mddocs/

JSX Support

Snabbdom provides comprehensive JSX support with factory functions and TypeScript definitions for React-style development patterns.

Capabilities

JSX Factory Function

Creates virtual nodes from JSX syntax, supporting both HTML elements and function components.

/**
 * JSX factory function for creating virtual nodes
 * @param tag - HTML tag name or function component
 * @param data - Virtual node data (props, attrs, etc.)
 * @param children - Child elements
 * @returns Virtual node
 */
function jsx(
  tag: string | FunctionComponent,
  data: VNodeData | null,
  ...children: JsxVNodeChildren[]
): VNode;

type FunctionComponent = (
  props: { [prop: string]: any } | null,
  children?: VNode[]
) => VNode;

Fragment Component

Creates document fragments for grouping elements without wrapper elements (experimental).

/**
 * JSX Fragment component for grouping elements
 * @param data - Optional data object with key
 * @param children - Child elements to group
 * @returns Virtual node representing a fragment
 */
function Fragment(
  data: { key?: Key } | null,
  ...children: JsxVNodeChildren[]
): VNode;

TypeScript Configuration

Add the following to your tsconfig.json:

{
  "compilerOptions": {
    "jsx": "react",
    "jsxFactory": "jsx",
    "jsxFragmentFactory": "Fragment"
  }
}

Usage Example:

import { Fragment, jsx, VNode, init, classModule, styleModule } from "snabbdom";

const patch = init([classModule, styleModule]);

// Simple JSX elements
const greeting: VNode = <h1>Hello, World!</h1>;

// Elements with props and children
const button: VNode = (
  <button 
    class={{ primary: true, large: false }}
    on={{ click: () => console.log("clicked") }}
  >
    Click me
  </button>
);

// Complex JSX structure
const app: VNode = (
  <div class="app">
    <header>
      <h1>My Application</h1>
    </header>
    <main>
      <p>Welcome to Snabbdom with JSX!</p>
      {button}
    </main>
  </div>
);

// JSX Fragments (experimental)
const fragmentExample: VNode = (
  <>
    <p>First paragraph</p>
    <p>Second paragraph</p>
  </>
);

Babel Configuration

For JavaScript projects using Babel, add the following to your Babel configuration:

{
  "plugins": [
    [
      "@babel/plugin-transform-react-jsx",
      {
        "pragma": "jsx",
        "pragmaFrag": "Fragment"
      }
    ]
  ]
}

Usage Example:

import { Fragment, jsx } from "snabbdom";

const component = (
  <div>
    <span>I was created with JSX</span>
  </div>
);

const fragmentComponent = (
  <>
    <span>JSX fragments</span>
    are experimentally supported
  </>
);

Function Components

Create reusable function components that receive props and return virtual nodes.

type FunctionComponent = (
  props: { [prop: string]: any } | null,
  children?: VNode[]
) => VNode;

Usage Examples:

import { jsx, VNode, h } from "snabbdom";

// Simple function component
function Greeting(props: { name: string } | null): VNode {
  return <h1>Hello, {props?.name || "World"}!</h1>;
}

// Function component with children
function Card(
  props: { title: string; className?: string } | null,
  children?: VNode[]
): VNode {
  return (
    <div class={props?.className || "card"}>
      <h2>{props?.title}</h2>
      <div class="card-body">
        {children}
      </div>
    </div>
  );
}

// Using function components
const app: VNode = (
  <div>
    <Greeting name="Snabbdom" />
    <Card title="Welcome" className="welcome-card">
      <p>This is card content</p>
      <button>Action</button>
    </Card>
  </div>
);

Conditional Rendering

JSX supports conditional rendering with boolean expressions.

import { jsx, VNode } from "snabbdom";

function ConditionalExample(props: { showMessage: boolean } | null): VNode {
  return (
    <div>
      <h1>Conditional Rendering</h1>
      {props?.showMessage && <p>This message is conditionally shown</p>}
      {props?.showMessage ? <p>Condition is true</p> : <p>Condition is false</p>}
    </div>
  );
}

Working with Lists

Map over arrays to create lists of elements.

import { jsx, VNode } from "snabbdom";

interface User {
  id: number;
  name: string;
  email: string;
}

function UserList(props: { users: User[] } | null): VNode {
  const users = props?.users || [];
  
  return (
    <ul class="user-list">
      {users.map(user => (
        <li key={user.id} class="user-item">
          <strong>{user.name}</strong> - {user.email}
        </li>
      ))}
    </ul>
  );
}

// Usage
const users: User[] = [
  { id: 1, name: "Alice", email: "alice@example.com" },
  { id: 2, name: "Bob", email: "bob@example.com" }
];

const userListVNode = <UserList users={users} />;

Types

type JsxVNodeChild = VNode | string | number | boolean | undefined | null;
type JsxVNodeChildren = ArrayOrElement<JsxVNodeChild>;

type ArrayOrElement<T> = T | T[];

namespace jsx {
  type Element = VNode;
  
  type VNodeProps<T> = ElementProperties<T> & Props;
  
  type HtmlElements = {
    [Property in keyof HTMLElementTagNameMap]: VNodeData<
      VNodeProps<HTMLElementTagNameMap[Property]>
    >;
  };
  
  interface IntrinsicElements extends HtmlElements {
    [elemName: string]: VNodeData;
  }
}

Install with Tessl CLI

npx tessl i tessl/npm-snabbdom

docs

advanced.md

core.md

index.md

jsx.md

modules.md

tile.json