@3plate/graph-react 0.1.10 → 0.1.14
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.mjs → index.cjs} +60 -21
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +22 -59
- package/dist/index.js.map +1 -0
- package/package.json +14 -6
- /package/dist/{index.d.mts → index.d.cts} +0 -0
|
@@ -1,14 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
Graph: () => Graph,
|
|
34
|
+
Playground: () => Playground
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(index_exports);
|
|
37
|
+
|
|
1
38
|
// src/Graph.tsx
|
|
2
|
-
|
|
3
|
-
|
|
39
|
+
var import_react = __toESM(require("react"), 1);
|
|
40
|
+
var import_graph_core = require("@3plate/graph-core");
|
|
4
41
|
function Graph(props) {
|
|
5
|
-
const rootRef = useRef(null);
|
|
6
|
-
const apiRef = useRef(null);
|
|
7
|
-
const rootIdRef = useRef(`graph-${Math.random().toString(36).slice(2, 11)}`);
|
|
8
|
-
useEffect(() => {
|
|
42
|
+
const rootRef = (0, import_react.useRef)(null);
|
|
43
|
+
const apiRef = (0, import_react.useRef)(null);
|
|
44
|
+
const rootIdRef = (0, import_react.useRef)(`graph-${Math.random().toString(36).slice(2, 11)}`);
|
|
45
|
+
(0, import_react.useEffect)(() => {
|
|
9
46
|
if (!rootRef.current || apiRef.current) return;
|
|
10
47
|
rootRef.current.id = rootIdRef.current;
|
|
11
|
-
graph({
|
|
48
|
+
(0, import_graph_core.graph)({
|
|
12
49
|
root: rootIdRef.current,
|
|
13
50
|
nodes: props.nodes,
|
|
14
51
|
edges: props.edges,
|
|
@@ -32,25 +69,25 @@ function Graph(props) {
|
|
|
32
69
|
}
|
|
33
70
|
};
|
|
34
71
|
}, []);
|
|
35
|
-
useEffect(() => {
|
|
72
|
+
(0, import_react.useEffect)(() => {
|
|
36
73
|
if (!apiRef.current) return;
|
|
37
74
|
apiRef.current.applyProps(props);
|
|
38
75
|
}, [props.nodes, props.edges, props.history, props.options]);
|
|
39
|
-
return /* @__PURE__ */
|
|
76
|
+
return /* @__PURE__ */ import_react.default.createElement("div", { ref: rootRef, style: { width: "100%", height: "100%" } });
|
|
40
77
|
}
|
|
41
78
|
|
|
42
79
|
// src/Playground.tsx
|
|
43
|
-
|
|
44
|
-
|
|
80
|
+
var import_react2 = __toESM(require("react"), 1);
|
|
81
|
+
var import_graph_core2 = require("@3plate/graph-core");
|
|
45
82
|
function Playground(props) {
|
|
46
|
-
const rootRef =
|
|
47
|
-
const playgroundRef =
|
|
48
|
-
const rootIdRef =
|
|
49
|
-
const prevExamplesRef =
|
|
50
|
-
|
|
83
|
+
const rootRef = (0, import_react2.useRef)(null);
|
|
84
|
+
const playgroundRef = (0, import_react2.useRef)(null);
|
|
85
|
+
const rootIdRef = (0, import_react2.useRef)(`playground-${Math.random().toString(36).slice(2, 11)}`);
|
|
86
|
+
const prevExamplesRef = (0, import_react2.useRef)({});
|
|
87
|
+
(0, import_react2.useEffect)(() => {
|
|
51
88
|
if (!rootRef.current || playgroundRef.current) return;
|
|
52
89
|
rootRef.current.id = rootIdRef.current;
|
|
53
|
-
const playground = new
|
|
90
|
+
const playground = new import_graph_core2.Playground({
|
|
54
91
|
root: rootIdRef.current,
|
|
55
92
|
examples: props.examples,
|
|
56
93
|
defaultExample: props.defaultExample
|
|
@@ -62,7 +99,7 @@ function Playground(props) {
|
|
|
62
99
|
playgroundRef.current = null;
|
|
63
100
|
};
|
|
64
101
|
}, []);
|
|
65
|
-
|
|
102
|
+
(0, import_react2.useEffect)(() => {
|
|
66
103
|
if (!playgroundRef.current) return;
|
|
67
104
|
const playground = playgroundRef.current;
|
|
68
105
|
const prev = prevExamplesRef.current;
|
|
@@ -81,7 +118,7 @@ function Playground(props) {
|
|
|
81
118
|
}
|
|
82
119
|
prevExamplesRef.current = { ...current };
|
|
83
120
|
}, [props.examples]);
|
|
84
|
-
return /* @__PURE__ */
|
|
121
|
+
return /* @__PURE__ */ import_react2.default.createElement("div", { ref: rootRef, style: { width: "100%", height: "100%" } });
|
|
85
122
|
}
|
|
86
123
|
function shallowEqualExample(a, b) {
|
|
87
124
|
if (a === b) return true;
|
|
@@ -119,7 +156,9 @@ function shallowEqualSource(a, b) {
|
|
|
119
156
|
}
|
|
120
157
|
return false;
|
|
121
158
|
}
|
|
122
|
-
export
|
|
159
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
160
|
+
0 && (module.exports = {
|
|
123
161
|
Graph,
|
|
124
162
|
Playground
|
|
125
|
-
};
|
|
163
|
+
});
|
|
164
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/Graph.tsx","../src/Playground.tsx"],"sourcesContent":["/**\n * @3plate/graph-react - React components for @3plate/graph graph visualization\n */\n\nexport { Graph } from './Graph'\nexport { Playground } from './Playground'\n\nexport type { GraphProps } from './Graph'\nexport type { PlaygroundProps } from './Playground'\n\n// Re-export types from core for convenience\nexport type {\n // API types\n API,\n APIArguments,\n APIOptions,\n Update,\n IngestionConfig,\n EventsOptions,\n // Callback parameter types\n NewNode,\n NewEdge,\n NodeProps,\n EdgeProps,\n PortProps,\n RenderNode,\n // Ingestion types\n IngestMessage,\n SnapshotMessage,\n UpdateMessage,\n HistoryMessage,\n // WebSocket types\n WebSocketStatus,\n WebSocketStatusListener,\n // Theming types\n ColorMode,\n ThemeVars,\n CanvasTheme,\n NodeTheme,\n PortTheme,\n EdgeTheme,\n // Common types\n Orientation,\n NodeAlign,\n PortStyle,\n} from '@3plate/graph-core'\n","import React, { useEffect, useRef } from 'react'\nimport { graph, type API } from '@3plate/graph-core'\nimport type { APIArguments, Update, IngestionConfig } from '@3plate/graph-core'\n\nexport type GraphProps<N, E> = {\n /** Initial nodes */\n nodes?: N[]\n /** Initial edges */\n edges?: E[]\n /** Initial history */\n history?: Update<N, E>[]\n /** Ingestion source configuration (alternative to nodes/edges/history) */\n ingestion?: IngestionConfig\n /** Options */\n options?: APIArguments<N, E>['options']\n /** Events */\n events?: APIArguments<N, E>['events']\n}\n\n/**\n * Graph component - renders a graph visualization\n * Intelligently handles prop changes by diffing nodes, edges, and history\n */\nexport function Graph<N, E>(props: GraphProps<N, E>) {\n const rootRef = useRef<HTMLDivElement>(null)\n const apiRef = useRef<API<N, E> | null>(null)\n const rootIdRef = useRef<string>(`graph-${Math.random().toString(36).slice(2, 11)}`)\n\n // Initialize API once\n useEffect(() => {\n if (!rootRef.current || apiRef.current) return\n\n rootRef.current.id = rootIdRef.current\n\n graph({\n root: rootIdRef.current,\n nodes: props.nodes,\n edges: props.edges,\n history: props.history,\n ingestion: props.ingestion,\n options: props.options,\n events: props.events,\n }).then(api => {\n apiRef.current = api\n })\n\n return () => {\n // Cleanup\n if (apiRef.current) {\n apiRef.current.destroy()\n apiRef.current = null\n }\n if (rootRef.current) {\n // Remove canvas from DOM\n const canvas = rootRef.current.querySelector('canvas, svg')\n if (canvas) {\n canvas.remove()\n }\n }\n }\n }, []) // Only run once on mount\n\n // Handle prop changes using the centralized applyProps method\n useEffect(() => {\n if (!apiRef.current) return\n apiRef.current.applyProps(props)\n }, [props.nodes, props.edges, props.history, props.options])\n\n return <div ref={rootRef} style={{ width: '100%', height: '100%' }} />\n}\n","import React, { useEffect, useRef } from 'react'\nimport { Playground as PlaygroundClass, type PlaygroundOptions, type Example } from '@3plate/graph-core'\n\nexport type PlaygroundProps = {\n /** Examples to display */\n examples: PlaygroundOptions['examples']\n /** Default example key */\n defaultExample?: string\n}\n\n/**\n * Playground component - renders the interactive playground with examples\n */\nexport function Playground(props: PlaygroundProps) {\n const rootRef = useRef<HTMLDivElement>(null)\n const playgroundRef = useRef<PlaygroundClass | null>(null)\n const rootIdRef = useRef<string>(`playground-${Math.random().toString(36).slice(2, 11)}`)\n const prevExamplesRef = useRef<Record<string, Example>>({})\n\n useEffect(() => {\n if (!rootRef.current || playgroundRef.current) return\n\n rootRef.current.id = rootIdRef.current\n\n const playground = new PlaygroundClass({\n root: rootIdRef.current,\n examples: props.examples,\n defaultExample: props.defaultExample,\n })\n playgroundRef.current = playground\n prevExamplesRef.current = { ...props.examples }\n playground.init()\n\n return () => {\n // Cleanup if needed\n playgroundRef.current = null\n }\n }, []) // Only initialize once\n\n // Handle examples changes\n useEffect(() => {\n if (!playgroundRef.current) return\n\n const playground = playgroundRef.current\n const prev = prevExamplesRef.current\n const current = props.examples\n\n // Get all keys from both previous and current\n const allKeys = new Set([...Object.keys(prev), ...Object.keys(current)])\n\n for (const key of allKeys) {\n const prevExample = prev[key]\n const currentExample = current[key]\n\n if (!prevExample && currentExample) {\n // Example was added\n playground.addExample(key, currentExample)\n } else if (prevExample && !currentExample) {\n // Example was removed\n playground.removeExample(key)\n } else if (prevExample && currentExample && !shallowEqualExample(prevExample, currentExample)) {\n // Example was modified\n playground.addExample(key, currentExample)\n }\n }\n\n prevExamplesRef.current = { ...current }\n }, [props.examples])\n\n return <div ref={rootRef} style={{ width: '100%', height: '100%' }} />\n}\n\n/**\n * Shallow comparison of two Example objects\n */\nfunction shallowEqualExample(a: Example, b: Example): boolean {\n if (a === b) return true\n if (a.name !== b.name) return false\n if (a.description !== b.description) return false\n if (!shallowEqualArray(a.nodes, b.nodes)) return false\n if (!shallowEqualArray(a.edges, b.edges)) return false\n if (!shallowEqualOptions(a.options, b.options)) return false\n if (!shallowEqualSource(a.source, b.source)) return false\n return true\n}\n\n/**\n * Shallow comparison of arrays\n */\nfunction shallowEqualArray<T>(a: T[] | undefined, b: T[] | undefined): boolean {\n if (a === b) return true\n if (!a || !b) return false\n if (a.length !== b.length) return false\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false\n }\n return true\n}\n\n/**\n * Shallow comparison of ExampleOptions\n */\nfunction shallowEqualOptions(\n a: Example['options'],\n b: Example['options']\n): boolean {\n if (a === b) return true\n if (!a || !b) return false\n // For now, do a simple reference check on options\n // Can be enhanced if needed\n return a === b\n}\n\n/**\n * Shallow comparison of ExampleSource\n */\nfunction shallowEqualSource(\n a: Example['source'],\n b: Example['source']\n): boolean {\n if (a === b) return true\n if (!a || !b) return false\n if (a.type !== b.type) return false\n if (a.type === 'file' && b.type === 'file') {\n return a.path === b.path\n }\n if (a.type === 'websocket' && b.type === 'websocket') {\n return a.url === b.url\n }\n return false\n}\n"],"mappings":"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","names":["React","import_react","import_graph_core","PlaygroundClass","React"]}
|
package/dist/index.js
CHANGED
|
@@ -1,51 +1,14 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
|
|
30
|
-
// src/index.ts
|
|
31
|
-
var index_exports = {};
|
|
32
|
-
__export(index_exports, {
|
|
33
|
-
Graph: () => Graph,
|
|
34
|
-
Playground: () => Playground
|
|
35
|
-
});
|
|
36
|
-
module.exports = __toCommonJS(index_exports);
|
|
37
|
-
|
|
38
1
|
// src/Graph.tsx
|
|
39
|
-
|
|
40
|
-
|
|
2
|
+
import React, { useEffect, useRef } from "react";
|
|
3
|
+
import { graph } from "@3plate/graph-core";
|
|
41
4
|
function Graph(props) {
|
|
42
|
-
const rootRef =
|
|
43
|
-
const apiRef =
|
|
44
|
-
const rootIdRef =
|
|
45
|
-
|
|
5
|
+
const rootRef = useRef(null);
|
|
6
|
+
const apiRef = useRef(null);
|
|
7
|
+
const rootIdRef = useRef(`graph-${Math.random().toString(36).slice(2, 11)}`);
|
|
8
|
+
useEffect(() => {
|
|
46
9
|
if (!rootRef.current || apiRef.current) return;
|
|
47
10
|
rootRef.current.id = rootIdRef.current;
|
|
48
|
-
|
|
11
|
+
graph({
|
|
49
12
|
root: rootIdRef.current,
|
|
50
13
|
nodes: props.nodes,
|
|
51
14
|
edges: props.edges,
|
|
@@ -69,25 +32,25 @@ function Graph(props) {
|
|
|
69
32
|
}
|
|
70
33
|
};
|
|
71
34
|
}, []);
|
|
72
|
-
|
|
35
|
+
useEffect(() => {
|
|
73
36
|
if (!apiRef.current) return;
|
|
74
37
|
apiRef.current.applyProps(props);
|
|
75
38
|
}, [props.nodes, props.edges, props.history, props.options]);
|
|
76
|
-
return /* @__PURE__ */
|
|
39
|
+
return /* @__PURE__ */ React.createElement("div", { ref: rootRef, style: { width: "100%", height: "100%" } });
|
|
77
40
|
}
|
|
78
41
|
|
|
79
42
|
// src/Playground.tsx
|
|
80
|
-
|
|
81
|
-
|
|
43
|
+
import React2, { useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
44
|
+
import { Playground as PlaygroundClass } from "@3plate/graph-core";
|
|
82
45
|
function Playground(props) {
|
|
83
|
-
const rootRef = (
|
|
84
|
-
const playgroundRef = (
|
|
85
|
-
const rootIdRef = (
|
|
86
|
-
const prevExamplesRef = (
|
|
87
|
-
(
|
|
46
|
+
const rootRef = useRef2(null);
|
|
47
|
+
const playgroundRef = useRef2(null);
|
|
48
|
+
const rootIdRef = useRef2(`playground-${Math.random().toString(36).slice(2, 11)}`);
|
|
49
|
+
const prevExamplesRef = useRef2({});
|
|
50
|
+
useEffect2(() => {
|
|
88
51
|
if (!rootRef.current || playgroundRef.current) return;
|
|
89
52
|
rootRef.current.id = rootIdRef.current;
|
|
90
|
-
const playground = new
|
|
53
|
+
const playground = new PlaygroundClass({
|
|
91
54
|
root: rootIdRef.current,
|
|
92
55
|
examples: props.examples,
|
|
93
56
|
defaultExample: props.defaultExample
|
|
@@ -99,7 +62,7 @@ function Playground(props) {
|
|
|
99
62
|
playgroundRef.current = null;
|
|
100
63
|
};
|
|
101
64
|
}, []);
|
|
102
|
-
(
|
|
65
|
+
useEffect2(() => {
|
|
103
66
|
if (!playgroundRef.current) return;
|
|
104
67
|
const playground = playgroundRef.current;
|
|
105
68
|
const prev = prevExamplesRef.current;
|
|
@@ -118,7 +81,7 @@ function Playground(props) {
|
|
|
118
81
|
}
|
|
119
82
|
prevExamplesRef.current = { ...current };
|
|
120
83
|
}, [props.examples]);
|
|
121
|
-
return /* @__PURE__ */
|
|
84
|
+
return /* @__PURE__ */ React2.createElement("div", { ref: rootRef, style: { width: "100%", height: "100%" } });
|
|
122
85
|
}
|
|
123
86
|
function shallowEqualExample(a, b) {
|
|
124
87
|
if (a === b) return true;
|
|
@@ -156,8 +119,8 @@ function shallowEqualSource(a, b) {
|
|
|
156
119
|
}
|
|
157
120
|
return false;
|
|
158
121
|
}
|
|
159
|
-
|
|
160
|
-
0 && (module.exports = {
|
|
122
|
+
export {
|
|
161
123
|
Graph,
|
|
162
124
|
Playground
|
|
163
|
-
}
|
|
125
|
+
};
|
|
126
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/Graph.tsx","../src/Playground.tsx"],"sourcesContent":["import React, { useEffect, useRef } from 'react'\nimport { graph, type API } from '@3plate/graph-core'\nimport type { APIArguments, Update, IngestionConfig } from '@3plate/graph-core'\n\nexport type GraphProps<N, E> = {\n /** Initial nodes */\n nodes?: N[]\n /** Initial edges */\n edges?: E[]\n /** Initial history */\n history?: Update<N, E>[]\n /** Ingestion source configuration (alternative to nodes/edges/history) */\n ingestion?: IngestionConfig\n /** Options */\n options?: APIArguments<N, E>['options']\n /** Events */\n events?: APIArguments<N, E>['events']\n}\n\n/**\n * Graph component - renders a graph visualization\n * Intelligently handles prop changes by diffing nodes, edges, and history\n */\nexport function Graph<N, E>(props: GraphProps<N, E>) {\n const rootRef = useRef<HTMLDivElement>(null)\n const apiRef = useRef<API<N, E> | null>(null)\n const rootIdRef = useRef<string>(`graph-${Math.random().toString(36).slice(2, 11)}`)\n\n // Initialize API once\n useEffect(() => {\n if (!rootRef.current || apiRef.current) return\n\n rootRef.current.id = rootIdRef.current\n\n graph({\n root: rootIdRef.current,\n nodes: props.nodes,\n edges: props.edges,\n history: props.history,\n ingestion: props.ingestion,\n options: props.options,\n events: props.events,\n }).then(api => {\n apiRef.current = api\n })\n\n return () => {\n // Cleanup\n if (apiRef.current) {\n apiRef.current.destroy()\n apiRef.current = null\n }\n if (rootRef.current) {\n // Remove canvas from DOM\n const canvas = rootRef.current.querySelector('canvas, svg')\n if (canvas) {\n canvas.remove()\n }\n }\n }\n }, []) // Only run once on mount\n\n // Handle prop changes using the centralized applyProps method\n useEffect(() => {\n if (!apiRef.current) return\n apiRef.current.applyProps(props)\n }, [props.nodes, props.edges, props.history, props.options])\n\n return <div ref={rootRef} style={{ width: '100%', height: '100%' }} />\n}\n","import React, { useEffect, useRef } from 'react'\nimport { Playground as PlaygroundClass, type PlaygroundOptions, type Example } from '@3plate/graph-core'\n\nexport type PlaygroundProps = {\n /** Examples to display */\n examples: PlaygroundOptions['examples']\n /** Default example key */\n defaultExample?: string\n}\n\n/**\n * Playground component - renders the interactive playground with examples\n */\nexport function Playground(props: PlaygroundProps) {\n const rootRef = useRef<HTMLDivElement>(null)\n const playgroundRef = useRef<PlaygroundClass | null>(null)\n const rootIdRef = useRef<string>(`playground-${Math.random().toString(36).slice(2, 11)}`)\n const prevExamplesRef = useRef<Record<string, Example>>({})\n\n useEffect(() => {\n if (!rootRef.current || playgroundRef.current) return\n\n rootRef.current.id = rootIdRef.current\n\n const playground = new PlaygroundClass({\n root: rootIdRef.current,\n examples: props.examples,\n defaultExample: props.defaultExample,\n })\n playgroundRef.current = playground\n prevExamplesRef.current = { ...props.examples }\n playground.init()\n\n return () => {\n // Cleanup if needed\n playgroundRef.current = null\n }\n }, []) // Only initialize once\n\n // Handle examples changes\n useEffect(() => {\n if (!playgroundRef.current) return\n\n const playground = playgroundRef.current\n const prev = prevExamplesRef.current\n const current = props.examples\n\n // Get all keys from both previous and current\n const allKeys = new Set([...Object.keys(prev), ...Object.keys(current)])\n\n for (const key of allKeys) {\n const prevExample = prev[key]\n const currentExample = current[key]\n\n if (!prevExample && currentExample) {\n // Example was added\n playground.addExample(key, currentExample)\n } else if (prevExample && !currentExample) {\n // Example was removed\n playground.removeExample(key)\n } else if (prevExample && currentExample && !shallowEqualExample(prevExample, currentExample)) {\n // Example was modified\n playground.addExample(key, currentExample)\n }\n }\n\n prevExamplesRef.current = { ...current }\n }, [props.examples])\n\n return <div ref={rootRef} style={{ width: '100%', height: '100%' }} />\n}\n\n/**\n * Shallow comparison of two Example objects\n */\nfunction shallowEqualExample(a: Example, b: Example): boolean {\n if (a === b) return true\n if (a.name !== b.name) return false\n if (a.description !== b.description) return false\n if (!shallowEqualArray(a.nodes, b.nodes)) return false\n if (!shallowEqualArray(a.edges, b.edges)) return false\n if (!shallowEqualOptions(a.options, b.options)) return false\n if (!shallowEqualSource(a.source, b.source)) return false\n return true\n}\n\n/**\n * Shallow comparison of arrays\n */\nfunction shallowEqualArray<T>(a: T[] | undefined, b: T[] | undefined): boolean {\n if (a === b) return true\n if (!a || !b) return false\n if (a.length !== b.length) return false\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false\n }\n return true\n}\n\n/**\n * Shallow comparison of ExampleOptions\n */\nfunction shallowEqualOptions(\n a: Example['options'],\n b: Example['options']\n): boolean {\n if (a === b) return true\n if (!a || !b) return false\n // For now, do a simple reference check on options\n // Can be enhanced if needed\n return a === b\n}\n\n/**\n * Shallow comparison of ExampleSource\n */\nfunction shallowEqualSource(\n a: Example['source'],\n b: Example['source']\n): boolean {\n if (a === b) return true\n if (!a || !b) return false\n if (a.type !== b.type) return false\n if (a.type === 'file' && b.type === 'file') {\n return a.path === b.path\n }\n if (a.type === 'websocket' && b.type === 'websocket') {\n return a.url === b.url\n }\n return false\n}\n"],"mappings":"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","names":["React","useEffect","useRef"]}
|
package/package.json
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@3plate/graph-react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"license": "GPL-3.0",
|
|
5
6
|
"repository": {
|
|
6
7
|
"type": "git",
|
|
7
8
|
"url": "https://github.com/3plt/graph",
|
|
8
9
|
"directory": "packages/react"
|
|
9
10
|
},
|
|
10
|
-
"main": "./dist/index.
|
|
11
|
-
"module": "./dist/index.
|
|
11
|
+
"main": "./dist/index.cjs",
|
|
12
|
+
"module": "./dist/index.js",
|
|
12
13
|
"types": "./dist/index.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"import": "./dist/index.js",
|
|
18
|
+
"require": "./dist/index.cjs"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
13
21
|
"files": [
|
|
14
22
|
"dist"
|
|
15
23
|
],
|
|
@@ -21,7 +29,7 @@
|
|
|
21
29
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
22
30
|
},
|
|
23
31
|
"dependencies": {
|
|
24
|
-
"@3plate/graph-core": "0.1.
|
|
32
|
+
"@3plate/graph-core": "0.1.14"
|
|
25
33
|
},
|
|
26
34
|
"devDependencies": {
|
|
27
35
|
"@testing-library/jest-dom": "^6.6.3",
|
|
@@ -35,8 +43,8 @@
|
|
|
35
43
|
"vitest": "^2.1.8"
|
|
36
44
|
},
|
|
37
45
|
"scripts": {
|
|
38
|
-
"build": "tsup src/index.ts --format cjs,esm --dts --external react --external react-dom",
|
|
39
|
-
"dev": "tsup src/index.ts --format cjs,esm --dts --watch --external react --external react-dom",
|
|
46
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --sourcemap --external react --external react-dom",
|
|
47
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --sourcemap --watch --external react --external react-dom",
|
|
40
48
|
"test": "vitest run",
|
|
41
49
|
"test:watch": "vitest"
|
|
42
50
|
}
|
|
File without changes
|