{"id":13445617,"url":"https://github.com/alex-kinokon/jsx-dom","last_synced_at":"2025-04-06T07:11:17.724Z","repository":{"id":40336222,"uuid":"71836314","full_name":"alex-kinokon/jsx-dom","owner":"alex-kinokon","description":"Use JSX to create DOM elements.","archived":false,"fork":false,"pushed_at":"2024-04-03T18:11:21.000Z","size":1330,"stargazers_count":269,"open_issues_count":3,"forks_count":29,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-05-10T02:41:32.113Z","etag":null,"topics":["dom","javascript","jsx","styled-components","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alex-kinokon.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-10-24T22:08:57.000Z","updated_at":"2024-06-10T03:44:43.815Z","dependencies_parsed_at":"2024-01-16T02:47:07.786Z","dependency_job_id":"789f5ab4-bb87-4e68-a3a8-8f3dc9a229c5","html_url":"https://github.com/alex-kinokon/jsx-dom","commit_stats":{"total_commits":191,"total_committers":18,"mean_commits":10.61111111111111,"dds":"0.19895287958115182","last_synced_commit":"d41b1c2489a251a881ba68539a5a70591cc998e6"},"previous_names":["glixlur/jsx-dom","proteriax/jsx-dom"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alex-kinokon%2Fjsx-dom","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alex-kinokon%2Fjsx-dom/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alex-kinokon%2Fjsx-dom/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alex-kinokon%2Fjsx-dom/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alex-kinokon","download_url":"https://codeload.github.com/alex-kinokon/jsx-dom/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247445669,"owners_count":20939958,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dom","javascript","jsx","styled-components","typescript"],"created_at":"2024-07-31T05:00:36.587Z","updated_at":"2025-04-06T07:11:17.702Z","avatar_url":"https://github.com/alex-kinokon.png","language":"TypeScript","funding_links":[],"categories":["Integrations","TypeScript"],"sub_categories":["Other JSX based libraries"],"readme":"# jsx-dom\n\n[![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)\n[![build status](https://travis-ci.org/proteriax/jsx-dom.svg?branch=master)](https://travis-ci.org/proteriax/jsx-dom)\n[![npm version](https://badge.fury.io/js/jsx-dom.svg)](https://badge.fury.io/js/jsx-dom)\n\nUse JSX for creating DOM elements. Supports ES Module and TypeScript.\n\n**NEW!** [Styled components are now supported.](#styled-components)\n\n## Installation\n\n```bash\nnpm install --save jsx-dom\nyarn install jsx-dom\npnpm add jsx-dom\n```\n\n## Usage\n\n`jsx-dom` is ESM only.\n\nIf you need CommonJS support, you can\n\n1. Use this library directly if you use [Node v22](https://nodejs.org/api/modules.html#loading-ecmascript-modules-using-require) or above.\n2. install `jsx-dom-cjs` instead. These two packages only differ in module format.\n\n**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.\n\n```jsx\nimport React from \"jsx-dom\"\n\n// DOM Elements.\ndocument.body.appendChild(\n  \u003cdiv id=\"greeting\" class=\"alert\"\u003e\n    Hello World\n  \u003c/div\u003e\n)\n\n// Functional components\n// `defaultProps` and `props.children` are supported natively and work as you expect.\nfunction Hello(props) {\n  return (\n    \u003cdiv\u003e\n      Hello, {props.firstName} {props.lastName}!\n    \u003c/div\u003e\n  )\n}\nHello.defaultProps = {\n  firstName: \"John\",\n}\n\ndocument.body.appendChild(\u003cHello firstName=\"Johnny\" lastName=\"Appleseed\" /\u003e)\n\n// Class components\n// `defaultProps` and `props.children` are supported natively and work as you expect.\n// In terms of React jsx-dom class components have no state,\n// so `render` function will be called only once.\n//\n// Component lifecycle functions are currently not supported. This may change in\n// the future.\nclass Welcome extends React.Component {\n  static defaultProps = {\n    firstName: \"John\",\n  }\n\n  render() {\n    return (\n      \u003cdiv\u003e\n        Welcome, {this.props.firstName} {this.props.lastName}!\n      \u003c/div\u003e\n    )\n  }\n}\n\ndocument.body.appendChild(\u003cWelcome firstName=\"Johnny\" lastName=\"Appleseed\" /\u003e)\n```\n\n### Styled Components\n```tsx\nimport { styled } from \"jsx-dom\"\n\nconst HeaderText = styled.h2`\n  font-size: 20px;\n  font-weight: 500;\n`\n\ndocument.body.appendChild(\n  \u003cHeaderText style={{ /* you can override here */ }}\u003e\n    Welcome!\n  \u003c/HeaderText\u003e\n)\n\nconst Name = styled.div\u003c{ large?: boolean }\u003e`\n  font-size: ${props =\u003e props.large ? 40 : 20}px;\n  ${props =\u003e props.large ? \"font-weight: 600;\" : \"\"}\n`\n\ndocument.body.appendChild(\n  \u003cName large\u003e\n    Welcome!\n  \u003c/Name\u003e\n)\n\n```\n\n### Shadow DOM\n```tsx\nimport { ShadowRoot } from \"jsx-dom\"\n\ndocument.body.appendChild(\n  \u003cdialog\u003e\n    \u003cShadowRoot mode=\"closed\"\u003e\n      \u003cstyle\u003e:root { font-family: Helvetica Neue; }\u003c/style\u003e\n      \u003cbutton\u003eHello\u003c/button\u003e\n    \u003c/ShadowRoot\u003e\n  \u003c/dialog\u003e\n)\n```\n\n\n## Syntax\n\n`jsx-dom` is based on the React JSX syntax with a few additions:\n\n### Class\n\n1. `class` is supported as an attribute as well as `className`.\n2. `class` can take:\n\n   - a string\n   - an object with the format `{ [key: string]: boolean }`. Keys with a truthy value will be added to the classList\n   - an array of values where falsy values (see below) are filtered out\n   - an array of any combination of the above, including deeply nested arrays\n\nNote 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,\n\n```jsx\n\u003cdiv class=\"greeting\" /\u003e\n\u003cdiv class={[ condition \u0026\u0026 \"class\" ]} /\u003e\n\u003cdiv class={{ hidden: isHidden, \"has-item\": !!array.length }} /\u003e\n\u003cdiv class={[ classArray1, classArray2, [\"nested\", [\"further\"]] ]} /\u003e\n```\n\n### Style\n\n1. `style` accepts a string, an object and an array of any combination of the above, including deeply nested arrays. Unitless properties supported by React are also supported.\n\n```jsx\n\u003cdiv style=\"background: transparent;\" /\u003e\n\u003cdiv style={{ background: \"transparent\", fontFamily: \"serif\", fontSize: 16 }} /\u003e\n```\n\n### Children\n\nPassing `children` as an explicit attribute, when there is no other JSX child node, is also supported. Any object that matches the TypeScript `ArrayLike` interface can be used as `children`, including jQuery objects.\n\n```jsx\n\u003cdiv children={[\"Total: \", 20]} /\u003e\n```\n\n### Other Attributes\n\n1. `dataset` accepts an object, where keys with a `null` or `undefined` value will be ignored.\n\n```jsx\n\u003cdiv dataset={{ user: \"guest\", isLoggedIn: false }} /\u003e\n```\n\n2. 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 = ...`).\n\n```jsx\n\u003cdiv onClick={e =\u003e e.preventDefault()} /\u003e\n```\n\n3. `innerHTML`, `innerText` and `textContent` are accepted.\n\n4. `ref` accepts either 1) a callback `(node: Element) =\u003e 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.\n\n```jsx\n// Callback\n\u003cinput ref={node =\u003e $(node).typehead({ hint: true })} /\u003e\n\n// React.createRef\nimport React, { createRef } from \"jsx-dom\"\n\nconst textbox = createRef()\nrender(\n  \u003cdiv\u003e\n    \u003clabel\u003eUsername:\u003c/label\u003e\n    \u003cinput ref={textbox} /\u003e\n  \u003c/div\u003e\n)\n\nwindow.onerror = () =\u003e {\n  textbox.current.focus()\n}\n\n// React.useRef\nimport React, { useRef } from \"jsx-dom\"\n\nfunction Component() {\n  const textbox = useRef()\n  const onClick = () =\u003e textbox.current.focus()\n\n  return (\n    \u003cdiv onClick={onClick}\u003e\n      \u003clabel\u003eUsername:\u003c/label\u003e\n      \u003cinput ref={textbox} /\u003e\n    \u003c/div\u003e\n  )\n}\n```\n\n5. Rich data jsx properties are accepted, but populated as properties rather than DOM attributes. \n\n```jsx\nclass MyCustomElement extends HTMLElement {\n  constructor() {\n    super();\n  }\n}\ncustomElements.define('my-custom-element', MyCustomElement);\nconst richData = { foo: 'bar' }\nreturn \u003cmy-custom-element richData={richData} /\u003e\n```\n\n### Functional and class components\n\nYou can write functional and class components and receive passed `props` in the same way in React. Unlike\nReact, `props.children` is guaranteed to be an array.\n\n### SVG and Namespaces\n\n```jsx\nimport React from \"jsx-dom\"\n\ndocument.body.appendChild(\n  \u003cdiv class=\"flag\" style={{ display: \"flex\" }}\u003e\n    \u003ch1\u003eFlag of Italy\u003c/h1\u003e\n    \u003csvg width=\"150\" height=\"100\" viewBox=\"0 0 3 2\" class=\"flag italy\"\u003e\n      \u003crect width=\"1\" height=\"2\" x=\"0\" fill=\"#008d46\" /\u003e\n      \u003crect width=\"1\" height=\"2\" x=\"1\" fill=\"#ffffff\" /\u003e\n      \u003crect width=\"1\" height=\"2\" x=\"2\" fill=\"#d2232c\" /\u003e\n    \u003c/svg\u003e\n  \u003c/div\u003e\n)\n```\n\nBelow is a list of SVG tags included.\n\n\u003e 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\n\nIf you do not need SVG and CSS property automatic type conversion support, you can import from `jsx-dom/min` for a smaller build.\n\n```jsx\nimport React, { SVGNamespace } from \"jsx-dom\"\n\nfunction Anchor() {\n  return \u003ca namespaceURI={SVGNamespace}\u003eI am an SVG element!\u003c/a\u003e\n}\n```\n\nIf 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`.\n\njsx-dom also includes a few utility functions to facilitate the process of refactoring from or to React.\n\n## `useText`\n\nWhile this is technically not a hook in the React sense, it functions like one and\nfacilitates simple DOM text changes.\n\n```jsx\nimport React, { useText } from \"jsx-dom\"\n\nfunction Component() {\n  const [text, setText] = useText(\"Downloading\")\n\n  fetch(\"./api\").then(() =\u003e {\n    setText(\"Done!\")\n  })\n\n  return (\n    \u003cdiv\u003eStatus: {text}\u003c/div\u003e\n  )\n}\n```\n\n## `useClassList`\n\n```jsx\nimport React, { useClassList } from \"jsx-dom\"\n\nfunction Component() {\n  const cls = useClassList([\"main\", { ready: false }])\n  setTimeout(() =\u003e {\n    cls.add(\"long-wait\")\n    cls.toggle(\"ready\")\n  }, 2000)\n\n  return (\n    \u003cdiv class={cls}\u003eStatus\u003c/div\u003e\n  )\n}\n```\n\n## Goodies\n\nSome extra features are provided by this package:\n\n```ts\n// Returns the event object\nexport function preventDefault(event: Event): Event;\n\n// Returns the event object\nexport function stopPropagation(event: Event): Event;\n\n// `namespaceURI` string for SVG Elements.\nexport const SVGNamespace: string;\n\n// Convert a value into a className string. See docs above.\nexport function className(value: any): string;\n```\n\n### Type aliases for convenience\n```ts\n/** Short type aliases for HTML elements */\nexport namespace HTML {\n    type Anchor = HTMLAnchorElement\n    type Button = HTMLButtonElement\n    type Div = HTMLDivElement\n    ...\n}\n\n/** Short type aliases for SVG elements */\nexport namespace SVG {\n    type Anchor = SVGAElement\n    type Animate = SVGAnimateElement\n    ...\n}\n```\n\n## API Compatibility with React\nThe following functions are included for compatibility with React API:\n\n```ts\nfunction createFactory(component: string): (props: object) =\u003e JSX.Element\nfunction useImperativeHandle\u003cT\u003e(ref: Ref\u003cT\u003e, init: () =\u003e T, deps?: DependencyList): void\nfunction useRef\u003cT\u003e(initialValue?: T): RefObject\u003cT\u003e\nfunction forwardRef\u003cT = Node, P = {}\u003e(\n  render: (props: P, ref: Ref\u003cT\u003e) =\u003e ReactNode\n): FunctionComponent\u003cP \u0026 { ref?: Ref\u003cT\u003e }\u003e\n```\n\nThe following functions do **not** have memoization or optimization, and are only useful if you are\nmigrating from/to React.\n\n```ts\n// Returns `render` function\nexport function memo\u003cP, T extends (props: P) =\u003e JSX.Element\u003e(render: T): T;\n// Returns `fn` function\nexport function useMemo\u003cT\u003e(fn: () =\u003e T, deps: any[]): T;\n// Returns `fn` function\nexport function useCallback\u003cT extends Function\u003e(fn: T, deps: any[]): T;\n\nexport const StrictMode: React.FC;\n\nexport class PureComponent {}\n```\n\n## Browser Support\n\nThere is no support for Internet Explorer.\n\n## Known Issues\n\n* `\u003cdiv /\u003e`, and other tags, are inferred as a general `JSX.Element` in TypeScript instead of\n`HTMLDivElement` (or the equivalent types). This is a known bug and its fix depends on [TypeScript#21699](https://github.com/Microsoft/TypeScript/issues/21699).\n\n* [htm](https://github.com/developit/htm) library is [not currently compatible](https://github.com/proteriax/jsx-dom/issues/32) with jsx-dom.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falex-kinokon%2Fjsx-dom","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falex-kinokon%2Fjsx-dom","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falex-kinokon%2Fjsx-dom/lists"}