@arcanejs/react-toolkit 0.1.3 → 0.1.5
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 +27 -15
- package/package.json +2 -3
- package/docs/architecture.svg +0 -271
- package/docs/example-controller.png +0 -0
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/@arcanejs/react-toolkit)
|
|
4
4
|
|
|
5
5
|
`@arcanejs/react-toolkit` Allows you to quickly create real-time control panels
|
|
6
|
-
for your
|
|
6
|
+
for your single-process Node.js apps,
|
|
7
7
|
using a custom react renderer, and WebSockets.
|
|
8
8
|
|
|
9
9
|
Control panels can be accessed by any number of
|
|
@@ -15,23 +15,20 @@ The UI has also been designed primarily with touch devices in mind,
|
|
|
15
15
|
but also works well with a cursor and keyboard.
|
|
16
16
|
|
|
17
17
|
<p align="center">
|
|
18
|
-
<img src="
|
|
18
|
+
<img src="https://raw.githubusercontent.com/arcanejs/arcanejs/main/packages/react-toolkit/docs/architecture.svg" alt="Architecture Diagram">
|
|
19
19
|
</p>
|
|
20
20
|
|
|
21
|
-
##
|
|
21
|
+
## What
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
and takes advantage of unstable `react` APIs exposed via `react-render`.
|
|
25
|
-
It's not suitable for production or commercial projects yet,
|
|
26
|
-
especially those that rely on regular updates of dependencies
|
|
27
|
-
for security reasons,
|
|
28
|
-
as usage of this project may make it difficult to keep `react` up-to-date
|
|
29
|
-
(that being said, the license does not prohibit this,
|
|
30
|
-
so feel free to at-your-own-risk).
|
|
23
|
+
- Easily create controller UIs for Node.js processes
|
|
31
24
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
25
|
+
- Uses server-side **React** for state management and UI composition
|
|
26
|
+
|
|
27
|
+
- This is not SSR, you can use `useState()` hooks etc...
|
|
28
|
+
|
|
29
|
+
- Instantly updates all clients using WebSockets
|
|
30
|
+
|
|
31
|
+
- Collection of 9+ components to build your UIs
|
|
35
32
|
|
|
36
33
|
## Why
|
|
37
34
|
|
|
@@ -117,7 +114,7 @@ ToolkitRenderer.render(<ControlPanel />, toolkit);
|
|
|
117
114
|
You would then be able to access the following control panel
|
|
118
115
|
from [localhost:3000](http://localhost:3000):
|
|
119
116
|
|
|
120
|
-

|
|
121
118
|
|
|
122
119
|
Please note:
|
|
123
120
|
|
|
@@ -291,3 +288,18 @@ TODO
|
|
|
291
288
|
For a comprehensive list of examples,
|
|
292
289
|
please see the example directory in the arcane monorepo:
|
|
293
290
|
<https://github.com/arcanejs/arcanejs/tree/main/examples/react>
|
|
291
|
+
|
|
292
|
+
## Status / Suitability / Security Disclaimer
|
|
293
|
+
|
|
294
|
+
This project is **experimental**,
|
|
295
|
+
and takes advantage of unstable `react` APIs exposed via `react-render`.
|
|
296
|
+
It's not suitable for production or commercial projects yet,
|
|
297
|
+
especially those that rely on regular updates of dependencies
|
|
298
|
+
for security reasons,
|
|
299
|
+
as usage of this project may make it difficult to keep `react` up-to-date
|
|
300
|
+
(that being said, the license does not prohibit this,
|
|
301
|
+
so feel free to at-your-own-risk).
|
|
302
|
+
|
|
303
|
+
There are also no authentication mechanisms implemented yet,
|
|
304
|
+
so be careful when exposing your control panels over the network,
|
|
305
|
+
as this will allow anyone to interact with your processes.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcanejs/react-toolkit",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Build web-accessible control interfaces for your long-running Node.js processes",
|
|
6
6
|
"keywords": [
|
|
@@ -43,8 +43,7 @@
|
|
|
43
43
|
"@arcanejs/toolkit": "^0.2.0"
|
|
44
44
|
},
|
|
45
45
|
"files": [
|
|
46
|
-
"dist"
|
|
47
|
-
"docs"
|
|
46
|
+
"dist"
|
|
48
47
|
],
|
|
49
48
|
"publishConfig": {
|
|
50
49
|
"access": "public"
|
package/docs/architecture.svg
DELETED
|
@@ -1,271 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg"
|
|
2
|
-
xmlns:xlink="http://www.w3.org/1999/xlink" id="svg8" version="1.1" viewBox="0 0 800 200" width="800" height="200">
|
|
3
|
-
<style>
|
|
4
|
-
* {
|
|
5
|
-
font-size: 14px;
|
|
6
|
-
font-family: sans-serif;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
#labels * {
|
|
10
|
-
font-size: 14px;
|
|
11
|
-
font-weight: bold;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
#code * {
|
|
15
|
-
font-size: 12px;
|
|
16
|
-
font-family: monospace;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
.black-border {
|
|
20
|
-
stroke: #151516;
|
|
21
|
-
stroke-width: 1;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
@keyframes btn-move-keyframes {
|
|
25
|
-
5% {
|
|
26
|
-
transform: translate(0, 0);
|
|
27
|
-
}
|
|
28
|
-
10% {
|
|
29
|
-
transform: translate(40px, 0);
|
|
30
|
-
}
|
|
31
|
-
55% {
|
|
32
|
-
transform: translate(40px, 0);
|
|
33
|
-
}
|
|
34
|
-
60% {
|
|
35
|
-
transform: translate(0, 0);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
.btn-move {
|
|
40
|
-
animation: 6s linear 0s infinite normal none running btn-move-keyframes;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
@keyframes mouse-anim-keyframes {
|
|
44
|
-
0% {
|
|
45
|
-
opacity: 1;
|
|
46
|
-
transform: scale(1);
|
|
47
|
-
}
|
|
48
|
-
2.5% {
|
|
49
|
-
opacity: 1;
|
|
50
|
-
transform: scale(0.8);
|
|
51
|
-
}
|
|
52
|
-
5% {
|
|
53
|
-
opacity: 1;
|
|
54
|
-
transform: scale(1);
|
|
55
|
-
}
|
|
56
|
-
7.5% {
|
|
57
|
-
opacity: 1;
|
|
58
|
-
transform: scale(1);
|
|
59
|
-
}
|
|
60
|
-
10% {
|
|
61
|
-
opacity: 0;
|
|
62
|
-
transform: scale(1);
|
|
63
|
-
}
|
|
64
|
-
90% {
|
|
65
|
-
opacity: 0;
|
|
66
|
-
transform: scale(1);
|
|
67
|
-
}
|
|
68
|
-
100% {
|
|
69
|
-
opacity: 1;
|
|
70
|
-
transform: scale(1);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
@keyframes highlight-keyframes {
|
|
75
|
-
0% {
|
|
76
|
-
opacity: 0;
|
|
77
|
-
}
|
|
78
|
-
2.45% {
|
|
79
|
-
opacity: 0;
|
|
80
|
-
}
|
|
81
|
-
2.5% {
|
|
82
|
-
opacity: 1;
|
|
83
|
-
}
|
|
84
|
-
10% {
|
|
85
|
-
opacity: 0;
|
|
86
|
-
}
|
|
87
|
-
100% {
|
|
88
|
-
opacity: 0;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
.mouse-anim-1 {
|
|
93
|
-
opacity: 0;
|
|
94
|
-
transform-origin: 60px 75px;
|
|
95
|
-
animation: 6s linear 0s infinite normal none running mouse-anim-keyframes;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
.highlight-anim-1 {
|
|
99
|
-
opacity: 0;
|
|
100
|
-
animation: 6s linear 0s infinite normal none running highlight-keyframes;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
.mouse-anim-2 {
|
|
104
|
-
opacity: 0;
|
|
105
|
-
transform-origin: 620px 75px;
|
|
106
|
-
animation: 6s linear 3s infinite normal none running mouse-anim-keyframes;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
.highlight-anim-2 {
|
|
110
|
-
opacity: 0;
|
|
111
|
-
animation: 6s linear 3s infinite normal none running highlight-keyframes;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
@keyframes state-keyframes {
|
|
115
|
-
4.9% {
|
|
116
|
-
opacity: 0;
|
|
117
|
-
fill: #aaa;
|
|
118
|
-
}
|
|
119
|
-
5% {
|
|
120
|
-
opacity: 1;
|
|
121
|
-
fill: #4286f4;
|
|
122
|
-
}
|
|
123
|
-
10% {
|
|
124
|
-
opacity: 1;
|
|
125
|
-
fill: #aaa;
|
|
126
|
-
}
|
|
127
|
-
54.9% {
|
|
128
|
-
opacity: 1;
|
|
129
|
-
fill: #aaa;
|
|
130
|
-
}
|
|
131
|
-
55% {
|
|
132
|
-
opacity: 0;
|
|
133
|
-
fill: #aaa;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
.text-off {
|
|
138
|
-
font-weight: bold;
|
|
139
|
-
opacity: 0;
|
|
140
|
-
animation: 6s linear 3s infinite normal none running state-keyframes;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
.text-on {
|
|
144
|
-
font-weight: bold;
|
|
145
|
-
opacity: 0;
|
|
146
|
-
animation: 6s linear 0s infinite normal none running state-keyframes;
|
|
147
|
-
}
|
|
148
|
-
</style>
|
|
149
|
-
<defs>
|
|
150
|
-
<linearGradient id="buttonOnGrad" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
151
|
-
<stop offset="0%" style="stop-color:#2a77f3;stop-opacity:1" />
|
|
152
|
-
<stop offset="100%" style="stop-color:#4286f4;stop-opacity:1" />
|
|
153
|
-
</linearGradient>
|
|
154
|
-
<linearGradient id="buttonOffGrad" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
155
|
-
<stop offset="0%" style="stop-color:#242525;stop-opacity:1" />
|
|
156
|
-
<stop offset="100%" style="stop-color:#37383a;stop-opacity:1" />
|
|
157
|
-
</linearGradient>
|
|
158
|
-
<linearGradient id="buttonGrad" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
159
|
-
<stop offset="0%" style="stop-color:#4f5053;stop-opacity:1" />
|
|
160
|
-
<stop offset="100%" style="stop-color:#343436;stop-opacity:1" />
|
|
161
|
-
</linearGradient>
|
|
162
|
-
<filter id="textShadow" x="-50%" y="-50%" width="200%" height="200%">
|
|
163
|
-
<feGaussianBlur in="SourceAlpha" stdDeviation="1"/>
|
|
164
|
-
<feOffset dx="0" dy="-1" result="offsetblur"/>
|
|
165
|
-
<feFlood flood-color="rgba(0,0,0,0.4)"/>
|
|
166
|
-
<feComposite in2="offsetblur" operator="in"/>
|
|
167
|
-
<feMerge>
|
|
168
|
-
<feMergeNode/>
|
|
169
|
-
<feMergeNode in="SourceGraphic"/>
|
|
170
|
-
</feMerge>
|
|
171
|
-
</filter>
|
|
172
|
-
<filter id="inset-shadow" x="-50%" y="-50%" width="200%" height="200%">
|
|
173
|
-
<feComponentTransfer in="SourceAlpha">
|
|
174
|
-
<feFuncA type="table" tableValues="1 0" />
|
|
175
|
-
</feComponentTransfer>
|
|
176
|
-
<feGaussianBlur stdDeviation="5" />
|
|
177
|
-
<feOffset dx="0" dy="0" result="offsetblur" />
|
|
178
|
-
<feFlood flood-color="black" result="color" />
|
|
179
|
-
<feComposite in2="offsetblur" operator="in" />
|
|
180
|
-
<feComposite in2="SourceAlpha" operator="in" />
|
|
181
|
-
<feMerge>
|
|
182
|
-
<feMergeNode in="SourceGraphic" />
|
|
183
|
-
<feMergeNode />
|
|
184
|
-
</feMerge>
|
|
185
|
-
</filter>
|
|
186
|
-
<marker id="arrow" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
|
187
|
-
<path d="M 0 0 L 10 5 L 0 10 z" fill="#777" />
|
|
188
|
-
</marker>
|
|
189
|
-
<g id="button_slider">
|
|
190
|
-
<rect x="-40" y="0" width="40" height="30" fill="url(#buttonOnGrad)" />
|
|
191
|
-
<text x="-20" y="15" width="40" height="30" dy="0.35em" text-anchor="middle" fill="white" filter="url(#textShadow)">ON</text>
|
|
192
|
-
<rect x="29" y="0" width="41" height="30" fill="url(#buttonOffGrad)" />
|
|
193
|
-
<text x="50" y="15" width="40" height="30" dy="0.35em" text-anchor="middle" fill="white" filter="url(#textShadow)">OFF</text>
|
|
194
|
-
<rect x="-1" y="0" class="black-border" width="31" height="30" fill="url(#buttonGrad)" rx="3" ry="3" />
|
|
195
|
-
</g>
|
|
196
|
-
<g id="screen">
|
|
197
|
-
<rect x="0" y="0" width="200" height="100" fill="#252524" filter="url(#inset-shadow)" rx="3" ry="3" />
|
|
198
|
-
<mask id="button_slider_1_mask">
|
|
199
|
-
<rect x="10.5" y="10.5" width="70" height="30" fill="#ffffff" rx="3" ry="3" />
|
|
200
|
-
</mask>
|
|
201
|
-
<g mask="url(#button_slider_1_mask)">
|
|
202
|
-
<g class="btn-move">
|
|
203
|
-
<use x="10.5" y="10.5" href="#button_slider" />
|
|
204
|
-
</g>
|
|
205
|
-
</g>
|
|
206
|
-
<rect class="black-border" x="10.5" y="10.5" width="70" height="30" fill="none" rx="3" ry="3" />
|
|
207
|
-
</g>
|
|
208
|
-
<g id="browser">
|
|
209
|
-
<rect x="-10" y="0" width="220" height="150" fill="#ccc" rx="5" ry="5" stroke-width="2" stroke="#aaa" />
|
|
210
|
-
<rect x="40.5" y="10.5" width="160" height="20" fill="#fff" rx="3" ry="3" stroke-width="1" stroke="#aaa" />
|
|
211
|
-
<path d="M 10 15 L 0 20 L 10 25 Z" fill="#777" />
|
|
212
|
-
<path d="M 20 15 L 30 20 L 20 25 Z" fill="#777" />
|
|
213
|
-
<text x="120" y="20" height="30" dy="0.35em" text-anchor="middle" fill="#777">10.10.10.10:8080</text>
|
|
214
|
-
</g>
|
|
215
|
-
<g id="switch_highlight">
|
|
216
|
-
<rect x="0.5" y="0.5" width="82" height="42" fill="none" stroke="#4286f4" stroke-width="2" rx="6" ry="6" />
|
|
217
|
-
</g>
|
|
218
|
-
<g id="mouse">
|
|
219
|
-
<g style="transform: scale(3)">
|
|
220
|
-
<path fill="#fefefe" d="M5.986 21.07v-2.155h-.958V17H4.07v-1.915h-.957V12.93H1.915v-.958H.958v-1.916h2.155v.958h.957v2.873h.958V.957h1.916v9.1H7.9V5.985h2.155v4.07h.958V6.944h1.916v4.07h.957V7.901h1.198V9.1h.957v6.943h-.957v2.873h-1.198v2.155H5.986z"/>
|
|
221
|
-
<path d="M5.028 22.028v-3.113H4.07V17h-.957v-1.915H1.915V12.93H.958v-.958H0V9.099h3.113v.957h.957V.958h.958V0h1.916v.958H7.9v4.07h2.155v.958h2.874v.958h2.155V7.9h.957V9.1H17v6.943h-.958v2.873h-.957v3.113H5.028zm8.86-.958v-2.155h1.197v-2.873h.957V9.1h-.957V7.9h-1.198v3.113h-.957v-4.07h-1.916v3.112h-.958v-4.07H7.901v4.07h-.957V.958H5.028v12.93H4.07v-2.874h-.957v-.958H.958v1.916h.957v.958h1.198v2.155h.957V17h.958v1.915h.958v2.155h7.901z" />
|
|
222
|
-
</g>
|
|
223
|
-
</g>
|
|
224
|
-
</defs>
|
|
225
|
-
|
|
226
|
-
<g>
|
|
227
|
-
<use y="10" x="20" href="#browser" />
|
|
228
|
-
<use y="50" x="20" href="#screen" />
|
|
229
|
-
|
|
230
|
-
<use y="10" x="580" href="#browser" />
|
|
231
|
-
<use y="50" x="580" href="#screen" />
|
|
232
|
-
|
|
233
|
-
<use y="54" x="24" href="#switch_highlight" class="highlight-anim-1" />
|
|
234
|
-
<use y="75" x="50.5" href="#mouse" class="mouse-anim-1" />
|
|
235
|
-
<use y="54" x="584" href="#switch_highlight" class="highlight-anim-2" />
|
|
236
|
-
<use y="75" x="610.5" href="#mouse" class="mouse-anim-2" />
|
|
237
|
-
</g>
|
|
238
|
-
|
|
239
|
-
<g>
|
|
240
|
-
<rect x="290" y="10" width="220" height="150" fill="#333" rx="5" ry="5" stroke-width="2" stroke="#050505" />
|
|
241
|
-
<g id="code">
|
|
242
|
-
<text x="300" y="30" text-anchor="start" fill="#f5f5f5">const [state, setState] =</text>
|
|
243
|
-
<text x="300" y="50" text-anchor="start" fill="#f5f5f5">  useState('off');</text>
|
|
244
|
-
<text x="300" y="80" text-anchor="start" fill="#aaa" class="text-off">// state == 'off'</text>
|
|
245
|
-
<text x="300" y="80" text-anchor="start" fill="#aaa" class="text-on">// state == 'on'</text>
|
|
246
|
-
<text x="300" y="110" text-anchor="start" fill="#f5f5f5"><Switch</text>
|
|
247
|
-
<text x="300" y="130" text-anchor="start" fill="#f5f5f5">  state={state}</text>
|
|
248
|
-
<text x="300" y="150" text-anchor="start" fill="#f5f5f5">  onChange={setState} /></text>
|
|
249
|
-
</g>
|
|
250
|
-
</g>
|
|
251
|
-
|
|
252
|
-
<g id="labels">
|
|
253
|
-
<!-- WS -->
|
|
254
|
-
<line x1="235" y1="90" x2="285" y2="90" stroke="#777" stroke-width="2" marker-start="url(#arrow)" marker-end="url(#arrow)" />
|
|
255
|
-
<rect x="235" y="52.5" width="50" height="25" fill="#f5f5f5" rx="6" ry="6" />
|
|
256
|
-
<text x="260" y="70" height="30" text-anchor="middle" fill="#333">WS</text>
|
|
257
|
-
|
|
258
|
-
<line x1="515" y1="90" x2="565" y2="90" stroke="#777" stroke-width="2" marker-start="url(#arrow)" marker-end="url(#arrow)" />
|
|
259
|
-
<rect x="515" y="52.5" width="50" height="25" fill="#f5f5f5" rx="6" ry="6" />
|
|
260
|
-
<text x="540" y="70" height="30" text-anchor="middle" fill="#333">WS</text>
|
|
261
|
-
|
|
262
|
-
<!-- Bottom -->
|
|
263
|
-
<rect x="35" y="167.5" width="170" height="25" fill="#f5f5f5" rx="6" ry="6" />
|
|
264
|
-
<text x="120" y="185" height="30" text-anchor="middle" fill="#333">Browser Client 1</text>
|
|
265
|
-
<rect x="315" y="167.5" width="170" height="25" fill="#f5f5f5" rx="6" ry="6" />
|
|
266
|
-
<text x="400" y="185" height="30" text-anchor="middle" fill="#333">Node.js Process</text>
|
|
267
|
-
<rect x="595" y="167.5" width="170" height="25" fill="#f5f5f5" rx="6" ry="6" />
|
|
268
|
-
<text x="680" y="185" height="30" text-anchor="middle" fill="#333">Browser Client 2</text>
|
|
269
|
-
</g>
|
|
270
|
-
|
|
271
|
-
</svg>
|
|
Binary file
|