Skip to content

Commit eb23b60

Browse files
committed
feat: add initial connections and update node positions in simple.dart; improve code previews and move quick-start code to a separate file
1 parent ff171a7 commit eb23b60

File tree

5 files changed

+101
-80
lines changed

5 files changed

+101
-80
lines changed

packages/demo/lib/examples/simple.dart

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,28 @@ class _SimpleNodeAdditionExampleState extends State<SimpleNodeAdditionExample>
3232
for (final node in _createInitialNodes()) {
3333
_controller.addNode(node);
3434
}
35+
for (final connection in _createInitialConnections()) {
36+
_controller.addConnection(connection);
37+
}
38+
}
39+
40+
static List<Connection> _createInitialConnections() {
41+
return [
42+
Connection(
43+
id: 'conn-1',
44+
sourceNodeId: 'node-1',
45+
sourcePortId: 'output',
46+
targetNodeId: 'node-2',
47+
targetPortId: 'input',
48+
),
49+
Connection(
50+
id: 'conn-2',
51+
sourceNodeId: 'node-2',
52+
sourcePortId: 'output',
53+
targetNodeId: 'node-3',
54+
targetPortId: 'input',
55+
),
56+
];
3557
}
3658

3759
static List<Node<Map<String, dynamic>>> _createInitialNodes() {
@@ -62,7 +84,7 @@ class _SimpleNodeAdditionExampleState extends State<SimpleNodeAdditionExample>
6284
Node<Map<String, dynamic>>(
6385
id: 'node-2',
6486
type: 'simple',
65-
position: const Offset(350, 100),
87+
position: const Offset(350, 150),
6688
data: {'label': 'Node 2'},
6789
size: const Size(150, 100),
6890
inputPorts: [
@@ -85,7 +107,7 @@ class _SimpleNodeAdditionExampleState extends State<SimpleNodeAdditionExample>
85107
Node<Map<String, dynamic>>(
86108
id: 'node-3',
87109
type: 'simple',
88-
position: const Offset(350, 250),
110+
position: const Offset(600, 150),
89111
data: {'label': 'Node 3'},
90112
size: const Size(150, 100),
91113
inputPorts: [
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:vyuh_node_flow/vyuh_node_flow.dart';
3+
4+
void main() => runApp(MaterialApp(home: SimpleFlowEditor())); // [!code focus]
5+
6+
class SimpleFlowEditor extends StatefulWidget {
7+
@override
8+
State<SimpleFlowEditor> createState() => _SimpleFlowEditorState();
9+
}
10+
11+
class _SimpleFlowEditorState extends State<SimpleFlowEditor> {
12+
13+
final _controller = NodeFlowController<String>( // [!code focus]
14+
nodes: [ // [!code focus]
15+
Node(id: 'a', position: Offset(100, 150), data: 'Node 1', // [!code focus]
16+
outputPorts: [Port(id: 'out')]), // [!code focus]
17+
Node(id: 'b', position: Offset(350, 150), data: 'Node 2', // [!code focus]
18+
inputPorts: [Port(id: 'in')], outputPorts: [Port(id: 'out')]), // [!code focus]
19+
Node(id: 'c', position: Offset(600, 150), data: 'Node 3', // [!code focus]
20+
inputPorts: [Port(id: 'in')]), // [!code focus]
21+
], // [!code focus]
22+
connections: [ // [!code focus]
23+
Connection(id: 'c1', sourceNodeId: 'a', sourcePortId: 'out', // [!code focus]
24+
targetNodeId: 'b', targetPortId: 'in'), // [!code focus]
25+
Connection(id: 'c2', sourceNodeId: 'b', sourcePortId: 'out', // [!code focus]
26+
targetNodeId: 'c', targetPortId: 'in'), // [!code focus]
27+
], // [!code focus]
28+
); // [!code focus]
29+
30+
@override
31+
Widget build(BuildContext context) => NodeFlowEditor<String>( // [!code focus]
32+
controller: _controller, // [!code focus]
33+
theme: NodeFlowTheme.light, // [!code focus]
34+
nodeBuilder: _buildNode, // [!code focus]
35+
); // [!code focus]
36+
37+
Widget _buildNode(BuildContext context, Node<String> node) { // [!code focus]
38+
return Container( // [!code focus]
39+
padding: EdgeInsets.all(16), // [!code focus]
40+
decoration: BoxDecoration( // [!code focus]
41+
color: Colors.indigo.shade100, // [!code focus]
42+
borderRadius: BorderRadius.circular(6), // [!code focus]
43+
), // [!code focus]
44+
child: Text(node.data, style: TextStyle(fontWeight: FontWeight.bold)), // [!code focus]
45+
); // [!code focus]
46+
} // [!code focus]
47+
48+
}

website/.vitepress/theme/components/CodePreview.vue

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,15 @@ onUnmounted(() => {
217217
min-width: 100%;
218218
}
219219
220+
/* Preserve height for empty/blank lines */
221+
.code-body :deep(.line) {
222+
min-height: 1.5em;
223+
}
224+
225+
.code-body :deep(.line:empty)::before {
226+
content: ' ';
227+
}
228+
220229
/* Shiki Line Focus Styling */
221230
.code-body :deep(.has-focused-lines .line:not(.focused)) {
222231
@apply opacity-35 transition-all duration-300;

website/.vitepress/theme/components/QuickStartSection.vue

Lines changed: 19 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -5,96 +5,37 @@ import SectionHeader from './SectionHeader.vue';
55
import TabbedCodePreview, { type CodeTab } from './TabbedCodePreview.vue';
66
import { usePubVersion } from '../composables/usePubVersion';
77
8+
// Import code sample as raw text
9+
import mainDartCode from '../code-samples/quick-start.dart?raw';
10+
811
// Fetch latest version from pub.dev
912
const { version, loading } = usePubVersion('vyuh_node_flow');
1013
11-
// Code example for the Quick Start section - main.dart
12-
const mainDartCode = `import 'package:flutter/material.dart';
13-
import 'package:vyuh_node_flow/vyuh_node_flow.dart';
14-
15-
void main() => runApp(const MyApp()); // [!code focus]
16-
17-
class MyApp extends StatelessWidget {
18-
const MyApp({super.key});
19-
20-
@override
21-
Widget build(BuildContext context) {
22-
return MaterialApp( // [!code focus]
23-
title: 'Node Flow Demo',
24-
theme: ThemeData.light(useMaterial3: true),
25-
home: const SimpleFlowEditor(), // [!code focus]
26-
);
27-
}
28-
}
29-
30-
class SimpleFlowEditor extends StatefulWidget {
31-
const SimpleFlowEditor({super.key});
32-
33-
@override
34-
State<SimpleFlowEditor> createState() => _SimpleFlowEditorState();
35-
}
36-
37-
class _SimpleFlowEditorState extends State<SimpleFlowEditor> {
38-
late final controller = NodeFlowController<String>( // [!code focus]
39-
nodes: [
40-
Node<String>(
41-
id: 'node-1',
42-
position: const Offset(100, 100),
43-
size: const Size(150, 60),
44-
data: 'Input Node',
45-
outputPorts: const [Port(id: 'out')],
46-
),
47-
Node<String>(
48-
id: 'node-2',
49-
position: const Offset(400, 100),
50-
size: const Size(150, 60),
51-
data: 'Output Node',
52-
inputPorts: const [Port(id: 'in')],
53-
),
54-
],
55-
connections: [
56-
Connection(
57-
id: 'conn-1',
58-
sourceNodeId: 'node-1', sourcePortId: 'out',
59-
targetNodeId: 'node-2', targetPortId: 'in',
60-
),
61-
],
62-
);
63-
64-
@override
65-
Widget build(BuildContext context) => NodeFlowEditor<String>( // [!code focus]
66-
controller: controller,
67-
theme: NodeFlowTheme.light,
68-
nodeBuilder: (context, node) => Container(
69-
padding: const EdgeInsets.all(16),
70-
decoration: BoxDecoration(
71-
color: Colors.white,
72-
borderRadius: BorderRadius.circular(6),
73-
),
74-
child: Center(child: Text(node.data)),
75-
),
76-
);
77-
}`;
78-
7914
// Code markers for main.dart
8015
const mainDartMarkers = [
8116
{
8217
line: 4,
83-
title: 'Entry Point',
18+
title: 'App Entry',
19+
description:
20+
'Standard Flutter entry point with MaterialApp wrapping the flow editor.',
21+
},
22+
{
23+
line: 13,
24+
title: 'Controller Setup',
8425
description:
85-
'Standard Flutter entry point. The app starts with MyApp which sets up MaterialApp with theming.',
26+
'NodeFlowController manages the graph state. Define nodes with positions, data, and ports. Connections link output ports to input ports.',
8627
},
8728
{
88-
line: 27,
89-
title: 'NodeFlowController',
29+
line: 31,
30+
title: 'NodeFlowEditor',
9031
description:
91-
'The main controller that manages nodes and connections. Provides programmatic control over the editor.',
32+
'The editor widget renders the canvas with pan, zoom, drag, and connection creation built-in.',
9233
},
9334
{
94-
line: 54,
95-
title: 'NodeFlowEditor Widget',
35+
line: 37,
36+
title: 'Node Builder',
9637
description:
97-
'The Flutter widget that renders the visual editor with pan & zoom, node dragging, and connection creation.',
38+
'Customize how each node looks. Receives node data to render any Flutter widget.',
9839
},
9940
];
10041
@@ -147,7 +88,8 @@ const codeTabs = computed<CodeTab[]>(() => [
14788
label: 'Preview',
14889
icon: 'ph:play-fill',
14990
isPreview: true,
150-
previewUrl: 'flow.demo.vyuh.tech/#/basics/simple',
91+
previewUrl:
92+
'https://flow.demo.vyuh.tech/#/getting-started/simple?embed=true',
15193
previewTitle: 'Simple Flow Editor',
15294
},
15395
]);

website/.vitepress/theme/components/TabbedCodePreview.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const activeTab = ref(props.tabs[0]?.id || '');
5555
<!-- Preview Tab -->
5656
<div v-else-if="tab.isPreview" class="preview-panel">
5757
<iframe
58-
:src="'https://' + (tab.previewUrl || 'flow.demo.vyuh.tech')"
58+
:src="tab.previewUrl"
5959
:title="tab.previewTitle || 'Preview'"
6060
class="preview-iframe"
6161
loading="lazy"

0 commit comments

Comments
 (0)