# jsx-dom [![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) [![build status](https://travis-ci.org/proteriax/jsx-dom.svg?branch=master)](https://travis-ci.org/proteriax/jsx-dom) [![dependency status](https://david-dm.org/proteriax/jsx-dom/status.svg)](https://david-dm.org/proteriax/jsx-dom#info=dependencies) [![devDependency status](https://david-dm.org/proteriax/jsx-dom/dev-status.svg)](https://david-dm.org/proteriax/jsx-dom#info=devDependencies) [![npm version](https://badge.fury.io/js/jsx-dom.svg)](https://badge.fury.io/js/jsx-dom) Use JSX for creating DOM elements. Supports ES Module and TypeScript. ## Installation ```bash npm install --save jsx-dom yarn install jsx-dom ``` ## Usage **Note:** `jsx-dom` is ESM only. If you absolutely need CommonJS support, use `jsx-dom-cjs` instead. **Note:** If you are using [React Automatic Runtime](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx), simply set `jsxImportSource` to `jsx-dom` or `jsx-dom/min` and you can omit the import. ```jsx import React from "jsx-dom" // DOM Elements. document.body.appendChild(
Hello World
) // Functional components // `defaultProps` and `props.children` are supported natively and work as you expect. function Hello(props) { return (
Hello, {props.firstName} {props.lastName}!
) } Hello.defaultProps = { firstName: "John", } document.body.appendChild() // Class components // `defaultProps` and `props.children` are supported natively and work as you expect. // In terms of React jsx-dom class components have no state, // so `render` function will be called only once. class Welcome extends React.Component { static defaultProps = { firstName: "John", } render() { return (
Welcome, {this.props.firstName} {this.props.lastName}!
) } } document.body.appendChild() ``` ## Syntax `jsx-dom` is based on the React JSX syntax with a few additions: ### Class 1. `class` is supported as an attribute as well as `className`. 2. `class` can take: - a string - an object with the format `{ [key: string]: boolean }`. Keys with a truthy value will be added to the classList - an array of values where falsy values (see below) are filtered out - an array of any combination of the above, including deeply nested arrays Note that `false`, `true`, `null`, `undefined` will be ignored per [React documentations](https://facebook.github.io/react/docs/jsx-in-depth.html#booleans-null-and-undefined-are-ignored), and everything else will be used. For example, ```jsx
``` ### Style 1. `style` accepts both strings and objects. Unitless properties supported by React are also supported. ```jsx
``` ### Children Passing `children` as an explicit attribute, when there is no other JSX child node, is also supported. ```jsx
``` ### Other Attributes 1. `dataset` accepts an object, where keys with a `null` or `undefined` value will be ignored. ```jsx
``` 2. Attributes starts with `on` and has a function value will be treated as an event listener and attached to the node by setting the property directly (e.g. `node.onclick = ...`). ```jsx
e.preventDefault()} /> ``` 3. `innerHTML`, `innerText` and `textContent` are accepted. 4. `ref` accepts either 1) a callback `(node: Element) => void` that allows access to the node after being created, or 2) a [React style `ref` object](https://reactjs.org/docs/react-api.html#reactcreateref). This is useful when you have a nested node tree and need to access a node inside without creating an intermediary variable. ```jsx // Callback $(node).typehead({ hint: true })} /> // React.createRef import React, { createRef } from "jsx-dom" const textbox = createRef() render(
) window.onerror = () => { textbox.current.focus() } // React.useRef import React, { useRef } from "jsx-dom" function Component() { const textbox = useRef() const onClick = () => textbox.current.focus() return (
) } ``` ### Functional and class components You can write functional and class components and receive passed `props` in the same way in React. Unlike React, `props.children` is guaranteed to be an array. ### SVG and Namespaces ```jsx import React from "jsx-dom" document.body.appendChild(

Flag of Italy

) ``` Below is a list of SVG tags included. > svg, animate, circle, clipPath, defs, desc, ellipse, feBlend, feColorMatrix, feComponentTransfer, feComposite, feConvolveMatrix, feDiffuseLighting, feDisplacementMap, feDistantLight, feFlood, feFuncA, feFuncB, feFuncG, feFuncR, feGaussianBlur, feImage, feMerge, feMergeNode, feMorphology, feOffset, fePointLight, feSpecularLighting, feSpotLight, feTile, feTurbulence, filter, foreignObject, g, image, line, linearGradient, marker, mask, metadata, path, pattern, polygon, polyline, radialGradient, rect, stop, switch, symbol, text, textPath, tspan, use, view If you do not need SVG and CSS property automatic type conversion support, you can import from `jsx-dom/min` for a smaller build. ```jsx import React, { SVGNamespace } from "jsx-dom" function Anchor() { return I am an SVG element! } ``` If you need to create an SVG element that is not in the list, or you want to specify a custom namespace, use the attribute `namespaceURI`. jsx-dom also includes a few utility functions to facilitate the process of refactoring from or to React. ## `useText` While this is technically not a hook in the React sense, it functions like one and facilitates simple DOM text changes. ```jsx import React, { useText } from "jsx-dom" function Component() { const [text, setText] = useText("Downloading") fetch("./api").then(() => setText("Done!")) return (
Status: {text}
) } ``` ## `useClassList` ```jsx import React, { useClassList } from "jsx-dom" function Component() { const cls = useClassList(["main", { ready: false }]) setTimeout(() => { cls.add("long-wait") cls.toggle("ready") }, 2000) return (
Status
) } ``` ## Goodies Some extra features are provided by this package: ```ts function preventDefault(event: Event): Event function stopPropagation(event: Event): Event /** `namespaceURI` string for SVG Elements. */ const SVGNamespace: string function className(value: any): string ``` ### Type aliases for convenience ```ts /** Short type aliases for HTML elements */ namespace HTML { type Anchor = HTMLAnchorElement type Button = HTMLButtonElement type Div = HTMLDivElement ... } /** Short type aliases for SVG elements */ namespace SVG { type Anchor = SVGAElement type Animate = SVGAnimateElement ... } ``` ## API The following functions are included for compatibility with React API: ```ts function createFactory(component: string): (props: object) => JSX.Element function useRef(initialValue?: T): RefObject ``` The following functions will **not** have memoization, and are only useful if you are migrating from/to React. ```ts function memo JSX.Element>(render: T): T function useMemo(fn: () => T, deps: any[]): T function useCallback(fn: T, deps: any[]): T ``` ## Browser Support There is no support for Internet Explorer, although it will very likely work if you bring your own polyfill. ## Known Issues * `
`, and other tags, are inferred as a general `JSX.Element` in TypeScript instead of `HTMLDivElement` (or the equivalent types). This is a known bug and its fix depends on [TypeScript#21699](https://github.com/Microsoft/TypeScript/issues/21699). * [html](https://github.com/developit/htm) library is [not currently compatible](https://github.com/proteriax/jsx-dom/issues/32) with jsx-dom.