Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/ibyra/angico

A small JSX async-rendering library.
https://github.com/ibyra/angico

javascript jsx typescript

Last synced: about 2 months ago
JSON representation

A small JSX async-rendering library.

Awesome Lists containing this project

README

        

# Angico

A small JSX async-rendering library.

## [![View on NPM](https://img.shields.io/npm/v/%40ibyra%2Fangico?style=flat-square)](https://www.npmjs.com/package/%40ibyra%2Fangico) [![License](https://img.shields.io/npm/l/%40ibyra%2Fangico?style=flat-square)](https://github.com/ibyra)

## Installation

Use the `npm` package manager or `bun` runtime to install Angico

```bash
npm i @ibyra/angico
bun i @ibyra/angico
```

## Usage

### Setting up the configuration

Firstly, you'll need to configure your JSX transformer to use Angico.

If you are using Typescript, you'll need to set the JSX properties your
`tsconfig.json` as follow:

```json
{
"jsx": "react-jsx",
"jsxImportSource": "@ibyra/angico"
}
```

If you are using other transpiler, like [Babel][babel-jsx], you can use these
pragma comments on the top of the your source file.

```jsx
/** @jsxImportSource @ibyra/angico */

var descriptions = items.map((item) => (
<>

{item.name}

{item.value}

>
));
```

### Authoring JSX

After setting up the configuration, using Angico is very similar to any other
JSX library. You can create and compose your components/fragments, even if they
are asynchronous.

```tsx
function Input(props: { type: 'text' | 'number' }): JSX.Element {
return ;
}

type BoxProps = {
width: JSX.StringNumber;
height: JSX.StringNumber;
children?: JSX.Children;
};

async function AsyncBox(props: BoxProps): JSX.AsyncElement {
const { height, width, children } = props;
const style = `height: ${height}px; width: ${width}px`;
await timeout(10);
return (


{timeout(10).then(() => children)}

);
}

// Just to here to simulate an asynchronous operation
function timeout(ms: number): Promise {
return new Promise((resolve) => setTimeout(resolve, ms, ms));
}

const box = (


Type a number.
Submit

);

console.log(box); // FunctionElement { ... }
```

As you can see, the JSX does not return an rendered version, but a instance of
`FunctionElement` instead. This is because Angico does not renders anything
immediately, only when it is required to do so.

### Rendering JSX into a string

You can request an JSX element to render into a string using the `render`
function, also available on Angico package.

```tsx
import { render } from '@ibyra/angico';

// ...

const box = (


Type a number.
Submit

);

const rendered = await render(box);

const expected = `

Type a number.Submit
`;

assert(rendered === expected);
```

### HTML, SVG, MathML, XML…

You can use Angico to render any XML markup you desire. You can use SVG out of
the box!

```tsx
import Angico from '@ibyra/angico';

export type IconProps = JSX.SVGSVGTag & {
fill?: string;
};

// The "envelope-simple" icon provided by @phosphor-icons/core
// https://github.com/phosphor-icons/core
export function EnvelopeSimple(props: IconProps): JSX.Element {
const {
fill = 'currentColor',
height = '1.5em',
width = '1.5em',
...rest
} = props;
return (



);
}
```

> [!WARNING]
> The current support for SVG and MathML is limited, only a few elements and
> attributes are defined. We aim to improve the support in the future.

### Extending type definitions

Sometimes you want to extend the definitions of the `JSX` available intrinsic
elements; e.g, when you are using an attribute-based JS library like
[HTMX][htmx] or [Alpine.js][alphine.js], or when you have some
[custom elements][custom-elements] in your markup. You can extend the
`JSX.IntrinsicElements` or `HTMLAttributes` interfaces with your custom
definitions.

```ts
declare global {
namespace JSX {
interface HTMLAttributes {
// HTMX attributes
[hx: `hx-${string}`]: string | boolean;
}

interface OpenableAttributes extends HTMLAttributes {
open?: boolean;
}

interface IntrinsicElements {
['my-custom-component']: OpenableAttributes;
}
}
}
```

## Roadmap

- Improve HTML elements and attributes typings;
- Improve support for WAI-ARIA attributes typings;
- Support all SVG elements and attributes typings;
- Support all MathML elements and attributes typings;
- Support streamed rendering;

## Contributing

Pull requests are welcome. For major changes, please open an issue first to
discuss what you would like to change.

Please make sure to update tests as appropriate.

## License

MIT © [Ibyra](https://github.com/ibyra)

[babel-jsx]: https://babeljs.io/docs/babel-plugin-transform-react-jsx
[htmx]: https://htmx.org/
[alphine.js]: https://alpinejs.dev/
[custom-elements]: https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements