Skip to content

BetterCorp/jsx-htmx

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

jsx-htmx

Why?

Simply put, I needed an htmx JSX library that did not (1) globally override the JSX namespace and (2) did not use /// require anywhere.
Both those meant that your whole project would be subject to those imports.
Where all I wanted was to be able to import a library and reference with jsx to get type same html/htmx AND be able to still use React/React.email elsewhere - while still being fully typesafe.

npm
asciicast (example from original design by Desdaemon - typed-htmx)

Definitions for HTML + HTMX v2 attributes in JSX.

This major version targets HTMX v2.

  • Legacy hx-on is not included.
  • SSE and WebSocket support are modeled as extensions via hx-ext, sse-connect, sse-swap, ws-connect, and ws-send.
  • For inline styles and scripts, prefer css(...) and js(...).

Usage

You can configure jsx-htmx either as pure type declarations, or as a JSX templating engine.

As type declarations

Configure your tsconfig.json as follows:

{
  "compilerOptions": {
    "jsx": "react-jsx",
    "moduleResolution": "node"
  }
}

This library was designed for use with commonjs.

Importing/using this:

Either by defining it globally in your tsconfig file:

{
  "compilerOptions": {
    "jsx": "react-jsx",
    "moduleResolution": "node16",
    "jsxImportSource": "jsx-htmx"
  }
}

OR Directly in the tsx/jsx files:

/** @jsxImportSource jsx-htmx */

function MyComponent({ children }) {
  return <div hx-get="/asd">{children}</div>;
  //          ^?: string | undefined
}

HTMX v2 event handlers

HTMX v2 uses hx-on:* attributes rather than the old hx-on form.

<button
  hx-post="/save"
  {...{
    "hx-on:htmx:before-request": "console.log('saving')",
    "hx-on::after-request": "console.log('saved')",
  }}
>
  Save
</button>

Typed HTMX DOM events

jsx-htmx also augments the DOM event maps for HTMX events, so browser listeners get typed event.detail automatically.

document.body.addEventListener("htmx:responseError", (event) => {
  console.log(event.detail.xhr.status);
  console.log(event.detail.failed);
});

document.body.addEventListener("htmx:configRequest", (event) => {
  console.log(event.detail.headers);
  console.log(event.detail.parameters);
});

Inline CSS and JS

For small inline blocks:

/** @jsxImportSource jsx-htmx */
import { css, js } from "jsx-htmx";

<style>
  {css({
    ".bp-shell": {
      display: "grid",
      gap: "1rem",
    },
  })}
</style>

<script>
  {js(() => {
    const shell = document.querySelector(".bp-shell");
    shell?.setAttribute("data-ready", "true");
  })}
</script>

js(() => { ... }) is type-checked while authoring, and is intended for small inline snippets rather than large serialized application logic.

Component Creation

There are 2 types to make things easier:
CustomComponent and SimpleCustomComponent.

The difference is the CustomComponent contains a type property which you can extend for default props you want to always passthrough instead of re-declaring them.

EG: SimpleCustomComponent

const Badge: SimpleCustomComponent = (props) => {
  return <div class="component">{props.children}</div>;
};

EG: CustomComponent

type MyParams = {
  userName: string;
};
type MyComponentType<Props = null> = CustomComponent<MyParams, Props>;
type MyComponentTypeUser<Props = null> = CustomComponent<
  MyParams & { id: string },
  Props
>;

const Badge: MyComponentType = (props) => {
  return <div class="component">{props.userName}</div>;
};

const Badge2: MyComponentType<{ id: string }> = (props) => {
  return (
    <div class="component2">
      {props.userName} - {props.id}
    </div>
  );
};

const Badge3: MyComponentTypeUser = (props) => {
  return (
    <div class="component2">
      {props.userName} - {props.id}
    </div>
  );
};

const Content: SimpleCustomComponent = (props) => {
  return (
    <div class="component">
      <MyComponentType userName="USER" id={"id"} />
    </div>
  );
};

Original sources/attributions:

typed-htmx
typed-html

About

TypeSafe HTML/HTMX templates using TypeScript. No need to learn a template library.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors