@cajoa/core 0.13.0 → 0.14.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/dist/index.cjs +175 -1
- package/dist/index.d.cts +47 -8
- package/dist/index.d.ts +47 -8
- package/dist/index.js +169 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -20,10 +20,15 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
Dynamic: () => Dynamic,
|
|
23
24
|
ErrorBoundary: () => ErrorBoundary,
|
|
24
25
|
For: () => For,
|
|
25
26
|
Fragment: () => Fragment,
|
|
27
|
+
Match: () => Match,
|
|
28
|
+
Portal: () => Portal,
|
|
26
29
|
Show: () => Show,
|
|
30
|
+
Suspense: () => Suspense,
|
|
31
|
+
Switch: () => Switch,
|
|
27
32
|
batch: () => batch,
|
|
28
33
|
catchError: () => catchError,
|
|
29
34
|
createContext: () => createContext,
|
|
@@ -37,6 +42,7 @@ __export(index_exports, {
|
|
|
37
42
|
jsx: () => jsx,
|
|
38
43
|
jsxDEV: () => jsxDEV,
|
|
39
44
|
jsxs: () => jsxs,
|
|
45
|
+
lazy: () => lazy,
|
|
40
46
|
onCleanup: () => onCleanup,
|
|
41
47
|
onMount: () => onMount,
|
|
42
48
|
provide: () => provide,
|
|
@@ -48,12 +54,22 @@ __export(index_exports, {
|
|
|
48
54
|
module.exports = __toCommonJS(index_exports);
|
|
49
55
|
|
|
50
56
|
// src/dev.ts
|
|
57
|
+
var muted = 0;
|
|
51
58
|
function isDev() {
|
|
52
59
|
return globalThis.__CAJOA_DEV__ === true;
|
|
53
60
|
}
|
|
61
|
+
function quietly(fn) {
|
|
62
|
+
muted++;
|
|
63
|
+
try {
|
|
64
|
+
return fn();
|
|
65
|
+
} finally {
|
|
66
|
+
muted--;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
54
69
|
function warn(message) {
|
|
55
|
-
if (isDev() && typeof console !== "undefined")
|
|
70
|
+
if (muted === 0 && isDev() && typeof console !== "undefined") {
|
|
56
71
|
console.warn(`[cajoa] ${message}`);
|
|
72
|
+
}
|
|
57
73
|
}
|
|
58
74
|
function logError(message, error) {
|
|
59
75
|
if (isDev() && typeof console !== "undefined")
|
|
@@ -260,6 +276,13 @@ function createMemo(fn) {
|
|
|
260
276
|
return value;
|
|
261
277
|
}
|
|
262
278
|
|
|
279
|
+
// src/reactivity/suspense.ts
|
|
280
|
+
var SuspenseContext = createContext(null);
|
|
281
|
+
function trackPending() {
|
|
282
|
+
const state = quietly(() => useContext(SuspenseContext));
|
|
283
|
+
return state ? () => state.add() : void 0;
|
|
284
|
+
}
|
|
285
|
+
|
|
263
286
|
// src/reactivity/resource.ts
|
|
264
287
|
function isPromiseLike(value) {
|
|
265
288
|
return typeof value?.then === "function";
|
|
@@ -273,8 +296,12 @@ function createResource(a, b) {
|
|
|
273
296
|
const [loading, setLoading] = createSignal(false);
|
|
274
297
|
const [version, setVersion] = createSignal(0);
|
|
275
298
|
let run = 0;
|
|
299
|
+
const track = trackPending();
|
|
300
|
+
let release;
|
|
301
|
+
let settled = false;
|
|
276
302
|
const finish = (id, outcome) => {
|
|
277
303
|
if (id !== run) return;
|
|
304
|
+
settled = true;
|
|
278
305
|
batch(() => {
|
|
279
306
|
setLoading(false);
|
|
280
307
|
if ("error" in outcome) {
|
|
@@ -284,6 +311,8 @@ function createResource(a, b) {
|
|
|
284
311
|
setData(() => outcome.value);
|
|
285
312
|
}
|
|
286
313
|
});
|
|
314
|
+
release?.();
|
|
315
|
+
release = void 0;
|
|
287
316
|
};
|
|
288
317
|
createEffect(() => {
|
|
289
318
|
const s = source();
|
|
@@ -292,6 +321,8 @@ function createResource(a, b) {
|
|
|
292
321
|
const id = run;
|
|
293
322
|
onCleanup(() => {
|
|
294
323
|
run++;
|
|
324
|
+
release?.();
|
|
325
|
+
release = void 0;
|
|
295
326
|
});
|
|
296
327
|
if (s === false || s === null || s === void 0) {
|
|
297
328
|
batch(() => {
|
|
@@ -301,6 +332,7 @@ function createResource(a, b) {
|
|
|
301
332
|
});
|
|
302
333
|
return;
|
|
303
334
|
}
|
|
335
|
+
if (!settled && track && !release) release = track();
|
|
304
336
|
setLoading(true);
|
|
305
337
|
setFailure(null);
|
|
306
338
|
let result;
|
|
@@ -537,6 +569,32 @@ function ErrorBoundary(props) {
|
|
|
537
569
|
};
|
|
538
570
|
}
|
|
539
571
|
|
|
572
|
+
// src/components/switch.ts
|
|
573
|
+
function resolve3(value) {
|
|
574
|
+
return typeof value === "function" ? value() : value;
|
|
575
|
+
}
|
|
576
|
+
function Match(props) {
|
|
577
|
+
return { __match: true, when: props.when, children: props.children };
|
|
578
|
+
}
|
|
579
|
+
var isMatch = (value) => typeof value === "object" && value !== null && value.__match === true;
|
|
580
|
+
function Switch(props) {
|
|
581
|
+
const matches = [props.children].flat(Infinity).filter(isMatch);
|
|
582
|
+
const selected = createMemo(() => {
|
|
583
|
+
for (let i = 0; i < matches.length; i++) {
|
|
584
|
+
if (resolve3(matches[i].when)) return i;
|
|
585
|
+
}
|
|
586
|
+
return -1;
|
|
587
|
+
});
|
|
588
|
+
return () => {
|
|
589
|
+
const i = selected();
|
|
590
|
+
return untrack(
|
|
591
|
+
() => resolve3(
|
|
592
|
+
i === -1 ? props.fallback ?? null : matches[i].children ?? null
|
|
593
|
+
)
|
|
594
|
+
);
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
|
|
540
598
|
// src/jsx-runtime.ts
|
|
541
599
|
function jsx(type, props) {
|
|
542
600
|
if (typeof type === "function") return type(props ?? {});
|
|
@@ -551,12 +609,127 @@ function Fragment(props) {
|
|
|
551
609
|
appendChildren(frag, props.children === void 0 ? [] : [props.children]);
|
|
552
610
|
return frag;
|
|
553
611
|
}
|
|
612
|
+
|
|
613
|
+
// src/components/dynamic.ts
|
|
614
|
+
function Dynamic(props) {
|
|
615
|
+
const { is, ...rest } = props;
|
|
616
|
+
const read = typeof is === "function" ? is : () => is;
|
|
617
|
+
return () => {
|
|
618
|
+
const target = read();
|
|
619
|
+
if (target == null || target === false) return null;
|
|
620
|
+
if (typeof target !== "string" && typeof target !== "function") {
|
|
621
|
+
throw new Error(
|
|
622
|
+
`<Dynamic>: \`is\` must be a tag name, or a function that returns a tag name or a component (got ${typeof target}). To render a component directly, write is={() => MyComponent}.`
|
|
623
|
+
);
|
|
624
|
+
}
|
|
625
|
+
return untrack(() => jsx(target, rest));
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// src/components/portal.ts
|
|
630
|
+
function resolve4(value) {
|
|
631
|
+
return typeof value === "function" ? value() : value;
|
|
632
|
+
}
|
|
633
|
+
function Portal(props) {
|
|
634
|
+
const r = getRenderer();
|
|
635
|
+
const mount = props.mount ?? r.portalRoot?.();
|
|
636
|
+
if (!mount) {
|
|
637
|
+
throw new Error(
|
|
638
|
+
"<Portal>: nowhere to render into. Pass a `mount` element (this renderer has no default)."
|
|
639
|
+
);
|
|
640
|
+
}
|
|
641
|
+
const start = r.createMarker();
|
|
642
|
+
const end = r.createMarker();
|
|
643
|
+
r.insert(mount, start);
|
|
644
|
+
r.insert(
|
|
645
|
+
mount,
|
|
646
|
+
materialize(() => resolve4(props.children ?? null))
|
|
647
|
+
);
|
|
648
|
+
r.insert(mount, end);
|
|
649
|
+
onCleanup(() => {
|
|
650
|
+
let node = r.nextSibling(start);
|
|
651
|
+
while (node && node !== end) {
|
|
652
|
+
const next = r.nextSibling(node);
|
|
653
|
+
r.remove(node);
|
|
654
|
+
node = next;
|
|
655
|
+
}
|
|
656
|
+
r.remove(start);
|
|
657
|
+
r.remove(end);
|
|
658
|
+
});
|
|
659
|
+
return null;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
// src/components/suspense.ts
|
|
663
|
+
function resolve5(value) {
|
|
664
|
+
return typeof value === "function" ? value() : value;
|
|
665
|
+
}
|
|
666
|
+
function Suspense(props) {
|
|
667
|
+
const [pending2, setPending] = createSignal(0);
|
|
668
|
+
const [ready, setReady] = createSignal(false);
|
|
669
|
+
const state = {
|
|
670
|
+
add() {
|
|
671
|
+
setPending((n) => n + 1);
|
|
672
|
+
let released = false;
|
|
673
|
+
return () => {
|
|
674
|
+
if (released) return;
|
|
675
|
+
released = true;
|
|
676
|
+
setPending((n) => n - 1);
|
|
677
|
+
};
|
|
678
|
+
}
|
|
679
|
+
};
|
|
680
|
+
const content = untrack(
|
|
681
|
+
() => provide(
|
|
682
|
+
SuspenseContext,
|
|
683
|
+
state,
|
|
684
|
+
() => materialize(resolve5(props.children ?? null))
|
|
685
|
+
)
|
|
686
|
+
);
|
|
687
|
+
createEffect(() => {
|
|
688
|
+
if (pending2() === 0) setReady(true);
|
|
689
|
+
});
|
|
690
|
+
return () => ready() ? content : untrack(() => resolve5(props.fallback ?? null));
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
// src/components/lazy.ts
|
|
694
|
+
function lazy(loader) {
|
|
695
|
+
let promise;
|
|
696
|
+
let component;
|
|
697
|
+
let failure = null;
|
|
698
|
+
const load = () => promise ??= loader().then(
|
|
699
|
+
(module2) => {
|
|
700
|
+
component = typeof module2 === "function" ? module2 : module2.default;
|
|
701
|
+
},
|
|
702
|
+
(error) => {
|
|
703
|
+
failure = { error };
|
|
704
|
+
}
|
|
705
|
+
);
|
|
706
|
+
return function LazyComponent(props) {
|
|
707
|
+
if (component) return component(props);
|
|
708
|
+
if (failure) throw failure.error;
|
|
709
|
+
const release = trackPending()?.();
|
|
710
|
+
const [done, setDone] = createSignal(false);
|
|
711
|
+
load().then(() => {
|
|
712
|
+
setDone(true);
|
|
713
|
+
release?.();
|
|
714
|
+
});
|
|
715
|
+
return () => {
|
|
716
|
+
done();
|
|
717
|
+
if (failure) throw failure.error;
|
|
718
|
+
return component ? untrack(() => component(props)) : null;
|
|
719
|
+
};
|
|
720
|
+
};
|
|
721
|
+
}
|
|
554
722
|
// Annotate the CommonJS export names for ESM import in node:
|
|
555
723
|
0 && (module.exports = {
|
|
724
|
+
Dynamic,
|
|
556
725
|
ErrorBoundary,
|
|
557
726
|
For,
|
|
558
727
|
Fragment,
|
|
728
|
+
Match,
|
|
729
|
+
Portal,
|
|
559
730
|
Show,
|
|
731
|
+
Suspense,
|
|
732
|
+
Switch,
|
|
560
733
|
batch,
|
|
561
734
|
catchError,
|
|
562
735
|
createContext,
|
|
@@ -570,6 +743,7 @@ function Fragment(props) {
|
|
|
570
743
|
jsx,
|
|
571
744
|
jsxDEV,
|
|
572
745
|
jsxs,
|
|
746
|
+
lazy,
|
|
573
747
|
onCleanup,
|
|
574
748
|
onMount,
|
|
575
749
|
provide,
|
package/dist/index.d.cts
CHANGED
|
@@ -41,6 +41,7 @@ interface Renderer<N = any> {
|
|
|
41
41
|
remove(node: N): void;
|
|
42
42
|
nextSibling(node: N): N | null;
|
|
43
43
|
parentNode(node: N): N | null;
|
|
44
|
+
portalRoot?(): N;
|
|
44
45
|
clear(parent: N): void;
|
|
45
46
|
setProp(el: N, name: string, value: unknown): void;
|
|
46
47
|
}
|
|
@@ -50,11 +51,11 @@ declare function h(tag: string, props: Record<string, any> | null, ...children:
|
|
|
50
51
|
|
|
51
52
|
declare function render(component: () => HostNode, container: HostNode): () => void;
|
|
52
53
|
|
|
53
|
-
type Lazy$
|
|
54
|
+
type Lazy$4<T> = T | (() => T);
|
|
54
55
|
declare function Show<T>(props: {
|
|
55
|
-
when: Lazy$
|
|
56
|
-
children?: Lazy$
|
|
57
|
-
fallback?: Lazy$
|
|
56
|
+
when: Lazy$4<T>;
|
|
57
|
+
children?: Lazy$4<Child>;
|
|
58
|
+
fallback?: Lazy$4<Child>;
|
|
58
59
|
}): () => string | number | boolean | object | null;
|
|
59
60
|
|
|
60
61
|
declare function For<T>(props: {
|
|
@@ -63,13 +64,51 @@ declare function For<T>(props: {
|
|
|
63
64
|
key?: (item: T, index: number) => unknown;
|
|
64
65
|
}): () => object[];
|
|
65
66
|
|
|
66
|
-
type Lazy<T> = T | (() => T);
|
|
67
|
+
type Lazy$3<T> = T | (() => T);
|
|
67
68
|
declare function ErrorBoundary(props: {
|
|
68
69
|
fallback: Child | ((error: unknown, reset: () => void) => Child);
|
|
69
|
-
children?: Lazy<Child>;
|
|
70
|
+
children?: Lazy$3<Child>;
|
|
70
71
|
onError?: (error: unknown) => void;
|
|
71
72
|
}): () => unknown;
|
|
72
73
|
|
|
74
|
+
type Lazy$2<T> = T | (() => T);
|
|
75
|
+
interface MatchDef {
|
|
76
|
+
__match: true;
|
|
77
|
+
when: Lazy$2<unknown>;
|
|
78
|
+
children?: Lazy$2<Child>;
|
|
79
|
+
}
|
|
80
|
+
declare function Match(props: {
|
|
81
|
+
when: Lazy$2<unknown>;
|
|
82
|
+
children?: Lazy$2<Child>;
|
|
83
|
+
}): MatchDef;
|
|
84
|
+
declare function Switch(props: {
|
|
85
|
+
fallback?: Lazy$2<Child>;
|
|
86
|
+
children?: unknown;
|
|
87
|
+
}): () => string | number | boolean | object | null;
|
|
88
|
+
|
|
89
|
+
type Target = string | ((props: any) => unknown) | null | undefined | false;
|
|
90
|
+
declare function Dynamic(props: {
|
|
91
|
+
is: Target | (() => Target);
|
|
92
|
+
[key: string]: unknown;
|
|
93
|
+
}): () => any;
|
|
94
|
+
|
|
95
|
+
type Lazy$1<T> = T | (() => T);
|
|
96
|
+
declare function Portal(props: {
|
|
97
|
+
mount?: HostNode;
|
|
98
|
+
children?: Lazy$1<Child>;
|
|
99
|
+
}): null;
|
|
100
|
+
|
|
101
|
+
type Lazy<T> = T | (() => T);
|
|
102
|
+
declare function Suspense(props: {
|
|
103
|
+
fallback?: Lazy<Child>;
|
|
104
|
+
children?: Lazy<Child>;
|
|
105
|
+
}): () => unknown;
|
|
106
|
+
|
|
107
|
+
type Component<P> = (props: P) => unknown;
|
|
108
|
+
declare function lazy<P = Record<string, unknown>>(loader: () => Promise<{
|
|
109
|
+
default: Component<P>;
|
|
110
|
+
} | Component<P>>): Component<P>;
|
|
111
|
+
|
|
73
112
|
declare function jsx(type: any, props: Record<string, any> | null): any;
|
|
74
113
|
declare const jsxs: typeof jsx;
|
|
75
114
|
declare const jsxDEV: typeof jsx;
|
|
@@ -89,5 +128,5 @@ declare function Fragment(props: {
|
|
|
89
128
|
declare function setRenderer(renderer: Renderer): void;
|
|
90
129
|
declare function getRenderer(): Renderer;
|
|
91
130
|
|
|
92
|
-
export { ErrorBoundary, For, Fragment, JSX, Show, batch, catchError, createContext, createEffect, createMemo, createResource, createRoot, createSignal, getRenderer, h, jsx, jsxDEV, jsxs, onCleanup, onMount, provide, render, setRenderer, untrack, useContext };
|
|
93
|
-
export type { Child, Context, HostNode, Renderer, Resource, ResourceActions };
|
|
131
|
+
export { Dynamic, ErrorBoundary, For, Fragment, JSX, Match, Portal, Show, Suspense, Switch, batch, catchError, createContext, createEffect, createMemo, createResource, createRoot, createSignal, getRenderer, h, jsx, jsxDEV, jsxs, lazy, onCleanup, onMount, provide, render, setRenderer, untrack, useContext };
|
|
132
|
+
export type { Child, Context, HostNode, MatchDef, Renderer, Resource, ResourceActions };
|
package/dist/index.d.ts
CHANGED
|
@@ -41,6 +41,7 @@ interface Renderer<N = any> {
|
|
|
41
41
|
remove(node: N): void;
|
|
42
42
|
nextSibling(node: N): N | null;
|
|
43
43
|
parentNode(node: N): N | null;
|
|
44
|
+
portalRoot?(): N;
|
|
44
45
|
clear(parent: N): void;
|
|
45
46
|
setProp(el: N, name: string, value: unknown): void;
|
|
46
47
|
}
|
|
@@ -50,11 +51,11 @@ declare function h(tag: string, props: Record<string, any> | null, ...children:
|
|
|
50
51
|
|
|
51
52
|
declare function render(component: () => HostNode, container: HostNode): () => void;
|
|
52
53
|
|
|
53
|
-
type Lazy$
|
|
54
|
+
type Lazy$4<T> = T | (() => T);
|
|
54
55
|
declare function Show<T>(props: {
|
|
55
|
-
when: Lazy$
|
|
56
|
-
children?: Lazy$
|
|
57
|
-
fallback?: Lazy$
|
|
56
|
+
when: Lazy$4<T>;
|
|
57
|
+
children?: Lazy$4<Child>;
|
|
58
|
+
fallback?: Lazy$4<Child>;
|
|
58
59
|
}): () => string | number | boolean | object | null;
|
|
59
60
|
|
|
60
61
|
declare function For<T>(props: {
|
|
@@ -63,13 +64,51 @@ declare function For<T>(props: {
|
|
|
63
64
|
key?: (item: T, index: number) => unknown;
|
|
64
65
|
}): () => object[];
|
|
65
66
|
|
|
66
|
-
type Lazy<T> = T | (() => T);
|
|
67
|
+
type Lazy$3<T> = T | (() => T);
|
|
67
68
|
declare function ErrorBoundary(props: {
|
|
68
69
|
fallback: Child | ((error: unknown, reset: () => void) => Child);
|
|
69
|
-
children?: Lazy<Child>;
|
|
70
|
+
children?: Lazy$3<Child>;
|
|
70
71
|
onError?: (error: unknown) => void;
|
|
71
72
|
}): () => unknown;
|
|
72
73
|
|
|
74
|
+
type Lazy$2<T> = T | (() => T);
|
|
75
|
+
interface MatchDef {
|
|
76
|
+
__match: true;
|
|
77
|
+
when: Lazy$2<unknown>;
|
|
78
|
+
children?: Lazy$2<Child>;
|
|
79
|
+
}
|
|
80
|
+
declare function Match(props: {
|
|
81
|
+
when: Lazy$2<unknown>;
|
|
82
|
+
children?: Lazy$2<Child>;
|
|
83
|
+
}): MatchDef;
|
|
84
|
+
declare function Switch(props: {
|
|
85
|
+
fallback?: Lazy$2<Child>;
|
|
86
|
+
children?: unknown;
|
|
87
|
+
}): () => string | number | boolean | object | null;
|
|
88
|
+
|
|
89
|
+
type Target = string | ((props: any) => unknown) | null | undefined | false;
|
|
90
|
+
declare function Dynamic(props: {
|
|
91
|
+
is: Target | (() => Target);
|
|
92
|
+
[key: string]: unknown;
|
|
93
|
+
}): () => any;
|
|
94
|
+
|
|
95
|
+
type Lazy$1<T> = T | (() => T);
|
|
96
|
+
declare function Portal(props: {
|
|
97
|
+
mount?: HostNode;
|
|
98
|
+
children?: Lazy$1<Child>;
|
|
99
|
+
}): null;
|
|
100
|
+
|
|
101
|
+
type Lazy<T> = T | (() => T);
|
|
102
|
+
declare function Suspense(props: {
|
|
103
|
+
fallback?: Lazy<Child>;
|
|
104
|
+
children?: Lazy<Child>;
|
|
105
|
+
}): () => unknown;
|
|
106
|
+
|
|
107
|
+
type Component<P> = (props: P) => unknown;
|
|
108
|
+
declare function lazy<P = Record<string, unknown>>(loader: () => Promise<{
|
|
109
|
+
default: Component<P>;
|
|
110
|
+
} | Component<P>>): Component<P>;
|
|
111
|
+
|
|
73
112
|
declare function jsx(type: any, props: Record<string, any> | null): any;
|
|
74
113
|
declare const jsxs: typeof jsx;
|
|
75
114
|
declare const jsxDEV: typeof jsx;
|
|
@@ -89,5 +128,5 @@ declare function Fragment(props: {
|
|
|
89
128
|
declare function setRenderer(renderer: Renderer): void;
|
|
90
129
|
declare function getRenderer(): Renderer;
|
|
91
130
|
|
|
92
|
-
export { ErrorBoundary, For, Fragment, JSX, Show, batch, catchError, createContext, createEffect, createMemo, createResource, createRoot, createSignal, getRenderer, h, jsx, jsxDEV, jsxs, onCleanup, onMount, provide, render, setRenderer, untrack, useContext };
|
|
93
|
-
export type { Child, Context, HostNode, Renderer, Resource, ResourceActions };
|
|
131
|
+
export { Dynamic, ErrorBoundary, For, Fragment, JSX, Match, Portal, Show, Suspense, Switch, batch, catchError, createContext, createEffect, createMemo, createResource, createRoot, createSignal, getRenderer, h, jsx, jsxDEV, jsxs, lazy, onCleanup, onMount, provide, render, setRenderer, untrack, useContext };
|
|
132
|
+
export type { Child, Context, HostNode, MatchDef, Renderer, Resource, ResourceActions };
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
// src/dev.ts
|
|
2
|
+
var muted = 0;
|
|
2
3
|
function isDev() {
|
|
3
4
|
return globalThis.__CAJOA_DEV__ === true;
|
|
4
5
|
}
|
|
6
|
+
function quietly(fn) {
|
|
7
|
+
muted++;
|
|
8
|
+
try {
|
|
9
|
+
return fn();
|
|
10
|
+
} finally {
|
|
11
|
+
muted--;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
5
14
|
function warn(message) {
|
|
6
|
-
if (isDev() && typeof console !== "undefined")
|
|
15
|
+
if (muted === 0 && isDev() && typeof console !== "undefined") {
|
|
7
16
|
console.warn(`[cajoa] ${message}`);
|
|
17
|
+
}
|
|
8
18
|
}
|
|
9
19
|
function logError(message, error) {
|
|
10
20
|
if (isDev() && typeof console !== "undefined")
|
|
@@ -211,6 +221,13 @@ function createMemo(fn) {
|
|
|
211
221
|
return value;
|
|
212
222
|
}
|
|
213
223
|
|
|
224
|
+
// src/reactivity/suspense.ts
|
|
225
|
+
var SuspenseContext = createContext(null);
|
|
226
|
+
function trackPending() {
|
|
227
|
+
const state = quietly(() => useContext(SuspenseContext));
|
|
228
|
+
return state ? () => state.add() : void 0;
|
|
229
|
+
}
|
|
230
|
+
|
|
214
231
|
// src/reactivity/resource.ts
|
|
215
232
|
function isPromiseLike(value) {
|
|
216
233
|
return typeof value?.then === "function";
|
|
@@ -224,8 +241,12 @@ function createResource(a, b) {
|
|
|
224
241
|
const [loading, setLoading] = createSignal(false);
|
|
225
242
|
const [version, setVersion] = createSignal(0);
|
|
226
243
|
let run = 0;
|
|
244
|
+
const track = trackPending();
|
|
245
|
+
let release;
|
|
246
|
+
let settled = false;
|
|
227
247
|
const finish = (id, outcome) => {
|
|
228
248
|
if (id !== run) return;
|
|
249
|
+
settled = true;
|
|
229
250
|
batch(() => {
|
|
230
251
|
setLoading(false);
|
|
231
252
|
if ("error" in outcome) {
|
|
@@ -235,6 +256,8 @@ function createResource(a, b) {
|
|
|
235
256
|
setData(() => outcome.value);
|
|
236
257
|
}
|
|
237
258
|
});
|
|
259
|
+
release?.();
|
|
260
|
+
release = void 0;
|
|
238
261
|
};
|
|
239
262
|
createEffect(() => {
|
|
240
263
|
const s = source();
|
|
@@ -243,6 +266,8 @@ function createResource(a, b) {
|
|
|
243
266
|
const id = run;
|
|
244
267
|
onCleanup(() => {
|
|
245
268
|
run++;
|
|
269
|
+
release?.();
|
|
270
|
+
release = void 0;
|
|
246
271
|
});
|
|
247
272
|
if (s === false || s === null || s === void 0) {
|
|
248
273
|
batch(() => {
|
|
@@ -252,6 +277,7 @@ function createResource(a, b) {
|
|
|
252
277
|
});
|
|
253
278
|
return;
|
|
254
279
|
}
|
|
280
|
+
if (!settled && track && !release) release = track();
|
|
255
281
|
setLoading(true);
|
|
256
282
|
setFailure(null);
|
|
257
283
|
let result;
|
|
@@ -488,6 +514,32 @@ function ErrorBoundary(props) {
|
|
|
488
514
|
};
|
|
489
515
|
}
|
|
490
516
|
|
|
517
|
+
// src/components/switch.ts
|
|
518
|
+
function resolve3(value) {
|
|
519
|
+
return typeof value === "function" ? value() : value;
|
|
520
|
+
}
|
|
521
|
+
function Match(props) {
|
|
522
|
+
return { __match: true, when: props.when, children: props.children };
|
|
523
|
+
}
|
|
524
|
+
var isMatch = (value) => typeof value === "object" && value !== null && value.__match === true;
|
|
525
|
+
function Switch(props) {
|
|
526
|
+
const matches = [props.children].flat(Infinity).filter(isMatch);
|
|
527
|
+
const selected = createMemo(() => {
|
|
528
|
+
for (let i = 0; i < matches.length; i++) {
|
|
529
|
+
if (resolve3(matches[i].when)) return i;
|
|
530
|
+
}
|
|
531
|
+
return -1;
|
|
532
|
+
});
|
|
533
|
+
return () => {
|
|
534
|
+
const i = selected();
|
|
535
|
+
return untrack(
|
|
536
|
+
() => resolve3(
|
|
537
|
+
i === -1 ? props.fallback ?? null : matches[i].children ?? null
|
|
538
|
+
)
|
|
539
|
+
);
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
|
|
491
543
|
// src/jsx-runtime.ts
|
|
492
544
|
function jsx(type, props) {
|
|
493
545
|
if (typeof type === "function") return type(props ?? {});
|
|
@@ -502,11 +554,126 @@ function Fragment(props) {
|
|
|
502
554
|
appendChildren(frag, props.children === void 0 ? [] : [props.children]);
|
|
503
555
|
return frag;
|
|
504
556
|
}
|
|
557
|
+
|
|
558
|
+
// src/components/dynamic.ts
|
|
559
|
+
function Dynamic(props) {
|
|
560
|
+
const { is, ...rest } = props;
|
|
561
|
+
const read = typeof is === "function" ? is : () => is;
|
|
562
|
+
return () => {
|
|
563
|
+
const target = read();
|
|
564
|
+
if (target == null || target === false) return null;
|
|
565
|
+
if (typeof target !== "string" && typeof target !== "function") {
|
|
566
|
+
throw new Error(
|
|
567
|
+
`<Dynamic>: \`is\` must be a tag name, or a function that returns a tag name or a component (got ${typeof target}). To render a component directly, write is={() => MyComponent}.`
|
|
568
|
+
);
|
|
569
|
+
}
|
|
570
|
+
return untrack(() => jsx(target, rest));
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// src/components/portal.ts
|
|
575
|
+
function resolve4(value) {
|
|
576
|
+
return typeof value === "function" ? value() : value;
|
|
577
|
+
}
|
|
578
|
+
function Portal(props) {
|
|
579
|
+
const r = getRenderer();
|
|
580
|
+
const mount = props.mount ?? r.portalRoot?.();
|
|
581
|
+
if (!mount) {
|
|
582
|
+
throw new Error(
|
|
583
|
+
"<Portal>: nowhere to render into. Pass a `mount` element (this renderer has no default)."
|
|
584
|
+
);
|
|
585
|
+
}
|
|
586
|
+
const start = r.createMarker();
|
|
587
|
+
const end = r.createMarker();
|
|
588
|
+
r.insert(mount, start);
|
|
589
|
+
r.insert(
|
|
590
|
+
mount,
|
|
591
|
+
materialize(() => resolve4(props.children ?? null))
|
|
592
|
+
);
|
|
593
|
+
r.insert(mount, end);
|
|
594
|
+
onCleanup(() => {
|
|
595
|
+
let node = r.nextSibling(start);
|
|
596
|
+
while (node && node !== end) {
|
|
597
|
+
const next = r.nextSibling(node);
|
|
598
|
+
r.remove(node);
|
|
599
|
+
node = next;
|
|
600
|
+
}
|
|
601
|
+
r.remove(start);
|
|
602
|
+
r.remove(end);
|
|
603
|
+
});
|
|
604
|
+
return null;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
// src/components/suspense.ts
|
|
608
|
+
function resolve5(value) {
|
|
609
|
+
return typeof value === "function" ? value() : value;
|
|
610
|
+
}
|
|
611
|
+
function Suspense(props) {
|
|
612
|
+
const [pending2, setPending] = createSignal(0);
|
|
613
|
+
const [ready, setReady] = createSignal(false);
|
|
614
|
+
const state = {
|
|
615
|
+
add() {
|
|
616
|
+
setPending((n) => n + 1);
|
|
617
|
+
let released = false;
|
|
618
|
+
return () => {
|
|
619
|
+
if (released) return;
|
|
620
|
+
released = true;
|
|
621
|
+
setPending((n) => n - 1);
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
const content = untrack(
|
|
626
|
+
() => provide(
|
|
627
|
+
SuspenseContext,
|
|
628
|
+
state,
|
|
629
|
+
() => materialize(resolve5(props.children ?? null))
|
|
630
|
+
)
|
|
631
|
+
);
|
|
632
|
+
createEffect(() => {
|
|
633
|
+
if (pending2() === 0) setReady(true);
|
|
634
|
+
});
|
|
635
|
+
return () => ready() ? content : untrack(() => resolve5(props.fallback ?? null));
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
// src/components/lazy.ts
|
|
639
|
+
function lazy(loader) {
|
|
640
|
+
let promise;
|
|
641
|
+
let component;
|
|
642
|
+
let failure = null;
|
|
643
|
+
const load = () => promise ??= loader().then(
|
|
644
|
+
(module) => {
|
|
645
|
+
component = typeof module === "function" ? module : module.default;
|
|
646
|
+
},
|
|
647
|
+
(error) => {
|
|
648
|
+
failure = { error };
|
|
649
|
+
}
|
|
650
|
+
);
|
|
651
|
+
return function LazyComponent(props) {
|
|
652
|
+
if (component) return component(props);
|
|
653
|
+
if (failure) throw failure.error;
|
|
654
|
+
const release = trackPending()?.();
|
|
655
|
+
const [done, setDone] = createSignal(false);
|
|
656
|
+
load().then(() => {
|
|
657
|
+
setDone(true);
|
|
658
|
+
release?.();
|
|
659
|
+
});
|
|
660
|
+
return () => {
|
|
661
|
+
done();
|
|
662
|
+
if (failure) throw failure.error;
|
|
663
|
+
return component ? untrack(() => component(props)) : null;
|
|
664
|
+
};
|
|
665
|
+
};
|
|
666
|
+
}
|
|
505
667
|
export {
|
|
668
|
+
Dynamic,
|
|
506
669
|
ErrorBoundary,
|
|
507
670
|
For,
|
|
508
671
|
Fragment,
|
|
672
|
+
Match,
|
|
673
|
+
Portal,
|
|
509
674
|
Show,
|
|
675
|
+
Suspense,
|
|
676
|
+
Switch,
|
|
510
677
|
batch,
|
|
511
678
|
catchError,
|
|
512
679
|
createContext,
|
|
@@ -520,6 +687,7 @@ export {
|
|
|
520
687
|
jsx,
|
|
521
688
|
jsxDEV,
|
|
522
689
|
jsxs,
|
|
690
|
+
lazy,
|
|
523
691
|
onCleanup,
|
|
524
692
|
onMount,
|
|
525
693
|
provide,
|