@expressive/dom 0.2.0 → 0.3.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 +1 -1
- package/dist/chunk-hot-BAqPvKEQ.js +331 -0
- package/dist/chunk-hot-BAqPvKEQ.js.map +1 -0
- package/dist/chunk-loader-kjuM318E.d.ts +58 -0
- package/dist/{chunk-vnode-CzmFSz5_.js → chunk-vnode-BG1Cv8F9.js} +11 -8
- package/dist/chunk-vnode-BG1Cv8F9.js.map +1 -0
- package/dist/index.d.ts +3 -31
- package/dist/index.js +178 -326
- package/dist/index.js.map +1 -1
- package/dist/jsx-dev-runtime.d.ts +2 -3
- package/dist/jsx-dev-runtime.js +3 -3
- package/dist/jsx-dev-runtime.js.map +1 -1
- package/dist/jsx-runtime.d.ts +44 -5
- package/dist/jsx-runtime.js +2 -2
- package/dist/jsx-runtime.js.map +1 -1
- package/dist/vite.js +43 -30
- package/dist/vite.js.map +1 -1
- package/package.json +5 -3
- package/dist/chunk-hot-gq8TyYJV.js +0 -178
- package/dist/chunk-hot-gq8TyYJV.js.map +0 -1
- package/dist/chunk-vnode-BsbDCqd1.d.ts +0 -25
- package/dist/chunk-vnode-CzmFSz5_.js.map +0 -1
package/README.md
CHANGED
|
@@ -70,7 +70,7 @@ Inline style always beats classes; among classes, a caller's rule beats the call
|
|
|
70
70
|
|
|
71
71
|
`Component` retains the React adapter's model: fields read by `render()` are dependencies, owned instances mount and clean up with the DOM range, and an externally activated instance can be placed directly without transferring ownership.
|
|
72
72
|
|
|
73
|
-
The first release includes keyed reconciliation, native events, refs, SVG,
|
|
73
|
+
The first release includes keyed reconciliation, native events, refs, SVG, `<Component for>` providers, direct `has` / `map` collection rendering, portals, lazy components, error and suspense fallbacks, generated component appearance rules, and retention of committed content while `pending()` work suspends. It deliberately excludes standalone hooks, synthetic events, memo wrappers, SSR, hydration, and build-time style extraction.
|
|
74
74
|
|
|
75
75
|
See [the DOM renderer guide](../../skills/dom/dom.md) for the API and constraints. This package currently targets browser DOM; native rendering and build-time expressive-jsx extraction are not included.
|
|
76
76
|
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
import { Component, State, pending, unbind } from "@expressive/mvc";
|
|
2
|
+
import { watch } from "@expressive/mvc/observable";
|
|
3
|
+
|
|
4
|
+
//#region src/scheduler.ts
|
|
5
|
+
const urgent = /* @__PURE__ */ new Set();
|
|
6
|
+
const passive = /* @__PURE__ */ new Set();
|
|
7
|
+
const after = [];
|
|
8
|
+
let depth = 0;
|
|
9
|
+
let urgentQueued = false;
|
|
10
|
+
let passiveQueued = false;
|
|
11
|
+
function flush(scopes) {
|
|
12
|
+
for (const scope of scopes) {
|
|
13
|
+
scopes.delete(scope);
|
|
14
|
+
scope.queued = void 0;
|
|
15
|
+
let waiting = void 0;
|
|
16
|
+
try {
|
|
17
|
+
waiting = scope.update(false);
|
|
18
|
+
} catch (error) {
|
|
19
|
+
console.error(error);
|
|
20
|
+
}
|
|
21
|
+
settle(scope);
|
|
22
|
+
if (!waiting) unblock(scope);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function flushUrgent() {
|
|
26
|
+
urgentQueued = false;
|
|
27
|
+
flush(urgent);
|
|
28
|
+
for (const run of after.splice(0)) run();
|
|
29
|
+
}
|
|
30
|
+
function afterFlush(run) {
|
|
31
|
+
after.push(run);
|
|
32
|
+
if (!urgentQueued) {
|
|
33
|
+
urgentQueued = true;
|
|
34
|
+
queueMicrotask(flushUrgent);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function flushPassive() {
|
|
38
|
+
passiveQueued = false;
|
|
39
|
+
const batch = [...passive].filter((scope) => scope.queued === "passive");
|
|
40
|
+
passive.clear();
|
|
41
|
+
for (const scope of batch) {
|
|
42
|
+
const waiting = scope.probe?.();
|
|
43
|
+
if (waiting) return defer(batch, waiting, scope);
|
|
44
|
+
}
|
|
45
|
+
batch.sort((a, b) => Number(!!b.empty?.()) - Number(!!a.empty?.()));
|
|
46
|
+
for (let index = 0; index < batch.length; index++) {
|
|
47
|
+
const scope = batch[index];
|
|
48
|
+
if (scope.queued !== "passive") continue;
|
|
49
|
+
scope.queued = void 0;
|
|
50
|
+
let waiting = void 0;
|
|
51
|
+
try {
|
|
52
|
+
waiting = scope.update(true);
|
|
53
|
+
} catch (error) {
|
|
54
|
+
console.error(error);
|
|
55
|
+
}
|
|
56
|
+
settle(scope);
|
|
57
|
+
if (waiting) return defer(batch.slice(index + 1), waiting, scope);
|
|
58
|
+
unblock(scope);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function defer(scopes, waiting, source) {
|
|
62
|
+
const held = scopes.filter((scope) => scope.queued === "passive");
|
|
63
|
+
for (const scope of held) {
|
|
64
|
+
scope.queued = "deferred";
|
|
65
|
+
scope.probed = void 0;
|
|
66
|
+
}
|
|
67
|
+
const resume = () => {
|
|
68
|
+
for (const scope of held) if (scope.queued === "deferred") {
|
|
69
|
+
scope.queued = void 0;
|
|
70
|
+
transition(() => schedule(scope));
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
(source.blocking ||= []).push(resume);
|
|
74
|
+
waiting.then(resume, resume);
|
|
75
|
+
}
|
|
76
|
+
function unblock(scope) {
|
|
77
|
+
const { blocking } = scope;
|
|
78
|
+
scope.blocking = void 0;
|
|
79
|
+
blocking?.forEach((resume) => resume());
|
|
80
|
+
}
|
|
81
|
+
function release(holds) {
|
|
82
|
+
holds?.forEach((held) => held());
|
|
83
|
+
}
|
|
84
|
+
function settle(scope) {
|
|
85
|
+
const { holds } = scope;
|
|
86
|
+
scope.holds = void 0;
|
|
87
|
+
release(holds);
|
|
88
|
+
}
|
|
89
|
+
function schedule(scope) {
|
|
90
|
+
const held = pending();
|
|
91
|
+
if (held) (scope.holds ||= []).push(held);
|
|
92
|
+
scope.probed = void 0;
|
|
93
|
+
if (!depth) {
|
|
94
|
+
passive.delete(scope);
|
|
95
|
+
scope.queued = "urgent";
|
|
96
|
+
urgent.add(scope);
|
|
97
|
+
if (!urgentQueued) {
|
|
98
|
+
urgentQueued = true;
|
|
99
|
+
queueMicrotask(flushUrgent);
|
|
100
|
+
}
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (scope.queued && scope.queued !== "deferred") return;
|
|
104
|
+
scope.queued = "passive";
|
|
105
|
+
passive.add(scope);
|
|
106
|
+
if (!passiveQueued) {
|
|
107
|
+
passiveQueued = true;
|
|
108
|
+
setTimeout(flushPassive);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function transition(work) {
|
|
112
|
+
depth++;
|
|
113
|
+
try {
|
|
114
|
+
work();
|
|
115
|
+
} finally {
|
|
116
|
+
depth--;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function claim(scope) {
|
|
120
|
+
urgent.delete(scope);
|
|
121
|
+
passive.delete(scope);
|
|
122
|
+
scope.queued = void 0;
|
|
123
|
+
scope.probed = void 0;
|
|
124
|
+
}
|
|
125
|
+
function unschedule(scope) {
|
|
126
|
+
urgent.delete(scope);
|
|
127
|
+
passive.delete(scope);
|
|
128
|
+
scope.queued = void 0;
|
|
129
|
+
scope.probed = void 0;
|
|
130
|
+
settle(scope);
|
|
131
|
+
unblock(scope);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
//#endregion
|
|
135
|
+
//#region src/adapter.ts
|
|
136
|
+
let current;
|
|
137
|
+
let collecting;
|
|
138
|
+
function enter(scope, render) {
|
|
139
|
+
const parent = current;
|
|
140
|
+
const releases = collecting;
|
|
141
|
+
const next = [];
|
|
142
|
+
current = scope;
|
|
143
|
+
collecting = next;
|
|
144
|
+
scope.childContext = scope.context;
|
|
145
|
+
scope.useIndex = 0;
|
|
146
|
+
try {
|
|
147
|
+
const output = render();
|
|
148
|
+
if (scope.kind == "function" && scope.useIndex !== scope.uses.length) {
|
|
149
|
+
if (!scope.hot) throw new Error("State.use() calls must keep the same order on every function-component render.");
|
|
150
|
+
truncate(scope, scope.useIndex);
|
|
151
|
+
}
|
|
152
|
+
return output;
|
|
153
|
+
} finally {
|
|
154
|
+
scope.hot = void 0;
|
|
155
|
+
current = parent;
|
|
156
|
+
collecting = releases;
|
|
157
|
+
scope.subscriptions.forEach((release) => release());
|
|
158
|
+
scope.subscriptions = next;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
function dispose(scope) {
|
|
162
|
+
scope.active = false;
|
|
163
|
+
unschedule(scope);
|
|
164
|
+
scope.subscriptions.forEach((release) => release());
|
|
165
|
+
scope.subscriptions = [];
|
|
166
|
+
truncate(scope, 0);
|
|
167
|
+
}
|
|
168
|
+
/** Destroy the `State.use()` slots of a scope from `index` on. */
|
|
169
|
+
function truncate(scope, index) {
|
|
170
|
+
for (let i = scope.uses.length - 1; i >= index; i--) {
|
|
171
|
+
const slot = scope.uses[i];
|
|
172
|
+
slot.release();
|
|
173
|
+
if (typeof slot.cleanup == "function") slot.cleanup();
|
|
174
|
+
slot.context.pop();
|
|
175
|
+
slot.instance.set(null);
|
|
176
|
+
}
|
|
177
|
+
scope.uses.length = index;
|
|
178
|
+
}
|
|
179
|
+
function commit(scope) {
|
|
180
|
+
for (const slot of scope.uses) if (!slot.mounted) {
|
|
181
|
+
slot.mounted = true;
|
|
182
|
+
slot.cleanup = slot.instance.mount?.();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function requireScope() {
|
|
186
|
+
if (!current) throw new Error("State.get() and State.use() may only run while @expressive/dom is rendering.");
|
|
187
|
+
return current;
|
|
188
|
+
}
|
|
189
|
+
function tracked(target, required) {
|
|
190
|
+
const scope = requireScope();
|
|
191
|
+
let proxy = target;
|
|
192
|
+
let first = true;
|
|
193
|
+
const release = watch(target, (next) => {
|
|
194
|
+
proxy = next;
|
|
195
|
+
if (!first && scope.active) schedule(scope);
|
|
196
|
+
first = false;
|
|
197
|
+
}, required, transition);
|
|
198
|
+
collecting.push(release);
|
|
199
|
+
return proxy;
|
|
200
|
+
}
|
|
201
|
+
State.get = function get(argument) {
|
|
202
|
+
const scope = requireScope();
|
|
203
|
+
const instance = scope.childContext.get(this, argument === false ? false : true);
|
|
204
|
+
if (!instance) return void 0;
|
|
205
|
+
const proxy = tracked(instance, argument === true);
|
|
206
|
+
if (typeof argument != "function") return proxy;
|
|
207
|
+
const refresh = ((action) => {
|
|
208
|
+
if (typeof action == "function") action = action();
|
|
209
|
+
schedule(scope);
|
|
210
|
+
return action instanceof Promise ? action.finally(() => schedule(scope)) : void 0;
|
|
211
|
+
});
|
|
212
|
+
return argument.call(proxy, proxy, refresh) ?? null;
|
|
213
|
+
};
|
|
214
|
+
State.use = function use(...args) {
|
|
215
|
+
const scope = requireScope();
|
|
216
|
+
if (scope.kind != "function") throw new Error("State.use() is only available at the top level of a function component.");
|
|
217
|
+
const index = scope.useIndex++;
|
|
218
|
+
let slot = scope.uses[index];
|
|
219
|
+
if (slot && slot.Type !== this) {
|
|
220
|
+
if (!scope.hot) throw new Error("State.use() calls must keep the same order on every function-component render.");
|
|
221
|
+
truncate(scope, index);
|
|
222
|
+
slot = void 0;
|
|
223
|
+
}
|
|
224
|
+
if (!slot) {
|
|
225
|
+
let instance;
|
|
226
|
+
const assign = (value) => typeof value == "object" && value && instance.set(value);
|
|
227
|
+
let apply = (...values) => Promise.all(values.flat().map(assign));
|
|
228
|
+
instance = new this((self) => {
|
|
229
|
+
const own = self;
|
|
230
|
+
if (typeof own.use == "function") {
|
|
231
|
+
apply = own.use.bind(own);
|
|
232
|
+
apply(...args);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
return args;
|
|
236
|
+
});
|
|
237
|
+
const context = scope.childContext.push(instance);
|
|
238
|
+
slot = {
|
|
239
|
+
Type: this,
|
|
240
|
+
context,
|
|
241
|
+
instance,
|
|
242
|
+
proxy: instance,
|
|
243
|
+
release: void 0,
|
|
244
|
+
apply
|
|
245
|
+
};
|
|
246
|
+
let first = true;
|
|
247
|
+
slot.release = watch(instance, (proxy) => {
|
|
248
|
+
slot.proxy = proxy;
|
|
249
|
+
if (!first && scope.active) schedule(scope);
|
|
250
|
+
first = false;
|
|
251
|
+
}, void 0, transition);
|
|
252
|
+
slot.apply = apply;
|
|
253
|
+
scope.uses.push(slot);
|
|
254
|
+
} else slot.apply(...args);
|
|
255
|
+
scope.childContext = slot.context;
|
|
256
|
+
return slot.proxy;
|
|
257
|
+
};
|
|
258
|
+
Object.defineProperty(Component, "use", {
|
|
259
|
+
configurable: true,
|
|
260
|
+
value() {
|
|
261
|
+
throw new Error(`${this} is a Component - render it instead of calling use().`);
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
const OWNERS = /* @__PURE__ */ new WeakMap();
|
|
265
|
+
State.on({ method(key, fn, owner) {
|
|
266
|
+
if (/^[A-Z]/.test(key)) OWNERS.set(fn, {
|
|
267
|
+
owner,
|
|
268
|
+
key
|
|
269
|
+
});
|
|
270
|
+
} });
|
|
271
|
+
function call(type, props) {
|
|
272
|
+
const sub = OWNERS.get(type);
|
|
273
|
+
if (!sub) return type(props);
|
|
274
|
+
const { owner, key } = sub;
|
|
275
|
+
return unbind(owner[key]).call(tracked(owner), props);
|
|
276
|
+
}
|
|
277
|
+
function owner(type) {
|
|
278
|
+
return typeof type == "function" ? OWNERS.get(type) : void 0;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
//#endregion
|
|
282
|
+
//#region src/hot.ts
|
|
283
|
+
const FAMILIES = /* @__PURE__ */ new Map();
|
|
284
|
+
const FAMILY = /* @__PURE__ */ new WeakMap();
|
|
285
|
+
/** The latest implementation of a component registered for hot refresh. */
|
|
286
|
+
function latest(type) {
|
|
287
|
+
return FAMILY.get(type)?.current || type;
|
|
288
|
+
}
|
|
289
|
+
/** Whether two element types are one component, across hot edits. */
|
|
290
|
+
function same(a, b) {
|
|
291
|
+
if (a === b) return true;
|
|
292
|
+
const sub = owner(a);
|
|
293
|
+
if (sub) {
|
|
294
|
+
const other = owner(b);
|
|
295
|
+
return !!other && other.owner === sub.owner && other.key === sub.key;
|
|
296
|
+
}
|
|
297
|
+
const family = typeof a == "function" && FAMILY.get(a);
|
|
298
|
+
return !!family && family === FAMILY.get(b);
|
|
299
|
+
}
|
|
300
|
+
function track(type, scope) {
|
|
301
|
+
FAMILY.get(type)?.scopes.add(scope);
|
|
302
|
+
}
|
|
303
|
+
function untrack(type, scope) {
|
|
304
|
+
FAMILY.get(type)?.scopes.delete(scope);
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Register a module's function components under stable ids. A component seen
|
|
308
|
+
* before takes its new implementation and re-renders where it is mounted.
|
|
309
|
+
*/
|
|
310
|
+
function hot(id, components) {
|
|
311
|
+
for (const [name, type] of Object.entries(components)) {
|
|
312
|
+
if (typeof type != "function") continue;
|
|
313
|
+
const key = `${id}#${name}`;
|
|
314
|
+
let family = FAMILIES.get(key);
|
|
315
|
+
if (!family) FAMILIES.set(key, family = {
|
|
316
|
+
current: type,
|
|
317
|
+
scopes: /* @__PURE__ */ new Set()
|
|
318
|
+
});
|
|
319
|
+
FAMILY.set(type, family);
|
|
320
|
+
if (family.current === type) continue;
|
|
321
|
+
family.current = type;
|
|
322
|
+
for (const scope of family.scopes) {
|
|
323
|
+
scope.hot = true;
|
|
324
|
+
schedule(scope);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
//#endregion
|
|
330
|
+
export { untrack as a, dispose as c, claim as d, release as f, transition as h, track as i, enter as l, settle as m, latest as n, call as o, schedule as p, same as r, commit as s, hot as t, afterFlush as u };
|
|
331
|
+
//# sourceMappingURL=chunk-hot-BAqPvKEQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk-hot-BAqPvKEQ.js","names":[],"sources":["../src/scheduler.ts","../src/adapter.ts","../src/hot.ts"],"sourcesContent":["import { pending } from '@expressive/mvc';\n\ninterface Schedulable {\n queued?: 'urgent' | 'passive' | 'deferred';\n holds?: (() => void)[];\n probed?: { output: unknown };\n blocking?: (() => void)[];\n update(passive: boolean): PromiseLike<unknown> | void;\n probe?(): PromiseLike<unknown> | void;\n empty?(): boolean;\n}\n\nconst urgent = new Set<Schedulable>();\nconst passive = new Set<Schedulable>();\nconst after: (() => void)[] = [];\n\nlet depth = 0;\nlet urgentQueued = false;\nlet passiveQueued = false;\n\nfunction flush(scopes: Set<Schedulable>) {\n for (const scope of scopes) {\n scopes.delete(scope);\n scope.queued = undefined;\n\n let waiting: PromiseLike<unknown> | void = undefined;\n\n try {\n waiting = scope.update(false);\n } catch (error) {\n console.error(error);\n }\n\n settle(scope);\n if (!waiting) unblock(scope);\n }\n}\n\nfunction flushUrgent() {\n urgentQueued = false;\n flush(urgent);\n\n for (const run of after.splice(0)) run();\n}\n\nfunction afterFlush(run: () => void) {\n after.push(run);\n\n if (!urgentQueued) {\n urgentQueued = true;\n queueMicrotask(flushUrgent);\n }\n}\n\nfunction flushPassive() {\n passiveQueued = false;\n\n const batch = [...passive].filter((scope) => scope.queued === 'passive');\n passive.clear();\n\n for (const scope of batch) {\n const waiting = scope.probe?.();\n if (waiting) return defer(batch, waiting, scope);\n }\n\n batch.sort((a, b) => Number(!!b.empty?.()) - Number(!!a.empty?.()));\n\n for (let index = 0; index < batch.length; index++) {\n const scope = batch[index];\n\n if (scope.queued !== 'passive') continue;\n\n scope.queued = undefined;\n\n let waiting: PromiseLike<unknown> | void = undefined;\n\n try {\n waiting = scope.update(true);\n } catch (error) {\n console.error(error);\n }\n\n settle(scope);\n\n if (waiting) return defer(batch.slice(index + 1), waiting, scope);\n unblock(scope);\n }\n}\n\nfunction defer(scopes: Schedulable[], waiting: PromiseLike<unknown>, source: Schedulable) {\n const held = scopes.filter((scope) => scope.queued === 'passive');\n\n for (const scope of held) {\n scope.queued = 'deferred';\n scope.probed = undefined;\n }\n\n const resume = () => {\n for (const scope of held)\n if (scope.queued === 'deferred') {\n scope.queued = undefined;\n transition(() => schedule(scope));\n }\n };\n\n (source.blocking ||= []).push(resume);\n waiting.then(resume, resume);\n}\n\nfunction unblock(scope: Schedulable) {\n const { blocking } = scope;\n\n scope.blocking = undefined;\n blocking?.forEach((resume) => resume());\n}\n\nfunction release(holds?: (() => void)[]) {\n holds?.forEach((held) => held());\n}\n\nfunction settle(scope: Schedulable) {\n const { holds } = scope;\n\n scope.holds = undefined;\n release(holds);\n}\n\nfunction schedule(scope: Schedulable) {\n const held = pending();\n\n if (held) (scope.holds ||= []).push(held);\n scope.probed = undefined;\n\n if (!depth) {\n passive.delete(scope);\n scope.queued = 'urgent';\n urgent.add(scope);\n\n if (!urgentQueued) {\n urgentQueued = true;\n queueMicrotask(flushUrgent);\n }\n\n return;\n }\n\n if (scope.queued && scope.queued !== 'deferred') return;\n\n scope.queued = 'passive';\n passive.add(scope);\n\n if (!passiveQueued) {\n passiveQueued = true;\n setTimeout(flushPassive);\n }\n}\n\nfunction transition(work: () => void) {\n depth++;\n\n try {\n work();\n } finally {\n depth--;\n }\n}\n\nfunction claim(scope: Schedulable) {\n urgent.delete(scope);\n passive.delete(scope);\n scope.queued = undefined;\n scope.probed = undefined;\n}\n\nfunction unschedule(scope: Schedulable) {\n urgent.delete(scope);\n passive.delete(scope);\n scope.queued = undefined;\n scope.probed = undefined;\n settle(scope);\n unblock(scope);\n}\n\nexport { afterFlush, claim, release, schedule, settle, transition, unschedule };\nexport type { Schedulable };\n","import { Component, Context, State, unbind } from '@expressive/mvc';\nimport { watch } from '@expressive/mvc/observable';\n\nimport { schedule, transition, unschedule } from './scheduler';\nimport type { Schedulable } from './scheduler';\n\ninterface UseState extends State {\n use?(...props: any[]): Promise<void> | void;\n mount?(): (() => void) | void;\n}\n\ninterface UseSlot {\n Type: State.Type;\n context: Context;\n instance: UseState;\n proxy: State;\n release: () => void;\n mounted?: true;\n cleanup?: (() => void) | void;\n apply: (...args: any[]) => unknown;\n}\n\ninterface Scope extends Schedulable {\n active: boolean;\n childContext: Context;\n context: Context;\n hot?: boolean;\n kind: 'component' | 'function' | 'collection';\n subscriptions: (() => void)[];\n uses: UseSlot[];\n useIndex: number;\n}\n\nlet current: Scope | undefined;\nlet collecting: (() => void)[] | undefined;\n\nfunction enter<T>(scope: Scope, render: () => T): T {\n const parent = current;\n const releases = collecting;\n const next: (() => void)[] = [];\n\n current = scope;\n collecting = next;\n scope.childContext = scope.context;\n scope.useIndex = 0;\n\n try {\n const output = render();\n\n if (scope.kind == 'function' && scope.useIndex !== scope.uses.length) {\n if (!scope.hot)\n throw new Error('State.use() calls must keep the same order on every function-component render.');\n\n truncate(scope, scope.useIndex);\n }\n\n return output;\n } finally {\n scope.hot = undefined;\n current = parent;\n collecting = releases;\n scope.subscriptions.forEach((release) => release());\n scope.subscriptions = next;\n }\n}\n\nfunction dispose(scope: Scope) {\n scope.active = false;\n unschedule(scope);\n scope.subscriptions.forEach((release) => release());\n scope.subscriptions = [];\n truncate(scope, 0);\n}\n\n/** Destroy the `State.use()` slots of a scope from `index` on. */\nfunction truncate(scope: Scope, index: number) {\n for (let i = scope.uses.length - 1; i >= index; i--) {\n const slot = scope.uses[i];\n\n slot.release();\n if (typeof slot.cleanup == 'function') slot.cleanup();\n slot.context.pop();\n slot.instance.set(null);\n }\n\n scope.uses.length = index;\n}\n\nfunction commit(scope: Scope) {\n for (const slot of scope.uses)\n if (!slot.mounted) {\n slot.mounted = true;\n slot.cleanup = slot.instance.mount?.();\n }\n}\n\nfunction requireScope(): Scope {\n if (!current)\n throw new Error('State.get() and State.use() may only run while @expressive/dom is rendering.');\n\n return current;\n}\n\nfunction tracked<T extends object>(target: T, required?: boolean): T {\n const scope = requireScope();\n let proxy = target;\n let first = true;\n\n const release = watch(\n target,\n (next) => {\n proxy = next;\n if (!first && scope.active) schedule(scope);\n first = false;\n },\n required,\n transition\n );\n\n collecting!.push(release);\n return proxy;\n}\n\ntype NoVoid<T> = T extends undefined | void ? null : T;\n\ndeclare module '@expressive/mvc' {\n interface UseState extends State {\n use?(...props: any[]): Promise<void> | void;\n mount?(): (() => void) | void;\n }\n\n namespace State {\n type ForceRefresh = {\n (): void;\n <T = void>(waitFor: Promise<T>): Promise<T>;\n <T = void>(invoke: () => Promise<T>): Promise<T>;\n };\n\n type GetFactory<T extends State, R> = (\n this: T,\n current: T,\n refresh: ForceRefresh\n ) => R;\n\n type UseArgs<T extends State> = T extends { use(...props: infer P): any }\n ? P\n : State.Args<T>;\n\n function get<T extends State>(this: State.Extends<T>): T;\n function get<T extends State>(this: State.Extends<T>, required: false): T | undefined;\n function get<T extends State>(this: State.Extends<T>, required: true): Required<T>;\n function get<T extends State, R>(\n this: State.Extends<T>,\n factory: GetFactory<T, R>\n ): NoVoid<R>;\n function use<T extends UseState>(\n this: State.Type<T>,\n ...args: UseArgs<T>\n ): T;\n }\n\n namespace Component {\n const use: never;\n }\n\n interface Component {\n mount?(): (() => void) | void;\n }\n}\n\n(State as any).get = function get<T extends State>(\n this: State.Extends<T>,\n argument?: boolean | State.GetFactory<T, unknown>\n) {\n const scope = requireScope();\n const instance = scope.childContext.get(this, argument === false ? false : true);\n\n if (!instance) return undefined;\n\n const proxy = tracked(instance, argument === true);\n\n if (typeof argument != 'function') return proxy;\n\n const refresh = ((action?: Promise<unknown> | (() => Promise<unknown>)) => {\n if (typeof action == 'function') action = action();\n schedule(scope);\n return action instanceof Promise ? action.finally(() => schedule(scope)) : undefined;\n }) as State.ForceRefresh;\n\n return argument.call(proxy, proxy, refresh) ?? null;\n};\n\n(State as any).use = function use<T extends UseState>(\n this: State.Type<T>,\n ...args: State.UseArgs<T>\n) {\n const scope = requireScope();\n\n if (scope.kind != 'function')\n throw new Error('State.use() is only available at the top level of a function component.');\n\n const index = scope.useIndex++;\n let slot = scope.uses[index] as UseSlot | undefined;\n\n if (slot && slot.Type !== this) {\n if (!scope.hot)\n throw new Error('State.use() calls must keep the same order on every function-component render.');\n\n truncate(scope, index);\n slot = undefined;\n }\n\n if (!slot) {\n let instance!: T;\n const assign = (value: unknown) =>\n typeof value == 'object' && value && instance.set(value as State.Assign<T>);\n let apply: (...values: any[]) => unknown = (...values) =>\n Promise.all(values.flat().map(assign));\n\n instance = new (this as any)((self: T) => {\n const own = self as T & UseState;\n\n if (typeof own.use == 'function') {\n apply = own.use.bind(own);\n apply(...args);\n return;\n }\n\n return args;\n });\n const context = scope.childContext.push(instance);\n\n slot = {\n Type: this,\n context,\n instance,\n proxy: instance,\n release: undefined!,\n apply\n };\n\n let first = true;\n slot.release = watch(instance, (proxy) => {\n slot!.proxy = proxy;\n\n if (!first && scope.active) schedule(scope);\n first = false;\n }, undefined, transition);\n\n slot.apply = apply;\n scope.uses.push(slot);\n } else {\n slot.apply(...args);\n }\n\n scope.childContext = slot.context;\n return slot.proxy as T;\n};\n\nObject.defineProperty(Component, 'use', {\n configurable: true,\n value() {\n throw new Error(`${this} is a Component - render it instead of calling use().`);\n }\n});\n\nconst OWNERS = new WeakMap<Function, { owner: State; key: string }>();\n\nState.on({\n method(key, fn, owner) {\n if (/^[A-Z]/.test(key)) OWNERS.set(fn, { owner, key });\n }\n});\n\nfunction call(type: Function, props: unknown) {\n const sub = OWNERS.get(type);\n\n if (!sub) return type(props);\n\n const { owner, key } = sub;\n return unbind((owner as any)[key]).call(tracked(owner), props);\n}\n\nfunction owner(type: unknown) {\n return typeof type == 'function' ? OWNERS.get(type) : undefined;\n}\n\nexport { call, commit, dispose, enter, owner };\nexport type { Scope };\n","import type { Scope } from './adapter';\nimport { owner } from './adapter';\nimport { schedule } from './scheduler';\n\ninterface Family {\n current: Function;\n scopes: Set<Scope>;\n}\n\nconst FAMILIES = new Map<string, Family>();\nconst FAMILY = new WeakMap<Function, Family>();\n\n/** The latest implementation of a component registered for hot refresh. */\nfunction latest(type: Function) {\n return FAMILY.get(type)?.current || type;\n}\n\n/** Whether two element types are one component, across hot edits. */\nfunction same(a: unknown, b: unknown) {\n if (a === b) return true;\n\n const sub = owner(a);\n\n if (sub) {\n const other = owner(b);\n return !!other && other.owner === sub.owner && other.key === sub.key;\n }\n\n const family = typeof a == 'function' && FAMILY.get(a);\n\n return !!family && family === FAMILY.get(b as Function);\n}\n\nfunction track(type: Function, scope: Scope) {\n FAMILY.get(type)?.scopes.add(scope);\n}\n\nfunction untrack(type: Function, scope: Scope) {\n FAMILY.get(type)?.scopes.delete(scope);\n}\n\n/**\n * Register a module's function components under stable ids. A component seen\n * before takes its new implementation and re-renders where it is mounted.\n */\nfunction hot(id: string, components: Record<string, unknown>) {\n for (const [name, type] of Object.entries(components)) {\n if (typeof type != 'function') continue;\n\n const key = `${id}#${name}`;\n let family = FAMILIES.get(key);\n\n if (!family) FAMILIES.set(key, (family = { current: type, scopes: new Set() }));\n\n FAMILY.set(type, family);\n\n if (family.current === type) continue;\n\n family.current = type;\n\n for (const scope of family.scopes) {\n scope.hot = true;\n schedule(scope);\n }\n }\n}\n\nexport { hot, latest, same, track, untrack };\n"],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { JSX } from "./jsx-runtime.js";
|
|
2
|
+
import { has, map } from "@expressive/mvc";
|
|
3
|
+
|
|
4
|
+
//#region src/vnode.d.ts
|
|
5
|
+
declare const VNODE: unique symbol;
|
|
6
|
+
type Key = string | number | null | undefined;
|
|
7
|
+
type FunctionComponent<P = any> = (props: P) => Node;
|
|
8
|
+
interface ComponentInstance {
|
|
9
|
+
render(props?: any): Node;
|
|
10
|
+
}
|
|
11
|
+
type ComponentType<P = any> = FunctionComponent<P> | (abstract new (...args: any[]) => object);
|
|
12
|
+
type Node = VNode | ComponentInstance | string | number | bigint | boolean | null | undefined | readonly Node[] | has.List<Node> | has.Pool<Node, any, any> | map.Managed<unknown, Node>;
|
|
13
|
+
interface VNode<P = any> {
|
|
14
|
+
readonly [VNODE]: true;
|
|
15
|
+
readonly type: string | symbol | ComponentType<P>;
|
|
16
|
+
readonly props: P & {
|
|
17
|
+
children?: Node;
|
|
18
|
+
};
|
|
19
|
+
readonly key?: Key;
|
|
20
|
+
}
|
|
21
|
+
declare function vnode<P>(type: VNode<P>['type'], props: P, key?: unknown): VNode<P>;
|
|
22
|
+
declare function createElement(type: VNode['type'], props?: Record<string, unknown> | null, ...children: unknown[]): VNode;
|
|
23
|
+
type JsxElement = JSX.Element;
|
|
24
|
+
type JsxElementType = JSX.ElementType;
|
|
25
|
+
type JsxElementClass = JSX.ElementClass;
|
|
26
|
+
type JsxAttributesProperty = JSX.ElementAttributesProperty;
|
|
27
|
+
type JsxManaged<C, P> = JSX.LibraryManagedAttributes<C, P>;
|
|
28
|
+
type JsxChildrenAttribute = JSX.ElementChildrenAttribute;
|
|
29
|
+
type JsxIntrinsicAttributes = JSX.IntrinsicAttributes;
|
|
30
|
+
type JsxIntrinsicElements = JSX.IntrinsicElements;
|
|
31
|
+
declare namespace createElement {
|
|
32
|
+
namespace JSX {
|
|
33
|
+
type Element = JsxElement;
|
|
34
|
+
type ElementType = JsxElementType;
|
|
35
|
+
interface ElementClass extends JsxElementClass {}
|
|
36
|
+
interface ElementAttributesProperty extends JsxAttributesProperty {}
|
|
37
|
+
type LibraryManagedAttributes<C, P> = JsxManaged<C, P>;
|
|
38
|
+
interface ElementChildrenAttribute extends JsxChildrenAttribute {}
|
|
39
|
+
interface IntrinsicAttributes extends JsxIntrinsicAttributes {}
|
|
40
|
+
type IntrinsicElements = JsxIntrinsicElements;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
declare const Fragment: (props: {
|
|
44
|
+
children?: Node;
|
|
45
|
+
}) => Node;
|
|
46
|
+
declare const Portal: (props: {
|
|
47
|
+
into: Element | DocumentFragment | string;
|
|
48
|
+
children?: Node;
|
|
49
|
+
}) => Node;
|
|
50
|
+
//#endregion
|
|
51
|
+
//#region src/loader.d.ts
|
|
52
|
+
type Module<T extends ComponentType = ComponentType> = T | {
|
|
53
|
+
default: T;
|
|
54
|
+
};
|
|
55
|
+
type Attributes<T> = [T] extends [never] ? {} : T extends (abstract new (...args: any[]) => infer I) ? JSX.LibraryManagedAttributes<T, I> : T extends ((props: infer P) => any) ? P : never;
|
|
56
|
+
//#endregion
|
|
57
|
+
export { Portal as a, vnode as c, Node as i, Module as n, VNode as o, Fragment as r, createElement as s, Attributes as t };
|
|
58
|
+
//# sourceMappingURL=chunk-loader-kjuM318E.d.ts.map
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Fragment } from "@expressive/mvc/jsx-runtime";
|
|
2
|
+
|
|
1
3
|
//#region src/vnode.ts
|
|
2
4
|
const VNODE = Symbol("@expressive/dom.vnode");
|
|
3
5
|
const PORTAL = Symbol("@expressive/dom.portal");
|
|
@@ -9,6 +11,11 @@ function vnode(type, props, key) {
|
|
|
9
11
|
key
|
|
10
12
|
};
|
|
11
13
|
}
|
|
14
|
+
function createElement(type, props, ...children) {
|
|
15
|
+
const { key, ...rest } = props || {};
|
|
16
|
+
if (children.length) rest.children = children.length == 1 ? children[0] : children;
|
|
17
|
+
return vnode(type, rest, key);
|
|
18
|
+
}
|
|
12
19
|
function isVNode(value) {
|
|
13
20
|
return !!value && typeof value == "object" && value[VNODE] === true;
|
|
14
21
|
}
|
|
@@ -21,13 +28,9 @@ function childrenOf(value) {
|
|
|
21
28
|
add(value);
|
|
22
29
|
return output;
|
|
23
30
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
children,
|
|
27
|
-
container
|
|
28
|
-
}, key);
|
|
29
|
-
}
|
|
31
|
+
const Fragment$1 = Fragment;
|
|
32
|
+
const Portal = PORTAL;
|
|
30
33
|
|
|
31
34
|
//#endregion
|
|
32
|
-
export {
|
|
33
|
-
//# sourceMappingURL=chunk-vnode-
|
|
35
|
+
export { createElement as a, childrenOf as i, PORTAL as n, isVNode as o, Portal as r, vnode as s, Fragment$1 as t };
|
|
36
|
+
//# sourceMappingURL=chunk-vnode-BG1Cv8F9.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk-vnode-BG1Cv8F9.js","names":["Fragment","FRAGMENT"],"sources":["../src/vnode.ts"],"sourcesContent":["import { Fragment as FRAGMENT } from '@expressive/mvc/jsx-runtime';\nimport type { has, map } from '@expressive/mvc';\nimport type { JSX as Runtime } from './jsx-runtime';\n\nconst VNODE = Symbol('@expressive/dom.vnode');\nconst PORTAL = Symbol('@expressive/dom.portal');\n\ntype Key = string | number | null | undefined;\ntype FunctionComponent<P = any> = (props: P) => Node;\ninterface ComponentInstance {\n render(props?: any): Node;\n}\ntype ComponentType<P = any> = FunctionComponent<P> | (abstract new (...args: any[]) => object);\n\ntype Node =\n | VNode\n | ComponentInstance\n | string\n | number\n | bigint\n | boolean\n | null\n | undefined\n | readonly Node[]\n | has.List<Node>\n | has.Pool<Node, any, any>\n | map.Managed<unknown, Node>;\n\ninterface VNode<P = any> {\n readonly [VNODE]: true;\n readonly type: string | symbol | ComponentType<P>;\n readonly props: P & { children?: Node };\n readonly key?: Key;\n}\n\nfunction vnode<P>(type: VNode<P>['type'], props: P, key?: unknown): VNode<P> {\n return {\n [VNODE]: true,\n type,\n props: (props || {}) as VNode<P>['props'],\n key: key as Key\n };\n}\n\nfunction createElement(type: VNode['type'], props?: Record<string, unknown> | null, ...children: unknown[]): VNode {\n const { key, ...rest } = props || {};\n\n if (children.length) rest.children = children.length == 1 ? children[0] : children;\n\n return vnode(type, rest, key);\n}\n\ntype JsxElement = Runtime.Element;\ntype JsxElementType = Runtime.ElementType;\ntype JsxElementClass = Runtime.ElementClass;\ntype JsxAttributesProperty = Runtime.ElementAttributesProperty;\ntype JsxManaged<C, P> = Runtime.LibraryManagedAttributes<C, P>;\ntype JsxChildrenAttribute = Runtime.ElementChildrenAttribute;\ntype JsxIntrinsicAttributes = Runtime.IntrinsicAttributes;\ntype JsxIntrinsicElements = Runtime.IntrinsicElements;\n\ndeclare namespace createElement {\n namespace JSX {\n type Element = JsxElement;\n type ElementType = JsxElementType;\n interface ElementClass extends JsxElementClass {}\n interface ElementAttributesProperty extends JsxAttributesProperty {}\n type LibraryManagedAttributes<C, P> = JsxManaged<C, P>;\n interface ElementChildrenAttribute extends JsxChildrenAttribute {}\n interface IntrinsicAttributes extends JsxIntrinsicAttributes {}\n type IntrinsicElements = JsxIntrinsicElements;\n }\n}\n\nfunction isVNode(value: unknown): value is VNode {\n return !!value && typeof value == 'object' && (value as VNode)[VNODE] === true;\n}\n\nfunction childrenOf(value: unknown): Node[] {\n const output: Node[] = [];\n\n function add(child: unknown) {\n if (Array.isArray(child)) child.forEach(add);\n else if (child !== null && child !== undefined && typeof child != 'boolean')\n output.push(child as Node);\n }\n\n add(value);\n return output;\n}\n\nconst Fragment = FRAGMENT as unknown as (props: { children?: Node }) => Node;\nconst Portal = PORTAL as unknown as (props: { into: Element | DocumentFragment | string; children?: Node }) => Node;\n\nexport {\n VNODE,\n PORTAL,\n childrenOf,\n createElement,\n Fragment,\n Portal,\n isVNode,\n vnode\n};\n\nexport type { ComponentInstance, ComponentType, FunctionComponent, Key, Node, VNode };\n"],"mappings":";;;AAIA,MAAM,QAAQ,OAAO,wBAAwB;AAC7C,MAAM,SAAS,OAAO,yBAAyB;AA8B/C,SAAS,MAAS,MAAwB,OAAU,KAAyB;AAC3E,QAAO;GACJ,QAAQ;EACT;EACA,OAAQ,SAAS,EAAE;EACd;EACN;;AAGH,SAAS,cAAc,MAAqB,OAAwC,GAAG,UAA4B;CACjH,MAAM,EAAE,KAAK,GAAG,SAAS,SAAS,EAAE;AAEpC,KAAI,SAAS,OAAQ,MAAK,WAAW,SAAS,UAAU,IAAI,SAAS,KAAK;AAE1E,QAAO,MAAM,MAAM,MAAM,IAAI;;AAyB/B,SAAS,QAAQ,OAAgC;AAC/C,QAAO,CAAC,CAAC,SAAS,OAAO,SAAS,YAAa,MAAgB,WAAW;;AAG5E,SAAS,WAAW,OAAwB;CAC1C,MAAM,SAAiB,EAAE;CAEzB,SAAS,IAAI,OAAgB;AAC3B,MAAI,MAAM,QAAQ,MAAM,CAAE,OAAM,QAAQ,IAAI;WACnC,UAAU,QAAQ,UAAU,UAAa,OAAO,SAAS,UAChE,QAAO,KAAK,MAAc;;AAG9B,KAAI,MAAM;AACV,QAAO;;AAGT,MAAMA,aAAWC;AACjB,MAAM,SAAS"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,34 +1,6 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
import {
|
|
1
|
+
import { a as Portal, i as Node, r as Fragment, s as createElement } from "./chunk-loader-kjuM318E.js";
|
|
2
|
+
import { JSX } from "./jsx-runtime.js";
|
|
3
3
|
|
|
4
|
-
//#region src/context.d.ts
|
|
5
|
-
declare namespace Consumer {
|
|
6
|
-
interface Props<T extends State> {
|
|
7
|
-
for: State.Extends<T>;
|
|
8
|
-
children: (value: T) => Node;
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
declare function Consumer<T extends State>(props: Consumer.Props<T>): Node;
|
|
12
|
-
declare namespace Provider {
|
|
13
|
-
type ForEach<T extends State> = (state: T) => void;
|
|
14
|
-
interface SharedProps {
|
|
15
|
-
children?: Node;
|
|
16
|
-
fallback?: Node;
|
|
17
|
-
name?: string;
|
|
18
|
-
}
|
|
19
|
-
type Props<T extends State = State> = SharedProps & {
|
|
20
|
-
for?: Context.Accept<T>;
|
|
21
|
-
is?: ForEach<T>;
|
|
22
|
-
} & Record<string, unknown>;
|
|
23
|
-
}
|
|
24
|
-
declare function Provider<T extends State>(_props: Provider.Props<T>): Component.Node;
|
|
25
|
-
//#endregion
|
|
26
|
-
//#region src/lazy.d.ts
|
|
27
|
-
type Module<P> = {
|
|
28
|
-
default: ComponentType<P>;
|
|
29
|
-
} | ComponentType<P>;
|
|
30
|
-
declare function lazy<P>(load: () => Promise<Module<P>>): FunctionComponent<P>;
|
|
31
|
-
//#endregion
|
|
32
4
|
//#region src/stylesheet.d.ts
|
|
33
5
|
type Member = Extract<keyof CSSStyleDeclaration, string>;
|
|
34
6
|
type Settable = { [K in Member]-?: CSSStyleDeclaration[K] extends Function ? never : K }[Member];
|
|
@@ -109,5 +81,5 @@ declare module '@expressive/dom' {
|
|
|
109
81
|
type Container = Element | DocumentFragment;
|
|
110
82
|
declare function render(node: Node, container: Container): () => void;
|
|
111
83
|
//#endregion
|
|
112
|
-
export {
|
|
84
|
+
export { Fragment, type JSX, Portal, createElement, css, macro, render, style };
|
|
113
85
|
//# sourceMappingURL=index.d.ts.map
|