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

https://github.com/s15n/ive

An extremely small Web Framework but just as powerful as all the others: Reactive without React.
https://github.com/s15n/ive

framework frontend jsx lightweight typescript

Last synced: 2 months ago
JSON representation

An extremely small Web Framework but just as powerful as all the others: Reactive without React.

Awesome Lists containing this project

README

          

# IVE

[![npm](https://img.shields.io/npm/v/ive-fw)](https://www.npmjs.com/package/ive-fw)
[![npm](https://img.shields.io/npm/dt/ive-fw)](https://www.npmjs.com/package/ive-fw)
![GitHub](https://img.shields.io/github/license/s15n/ive)

IVE /ˈaɪ.viː/ is an extremely lightweight front-end framework best used
alongside Vite and TypeScript.

## Features

- Extremely small and lightweight
- No virtual DOM
- No dependencies
- TypeScript and JSX support
- Really just two functions: `ive.createState` and `ive.watch`
- Convenience functions on top for awaiting promises and routing

## Installation

Create a vite project (creates a new folder with the project name)
```bash
npm init vite
```
Use the following settings:
- Select framework: `vanilla`
- Select variant: `TypeScript`

Install IVE
```bash
npm install ive-fw
```

## Usage

```typescript
import ive from 'ive-fw/ive';
```

You have to add the following to your `tsconfig.json` file:
```jsonc
{
"compilerOptions": {
/* ... */
"jsx": "preserve",
"jsxFactory": "ive._jsx",
"jsxFragmentFactory": "ive._jsxFragment",
/* ... */
}
}
```

And you might need to add this line somewhere in your code (best in a separate `jsx.ts` file)
```typescript
import 'ive-fw/jsx';
```

And you're good to go!

## Example

### Hello, World!

Create a new file `App.tsx` with the following content:
```tsx
import ive from 'ive-fw/ive';

const Hello = ({ name }: { name: string }) => (

Hello, {name}!


);

export default () => (




);
```

Render this component in `main.ts`:
```typescript
import App from './App';

document.body.appendChild(App());
```

### Counter with State

Create a new file `Counter.tsx` with the following content:
```tsx
import ive from 'ive-fw/ive';

const counter = ive.createState(0);

export default ive.watch([counter], ([count]) => (


Counter


{count}


counter.set(count + 1)}>Increment

));
```
This component will be re-rendered every time the `counter` state changes.

Keep in mind that events need to be prefixed with `on:` in ive in order to work.

### Fetching Data (awaiting Promises)

Ive provides a convenience function `ive.wait` to await promises.
Though it really is just a wrapper around `ive.watch`.

Create a new file `Posts.tsx` with the following content:
```tsx
import ive from 'ive-fw/ive';

export default ive.wait(fetch('https://jsonplaceholder.typicode.com/posts').then((response) => response.json()), (posts) => (


Posts



    {posts.map((post: any) => (

  • {post.title}


    {post.body}



  • ))}


), () => ( // optional loading component

Loading...



), (error) => ( // optional error component

Error


{JSON.stringify(error)}



));
```

### Routing

Ive provides a convenience function `ive.router` to conditionally render components based on the current route.
Again, it really is just a wrapper around `ive.watch`.

Create a new file `Routing.tsx` with the following content:
```tsx
import ive from 'ive-fw/ive';

const Home = () => (


Home


Welcome to the home page!


About

);

const About = () => (


About


Learn more about us!



);

const Greet = ({ name }: { name: string }) => (


Greet


Hello, {name}!



);

export default ive.router("/", {
'/': , // statically rendered
'/about': About, // lazily rendered
'/greet/{name}': Greet, // lazily rendered with parameters
}, () => ( // optional fallback route


404


Page not found!



));
```

You could also use dynamic imports to lazily load components:
```tsx
export default ive.route({
'/greet/{name}': import('./Greet')
});
```