diff --git a/.bazelignore b/.bazelignore
index 548e7a9ec..beb4c9989 100644
--- a/.bazelignore
+++ b/.bazelignore
@@ -37,6 +37,7 @@ plugins/asset-provider/react/node_modules
plugins/asset-transform/core/node_modules
plugins/async-node/core/node_modules
plugins/common-types/core/node_modules
+plugins/async-node/components/node_modules
plugins/types-provider/core/node_modules
plugins/auto-scroll/react/node_modules
plugins/beacon/react/node_modules
diff --git a/package.json b/package.json
index f0afeaa27..ff2322fa5 100644
--- a/package.json
+++ b/package.json
@@ -142,6 +142,7 @@
"react-redux": "^7.2.6",
"react-router": "^6.22.3",
"react-router-dom": "^6.22.3",
+ "react-json-reconciler": "^2.0.0",
"react-syntax-highlighter": "^15.4.5",
"redux": "^4.1.2",
"redux-state-sync": "^3.1.4",
diff --git a/plugins/async-node/components/BUILD b/plugins/async-node/components/BUILD
new file mode 100644
index 000000000..551e5a608
--- /dev/null
+++ b/plugins/async-node/components/BUILD
@@ -0,0 +1,23 @@
+load("@npm//:defs.bzl", "npm_link_all_packages")
+load("//tools:defs.bzl", "tsup_config", "vitest_config")
+load("@rules_player//javascript:defs.bzl", "js_pipeline")
+
+npm_link_all_packages(name = "node_modules")
+
+tsup_config(name = "tsup_config")
+
+vitest_config(name = "vitest_config")
+
+js_pipeline(
+ package_name = "@player-ui/async-node-components",
+ peer_deps = [
+ "//:node_modules/react",
+ "//:node_modules/@types/react",
+ "//:node_modules/@player-tools/dsl",
+ ":node_modules/@player-ui/player",
+ "//:node_modules/react-json-reconciler",
+ ],
+ deps = [
+ ":node_modules/@player-ui/async-node-plugin",
+ ],
+)
\ No newline at end of file
diff --git a/plugins/async-node/components/package.json b/plugins/async-node/components/package.json
new file mode 100644
index 000000000..e24d8ad84
--- /dev/null
+++ b/plugins/async-node/components/package.json
@@ -0,0 +1,11 @@
+{
+ "name": "@player-ui/async-node-plugin-components",
+ "version": "0.0.0-PLACEHOLDER",
+ "main": "src/index.tsx",
+ "peerDependencies": {
+ "@player-ui/player": "workspace:*"
+ },
+ "dependencies": {
+ "@player-ui/async-node-plugin": "workspace:*"
+ }
+}
diff --git a/plugins/async-node/components/src/__tests__/index.test.tsx b/plugins/async-node/components/src/__tests__/index.test.tsx
new file mode 100644
index 000000000..211f087f9
--- /dev/null
+++ b/plugins/async-node/components/src/__tests__/index.test.tsx
@@ -0,0 +1,11 @@
+import React from "react";
+import { test, expect } from "vitest";
+import { render } from "@player-tools/dsl";
+import { AsyncNode } from "../index";
+
+test("works for id prop", async () => {
+ expect((await render()).jsonValue).toStrictEqual({
+ id: "nodeId",
+ async: "true",
+ });
+});
diff --git a/plugins/async-node/components/src/index.tsx b/plugins/async-node/components/src/index.tsx
new file mode 100644
index 000000000..85c273692
--- /dev/null
+++ b/plugins/async-node/components/src/index.tsx
@@ -0,0 +1,19 @@
+import React from "react";
+import type { ObjectNode } from "react-json-reconciler";
+
+export type AsyncNodeProps = {
+ id: string;
+};
+
+export const AsyncNode = React.forwardRef(
+ ({ id }, ref) => {
+ return (
+
+ {id}
+ true
+
+ );
+ },
+);
+
+AsyncNode.displayName = "AsyncNode";
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 8a7ff0cc0..b83f947b9 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -372,6 +372,9 @@ importers:
react-icons:
specifier: ^4.3.1
version: 4.12.0(react@18.3.1)
+ react-json-reconciler:
+ specifier: ^2.0.0
+ version: 2.0.0(react@18.3.1)
react-redux:
specifier: ^7.2.6
version: 7.2.9(react-dom@18.3.1)(react@18.3.1)
@@ -590,6 +593,15 @@ importers:
specifier: workspace:*
version: link:../../../core/types
+ plugins/async-node/components:
+ dependencies:
+ '@player-ui/async-node-plugin':
+ specifier: workspace:*
+ version: link:../core
+ '@player-ui/player':
+ specifier: workspace:*
+ version: link:../../../core/player
+
plugins/async-node/core:
dependencies:
'@player-ui/player':