@alixex/ranview 0.1.0-alpha.0 → 0.2.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.
package/README.md CHANGED
@@ -7,15 +7,57 @@ the exact node bound to it.
7
7
  It runs in a browser against real elements, and in Node against a mock that serialises to
8
8
  HTML, so the same view code renders client-side or to a string.
9
9
 
10
- This is the view layer under [ranui](https://www.npmjs.com/package/ranui)'s 40 components.
11
- It lived inside that package until it outgrew it: a general-purpose library should not
12
- require you to install a video player, a diagram renderer and a maths typesetter to use
13
- it. `ranui/builder` still re-exports everything here, unchanged.
10
+ The DOM builder and reactive primitives behind [ranui](https://www.npmjs.com/package/ranui).
11
+ Use it on its own for application views; `ranui/builder` exposes the builder APIs for
12
+ ranui consumers. It does not register custom elements.
13
+
14
+ **ESM-only · TypeScript.** Use Node 24+ for server rendering;
15
+ browser reactivity requires a browser DOM. There is no hydration API.
16
+
17
+ ## Quick start
14
18
 
15
19
  ```sh
16
- npm i @alixex/ranview
20
+ npm install @alixex/ranview
21
+ ```
22
+
23
+ ```ts
24
+ import { Div, Span, ButtonBuilder, signal, createRoot } from '@alixex/ranview';
25
+
26
+ const dispose = createRoot((dispose) => {
27
+ const [count, setCount] = signal(0);
28
+ const view = Div()
29
+ .children(
30
+ Span().text(() => `Count: ${count()}`),
31
+ ButtonBuilder()
32
+ .text('+1')
33
+ .on('click', () => setCount((value) => value + 1)),
34
+ )
35
+ .build();
36
+ document.body.appendChild(view);
37
+ return () => {
38
+ view.remove();
39
+ dispose();
40
+ };
41
+ });
42
+ // Call dispose() when the page is unmounted.
43
+ ```
44
+
45
+ For a static server snapshot, import from `@alixex/ranview/static`:
46
+
47
+ ```ts
48
+ import { Div } from '@alixex/ranview/static';
49
+
50
+ console.log(Div().text('Hello').serialize()); // <div>Hello</div>
17
51
  ```
18
52
 
53
+ ## Guide
54
+
55
+ - [Elements](#1-elements) — factories, SVG, attributes and events
56
+ - [Reactivity](#2-reactivity) — signals, bindings and control flow
57
+ - [Ownership](#3-ownership--the-key-to-leak-free-apps-and-mpas) — disposal and page scopes
58
+ - [EventManager](#4-web-component-listeners--eventmanager) — listener lifecycle
59
+ - [Static DOM and SSR](#static-dom-and-ssr--ssg-snapshots) — one-shot snapshots
60
+
19
61
  > **Principle: build once, update in place.** A view function runs once; state
20
62
  > changes flow through fine-grained bindings, never by re-running the view. Pick
21
63
  > the primitive that matches the shape — value → getter binding; conditional →
@@ -23,27 +65,7 @@ npm i @alixex/ranview
23
65
  > [`For`](#keyed-lists--for) / [`Index`](#index-lists--index). A raw getter child
24
66
  > is the coarse fallback (rebuilds its whole region on any read).
25
67
 
26
- ```ts
27
- import {
28
- View,
29
- Div,
30
- Span,
31
- ButtonBuilder, // element factories
32
- signal,
33
- computed,
34
- createEffect,
35
- batch,
36
- untrack, // reactivity
37
- createRoot,
38
- onCleanup,
39
- getOwner,
40
- runWithOwner, // ownership
41
- EventManager, // lifecycle-scoped events
42
- } from '@alixex/ranview';
43
- ```
44
-
45
- The builder does **not** register custom elements. To use `<r-button>` etc.,
46
- also import the component subpath once: `import 'ranui/button'`.
68
+ To use `<r-button>` etc., import the component subpath once: `import 'ranui/button'`.
47
69
 
48
70
  ---
49
71
 
@@ -444,3 +466,55 @@ disconnectedCallback() { this.events.abort(); } // resets for the next connect
444
466
  - **Components vs builder**: use registered `<r-*>` elements (see
445
467
  [ranui's component list](../ranui/docs/COMPONENTS.md)) for rich widgets; use the builder for
446
468
  layout/glue and reactive views. Theme tokens: [ranui's DESIGN.md](../ranui/docs/DESIGN.md).
469
+
470
+ ## Static DOM and SSR / SSG snapshots
471
+
472
+ Use the static entry when nodes will not update after construction:
473
+
474
+ ```ts
475
+ import { Div, Span, For } from '@alixex/ranview/static';
476
+
477
+ const page = Div()
478
+ .class('page')
479
+ .children(
480
+ Span().text(() => data.title),
481
+ For({
482
+ each: () => data.items,
483
+ key: (item) => item.id,
484
+ render: (item) => Span().text(item.title),
485
+ }),
486
+ );
487
+
488
+ const element = page.build(); // real DOM in a browser, a mock node in Node
489
+ const html = page.serialize(); // escaped HTML suitable for SSR / SSG
490
+ ```
491
+
492
+ The static entry shares node operations with the default entry but imports no signal
493
+ runtime. Binding and child getters are evaluated when applied, once per occurrence.
494
+ `Show`, `Switch`, `For`, and `Index` return one-shot child getters: there are no effects,
495
+ subscriptions, list reconciliation, or comment markers. `For` accepts the familiar
496
+ `key` option for source compatibility but does not use it to reconcile a snapshot.
497
+ Refs, SVG namespaces, shadow construction, event listeners, and serialization work
498
+ as with the default entry. Static listeners still handle events; static does not mean
499
+ that clicks are disabled. Do not pass reactive `For` / `Index` handles to this entry;
500
+ import the control-flow helpers from the same entry as your factories.
501
+
502
+ Static getters are ordinary callbacks. If you build a static subtree _inside_ an
503
+ existing reactive effect and read signals, wrap construction in `untrack` from the
504
+ default entry to avoid subscribing that surrounding effect.
505
+
506
+ The default entry now also treats server rendering as a snapshot: bindings and
507
+ control flow execute without tracking, and subsequent signal writes do not change
508
+ already-built server nodes. Browser bindings from the default entry remain reactive.
509
+ Direct values already avoid effects in both entries, so prefer them when no getter
510
+ is needed. This change does not globally disable `signal`, `computed`, or explicit
511
+ `createEffect` calls in server application code.
512
+
513
+ Both entries retain an intermediate node tree. There is no hydration or direct HTML
514
+ streaming API added by the static entry; use it when refs, node manipulation, and
515
+ shadow serialization matter.
516
+
517
+ Run `pnpm -F @alixex/ranview bench:ssr` for build-and-serialize timings covering
518
+ plain values, getters, conditionals and 100-item lists. The benchmark checks output
519
+ equivalence before timing and reports the median of seven warmed batches. Results
520
+ are local microbenchmarks, not end-to-end request latency or a memory measurement.
@@ -0,0 +1,128 @@
1
+ import type { EventManager } from "./events.js";
2
+ import type { Child, Ref } from "./core.js";
3
+ type Getter<T> = () => T;
4
+ export interface BuilderRuntime {
5
+ bind<V>(value: V | Getter<V>, apply: (value: V) => void): void;
6
+ append(parent: Node, items: Child[]): void;
7
+ }
8
+ /** One-shot node operations shared by SSR and the signal-free static entry. */
9
+ export declare const staticRuntime: BuilderRuntime;
10
+ export declare const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
11
+ export declare class ElementBuilder<T extends HTMLElement = HTMLElement> {
12
+ private runtime;
13
+ private el;
14
+ /**
15
+ * @param tag element name
16
+ * @param namespace element namespace; inferred for SVG-only tags, and forced
17
+ * by `Svg()` for the tags SVG shares with HTML.
18
+ *
19
+ * The namespace matters more than it looks. `document.createElement('svg')`
20
+ * yields an `HTMLUnknownElement`: the browser does not render it as SVG, and
21
+ * -- because HTML lowercases attribute names -- `viewBox` lands as `viewbox`,
22
+ * which SVG reads case-sensitively and therefore ignores. An icon built that
23
+ * way is invisible, with markup that looks right in a serialized page.
24
+ */
25
+ constructor(tag: string, namespace?: string, runtime?: BuilderRuntime);
26
+ id(value: string): this;
27
+ /**
28
+ * Apply a value now, or bind it reactively when a getter is passed.
29
+ * A getter creates an effect owned by the current reactive scope (createRoot),
30
+ * so the binding is disposed automatically when that scope is torn down.
31
+ */
32
+ private bind;
33
+ /**
34
+ * Sets the element's class.
35
+ *
36
+ * Written through `setAttribute` rather than `className`. On an SVG element `className`
37
+ * is a read-only `SVGAnimatedString`, so assigning to it throws
38
+ * `Cannot set property className of [object SVGElement] which has only a getter` — which,
39
+ * happening inside a custom element's constructor, leaves the element un-upgraded with
40
+ * no shadow root rather than reporting a styling problem. `setAttribute` is equivalent
41
+ * for HTML elements and correct for both.
42
+ */
43
+ class(name: string | Getter<string>): this;
44
+ addClass(...names: string[]): this;
45
+ removeClass(...names: string[]): this;
46
+ attr(name: string, value: string | Getter<string>): this;
47
+ attrs(values: Record<string, string | number | boolean | null | undefined>): this;
48
+ boolAttr(name: string, value: boolean | Getter<boolean>, enabledValue?: string): this;
49
+ part(value: string | Getter<string>): this;
50
+ data(key: string, value: string | Getter<string>): this;
51
+ style(keyOrMap: string | Record<string, string>, value?: string | Getter<string>): this;
52
+ cssVar(name: string, value: string | Getter<string>): this;
53
+ aria(key: string, value: string | Getter<string>): this;
54
+ role(value: string | Getter<string>): this;
55
+ tabIndex(value: number): this;
56
+ label(value: string | Getter<string>): this;
57
+ labelledBy(id: string | Getter<string>): this;
58
+ describedBy(id: string | Getter<string>): this;
59
+ ariaHidden(hidden?: boolean): this;
60
+ /**
61
+ * Permanent build-time listener — tied to the element's lifetime.
62
+ * Use for internal shadow DOM elements created in the constructor.
63
+ */
64
+ on<K extends keyof HTMLElementEventMap>(type: K, listener: (this: T, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): this;
65
+ /**
66
+ * Lifecycle-managed listener — registered into an EventManager.
67
+ * Use in connectedCallback when building elements that need cleanup on disconnect.
68
+ * Call manager.abort() in disconnectedCallback to remove all listeners at once.
69
+ */
70
+ listen<K extends keyof HTMLElementEventMap>(manager: EventManager, type: K, handler: (this: T, ev: HTMLElementEventMap[K]) => any, options?: Omit<AddEventListenerOptions, 'signal'>): this;
71
+ /**
72
+ * Delegated listener — the built element acts as the parent container.
73
+ * Fires handler only when the event originates from a descendant matching selector.
74
+ * Registered into an EventManager so it is cleaned up with manager.abort().
75
+ *
76
+ * Div().class('list')
77
+ * .children(...)
78
+ * .delegate(scope, '.item', 'click', (ev, item) => handleItem(item))
79
+ * .build();
80
+ */
81
+ delegate<K extends keyof HTMLElementEventMap>(manager: EventManager, selector: string, type: K, handler: (ev: HTMLElementEventMap[K], target: Element) => void, options?: Omit<AddEventListenerOptions, 'signal'>): this;
82
+ children(...items: Child[]): this;
83
+ replaceChildren(...items: Child[]): this;
84
+ text(value: string | Getter<string>): this;
85
+ /**
86
+ * Set the element's content from a string of markup, without escaping it.
87
+ *
88
+ * The counterpart to `text()`, and named for the difference: `text()` escapes,
89
+ * this does not. Everything handed here is parsed as HTML, so anything that
90
+ * came from outside the program must be sanitized before it arrives.
91
+ *
92
+ * It exists because some content simply *is* HTML, and a builder without this
93
+ * cannot express it at all: markdown rendered for a page, a fragment assembled
94
+ * somewhere else, a translated string that carries its own emphasis
95
+ * (`Local-first · <b>open source</b>`). That gap is why a static-site
96
+ * generator with markdown in it could not be written against this API and had
97
+ * to concatenate strings instead.
98
+ *
99
+ * Like `textContent`, this replaces whatever content the element had --
100
+ * including anything set by `text()` or `children()` before it.
101
+ */
102
+ unsafeHtml(value: string | Getter<string>): this;
103
+ ref(holder: Ref<T>): this;
104
+ shadow(options?: ShadowRootInit): ShadowBuilder<T>;
105
+ build(): T;
106
+ serialize(): string;
107
+ }
108
+ export declare class ShadowBuilder<T extends HTMLElement = HTMLElement> {
109
+ private runtime;
110
+ private root;
111
+ private hostEl;
112
+ /**
113
+ * `options` is taken and discarded: `attachShadow` has already consumed it by the time
114
+ * a builder exists, and nothing ever read the copy this class used to keep. The
115
+ * parameter stays so the call signature is unchanged.
116
+ */
117
+ constructor(host: T, root: ShadowRoot, _options: ShadowRootInit, runtime?: BuilderRuntime);
118
+ children(...items: Child[]): this;
119
+ adoptSheet(...sheets: CSSStyleSheet[]): this;
120
+ css(cssText: string): this;
121
+ done(): {
122
+ host: T;
123
+ shadow: ShadowRoot;
124
+ };
125
+ serialize(): string;
126
+ }
127
+ export {};
128
+ //# sourceMappingURL=builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../src/builder.ts"],"names":[],"mappings":"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"}
package/dist/core.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { EventManager } from './events';
2
- import { type Getter } from './signal';
1
+ import { ElementBuilder as BaseElementBuilder } from "./builder.js";
2
+ import { type Getter } from "./signal.js";
3
3
  export interface Ref<T extends HTMLElement = HTMLElement> {
4
4
  current: T | null;
5
5
  }
@@ -135,120 +135,9 @@ export type IndexHandle = {
135
135
  * );
136
136
  */
137
137
  export declare function Index<T>(options: IndexOptions<T>): IndexHandle;
138
- export declare const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
139
- export declare class ElementBuilder<T extends HTMLElement = HTMLElement> {
140
- private el;
141
- /**
142
- * @param tag element name
143
- * @param namespace element namespace; inferred for SVG-only tags, and forced
144
- * by `Svg()` for the tags SVG shares with HTML.
145
- *
146
- * The namespace matters more than it looks. `document.createElement('svg')`
147
- * yields an `HTMLUnknownElement`: the browser does not render it as SVG, and
148
- * -- because HTML lowercases attribute names -- `viewBox` lands as `viewbox`,
149
- * which SVG reads case-sensitively and therefore ignores. An icon built that
150
- * way is invisible, with markup that looks right in a serialized page.
151
- */
138
+ export { ShadowBuilder, SVG_NAMESPACE } from "./builder.js";
139
+ /** Reactive browser builder; SSR bindings are untracked snapshots. */
140
+ export declare class ElementBuilder<T extends HTMLElement = HTMLElement> extends BaseElementBuilder<T> {
152
141
  constructor(tag: string, namespace?: string);
153
- id(value: string): this;
154
- /**
155
- * Apply a value now, or bind it reactively when a getter is passed.
156
- * A getter creates an effect owned by the current reactive scope (createRoot),
157
- * so the binding is disposed automatically when that scope is torn down.
158
- */
159
- private bind;
160
- /**
161
- * Sets the element's class.
162
- *
163
- * Written through `setAttribute` rather than `className`. On an SVG element `className`
164
- * is a read-only `SVGAnimatedString`, so assigning to it throws
165
- * `Cannot set property className of [object SVGElement] which has only a getter` — which,
166
- * happening inside a custom element's constructor, leaves the element un-upgraded with
167
- * no shadow root rather than reporting a styling problem. `setAttribute` is equivalent
168
- * for HTML elements and correct for both.
169
- */
170
- class(name: string | Getter<string>): this;
171
- addClass(...names: string[]): this;
172
- removeClass(...names: string[]): this;
173
- attr(name: string, value: string | Getter<string>): this;
174
- attrs(values: Record<string, string | number | boolean | null | undefined>): this;
175
- boolAttr(name: string, value: boolean | Getter<boolean>, enabledValue?: string): this;
176
- part(value: string | Getter<string>): this;
177
- data(key: string, value: string | Getter<string>): this;
178
- style(keyOrMap: string | Record<string, string>, value?: string | Getter<string>): this;
179
- cssVar(name: string, value: string | Getter<string>): this;
180
- aria(key: string, value: string | Getter<string>): this;
181
- role(value: string | Getter<string>): this;
182
- tabIndex(value: number): this;
183
- label(value: string | Getter<string>): this;
184
- labelledBy(id: string | Getter<string>): this;
185
- describedBy(id: string | Getter<string>): this;
186
- ariaHidden(hidden?: boolean): this;
187
- /**
188
- * Permanent build-time listener — tied to the element's lifetime.
189
- * Use for internal shadow DOM elements created in the constructor.
190
- */
191
- on<K extends keyof HTMLElementEventMap>(type: K, listener: (this: T, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): this;
192
- /**
193
- * Lifecycle-managed listener — registered into an EventManager.
194
- * Use in connectedCallback when building elements that need cleanup on disconnect.
195
- * Call manager.abort() in disconnectedCallback to remove all listeners at once.
196
- */
197
- listen<K extends keyof HTMLElementEventMap>(manager: EventManager, type: K, handler: (this: T, ev: HTMLElementEventMap[K]) => any, options?: Omit<AddEventListenerOptions, 'signal'>): this;
198
- /**
199
- * Delegated listener — the built element acts as the parent container.
200
- * Fires handler only when the event originates from a descendant matching selector.
201
- * Registered into an EventManager so it is cleaned up with manager.abort().
202
- *
203
- * Div().class('list')
204
- * .children(...)
205
- * .delegate(scope, '.item', 'click', (ev, item) => handleItem(item))
206
- * .build();
207
- */
208
- delegate<K extends keyof HTMLElementEventMap>(manager: EventManager, selector: string, type: K, handler: (ev: HTMLElementEventMap[K], target: Element) => void, options?: Omit<AddEventListenerOptions, 'signal'>): this;
209
- children(...items: Child[]): this;
210
- replaceChildren(...items: Child[]): this;
211
- text(value: string | Getter<string>): this;
212
- /**
213
- * Set the element's content from a string of markup, without escaping it.
214
- *
215
- * The counterpart to `text()`, and named for the difference: `text()` escapes,
216
- * this does not. Everything handed here is parsed as HTML, so anything that
217
- * came from outside the program must be sanitized before it arrives.
218
- *
219
- * It exists because some content simply *is* HTML, and a builder without this
220
- * cannot express it at all: markdown rendered for a page, a fragment assembled
221
- * somewhere else, a translated string that carries its own emphasis
222
- * (`Local-first · <b>open source</b>`). That gap is why a static-site
223
- * generator with markdown in it could not be written against this API and had
224
- * to concatenate strings instead.
225
- *
226
- * Like `textContent`, this replaces whatever content the element had --
227
- * including anything set by `text()` or `children()` before it.
228
- */
229
- unsafeHtml(value: string | Getter<string>): this;
230
- ref(holder: Ref<T>): this;
231
- shadow(options?: ShadowRootInit): ShadowBuilder<T>;
232
- build(): T;
233
- serialize(): string;
234
142
  }
235
- export declare class ShadowBuilder<T extends HTMLElement = HTMLElement> {
236
- private root;
237
- private hostEl;
238
- /**
239
- * `options` is taken and discarded: `attachShadow` has already consumed it by the time
240
- * a builder exists, and nothing ever read the copy this class used to keep. The
241
- * parameter stays so the call signature is unchanged.
242
- */
243
- constructor(host: T, root: ShadowRoot, _options: ShadowRootInit);
244
- children(...items: Child[]): this;
245
- adoptSheet(...sheets: CSSStyleSheet[]): this;
246
- css(cssText: string): this;
247
- done(): {
248
- host: T;
249
- shadow: ShadowRoot;
250
- };
251
- serialize(): string;
252
- }
253
- export {};
254
143
  //# sourceMappingURL=core.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}
package/dist/events.d.ts CHANGED
@@ -1,64 +1,3 @@
1
- /**
2
- * EventManager — lifecycle-scoped event registry backed by AbortController.
3
- *
4
- * Web Component usage:
5
- *
6
- * private _events = new EventManager();
7
- *
8
- * connectedCallback() {
9
- * this._events
10
- * .on(this._input, 'input', this.handleInput)
11
- * .on(this, 'click', this.handleClick, { capture: true });
12
- * }
13
- *
14
- * disconnectedCallback() {
15
- * this._events.abort(); // removes all listeners, resets for next connect
16
- * }
17
- *
18
- * Page development usage:
19
- *
20
- * function initSection(container: HTMLElement) {
21
- * const scope = new EventManager();
22
- *
23
- * scope
24
- * .on(input, 'input', handleSearch)
25
- * .delegate(container, '[data-action]', 'click', (ev, target) => {
26
- * handleAction(target.getAttribute('data-action'));
27
- * });
28
- *
29
- * return () => scope.abort(); // call on section teardown
30
- * }
31
- */
32
- export declare class EventManager {
33
- /**
34
- * Created on first use, and dropped again by {@link abort}.
35
- *
36
- * No component registers a listener in its constructor — they all wait for
37
- * `connectedCallback` — and some managers, like the drag-scoped one in `r-progress`,
38
- * only ever register during an interaction that may not happen. Allocating eagerly
39
- * charged every construction, and every `abort()`, for a controller that might go unused:
40
- * about 30% of a mount/unmount cycle for `r-progress`.
41
- */
42
- private ac;
43
- /** The underlying AbortSignal — pass to addEventListener options directly if needed. */
44
- get signal(): AbortSignal;
45
- on<K extends keyof HTMLElementEventMap>(target: HTMLElement, type: K, handler: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: Omit<AddEventListenerOptions, 'signal'>): this;
46
- on(target: EventTarget, type: string, handler: EventListener, options?: Omit<AddEventListenerOptions, 'signal'>): this;
47
- /**
48
- * Event delegation — attach one listener to `parent`, fire `handler` only when
49
- * the event originates from a descendant matching `selector`.
50
- *
51
- * The handler receives the original event and the matched element as arguments.
52
- *
53
- * scope.delegate(list, '.item', 'click', (ev, item) => {
54
- * console.log(item.dataset.id);
55
- * });
56
- */
57
- delegate<K extends keyof HTMLElementEventMap>(parent: HTMLElement, selector: string, type: K, handler: (ev: HTMLElementEventMap[K], target: Element) => void, options?: Omit<AddEventListenerOptions, 'signal'>): this;
58
- /**
59
- * Remove all registered listeners and drop the controller.
60
- * Safe to call multiple times; the next on() / delegate() starts a fresh one.
61
- */
62
- abort(): void;
63
- }
1
+ /** Lifecycle-scoped listeners share the utility package's lazy controller runtime. */
2
+ export { EventManager } from 'ranuts/utils';
64
3
  //# sourceMappingURL=events.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,YAAY;IACvB;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,CAAgC;IAE1C,wFAAwF;IACxF,IAAI,MAAM,IAAI,WAAW,CAGxB;IAED,EAAE,CAAC,CAAC,SAAS,MAAM,mBAAmB,EACpC,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC,KAAK,GAAG,EAC/D,OAAO,CAAC,EAAE,IAAI,CAAC,uBAAuB,EAAE,QAAQ,CAAC,GAChD,IAAI,CAAC;IACR,EAAE,CACA,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,aAAa,EACtB,OAAO,CAAC,EAAE,IAAI,CAAC,uBAAuB,EAAE,QAAQ,CAAC,GAChD,IAAI,CAAC;IAMR;;;;;;;;;OASG;IACH,QAAQ,CAAC,CAAC,SAAS,MAAM,mBAAmB,EAC1C,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,CAAC,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,EAC9D,OAAO,CAAC,EAAE,IAAI,CAAC,uBAAuB,EAAE,QAAQ,CAAC,GAChD,IAAI,CAUN;IAED;;;OAGG;IACH,KAAK,IAAI,IAAI,CAGZ;CACF"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC"}