@3plate/graph-vue 0.1.6 → 0.1.9

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 ADDED
@@ -0,0 +1,223 @@
1
+ # @3plate/graph-vue
2
+
3
+ Vue 3 components for @3plate/graph visualization.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @3plate/graph-vue
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Basic Example
14
+
15
+ ```vue
16
+ <script setup lang="ts">
17
+ import { Graph } from '@3plate/graph-vue'
18
+
19
+ const nodes = [
20
+ { id: 'a', title: 'Start' },
21
+ { id: 'b', title: 'Process' },
22
+ { id: 'c', title: 'End' },
23
+ ]
24
+
25
+ const edges = [
26
+ { source: 'a', target: 'b' },
27
+ { source: 'b', target: 'c' },
28
+ ]
29
+ </script>
30
+
31
+ <template>
32
+ <div style="width: 100%; height: 400px">
33
+ <Graph :nodes="nodes" :edges="edges" />
34
+ </div>
35
+ </template>
36
+ ```
37
+
38
+ ### With Options
39
+
40
+ ```vue
41
+ <script setup lang="ts">
42
+ import { Graph } from '@3plate/graph-vue'
43
+
44
+ const nodes = [
45
+ { id: 'input', type: 'input', title: 'Input' },
46
+ { id: 'process', type: 'process', title: 'Process' },
47
+ { id: 'output', type: 'success', title: 'Output' },
48
+ ]
49
+
50
+ const edges = [
51
+ { source: 'input', target: 'process' },
52
+ { source: 'process', target: 'output', type: 'success' },
53
+ ]
54
+
55
+ const options = {
56
+ graph: {
57
+ orientation: 'LR',
58
+ },
59
+ canvas: {
60
+ colorMode: 'dark',
61
+ nodeTypes: {
62
+ input: { border: '#3b82f6' },
63
+ process: { border: '#8b5cf6' },
64
+ success: { bg: '#f0fdf4', border: '#22c55e', text: '#166534' },
65
+ },
66
+ edgeTypes: {
67
+ success: { color: '#22c55e' },
68
+ },
69
+ },
70
+ }
71
+ </script>
72
+
73
+ <template>
74
+ <div style="width: 100%; height: 400px">
75
+ <Graph :nodes="nodes" :edges="edges" :options="options" />
76
+ </div>
77
+ </template>
78
+ ```
79
+
80
+ ### With Events
81
+
82
+ ```vue
83
+ <script setup lang="ts">
84
+ import { Graph } from '@3plate/graph-vue'
85
+
86
+ const nodes = [
87
+ { id: 'a', title: 'Node A' },
88
+ { id: 'b', title: 'Node B' },
89
+ ]
90
+
91
+ const edges = [{ source: 'a', target: 'b' }]
92
+
93
+ const events = {
94
+ nodeClick: (node) => console.log('Clicked:', node),
95
+ edgeClick: (edge) => console.log('Edge clicked:', edge),
96
+ historyChange: (index, length) => {
97
+ console.log(`Step ${index + 1} of ${length}`)
98
+ },
99
+ }
100
+ </script>
101
+
102
+ <template>
103
+ <div style="width: 100%; height: 400px">
104
+ <Graph :nodes="nodes" :edges="edges" :events="events" />
105
+ </div>
106
+ </template>
107
+ ```
108
+
109
+ ### With Real-time Ingestion
110
+
111
+ ```vue
112
+ <script setup lang="ts">
113
+ import { Graph } from '@3plate/graph-vue'
114
+
115
+ // WebSocket ingestion
116
+ const ingestion = {
117
+ type: 'websocket' as const,
118
+ url: 'ws://localhost:8787',
119
+ }
120
+ </script>
121
+
122
+ <template>
123
+ <div style="width: 100%; height: 400px">
124
+ <Graph :ingestion="ingestion" />
125
+ </div>
126
+ </template>
127
+ ```
128
+
129
+ ### Reactive Updates
130
+
131
+ The component automatically handles reactive prop changes:
132
+
133
+ ```vue
134
+ <script setup lang="ts">
135
+ import { ref } from 'vue'
136
+ import { Graph } from '@3plate/graph-vue'
137
+
138
+ const nodes = ref([
139
+ { id: 'a', title: 'Start' },
140
+ { id: 'b', title: 'End' },
141
+ ])
142
+
143
+ const edges = ref([{ source: 'a', target: 'b' }])
144
+
145
+ function addNode() {
146
+ const id = `node-${Date.now()}`
147
+ nodes.value = [...nodes.value, { id, title: `Node ${id}` }]
148
+ edges.value = [...edges.value, { source: 'a', target: id }]
149
+ }
150
+ </script>
151
+
152
+ <template>
153
+ <button @click="addNode">Add Node</button>
154
+ <div style="width: 100%; height: 400px">
155
+ <Graph :nodes="nodes" :edges="edges" />
156
+ </div>
157
+ </template>
158
+ ```
159
+
160
+ ## Props
161
+
162
+ | Prop | Type | Description |
163
+ |------|------|-------------|
164
+ | `nodes` | `N[]` | Array of node objects |
165
+ | `edges` | `E[]` | Array of edge objects |
166
+ | `history` | `Update<N, E>[]` | History frames for time-travel |
167
+ | `ingestion` | `IngestionConfig` | WebSocket or file source config |
168
+ | `options` | `APIOptions` | Graph and canvas options |
169
+ | `events` | `EventsOptions` | Event handlers |
170
+
171
+ ### Playground Component
172
+
173
+ The Playground component provides a full-featured demo environment:
174
+
175
+ ```vue
176
+ <script setup lang="ts">
177
+ import { Playground } from '@3plate/graph-vue'
178
+
179
+ const examples = {
180
+ simple: {
181
+ name: 'Simple Graph',
182
+ description: 'A basic graph example',
183
+ nodes: [
184
+ { id: 'a', title: 'Start' },
185
+ { id: 'b', title: 'End' },
186
+ ],
187
+ edges: [{ source: 'a', target: 'b' }],
188
+ },
189
+ complex: {
190
+ name: 'Complex Graph',
191
+ description: 'A more complex example',
192
+ nodes: [
193
+ { id: '1', title: 'Input' },
194
+ { id: '2', title: 'Process A' },
195
+ { id: '3', title: 'Process B' },
196
+ { id: '4', title: 'Output' },
197
+ ],
198
+ edges: [
199
+ { source: '1', target: '2' },
200
+ { source: '1', target: '3' },
201
+ { source: '2', target: '4' },
202
+ { source: '3', target: '4' },
203
+ ],
204
+ },
205
+ }
206
+ </script>
207
+
208
+ <template>
209
+ <div style="width: 100%; height: 600px">
210
+ <Playground :examples="examples" default-example="simple" />
211
+ </div>
212
+ </template>
213
+ ```
214
+
215
+ ## Features
216
+
217
+ - **Reactive updates** — Props changes are efficiently diffed and applied
218
+ - **Incremental history** — Appended history frames are applied incrementally
219
+ - **Style updates** — Theme and type changes are applied without re-render
220
+ - **Color mode** — Light/dark mode changes are applied instantly
221
+ - **Cleanup** — Resources are properly cleaned up on unmount
222
+ - **Playground** — Full-featured demo environment with example switching
223
+
package/dist/index.d.mts CHANGED
@@ -1,2 +1,135 @@
1
+ import * as _3plate_graph_core from '@3plate/graph-core';
2
+ import { Update, IngestionConfig, APIArguments, PlaygroundOptions } from '@3plate/graph-core';
3
+ export { API, APIArguments, IngestionConfig, Update } from '@3plate/graph-core';
4
+ import * as vue from 'vue';
5
+ import { PropType } from 'vue';
1
6
 
2
- export { }
7
+ type GraphProps<N, E> = {
8
+ /** Initial nodes */
9
+ nodes?: N[];
10
+ /** Initial edges */
11
+ edges?: E[];
12
+ /** Initial history */
13
+ history?: Update<N, E>[];
14
+ /** Ingestion source configuration (alternative to nodes/edges/history) */
15
+ ingestion?: IngestionConfig;
16
+ /** Options */
17
+ options?: APIArguments<N, E>['options'];
18
+ /** Events */
19
+ events?: APIArguments<N, E>['events'];
20
+ };
21
+ /**
22
+ * Graph component - renders a graph visualization
23
+ * Intelligently handles prop changes by diffing nodes, edges, and history
24
+ */
25
+ declare const Graph: vue.DefineComponent<vue.ExtractPropTypes<{
26
+ /** Initial nodes */
27
+ nodes: {
28
+ type: PropType<any[]>;
29
+ default: undefined;
30
+ };
31
+ /** Initial edges */
32
+ edges: {
33
+ type: PropType<any[]>;
34
+ default: undefined;
35
+ };
36
+ /** Initial history */
37
+ history: {
38
+ type: PropType<Update<any, any>[]>;
39
+ default: undefined;
40
+ };
41
+ /** Ingestion source configuration */
42
+ ingestion: {
43
+ type: PropType<IngestionConfig>;
44
+ default: undefined;
45
+ };
46
+ /** Options */
47
+ options: {
48
+ type: PropType<APIArguments<any, any>["options"]>;
49
+ default: undefined;
50
+ };
51
+ /** Events */
52
+ events: {
53
+ type: PropType<APIArguments<any, any>["events"]>;
54
+ default: undefined;
55
+ };
56
+ }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
57
+ [key: string]: any;
58
+ }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
59
+ /** Initial nodes */
60
+ nodes: {
61
+ type: PropType<any[]>;
62
+ default: undefined;
63
+ };
64
+ /** Initial edges */
65
+ edges: {
66
+ type: PropType<any[]>;
67
+ default: undefined;
68
+ };
69
+ /** Initial history */
70
+ history: {
71
+ type: PropType<Update<any, any>[]>;
72
+ default: undefined;
73
+ };
74
+ /** Ingestion source configuration */
75
+ ingestion: {
76
+ type: PropType<IngestionConfig>;
77
+ default: undefined;
78
+ };
79
+ /** Options */
80
+ options: {
81
+ type: PropType<APIArguments<any, any>["options"]>;
82
+ default: undefined;
83
+ };
84
+ /** Events */
85
+ events: {
86
+ type: PropType<APIArguments<any, any>["events"]>;
87
+ default: undefined;
88
+ };
89
+ }>> & Readonly<{}>, {
90
+ options: _3plate_graph_core.APIOptions<any, any> | undefined;
91
+ events: _3plate_graph_core.EventsOptions<any, any> | undefined;
92
+ nodes: any[];
93
+ edges: any[];
94
+ history: Update<any, any>[];
95
+ ingestion: IngestionConfig;
96
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
97
+
98
+ type PlaygroundProps = {
99
+ /** Examples to display */
100
+ examples: PlaygroundOptions['examples'];
101
+ /** Default example key */
102
+ defaultExample?: string;
103
+ };
104
+ /**
105
+ * Playground component - renders the interactive playground with examples
106
+ */
107
+ declare const Playground: vue.DefineComponent<vue.ExtractPropTypes<{
108
+ /** Examples to display */
109
+ examples: {
110
+ type: PropType<PlaygroundOptions["examples"]>;
111
+ required: true;
112
+ };
113
+ /** Default example key */
114
+ defaultExample: {
115
+ type: StringConstructor;
116
+ default: undefined;
117
+ };
118
+ }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
119
+ [key: string]: any;
120
+ }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
121
+ /** Examples to display */
122
+ examples: {
123
+ type: PropType<PlaygroundOptions["examples"]>;
124
+ required: true;
125
+ };
126
+ /** Default example key */
127
+ defaultExample: {
128
+ type: StringConstructor;
129
+ default: undefined;
130
+ };
131
+ }>> & Readonly<{}>, {
132
+ defaultExample: string;
133
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
134
+
135
+ export { Graph, type GraphProps, Playground, type PlaygroundProps };
package/dist/index.d.ts CHANGED
@@ -1,2 +1,135 @@
1
+ import * as _3plate_graph_core from '@3plate/graph-core';
2
+ import { Update, IngestionConfig, APIArguments, PlaygroundOptions } from '@3plate/graph-core';
3
+ export { API, APIArguments, IngestionConfig, Update } from '@3plate/graph-core';
4
+ import * as vue from 'vue';
5
+ import { PropType } from 'vue';
1
6
 
2
- export { }
7
+ type GraphProps<N, E> = {
8
+ /** Initial nodes */
9
+ nodes?: N[];
10
+ /** Initial edges */
11
+ edges?: E[];
12
+ /** Initial history */
13
+ history?: Update<N, E>[];
14
+ /** Ingestion source configuration (alternative to nodes/edges/history) */
15
+ ingestion?: IngestionConfig;
16
+ /** Options */
17
+ options?: APIArguments<N, E>['options'];
18
+ /** Events */
19
+ events?: APIArguments<N, E>['events'];
20
+ };
21
+ /**
22
+ * Graph component - renders a graph visualization
23
+ * Intelligently handles prop changes by diffing nodes, edges, and history
24
+ */
25
+ declare const Graph: vue.DefineComponent<vue.ExtractPropTypes<{
26
+ /** Initial nodes */
27
+ nodes: {
28
+ type: PropType<any[]>;
29
+ default: undefined;
30
+ };
31
+ /** Initial edges */
32
+ edges: {
33
+ type: PropType<any[]>;
34
+ default: undefined;
35
+ };
36
+ /** Initial history */
37
+ history: {
38
+ type: PropType<Update<any, any>[]>;
39
+ default: undefined;
40
+ };
41
+ /** Ingestion source configuration */
42
+ ingestion: {
43
+ type: PropType<IngestionConfig>;
44
+ default: undefined;
45
+ };
46
+ /** Options */
47
+ options: {
48
+ type: PropType<APIArguments<any, any>["options"]>;
49
+ default: undefined;
50
+ };
51
+ /** Events */
52
+ events: {
53
+ type: PropType<APIArguments<any, any>["events"]>;
54
+ default: undefined;
55
+ };
56
+ }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
57
+ [key: string]: any;
58
+ }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
59
+ /** Initial nodes */
60
+ nodes: {
61
+ type: PropType<any[]>;
62
+ default: undefined;
63
+ };
64
+ /** Initial edges */
65
+ edges: {
66
+ type: PropType<any[]>;
67
+ default: undefined;
68
+ };
69
+ /** Initial history */
70
+ history: {
71
+ type: PropType<Update<any, any>[]>;
72
+ default: undefined;
73
+ };
74
+ /** Ingestion source configuration */
75
+ ingestion: {
76
+ type: PropType<IngestionConfig>;
77
+ default: undefined;
78
+ };
79
+ /** Options */
80
+ options: {
81
+ type: PropType<APIArguments<any, any>["options"]>;
82
+ default: undefined;
83
+ };
84
+ /** Events */
85
+ events: {
86
+ type: PropType<APIArguments<any, any>["events"]>;
87
+ default: undefined;
88
+ };
89
+ }>> & Readonly<{}>, {
90
+ options: _3plate_graph_core.APIOptions<any, any> | undefined;
91
+ events: _3plate_graph_core.EventsOptions<any, any> | undefined;
92
+ nodes: any[];
93
+ edges: any[];
94
+ history: Update<any, any>[];
95
+ ingestion: IngestionConfig;
96
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
97
+
98
+ type PlaygroundProps = {
99
+ /** Examples to display */
100
+ examples: PlaygroundOptions['examples'];
101
+ /** Default example key */
102
+ defaultExample?: string;
103
+ };
104
+ /**
105
+ * Playground component - renders the interactive playground with examples
106
+ */
107
+ declare const Playground: vue.DefineComponent<vue.ExtractPropTypes<{
108
+ /** Examples to display */
109
+ examples: {
110
+ type: PropType<PlaygroundOptions["examples"]>;
111
+ required: true;
112
+ };
113
+ /** Default example key */
114
+ defaultExample: {
115
+ type: StringConstructor;
116
+ default: undefined;
117
+ };
118
+ }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
119
+ [key: string]: any;
120
+ }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
121
+ /** Examples to display */
122
+ examples: {
123
+ type: PropType<PlaygroundOptions["examples"]>;
124
+ required: true;
125
+ };
126
+ /** Default example key */
127
+ defaultExample: {
128
+ type: StringConstructor;
129
+ default: undefined;
130
+ };
131
+ }>> & Readonly<{}>, {
132
+ defaultExample: string;
133
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
134
+
135
+ export { Graph, type GraphProps, Playground, type PlaygroundProps };
package/dist/index.js CHANGED
@@ -1 +1,215 @@
1
1
  "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Graph: () => Graph,
24
+ Playground: () => Playground
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/Graph.ts
29
+ var import_vue = require("vue");
30
+ var import_graph_core = require("@3plate/graph-core");
31
+ var Graph = (0, import_vue.defineComponent)({
32
+ name: "Graph",
33
+ props: {
34
+ /** Initial nodes */
35
+ nodes: {
36
+ type: Array,
37
+ default: void 0
38
+ },
39
+ /** Initial edges */
40
+ edges: {
41
+ type: Array,
42
+ default: void 0
43
+ },
44
+ /** Initial history */
45
+ history: {
46
+ type: Array,
47
+ default: void 0
48
+ },
49
+ /** Ingestion source configuration */
50
+ ingestion: {
51
+ type: Object,
52
+ default: void 0
53
+ },
54
+ /** Options */
55
+ options: {
56
+ type: Object,
57
+ default: void 0
58
+ },
59
+ /** Events */
60
+ events: {
61
+ type: Object,
62
+ default: void 0
63
+ }
64
+ },
65
+ setup(props) {
66
+ const rootRef = (0, import_vue.ref)(null);
67
+ const apiRef = (0, import_vue.ref)(null);
68
+ const rootId = `graph-${Math.random().toString(36).slice(2, 11)}`;
69
+ (0, import_vue.onMounted)(async () => {
70
+ if (!rootRef.value) return;
71
+ rootRef.value.id = rootId;
72
+ const api = await (0, import_graph_core.graph)({
73
+ root: rootId,
74
+ nodes: props.nodes,
75
+ edges: props.edges,
76
+ history: props.history,
77
+ ingestion: props.ingestion,
78
+ options: props.options,
79
+ events: props.events
80
+ });
81
+ apiRef.value = api;
82
+ });
83
+ (0, import_vue.onUnmounted)(() => {
84
+ if (apiRef.value) {
85
+ apiRef.value.destroy();
86
+ apiRef.value = null;
87
+ }
88
+ if (rootRef.value) {
89
+ const canvas = rootRef.value.querySelector("canvas, svg");
90
+ if (canvas) {
91
+ canvas.remove();
92
+ }
93
+ }
94
+ });
95
+ (0, import_vue.watch)(
96
+ () => [props.nodes, props.edges, props.history, props.options],
97
+ () => {
98
+ if (!apiRef.value) return;
99
+ apiRef.value.applyProps({ nodes: props.nodes, edges: props.edges, history: props.history, options: props.options });
100
+ },
101
+ { deep: true }
102
+ );
103
+ return () => (0, import_vue.h)("div", {
104
+ ref: rootRef,
105
+ style: { width: "100%", height: "100%" }
106
+ });
107
+ }
108
+ });
109
+
110
+ // src/Playground.ts
111
+ var import_vue2 = require("vue");
112
+ var import_graph_core2 = require("@3plate/graph-core");
113
+ var Playground = (0, import_vue2.defineComponent)({
114
+ name: "Playground",
115
+ props: {
116
+ /** Examples to display */
117
+ examples: {
118
+ type: Object,
119
+ required: true
120
+ },
121
+ /** Default example key */
122
+ defaultExample: {
123
+ type: String,
124
+ default: void 0
125
+ }
126
+ },
127
+ setup(props) {
128
+ const rootRef = (0, import_vue2.ref)(null);
129
+ const playgroundRef = (0, import_vue2.ref)(null);
130
+ const rootId = `playground-${Math.random().toString(36).slice(2, 11)}`;
131
+ const prevExamples = (0, import_vue2.ref)({});
132
+ (0, import_vue2.onMounted)(async () => {
133
+ if (!rootRef.value) return;
134
+ rootRef.value.id = rootId;
135
+ const playground = new import_graph_core2.Playground({
136
+ root: rootId,
137
+ examples: props.examples,
138
+ defaultExample: props.defaultExample
139
+ });
140
+ playgroundRef.value = playground;
141
+ prevExamples.value = { ...props.examples };
142
+ await playground.init();
143
+ });
144
+ (0, import_vue2.onUnmounted)(() => {
145
+ playgroundRef.value = null;
146
+ });
147
+ (0, import_vue2.watch)(
148
+ () => props.examples,
149
+ (current) => {
150
+ if (!playgroundRef.value) return;
151
+ const playground = playgroundRef.value;
152
+ const prev = prevExamples.value;
153
+ const allKeys = /* @__PURE__ */ new Set([...Object.keys(prev), ...Object.keys(current)]);
154
+ for (const key of allKeys) {
155
+ const prevExample = prev[key];
156
+ const currentExample = current[key];
157
+ if (!prevExample && currentExample) {
158
+ playground.addExample(key, currentExample);
159
+ } else if (prevExample && !currentExample) {
160
+ playground.removeExample(key);
161
+ } else if (prevExample && currentExample && !shallowEqualExample(prevExample, currentExample)) {
162
+ playground.addExample(key, currentExample);
163
+ }
164
+ }
165
+ prevExamples.value = { ...current };
166
+ },
167
+ { deep: true }
168
+ );
169
+ return () => (0, import_vue2.h)("div", {
170
+ ref: rootRef,
171
+ style: { width: "100%", height: "100%" }
172
+ });
173
+ }
174
+ });
175
+ function shallowEqualExample(a, b) {
176
+ if (a === b) return true;
177
+ if (a.name !== b.name) return false;
178
+ if (a.description !== b.description) return false;
179
+ if (!shallowEqualArray(a.nodes, b.nodes)) return false;
180
+ if (!shallowEqualArray(a.edges, b.edges)) return false;
181
+ if (!shallowEqualOptions(a.options, b.options)) return false;
182
+ if (!shallowEqualSource(a.source, b.source)) return false;
183
+ return true;
184
+ }
185
+ function shallowEqualArray(a, b) {
186
+ if (a === b) return true;
187
+ if (!a || !b) return false;
188
+ if (a.length !== b.length) return false;
189
+ for (let i = 0; i < a.length; i++) {
190
+ if (a[i] !== b[i]) return false;
191
+ }
192
+ return true;
193
+ }
194
+ function shallowEqualOptions(a, b) {
195
+ if (a === b) return true;
196
+ if (!a || !b) return false;
197
+ return a === b;
198
+ }
199
+ function shallowEqualSource(a, b) {
200
+ if (a === b) return true;
201
+ if (!a || !b) return false;
202
+ if (a.type !== b.type) return false;
203
+ if (a.type === "file" && b.type === "file") {
204
+ return a.path === b.path;
205
+ }
206
+ if (a.type === "websocket" && b.type === "websocket") {
207
+ return a.url === b.url;
208
+ }
209
+ return false;
210
+ }
211
+ // Annotate the CommonJS export names for ESM import in node:
212
+ 0 && (module.exports = {
213
+ Graph,
214
+ Playground
215
+ });
package/dist/index.mjs CHANGED
@@ -0,0 +1,187 @@
1
+ // src/Graph.ts
2
+ import { defineComponent, ref, onMounted, onUnmounted, watch, h } from "vue";
3
+ import { graph } from "@3plate/graph-core";
4
+ var Graph = defineComponent({
5
+ name: "Graph",
6
+ props: {
7
+ /** Initial nodes */
8
+ nodes: {
9
+ type: Array,
10
+ default: void 0
11
+ },
12
+ /** Initial edges */
13
+ edges: {
14
+ type: Array,
15
+ default: void 0
16
+ },
17
+ /** Initial history */
18
+ history: {
19
+ type: Array,
20
+ default: void 0
21
+ },
22
+ /** Ingestion source configuration */
23
+ ingestion: {
24
+ type: Object,
25
+ default: void 0
26
+ },
27
+ /** Options */
28
+ options: {
29
+ type: Object,
30
+ default: void 0
31
+ },
32
+ /** Events */
33
+ events: {
34
+ type: Object,
35
+ default: void 0
36
+ }
37
+ },
38
+ setup(props) {
39
+ const rootRef = ref(null);
40
+ const apiRef = ref(null);
41
+ const rootId = `graph-${Math.random().toString(36).slice(2, 11)}`;
42
+ onMounted(async () => {
43
+ if (!rootRef.value) return;
44
+ rootRef.value.id = rootId;
45
+ const api = await graph({
46
+ root: rootId,
47
+ nodes: props.nodes,
48
+ edges: props.edges,
49
+ history: props.history,
50
+ ingestion: props.ingestion,
51
+ options: props.options,
52
+ events: props.events
53
+ });
54
+ apiRef.value = api;
55
+ });
56
+ onUnmounted(() => {
57
+ if (apiRef.value) {
58
+ apiRef.value.destroy();
59
+ apiRef.value = null;
60
+ }
61
+ if (rootRef.value) {
62
+ const canvas = rootRef.value.querySelector("canvas, svg");
63
+ if (canvas) {
64
+ canvas.remove();
65
+ }
66
+ }
67
+ });
68
+ watch(
69
+ () => [props.nodes, props.edges, props.history, props.options],
70
+ () => {
71
+ if (!apiRef.value) return;
72
+ apiRef.value.applyProps({ nodes: props.nodes, edges: props.edges, history: props.history, options: props.options });
73
+ },
74
+ { deep: true }
75
+ );
76
+ return () => h("div", {
77
+ ref: rootRef,
78
+ style: { width: "100%", height: "100%" }
79
+ });
80
+ }
81
+ });
82
+
83
+ // src/Playground.ts
84
+ import { defineComponent as defineComponent2, ref as ref2, onMounted as onMounted2, onUnmounted as onUnmounted2, watch as watch2, h as h2 } from "vue";
85
+ import { Playground as PlaygroundClass } from "@3plate/graph-core";
86
+ var Playground = defineComponent2({
87
+ name: "Playground",
88
+ props: {
89
+ /** Examples to display */
90
+ examples: {
91
+ type: Object,
92
+ required: true
93
+ },
94
+ /** Default example key */
95
+ defaultExample: {
96
+ type: String,
97
+ default: void 0
98
+ }
99
+ },
100
+ setup(props) {
101
+ const rootRef = ref2(null);
102
+ const playgroundRef = ref2(null);
103
+ const rootId = `playground-${Math.random().toString(36).slice(2, 11)}`;
104
+ const prevExamples = ref2({});
105
+ onMounted2(async () => {
106
+ if (!rootRef.value) return;
107
+ rootRef.value.id = rootId;
108
+ const playground = new PlaygroundClass({
109
+ root: rootId,
110
+ examples: props.examples,
111
+ defaultExample: props.defaultExample
112
+ });
113
+ playgroundRef.value = playground;
114
+ prevExamples.value = { ...props.examples };
115
+ await playground.init();
116
+ });
117
+ onUnmounted2(() => {
118
+ playgroundRef.value = null;
119
+ });
120
+ watch2(
121
+ () => props.examples,
122
+ (current) => {
123
+ if (!playgroundRef.value) return;
124
+ const playground = playgroundRef.value;
125
+ const prev = prevExamples.value;
126
+ const allKeys = /* @__PURE__ */ new Set([...Object.keys(prev), ...Object.keys(current)]);
127
+ for (const key of allKeys) {
128
+ const prevExample = prev[key];
129
+ const currentExample = current[key];
130
+ if (!prevExample && currentExample) {
131
+ playground.addExample(key, currentExample);
132
+ } else if (prevExample && !currentExample) {
133
+ playground.removeExample(key);
134
+ } else if (prevExample && currentExample && !shallowEqualExample(prevExample, currentExample)) {
135
+ playground.addExample(key, currentExample);
136
+ }
137
+ }
138
+ prevExamples.value = { ...current };
139
+ },
140
+ { deep: true }
141
+ );
142
+ return () => h2("div", {
143
+ ref: rootRef,
144
+ style: { width: "100%", height: "100%" }
145
+ });
146
+ }
147
+ });
148
+ function shallowEqualExample(a, b) {
149
+ if (a === b) return true;
150
+ if (a.name !== b.name) return false;
151
+ if (a.description !== b.description) return false;
152
+ if (!shallowEqualArray(a.nodes, b.nodes)) return false;
153
+ if (!shallowEqualArray(a.edges, b.edges)) return false;
154
+ if (!shallowEqualOptions(a.options, b.options)) return false;
155
+ if (!shallowEqualSource(a.source, b.source)) return false;
156
+ return true;
157
+ }
158
+ function shallowEqualArray(a, b) {
159
+ if (a === b) return true;
160
+ if (!a || !b) return false;
161
+ if (a.length !== b.length) return false;
162
+ for (let i = 0; i < a.length; i++) {
163
+ if (a[i] !== b[i]) return false;
164
+ }
165
+ return true;
166
+ }
167
+ function shallowEqualOptions(a, b) {
168
+ if (a === b) return true;
169
+ if (!a || !b) return false;
170
+ return a === b;
171
+ }
172
+ function shallowEqualSource(a, b) {
173
+ if (a === b) return true;
174
+ if (!a || !b) return false;
175
+ if (a.type !== b.type) return false;
176
+ if (a.type === "file" && b.type === "file") {
177
+ return a.path === b.path;
178
+ }
179
+ if (a.type === "websocket" && b.type === "websocket") {
180
+ return a.url === b.url;
181
+ }
182
+ return false;
183
+ }
184
+ export {
185
+ Graph,
186
+ Playground
187
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@3plate/graph-vue",
3
- "version": "0.1.6",
3
+ "version": "0.1.9",
4
4
  "license": "GPL-3.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -20,7 +20,7 @@
20
20
  "vue": "^3.3.0"
21
21
  },
22
22
  "dependencies": {
23
- "@3plate/graph-core": "0.1.6"
23
+ "@3plate/graph-core": "0.1.9"
24
24
  },
25
25
  "devDependencies": {
26
26
  "tsup": "^8.5.1",