pict-section-flow 0.0.1
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/LICENSE +21 -0
- package/example_application/css/flowexample.css +65 -0
- package/example_application/html/index.html +32 -0
- package/example_application/package.json +41 -0
- package/example_application/source/Pict-Application-FlowExample-Configuration.json +15 -0
- package/example_application/source/Pict-Application-FlowExample.js +241 -0
- package/example_application/source/providers/PictRouter-FlowExample-Configuration.json +22 -0
- package/example_application/source/views/PictView-FlowExample-About.js +184 -0
- package/example_application/source/views/PictView-FlowExample-BottomBar.js +77 -0
- package/example_application/source/views/PictView-FlowExample-Documentation.js +325 -0
- package/example_application/source/views/PictView-FlowExample-Layout.js +86 -0
- package/example_application/source/views/PictView-FlowExample-MainWorkspace.js +191 -0
- package/example_application/source/views/PictView-FlowExample-TopBar.js +95 -0
- package/package.json +22 -0
- package/source/Pict-Section-Flow.js +19 -0
- package/source/providers/PictProvider-Flow-EventHandler.js +158 -0
- package/source/providers/PictProvider-Flow-NodeTypes.js +174 -0
- package/source/services/PictService-Flow-ConnectionRenderer.js +251 -0
- package/source/services/PictService-Flow-InteractionManager.js +567 -0
- package/source/services/PictService-Flow-Layout.js +207 -0
- package/source/views/PictView-Flow-Node.js +267 -0
- package/source/views/PictView-Flow-Toolbar.js +223 -0
- package/source/views/PictView-Flow.js +1116 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Steven Velozo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
Pict Section Flow Example - Base Styles
|
|
3
|
+
============================================================================ */
|
|
4
|
+
|
|
5
|
+
/* Reset and base */
|
|
6
|
+
*, *::before, *::after {
|
|
7
|
+
box-sizing: border-box;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
html, body {
|
|
11
|
+
margin: 0;
|
|
12
|
+
padding: 0;
|
|
13
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
14
|
+
font-size: 16px;
|
|
15
|
+
line-height: 1.5;
|
|
16
|
+
color: #333;
|
|
17
|
+
background-color: #f5f7fa;
|
|
18
|
+
-webkit-font-smoothing: antialiased;
|
|
19
|
+
-moz-osx-font-smoothing: grayscale;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* Typography */
|
|
23
|
+
h1, h2, h3, h4, h5, h6 {
|
|
24
|
+
margin-top: 0;
|
|
25
|
+
line-height: 1.3;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
a {
|
|
29
|
+
color: #3498db;
|
|
30
|
+
text-decoration: none;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
a:hover {
|
|
34
|
+
color: #2980b9;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* Application container */
|
|
38
|
+
#FlowExample-Application-Container {
|
|
39
|
+
min-height: 100vh;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* Utility: scrollbar styling */
|
|
43
|
+
::-webkit-scrollbar {
|
|
44
|
+
width: 8px;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
::-webkit-scrollbar-track {
|
|
48
|
+
background: #f1f1f1;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
::-webkit-scrollbar-thumb {
|
|
52
|
+
background: #bdc3c7;
|
|
53
|
+
border-radius: 4px;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
::-webkit-scrollbar-thumb:hover {
|
|
57
|
+
background: #95a5a6;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* Responsive adjustments */
|
|
61
|
+
@media (max-width: 768px) {
|
|
62
|
+
html {
|
|
63
|
+
font-size: 14px;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
7
|
+
<meta name="description" content="Pict Section Flow Example Application">
|
|
8
|
+
|
|
9
|
+
<title>Pict Section Flow</title>
|
|
10
|
+
|
|
11
|
+
<!-- Application Stylesheet -->
|
|
12
|
+
<link href="css/flowexample.css" rel="stylesheet">
|
|
13
|
+
<!-- PICT Dynamic View CSS Container -->
|
|
14
|
+
<style id="PICT-CSS"></style>
|
|
15
|
+
|
|
16
|
+
<!-- Load the PICT library -->
|
|
17
|
+
<script src="./js/pict.min.js" type="text/javascript"></script>
|
|
18
|
+
<!-- Bootstrap the Application -->
|
|
19
|
+
<script type="text/javascript">
|
|
20
|
+
//<![CDATA[
|
|
21
|
+
Pict.safeOnDocumentReady(() => { Pict.safeLoadPictApplication(PictSectionFlowExample, 2)});
|
|
22
|
+
//]]>
|
|
23
|
+
</script>
|
|
24
|
+
</head>
|
|
25
|
+
<body>
|
|
26
|
+
<!-- The root container for the Pict application -->
|
|
27
|
+
<div id="FlowExample-Application-Container"></div>
|
|
28
|
+
|
|
29
|
+
<!-- Load the FlowExample PICT Application Bundle -->
|
|
30
|
+
<script src="./pict-section-flow-example.compatible.min.js" type="text/javascript"></script>
|
|
31
|
+
</body>
|
|
32
|
+
</html>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pict-section-flow-example",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Pict Section Flow Example Application",
|
|
5
|
+
"main": "source/Pict-Application-FlowExample.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "node source/Pict-Application-FlowExample.js",
|
|
8
|
+
"build": "npx quack build && npx quack copy",
|
|
9
|
+
"test": "echo \"Error: no test specified\" && exit 0"
|
|
10
|
+
},
|
|
11
|
+
"author": "steven velozo <steven@velozo.com>",
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"pict": "^1.0.343",
|
|
15
|
+
"pict-application": "^1.0.28",
|
|
16
|
+
"pict-router": "^1.0.4",
|
|
17
|
+
"pict-view": "^1.0.64",
|
|
18
|
+
"pict-provider": "^1.0.3",
|
|
19
|
+
"pict-section-flow": "file:../"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"quackage": "^1.0.42"
|
|
23
|
+
},
|
|
24
|
+
"copyFilesSettings": {
|
|
25
|
+
"whenFileExists": "overwrite"
|
|
26
|
+
},
|
|
27
|
+
"copyFiles": [
|
|
28
|
+
{
|
|
29
|
+
"from": "./html/*",
|
|
30
|
+
"to": "./dist/"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"from": "./css/**",
|
|
34
|
+
"to": "./dist/css/"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"from": "./node_modules/pict/dist/*",
|
|
38
|
+
"to": "./dist/js/"
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"Name": "Pict Section Flow Example",
|
|
3
|
+
"Hash": "FlowExample",
|
|
4
|
+
|
|
5
|
+
"MainViewportViewIdentifier": "FlowExample-Layout",
|
|
6
|
+
|
|
7
|
+
"AutoSolveAfterInitialize": true,
|
|
8
|
+
"AutoRenderMainViewportViewAfterInitialize": false,
|
|
9
|
+
"AutoRenderViewsAfterInitialize": false,
|
|
10
|
+
|
|
11
|
+
"pict_configuration":
|
|
12
|
+
{
|
|
13
|
+
"Product": "FlowExample-Pict-Application"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
const libPictApplication = require('pict-application');
|
|
2
|
+
const libPictRouter = require('pict-router');
|
|
3
|
+
|
|
4
|
+
// Views
|
|
5
|
+
const libViewLayout = require('./views/PictView-FlowExample-Layout.js');
|
|
6
|
+
const libViewTopBar = require('./views/PictView-FlowExample-TopBar.js');
|
|
7
|
+
const libViewBottomBar = require('./views/PictView-FlowExample-BottomBar.js');
|
|
8
|
+
const libViewMainWorkspace = require('./views/PictView-FlowExample-MainWorkspace.js');
|
|
9
|
+
const libViewAbout = require('./views/PictView-FlowExample-About.js');
|
|
10
|
+
const libViewDocumentation = require('./views/PictView-FlowExample-Documentation.js');
|
|
11
|
+
|
|
12
|
+
class FlowExampleApplication extends libPictApplication
|
|
13
|
+
{
|
|
14
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
15
|
+
{
|
|
16
|
+
super(pFable, pOptions, pServiceHash);
|
|
17
|
+
|
|
18
|
+
// Add the router provider with routes
|
|
19
|
+
this.pict.addProvider('PictRouter', require('./providers/PictRouter-FlowExample-Configuration.json'), libPictRouter);
|
|
20
|
+
|
|
21
|
+
// Add the layout view (the shell that contains top bar, workspace, bottom bar)
|
|
22
|
+
this.pict.addView('FlowExample-Layout', libViewLayout.default_configuration, libViewLayout);
|
|
23
|
+
|
|
24
|
+
// Add the top bar and bottom bar views
|
|
25
|
+
this.pict.addView('FlowExample-TopBar', libViewTopBar.default_configuration, libViewTopBar);
|
|
26
|
+
this.pict.addView('FlowExample-BottomBar', libViewBottomBar.default_configuration, libViewBottomBar);
|
|
27
|
+
|
|
28
|
+
// Add the main content workspace view
|
|
29
|
+
this.pict.addView('FlowExample-MainWorkspace', libViewMainWorkspace.default_configuration, libViewMainWorkspace);
|
|
30
|
+
|
|
31
|
+
// Add the about page view
|
|
32
|
+
this.pict.addView('FlowExample-About', libViewAbout.default_configuration, libViewAbout);
|
|
33
|
+
|
|
34
|
+
// Add the documentation page view
|
|
35
|
+
this.pict.addView('FlowExample-Documentation', libViewDocumentation.default_configuration, libViewDocumentation);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
onAfterInitializeAsync(fCallback)
|
|
39
|
+
{
|
|
40
|
+
// Initialize application state
|
|
41
|
+
this.pict.AppData.FlowExample =
|
|
42
|
+
{
|
|
43
|
+
CurrentRoute: 'home'
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Initialize sample flow data
|
|
47
|
+
this.pict.AppData.FlowExample.SampleFlow =
|
|
48
|
+
{
|
|
49
|
+
Nodes:
|
|
50
|
+
[
|
|
51
|
+
{
|
|
52
|
+
Hash: 'node-start',
|
|
53
|
+
Type: 'start',
|
|
54
|
+
X: 50,
|
|
55
|
+
Y: 150,
|
|
56
|
+
Width: 140,
|
|
57
|
+
Height: 80,
|
|
58
|
+
Title: 'Start',
|
|
59
|
+
Ports:
|
|
60
|
+
[
|
|
61
|
+
{ Hash: 'port-start-out', Direction: 'output', Side: 'right', Label: 'Out' }
|
|
62
|
+
],
|
|
63
|
+
Data: {}
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
Hash: 'node-process-1',
|
|
67
|
+
Type: 'default',
|
|
68
|
+
X: 300,
|
|
69
|
+
Y: 80,
|
|
70
|
+
Width: 180,
|
|
71
|
+
Height: 80,
|
|
72
|
+
Title: 'Validate',
|
|
73
|
+
Ports:
|
|
74
|
+
[
|
|
75
|
+
{ Hash: 'port-proc1-in', Direction: 'input', Side: 'left', Label: 'In' },
|
|
76
|
+
{ Hash: 'port-proc1-out', Direction: 'output', Side: 'right', Label: 'Out' }
|
|
77
|
+
],
|
|
78
|
+
Data: {}
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
Hash: 'node-decision',
|
|
82
|
+
Type: 'decision',
|
|
83
|
+
X: 580,
|
|
84
|
+
Y: 100,
|
|
85
|
+
Width: 200,
|
|
86
|
+
Height: 100,
|
|
87
|
+
Title: 'Valid?',
|
|
88
|
+
Ports:
|
|
89
|
+
[
|
|
90
|
+
{ Hash: 'port-dec-in', Direction: 'input', Side: 'left', Label: 'In' },
|
|
91
|
+
{ Hash: 'port-dec-yes', Direction: 'output', Side: 'right', Label: 'Yes' },
|
|
92
|
+
{ Hash: 'port-dec-no', Direction: 'output', Side: 'bottom', Label: 'No' }
|
|
93
|
+
],
|
|
94
|
+
Data: {}
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
Hash: 'node-process-2',
|
|
98
|
+
Type: 'default',
|
|
99
|
+
X: 880,
|
|
100
|
+
Y: 80,
|
|
101
|
+
Width: 180,
|
|
102
|
+
Height: 80,
|
|
103
|
+
Title: 'Process',
|
|
104
|
+
Ports:
|
|
105
|
+
[
|
|
106
|
+
{ Hash: 'port-proc2-in', Direction: 'input', Side: 'left', Label: 'In' },
|
|
107
|
+
{ Hash: 'port-proc2-out', Direction: 'output', Side: 'right', Label: 'Out' }
|
|
108
|
+
],
|
|
109
|
+
Data: {}
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
Hash: 'node-error',
|
|
113
|
+
Type: 'default',
|
|
114
|
+
X: 600,
|
|
115
|
+
Y: 320,
|
|
116
|
+
Width: 180,
|
|
117
|
+
Height: 80,
|
|
118
|
+
Title: 'Error',
|
|
119
|
+
Ports:
|
|
120
|
+
[
|
|
121
|
+
{ Hash: 'port-err-in', Direction: 'input', Side: 'top', Label: 'In' },
|
|
122
|
+
{ Hash: 'port-err-out', Direction: 'output', Side: 'right', Label: 'Out' }
|
|
123
|
+
],
|
|
124
|
+
Data: {}
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
Hash: 'node-end',
|
|
128
|
+
Type: 'end',
|
|
129
|
+
X: 1160,
|
|
130
|
+
Y: 150,
|
|
131
|
+
Width: 140,
|
|
132
|
+
Height: 80,
|
|
133
|
+
Title: 'End',
|
|
134
|
+
Ports:
|
|
135
|
+
[
|
|
136
|
+
{ Hash: 'port-end-in', Direction: 'input', Side: 'left', Label: 'In' }
|
|
137
|
+
],
|
|
138
|
+
Data: {}
|
|
139
|
+
}
|
|
140
|
+
],
|
|
141
|
+
Connections:
|
|
142
|
+
[
|
|
143
|
+
{
|
|
144
|
+
Hash: 'conn-1',
|
|
145
|
+
SourceNodeHash: 'node-start',
|
|
146
|
+
SourcePortHash: 'port-start-out',
|
|
147
|
+
TargetNodeHash: 'node-process-1',
|
|
148
|
+
TargetPortHash: 'port-proc1-in',
|
|
149
|
+
Data: {}
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
Hash: 'conn-2',
|
|
153
|
+
SourceNodeHash: 'node-process-1',
|
|
154
|
+
SourcePortHash: 'port-proc1-out',
|
|
155
|
+
TargetNodeHash: 'node-decision',
|
|
156
|
+
TargetPortHash: 'port-dec-in',
|
|
157
|
+
Data: {}
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
Hash: 'conn-3',
|
|
161
|
+
SourceNodeHash: 'node-decision',
|
|
162
|
+
SourcePortHash: 'port-dec-yes',
|
|
163
|
+
TargetNodeHash: 'node-process-2',
|
|
164
|
+
TargetPortHash: 'port-proc2-in',
|
|
165
|
+
Data: {}
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
Hash: 'conn-4',
|
|
169
|
+
SourceNodeHash: 'node-decision',
|
|
170
|
+
SourcePortHash: 'port-dec-no',
|
|
171
|
+
TargetNodeHash: 'node-error',
|
|
172
|
+
TargetPortHash: 'port-err-in',
|
|
173
|
+
Data: {}
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
Hash: 'conn-5',
|
|
177
|
+
SourceNodeHash: 'node-process-2',
|
|
178
|
+
SourcePortHash: 'port-proc2-out',
|
|
179
|
+
TargetNodeHash: 'node-end',
|
|
180
|
+
TargetPortHash: 'port-end-in',
|
|
181
|
+
Data: {}
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
Hash: 'conn-6',
|
|
185
|
+
SourceNodeHash: 'node-error',
|
|
186
|
+
SourcePortHash: 'port-err-out',
|
|
187
|
+
TargetNodeHash: 'node-end',
|
|
188
|
+
TargetPortHash: 'port-end-in',
|
|
189
|
+
Data: {}
|
|
190
|
+
}
|
|
191
|
+
],
|
|
192
|
+
ViewState:
|
|
193
|
+
{
|
|
194
|
+
PanX: 0,
|
|
195
|
+
PanY: 0,
|
|
196
|
+
Zoom: 1,
|
|
197
|
+
SelectedNodeHash: null,
|
|
198
|
+
SelectedConnectionHash: null
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
// Render the layout shell first, then the initial content
|
|
203
|
+
this.pict.views['FlowExample-Layout'].render();
|
|
204
|
+
|
|
205
|
+
return super.onAfterInitializeAsync(fCallback);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Navigate to a route using the pict-router.
|
|
210
|
+
*
|
|
211
|
+
* @param {string} pRoute - The route path to navigate to (e.g. '/About')
|
|
212
|
+
*/
|
|
213
|
+
navigateTo(pRoute)
|
|
214
|
+
{
|
|
215
|
+
this.pict.providers.PictRouter.navigate(pRoute);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Render a specific content view into the main workspace area.
|
|
220
|
+
* This is called by the router when a route is matched.
|
|
221
|
+
*
|
|
222
|
+
* @param {string} pViewIdentifier - The view identifier to render
|
|
223
|
+
*/
|
|
224
|
+
showView(pViewIdentifier)
|
|
225
|
+
{
|
|
226
|
+
if (pViewIdentifier in this.pict.views)
|
|
227
|
+
{
|
|
228
|
+
this.pict.AppData.FlowExample.CurrentRoute = pViewIdentifier;
|
|
229
|
+
this.pict.views[pViewIdentifier].render();
|
|
230
|
+
}
|
|
231
|
+
else
|
|
232
|
+
{
|
|
233
|
+
this.pict.log.warn(`View [${pViewIdentifier}] not found; falling back to main workspace.`);
|
|
234
|
+
this.pict.views['FlowExample-MainWorkspace'].render();
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
module.exports = FlowExampleApplication;
|
|
240
|
+
|
|
241
|
+
module.exports.default_configuration = require('./Pict-Application-FlowExample-Configuration.json');
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ProviderIdentifier": "Pict-Router",
|
|
3
|
+
|
|
4
|
+
"AutoInitialize": true,
|
|
5
|
+
"AutoInitializeOrdinal": 0,
|
|
6
|
+
|
|
7
|
+
"Routes":
|
|
8
|
+
[
|
|
9
|
+
{
|
|
10
|
+
"path": "/Home",
|
|
11
|
+
"template": "{~LV:Pict.PictApplication.showView(`FlowExample-MainWorkspace`)~}"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"path": "/About",
|
|
15
|
+
"template": "{~LV:Pict.PictApplication.showView(`FlowExample-About`)~}"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"path": "/Documentation",
|
|
19
|
+
"template": "{~LV:Pict.PictApplication.showView(`FlowExample-Documentation`)~}"
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
const libPictView = require('pict-view');
|
|
2
|
+
|
|
3
|
+
const _ViewConfiguration =
|
|
4
|
+
{
|
|
5
|
+
ViewIdentifier: "FlowExample-About",
|
|
6
|
+
|
|
7
|
+
DefaultRenderable: "FlowExample-About-Content",
|
|
8
|
+
DefaultDestinationAddress: "#FlowExample-Content-Container",
|
|
9
|
+
|
|
10
|
+
AutoRender: false,
|
|
11
|
+
|
|
12
|
+
CSS: /*css*/`
|
|
13
|
+
.flowexample-about {
|
|
14
|
+
padding: 2em;
|
|
15
|
+
max-width: 800px;
|
|
16
|
+
margin: 0 auto;
|
|
17
|
+
}
|
|
18
|
+
.flowexample-about-header {
|
|
19
|
+
text-align: center;
|
|
20
|
+
padding-bottom: 1.5em;
|
|
21
|
+
border-bottom: 1px solid #eee;
|
|
22
|
+
margin-bottom: 2em;
|
|
23
|
+
}
|
|
24
|
+
.flowexample-about-header h1 {
|
|
25
|
+
margin: 0 0 0.25em 0;
|
|
26
|
+
font-size: 2em;
|
|
27
|
+
font-weight: 300;
|
|
28
|
+
color: #2c3e50;
|
|
29
|
+
}
|
|
30
|
+
.flowexample-about-header p {
|
|
31
|
+
margin: 0;
|
|
32
|
+
color: #7f8c8d;
|
|
33
|
+
font-size: 1.1em;
|
|
34
|
+
}
|
|
35
|
+
.flowexample-about h2 {
|
|
36
|
+
margin: 1.5em 0 0.5em 0;
|
|
37
|
+
font-weight: 400;
|
|
38
|
+
color: #2c3e50;
|
|
39
|
+
font-size: 1.3em;
|
|
40
|
+
}
|
|
41
|
+
.flowexample-about p {
|
|
42
|
+
color: #555;
|
|
43
|
+
line-height: 1.7;
|
|
44
|
+
}
|
|
45
|
+
.flowexample-about-tech {
|
|
46
|
+
display: grid;
|
|
47
|
+
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
|
|
48
|
+
gap: 1em;
|
|
49
|
+
margin-top: 1em;
|
|
50
|
+
}
|
|
51
|
+
.flowexample-about-tech-item {
|
|
52
|
+
background: #f8f9fa;
|
|
53
|
+
border: 1px solid #e9ecef;
|
|
54
|
+
border-radius: 4px;
|
|
55
|
+
padding: 1em;
|
|
56
|
+
text-align: center;
|
|
57
|
+
}
|
|
58
|
+
.flowexample-about-tech-item strong {
|
|
59
|
+
display: block;
|
|
60
|
+
margin-bottom: 0.25em;
|
|
61
|
+
color: #2c3e50;
|
|
62
|
+
}
|
|
63
|
+
.flowexample-about-tech-item span {
|
|
64
|
+
font-size: 0.85em;
|
|
65
|
+
color: #666;
|
|
66
|
+
}
|
|
67
|
+
.flowexample-about-features {
|
|
68
|
+
display: grid;
|
|
69
|
+
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
|
70
|
+
gap: 1em;
|
|
71
|
+
margin-top: 1em;
|
|
72
|
+
}
|
|
73
|
+
.flowexample-about-feature {
|
|
74
|
+
background: #fff;
|
|
75
|
+
border: 1px solid #e0e0e0;
|
|
76
|
+
border-radius: 6px;
|
|
77
|
+
padding: 1.25em;
|
|
78
|
+
}
|
|
79
|
+
.flowexample-about-feature h3 {
|
|
80
|
+
margin: 0 0 0.35em 0;
|
|
81
|
+
font-size: 1em;
|
|
82
|
+
color: #2c3e50;
|
|
83
|
+
}
|
|
84
|
+
.flowexample-about-feature p {
|
|
85
|
+
margin: 0;
|
|
86
|
+
font-size: 0.9em;
|
|
87
|
+
}
|
|
88
|
+
`,
|
|
89
|
+
|
|
90
|
+
Templates:
|
|
91
|
+
[
|
|
92
|
+
{
|
|
93
|
+
Hash: "FlowExample-About-Template",
|
|
94
|
+
Template: /*html*/`
|
|
95
|
+
<div class="flowexample-about">
|
|
96
|
+
<div class="flowexample-about-header">
|
|
97
|
+
<h1>About Pict Section Flow</h1>
|
|
98
|
+
<p>A pure SVG flow diagram component for the Pict framework</p>
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
<h2>What It Does</h2>
|
|
102
|
+
<p>Pict Section Flow provides a self-contained, extensible flow diagram view for Pict applications. It renders nodes and connections as SVG elements, supports drag-and-drop node positioning, interactive connection creation between ports, and viewport panning and zooming — all with zero external diagram library dependencies.</p>
|
|
103
|
+
|
|
104
|
+
<h2>Key Features</h2>
|
|
105
|
+
<div class="flowexample-about-features">
|
|
106
|
+
<div class="flowexample-about-feature">
|
|
107
|
+
<h3>Pure SVG Rendering</h3>
|
|
108
|
+
<p>All diagram elements are rendered as standard SVG, providing native DOM events and CSS styling with no canvas or external libraries required.</p>
|
|
109
|
+
</div>
|
|
110
|
+
<div class="flowexample-about-feature">
|
|
111
|
+
<h3>Drag & Drop Nodes</h3>
|
|
112
|
+
<p>Click and drag nodes to reposition them. Connections update in real time with smooth cubic bezier curves.</p>
|
|
113
|
+
</div>
|
|
114
|
+
<div class="flowexample-about-feature">
|
|
115
|
+
<h3>Interactive Connections</h3>
|
|
116
|
+
<p>Drag from an output port to an input port to create connections visually. Validation prevents self-connections and duplicates.</p>
|
|
117
|
+
</div>
|
|
118
|
+
<div class="flowexample-about-feature">
|
|
119
|
+
<h3>Pan & Zoom</h3>
|
|
120
|
+
<p>Navigate large diagrams with background panning and mouse wheel zoom. Zoom-to-fit centers all nodes automatically.</p>
|
|
121
|
+
</div>
|
|
122
|
+
<div class="flowexample-about-feature">
|
|
123
|
+
<h3>Extensible Node Types</h3>
|
|
124
|
+
<p>Register custom node types with different shapes, colors, port configurations, and styles through the Node Type Provider.</p>
|
|
125
|
+
</div>
|
|
126
|
+
<div class="flowexample-about-feature">
|
|
127
|
+
<h3>Event Hooks</h3>
|
|
128
|
+
<p>Listen for node selection, movement, connection creation and removal through the Event Handler Provider for full extensibility.</p>
|
|
129
|
+
</div>
|
|
130
|
+
</div>
|
|
131
|
+
|
|
132
|
+
<h2>Built With</h2>
|
|
133
|
+
<div class="flowexample-about-tech">
|
|
134
|
+
<div class="flowexample-about-tech-item">
|
|
135
|
+
<strong>Pict</strong>
|
|
136
|
+
<span>Application Framework</span>
|
|
137
|
+
</div>
|
|
138
|
+
<div class="flowexample-about-tech-item">
|
|
139
|
+
<strong>Pict-View</strong>
|
|
140
|
+
<span>View Lifecycle</span>
|
|
141
|
+
</div>
|
|
142
|
+
<div class="flowexample-about-tech-item">
|
|
143
|
+
<strong>Pict-Router</strong>
|
|
144
|
+
<span>Hash Routing</span>
|
|
145
|
+
</div>
|
|
146
|
+
<div class="flowexample-about-tech-item">
|
|
147
|
+
<strong>SVG</strong>
|
|
148
|
+
<span>Diagram Rendering</span>
|
|
149
|
+
</div>
|
|
150
|
+
<div class="flowexample-about-tech-item">
|
|
151
|
+
<strong>Fable</strong>
|
|
152
|
+
<span>Service Architecture</span>
|
|
153
|
+
</div>
|
|
154
|
+
</div>
|
|
155
|
+
|
|
156
|
+
<h2>License</h2>
|
|
157
|
+
<p>This project is released under the MIT License. It is part of the Retold ecosystem of tools for building complex data-driven applications.</p>
|
|
158
|
+
</div>
|
|
159
|
+
`
|
|
160
|
+
}
|
|
161
|
+
],
|
|
162
|
+
|
|
163
|
+
Renderables:
|
|
164
|
+
[
|
|
165
|
+
{
|
|
166
|
+
RenderableHash: "FlowExample-About-Content",
|
|
167
|
+
TemplateHash: "FlowExample-About-Template",
|
|
168
|
+
DestinationAddress: "#FlowExample-Content-Container",
|
|
169
|
+
RenderMethod: "replace"
|
|
170
|
+
}
|
|
171
|
+
]
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
class FlowExampleAboutView extends libPictView
|
|
175
|
+
{
|
|
176
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
177
|
+
{
|
|
178
|
+
super(pFable, pOptions, pServiceHash);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
module.exports = FlowExampleAboutView;
|
|
183
|
+
|
|
184
|
+
module.exports.default_configuration = _ViewConfiguration;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
const libPictView = require('pict-view');
|
|
2
|
+
|
|
3
|
+
const _ViewConfiguration =
|
|
4
|
+
{
|
|
5
|
+
ViewIdentifier: "FlowExample-BottomBar",
|
|
6
|
+
|
|
7
|
+
DefaultRenderable: "FlowExample-BottomBar-Content",
|
|
8
|
+
DefaultDestinationAddress: "#FlowExample-BottomBar-Container",
|
|
9
|
+
|
|
10
|
+
AutoRender: false,
|
|
11
|
+
|
|
12
|
+
CSS: /*css*/`
|
|
13
|
+
.flowexample-bottombar {
|
|
14
|
+
display: flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
justify-content: space-between;
|
|
17
|
+
background-color: #2c3e50;
|
|
18
|
+
color: #7f8c8d;
|
|
19
|
+
padding: 0.75em 1.5em;
|
|
20
|
+
font-size: 0.8em;
|
|
21
|
+
border-top: 1px solid #34495e;
|
|
22
|
+
}
|
|
23
|
+
.flowexample-bottombar a {
|
|
24
|
+
color: #95a5a6;
|
|
25
|
+
text-decoration: none;
|
|
26
|
+
margin-left: 1em;
|
|
27
|
+
transition: color 0.15s;
|
|
28
|
+
}
|
|
29
|
+
.flowexample-bottombar a:hover {
|
|
30
|
+
color: #ecf0f1;
|
|
31
|
+
}
|
|
32
|
+
.flowexample-bottombar-links {
|
|
33
|
+
display: flex;
|
|
34
|
+
align-items: center;
|
|
35
|
+
gap: 0.5em;
|
|
36
|
+
}
|
|
37
|
+
`,
|
|
38
|
+
|
|
39
|
+
Templates:
|
|
40
|
+
[
|
|
41
|
+
{
|
|
42
|
+
Hash: "FlowExample-BottomBar-Template",
|
|
43
|
+
Template: /*html*/`
|
|
44
|
+
<div class="flowexample-bottombar">
|
|
45
|
+
<span>Pict Section Flow Example © 2025</span>
|
|
46
|
+
<div class="flowexample-bottombar-links">
|
|
47
|
+
<a href="https://github.com/stevenvelozo/pict" target="_blank">Pict</a>
|
|
48
|
+
<a href="https://github.com/stevenvelozo/fable" target="_blank">Fable</a>
|
|
49
|
+
<a onclick="{~P~}.PictApplication.navigateTo('/About')">About</a>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
`
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
|
|
56
|
+
Renderables:
|
|
57
|
+
[
|
|
58
|
+
{
|
|
59
|
+
RenderableHash: "FlowExample-BottomBar-Content",
|
|
60
|
+
TemplateHash: "FlowExample-BottomBar-Template",
|
|
61
|
+
DestinationAddress: "#FlowExample-BottomBar-Container",
|
|
62
|
+
RenderMethod: "replace"
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
class FlowExampleBottomBarView extends libPictView
|
|
68
|
+
{
|
|
69
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
70
|
+
{
|
|
71
|
+
super(pFable, pOptions, pServiceHash);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = FlowExampleBottomBarView;
|
|
76
|
+
|
|
77
|
+
module.exports.default_configuration = _ViewConfiguration;
|