@pyreon/vue-compat 0.13.1 → 0.15.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 +20 -0
- package/lib/analysis/index.js.html +1 -1
- package/lib/analysis/jsx-runtime.js.html +1 -1
- package/lib/index.js +410 -28
- package/lib/jsx-runtime.js +18 -5
- package/lib/types/index.d.ts +168 -8
- package/package.json +8 -4
- package/src/index.ts +622 -21
- package/src/jsx-runtime.ts +26 -2
- package/src/tests/jsx-runtime-wrapper.test.ts +158 -0
- package/src/tests/new-apis.test.ts +1303 -0
- package/src/vue-compat.browser.test.ts +31 -0
- package/lib/index.js.map +0 -1
- package/lib/jsx-runtime.js.map +0 -1
- package/lib/types/index.d.ts.map +0 -1
- package/lib/types/jsx-runtime.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -163,3 +163,23 @@ app.mount('#app')
|
|
|
163
163
|
|
|
164
164
|
- **`h` / `Fragment`** -- JSX runtime.
|
|
165
165
|
- **`batch(fn)`** -- coalesce multiple signal writes.
|
|
166
|
+
|
|
167
|
+
## Composing Pyreon framework components inside vue-compat
|
|
168
|
+
|
|
169
|
+
Pyreon's framework components (`RouterView`, `PyreonUI`, `FormProvider`, `QueryClientProvider`, …) ship marked with `nativeCompat()` from `@pyreon/core` — vue-compat's JSX runtime detects the marker and routes them through Pyreon's setup frame instead of the compat wrapper. **You don't need to do anything** for the 24 components shipped marked.
|
|
170
|
+
|
|
171
|
+
If you write your **own** Pyreon-flavored helper that uses `provide()` / `onMount()` / `onUnmount()` / `effect()` at component-body scope and use it in a vue-compat app, mark it explicitly:
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
import { nativeCompat, provide, createContext } from '@pyreon/core'
|
|
175
|
+
|
|
176
|
+
const MyCtx = createContext<string>('default')
|
|
177
|
+
|
|
178
|
+
function MyProvider(props: { value: string; children?: unknown }) {
|
|
179
|
+
provide(MyCtx, props.value)
|
|
180
|
+
return props.children as never
|
|
181
|
+
}
|
|
182
|
+
nativeCompat(MyProvider) // ← required for compat-mode apps
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Without the marker, the wrapper relocates the body's render context and `provide()` lands in a torn-down context stack — descendants read the default. See [`packages/core/core/src/compat-marker.ts`](../../core/core/src/compat-marker.ts) for details.
|
|
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
|
|
|
5386
5386
|
</script>
|
|
5387
5387
|
<script>
|
|
5388
5388
|
/*<!--*/
|
|
5389
|
-
const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"
|
|
5389
|
+
const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"2431af31-1","name":"jsx-runtime.ts"},{"uid":"2431af31-3","name":"index.ts"}]}]}],"isRoot":true},"nodeParts":{"2431af31-1":{"renderedLength":186,"gzipLength":138,"brotliLength":0,"metaUid":"2431af31-0"},"2431af31-3":{"renderedLength":21829,"gzipLength":5180,"brotliLength":0,"metaUid":"2431af31-2"}},"nodeMetas":{"2431af31-0":{"id":"/src/jsx-runtime.ts","moduleParts":{"index.js":"2431af31-1"},"imported":[{"uid":"2431af31-4"},{"uid":"2431af31-5"}],"importedBy":[{"uid":"2431af31-2"}]},"2431af31-2":{"id":"/src/index.ts","moduleParts":{"index.js":"2431af31-3"},"imported":[{"uid":"2431af31-4"},{"uid":"2431af31-5"},{"uid":"2431af31-6"},{"uid":"2431af31-0"}],"importedBy":[],"isEntry":true},"2431af31-4":{"id":"@pyreon/core","moduleParts":{},"imported":[],"importedBy":[{"uid":"2431af31-2"},{"uid":"2431af31-0"}]},"2431af31-5":{"id":"@pyreon/reactivity","moduleParts":{},"imported":[],"importedBy":[{"uid":"2431af31-2"},{"uid":"2431af31-0"}]},"2431af31-6":{"id":"@pyreon/runtime-dom","moduleParts":{},"imported":[],"importedBy":[{"uid":"2431af31-2"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
|
|
5390
5390
|
|
|
5391
5391
|
const run = () => {
|
|
5392
5392
|
const width = window.innerWidth;
|
|
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
|
|
|
5386
5386
|
</script>
|
|
5387
5387
|
<script>
|
|
5388
5388
|
/*<!--*/
|
|
5389
|
-
const data = {"version":2,"tree":{"name":"root","children":[{"name":"jsx-runtime.js","children":[{"name":"src","children":[{"uid":"
|
|
5389
|
+
const data = {"version":2,"tree":{"name":"root","children":[{"name":"jsx-runtime.js","children":[{"name":"src","children":[{"uid":"5769505c-1","name":"jsx-runtime.ts"},{"uid":"5769505c-3","name":"jsx-dev-runtime.ts"}]}]}],"isRoot":true},"nodeParts":{"5769505c-1":{"renderedLength":2715,"gzipLength":981,"brotliLength":0,"metaUid":"5769505c-0"},"5769505c-3":{"renderedLength":0,"gzipLength":0,"brotliLength":0,"metaUid":"5769505c-2"}},"nodeMetas":{"5769505c-0":{"id":"/src/jsx-runtime.ts","moduleParts":{"jsx-runtime.js":"5769505c-1"},"imported":[{"uid":"5769505c-4"},{"uid":"5769505c-5"}],"importedBy":[{"uid":"5769505c-2"}]},"5769505c-2":{"id":"/src/jsx-dev-runtime.ts","moduleParts":{"jsx-runtime.js":"5769505c-3"},"imported":[{"uid":"5769505c-0"}],"importedBy":[],"isEntry":true},"5769505c-4":{"id":"@pyreon/core","moduleParts":{},"imported":[],"importedBy":[{"uid":"5769505c-0"}]},"5769505c-5":{"id":"@pyreon/reactivity","moduleParts":{},"imported":[],"importedBy":[{"uid":"5769505c-0"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
|
|
5390
5390
|
|
|
5391
5391
|
const run = () => {
|
|
5392
5392
|
const width = window.innerWidth;
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Fragment, createContext, h as pyreonH, onMount, onUnmount, onUpdate, popContext, pushContext, useContext } from "@pyreon/core";
|
|
1
|
+
import { Fragment, Portal, createContext, h as pyreonH, onMount, onUnmount, onUpdate, popContext, pushContext, useContext } from "@pyreon/core";
|
|
2
2
|
import { batch, computed as computed$1, createStore, effect, nextTick as nextTick$1, signal } from "@pyreon/reactivity";
|
|
3
3
|
import { mount } from "@pyreon/runtime-dom";
|
|
4
4
|
|
|
@@ -14,8 +14,9 @@ function getHookIndex() {
|
|
|
14
14
|
|
|
15
15
|
//#endregion
|
|
16
16
|
//#region src/index.ts
|
|
17
|
-
const V_IS_REF = Symbol("__v_isRef");
|
|
17
|
+
const V_IS_REF = Symbol.for("__v_isRef");
|
|
18
18
|
const V_IS_READONLY = Symbol("__v_isReadonly");
|
|
19
|
+
const V_SKIP = Symbol("__v_skip");
|
|
19
20
|
const V_RAW = Symbol("__v_raw");
|
|
20
21
|
/**
|
|
21
22
|
* Creates a reactive ref wrapping the given value.
|
|
@@ -40,6 +41,7 @@ function ref(value) {
|
|
|
40
41
|
s.set(v);
|
|
41
42
|
scheduleRerender();
|
|
42
43
|
},
|
|
44
|
+
/** @internal — access underlying signal for triggerRef */
|
|
43
45
|
_signal: s,
|
|
44
46
|
_scheduleRerender: scheduleRerender
|
|
45
47
|
};
|
|
@@ -55,6 +57,7 @@ function ref(value) {
|
|
|
55
57
|
set value(v) {
|
|
56
58
|
s.set(v);
|
|
57
59
|
},
|
|
60
|
+
/** @internal — access underlying signal for triggerRef */
|
|
58
61
|
_signal: s
|
|
59
62
|
};
|
|
60
63
|
}
|
|
@@ -88,6 +91,15 @@ function isRef(val) {
|
|
|
88
91
|
function unref(r) {
|
|
89
92
|
return isRef(r) ? r.value : r;
|
|
90
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Unwraps a ref, calls a getter, or returns the value as-is.
|
|
96
|
+
* Vue 3.3+ API for normalizing ref/getter/value inputs.
|
|
97
|
+
*/
|
|
98
|
+
function toValue(source) {
|
|
99
|
+
if (isRef(source)) return source.value;
|
|
100
|
+
if (typeof source === "function") return source();
|
|
101
|
+
return source;
|
|
102
|
+
}
|
|
91
103
|
function computed(fnOrOptions) {
|
|
92
104
|
const ctx = getCurrentCtx();
|
|
93
105
|
if (ctx) {
|
|
@@ -134,6 +146,7 @@ const rawMap = /* @__PURE__ */ new WeakMap();
|
|
|
134
146
|
* call `scheduleRerender()`.
|
|
135
147
|
*/
|
|
136
148
|
function reactive(obj) {
|
|
149
|
+
if (obj[V_SKIP]) return obj;
|
|
137
150
|
const ctx = getCurrentCtx();
|
|
138
151
|
if (ctx) {
|
|
139
152
|
const idx = getHookIndex();
|
|
@@ -183,7 +196,22 @@ function readonly(obj) {
|
|
|
183
196
|
}
|
|
184
197
|
return _createReadonlyProxy(obj);
|
|
185
198
|
}
|
|
186
|
-
|
|
199
|
+
/**
|
|
200
|
+
* Returns a shallow readonly proxy — only top-level properties throw on set.
|
|
201
|
+
* Nested objects are NOT wrapped in readonly (unlike `readonly()`).
|
|
202
|
+
*/
|
|
203
|
+
function shallowReadonly(obj) {
|
|
204
|
+
const ctx = getCurrentCtx();
|
|
205
|
+
if (ctx) {
|
|
206
|
+
const idx = getHookIndex();
|
|
207
|
+
if (idx < ctx.hooks.length) return ctx.hooks[idx];
|
|
208
|
+
const proxy = _createShallowReadonlyProxy(obj);
|
|
209
|
+
ctx.hooks[idx] = proxy;
|
|
210
|
+
return proxy;
|
|
211
|
+
}
|
|
212
|
+
return _createShallowReadonlyProxy(obj);
|
|
213
|
+
}
|
|
214
|
+
function _createShallowReadonlyProxy(obj) {
|
|
187
215
|
return new Proxy(obj, {
|
|
188
216
|
get(target, key) {
|
|
189
217
|
if (key === V_IS_READONLY) return true;
|
|
@@ -199,6 +227,24 @@ function _createReadonlyProxy(obj) {
|
|
|
199
227
|
}
|
|
200
228
|
});
|
|
201
229
|
}
|
|
230
|
+
function _createReadonlyProxy(obj) {
|
|
231
|
+
return new Proxy(obj, {
|
|
232
|
+
get(target, key) {
|
|
233
|
+
if (key === V_IS_READONLY) return true;
|
|
234
|
+
if (key === V_RAW) return target;
|
|
235
|
+
const value = Reflect.get(target, key);
|
|
236
|
+
if (value !== null && typeof value === "object" && !isRef(value)) return _createReadonlyProxy(value);
|
|
237
|
+
return value;
|
|
238
|
+
},
|
|
239
|
+
set(_target, key) {
|
|
240
|
+
if (key === V_IS_READONLY || key === V_RAW) return true;
|
|
241
|
+
throw new Error(`Cannot set property "${String(key)}" on a readonly object`);
|
|
242
|
+
},
|
|
243
|
+
deleteProperty(_target, key) {
|
|
244
|
+
throw new Error(`Cannot delete property "${String(key)}" from a readonly object`);
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
}
|
|
202
248
|
/**
|
|
203
249
|
* Returns the raw (unwrapped) object behind a reactive or readonly proxy.
|
|
204
250
|
*/
|
|
@@ -255,12 +301,102 @@ function toRefs(obj) {
|
|
|
255
301
|
for (const key of Object.keys(obj)) result[key] = _createToRef(obj, key);
|
|
256
302
|
return result;
|
|
257
303
|
}
|
|
258
|
-
/**
|
|
259
|
-
* Watches a reactive source and calls `cb` when it changes.
|
|
260
|
-
*
|
|
261
|
-
* Inside a component: hook-indexed, created once. Disposed on unmount.
|
|
262
|
-
*/
|
|
263
304
|
function watch(source, cb, options) {
|
|
305
|
+
if (Array.isArray(source)) return _watchArray(source, cb, options);
|
|
306
|
+
return _watchSingle(source, cb, options);
|
|
307
|
+
}
|
|
308
|
+
function _watchArray(sources, cb, options) {
|
|
309
|
+
const getters = sources.map((s) => isRef(s) ? () => s.value : s);
|
|
310
|
+
let cleanupFn;
|
|
311
|
+
const onCleanup = (fn) => {
|
|
312
|
+
cleanupFn = fn;
|
|
313
|
+
};
|
|
314
|
+
const runCleanup = () => {
|
|
315
|
+
if (cleanupFn) {
|
|
316
|
+
cleanupFn();
|
|
317
|
+
cleanupFn = void 0;
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
const ctx = getCurrentCtx();
|
|
321
|
+
if (ctx) {
|
|
322
|
+
const idx = getHookIndex();
|
|
323
|
+
if (idx < ctx.hooks.length) return ctx.hooks[idx];
|
|
324
|
+
let oldValues;
|
|
325
|
+
let initialized = false;
|
|
326
|
+
if (options?.immediate) {
|
|
327
|
+
const current = getters.map((g) => g());
|
|
328
|
+
cb(current, getters.map(() => void 0), onCleanup);
|
|
329
|
+
oldValues = current;
|
|
330
|
+
initialized = true;
|
|
331
|
+
}
|
|
332
|
+
let running = false;
|
|
333
|
+
const combined = computed$1(() => getters.map((g) => g()));
|
|
334
|
+
const e = effect(() => {
|
|
335
|
+
if (running) return;
|
|
336
|
+
running = true;
|
|
337
|
+
try {
|
|
338
|
+
const newValues = combined();
|
|
339
|
+
if (initialized) {
|
|
340
|
+
runCleanup();
|
|
341
|
+
cb([...newValues], oldValues ? [...oldValues] : getters.map(() => void 0), onCleanup);
|
|
342
|
+
}
|
|
343
|
+
oldValues = [...newValues];
|
|
344
|
+
initialized = true;
|
|
345
|
+
} finally {
|
|
346
|
+
running = false;
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
const stop = () => {
|
|
350
|
+
runCleanup();
|
|
351
|
+
e.dispose();
|
|
352
|
+
};
|
|
353
|
+
ctx.hooks[idx] = stop;
|
|
354
|
+
ctx.unmountCallbacks.push(stop);
|
|
355
|
+
return stop;
|
|
356
|
+
}
|
|
357
|
+
let oldValues;
|
|
358
|
+
let initialized = false;
|
|
359
|
+
if (options?.immediate) {
|
|
360
|
+
const current = getters.map((g) => g());
|
|
361
|
+
cb(current, getters.map(() => void 0), onCleanup);
|
|
362
|
+
oldValues = current;
|
|
363
|
+
initialized = true;
|
|
364
|
+
}
|
|
365
|
+
let running = false;
|
|
366
|
+
const combined = computed$1(() => getters.map((g) => g()));
|
|
367
|
+
const e = effect(() => {
|
|
368
|
+
if (running) return;
|
|
369
|
+
running = true;
|
|
370
|
+
try {
|
|
371
|
+
const newValues = combined();
|
|
372
|
+
if (initialized) {
|
|
373
|
+
runCleanup();
|
|
374
|
+
cb([...newValues], oldValues ? [...oldValues] : getters.map(() => void 0), onCleanup);
|
|
375
|
+
}
|
|
376
|
+
oldValues = [...newValues];
|
|
377
|
+
initialized = true;
|
|
378
|
+
} finally {
|
|
379
|
+
running = false;
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
const stop = () => {
|
|
383
|
+
runCleanup();
|
|
384
|
+
e.dispose();
|
|
385
|
+
};
|
|
386
|
+
if (_currentEffectScope) _currentEffectScope._cleanups.push(stop);
|
|
387
|
+
return stop;
|
|
388
|
+
}
|
|
389
|
+
function _watchSingle(source, cb, options) {
|
|
390
|
+
let cleanupFn;
|
|
391
|
+
const onCleanup = (fn) => {
|
|
392
|
+
cleanupFn = fn;
|
|
393
|
+
};
|
|
394
|
+
const runCleanup = () => {
|
|
395
|
+
if (cleanupFn) {
|
|
396
|
+
cleanupFn();
|
|
397
|
+
cleanupFn = void 0;
|
|
398
|
+
}
|
|
399
|
+
};
|
|
264
400
|
const ctx = getCurrentCtx();
|
|
265
401
|
if (ctx) {
|
|
266
402
|
const idx = getHookIndex();
|
|
@@ -271,7 +407,7 @@ function watch(source, cb, options) {
|
|
|
271
407
|
if (options?.immediate) {
|
|
272
408
|
oldValue = void 0;
|
|
273
409
|
const current = getter();
|
|
274
|
-
cb(current, oldValue);
|
|
410
|
+
cb(current, oldValue, onCleanup);
|
|
275
411
|
oldValue = current;
|
|
276
412
|
initialized = true;
|
|
277
413
|
}
|
|
@@ -281,14 +417,20 @@ function watch(source, cb, options) {
|
|
|
281
417
|
running = true;
|
|
282
418
|
try {
|
|
283
419
|
const newValue = getter();
|
|
284
|
-
if (initialized)
|
|
420
|
+
if (initialized) {
|
|
421
|
+
runCleanup();
|
|
422
|
+
cb(newValue, oldValue, onCleanup);
|
|
423
|
+
}
|
|
285
424
|
oldValue = newValue;
|
|
286
425
|
initialized = true;
|
|
287
426
|
} finally {
|
|
288
427
|
running = false;
|
|
289
428
|
}
|
|
290
429
|
});
|
|
291
|
-
const stop = () =>
|
|
430
|
+
const stop = () => {
|
|
431
|
+
runCleanup();
|
|
432
|
+
e.dispose();
|
|
433
|
+
};
|
|
292
434
|
ctx.hooks[idx] = stop;
|
|
293
435
|
ctx.unmountCallbacks.push(stop);
|
|
294
436
|
return stop;
|
|
@@ -299,7 +441,7 @@ function watch(source, cb, options) {
|
|
|
299
441
|
if (options?.immediate) {
|
|
300
442
|
oldValue = void 0;
|
|
301
443
|
const current = getter();
|
|
302
|
-
cb(current, oldValue);
|
|
444
|
+
cb(current, oldValue, onCleanup);
|
|
303
445
|
oldValue = current;
|
|
304
446
|
initialized = true;
|
|
305
447
|
}
|
|
@@ -309,23 +451,43 @@ function watch(source, cb, options) {
|
|
|
309
451
|
running = true;
|
|
310
452
|
try {
|
|
311
453
|
const newValue = getter();
|
|
312
|
-
if (initialized)
|
|
454
|
+
if (initialized) {
|
|
455
|
+
runCleanup();
|
|
456
|
+
cb(newValue, oldValue, onCleanup);
|
|
457
|
+
}
|
|
313
458
|
oldValue = newValue;
|
|
314
459
|
initialized = true;
|
|
315
460
|
} finally {
|
|
316
461
|
running = false;
|
|
317
462
|
}
|
|
318
463
|
});
|
|
319
|
-
|
|
464
|
+
const stop = () => {
|
|
465
|
+
runCleanup();
|
|
466
|
+
e.dispose();
|
|
467
|
+
};
|
|
468
|
+
if (_currentEffectScope) _currentEffectScope._cleanups.push(stop);
|
|
469
|
+
return stop;
|
|
320
470
|
}
|
|
321
471
|
/**
|
|
322
472
|
* Runs the given function reactively — re-executes whenever its tracked
|
|
323
|
-
* dependencies change.
|
|
473
|
+
* dependencies change. Passes an `onCleanup` registration function to the
|
|
474
|
+
* callback, matching Vue 3's `watchEffect((onCleanup) => { ... })` API.
|
|
324
475
|
*
|
|
325
476
|
* Inside a component: hook-indexed, created once. Disposed on unmount.
|
|
326
477
|
*/
|
|
327
478
|
function watchEffect(fn) {
|
|
328
479
|
const ctx = getCurrentCtx();
|
|
480
|
+
let cleanupFn;
|
|
481
|
+
const onCleanup = (cleanup) => {
|
|
482
|
+
cleanupFn = cleanup;
|
|
483
|
+
};
|
|
484
|
+
const runEffect = () => {
|
|
485
|
+
if (cleanupFn) {
|
|
486
|
+
cleanupFn();
|
|
487
|
+
cleanupFn = void 0;
|
|
488
|
+
}
|
|
489
|
+
fn(onCleanup);
|
|
490
|
+
};
|
|
329
491
|
if (ctx) {
|
|
330
492
|
const idx = getHookIndex();
|
|
331
493
|
if (idx < ctx.hooks.length) return ctx.hooks[idx];
|
|
@@ -334,12 +496,15 @@ function watchEffect(fn) {
|
|
|
334
496
|
if (running) return;
|
|
335
497
|
running = true;
|
|
336
498
|
try {
|
|
337
|
-
|
|
499
|
+
runEffect();
|
|
338
500
|
} finally {
|
|
339
501
|
running = false;
|
|
340
502
|
}
|
|
341
503
|
});
|
|
342
|
-
const stop = () =>
|
|
504
|
+
const stop = () => {
|
|
505
|
+
if (cleanupFn) cleanupFn();
|
|
506
|
+
e.dispose();
|
|
507
|
+
};
|
|
343
508
|
ctx.hooks[idx] = stop;
|
|
344
509
|
ctx.unmountCallbacks.push(stop);
|
|
345
510
|
return stop;
|
|
@@ -349,12 +514,17 @@ function watchEffect(fn) {
|
|
|
349
514
|
if (running) return;
|
|
350
515
|
running = true;
|
|
351
516
|
try {
|
|
352
|
-
|
|
517
|
+
runEffect();
|
|
353
518
|
} finally {
|
|
354
519
|
running = false;
|
|
355
520
|
}
|
|
356
521
|
});
|
|
357
|
-
|
|
522
|
+
const stop = () => {
|
|
523
|
+
if (cleanupFn) cleanupFn();
|
|
524
|
+
e.dispose();
|
|
525
|
+
};
|
|
526
|
+
if (_currentEffectScope) _currentEffectScope._cleanups.push(stop);
|
|
527
|
+
return stop;
|
|
358
528
|
}
|
|
359
529
|
/**
|
|
360
530
|
* Registers a callback to run after the component is mounted.
|
|
@@ -463,10 +633,14 @@ function provide(key, value) {
|
|
|
463
633
|
}
|
|
464
634
|
/**
|
|
465
635
|
* Injects a value provided by an ancestor component.
|
|
636
|
+
* Supports Vue 3's factory default pattern: `inject(key, () => expensiveDefault, true)`.
|
|
466
637
|
*/
|
|
467
|
-
function inject(key, defaultValue) {
|
|
638
|
+
function inject(key, defaultValue, treatDefaultAsFactory) {
|
|
468
639
|
const value = useContext(getOrCreateContext(key));
|
|
469
|
-
|
|
640
|
+
if (value !== void 0) return value;
|
|
641
|
+
if (defaultValue === void 0) return void 0;
|
|
642
|
+
if (treatDefaultAsFactory && typeof defaultValue === "function") return defaultValue();
|
|
643
|
+
return defaultValue;
|
|
470
644
|
}
|
|
471
645
|
/**
|
|
472
646
|
* Defines a component using Vue 3 Composition API style.
|
|
@@ -475,7 +649,16 @@ function inject(key, defaultValue) {
|
|
|
475
649
|
function defineComponent(options) {
|
|
476
650
|
if (typeof options === "function") return options;
|
|
477
651
|
const comp = (props) => {
|
|
478
|
-
const
|
|
652
|
+
const children = props.children;
|
|
653
|
+
const setupCtx = {
|
|
654
|
+
emit: (event, ...args) => {
|
|
655
|
+
const handler = props[`on${event.charAt(0).toUpperCase()}${event.slice(1)}`];
|
|
656
|
+
if (typeof handler === "function") handler(...args);
|
|
657
|
+
},
|
|
658
|
+
slots: { default: children !== void 0 ? (() => children) : void 0 },
|
|
659
|
+
attrs: props
|
|
660
|
+
};
|
|
661
|
+
const result = options.setup(props, setupCtx);
|
|
479
662
|
if (typeof result === "function") return result();
|
|
480
663
|
return result;
|
|
481
664
|
};
|
|
@@ -483,16 +666,215 @@ function defineComponent(options) {
|
|
|
483
666
|
return comp;
|
|
484
667
|
}
|
|
485
668
|
/**
|
|
669
|
+
* Defines an async component that lazily loads on first use.
|
|
670
|
+
* Supports both a bare loader function and an options object with
|
|
671
|
+
* loadingComponent, errorComponent, delay, and timeout.
|
|
672
|
+
*
|
|
673
|
+
* Returns a ComponentFn with a `__loading` property for Suspense integration.
|
|
674
|
+
*/
|
|
675
|
+
function defineAsyncComponent(loader) {
|
|
676
|
+
const load = typeof loader === "function" ? loader : loader.loader;
|
|
677
|
+
const loaded = signal(null);
|
|
678
|
+
const error = signal(null);
|
|
679
|
+
let promise = null;
|
|
680
|
+
const startLoad = () => {
|
|
681
|
+
if (promise) return;
|
|
682
|
+
promise = load().then((mod) => loaded.set(mod.default), (err) => error.set(err instanceof Error ? err : new Error(String(err))));
|
|
683
|
+
};
|
|
684
|
+
const AsyncComp = ((props) => {
|
|
685
|
+
startLoad();
|
|
686
|
+
const err = error();
|
|
687
|
+
if (err) throw err;
|
|
688
|
+
const comp = loaded();
|
|
689
|
+
if (!comp) return null;
|
|
690
|
+
return comp(props);
|
|
691
|
+
});
|
|
692
|
+
AsyncComp.__loading = () => {
|
|
693
|
+
const isLoading = loaded() === null && error() === null;
|
|
694
|
+
if (isLoading) startLoad();
|
|
695
|
+
return isLoading;
|
|
696
|
+
};
|
|
697
|
+
return AsyncComp;
|
|
698
|
+
}
|
|
699
|
+
/**
|
|
486
700
|
* Creates a Pyreon application instance — Vue 3 `createApp()` compatible.
|
|
487
701
|
*/
|
|
488
702
|
function createApp(component, props) {
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
703
|
+
const provisions = [];
|
|
704
|
+
const app = {
|
|
705
|
+
mount(el) {
|
|
706
|
+
const container = typeof el === "string" ? document.querySelector(el) : el;
|
|
707
|
+
if (!container) throw new Error(`Cannot find mount target: ${el}`);
|
|
708
|
+
for (const { key, value } of provisions) {
|
|
709
|
+
const ctx = getOrCreateContext(key);
|
|
710
|
+
pushContext(new Map([[ctx.id, value]]));
|
|
711
|
+
}
|
|
712
|
+
return mount(pyreonH(component, props ?? null), container);
|
|
713
|
+
},
|
|
714
|
+
use(plugin) {
|
|
715
|
+
plugin.install(app);
|
|
716
|
+
return app;
|
|
717
|
+
},
|
|
718
|
+
provide(key, value) {
|
|
719
|
+
provisions.push({
|
|
720
|
+
key,
|
|
721
|
+
value
|
|
722
|
+
});
|
|
723
|
+
return app;
|
|
724
|
+
}
|
|
725
|
+
};
|
|
726
|
+
return app;
|
|
494
727
|
}
|
|
728
|
+
/**
|
|
729
|
+
* Returns `true` if the value was created by `reactive()`.
|
|
730
|
+
*/
|
|
731
|
+
function isReactive(value) {
|
|
732
|
+
return value !== null && typeof value === "object" && rawMap.has(value);
|
|
733
|
+
}
|
|
734
|
+
/**
|
|
735
|
+
* Returns `true` if the value was created by `readonly()`.
|
|
736
|
+
*/
|
|
737
|
+
function isReadonly(value) {
|
|
738
|
+
return value !== null && typeof value === "object" && value[V_IS_READONLY] === true;
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* Returns `true` if the value is either reactive or readonly.
|
|
742
|
+
*/
|
|
743
|
+
function isProxy(value) {
|
|
744
|
+
return isReactive(value) || isReadonly(value);
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* Marks an object so that `reactive()` will return it as-is (not wrapped).
|
|
748
|
+
*/
|
|
749
|
+
function markRaw(obj) {
|
|
750
|
+
obj[V_SKIP] = true;
|
|
751
|
+
return obj;
|
|
752
|
+
}
|
|
753
|
+
let _currentEffectScope = null;
|
|
754
|
+
/**
|
|
755
|
+
* Creates an effect scope that collects reactive effects for grouped disposal.
|
|
756
|
+
*
|
|
757
|
+
* @param detached - If true, the scope is not collected by a parent scope.
|
|
758
|
+
*/
|
|
759
|
+
function effectScope(detached) {
|
|
760
|
+
const cleanups = [];
|
|
761
|
+
let active = true;
|
|
762
|
+
const scope = {
|
|
763
|
+
get active() {
|
|
764
|
+
return active;
|
|
765
|
+
},
|
|
766
|
+
run(fn) {
|
|
767
|
+
if (!active) return void 0;
|
|
768
|
+
const prev = _currentEffectScope;
|
|
769
|
+
_currentEffectScope = scope;
|
|
770
|
+
try {
|
|
771
|
+
return fn();
|
|
772
|
+
} finally {
|
|
773
|
+
_currentEffectScope = prev;
|
|
774
|
+
}
|
|
775
|
+
},
|
|
776
|
+
stop() {
|
|
777
|
+
if (!active) return;
|
|
778
|
+
active = false;
|
|
779
|
+
for (const fn of cleanups) fn();
|
|
780
|
+
cleanups.length = 0;
|
|
781
|
+
}
|
|
782
|
+
};
|
|
783
|
+
if (!detached && _currentEffectScope) {
|
|
784
|
+
const parentCleanups = _currentEffectScope._cleanups;
|
|
785
|
+
if (parentCleanups) parentCleanups.push(() => scope.stop());
|
|
786
|
+
}
|
|
787
|
+
scope._cleanups = cleanups;
|
|
788
|
+
return scope;
|
|
789
|
+
}
|
|
790
|
+
/**
|
|
791
|
+
* Returns the current active effect scope, or undefined if none.
|
|
792
|
+
*/
|
|
793
|
+
function getCurrentScope() {
|
|
794
|
+
return _currentEffectScope ?? void 0;
|
|
795
|
+
}
|
|
796
|
+
/**
|
|
797
|
+
* Registers a cleanup function on the current effect scope.
|
|
798
|
+
*/
|
|
799
|
+
function onScopeDispose(fn) {
|
|
800
|
+
if (_currentEffectScope) _currentEffectScope._cleanups.push(fn);
|
|
801
|
+
}
|
|
802
|
+
/**
|
|
803
|
+
* Registers an error capture handler.
|
|
804
|
+
* No direct equivalent in Pyreon — stored but not actively used.
|
|
805
|
+
*/
|
|
806
|
+
function onErrorCaptured(fn) {
|
|
807
|
+
const ctx = getCurrentCtx();
|
|
808
|
+
if (ctx) {
|
|
809
|
+
const idx = getHookIndex();
|
|
810
|
+
if (idx < ctx.hooks.length) return;
|
|
811
|
+
ctx.hooks[idx] = fn;
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Dev-only lifecycle hook — no-op in Pyreon.
|
|
816
|
+
*/
|
|
817
|
+
function onRenderTracked(_fn) {}
|
|
818
|
+
/**
|
|
819
|
+
* Dev-only lifecycle hook — no-op in Pyreon.
|
|
820
|
+
*/
|
|
821
|
+
function onRenderTriggered(_fn) {}
|
|
822
|
+
/**
|
|
823
|
+
* Teleport — renders children into a different DOM element.
|
|
824
|
+
* Maps to Pyreon's Portal.
|
|
825
|
+
*/
|
|
826
|
+
function Teleport(props) {
|
|
827
|
+
const target = typeof props.to === "string" ? document.querySelector(props.to) : props.to;
|
|
828
|
+
if (!target) return props.children ?? null;
|
|
829
|
+
return Portal({
|
|
830
|
+
target,
|
|
831
|
+
children: props.children ?? null
|
|
832
|
+
});
|
|
833
|
+
}
|
|
834
|
+
/**
|
|
835
|
+
* KeepAlive — not supported in Pyreon. Renders children as-is.
|
|
836
|
+
*/
|
|
837
|
+
function KeepAlive(props) {
|
|
838
|
+
return props.children ?? null;
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* Runs a watchEffect that flushes after DOM updates.
|
|
842
|
+
* In Pyreon, same as `watchEffect()`.
|
|
843
|
+
*/
|
|
844
|
+
function watchPostEffect(fn) {
|
|
845
|
+
return watchEffect(fn);
|
|
846
|
+
}
|
|
847
|
+
/**
|
|
848
|
+
* Runs a watchEffect that flushes synchronously.
|
|
849
|
+
* In Pyreon, same as `watchEffect()`.
|
|
850
|
+
*/
|
|
851
|
+
function watchSyncEffect(fn) {
|
|
852
|
+
return watchEffect(fn);
|
|
853
|
+
}
|
|
854
|
+
/**
|
|
855
|
+
* Creates a customized ref with explicit control over dependency tracking
|
|
856
|
+
* and update triggering.
|
|
857
|
+
*/
|
|
858
|
+
function customRef(factory) {
|
|
859
|
+
const s = signal(0);
|
|
860
|
+
const { get, set } = factory(() => {
|
|
861
|
+
s();
|
|
862
|
+
}, () => s.set(s.peek() + 1));
|
|
863
|
+
return {
|
|
864
|
+
[V_IS_REF]: true,
|
|
865
|
+
get value() {
|
|
866
|
+
return get();
|
|
867
|
+
},
|
|
868
|
+
set value(v) {
|
|
869
|
+
set(v);
|
|
870
|
+
}
|
|
871
|
+
};
|
|
872
|
+
}
|
|
873
|
+
/**
|
|
874
|
+
* Compatibility version string — indicates Vue 3 API compatibility.
|
|
875
|
+
*/
|
|
876
|
+
const version = "3.5.0-pyreon";
|
|
495
877
|
|
|
496
878
|
//#endregion
|
|
497
|
-
export { Fragment, batch, computed, createApp, defineComponent, pyreonH as h, inject, isRef, nextTick, onBeforeMount, onBeforeUnmount, onMounted, onUnmounted, onUpdated, provide, reactive, readonly, ref, shallowReactive, shallowRef, toRaw, toRef, toRefs, triggerRef, unref, watch, watchEffect };
|
|
879
|
+
export { Fragment, KeepAlive, Teleport, batch, computed, createApp, customRef, defineAsyncComponent, defineComponent, effectScope, getCurrentScope, pyreonH as h, inject, isProxy, isReactive, isReadonly, isRef, markRaw, nextTick, onBeforeMount, onBeforeUnmount, onErrorCaptured, onMounted, onRenderTracked, onRenderTriggered, onScopeDispose, onUnmounted, onUpdated, provide, reactive, readonly, ref, shallowReactive, shallowReadonly, shallowRef, toRaw, toRef, toRefs, toValue, triggerRef, unref, version, watch, watchEffect, watchPostEffect, watchSyncEffect };
|
|
498
880
|
//# sourceMappingURL=index.js.map
|
package/lib/jsx-runtime.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Fragment, h, onUnmount } from "@pyreon/core";
|
|
1
|
+
import { Fragment, h, isNativeCompat, onUnmount } from "@pyreon/core";
|
|
2
2
|
import { runUntracked, signal } from "@pyreon/reactivity";
|
|
3
3
|
|
|
4
4
|
//#region src/jsx-runtime.ts
|
|
@@ -80,10 +80,23 @@ function jsx(type, props, key) {
|
|
|
80
80
|
...rest,
|
|
81
81
|
key
|
|
82
82
|
} : rest;
|
|
83
|
-
if (typeof type === "function")
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
if (typeof type === "function") {
|
|
84
|
+
const componentProps = children !== void 0 ? {
|
|
85
|
+
...propsWithKey,
|
|
86
|
+
children
|
|
87
|
+
} : propsWithKey;
|
|
88
|
+
if (isNativeCompat(type)) return h(type, componentProps);
|
|
89
|
+
return h(wrapCompatComponent(type), componentProps);
|
|
90
|
+
}
|
|
91
|
+
if (typeof type === "string" && propsWithKey.ref != null) {
|
|
92
|
+
const r = propsWithKey.ref;
|
|
93
|
+
if (typeof r === "object" && r !== null && r[Symbol.for("__v_isRef")] === true) {
|
|
94
|
+
const vueRef = r;
|
|
95
|
+
propsWithKey.ref = (el) => {
|
|
96
|
+
vueRef.value = el;
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
}
|
|
87
100
|
return h(type, propsWithKey, ...children === void 0 ? [] : Array.isArray(children) ? children : [children]);
|
|
88
101
|
}
|
|
89
102
|
const jsxs = jsx;
|