autosuspense 0.1.14 → 1.0.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 +95 -21
- package/dist/components/suspense/AutoSuspense.d.ts.map +1 -1
- package/dist/components/suspense/AutoSuspense.js +4 -9
- package/dist/functions/Suspend.d.ts +4 -0
- package/dist/functions/Suspend.d.ts.map +1 -0
- package/dist/functions/Suspend.js +22 -0
- package/dist/functions/index.d.ts +3 -0
- package/dist/functions/index.d.ts.map +1 -0
- package/dist/functions/index.js +2 -0
- package/dist/hooks/index.d.ts +1 -3
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -3
- package/dist/hooks/useSuspenseBoundary.js +4 -4
- package/dist/hooks/useSuspenseFallback.d.ts.map +1 -1
- package/dist/hooks/useSuspenseFallback.js +5 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/types/FallbackRegistry.d.ts +5 -2
- package/dist/types/FallbackRegistry.d.ts.map +1 -1
- package/dist/utils/renderNode.d.ts.map +1 -1
- package/dist/utils/renderNode.js +3 -3
- package/package.json +1 -1
- package/src/components/suspense/AutoSuspense.tsx +6 -9
- package/src/functions/Suspend.tsx +33 -0
- package/src/functions/index.ts +2 -0
- package/src/hooks/index.ts +1 -3
- package/src/hooks/useSuspenseBoundary.ts +4 -4
- package/src/hooks/useSuspenseFallback.ts +5 -4
- package/src/index.ts +1 -0
- package/src/types/FallbackRegistry.ts +6 -2
- package/src/utils/renderNode.tsx +4 -7
- package/tsconfig.tsbuildinfo +1 -1
package/README.md
CHANGED
|
@@ -1,13 +1,49 @@
|
|
|
1
1
|
# AutoSupense Beta
|
|
2
|
-
AutoSuspense is a
|
|
3
|
-
Suspense fallback UI based on your component tree without manually wiring
|
|
4
|
-
nested fallback components.
|
|
2
|
+
AutoSuspense is a lightweight React utility that automatically composes Suspense fallback UI based on your component tree without manually wiring nested ```<Suspense>``` boundaries.
|
|
5
3
|
|
|
6
|
-
|
|
7
|
-
1. Install this library
|
|
8
|
-
```npm i autosuspense```
|
|
4
|
+
It lets you define fallback UI at the component level, while a parent ```<AutoSuspense>``` boundary handles rendering everything correctly.
|
|
9
5
|
|
|
10
|
-
|
|
6
|
+
## Why AutoSuspense?:
|
|
7
|
+
|
|
8
|
+
React Suspense solves async rendering, but fallback composition quickly becomes messy:
|
|
9
|
+
```
|
|
10
|
+
<Suspense fallback={<PageSkeleton />}>
|
|
11
|
+
<Header />
|
|
12
|
+
<Suspense fallback={<FeedSkeleton />}>
|
|
13
|
+
<Feed />
|
|
14
|
+
</Suspense>
|
|
15
|
+
</Suspense>
|
|
16
|
+
```
|
|
17
|
+
AutoSuspense removes that boilerplate:
|
|
18
|
+
```
|
|
19
|
+
<AutoSuspense>
|
|
20
|
+
<Page />
|
|
21
|
+
</AutoSuspense>
|
|
22
|
+
```
|
|
23
|
+
Each component defines it's own fallback and autosuspense builds the fallback tree for you.
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
import { Suspend } from "autosuspense";
|
|
27
|
+
import Feed from "./Feed";
|
|
28
|
+
import Sidebar from "./Sidebar";
|
|
29
|
+
|
|
30
|
+
function Page() {
|
|
31
|
+
return (
|
|
32
|
+
<div>
|
|
33
|
+
<Feed />
|
|
34
|
+
<Sidebar />
|
|
35
|
+
</div>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default Suspend(Page, <div>Loading page...</div>);
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Installation:
|
|
43
|
+
```npm install autosuspense```
|
|
44
|
+
|
|
45
|
+
Usage
|
|
46
|
+
1. Add AutoSuspense boundary
|
|
11
47
|
```
|
|
12
48
|
import { AutoSuspense } from "autosuspense";
|
|
13
49
|
|
|
@@ -19,24 +55,62 @@ function App() {
|
|
|
19
55
|
);
|
|
20
56
|
}
|
|
21
57
|
```
|
|
58
|
+
2. Wrap components with Suspend
|
|
59
|
+
```
|
|
60
|
+
import { Suspend } from "autosuspense";
|
|
61
|
+
|
|
62
|
+
const UserCard = () => {
|
|
63
|
+
const data = resource.read(); // may suspend
|
|
64
|
+
return <div>{data.name}</div>;
|
|
65
|
+
};
|
|
22
66
|
|
|
23
|
-
|
|
67
|
+
export default Suspend(UserCard, <div>Loading user...</div>);
|
|
24
68
|
```
|
|
25
|
-
import { useSuspenseFallback } from "autosuspense";
|
|
26
69
|
|
|
27
|
-
|
|
28
|
-
|
|
70
|
+
3. Nested components automatically compose
|
|
71
|
+
```
|
|
72
|
+
const Parent = () => <Child />;
|
|
29
73
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
74
|
+
export default Suspend(Parent, <div>Big Loader...</div>);
|
|
75
|
+
const Child = () => {
|
|
76
|
+
const data = resource.read();
|
|
77
|
+
return <div>{data}</div>;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export default Suspend(Child, <div>Inner Loader...</div>);
|
|
81
|
+
```
|
|
82
|
+
👉 Resulting fallback:
|
|
83
|
+
```
|
|
84
|
+
Big Loader...
|
|
85
|
+
Inner Loader...
|
|
86
|
+
```
|
|
87
|
+
No manual fallback nesting required.
|
|
88
|
+
|
|
89
|
+
## Core Idea:
|
|
90
|
+
- Wrap a subtree with <AutoSuspense>.
|
|
91
|
+
- Wrap components with Suspend().
|
|
92
|
+
- Each component declares its fallback.
|
|
93
|
+
- AutoSuspense automatically composes the fallback UI tree without explicit maintaince and wiring.
|
|
94
|
+
|
|
95
|
+
## Fallback Options:
|
|
96
|
+
|
|
97
|
+
You can provide fallbacks in multiple ways:
|
|
98
|
+
|
|
99
|
+
1. JSX element:
|
|
100
|
+
```
|
|
101
|
+
Suspend(Component, <Skeleton />);
|
|
102
|
+
Component
|
|
103
|
+
Suspend(Component, SkeletonComponent);
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
2. Component:
|
|
107
|
+
```
|
|
108
|
+
Suspend(Component, SkeletonComponent);
|
|
33
109
|
```
|
|
34
110
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
111
|
+
3. String:
|
|
112
|
+
```
|
|
113
|
+
Suspend(Component, SkeletonComponent);
|
|
114
|
+
```
|
|
38
115
|
|
|
39
|
-
|
|
40
|
-
1. Adding Default Skeletons.
|
|
41
|
-
2. Supporting existing Library skeleton implementations.
|
|
42
|
-
3. Adding a central config & template extension components & file to easily extend and manage your Fallback UI.
|
|
116
|
+
AutoSuspense does not replace Suspense. It enhances fallback composition.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutoSuspense.d.ts","sourceRoot":"","sources":["../../../src/components/suspense/AutoSuspense.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAS/B,eAAO,MAAM,YAAY,
|
|
1
|
+
{"version":3,"file":"AutoSuspense.d.ts","sourceRoot":"","sources":["../../../src/components/suspense/AutoSuspense.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAS/B,eAAO,MAAM,YAAY,0BAGtB;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;CACxE,gBAkBA,CAAC"}
|
|
@@ -6,16 +6,11 @@ import { defaultPrefab } from "../prefabs/defaultPrefab";
|
|
|
6
6
|
export const AutoSuspense = ({ children, prefab = defaultPrefab, }) => {
|
|
7
7
|
const registryRef = React.useRef({
|
|
8
8
|
nodes: new Map(),
|
|
9
|
-
currentParent: null,
|
|
10
9
|
prebuild: new Map(Object.entries(prefab)),
|
|
11
10
|
});
|
|
12
|
-
if (registryRef.current === null) {
|
|
13
|
-
registryRef.current = {
|
|
14
|
-
nodes: new Map(),
|
|
15
|
-
currentParent: null,
|
|
16
|
-
prebuild: new Map(Object.entries(prefab)),
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
11
|
const fallback = _jsx(GeneratedFallback, { registry: registryRef.current });
|
|
20
|
-
return (_jsx(FallbackContext.Provider, { value:
|
|
12
|
+
return (_jsx(FallbackContext.Provider, { value: {
|
|
13
|
+
registry: registryRef.current,
|
|
14
|
+
parentId: null,
|
|
15
|
+
}, children: _jsx(React.Suspense, { fallback: fallback, children: children }) }));
|
|
21
16
|
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { FallbackDescriptor } from "../types/FallbackRegistry";
|
|
3
|
+
export declare function Suspend<T extends object>(Component: React.ComponentType<T>, fallback?: FallbackDescriptor): (props: T) => JSX.Element;
|
|
4
|
+
//# sourceMappingURL=Suspend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Suspend.d.ts","sourceRoot":"","sources":["../../src/functions/Suspend.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAmB,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAGhF,wBAAgB,OAAO,CAAC,CAAC,SAAS,MAAM,EACtC,SAAS,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,EACjC,QAAQ,CAAC,EAAE,kBAAkB,WAEE,CAAC,iBAwBjC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { FallbackContext } from "../types/FallbackRegistry";
|
|
4
|
+
import { useCompatId } from "../hooks/useCompatId";
|
|
5
|
+
export function Suspend(Component, fallback) {
|
|
6
|
+
return function Wrapped(props) {
|
|
7
|
+
const ctx = React.useContext(FallbackContext);
|
|
8
|
+
const id = useCompatId();
|
|
9
|
+
if (!ctx) {
|
|
10
|
+
return _jsx(Component, { ...props });
|
|
11
|
+
}
|
|
12
|
+
const { registry, parentId } = ctx;
|
|
13
|
+
if (!registry.nodes.has(id)) {
|
|
14
|
+
registry.nodes.set(id, {
|
|
15
|
+
id,
|
|
16
|
+
element: fallback ?? Component,
|
|
17
|
+
parent: parentId,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return (_jsx(FallbackContext.Provider, { value: { registry, parentId: id }, children: _jsx(Component, { ...props }) }));
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/functions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAC,OAAO,EAAC,CAAC"}
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC"}
|
package/dist/hooks/index.js
CHANGED
|
@@ -6,14 +6,14 @@ export function useSuspenseBoundary(element) {
|
|
|
6
6
|
const id = useCompatId();
|
|
7
7
|
if (!registry)
|
|
8
8
|
return;
|
|
9
|
-
if (registry.nodes.has(id))
|
|
9
|
+
if (registry.registry.nodes.has(id))
|
|
10
10
|
return;
|
|
11
|
-
const parentId = registry.
|
|
12
|
-
registry.nodes.set(id, {
|
|
11
|
+
const parentId = registry.parentId;
|
|
12
|
+
registry.registry.nodes.set(id, {
|
|
13
13
|
id,
|
|
14
14
|
element,
|
|
15
15
|
parent: parentId,
|
|
16
16
|
isBoundary: true,
|
|
17
17
|
});
|
|
18
|
-
registry.
|
|
18
|
+
registry.parentId = id;
|
|
19
19
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSuspenseFallback.d.ts","sourceRoot":"","sources":["../../src/hooks/useSuspenseFallback.ts"],"names":[],"mappings":"AACA,OAAO,EAAmB,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"useSuspenseFallback.d.ts","sourceRoot":"","sources":["../../src/hooks/useSuspenseFallback.ts"],"names":[],"mappings":"AACA,OAAO,EAAmB,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAIhF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAgBrE"}
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import { useContext } from "react";
|
|
2
2
|
import { FallbackContext } from "../types/FallbackRegistry";
|
|
3
3
|
import { useCompatId } from "./useCompatId";
|
|
4
|
+
// Depricated hook, core logic changed
|
|
4
5
|
export function useSuspenseFallback(element) {
|
|
5
6
|
const registry = useContext(FallbackContext);
|
|
6
7
|
const id = useCompatId();
|
|
7
8
|
if (!registry)
|
|
8
9
|
return;
|
|
9
|
-
if (registry.nodes.has(id))
|
|
10
|
+
if (registry.registry.nodes.has(id))
|
|
10
11
|
return;
|
|
11
|
-
const parentId = registry.
|
|
12
|
-
registry.nodes.set(id, {
|
|
12
|
+
const parentId = registry.parentId;
|
|
13
|
+
registry.registry.nodes.set(id, {
|
|
13
14
|
id,
|
|
14
15
|
element,
|
|
15
16
|
parent: parentId,
|
|
16
17
|
});
|
|
17
|
-
registry.
|
|
18
|
+
registry.parentId = id;
|
|
18
19
|
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,cAAc,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -7,9 +7,12 @@ export type Node = {
|
|
|
7
7
|
};
|
|
8
8
|
export type FallbackRegistry = {
|
|
9
9
|
nodes: Map<string, Node>;
|
|
10
|
-
currentParent: string | null;
|
|
11
10
|
prebuild: Map<string, React.ReactElement | React.ComponentType<any>>;
|
|
12
11
|
};
|
|
13
12
|
export type FallbackDescriptor = string | React.ReactElement | React.ComponentType;
|
|
14
|
-
export
|
|
13
|
+
export type FallbackContextValue = {
|
|
14
|
+
registry: FallbackRegistry;
|
|
15
|
+
parentId: string | null;
|
|
16
|
+
};
|
|
17
|
+
export declare const FallbackContext: React.Context<FallbackContextValue | null>;
|
|
15
18
|
//# sourceMappingURL=FallbackRegistry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FallbackRegistry.d.ts","sourceRoot":"","sources":["../../src/types/FallbackRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,MAAM,IAAI,GAAG;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,kBAAkB,CAAC;IAC5B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACzB,
|
|
1
|
+
{"version":3,"file":"FallbackRegistry.d.ts","sourceRoot":"","sources":["../../src/types/FallbackRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,MAAM,IAAI,GAAG;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,kBAAkB,CAAC;IAC5B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACzB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;CACtE,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAC1B,MAAM,GACN,KAAK,CAAC,YAAY,GAClB,KAAK,CAAC,aAAa,CAAC;AAExB,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC;AAEF,eAAO,MAAM,eAAe,4CAE3B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderNode.d.ts","sourceRoot":"","sources":["../../src/utils/renderNode.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"renderNode.d.ts","sourceRoot":"","sources":["../../src/utils/renderNode.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AACxC,OAAO,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,2BAA2B,CAAC;AAIxE,wBAAgB,UAAU,CACxB,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,GAAG,CAAC,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC,EACpC,QAAQ,EAAE,gBAAgB,GACzB,KAAK,CAAC,YAAY,GAAG,IAAI,CAkB3B"}
|
package/dist/utils/renderNode.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import React from "react";
|
|
2
|
+
import React, { Suspense } from "react";
|
|
3
3
|
import { resolveElement } from "./resolveElement";
|
|
4
|
-
import {
|
|
4
|
+
import { Block } from "../components/prefabs/prebuilt/Block";
|
|
5
5
|
export function renderNode(node, childMap, registry) {
|
|
6
6
|
const children = childMap.get(node.id) ?? [];
|
|
7
7
|
const resolvedEle = resolveElement(node.element, registry);
|
|
@@ -9,7 +9,7 @@ export function renderNode(node, childMap, registry) {
|
|
|
9
9
|
return null;
|
|
10
10
|
const renderedChildren = children.map((child) => renderNode(child, childMap, registry));
|
|
11
11
|
if (node.isBoundary) {
|
|
12
|
-
return (_jsx(
|
|
12
|
+
return (_jsx(Suspense, { fallback: _jsx(Block, {}), children: React.cloneElement(resolvedEle, {}, renderedChildren) }, node.id));
|
|
13
13
|
}
|
|
14
14
|
return React.cloneElement(resolvedEle, { key: node.id }, renderedChildren);
|
|
15
15
|
}
|
package/package.json
CHANGED
|
@@ -16,21 +16,18 @@ export const AutoSuspense = ({
|
|
|
16
16
|
}) => {
|
|
17
17
|
const registryRef = React.useRef<FallbackRegistry>({
|
|
18
18
|
nodes: new Map(),
|
|
19
|
-
currentParent: null,
|
|
20
19
|
prebuild: new Map(Object.entries(prefab)),
|
|
21
20
|
});
|
|
22
21
|
|
|
23
|
-
if (registryRef.current === null) {
|
|
24
|
-
registryRef.current = {
|
|
25
|
-
nodes: new Map(),
|
|
26
|
-
currentParent: null,
|
|
27
|
-
prebuild: new Map(Object.entries(prefab)),
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
22
|
const fallback = <GeneratedFallback registry={registryRef.current} />;
|
|
31
23
|
|
|
32
24
|
return (
|
|
33
|
-
<FallbackContext.Provider
|
|
25
|
+
<FallbackContext.Provider
|
|
26
|
+
value={{
|
|
27
|
+
registry: registryRef.current,
|
|
28
|
+
parentId: null,
|
|
29
|
+
}}
|
|
30
|
+
>
|
|
34
31
|
<React.Suspense fallback={fallback}>{children}</React.Suspense>
|
|
35
32
|
</FallbackContext.Provider>
|
|
36
33
|
);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { FallbackContext, FallbackDescriptor } from "../types/FallbackRegistry";
|
|
3
|
+
import { useCompatId } from "../hooks/useCompatId";
|
|
4
|
+
|
|
5
|
+
export function Suspend<T extends object>(
|
|
6
|
+
Component: React.ComponentType<T>,
|
|
7
|
+
fallback?: FallbackDescriptor,
|
|
8
|
+
) {
|
|
9
|
+
return function Wrapped(props: T) {
|
|
10
|
+
const ctx = React.useContext(FallbackContext);
|
|
11
|
+
const id = useCompatId();
|
|
12
|
+
|
|
13
|
+
if (!ctx) {
|
|
14
|
+
return <Component {...props} />;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const { registry, parentId } = ctx;
|
|
18
|
+
|
|
19
|
+
if (!registry.nodes.has(id)) {
|
|
20
|
+
registry.nodes.set(id, {
|
|
21
|
+
id,
|
|
22
|
+
element: fallback ?? (Component as React.ComponentType<any>),
|
|
23
|
+
parent: parentId,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<FallbackContext.Provider value={{ registry, parentId: id }}>
|
|
29
|
+
<Component {...props} />
|
|
30
|
+
</FallbackContext.Provider>
|
|
31
|
+
);
|
|
32
|
+
};
|
|
33
|
+
}
|
package/src/hooks/index.ts
CHANGED
|
@@ -7,16 +7,16 @@ export function useSuspenseBoundary(element: FallbackDescriptor): void {
|
|
|
7
7
|
const id = useCompatId();
|
|
8
8
|
|
|
9
9
|
if (!registry) return;
|
|
10
|
-
if (registry.nodes.has(id)) return;
|
|
10
|
+
if (registry.registry.nodes.has(id)) return;
|
|
11
11
|
|
|
12
|
-
const parentId = registry.
|
|
12
|
+
const parentId = registry.parentId;
|
|
13
13
|
|
|
14
|
-
registry.nodes.set(id, {
|
|
14
|
+
registry.registry.nodes.set(id, {
|
|
15
15
|
id,
|
|
16
16
|
element,
|
|
17
17
|
parent: parentId,
|
|
18
18
|
isBoundary: true,
|
|
19
19
|
});
|
|
20
20
|
|
|
21
|
-
registry.
|
|
21
|
+
registry.parentId = id;
|
|
22
22
|
}
|
|
@@ -2,20 +2,21 @@ import { useContext } from "react";
|
|
|
2
2
|
import { FallbackContext, FallbackDescriptor } from "../types/FallbackRegistry";
|
|
3
3
|
import { useCompatId } from "./useCompatId";
|
|
4
4
|
|
|
5
|
+
// Depricated hook, core logic changed
|
|
5
6
|
export function useSuspenseFallback(element: FallbackDescriptor): void {
|
|
6
7
|
const registry = useContext(FallbackContext);
|
|
7
8
|
const id = useCompatId();
|
|
8
9
|
|
|
9
10
|
if (!registry) return;
|
|
10
|
-
if (registry.nodes.has(id)) return;
|
|
11
|
+
if (registry.registry.nodes.has(id)) return;
|
|
11
12
|
|
|
12
|
-
const parentId = registry.
|
|
13
|
+
const parentId = registry.parentId;
|
|
13
14
|
|
|
14
|
-
registry.nodes.set(id, {
|
|
15
|
+
registry.registry.nodes.set(id, {
|
|
15
16
|
id,
|
|
16
17
|
element,
|
|
17
18
|
parent: parentId,
|
|
18
19
|
});
|
|
19
20
|
|
|
20
|
-
registry.
|
|
21
|
+
registry.parentId = id;
|
|
21
22
|
}
|
package/src/index.ts
CHANGED
|
@@ -9,7 +9,6 @@ export type Node = {
|
|
|
9
9
|
|
|
10
10
|
export type FallbackRegistry = {
|
|
11
11
|
nodes: Map<string, Node>;
|
|
12
|
-
currentParent: string | null;
|
|
13
12
|
prebuild: Map<string, React.ReactElement | React.ComponentType<any>>;
|
|
14
13
|
};
|
|
15
14
|
|
|
@@ -18,6 +17,11 @@ export type FallbackDescriptor =
|
|
|
18
17
|
| React.ReactElement
|
|
19
18
|
| React.ComponentType;
|
|
20
19
|
|
|
21
|
-
export
|
|
20
|
+
export type FallbackContextValue = {
|
|
21
|
+
registry: FallbackRegistry;
|
|
22
|
+
parentId: string | null;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const FallbackContext = React.createContext<FallbackContextValue | null>(
|
|
22
26
|
null,
|
|
23
27
|
);
|
package/src/utils/renderNode.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { Suspense } from "react";
|
|
2
2
|
import type { FallbackRegistry, Node } from "../types/FallbackRegistry";
|
|
3
3
|
import { resolveElement } from "./resolveElement";
|
|
4
|
-
import {
|
|
4
|
+
import { Block } from "../components/prefabs/prebuilt/Block";
|
|
5
5
|
|
|
6
6
|
export function renderNode(
|
|
7
7
|
node: Node,
|
|
@@ -18,12 +18,9 @@ export function renderNode(
|
|
|
18
18
|
|
|
19
19
|
if (node.isBoundary) {
|
|
20
20
|
return (
|
|
21
|
-
<
|
|
22
|
-
key={node.id}
|
|
23
|
-
prefab={Object.fromEntries(registry.prebuild)}
|
|
24
|
-
>
|
|
21
|
+
<Suspense key={node.id} fallback={<Block />}>
|
|
25
22
|
{React.cloneElement(resolvedEle, {}, renderedChildren)}
|
|
26
|
-
</
|
|
23
|
+
</Suspense>
|
|
27
24
|
);
|
|
28
25
|
}
|
|
29
26
|
|
package/tsconfig.tsbuildinfo
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["./src/index.ts","./src/components/index.ts","./src/components/prefabs/defaultprefab.tsx","./src/components/prefabs/prebuilt/block.tsx","./src/components/prefabs/prebuilt/card.tsx","./src/components/prefabs/prebuilt/list.tsx","./src/components/suspense/autosuspense.tsx","./src/components/suspense/generatedfallback.tsx","./src/hooks/index.ts","./src/hooks/usecompatid.ts","./src/hooks/
|
|
1
|
+
{"root":["./src/index.ts","./src/components/index.ts","./src/components/prefabs/defaultprefab.tsx","./src/components/prefabs/prebuilt/block.tsx","./src/components/prefabs/prebuilt/card.tsx","./src/components/prefabs/prebuilt/list.tsx","./src/components/suspense/autosuspense.tsx","./src/components/suspense/generatedfallback.tsx","./src/functions/suspend.tsx","./src/functions/index.ts","./src/hooks/index.ts","./src/hooks/usecompatid.ts","./src/hooks/usesuspenseboundary.ts","./src/hooks/usesuspensefallback.ts","./src/types/fallbackregistry.ts","./src/utils/buildtree.ts","./src/utils/rendernode.tsx","./src/utils/resolveelement.ts"],"version":"5.6.3"}
|