+1
-1
| { | ||
| "name": "rasti", | ||
| "version": "4.1.0-alpha.0", | ||
| "version": "4.1.0-alpha.1", | ||
| "description": "Modern MVC for building user interfaces", | ||
@@ -5,0 +5,0 @@ "type": "module", |
+47
-10
| <p align="center"> | ||
| <picture> | ||
| <source media="(prefers-color-scheme: dark)" srcset="https://cdn.jsdelivr.net/gh/8tentaculos/rasti@v4.1.0-alpha.0/docs/logo-dark.svg"> | ||
| <img alt="Rasti.js" src="https://cdn.jsdelivr.net/gh/8tentaculos/rasti@v4.1.0-alpha.0/docs/logo.svg" height="120"> | ||
| <source media="(prefers-color-scheme: dark)" srcset="https://cdn.jsdelivr.net/gh/8tentaculos/rasti@v4.1.0-alpha.1/docs/logo-dark.svg"> | ||
| <img alt="Rasti.js" src="https://cdn.jsdelivr.net/gh/8tentaculos/rasti@v4.1.0-alpha.1/docs/logo.svg" height="120"> | ||
| </picture> | ||
@@ -187,6 +187,32 @@ </p> | ||
| ## Scaffolding a New Project | ||
| The fastest way to start a real-world **Rasti** project is [`create-rasti`](https://github.com/8tentaculos/create-rasti), the official scaffolding tool. It generates a ready-to-use **Rasti** + **Vite** setup with optional server-side rendering, routing, styling, and icon components. | ||
| ```bash | ||
| # Interactive setup | ||
| npm create rasti | ||
| # Non-interactive single-page app | ||
| npm create rasti my-app | ||
| # Server-side rendering with routing and Tailwind CSS | ||
| npm create rasti my-app --ssr --router --tailwind | ||
| ``` | ||
| Available options include: | ||
| - **Rendering** — Single-page app (default), server-side rendering (`--ssr`), or static pre-rendering (`--static`). | ||
| - **Styling** — Plain CSS (default), Tailwind CSS (`--tailwind`), or CSSFUN with light/dark theme support (`--cssfun`). | ||
| - **Routing** (`--router`) — A small universal router built on `path-to-regexp`. | ||
| - **Icons** (`--icons`) — Generate **Rasti** components from popular SVG icon sets (heroicons, akar-icons, feathericon, pixelarticons, and more). | ||
| See the [`create-rasti` repository](https://github.com/8tentaculos/create-rasti) for the full list of templates and options. | ||
| ## Example | ||
| You can find a sample **TODO application** in the [example folder](https://github.com/8tentaculos/rasti/tree/master/example/todo) of the **Rasti** [GitHub repository](https://github.com/8tentaculos/rasti). This example serves as a great starting point for your own projects. Try it live [here](https://rasti.js.org/example/todo/index.html). | ||
| To see how **Rasti**'s API and architecture come together in a small app, explore the sample **TODO application** in the [example folder](https://github.com/8tentaculos/rasti/tree/master/example/todo) of the **Rasti** [GitHub repository](https://github.com/8tentaculos/rasti). It's a concise, self-contained reference for understanding how models, views, and components fit together in a simple application. Try it live [here](https://rasti.js.org/example/todo/index.html). | ||
| To scaffold a real-world project, use [`create-rasti`](#scaffolding-a-new-project). | ||
| ## API Documentation | ||
@@ -223,2 +249,18 @@ | ||
| `Component.extend` adds the object members to the instance type. Inside its methods, `this` is the extended component, and lifecycle overrides get their parameters typed automatically: | ||
| ```ts | ||
| const Counter = Component.create<{ initial: number }>`<div>...</div>`.extend({ | ||
| onCreate() { | ||
| this.state = new Model({ count: this.props.initial }); // `this` is typed | ||
| }, | ||
| onChange(model, changed) { // parameters typed automatically | ||
| if ('count' in changed) this.render(); | ||
| }, | ||
| increment() { this.state.count++; }, | ||
| }); | ||
| Counter.mount({ initial: 0 }, document.body).increment(); // ✅ increment is typed | ||
| ``` | ||
| ### Models | ||
@@ -283,11 +325,6 @@ | ||
| ## Version History | ||
| ## Changelog | ||
| We strive to minimize breaking changes between major versions. However, if you're migrating between major versions, please refer to the release notes below for details on any breaking changes and migration tips. | ||
| Release history and migration notes for major versions are in [CHANGELOG.md](CHANGELOG.md). | ||
| - **[v4.0.0](https://github.com/8tentaculos/rasti/releases/tag/v4.0.0)** | ||
| - **[v3.0.0](https://github.com/8tentaculos/rasti/releases/tag/v3.0.0)** | ||
| - **[v2.0.0](https://github.com/8tentaculos/rasti/releases/tag/v2.0.0)** | ||
| - **[v1.0.0](https://github.com/8tentaculos/rasti/releases/tag/v1.0.0)** | ||
| ## License | ||
@@ -294,0 +331,0 @@ |
+55
-7
@@ -41,3 +41,3 @@ import View, { ViewOptions } from './View.js'; | ||
| /** A partial template produced by `this.partial` — preserves structure for position-based recycling. */ | ||
| export interface Partial { | ||
| export interface ComponentPartial { | ||
| strings: TemplateStringsArray; | ||
@@ -79,5 +79,38 @@ expressions: any[]; | ||
| /** Extracts the model type `M` from a Component / View subclass. */ | ||
| export type ComponentModel<C> = C extends Component<any, any, infer M> ? M : never; | ||
| export type ComponentModel<C> = | ||
| C extends Component<any, any, infer M> ? M : | ||
| C extends View<infer M> ? M : | ||
| never; | ||
| /** | ||
| * Lifecycle methods, with their real signatures, made available for contextual typing | ||
| * inside `Component.extend({ ... })` so overrides don't need parameter annotations. | ||
| */ | ||
| export interface ComponentLifecycle { | ||
| /** Lifecycle. Called at the end of the constructor. Runs on both client and server. */ | ||
| onCreate?(...args: any[]): void; | ||
| /** Lifecycle. Called when model/state/props emit `change`. Default: triggers `render`. */ | ||
| onChange?(model: object, changed: Record<string, any>, ...args: any[]): void; | ||
| /** Lifecycle. Called after the first render hydrates the DOM. Client only. */ | ||
| onHydrate?(): void; | ||
| /** Lifecycle. Called at the start of `recycle`, before any recycling happens. */ | ||
| onBeforeRecycle?(): void; | ||
| /** Lifecycle. Called when the component is recycled and its props are updated. */ | ||
| onRecycle?(): void; | ||
| /** Lifecycle. Called at the start of `render` on update. */ | ||
| onBeforeUpdate?(): void; | ||
| /** Lifecycle. Called at the end of `render` on update. */ | ||
| onUpdate?(): void; | ||
| /** Lifecycle. Called when the component is destroyed. */ | ||
| onDestroy?(...args: any[]): void; | ||
| } | ||
| /** | ||
| * Class returned by `Component.extend`: keeps the statics and constructor signature of the | ||
| * parent class `T`, and adds the members of `O` to the instance type. | ||
| */ | ||
| export type ExtendedComponent<T extends new (...args: any[]) => any, O> = | ||
| Omit<T, never> & (new (...args: ConstructorParameters<T>) => InstanceType<T> & O); | ||
| /** | ||
| * Components are a special kind of `View` designed to be easily composable. Unlike views, | ||
@@ -109,2 +142,7 @@ * which are render-agnostic, components have a specific set of rendering guidelines that | ||
| * Helper method used to extend a `Component`, creating a subclass. | ||
| * | ||
| * The members of `object` are added to the resulting instance type, and `this` inside | ||
| * its methods is typed as the extended component. Lifecycle overrides (`onCreate`, | ||
| * `onChange`, ...) get their parameters typed automatically. | ||
| * | ||
| * @param object Object with methods to add to the subclass, or a function that receives | ||
@@ -114,6 +152,10 @@ * the parent prototype and returns such an object. | ||
| */ | ||
| static extend<T extends new (...args: any[]) => Component<any, any, any>>( | ||
| static extend<T extends new (...args: any[]) => Component<any, any, any>, O extends object>( | ||
| this: T, | ||
| object: object | ((proto: InstanceType<T>) => object), | ||
| ): T; | ||
| object: (proto: InstanceType<T>) => O & ThisType<InstanceType<T> & O>, | ||
| ): ExtendedComponent<T, O>; | ||
| static extend<T extends new (...args: any[]) => Component<any, any, any>, O extends object>( | ||
| this: T, | ||
| object: O & ComponentLifecycle & ThisType<InstanceType<T> & O>, | ||
| ): ExtendedComponent<T, O>; | ||
@@ -165,2 +207,8 @@ /** | ||
| /** | ||
| * A unique key to identify the component, merged from options. | ||
| * Components with keys are recycled when the same key is found in the previous render. | ||
| */ | ||
| key?: string; | ||
| /** | ||
| * Props passed from the parent component, stored as a `Model` for reactive updates. | ||
@@ -192,3 +240,3 @@ * Accessible directly (`this.props.foo`) or via `Model` API (`this.props.get('foo')`). | ||
| * Tagged template helper bound to the component instance. | ||
| * Returns a `Partial` that preserves structure for position-based recycling. | ||
| * Returns a `ComponentPartial` that preserves structure for position-based recycling. | ||
| * String literals are marked as safe HTML automatically. | ||
@@ -201,3 +249,3 @@ * | ||
| */ | ||
| partial(strings: TemplateStringsArray, ...expressions: any[]): Partial; | ||
| partial(strings: TemplateStringsArray, ...expressions: any[]): ComponentPartial; | ||
@@ -204,0 +252,0 @@ /** |
+3
-1
@@ -9,3 +9,3 @@ export { default as Emitter, EventMap } from './Emitter.js'; | ||
| SafeHTML, | ||
| Partial, | ||
| ComponentPartial, | ||
| EventHandler, | ||
@@ -16,2 +16,4 @@ RenderExpression, | ||
| ComponentModel, | ||
| ComponentLifecycle, | ||
| ExtendedComponent, | ||
| } from './Component.js'; |
+11
-3
@@ -41,2 +41,10 @@ import Emitter from './Emitter.js'; | ||
| /** | ||
| * Counter for generating unique IDs for view instances. | ||
| * For server-side rendering, reset it to `0` on every request (see `resetUid`) so the | ||
| * generated IDs match those on the client, enabling seamless hydration of components. | ||
| * @default 0 | ||
| */ | ||
| static uid: number; | ||
| /** | ||
| * Escape HTML entities in a string. | ||
@@ -78,4 +86,4 @@ * Use this method to sanitize user-generated content before inserting it into the DOM. | ||
| /** Whether `destroy()` has been called on this view. */ | ||
| destroyed: boolean; | ||
| /** Whether `destroy()` has been called on this view. `undefined` until then. */ | ||
| destroyed?: boolean; | ||
@@ -129,3 +137,3 @@ /** | ||
| */ | ||
| addChild(child: View): View; | ||
| addChild<C extends View>(child: C): C; | ||
@@ -132,0 +140,0 @@ /** Call `destroy()` on children views. */ |
1999877
0.21%13429
0.4%334
12.46%