summitjs 0.1.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/AGENTS.md +105 -0
- package/LICENSE +21 -0
- package/README.md +160 -0
- package/dist/summit.cjs +3324 -0
- package/dist/summit.cjs.map +1 -0
- package/dist/summit.d.cts +269 -0
- package/dist/summit.d.ts +269 -0
- package/dist/summit.js +3304 -0
- package/dist/summit.js.map +1 -0
- package/dist/summit.min.js +7 -0
- package/dist/summit.min.js.map +1 -0
- package/package.json +79 -0
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-element bookkeeping.
|
|
3
|
+
*
|
|
4
|
+
* Summit attaches a small metadata record to every element it touches: the
|
|
5
|
+
* scope stack in effect there, teardown callbacks, a move-detection marker, and
|
|
6
|
+
* whether the element is a component root. Kept in a WeakMap so nothing leaks
|
|
7
|
+
* onto the DOM and everything is collected when a node is dropped.
|
|
8
|
+
*/
|
|
9
|
+
type Scope = Record<PropertyKey, unknown>;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Shared type contracts used across Summit's modules.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** A parsed Summit attribute, e.g. `s-on:click.prevent="go()"`. */
|
|
16
|
+
interface DirectiveMeta {
|
|
17
|
+
/** The directive name without the `s-` prefix, e.g. "on", "bind", "text". */
|
|
18
|
+
name: string;
|
|
19
|
+
/** The part after the colon, e.g. "click" in s-on:click. Null if absent. */
|
|
20
|
+
value: string | null;
|
|
21
|
+
/** Dot-separated modifiers, e.g. ["prevent", "stop"]. */
|
|
22
|
+
modifiers: string[];
|
|
23
|
+
/** The attribute's expression string (its value). */
|
|
24
|
+
expression: string;
|
|
25
|
+
/** The original attribute name as written in the DOM. */
|
|
26
|
+
raw: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Utilities handed to every directive. This is the directive author's API and
|
|
30
|
+
* intentionally mirrors what the built-ins use, so third-party directives are
|
|
31
|
+
* first-class.
|
|
32
|
+
*/
|
|
33
|
+
interface DirectiveUtils {
|
|
34
|
+
/** Evaluate a value expression in this element's scope. */
|
|
35
|
+
evaluate(expression: string): unknown;
|
|
36
|
+
/** Evaluate an action (statements) in this element's scope, with extra locals. */
|
|
37
|
+
evaluateAction(expression: string, locals?: Scope): unknown;
|
|
38
|
+
/** Create a batched reactive effect that is torn down with the element. */
|
|
39
|
+
effect(fn: () => void): void;
|
|
40
|
+
/** Register a teardown callback. */
|
|
41
|
+
cleanup(fn: () => void): void;
|
|
42
|
+
/** Initialize a subtree (used by structural directives). */
|
|
43
|
+
initTree(el: Element, scopes?: Scope[]): void;
|
|
44
|
+
/** Tear down a subtree. */
|
|
45
|
+
destroyTree(el: Element): void;
|
|
46
|
+
/** The scope stack visible at this element. */
|
|
47
|
+
scopes: Scope[];
|
|
48
|
+
/** Build a fresh RootEnv for an element, optionally with extra locals. */
|
|
49
|
+
makeEnv(el: Element, locals?: Scope): RootEnvLike;
|
|
50
|
+
/** The Summit global. */
|
|
51
|
+
Summit: SummitGlobalLike;
|
|
52
|
+
}
|
|
53
|
+
interface RootEnvLike {
|
|
54
|
+
has(name: string): boolean;
|
|
55
|
+
get(name: string): unknown;
|
|
56
|
+
set(name: string, value: unknown): void;
|
|
57
|
+
}
|
|
58
|
+
/** The context object passed to a magic factory. */
|
|
59
|
+
interface MagicContext {
|
|
60
|
+
el: Element;
|
|
61
|
+
scopes: Scope[];
|
|
62
|
+
evaluate(expression: string): unknown;
|
|
63
|
+
effect(fn: () => void): void;
|
|
64
|
+
cleanup(fn: () => void): void;
|
|
65
|
+
}
|
|
66
|
+
type DirectiveHandler = (el: Element, meta: DirectiveMeta, utils: DirectiveUtils) => void;
|
|
67
|
+
type MagicFactory = (ctx: MagicContext) => unknown;
|
|
68
|
+
type DataProvider = (...args: unknown[]) => Record<PropertyKey, unknown>;
|
|
69
|
+
type BindProvider = () => Record<string, unknown>;
|
|
70
|
+
/** A minimal shape of the Summit global for internal cross-references. */
|
|
71
|
+
interface SummitGlobalLike {
|
|
72
|
+
version: string;
|
|
73
|
+
store(name: string, value?: unknown): unknown;
|
|
74
|
+
[key: string]: unknown;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The registries.
|
|
79
|
+
*
|
|
80
|
+
* Everything pluggable in Summit lives here: directives, magics, reusable data
|
|
81
|
+
* providers, global stores, and reusable bind objects. Keeping these in a leaf
|
|
82
|
+
* module (no imports from the rest of Summit) means registration can happen at
|
|
83
|
+
* any time without import cycles, which is what makes Summit's registration
|
|
84
|
+
* timing-safe instead of Alpine's load-order-sensitive model.
|
|
85
|
+
*/
|
|
86
|
+
|
|
87
|
+
declare function getBind(name: string): BindProvider | undefined;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* initTree / destroyTree: the DOM engine.
|
|
91
|
+
*
|
|
92
|
+
* initTree walks an element and its descendants, establishing s-data scopes and
|
|
93
|
+
* running directives in priority order. Structural directives (s-if, s-for,
|
|
94
|
+
* s-teleport) take over their own subtree. destroyTree runs every teardown
|
|
95
|
+
* callback so effects stop, listeners detach, and component `destroy()` fires.
|
|
96
|
+
*/
|
|
97
|
+
|
|
98
|
+
declare function initTree(el: Element, scopesArg?: Scope[]): void;
|
|
99
|
+
declare function destroyTree(el: Element): void;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* A signal: a single reactive value with an explicit getter/setter.
|
|
103
|
+
*
|
|
104
|
+
* Reading the signal (calling it) subscribes the active effect. Writing it
|
|
105
|
+
* (`.set`) wakes every subscribed effect, but only if the value actually
|
|
106
|
+
* changed (`Object.is`). `.peek()` reads without subscribing.
|
|
107
|
+
*/
|
|
108
|
+
interface Signal<T> {
|
|
109
|
+
(): T;
|
|
110
|
+
set(next: T | ((prev: T) => T)): void;
|
|
111
|
+
peek(): T;
|
|
112
|
+
}
|
|
113
|
+
declare function signal<T>(initial: T): Signal<T>;
|
|
114
|
+
/** True if `x` is a signal produced by `signal()`. */
|
|
115
|
+
declare function isSignal<T = unknown>(x: unknown): x is Signal<T>;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* A computed value: a memoized, lazily-evaluated derivation.
|
|
119
|
+
*
|
|
120
|
+
* Unlike a plain getter (which Alpine re-runs on every read), a computed caches
|
|
121
|
+
* its result and only recomputes when one of its own dependencies changes. It
|
|
122
|
+
* stays lazy: the getter does not run until something reads the computed.
|
|
123
|
+
*/
|
|
124
|
+
interface Computed<T> {
|
|
125
|
+
(): T;
|
|
126
|
+
peek(): T;
|
|
127
|
+
}
|
|
128
|
+
declare function computed<T>(getter: () => T): Computed<T>;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Deep reactive objects.
|
|
132
|
+
*
|
|
133
|
+
* `reactive(obj)` returns a Proxy that tracks property reads and triggers on
|
|
134
|
+
* writes, so `this.open = true` inside a component method just works. Nested
|
|
135
|
+
* objects and arrays are wrapped lazily on access. This is what backs a
|
|
136
|
+
* component's `s-data` scope, giving Alpine-style ergonomics on top of
|
|
137
|
+
* Summit's fine-grained effect system.
|
|
138
|
+
*/
|
|
139
|
+
/** Wrap an object in a deep reactive proxy. Idempotent and cached per object. */
|
|
140
|
+
declare function reactive<T extends object>(target: T): T;
|
|
141
|
+
/** Unwrap a reactive proxy back to its plain object. Safe on non-proxies. */
|
|
142
|
+
declare function toRaw<T>(observed: T): T;
|
|
143
|
+
/** True if `x` is a reactive proxy. */
|
|
144
|
+
declare function isReactive(x: unknown): boolean;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* The reactive effect system.
|
|
148
|
+
*
|
|
149
|
+
* This is the heart of Summit. An `effect` is a function that automatically
|
|
150
|
+
* re-runs whenever any reactive value it read during its last run changes.
|
|
151
|
+
* Dependency tracking is fine-grained: a `dep` is a set of effects that
|
|
152
|
+
* depend on one specific value, so a change only wakes the effects that
|
|
153
|
+
* actually read that value. Nothing else re-runs.
|
|
154
|
+
*/
|
|
155
|
+
type Dep = Set<ReactiveEffect>;
|
|
156
|
+
interface EffectOptions {
|
|
157
|
+
/** Skip the initial run. The effect only runs when its scheduler fires. */
|
|
158
|
+
lazy?: boolean;
|
|
159
|
+
/** Called instead of re-running the effect directly when a dep changes. */
|
|
160
|
+
scheduler?: () => void;
|
|
161
|
+
/** Called when the effect is stopped. */
|
|
162
|
+
onStop?: () => void;
|
|
163
|
+
}
|
|
164
|
+
interface ReactiveEffect {
|
|
165
|
+
(): void;
|
|
166
|
+
/** The deps this effect is currently subscribed to. */
|
|
167
|
+
deps: Dep[];
|
|
168
|
+
/** Whether the effect is still live. Stopped effects never re-run. */
|
|
169
|
+
active: boolean;
|
|
170
|
+
scheduler?: () => void;
|
|
171
|
+
onStop?: () => void;
|
|
172
|
+
/** The user function this effect wraps. */
|
|
173
|
+
raw: () => unknown;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Create a reactive effect. Runs immediately unless `lazy` is set. Returns a
|
|
177
|
+
* runner you can call manually or hand to `stop()`.
|
|
178
|
+
*/
|
|
179
|
+
declare function effect(fn: () => unknown, options?: EffectOptions): ReactiveEffect;
|
|
180
|
+
/** Permanently stop an effect and unsubscribe it from every dep. */
|
|
181
|
+
declare function stop(runner: ReactiveEffect): void;
|
|
182
|
+
/** Run `fn` without subscribing the active effect to anything read inside it. */
|
|
183
|
+
declare function untrack<T>(fn: () => T): T;
|
|
184
|
+
/**
|
|
185
|
+
* Group multiple writes so dependent effects run once at the end instead of
|
|
186
|
+
* after each write. Batches nest; only the outermost flush runs effects.
|
|
187
|
+
*/
|
|
188
|
+
declare function batch<T>(fn: () => T): T;
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Resolve after the current flush completes. With a callback, runs it after the
|
|
192
|
+
* flush; without one, returns a promise you can await.
|
|
193
|
+
*/
|
|
194
|
+
declare function nextTick(callback?: () => void): Promise<void>;
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* The Summit global.
|
|
198
|
+
*
|
|
199
|
+
* This is the object users interact with: register data, directives, magics,
|
|
200
|
+
* stores, and plugins, then start. Registration is timing-safe. Built-ins are
|
|
201
|
+
* registered at import, custom registrations override them, and start() can be
|
|
202
|
+
* called whenever the DOM is ready. There is no load-order event to miss.
|
|
203
|
+
*/
|
|
204
|
+
|
|
205
|
+
declare const version = "0.1.0";
|
|
206
|
+
interface SummitGlobal {
|
|
207
|
+
version: string;
|
|
208
|
+
started: () => boolean;
|
|
209
|
+
start(root?: Element): void;
|
|
210
|
+
data(name: string, provider: DataProvider): SummitGlobal;
|
|
211
|
+
directive(name: string, handler: DirectiveHandler, priority?: number): SummitGlobal;
|
|
212
|
+
magic(name: string, factory: MagicFactory): SummitGlobal;
|
|
213
|
+
bind(name: string, provider: BindProvider): SummitGlobal;
|
|
214
|
+
store(name: string, value?: unknown): unknown;
|
|
215
|
+
plugin(fn: (summit: SummitGlobal) => void): SummitGlobal;
|
|
216
|
+
addGlobals(names: string[]): SummitGlobal;
|
|
217
|
+
getBind: typeof getBind;
|
|
218
|
+
signal: typeof signal;
|
|
219
|
+
computed: typeof computed;
|
|
220
|
+
effect: typeof effect;
|
|
221
|
+
reactive: typeof reactive;
|
|
222
|
+
batch: typeof batch;
|
|
223
|
+
nextTick: typeof nextTick;
|
|
224
|
+
initTree: typeof initTree;
|
|
225
|
+
destroyTree: typeof destroyTree;
|
|
226
|
+
}
|
|
227
|
+
declare const Summit: SummitGlobal;
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* The interpreter walks an AST and produces a value. It never calls `eval` or
|
|
231
|
+
* `new Function`, so a strict `script-src` CSP with no `unsafe-eval` is fully
|
|
232
|
+
* satisfied. Identifiers resolve first against interpreter-local bindings
|
|
233
|
+
* (arrow params, let/const), then the component data scope (the RootEnv), then
|
|
234
|
+
* a small allowlist of safe globals.
|
|
235
|
+
*/
|
|
236
|
+
|
|
237
|
+
/** The component-level environment: the merged s-data stack plus magics. */
|
|
238
|
+
interface RootEnv {
|
|
239
|
+
has(name: string): boolean;
|
|
240
|
+
get(name: string): unknown;
|
|
241
|
+
set(name: string, value: unknown): void;
|
|
242
|
+
}
|
|
243
|
+
/** Add names to the global allowlist that expressions may access. */
|
|
244
|
+
declare function addGlobals(names: string[]): void;
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Public evaluator API.
|
|
248
|
+
*
|
|
249
|
+
* `evaluateExpression` runs a value expression (s-data, s-text, :bind, s-show).
|
|
250
|
+
* `evaluateAction` runs a statement list (s-on handlers, s-init). Both parse to
|
|
251
|
+
* a cached AST and interpret it with no `eval` / `new Function`, so Summit runs
|
|
252
|
+
* under a strict Content-Security-Policy out of the box.
|
|
253
|
+
*/
|
|
254
|
+
|
|
255
|
+
/** Evaluate a value expression against a component environment. */
|
|
256
|
+
declare function evaluateExpression(source: string, root: RootEnv, thisVal?: unknown): unknown;
|
|
257
|
+
/** Evaluate an action (one or more statements) against a component environment. */
|
|
258
|
+
declare function evaluateAction(source: string, root: RootEnv, thisVal?: unknown): unknown;
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Summit: a rugged, signal-powered framework for composing behavior directly
|
|
262
|
+
* in your HTML. This is the package entry for bundler/npm users. Import the
|
|
263
|
+
* default `Summit` global, register anything you like, then call `Summit.start()`.
|
|
264
|
+
*
|
|
265
|
+
* For a zero-build drop-in, use the CDN build (dist/summit.min.js), which
|
|
266
|
+
* attaches `window.Summit` and starts automatically.
|
|
267
|
+
*/
|
|
268
|
+
|
|
269
|
+
export { type BindProvider, type Computed, type DataProvider, type DirectiveHandler, type DirectiveMeta, type DirectiveUtils, type MagicContext, type MagicFactory, type Signal, Summit, type SummitGlobal, addGlobals, batch, computed, Summit as default, effect, evaluateAction, evaluateExpression, isReactive, isSignal, nextTick, reactive, signal, stop, toRaw, untrack, version };
|
package/dist/summit.d.ts
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-element bookkeeping.
|
|
3
|
+
*
|
|
4
|
+
* Summit attaches a small metadata record to every element it touches: the
|
|
5
|
+
* scope stack in effect there, teardown callbacks, a move-detection marker, and
|
|
6
|
+
* whether the element is a component root. Kept in a WeakMap so nothing leaks
|
|
7
|
+
* onto the DOM and everything is collected when a node is dropped.
|
|
8
|
+
*/
|
|
9
|
+
type Scope = Record<PropertyKey, unknown>;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Shared type contracts used across Summit's modules.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** A parsed Summit attribute, e.g. `s-on:click.prevent="go()"`. */
|
|
16
|
+
interface DirectiveMeta {
|
|
17
|
+
/** The directive name without the `s-` prefix, e.g. "on", "bind", "text". */
|
|
18
|
+
name: string;
|
|
19
|
+
/** The part after the colon, e.g. "click" in s-on:click. Null if absent. */
|
|
20
|
+
value: string | null;
|
|
21
|
+
/** Dot-separated modifiers, e.g. ["prevent", "stop"]. */
|
|
22
|
+
modifiers: string[];
|
|
23
|
+
/** The attribute's expression string (its value). */
|
|
24
|
+
expression: string;
|
|
25
|
+
/** The original attribute name as written in the DOM. */
|
|
26
|
+
raw: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Utilities handed to every directive. This is the directive author's API and
|
|
30
|
+
* intentionally mirrors what the built-ins use, so third-party directives are
|
|
31
|
+
* first-class.
|
|
32
|
+
*/
|
|
33
|
+
interface DirectiveUtils {
|
|
34
|
+
/** Evaluate a value expression in this element's scope. */
|
|
35
|
+
evaluate(expression: string): unknown;
|
|
36
|
+
/** Evaluate an action (statements) in this element's scope, with extra locals. */
|
|
37
|
+
evaluateAction(expression: string, locals?: Scope): unknown;
|
|
38
|
+
/** Create a batched reactive effect that is torn down with the element. */
|
|
39
|
+
effect(fn: () => void): void;
|
|
40
|
+
/** Register a teardown callback. */
|
|
41
|
+
cleanup(fn: () => void): void;
|
|
42
|
+
/** Initialize a subtree (used by structural directives). */
|
|
43
|
+
initTree(el: Element, scopes?: Scope[]): void;
|
|
44
|
+
/** Tear down a subtree. */
|
|
45
|
+
destroyTree(el: Element): void;
|
|
46
|
+
/** The scope stack visible at this element. */
|
|
47
|
+
scopes: Scope[];
|
|
48
|
+
/** Build a fresh RootEnv for an element, optionally with extra locals. */
|
|
49
|
+
makeEnv(el: Element, locals?: Scope): RootEnvLike;
|
|
50
|
+
/** The Summit global. */
|
|
51
|
+
Summit: SummitGlobalLike;
|
|
52
|
+
}
|
|
53
|
+
interface RootEnvLike {
|
|
54
|
+
has(name: string): boolean;
|
|
55
|
+
get(name: string): unknown;
|
|
56
|
+
set(name: string, value: unknown): void;
|
|
57
|
+
}
|
|
58
|
+
/** The context object passed to a magic factory. */
|
|
59
|
+
interface MagicContext {
|
|
60
|
+
el: Element;
|
|
61
|
+
scopes: Scope[];
|
|
62
|
+
evaluate(expression: string): unknown;
|
|
63
|
+
effect(fn: () => void): void;
|
|
64
|
+
cleanup(fn: () => void): void;
|
|
65
|
+
}
|
|
66
|
+
type DirectiveHandler = (el: Element, meta: DirectiveMeta, utils: DirectiveUtils) => void;
|
|
67
|
+
type MagicFactory = (ctx: MagicContext) => unknown;
|
|
68
|
+
type DataProvider = (...args: unknown[]) => Record<PropertyKey, unknown>;
|
|
69
|
+
type BindProvider = () => Record<string, unknown>;
|
|
70
|
+
/** A minimal shape of the Summit global for internal cross-references. */
|
|
71
|
+
interface SummitGlobalLike {
|
|
72
|
+
version: string;
|
|
73
|
+
store(name: string, value?: unknown): unknown;
|
|
74
|
+
[key: string]: unknown;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The registries.
|
|
79
|
+
*
|
|
80
|
+
* Everything pluggable in Summit lives here: directives, magics, reusable data
|
|
81
|
+
* providers, global stores, and reusable bind objects. Keeping these in a leaf
|
|
82
|
+
* module (no imports from the rest of Summit) means registration can happen at
|
|
83
|
+
* any time without import cycles, which is what makes Summit's registration
|
|
84
|
+
* timing-safe instead of Alpine's load-order-sensitive model.
|
|
85
|
+
*/
|
|
86
|
+
|
|
87
|
+
declare function getBind(name: string): BindProvider | undefined;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* initTree / destroyTree: the DOM engine.
|
|
91
|
+
*
|
|
92
|
+
* initTree walks an element and its descendants, establishing s-data scopes and
|
|
93
|
+
* running directives in priority order. Structural directives (s-if, s-for,
|
|
94
|
+
* s-teleport) take over their own subtree. destroyTree runs every teardown
|
|
95
|
+
* callback so effects stop, listeners detach, and component `destroy()` fires.
|
|
96
|
+
*/
|
|
97
|
+
|
|
98
|
+
declare function initTree(el: Element, scopesArg?: Scope[]): void;
|
|
99
|
+
declare function destroyTree(el: Element): void;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* A signal: a single reactive value with an explicit getter/setter.
|
|
103
|
+
*
|
|
104
|
+
* Reading the signal (calling it) subscribes the active effect. Writing it
|
|
105
|
+
* (`.set`) wakes every subscribed effect, but only if the value actually
|
|
106
|
+
* changed (`Object.is`). `.peek()` reads without subscribing.
|
|
107
|
+
*/
|
|
108
|
+
interface Signal<T> {
|
|
109
|
+
(): T;
|
|
110
|
+
set(next: T | ((prev: T) => T)): void;
|
|
111
|
+
peek(): T;
|
|
112
|
+
}
|
|
113
|
+
declare function signal<T>(initial: T): Signal<T>;
|
|
114
|
+
/** True if `x` is a signal produced by `signal()`. */
|
|
115
|
+
declare function isSignal<T = unknown>(x: unknown): x is Signal<T>;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* A computed value: a memoized, lazily-evaluated derivation.
|
|
119
|
+
*
|
|
120
|
+
* Unlike a plain getter (which Alpine re-runs on every read), a computed caches
|
|
121
|
+
* its result and only recomputes when one of its own dependencies changes. It
|
|
122
|
+
* stays lazy: the getter does not run until something reads the computed.
|
|
123
|
+
*/
|
|
124
|
+
interface Computed<T> {
|
|
125
|
+
(): T;
|
|
126
|
+
peek(): T;
|
|
127
|
+
}
|
|
128
|
+
declare function computed<T>(getter: () => T): Computed<T>;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Deep reactive objects.
|
|
132
|
+
*
|
|
133
|
+
* `reactive(obj)` returns a Proxy that tracks property reads and triggers on
|
|
134
|
+
* writes, so `this.open = true` inside a component method just works. Nested
|
|
135
|
+
* objects and arrays are wrapped lazily on access. This is what backs a
|
|
136
|
+
* component's `s-data` scope, giving Alpine-style ergonomics on top of
|
|
137
|
+
* Summit's fine-grained effect system.
|
|
138
|
+
*/
|
|
139
|
+
/** Wrap an object in a deep reactive proxy. Idempotent and cached per object. */
|
|
140
|
+
declare function reactive<T extends object>(target: T): T;
|
|
141
|
+
/** Unwrap a reactive proxy back to its plain object. Safe on non-proxies. */
|
|
142
|
+
declare function toRaw<T>(observed: T): T;
|
|
143
|
+
/** True if `x` is a reactive proxy. */
|
|
144
|
+
declare function isReactive(x: unknown): boolean;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* The reactive effect system.
|
|
148
|
+
*
|
|
149
|
+
* This is the heart of Summit. An `effect` is a function that automatically
|
|
150
|
+
* re-runs whenever any reactive value it read during its last run changes.
|
|
151
|
+
* Dependency tracking is fine-grained: a `dep` is a set of effects that
|
|
152
|
+
* depend on one specific value, so a change only wakes the effects that
|
|
153
|
+
* actually read that value. Nothing else re-runs.
|
|
154
|
+
*/
|
|
155
|
+
type Dep = Set<ReactiveEffect>;
|
|
156
|
+
interface EffectOptions {
|
|
157
|
+
/** Skip the initial run. The effect only runs when its scheduler fires. */
|
|
158
|
+
lazy?: boolean;
|
|
159
|
+
/** Called instead of re-running the effect directly when a dep changes. */
|
|
160
|
+
scheduler?: () => void;
|
|
161
|
+
/** Called when the effect is stopped. */
|
|
162
|
+
onStop?: () => void;
|
|
163
|
+
}
|
|
164
|
+
interface ReactiveEffect {
|
|
165
|
+
(): void;
|
|
166
|
+
/** The deps this effect is currently subscribed to. */
|
|
167
|
+
deps: Dep[];
|
|
168
|
+
/** Whether the effect is still live. Stopped effects never re-run. */
|
|
169
|
+
active: boolean;
|
|
170
|
+
scheduler?: () => void;
|
|
171
|
+
onStop?: () => void;
|
|
172
|
+
/** The user function this effect wraps. */
|
|
173
|
+
raw: () => unknown;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Create a reactive effect. Runs immediately unless `lazy` is set. Returns a
|
|
177
|
+
* runner you can call manually or hand to `stop()`.
|
|
178
|
+
*/
|
|
179
|
+
declare function effect(fn: () => unknown, options?: EffectOptions): ReactiveEffect;
|
|
180
|
+
/** Permanently stop an effect and unsubscribe it from every dep. */
|
|
181
|
+
declare function stop(runner: ReactiveEffect): void;
|
|
182
|
+
/** Run `fn` without subscribing the active effect to anything read inside it. */
|
|
183
|
+
declare function untrack<T>(fn: () => T): T;
|
|
184
|
+
/**
|
|
185
|
+
* Group multiple writes so dependent effects run once at the end instead of
|
|
186
|
+
* after each write. Batches nest; only the outermost flush runs effects.
|
|
187
|
+
*/
|
|
188
|
+
declare function batch<T>(fn: () => T): T;
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Resolve after the current flush completes. With a callback, runs it after the
|
|
192
|
+
* flush; without one, returns a promise you can await.
|
|
193
|
+
*/
|
|
194
|
+
declare function nextTick(callback?: () => void): Promise<void>;
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* The Summit global.
|
|
198
|
+
*
|
|
199
|
+
* This is the object users interact with: register data, directives, magics,
|
|
200
|
+
* stores, and plugins, then start. Registration is timing-safe. Built-ins are
|
|
201
|
+
* registered at import, custom registrations override them, and start() can be
|
|
202
|
+
* called whenever the DOM is ready. There is no load-order event to miss.
|
|
203
|
+
*/
|
|
204
|
+
|
|
205
|
+
declare const version = "0.1.0";
|
|
206
|
+
interface SummitGlobal {
|
|
207
|
+
version: string;
|
|
208
|
+
started: () => boolean;
|
|
209
|
+
start(root?: Element): void;
|
|
210
|
+
data(name: string, provider: DataProvider): SummitGlobal;
|
|
211
|
+
directive(name: string, handler: DirectiveHandler, priority?: number): SummitGlobal;
|
|
212
|
+
magic(name: string, factory: MagicFactory): SummitGlobal;
|
|
213
|
+
bind(name: string, provider: BindProvider): SummitGlobal;
|
|
214
|
+
store(name: string, value?: unknown): unknown;
|
|
215
|
+
plugin(fn: (summit: SummitGlobal) => void): SummitGlobal;
|
|
216
|
+
addGlobals(names: string[]): SummitGlobal;
|
|
217
|
+
getBind: typeof getBind;
|
|
218
|
+
signal: typeof signal;
|
|
219
|
+
computed: typeof computed;
|
|
220
|
+
effect: typeof effect;
|
|
221
|
+
reactive: typeof reactive;
|
|
222
|
+
batch: typeof batch;
|
|
223
|
+
nextTick: typeof nextTick;
|
|
224
|
+
initTree: typeof initTree;
|
|
225
|
+
destroyTree: typeof destroyTree;
|
|
226
|
+
}
|
|
227
|
+
declare const Summit: SummitGlobal;
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* The interpreter walks an AST and produces a value. It never calls `eval` or
|
|
231
|
+
* `new Function`, so a strict `script-src` CSP with no `unsafe-eval` is fully
|
|
232
|
+
* satisfied. Identifiers resolve first against interpreter-local bindings
|
|
233
|
+
* (arrow params, let/const), then the component data scope (the RootEnv), then
|
|
234
|
+
* a small allowlist of safe globals.
|
|
235
|
+
*/
|
|
236
|
+
|
|
237
|
+
/** The component-level environment: the merged s-data stack plus magics. */
|
|
238
|
+
interface RootEnv {
|
|
239
|
+
has(name: string): boolean;
|
|
240
|
+
get(name: string): unknown;
|
|
241
|
+
set(name: string, value: unknown): void;
|
|
242
|
+
}
|
|
243
|
+
/** Add names to the global allowlist that expressions may access. */
|
|
244
|
+
declare function addGlobals(names: string[]): void;
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Public evaluator API.
|
|
248
|
+
*
|
|
249
|
+
* `evaluateExpression` runs a value expression (s-data, s-text, :bind, s-show).
|
|
250
|
+
* `evaluateAction` runs a statement list (s-on handlers, s-init). Both parse to
|
|
251
|
+
* a cached AST and interpret it with no `eval` / `new Function`, so Summit runs
|
|
252
|
+
* under a strict Content-Security-Policy out of the box.
|
|
253
|
+
*/
|
|
254
|
+
|
|
255
|
+
/** Evaluate a value expression against a component environment. */
|
|
256
|
+
declare function evaluateExpression(source: string, root: RootEnv, thisVal?: unknown): unknown;
|
|
257
|
+
/** Evaluate an action (one or more statements) against a component environment. */
|
|
258
|
+
declare function evaluateAction(source: string, root: RootEnv, thisVal?: unknown): unknown;
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Summit: a rugged, signal-powered framework for composing behavior directly
|
|
262
|
+
* in your HTML. This is the package entry for bundler/npm users. Import the
|
|
263
|
+
* default `Summit` global, register anything you like, then call `Summit.start()`.
|
|
264
|
+
*
|
|
265
|
+
* For a zero-build drop-in, use the CDN build (dist/summit.min.js), which
|
|
266
|
+
* attaches `window.Summit` and starts automatically.
|
|
267
|
+
*/
|
|
268
|
+
|
|
269
|
+
export { type BindProvider, type Computed, type DataProvider, type DirectiveHandler, type DirectiveMeta, type DirectiveUtils, type MagicContext, type MagicFactory, type Signal, Summit, type SummitGlobal, addGlobals, batch, computed, Summit as default, effect, evaluateAction, evaluateExpression, isReactive, isSignal, nextTick, reactive, signal, stop, toRaw, untrack, version };
|