npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ktjs/jsx

v0.7.3

Published

JSX/TSX support for KT.js - Build UIs with JSX syntax while keeping direct DOM control

Readme

@ktjs/jsx

npm version

📦 Part of KT.js - JSX/TSX support for the KT.js framework

Write UI code with JSX syntax while maintaining KT.js's philosophy of direct DOM manipulation and zero unnecessary re-renders.

Features

  • JSX/TSX Support: Write declarative UI code with familiar JSX syntax
  • 🎯 Direct DOM Manipulation: JSX compiles to direct h() calls, no virtual DOM
  • 🔧 Full TypeScript Support: Complete type safety with IntelliSense
  • Zero Runtime Overhead: JSX is pure syntax sugar over KT.js's h function
  • 🎨 Event Handler Syntax: Support for both function props and on:eventName syntax
  • 📦 Multiple Runtime Modes: Support both automatic and classic JSX transforms
  • 🔌 Easy Integration: Works with Babel, TypeScript, and modern build tools

Installation

pnpm add @ktjs/jsx @ktjs/core
# or
npm install @ktjs/jsx @ktjs/core

Quick Start

TypeScript Configuration

For automatic runtime (recommended, React 17+ style):

// tsconfig.json
{
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "@ktjs/jsx"
  }
}

For classic runtime (React 16 style):

// tsconfig.json
{
  "compilerOptions": {
    "jsx": "react",
    "jsxFactory": "h",
    "jsxFragmentFactory": "Fragment"
  }
}

Basic Usage

import { h } from '@ktjs/jsx';

// Simple element
const greeting = <div class="greeting">Hello, KT.js!</div>;

// With attributes and event handlers
const button = (
  <button
    class="btn primary"
    on:click={() => alert('Clicked!')}
  >
    Click me
  </button>
);

// Nested elements
const app = (
  <div id="app">
    <header class="header">
      <h1>My App</h1>
    </header>
    <main class="content">
      <p>Welcome to KT.js with JSX!</p>
      {button}
    </main>
  </div>
);

document.body.appendChild(app);

Event Handlers

You can use event handlers in two ways:

// 1. Function props (automatically converted to event listeners)
<button click={() => console.log('clicked')}>Button 1</button>

// 2. on:-prefixed attributes (explicit event handlers)
<button on:click={(e) => console.log('clicked', e)}>Button 2</button>

// 3. Mix both (regular attribute + event listener)
<input
  change="change-value"          // Regular attribute
  on:change={(e) => console.log(e)} // Event listener
/>

Conditional Rendering

Use JavaScript expressions for conditional rendering:

import { ktnull } from '@ktjs/jsx';

const isLoggedIn = true;

const app = (
  <div>
    {isLoggedIn ? <p>Welcome back!</p> : <p>Please log in</p>}

    {/* Use ktnull to render nothing */}
    {isLoggedIn ? <button>Logout</button> : ktnull}
  </div>
);

Lists

Map arrays to JSX elements:

const items = ['Apple', 'Banana', 'Orange'];

const list = (
  <ul>
    {items.map((item, index) => (
      <li key={index}>{item}</li>
    ))}
  </ul>
);

Dynamic Attributes

const className = 'card primary';
const isDisabled = false;

const element = (
  <div class={className} style="padding: 20px; background: #f0f0f0" data-disabled={isDisabled ? 'true' : 'false'}>
    Dynamic attributes
  </div>
);

Advanced Usage

Using with Babel

If you're using Babel instead of TypeScript:

pnpm add -D @babel/plugin-transform-react-jsx
// babel.config.js
module.exports = {
  presets: [
    [
      '@ktjs/jsx/babel-preset',
      {
        runtime: 'automatic', // or 'classic'
      },
    ],
  ],
};

Classic Runtime (Manual Import)

If you prefer the classic JSX transform:

// You need to import h in every file using JSX
import { h, Fragment } from '@ktjs/jsx';

const app = (
  <div>
    <h1>Classic Runtime</h1>
  </div>
);

Fragments

Note: KT.js doesn't have a native Fragment concept. Fragments are wrapped in a div with data-kt-fragment="true":

import { Fragment } from '@ktjs/jsx';

const list = (
  <>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
  </>
);
// Results in: <div data-kt-fragment="true"><li>Item 1</li>...</div>

If you want truly unwrapped children, use arrays instead:

const items = [<li key="1">Item 1</li>, <li key="2">Item 2</li>, <li key="3">Item 3</li>];

const list = <ul>{items}</ul>;

Integration with CSS-in-JS

Works seamlessly with CSS-in-JS libraries:

import { css } from '@emotion/css';

const buttonStyle = css`
  background: blue;
  color: white;
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;

  &:hover {
    background: darkblue;
  }
`;

const button = (
  <button class={buttonStyle} on:click={() => alert('Styled!')}>
    Styled Button
  </button>
);

Creating Reusable Components

While KT.js doesn't have a component system, you can create factory functions:

interface CardProps {
  title: string;
  content: string;
  onClose?: () => void;
}

function Card({ title, content, onClose }: CardProps) {
  return (
    <div class="card">
      <div class="card-header">
        <h3>{title}</h3>
        {onClose && (
          <button class="close" on:click={onClose}>×</button>
        )}
      </div>
      <div class="card-body">
        {content}
      </div>
    </div>
  );
}

// Usage
const myCard = Card({
  title: 'Hello',
  content: 'This is a card',
  onClose: () => console.log('Closing...')
});

document.body.appendChild(myCard);

API Reference

JSX Runtime Functions

jsx(tag, props, ...children)

The main JSX transformation function. Called automatically by the JSX compiler.

Parameters:

  • tag (string): HTML tag name
  • props (object): Element attributes and event handlers
  • children (...): Child elements

Returns: HTMLElement

Fragment(props)

Fragment component for grouping elements without a wrapper (wraps in a div with data-kt-fragment).

h(tag, props, children)

Classic JSX factory function, equivalent to jsx.

Re-exported from @ktjs/core

  • ktnull: Special value for conditional rendering (renders nothing)

Type Definitions

Full TypeScript support with comprehensive JSX type definitions:

declare global {
  namespace JSX {
    type Element = HTMLElement;

    interface IntrinsicElements {
      div: KTAttribute & { children?: KTRawContent };
      span: KTAttribute & { children?: KTRawContent };
      // ... all HTML elements
    }
  }
}

Comparison: JSX vs Function Calls

// JSX syntax
const app = (
  <div class="container">
    <h1>Hello</h1>
    <button on:click={() => alert('Hi')}>Click</button>
  </div>
);

// Equivalent function calls
import { h, div, button } from '@ktjs/core';

const app = div({ class: 'container' }, [
  h('h1', {}, 'Hello'),
  button({ 'on:click': () => alert('Hi') }, 'Click')
]);

Both produce exactly the same DOM with zero performance difference. Choose the style you prefer!

Build Tool Integration

Vite

// vite.config.ts
import { defineConfig } from 'vite';

export default defineConfig({
  esbuild: {
    jsxImportSource: '@ktjs/jsx',
    jsx: 'automatic',
  },
});

Webpack

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.[jt]sx?$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@ktjs/jsx/babel-preset'],
          },
        },
      },
    ],
  },
};

esbuild

// build.js
import esbuild from 'esbuild';

esbuild.build({
  entryPoints: ['src/index.tsx'],
  bundle: true,
  jsxImportSource: '@ktjs/jsx',
  jsx: 'automatic',
  outfile: 'dist/bundle.js',
});

Browser Compatibility

Same as @ktjs/core - works in all modern browsers and IE9+ (with transpilation).

Why Use JSX with KT.js?

Familiar Syntax: If you're coming from React, JSX feels natural
Better IDE Support: Enhanced autocomplete and error checking
Readability: Complex nested structures are easier to read
Zero Cost: Pure compile-time transformation, no runtime overhead
Optional: You can mix JSX with regular function calls

Philosophy

@ktjs/jsx is purely syntactic sugar. It transforms JSX to direct h() function calls at compile time:

<div>Hello</div>  →  h('div', {}, 'Hello')

This means:

  • No virtual DOM - direct DOM manipulation
  • No reconciliation - you control when and what updates
  • No framework magic - just JavaScript and the DOM API

License

MIT

Links