autosuspense 0.1.2 → 0.1.4

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.
Files changed (50) hide show
  1. package/dist/components/index.d.ts +2 -2
  2. package/dist/components/index.d.ts.map +1 -1
  3. package/dist/components/index.js +2 -2
  4. package/dist/components/prefabs/defaultPrefab.d.ts +3 -0
  5. package/dist/components/prefabs/defaultPrefab.d.ts.map +1 -0
  6. package/dist/components/prefabs/defaultPrefab.js +9 -0
  7. package/dist/components/prefabs/prebuilt/Block.d.ts +10 -0
  8. package/dist/components/prefabs/prebuilt/Block.d.ts.map +1 -0
  9. package/dist/components/prefabs/prebuilt/Block.js +5 -0
  10. package/dist/components/prefabs/prebuilt/Card.d.ts +10 -0
  11. package/dist/components/prefabs/prebuilt/Card.d.ts.map +1 -0
  12. package/dist/components/prefabs/prebuilt/Card.js +5 -0
  13. package/dist/components/prefabs/prebuilt/List.d.ts +10 -0
  14. package/dist/components/prefabs/prebuilt/List.d.ts.map +1 -0
  15. package/dist/components/prefabs/prebuilt/List.js +5 -0
  16. package/dist/components/suspense/AutoSuspense.d.ts +6 -0
  17. package/dist/components/suspense/AutoSuspense.d.ts.map +1 -0
  18. package/dist/components/suspense/AutoSuspense.js +21 -0
  19. package/dist/components/suspense/GeneratedFallback.d.ts +5 -0
  20. package/dist/components/suspense/GeneratedFallback.d.ts.map +1 -0
  21. package/dist/components/suspense/GeneratedFallback.js +9 -0
  22. package/dist/hooks/useSuspenseProvider.d.ts +1 -0
  23. package/dist/hooks/useSuspenseProvider.d.ts.map +1 -0
  24. package/dist/hooks/useSuspenseProvider.js +1 -0
  25. package/dist/types/FallbackRegistry.d.ts +5 -3
  26. package/dist/types/FallbackRegistry.d.ts.map +1 -1
  27. package/dist/types/FallbackRegistry.js +2 -2
  28. package/dist/utils/renderNode.d.ts +2 -2
  29. package/dist/utils/renderNode.d.ts.map +1 -1
  30. package/dist/utils/renderNode.js +6 -2
  31. package/dist/utils/resolveElement.d.ts +4 -0
  32. package/dist/utils/resolveElement.d.ts.map +1 -0
  33. package/dist/utils/resolveElement.js +20 -0
  34. package/package.json +1 -1
  35. package/src/components/index.ts +2 -2
  36. package/src/components/prefabs/defaultPrefab.tsx +10 -0
  37. package/src/components/prefabs/prebuilt/Block.css +42 -0
  38. package/src/components/prefabs/prebuilt/Block.tsx +16 -0
  39. package/src/components/prefabs/prebuilt/Card.css +45 -0
  40. package/src/components/prefabs/prebuilt/Card.tsx +16 -0
  41. package/src/components/prefabs/prebuilt/List.css +48 -0
  42. package/src/components/prefabs/prebuilt/List.tsx +16 -0
  43. package/src/components/{AutoSuspense.tsx → suspense/AutoSuspense.tsx} +14 -4
  44. package/src/components/{GeneratedFallback.tsx → suspense/GeneratedFallback.tsx} +4 -4
  45. package/src/hooks/useSuspenseProvider.ts +0 -0
  46. package/src/types/FallbackRegistry.ts +11 -3
  47. package/src/utils/renderNode.ts +10 -5
  48. package/src/utils/resolveElement.ts +32 -0
  49. package/tsconfig.json +5 -5
  50. package/tsconfig.tsbuildinfo +1 -1
@@ -1,4 +1,4 @@
1
- import { AutoSuspense } from "./AutoSuspense";
2
- import { GeneratedFallback } from "./GeneratedFallback";
1
+ import { AutoSuspense } from "./suspense/AutoSuspense";
2
+ import { GeneratedFallback } from "./suspense/GeneratedFallback";
3
3
  export { AutoSuspense, GeneratedFallback };
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,CAAC"}
@@ -1,3 +1,3 @@
1
- import { AutoSuspense } from "./AutoSuspense";
2
- import { GeneratedFallback } from "./GeneratedFallback";
1
+ import { AutoSuspense } from "./suspense/AutoSuspense";
2
+ import { GeneratedFallback } from "./suspense/GeneratedFallback";
3
3
  export { AutoSuspense, GeneratedFallback };
@@ -0,0 +1,3 @@
1
+ import * as React from "react";
2
+ export declare const defaultPrefab: Record<string, React.ReactElement>;
3
+ //# sourceMappingURL=defaultPrefab.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaultPrefab.d.ts","sourceRoot":"","sources":["../../../src/components/prefabs/defaultPrefab.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,YAAY,CAI5D,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Block } from "./prebuilt/Block";
3
+ import { Card } from "./prebuilt/Card";
4
+ import { List } from "./prebuilt/List";
5
+ export const defaultPrefab = {
6
+ block: _jsx(Block, {}),
7
+ card: _jsx(Card, {}),
8
+ list: _jsx(List, {}),
9
+ };
@@ -0,0 +1,10 @@
1
+ import * as React from "react";
2
+ import "./Block.css";
3
+ type BlockProps = {
4
+ children?: React.ReactNode;
5
+ className?: string;
6
+ style?: React.CSSProperties;
7
+ };
8
+ export declare const Block: React.FC<BlockProps>;
9
+ export {};
10
+ //# sourceMappingURL=Block.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Block.d.ts","sourceRoot":"","sources":["../../../../src/components/prefabs/prebuilt/Block.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,aAAa,CAAC;AAErB,KAAK,UAAU,GAAG;IAChB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CAMtC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import "./Block.css";
3
+ export const Block = ({ children, className, style }) => {
4
+ return (_jsx("div", { className: `as-block ${className ?? ""}`, style: style, "data-as-block": true, children: children }));
5
+ };
@@ -0,0 +1,10 @@
1
+ import * as React from "react";
2
+ import "./Card.css";
3
+ type CardProps = {
4
+ children?: React.ReactNode;
5
+ className?: string;
6
+ style?: React.CSSProperties;
7
+ };
8
+ export declare const Card: React.FC<CardProps>;
9
+ export {};
10
+ //# sourceMappingURL=Card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../../../src/components/prefabs/prebuilt/Card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,YAAY,CAAC;AAEpB,KAAK,SAAS,GAAG;IACf,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B,CAAC;AAEF,eAAO,MAAM,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CAMpC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import "./Card.css";
3
+ export const Card = ({ children, className, style }) => {
4
+ return (_jsx("div", { className: `as-card ${className ?? ""}`, style: style, "data-as-card": true, children: children }));
5
+ };
@@ -0,0 +1,10 @@
1
+ import * as React from "react";
2
+ import "./List.css";
3
+ type ListProps = {
4
+ children?: React.ReactNode;
5
+ className?: string;
6
+ style?: React.CSSProperties;
7
+ };
8
+ export declare const List: React.FC<ListProps>;
9
+ export {};
10
+ //# sourceMappingURL=List.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"List.d.ts","sourceRoot":"","sources":["../../../../src/components/prefabs/prebuilt/List.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,YAAY,CAAC;AAEpB,KAAK,SAAS,GAAG;IACf,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B,CAAC;AAEF,eAAO,MAAM,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CAMpC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import "./List.css";
3
+ export const List = ({ children, className, style }) => {
4
+ return (_jsx("div", { className: `as-list ${className ?? ""}`, style: style, "data-as-list": true, children: children }));
5
+ };
@@ -0,0 +1,6 @@
1
+ import * as React from "react";
2
+ export declare const AutoSuspense: ({ children, prefab, }: {
3
+ children: React.ReactNode;
4
+ prefab?: Record<string, React.ReactElement>;
5
+ }) => JSX.Element;
6
+ //# sourceMappingURL=AutoSuspense.d.ts.map
@@ -0,0 +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,GAAI,uBAG1B;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;CAC7C,gBAqBA,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { GeneratedFallback } from "./GeneratedFallback";
4
+ import { FallbackContext, } from "../../types/FallbackRegistry";
5
+ import { defaultPrefab } from "../prefabs/defaultPrefab";
6
+ export const AutoSuspense = ({ children, prefab = defaultPrefab, }) => {
7
+ const registryRef = React.useRef({
8
+ nodes: new Map(),
9
+ currentParent: null,
10
+ prebuild: new Map(Object.entries(prefab)),
11
+ });
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
+ const fallback = _jsx(GeneratedFallback, { registry: registryRef.current });
20
+ return (_jsx(FallbackContext.Provider, { value: registryRef.current, children: _jsx(React.Suspense, { fallback: fallback, children: children }) }));
21
+ };
@@ -0,0 +1,5 @@
1
+ import { FallbackRegistry } from "../../types/FallbackRegistry";
2
+ export declare function GeneratedFallback({ registry, }: {
3
+ registry: FallbackRegistry;
4
+ }): JSX.Element;
5
+ //# sourceMappingURL=GeneratedFallback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GeneratedFallback.d.ts","sourceRoot":"","sources":["../../../src/components/suspense/GeneratedFallback.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAIhE,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,GACT,EAAE;IACD,QAAQ,EAAE,gBAAgB,CAAC;CAC5B,eASA"}
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { buildTree } from "../../utils/buildTree";
4
+ import { renderNode } from "../../utils/renderNode";
5
+ export function GeneratedFallback({ registry, }) {
6
+ const tree = buildTree(registry.nodes);
7
+ const roots = tree.get(null) ?? [];
8
+ return (_jsx(React.Fragment, { children: roots.map((node) => renderNode(node, tree, registry)) }));
9
+ }
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=useSuspenseProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSuspenseProvider.d.ts","sourceRoot":"","sources":["../../src/hooks/useSuspenseProvider.ts"],"names":[],"mappings":""}
@@ -0,0 +1 @@
1
+ "use strict";
@@ -1,12 +1,14 @@
1
- import { type ReactElement } from "react";
1
+ import * as React from "react";
2
2
  export type Node = {
3
3
  id: string;
4
- element: ReactElement;
4
+ element: FallbackDescriptor;
5
5
  parent: string | null;
6
6
  };
7
7
  export type FallbackRegistry = {
8
8
  nodes: Map<string, Node>;
9
9
  currentParent: string | null;
10
+ prebuild: Map<string, React.ReactElement | React.ComponentType<any>>;
10
11
  };
11
- export declare const FallbackContext: import("react").Context<FallbackRegistry | null>;
12
+ export type FallbackDescriptor = string | React.ReactElement | React.ComponentType;
13
+ export declare const FallbackContext: React.Context<FallbackRegistry | null>;
12
14
  //# sourceMappingURL=FallbackRegistry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FallbackRegistry.d.ts","sourceRoot":"","sources":["../../src/types/FallbackRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAEzD,MAAM,MAAM,IAAI,GAAG;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,CAAC;AAEF,eAAO,MAAM,eAAe,kDAA+C,CAAC"}
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;CACvB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,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,eAAO,MAAM,eAAe,wCAE3B,CAAC"}
@@ -1,2 +1,2 @@
1
- import { createContext } from "react";
2
- export const FallbackContext = createContext(null);
1
+ import * as React from "react";
2
+ export const FallbackContext = React.createContext(null);
@@ -1,4 +1,4 @@
1
1
  import React from "react";
2
- import type { Node } from "../types/FallbackRegistry";
3
- export declare function renderNode(node: Node, childMap: Map<string | null, Node[]>): React.ReactElement;
2
+ import type { FallbackRegistry, Node } from "../types/FallbackRegistry";
3
+ export declare function renderNode(node: Node, childMap: Map<string | null, Node[]>, registry: FallbackRegistry): React.ReactElement | null;
4
4
  //# sourceMappingURL=renderNode.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"renderNode.d.ts","sourceRoot":"","sources":["../../src/utils/renderNode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,2BAA2B,CAAC;AAEtD,wBAAgB,UAAU,CACxB,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,GAAG,CAAC,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC,GACnC,KAAK,CAAC,YAAY,CAQpB"}
1
+ {"version":3,"file":"renderNode.d.ts","sourceRoot":"","sources":["../../src/utils/renderNode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,2BAA2B,CAAC;AAGxE,wBAAgB,UAAU,CAExB,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,CAU3B"}
@@ -1,5 +1,9 @@
1
1
  import React from "react";
2
- export function renderNode(node, childMap) {
2
+ import { resolveElement } from "./resolveElement";
3
+ export function renderNode(node, childMap, registry) {
3
4
  const children = childMap.get(node.id) ?? [];
4
- return React.cloneElement(node.element, undefined, children.map((child) => renderNode(child, childMap)));
5
+ const resolvedEle = resolveElement(node.element, registry);
6
+ if (!resolvedEle)
7
+ return null;
8
+ return React.cloneElement(resolvedEle, { key: node.id }, children.map((child) => renderNode(child, childMap, registry)));
5
9
  }
@@ -0,0 +1,4 @@
1
+ import * as React from "react";
2
+ import { FallbackDescriptor, FallbackRegistry } from "../types/FallbackRegistry";
3
+ export declare function resolveElement(descriptor: FallbackDescriptor, registry: FallbackRegistry): React.ReactElement | null;
4
+ //# sourceMappingURL=resolveElement.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveElement.d.ts","sourceRoot":"","sources":["../../src/utils/resolveElement.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EACjB,MAAM,2BAA2B,CAAC;AAEnC,wBAAgB,cAAc,CAC5B,UAAU,EAAE,kBAAkB,EAC9B,QAAQ,EAAE,gBAAgB,GACzB,KAAK,CAAC,YAAY,GAAG,IAAI,CAsB3B"}
@@ -0,0 +1,20 @@
1
+ import * as React from "react";
2
+ export function resolveElement(descriptor, registry) {
3
+ if (React.isValidElement(descriptor)) {
4
+ return descriptor;
5
+ }
6
+ if (typeof descriptor === "function") {
7
+ return React.createElement(descriptor);
8
+ }
9
+ if (typeof descriptor === "string") {
10
+ const value = registry.prebuild.get(descriptor);
11
+ if (!value)
12
+ return null;
13
+ if (React.isValidElement(value)) {
14
+ return value;
15
+ }
16
+ const Component = value;
17
+ return React.createElement(Component);
18
+ }
19
+ return null;
20
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "autosuspense",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Automatic suspense wiring block for React.",
5
5
  "license": "ISC",
6
6
  "type": "commonjs",
@@ -1,3 +1,3 @@
1
- import { AutoSuspense } from "./AutoSuspense";
2
- import { GeneratedFallback } from "./GeneratedFallback";
1
+ import { AutoSuspense } from "./suspense/AutoSuspense";
2
+ import { GeneratedFallback } from "./suspense/GeneratedFallback";
3
3
  export { AutoSuspense, GeneratedFallback };
@@ -0,0 +1,10 @@
1
+ import * as React from "react";
2
+ import { Block } from "./prebuilt/Block";
3
+ import { Card } from "./prebuilt/Card";
4
+ import { List } from "./prebuilt/List";
5
+
6
+ export const defaultPrefab: Record<string, React.ReactElement> = {
7
+ block: <Block />,
8
+ card: <Card />,
9
+ list: <List />,
10
+ };
@@ -0,0 +1,42 @@
1
+ .as-block {
2
+ width: 100%;
3
+ min-height: var(--as-block-min-height, 96px);
4
+ border-radius: var(--as-block-radius, 12px);
5
+ box-sizing: border-box;
6
+
7
+ background: var(
8
+ --as-block-bg,
9
+ linear-gradient(
10
+ 90deg,
11
+ var(--as-skeleton-base, #ececec) 25%,
12
+ var(--as-skeleton-highlight, #f5f5f5) 37%,
13
+ var(--as-skeleton-base, #ececec) 63%
14
+ )
15
+ );
16
+
17
+ background-size: 400% 100%;
18
+ animation:
19
+ as-shimmer 1.4s ease infinite,
20
+ as-pulse 2s ease-in-out infinite;
21
+ }
22
+
23
+ @keyframes as-shimmer {
24
+ 0% {
25
+ background-position: 100% 0;
26
+ }
27
+ 100% {
28
+ background-position: 0 0;
29
+ }
30
+ }
31
+
32
+ @keyframes as-pulse {
33
+ 0% {
34
+ opacity: 1;
35
+ }
36
+ 50% {
37
+ opacity: 0.85;
38
+ }
39
+ 100% {
40
+ opacity: 1;
41
+ }
42
+ }
@@ -0,0 +1,16 @@
1
+ import * as React from "react";
2
+ import "./Block.css";
3
+
4
+ type BlockProps = {
5
+ children?: React.ReactNode;
6
+ className?: string;
7
+ style?: React.CSSProperties;
8
+ };
9
+
10
+ export const Block: React.FC<BlockProps> = ({ children, className, style }) => {
11
+ return (
12
+ <div className={`as-block ${className ?? ""}`} style={style} data-as-block>
13
+ {children}
14
+ </div>
15
+ );
16
+ };
@@ -0,0 +1,45 @@
1
+ .as-card {
2
+ width: 100%;
3
+ min-height: var(--as-card-min-height, 120px);
4
+ padding: var(--as-card-padding, 16px);
5
+ box-sizing: border-box;
6
+
7
+ border-radius: var(--as-card-radius, 12px);
8
+
9
+ background: var(
10
+ --as-card-bg,
11
+ linear-gradient(
12
+ 90deg,
13
+ var(--as-skeleton-base, #ececec) 25%,
14
+ var(--as-skeleton-highlight, #f5f5f5) 37%,
15
+ var(--as-skeleton-base, #ececec) 63%
16
+ )
17
+ );
18
+
19
+ background-size: 400% 100%;
20
+ animation:
21
+ as-shimmer 1.4s ease infinite,
22
+ as-pulse 2s ease-in-out infinite;
23
+ }
24
+
25
+ /* reuse same animations */
26
+ @keyframes as-shimmer {
27
+ 0% {
28
+ background-position: 100% 0;
29
+ }
30
+ 100% {
31
+ background-position: 0 0;
32
+ }
33
+ }
34
+
35
+ @keyframes as-pulse {
36
+ 0% {
37
+ opacity: 1;
38
+ }
39
+ 50% {
40
+ opacity: 0.85;
41
+ }
42
+ 100% {
43
+ opacity: 1;
44
+ }
45
+ }
@@ -0,0 +1,16 @@
1
+ import * as React from "react";
2
+ import "./Card.css";
3
+
4
+ type CardProps = {
5
+ children?: React.ReactNode;
6
+ className?: string;
7
+ style?: React.CSSProperties;
8
+ };
9
+
10
+ export const Card: React.FC<CardProps> = ({ children, className, style }) => {
11
+ return (
12
+ <div className={`as-card ${className ?? ""}`} style={style} data-as-card>
13
+ {children}
14
+ </div>
15
+ );
16
+ };
@@ -0,0 +1,48 @@
1
+ .as-list {
2
+ width: 100%;
3
+ min-height: var(--as-list-min-height, 160px);
4
+ padding: var(--as-list-padding, 12px);
5
+ box-sizing: border-box;
6
+
7
+ border-radius: var(--as-list-radius, 8px);
8
+
9
+ display: flex;
10
+ flex-direction: column;
11
+ gap: var(--as-list-gap, 12px);
12
+
13
+ background: var(
14
+ --as-list-bg,
15
+ linear-gradient(
16
+ 90deg,
17
+ var(--as-skeleton-base, #ececec) 25%,
18
+ var(--as-skeleton-highlight, #f5f5f5) 37%,
19
+ var(--as-skeleton-base, #ececec) 63%
20
+ )
21
+ );
22
+
23
+ background-size: 400% 100%;
24
+ animation:
25
+ as-shimmer 1.4s ease infinite,
26
+ as-pulse 2s ease-in-out infinite;
27
+ }
28
+
29
+ @keyframes as-shimmer {
30
+ 0% {
31
+ background-position: 100% 0;
32
+ }
33
+ 100% {
34
+ background-position: 0 0;
35
+ }
36
+ }
37
+
38
+ @keyframes as-pulse {
39
+ 0% {
40
+ opacity: 1;
41
+ }
42
+ 50% {
43
+ opacity: 0.85;
44
+ }
45
+ 100% {
46
+ opacity: 1;
47
+ }
48
+ }
@@ -0,0 +1,16 @@
1
+ import * as React from "react";
2
+ import "./List.css";
3
+
4
+ type ListProps = {
5
+ children?: React.ReactNode;
6
+ className?: string;
7
+ style?: React.CSSProperties;
8
+ };
9
+
10
+ export const List: React.FC<ListProps> = ({ children, className, style }) => {
11
+ return (
12
+ <div className={`as-list ${className ?? ""}`} style={style} data-as-list>
13
+ {children}
14
+ </div>
15
+ );
16
+ };
@@ -1,20 +1,30 @@
1
1
  import * as React from "react";
2
+
3
+ import { GeneratedFallback } from "./GeneratedFallback";
2
4
  import {
3
5
  FallbackContext,
4
- type FallbackRegistry,
5
- } from "../types/FallbackRegistry";
6
- import { GeneratedFallback } from "./GeneratedFallback";
6
+ FallbackRegistry,
7
+ } from "../../types/FallbackRegistry";
8
+ import { defaultPrefab } from "../prefabs/defaultPrefab";
7
9
 
8
- export const AutoSuspense = ({ children }: { children: React.ReactNode }) => {
10
+ export const AutoSuspense = ({
11
+ children,
12
+ prefab = defaultPrefab,
13
+ }: {
14
+ children: React.ReactNode;
15
+ prefab?: Record<string, React.ReactElement>;
16
+ }) => {
9
17
  const registryRef = React.useRef<FallbackRegistry>({
10
18
  nodes: new Map(),
11
19
  currentParent: null,
20
+ prebuild: new Map(Object.entries(prefab)),
12
21
  });
13
22
 
14
23
  if (registryRef.current === null) {
15
24
  registryRef.current = {
16
25
  nodes: new Map(),
17
26
  currentParent: null,
27
+ prebuild: new Map(Object.entries(prefab)),
18
28
  };
19
29
  }
20
30
  const fallback = <GeneratedFallback registry={registryRef.current} />;
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
- import type { FallbackRegistry } from "../types/FallbackRegistry";
3
- import { buildTree } from "../utils/buildTree";
4
- import { renderNode } from "../utils/renderNode";
2
+ import { FallbackRegistry } from "../../types/FallbackRegistry";
3
+ import { buildTree } from "../../utils/buildTree";
4
+ import { renderNode } from "../../utils/renderNode";
5
5
 
6
6
  export function GeneratedFallback({
7
7
  registry,
@@ -13,7 +13,7 @@ export function GeneratedFallback({
13
13
 
14
14
  return (
15
15
  <React.Fragment>
16
- {roots.map((node) => renderNode(node, tree))}
16
+ {roots.map((node) => renderNode(node, tree, registry))}
17
17
  </React.Fragment>
18
18
  );
19
19
  }
File without changes
@@ -1,14 +1,22 @@
1
- import { createContext, type ReactElement } from "react";
1
+ import * as React from "react";
2
2
 
3
3
  export type Node = {
4
4
  id: string;
5
- element: ReactElement;
5
+ element: FallbackDescriptor;
6
6
  parent: string | null;
7
7
  };
8
8
 
9
9
  export type FallbackRegistry = {
10
10
  nodes: Map<string, Node>;
11
11
  currentParent: string | null;
12
+ prebuild: Map<string, React.ReactElement | React.ComponentType<any>>;
12
13
  };
13
14
 
14
- export const FallbackContext = createContext<FallbackRegistry | null>(null);
15
+ export type FallbackDescriptor =
16
+ | string
17
+ | React.ReactElement
18
+ | React.ComponentType;
19
+
20
+ export const FallbackContext = React.createContext<FallbackRegistry | null>(
21
+ null,
22
+ );
@@ -1,15 +1,20 @@
1
1
  import React from "react";
2
- import type { Node } from "../types/FallbackRegistry";
2
+ import type { FallbackRegistry, Node } from "../types/FallbackRegistry";
3
+ import { resolveElement } from "./resolveElement";
3
4
 
4
5
  export function renderNode(
6
+
5
7
  node: Node,
6
8
  childMap: Map<string | null, Node[]>,
7
- ): React.ReactElement {
9
+ registry: FallbackRegistry,
10
+ ): React.ReactElement | null {
8
11
  const children = childMap.get(node.id) ?? [];
12
+ const resolvedEle = resolveElement(node.element, registry);
13
+ if (!resolvedEle) return null;
9
14
 
10
15
  return React.cloneElement(
11
- node.element,
12
- undefined,
13
- children.map((child) => renderNode(child, childMap)),
16
+ resolvedEle,
17
+ { key: node.id },
18
+ children.map((child) => renderNode(child, childMap, registry)),
14
19
  );
15
20
  }
@@ -0,0 +1,32 @@
1
+ import * as React from "react";
2
+ import {
3
+ FallbackDescriptor,
4
+ FallbackRegistry,
5
+ } from "../types/FallbackRegistry";
6
+
7
+ export function resolveElement(
8
+ descriptor: FallbackDescriptor,
9
+ registry: FallbackRegistry,
10
+ ): React.ReactElement | null {
11
+ if (React.isValidElement(descriptor)) {
12
+ return descriptor;
13
+ }
14
+
15
+ if (typeof descriptor === "function") {
16
+ return React.createElement(descriptor);
17
+ }
18
+
19
+ if (typeof descriptor === "string") {
20
+ const value = registry.prebuild.get(descriptor);
21
+ if (!value) return null;
22
+
23
+ if (React.isValidElement(value)) {
24
+ return value;
25
+ }
26
+
27
+ const Component = value as React.ComponentType<any>;
28
+ return React.createElement(Component);
29
+ }
30
+
31
+ return null;
32
+ }
package/tsconfig.json CHANGED
@@ -1,9 +1,11 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "target": "ES2020",
4
- "module": "CommonJS",
5
- "jsx": "react",
6
- "lib": ["DOM", "ES2019"],
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+
7
+ "jsx": "react-jsx",
8
+ "lib": ["DOM", "ES2020"],
7
9
  "types": ["react"],
8
10
 
9
11
  "declaration": true,
@@ -14,8 +16,6 @@
14
16
  "rootDir": "./src",
15
17
 
16
18
  "strict": true,
17
-
18
- "moduleResolution": "Bundler",
19
19
  "esModuleInterop": true,
20
20
  "skipLibCheck": true
21
21
  },
@@ -1 +1 @@
1
- {"root":["./src/index.ts","./src/components/autosuspense.tsx","./src/components/generatedfallback.tsx","./src/components/index.ts","./src/hooks/index.ts","./src/hooks/usecompatid.ts","./src/hooks/usesuspensefallback.ts","./src/types/fallbackregistry.ts","./src/utils/buildtree.ts","./src/utils/rendernode.ts"],"version":"5.9.3"}
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/usesuspensefallback.ts","./src/hooks/usesuspenseprovider.ts","./src/types/fallbackregistry.ts","./src/utils/buildtree.ts","./src/utils/rendernode.ts","./src/utils/resolveelement.ts"],"version":"5.9.3"}