rasti 4.0.0 → 4.1.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,238 @@
1
+ import View, { ViewOptions } from './View.js';
2
+ import Model from './Model.js';
3
+
4
+ export interface ComponentReservedOptions<S = any, M = any> extends ViewOptions<M> {
5
+ /**
6
+ * A unique key to identify the component.
7
+ * Components with keys are recycled when the same key is found in the previous render.
8
+ * Unkeyed components are recycled based on type and position.
9
+ */
10
+ key?: string;
11
+ /**
12
+ * A `Model` or any emitter object containing data and business logic, to be used as internal
13
+ * state. The component will listen to `change` events and call `onChange` lifecycle method.
14
+ */
15
+ state?: S;
16
+ /** Lifecycle hook called at the end of the constructor. */
17
+ onCreate?: (...args: any[]) => void;
18
+ /** Lifecycle hook called when `model`, `state` or `props` emits `change`. */
19
+ onChange?: (...args: any[]) => void;
20
+ /** Lifecycle hook called after the first render (client only). */
21
+ onHydrate?: () => void;
22
+ /** Lifecycle hook called at the start of `recycle`, before any recycling happens. */
23
+ onBeforeRecycle?: () => void;
24
+ /** Lifecycle hook called after the component is recycled and props are updated. */
25
+ onRecycle?: () => void;
26
+ /** Lifecycle hook called at the start of `render` on update. */
27
+ onBeforeUpdate?: () => void;
28
+ /** Lifecycle hook called at the end of `render` on update. */
29
+ onUpdate?: () => void;
30
+ }
31
+
32
+ export type ComponentOptions<P = {}, S = any, M = any> = P & ComponentReservedOptions<S, M>;
33
+
34
+ /** Marker type for strings that are safe to inject as HTML without sanitization. */
35
+ export interface SafeHTML {
36
+ readonly __rastiSafeHTML: true;
37
+ toString(): string;
38
+ }
39
+
40
+ /** A partial template produced by `this.partial` — preserves structure for position-based recycling. */
41
+ export interface Partial {
42
+ strings: TemplateStringsArray;
43
+ expressions: any[];
44
+ }
45
+
46
+ /**
47
+ * Helper type for typing event handlers passed to component templates.
48
+ * `this` is bound to the component, and the handler also receives `(event, component, matched)`.
49
+ *
50
+ * @example
51
+ * const onClick: EventHandler<Todo, MouseEvent> = function(ev) {
52
+ * this.model.toggle();
53
+ * };
54
+ */
55
+ export type EventHandler<C, E extends Event = Event> = (
56
+ this: C,
57
+ event: E,
58
+ component: C,
59
+ matched: Element,
60
+ ) => void;
61
+
62
+ /**
63
+ * Helper type for typing render expressions inside component templates.
64
+ * Rasti calls the expression with the component as argument **and** binds `this` to it,
65
+ * so both arrow and `function` forms are covered.
66
+ *
67
+ * @example
68
+ * const renderTitle: RenderExpression<Todo> = ({ model }) => model.title;
69
+ * const renderTotal: RenderExpression<Todo> = function() { return this.props.total; };
70
+ */
71
+ export type RenderExpression<C> = (this: C, component: C) => any;
72
+
73
+ /** Extracts the props type `P` from a Component subclass. */
74
+ export type Props<C> = C extends Component<infer P, any, any> ? P : never;
75
+ /** Extracts the state type `S` from a Component subclass. */
76
+ export type State<C> = C extends Component<any, infer S, any> ? S : never;
77
+ /** Extracts the model type `M` from a Component / View subclass. */
78
+ export type ComponentModel<C> = C extends Component<any, any, infer M> ? M : never;
79
+
80
+ /**
81
+ * Components are a special kind of `View` designed to be easily composable. Unlike views,
82
+ * which are render-agnostic, components have a specific set of rendering guidelines that
83
+ * allow for a more declarative development style.
84
+ *
85
+ * Components are defined with the {@link Component.create} static method, which takes a
86
+ * tagged template string or a function that returns another component.
87
+ *
88
+ * @example
89
+ * import { Component, Model } from 'rasti';
90
+ * const Timer = Component.create`
91
+ * <div>Seconds: <span>${({ model }) => model.seconds}</span></div>
92
+ * `;
93
+ * const model = new Model({ seconds: 0 });
94
+ * Timer.mount({ model }, document.body);
95
+ * setInterval(() => model.seconds++, 1000);
96
+ */
97
+ declare class Component<P = {}, S = any, M = any> extends View<M> {
98
+ /**
99
+ * Mark a string as safe HTML to be rendered.
100
+ * Rasti marks string literals as safe automatically when a component is created or when
101
+ * using `this.partial`. Only use this manually when you're sure the string is safe.
102
+ */
103
+ static markAsSafeHTML(value: string): SafeHTML;
104
+
105
+ /**
106
+ * Helper method used to extend a `Component`, creating a subclass.
107
+ * @param object Object with methods to add to the subclass, or a function that receives
108
+ * the parent prototype and returns such an object.
109
+ * @return The newly created Component subclass.
110
+ */
111
+ static extend<T extends new (...args: any[]) => Component<any, any, any>>(
112
+ this: T,
113
+ object: object | ((proto: InstanceType<T>) => object),
114
+ ): T;
115
+
116
+ /**
117
+ * Mount the component into the DOM.
118
+ *
119
+ * - **Normal mount** (default): renders as HTML and appends it to `el`.
120
+ * - **Hydration mode**: assumes the DOM already contains the component's HTML (SSR).
121
+ *
122
+ * If `el` is omitted, the component is instantiated but not mounted.
123
+ *
124
+ * @param options Passed to the constructor.
125
+ * @param el Target DOM element.
126
+ * @param hydrate If `true`, hydrate an existing SSR tree instead of rendering from scratch.
127
+ * @return The component instance.
128
+ */
129
+ static mount<T extends new (...args: any[]) => Component<any, any, any>>(
130
+ this: T,
131
+ options?: ConstructorParameters<T>[0],
132
+ el?: Element,
133
+ hydrate?: boolean,
134
+ ): InstanceType<T>;
135
+
136
+ /**
137
+ * Takes a tagged template string (or a function returning another component) and returns
138
+ * a new `Component` class.
139
+ *
140
+ * - The template outer tag and attributes define the view's root element.
141
+ * - Inner HTML becomes the view's template.
142
+ * - Function interpolations are evaluated on render, bound to the component instance.
143
+ * - DOM event handlers via camelCased attributes (`onClick=${handler}`), delegated to the root.
144
+ * - Returning a component instance (or array of them) adds it as a child.
145
+ * - Use `<${Sub}>…</${Sub}>` syntax for child component tags.
146
+ *
147
+ * @example
148
+ * const Button = Component.create`
149
+ * <button class="${({ props }) => props.className}"
150
+ * onClick=${function(event, self) { self.emit('click'); }}>
151
+ * ${({ props }) => props.label}
152
+ * </button>
153
+ * `;
154
+ */
155
+ static create<P = Record<string, any>, S = any, M = any>(
156
+ strings: string | TemplateStringsArray | ((...args: any[]) => any),
157
+ ...expressions: any[]
158
+ ): typeof Component<P, S, M>;
159
+
160
+ /**
161
+ * Props passed from the parent component, stored as a `Model` for reactive updates.
162
+ * Accessible directly (`this.props.foo`) or via `Model` API (`this.props.get('foo')`).
163
+ */
164
+ props: Model<P> & P;
165
+
166
+ /**
167
+ * A `Model` or any emitter object containing data and business logic, to be used as internal
168
+ * state. The component will listen to `change` events and call `onChange` lifecycle method.
169
+ */
170
+ state?: S;
171
+
172
+ /** The original options object passed to the constructor. */
173
+ options: ComponentOptions<P, S, M>;
174
+
175
+ /** Template function returning the view's inner HTML. */
176
+ template: (...args: any[]) => string;
177
+
178
+ /**
179
+ * @param options Component options. Keys `model`, `state`, `key`, `onCreate`, `onChange`,
180
+ * `onHydrate`, `onBeforeRecycle`, `onRecycle`, `onBeforeUpdate`, `onUpdate`, `onDestroy`
181
+ * are merged into `this`. Any remaining options become `this.props`.
182
+ */
183
+ constructor(options?: ComponentOptions<P, S, M>, ...args: any[]);
184
+
185
+ /**
186
+ * Tagged template helper bound to the component instance.
187
+ * Returns a `Partial` that preserves structure for position-based recycling.
188
+ * String literals are marked as safe HTML automatically.
189
+ *
190
+ * @example
191
+ * renderHeader() {
192
+ * return this.partial`<header><${Title}>${this.model.title}</${Title}></header>`;
193
+ * }
194
+ */
195
+ partial(strings: TemplateStringsArray, ...expressions: any[]): Partial;
196
+
197
+ /**
198
+ * Subscribes to a `change` event on a model or emitter and invokes `onChange`.
199
+ * Cleaned up automatically on destroy. By default the component subscribes to
200
+ * `this.model`, `this.state` and `this.props`.
201
+ */
202
+ subscribe(model: object, type?: string, listener?: (...args: any[]) => void): this;
203
+
204
+ /**
205
+ * Render the component.
206
+ *
207
+ * - **First render** (`this.el` absent): renders as a string inside a `DocumentFragment`
208
+ * and hydrates it. `onHydrate` is called.
209
+ * - **Update render** (`this.el` present): updates root attributes and interpolation content.
210
+ * `onBeforeUpdate` and `onUpdate` are called.
211
+ */
212
+ render(): this;
213
+
214
+ /** Lifecycle. Called at the end of the constructor. Runs on both client and server. */
215
+ onCreate(...args: any[]): void;
216
+
217
+ /** Lifecycle. Called when model/state/props emit `change`. Default: triggers `render`. */
218
+ onChange(model: object, changed: object, ...args: any[]): void;
219
+
220
+ /** Lifecycle. Called after the first render hydrates the DOM. Client only. */
221
+ onHydrate(): void;
222
+
223
+ /** Lifecycle. Called at the start of `recycle`, before any recycling happens. */
224
+ onBeforeRecycle(): void;
225
+
226
+ /** Lifecycle. Called when the component is recycled and its props are updated. */
227
+ onRecycle(): void;
228
+
229
+ /** Lifecycle. Called at the start of `render` on update. */
230
+ onBeforeUpdate(): void;
231
+
232
+ /** Lifecycle. Called at the end of `render` on update. */
233
+ onUpdate(): void;
234
+ }
235
+
236
+ declare const _default: typeof Component;
237
+ export default _default;
238
+ export { Component };
@@ -0,0 +1,111 @@
1
+ export type EventMap = Record<string, (...args: any[]) => void>;
2
+
3
+ /**
4
+ * `Emitter` is a class that provides an easy way to implement the observer pattern
5
+ * in your applications.
6
+ *
7
+ * It can be extended to create new classes that have the ability to emit and bind custom named events.
8
+ * Emitter is used by `Model` and `View` classes, which inherit from it to implement
9
+ * event-driven functionality.
10
+ *
11
+ * ## Inverse of Control Pattern
12
+ *
13
+ * The Emitter class includes "inverse of control" methods (`listenTo`, `listenToOnce`, `stopListening`)
14
+ * that allow an object to manage its own listening relationships, making cleanup easier and
15
+ * preventing memory leaks.
16
+ *
17
+ * @example
18
+ * import { Emitter } from 'rasti';
19
+ * class ShoppingCart extends Emitter {
20
+ * constructor() {
21
+ * super();
22
+ * this.items = [];
23
+ * }
24
+ * addItem(item) {
25
+ * this.items.push(item);
26
+ * this.emit('itemAdded', item);
27
+ * }
28
+ * }
29
+ */
30
+ export default class Emitter<E extends EventMap = EventMap> {
31
+ /** Registered event listeners, keyed by event type. */
32
+ listeners?: { [K in keyof E]?: Array<E[K]> };
33
+ /** Active `listenTo` subscriptions, tracked so `stopListening` can clean them up. */
34
+ listeningTo?: Array<{
35
+ emitter: Emitter<any>;
36
+ type: string;
37
+ listener: (...args: any[]) => void;
38
+ }>;
39
+
40
+ /**
41
+ * Adds event listener.
42
+ * @param type Type of the event (e.g. `change`).
43
+ * @param listener Callback function to be called when the event is emitted.
44
+ * @return A function to remove the listener.
45
+ * @example
46
+ * this.model.on('change', this.render.bind(this));
47
+ */
48
+ on<K extends keyof E>(type: K, listener: E[K]): () => void;
49
+
50
+ /**
51
+ * Adds event listener that executes once.
52
+ * @param type Type of the event (e.g. `change`).
53
+ * @param listener Callback function to be called when the event is emitted.
54
+ * @return A function to remove the listener.
55
+ * @example
56
+ * this.model.once('change', () => console.log('This will happen once'));
57
+ */
58
+ once<K extends keyof E>(type: K, listener: E[K]): () => void;
59
+
60
+ /**
61
+ * Removes event listeners with flexible parameter combinations.
62
+ *
63
+ * - `off()` - Removes ALL listeners from this emitter
64
+ * - `off(type)` - Removes all listeners for the specified event type
65
+ * - `off(type, listener)` - Removes the specific listener for the specified event type
66
+ */
67
+ off(): void;
68
+ off<K extends keyof E>(type: K, listener?: E[K]): void;
69
+
70
+ /**
71
+ * Emits event of specified type. Listeners will receive specified arguments.
72
+ * @param type Type of the event (e.g. `change`).
73
+ * @param args Optional arguments to be passed to listeners.
74
+ * @example
75
+ * this.emit('change', { field: 'name', value: 'John' });
76
+ */
77
+ emit<K extends keyof E>(type: K, ...args: Parameters<E[K]>): void;
78
+
79
+ /**
80
+ * Listen to an event of another emitter (Inverse of Control pattern).
81
+ *
82
+ * Allows this object to track and clean up all its listeners at once via `stopListening()`.
83
+ * @param emitter The emitter to listen to.
84
+ * @param type The type of the event to listen to.
85
+ * @param listener The listener to call when the event is emitted.
86
+ * @return A function to stop listening to the event.
87
+ * @example
88
+ * this.listenTo(otherModel, 'change', this.render.bind(this));
89
+ */
90
+ listenTo(emitter: Emitter<any>, type: string, listener: (...args: any[]) => void): () => void;
91
+
92
+ /**
93
+ * Listen to an event of another emitter and remove the listener after it is called.
94
+ * Similar to `listenTo()` but the listener runs only once.
95
+ * @param emitter The emitter to listen to.
96
+ * @param type The type of the event to listen to.
97
+ * @param listener The listener to call when the event is emitted.
98
+ * @return A function to stop listening to the event.
99
+ */
100
+ listenToOnce(emitter: Emitter<any>, type: string, listener: (...args: any[]) => void): () => void;
101
+
102
+ /**
103
+ * Stop listening to events from other emitters.
104
+ *
105
+ * - `stopListening()` - Stops listening to ALL events from ALL emitters
106
+ * - `stopListening(emitter)` - Stops listening to all events from the specified emitter
107
+ * - `stopListening(emitter, type)` - Stops listening to the specified event type from the specified emitter
108
+ * - `stopListening(emitter, type, listener)` - Stops the specific listener for the specific event
109
+ */
110
+ stopListening(emitter?: Emitter<any>, type?: string, listener?: (...args: any[]) => void): void;
111
+ }
@@ -0,0 +1,123 @@
1
+ import Emitter from './Emitter.js';
2
+
3
+ /** Extracts the attribute type `A` from a Model subclass. */
4
+ export type Attrs<M> = M extends Model<infer A> ? A : never;
5
+
6
+ export type ModelEvents<A> =
7
+ & {
8
+ change: (model: Model<A>, changed: Partial<A>, ...args: any[]) => void;
9
+ [event: string]: (...args: any[]) => void;
10
+ }
11
+ & {
12
+ [K in keyof A & string as `change:${K}`]: (model: Model<A>, value: A[K], ...args: any[]) => void;
13
+ };
14
+
15
+ /**
16
+ * - Orchestrates data and business logic.
17
+ * - Emits events when data changes.
18
+ *
19
+ * A `Model` manages an internal table of data attributes and triggers change events when
20
+ * any of its data is modified. Models may handle syncing data with a persistence layer.
21
+ *
22
+ * ## Construction Flow
23
+ * 1. `preinitialize()` is called with all constructor arguments
24
+ * 2. `this.defaults` are resolved (if function, it's called and bound to the model)
25
+ * 3. `parse()` is called with all constructor arguments to process the data
26
+ * 4. `this.attributes` is built by merging defaults and parsed data
27
+ * 5. Getters/setters are generated for each attribute to emit change events
28
+ *
29
+ * @example
30
+ * import { Model } from 'rasti';
31
+ * class User extends Model {
32
+ * preinitialize() {
33
+ * this.defaults = { name: '', email: '', role: 'user' };
34
+ * }
35
+ * }
36
+ */
37
+ export default class Model<A = any> extends Emitter<ModelEvents<A>> {
38
+ /**
39
+ * Static property that defines a prefix for generated getters/setters.
40
+ * When set, all attribute properties will be prefixed (e.g., 'attr_name' instead of 'name').
41
+ * @default ''
42
+ */
43
+ static attributePrefix: string;
44
+
45
+ /**
46
+ * Default attributes for the model, merged into `this.attributes` during construction.
47
+ * Can be a plain object, or a function (called bound to the instance) that returns the
48
+ * defaults. Assign it on the prototype, or via `this.defaults` inside
49
+ * `preinitialize`.
50
+ */
51
+ defaults?: Partial<A> | (() => Partial<A>);
52
+
53
+ /** Primary data object holding the model attributes. */
54
+ attributes: A;
55
+
56
+ /** Object containing previous attributes when a change occurs. */
57
+ previous: Partial<A>;
58
+
59
+ /**
60
+ * @param attributes Primary data object containing model attributes.
61
+ * @param args Additional arguments passed to `preinitialize` and `parse`.
62
+ */
63
+ constructor(attributes?: Partial<A>, ...args: any[]);
64
+
65
+ /**
66
+ * Called before any instantiation logic runs for the Model.
67
+ * Receives all constructor arguments, allowing for flexible initialization patterns.
68
+ * Use this to set up `defaults`, configure the model, or handle custom constructor arguments.
69
+ * @example
70
+ * class User extends Model {
71
+ * preinitialize(attributes, options = {}) {
72
+ * this.defaults = { name: '', role: options.defaultRole || 'user' };
73
+ * this.apiEndpoint = options.apiEndpoint || '/users';
74
+ * }
75
+ * }
76
+ */
77
+ preinitialize(attributes?: Partial<A>, ...args: any[]): void;
78
+
79
+ /**
80
+ * Generate getter/setter for the given attribute key to emit `change` events.
81
+ * Called internally by the constructor for each key in `this.attributes`.
82
+ * Override with an empty method if you don't want automatic getters/setters.
83
+ */
84
+ defineAttribute(key: keyof A & string): void;
85
+
86
+ /**
87
+ * Get an attribute from `this.attributes`.
88
+ * @param key Attribute key.
89
+ * @return The attribute value.
90
+ */
91
+ get<K extends keyof A>(key: K): A[K];
92
+ get(key: string): any;
93
+
94
+ /**
95
+ * Set one or more attributes into `this.attributes` and emit change events.
96
+ * Supports two call signatures: `set(key, value, ...args)` or `set(object, ...args)`.
97
+ * Additional arguments are passed to change event listeners.
98
+ *
99
+ * Emits `change` (listeners receive `(model, changedAttributes, ...args)`) and
100
+ * `change:<attribute>` (listeners receive `(model, newValue, ...args)`).
101
+ *
102
+ * @return This model instance for chaining.
103
+ * @example
104
+ * model.set('name', 'Alice');
105
+ * model.set({ name: 'Alice', age: 30 });
106
+ * model.set('name', 'Bob', { silent: false });
107
+ */
108
+ set<K extends keyof A>(key: K, value: A[K], ...args: any[]): this;
109
+ set(attrs: Partial<A>, ...args: any[]): this;
110
+
111
+ /**
112
+ * Transforms and validates data before it becomes model attributes.
113
+ * Called during construction with all constructor arguments.
114
+ * Override this method to transform incoming data, create nested models, or handle different data formats.
115
+ */
116
+ parse(data?: Partial<A>, ...args: any[]): Partial<A>;
117
+
118
+ /**
119
+ * Return object representation of the model to be used for JSON serialization.
120
+ * By default returns a copy of `this.attributes`.
121
+ */
122
+ toJSON(): A;
123
+ }
@@ -0,0 +1,173 @@
1
+ import Emitter from './Emitter.js';
2
+
3
+ export interface ViewOptions<M = any> {
4
+ el?: HTMLElement | (() => HTMLElement);
5
+ tag?: string | (() => string);
6
+ attributes?: Record<string, any> | (() => Record<string, any>);
7
+ events?: Record<string, string | Function> | (() => Record<string, string | Function>);
8
+ model?: M;
9
+ template?: (...args: any[]) => string;
10
+ onDestroy?: (...args: any[]) => void;
11
+ }
12
+
13
+ /**
14
+ * - Listens for changes and renders the UI.
15
+ * - Handles user input and interactivity.
16
+ * - Sends captured input to the model.
17
+ *
18
+ * A `View` is an atomic unit of the user interface that can render data from a specific model or multiple models.
19
+ * Each `View` has a root element, `this.el`, used for event delegation. All element lookups are scoped to it.
20
+ * If `this.el` is not present, an element will be created using `this.tag` (defaulting to `div`) and `this.attributes`.
21
+ *
22
+ * @example
23
+ * import { View, Model } from 'rasti';
24
+ * class Timer extends View {
25
+ * constructor(options) {
26
+ * super(options);
27
+ * this.model = new Model({ seconds: 0 });
28
+ * this.model.on('change:seconds', this.render.bind(this));
29
+ * }
30
+ * template(model) {
31
+ * return `Seconds: <span>${View.sanitize(model.seconds)}</span>`;
32
+ * }
33
+ * render() {
34
+ * if (this.template) this.el.innerHTML = this.template(this.model);
35
+ * return this;
36
+ * }
37
+ * }
38
+ */
39
+ export default class View<M = any> extends Emitter {
40
+ /**
41
+ * Escape HTML entities in a string.
42
+ * Use this method to sanitize user-generated content before inserting it into the DOM.
43
+ */
44
+ static sanitize(value: string): string;
45
+
46
+ /**
47
+ * Reset the unique ID counter to 0.
48
+ * Useful for server-side rendering scenarios to ensure generated unique IDs match the client,
49
+ * enabling seamless hydration of components.
50
+ */
51
+ static resetUid(): void;
52
+
53
+ /** Root DOM element of the view. */
54
+ el: HTMLElement;
55
+
56
+ /** A model or any object containing data and business logic. */
57
+ model?: M;
58
+
59
+ /** Tag used to create the root element when `el` is not provided (default `div`). */
60
+ tag?: string | (() => string);
61
+
62
+ /** Attributes used to create the root element when `el` is not provided. */
63
+ attributes?: Record<string, any> | (() => Record<string, any>);
64
+
65
+ /** Declarative DOM event listeners in the form `{'event selector': listener}`. */
66
+ events?: Record<string, string | Function> | (() => Record<string, string | Function>);
67
+
68
+ /** Function returning the view's inner HTML, used by `render`. */
69
+ template?: (...args: any[]) => string;
70
+
71
+ /** Unique identifier for the view instance. */
72
+ uid: string;
73
+
74
+ /** Child views. Destroyed automatically when the parent is destroyed. */
75
+ children: View[];
76
+
77
+ /** Whether `destroy()` has been called on this view. */
78
+ destroyed: boolean;
79
+
80
+ /**
81
+ * Functions run on `destroy()`. Push cleanup callbacks here for external subscriptions
82
+ * Rasti doesn't manage (DOM events, timers, third-party libraries).
83
+ */
84
+ destroyQueue: Array<() => void>;
85
+
86
+ /**
87
+ * @param options View options. The following keys are merged into the view instance:
88
+ * `el`, `tag`, `attributes`, `events`, `model`, `template`, `onDestroy`.
89
+ */
90
+ constructor(options?: ViewOptions<M>, ...args: any[]);
91
+
92
+ /**
93
+ * If you define a preinitialize method, it will be invoked when the view is first created,
94
+ * before any instantiation logic is run. Receives all constructor arguments.
95
+ */
96
+ preinitialize(options?: ViewOptions<M>, ...args: any[]): void;
97
+
98
+ /**
99
+ * Returns the first element that matches the selector, scoped to the view's root element
100
+ * (`this.el`), or `null` if none matches. Defaults to `HTMLElement`; pass a type argument
101
+ * to narrow (e.g. `this.$<HTMLInputElement>('input.edit')`).
102
+ */
103
+ $<E extends Element = HTMLElement>(selector: string): E | null;
104
+
105
+ /**
106
+ * Returns a list of elements matching the selector, scoped to the view's root element
107
+ * (`this.el`). Defaults to `HTMLElement`; pass a type argument to narrow.
108
+ */
109
+ $$<E extends Element = HTMLElement>(selector: string): NodeListOf<E>;
110
+
111
+ /**
112
+ * Destroy the view.
113
+ * Destroys children views, undelegates events, stops listening to events, calls `onDestroy`.
114
+ * @return This view for chaining.
115
+ */
116
+ destroy(...args: any[]): this;
117
+
118
+ /**
119
+ * Lifecycle method called after the view is destroyed. Override with your cleanup code.
120
+ */
121
+ onDestroy(...args: any[]): void;
122
+
123
+ /**
124
+ * Add a view as a child. Children are stored in `this.children` and destroyed when the parent is destroyed.
125
+ * @return The child view for chaining.
126
+ */
127
+ addChild(child: View): View;
128
+
129
+ /** Call `destroy()` on children views. */
130
+ destroyChildren(): void;
131
+
132
+ /** Ensure the view has a unique id at `this.uid`. */
133
+ ensureUid(): void;
134
+
135
+ /**
136
+ * Ensure the view has a root element at `this.el`.
137
+ * Called from the constructor. Override for custom element-creation logic.
138
+ */
139
+ ensureElement(): void;
140
+
141
+ /**
142
+ * Create a DOM element. Called from the constructor if `this.el` is undefined.
143
+ * @param tag Tag for the element (default `div`).
144
+ * @param attributes Attributes for the element.
145
+ */
146
+ createElement(tag?: string, attributes?: Record<string, any>): HTMLElement;
147
+
148
+ /** Remove `this.el` from the DOM. */
149
+ removeElement(): this;
150
+
151
+ /**
152
+ * Provide declarative listeners for DOM events. The events object follows
153
+ * `{'event selector': 'listener'}` — listener may be a function or a method name on the view.
154
+ *
155
+ * Listener signature: `(event, view, matched)`.
156
+ *
157
+ * @example
158
+ * class Modal extends View {
159
+ * onClickOk() { this.close(); }
160
+ * }
161
+ * Modal.prototype.events = { 'click button.ok': 'onClickOk' };
162
+ */
163
+ delegateEvents(events?: Record<string, string | Function>): this;
164
+
165
+ /** Removes all of the view's delegated events. */
166
+ undelegateEvents(): this;
167
+
168
+ /**
169
+ * Core render function. Override to populate the view's element (`this.el`) with HTML.
170
+ * Convention: always return `this`.
171
+ */
172
+ render(): this;
173
+ }
@@ -0,0 +1,15 @@
1
+ export { default as Emitter, EventMap } from './Emitter.js';
2
+ export { default as Model, ModelEvents, Attrs } from './Model.js';
3
+ export { default as View, ViewOptions } from './View.js';
4
+ export {
5
+ default as Component,
6
+ ComponentOptions,
7
+ ComponentReservedOptions,
8
+ SafeHTML,
9
+ Partial,
10
+ EventHandler,
11
+ RenderExpression,
12
+ Props,
13
+ State,
14
+ ComponentModel,
15
+ } from './Component.js';