Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
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.
- Host: GitHub
- URL: https://github.com/ibyra/angico
- Owner: ibyra
- License: mit
- Created: 2023-12-30T16:42:55.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2024-01-04T01:49:30.000Z (12 months ago)
- Last Synced: 2024-10-31T19:36:28.102Z (2 months ago)
- Topics: javascript, jsx, typescript
- Language: TypeScript
- Homepage:
- Size: 142 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
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) => (
<>
>
));
```
### 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 = `
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