@procaaso/alphinity-ui-components 1.0.2 → 1.0.4
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/IMPLEMENTATION_GUIDE.md +1351 -0
- package/README.md +9 -22
- package/dist/index.cjs +162 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -1
- package/dist/index.d.ts +26 -1
- package/dist/index.js +162 -11
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -18,33 +18,20 @@ function HMIPanel() {
|
|
|
18
18
|
const [temperature, setTemperature] = useState(72.5);
|
|
19
19
|
const [pressure, setPressure] = useState(14.7);
|
|
20
20
|
const [systemStatus, setSystemStatus] = useState('normal');
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
return (
|
|
23
23
|
<div className="p-4 space-y-4">
|
|
24
24
|
{/* System status indicators */}
|
|
25
25
|
<div className="flex gap-4 items-center">
|
|
26
|
-
<StatusIndicator
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
led={true}
|
|
31
|
-
/>
|
|
32
|
-
<StatusIndicator
|
|
33
|
-
status="alarm"
|
|
34
|
-
label="Temperature Alert"
|
|
26
|
+
<StatusIndicator status="normal" label="Power" size="medium" led={true} />
|
|
27
|
+
<StatusIndicator
|
|
28
|
+
status="alarm"
|
|
29
|
+
label="Temperature Alert"
|
|
35
30
|
animation="pulse"
|
|
36
31
|
shape="circle"
|
|
37
32
|
/>
|
|
38
|
-
<StatusIndicator
|
|
39
|
-
|
|
40
|
-
label="Maintenance Due"
|
|
41
|
-
animation="blink"
|
|
42
|
-
/>
|
|
43
|
-
<StatusIndicator
|
|
44
|
-
status="active"
|
|
45
|
-
label="Process Running"
|
|
46
|
-
size="large"
|
|
47
|
-
/>
|
|
33
|
+
<StatusIndicator status="warning" label="Maintenance Due" animation="blink" />
|
|
34
|
+
<StatusIndicator status="active" label="Process Running" size="large" />
|
|
48
35
|
</div>
|
|
49
36
|
|
|
50
37
|
{/* Process control values */}
|
|
@@ -58,7 +45,7 @@ function HMIPanel() {
|
|
|
58
45
|
precision={1}
|
|
59
46
|
status="normal"
|
|
60
47
|
/>
|
|
61
|
-
|
|
48
|
+
|
|
62
49
|
<ValueEntry
|
|
63
50
|
value={pressure}
|
|
64
51
|
onChange={setPressure}
|
|
@@ -67,7 +54,7 @@ function HMIPanel() {
|
|
|
67
54
|
status="warning"
|
|
68
55
|
readOnly
|
|
69
56
|
/>
|
|
70
|
-
|
|
57
|
+
|
|
71
58
|
{/* Control buttons */}
|
|
72
59
|
<Button variant="primary" onClick={() => console.log('Start process')}>
|
|
73
60
|
Start
|
package/dist/index.cjs
CHANGED
|
@@ -2055,9 +2055,10 @@ function NodeRenderer({
|
|
|
2055
2055
|
x: symbol.viewBox.width / 2 + (node.labelOffset?.x ?? 0),
|
|
2056
2056
|
y: symbol.viewBox.height + 12 + (node.labelOffset?.y ?? 0),
|
|
2057
2057
|
textAnchor: "middle",
|
|
2058
|
-
fontSize:
|
|
2058
|
+
fontSize: node.labelFontSize ?? 10,
|
|
2059
2059
|
fontWeight: "600",
|
|
2060
2060
|
fill: isSelected ? "#3b82f6" : "#1f2937",
|
|
2061
|
+
transform: node.transform.rotation ? `rotate(${-node.transform.rotation}, ${symbol.viewBox.width / 2 + (node.labelOffset?.x ?? 0)}, ${symbol.viewBox.height + 12 + (node.labelOffset?.y ?? 0)})` : void 0,
|
|
2061
2062
|
children: node.label || node.id
|
|
2062
2063
|
}
|
|
2063
2064
|
)
|
|
@@ -2437,6 +2438,34 @@ function useViewBox(options) {
|
|
|
2437
2438
|
};
|
|
2438
2439
|
});
|
|
2439
2440
|
}, [initialViewBox, maxZoom]);
|
|
2441
|
+
const fitToContent = (0, import_react8.useCallback)((bounds, padding = 50) => {
|
|
2442
|
+
const contentWidth = bounds.maxX - bounds.minX;
|
|
2443
|
+
const contentHeight = bounds.maxY - bounds.minY;
|
|
2444
|
+
if (contentWidth === 0 || contentHeight === 0) {
|
|
2445
|
+
return;
|
|
2446
|
+
}
|
|
2447
|
+
const paddedWidth = contentWidth + padding * 2;
|
|
2448
|
+
const paddedHeight = contentHeight + padding * 2;
|
|
2449
|
+
const aspectRatio = initialViewBox.width / initialViewBox.height;
|
|
2450
|
+
const contentAspectRatio = paddedWidth / paddedHeight;
|
|
2451
|
+
let newWidth;
|
|
2452
|
+
let newHeight;
|
|
2453
|
+
if (contentAspectRatio > aspectRatio) {
|
|
2454
|
+
newWidth = paddedWidth;
|
|
2455
|
+
newHeight = paddedWidth / aspectRatio;
|
|
2456
|
+
} else {
|
|
2457
|
+
newHeight = paddedHeight;
|
|
2458
|
+
newWidth = paddedHeight * aspectRatio;
|
|
2459
|
+
}
|
|
2460
|
+
const centerX = bounds.minX + contentWidth / 2;
|
|
2461
|
+
const centerY = bounds.minY + contentHeight / 2;
|
|
2462
|
+
setViewBox({
|
|
2463
|
+
x: centerX - newWidth / 2,
|
|
2464
|
+
y: centerY - newHeight / 2,
|
|
2465
|
+
width: newWidth,
|
|
2466
|
+
height: newHeight
|
|
2467
|
+
});
|
|
2468
|
+
}, [initialViewBox]);
|
|
2440
2469
|
(0, import_react8.useEffect)(() => {
|
|
2441
2470
|
if (!enableZoom || !svgRef.current) return;
|
|
2442
2471
|
const svg = svgRef.current;
|
|
@@ -2668,6 +2697,8 @@ function useViewBox(options) {
|
|
|
2668
2697
|
resetViewBox,
|
|
2669
2698
|
zoomIn,
|
|
2670
2699
|
zoomOut,
|
|
2700
|
+
fitToContent,
|
|
2701
|
+
setViewBox,
|
|
2671
2702
|
screenToWorld,
|
|
2672
2703
|
svgRef
|
|
2673
2704
|
};
|
|
@@ -3322,6 +3353,7 @@ function PIDCanvas({
|
|
|
3322
3353
|
onPaste,
|
|
3323
3354
|
onSymbolDrop,
|
|
3324
3355
|
onPipeCreated,
|
|
3356
|
+
onMounted,
|
|
3325
3357
|
telemetry,
|
|
3326
3358
|
...props
|
|
3327
3359
|
}) {
|
|
@@ -3339,12 +3371,72 @@ function PIDCanvas({
|
|
|
3339
3371
|
const {
|
|
3340
3372
|
viewBox: controlledViewBox,
|
|
3341
3373
|
svgRef,
|
|
3342
|
-
screenToWorld
|
|
3374
|
+
screenToWorld,
|
|
3375
|
+
fitToContent: fitToContentViewBox,
|
|
3376
|
+
setViewBox
|
|
3343
3377
|
} = useViewBox({
|
|
3344
3378
|
initialViewBox: diagram.viewBox,
|
|
3345
3379
|
enablePan: features.pan ?? true,
|
|
3346
3380
|
enableZoom: features.zoom ?? true
|
|
3347
3381
|
});
|
|
3382
|
+
const calculateContentBounds = (0, import_react13.useCallback)(() => {
|
|
3383
|
+
const nodes2 = localDiagram.nodes.filter((n) => n.visible !== false);
|
|
3384
|
+
if (nodes2.length === 0) {
|
|
3385
|
+
return null;
|
|
3386
|
+
}
|
|
3387
|
+
let minX = Infinity;
|
|
3388
|
+
let minY = Infinity;
|
|
3389
|
+
let maxX = -Infinity;
|
|
3390
|
+
let maxY = -Infinity;
|
|
3391
|
+
nodes2.forEach((node) => {
|
|
3392
|
+
const symbol = getSymbolDefinition(node.symbolId);
|
|
3393
|
+
if (!symbol) return;
|
|
3394
|
+
const nodeMinX = node.transform.x;
|
|
3395
|
+
const nodeMinY = node.transform.y;
|
|
3396
|
+
const nodeMaxX = node.transform.x + symbol.viewBox.width;
|
|
3397
|
+
const nodeMaxY = node.transform.y + symbol.viewBox.height;
|
|
3398
|
+
minX = Math.min(minX, nodeMinX);
|
|
3399
|
+
minY = Math.min(minY, nodeMinY);
|
|
3400
|
+
maxX = Math.max(maxX, nodeMaxX);
|
|
3401
|
+
maxY = Math.max(maxY, nodeMaxY);
|
|
3402
|
+
});
|
|
3403
|
+
return { minX, minY, maxX, maxY };
|
|
3404
|
+
}, [localDiagram.nodes]);
|
|
3405
|
+
(0, import_react13.useEffect)(() => {
|
|
3406
|
+
if (onMounted) {
|
|
3407
|
+
const controls = {
|
|
3408
|
+
fitToContent: (padding = 50) => {
|
|
3409
|
+
const bounds = calculateContentBounds();
|
|
3410
|
+
if (bounds) {
|
|
3411
|
+
fitToContentViewBox(bounds, padding);
|
|
3412
|
+
}
|
|
3413
|
+
},
|
|
3414
|
+
setZoom: (zoomLevel) => {
|
|
3415
|
+
const centerX = controlledViewBox.x + controlledViewBox.width / 2;
|
|
3416
|
+
const centerY = controlledViewBox.y + controlledViewBox.height / 2;
|
|
3417
|
+
const newWidth = diagram.viewBox.width / zoomLevel;
|
|
3418
|
+
const newHeight = diagram.viewBox.height / zoomLevel;
|
|
3419
|
+
setViewBox({
|
|
3420
|
+
x: centerX - newWidth / 2,
|
|
3421
|
+
y: centerY - newHeight / 2,
|
|
3422
|
+
width: newWidth,
|
|
3423
|
+
height: newHeight
|
|
3424
|
+
});
|
|
3425
|
+
},
|
|
3426
|
+
getZoom: () => {
|
|
3427
|
+
return diagram.viewBox.width / controlledViewBox.width;
|
|
3428
|
+
}
|
|
3429
|
+
};
|
|
3430
|
+
onMounted(controls);
|
|
3431
|
+
}
|
|
3432
|
+
}, [
|
|
3433
|
+
onMounted,
|
|
3434
|
+
calculateContentBounds,
|
|
3435
|
+
fitToContentViewBox,
|
|
3436
|
+
setViewBox,
|
|
3437
|
+
controlledViewBox,
|
|
3438
|
+
diagram.viewBox
|
|
3439
|
+
]);
|
|
3348
3440
|
const { selection, selectNode, selectPipe, clearSelection } = useSelection({
|
|
3349
3441
|
multiSelect: features.multiSelect ?? true,
|
|
3350
3442
|
onSelectionChange
|
|
@@ -3635,21 +3727,32 @@ function PIDCanvas({
|
|
|
3635
3727
|
onDrop: handleDrop,
|
|
3636
3728
|
onDragLeave: handleDragLeave,
|
|
3637
3729
|
children: [
|
|
3638
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
3639
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.
|
|
3640
|
-
|
|
3641
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3730
|
+
features.showGrid !== false ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
|
|
3731
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("defs", { children: [
|
|
3732
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("pattern", { id: "grid-minor", width: "5", height: "5", patternUnits: "userSpaceOnUse", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("path", { d: "M 5 0 L 0 0 0 5", fill: "none", stroke: "#e5e7eb", strokeWidth: "0.5" }) }),
|
|
3733
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("pattern", { id: "grid-major", width: "25", height: "25", patternUnits: "userSpaceOnUse", children: [
|
|
3734
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("rect", { width: "25", height: "25", fill: "url(#grid-minor)" }),
|
|
3735
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("path", { d: "M 25 0 L 0 0 0 25", fill: "none", stroke: "#d1d5db", strokeWidth: "1" })
|
|
3736
|
+
] })
|
|
3737
|
+
] }),
|
|
3738
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
3739
|
+
"rect",
|
|
3740
|
+
{
|
|
3741
|
+
x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
|
|
3742
|
+
y: Math.floor(viewBox.y / 25) * 25 - viewBox.height,
|
|
3743
|
+
width: Math.ceil(viewBox.width * 3 / 25) * 25,
|
|
3744
|
+
height: Math.ceil(viewBox.height * 3 / 25) * 25,
|
|
3745
|
+
fill: "url(#grid-major)"
|
|
3746
|
+
}
|
|
3747
|
+
)
|
|
3748
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
3646
3749
|
"rect",
|
|
3647
3750
|
{
|
|
3648
3751
|
x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
|
|
3649
3752
|
y: Math.floor(viewBox.y / 25) * 25 - viewBox.height,
|
|
3650
3753
|
width: Math.ceil(viewBox.width * 3 / 25) * 25,
|
|
3651
3754
|
height: Math.ceil(viewBox.height * 3 / 25) * 25,
|
|
3652
|
-
fill: "
|
|
3755
|
+
fill: features.backgroundColor ?? "#ffffff"
|
|
3653
3756
|
}
|
|
3654
3757
|
),
|
|
3655
3758
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
@@ -4082,6 +4185,54 @@ function NodeConfigPanel({
|
|
|
4082
4185
|
}
|
|
4083
4186
|
)
|
|
4084
4187
|
] })
|
|
4188
|
+
] }),
|
|
4189
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { children: [
|
|
4190
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Font Size:" }),
|
|
4191
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4192
|
+
"input",
|
|
4193
|
+
{
|
|
4194
|
+
type: "number",
|
|
4195
|
+
min: "6",
|
|
4196
|
+
max: "24",
|
|
4197
|
+
value: node.labelFontSize ?? 10,
|
|
4198
|
+
onChange: (e) => onUpdateNode({
|
|
4199
|
+
labelFontSize: parseFloat(e.target.value) || 10
|
|
4200
|
+
}),
|
|
4201
|
+
style: {
|
|
4202
|
+
width: "100%",
|
|
4203
|
+
padding: "6px 8px",
|
|
4204
|
+
borderRadius: "4px",
|
|
4205
|
+
border: "1px solid #cbd5e1",
|
|
4206
|
+
fontSize: "0.875rem"
|
|
4207
|
+
}
|
|
4208
|
+
}
|
|
4209
|
+
)
|
|
4210
|
+
] }),
|
|
4211
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { children: [
|
|
4212
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Rotation (degrees):" }),
|
|
4213
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4214
|
+
"input",
|
|
4215
|
+
{
|
|
4216
|
+
type: "number",
|
|
4217
|
+
min: "0",
|
|
4218
|
+
max: "360",
|
|
4219
|
+
step: "15",
|
|
4220
|
+
value: node.transform.rotation ?? 0,
|
|
4221
|
+
onChange: (e) => onUpdateNode({
|
|
4222
|
+
transform: {
|
|
4223
|
+
...node.transform,
|
|
4224
|
+
rotation: parseFloat(e.target.value) || 0
|
|
4225
|
+
}
|
|
4226
|
+
}),
|
|
4227
|
+
style: {
|
|
4228
|
+
width: "100%",
|
|
4229
|
+
padding: "6px 8px",
|
|
4230
|
+
borderRadius: "4px",
|
|
4231
|
+
border: "1px solid #cbd5e1",
|
|
4232
|
+
fontSize: "0.875rem"
|
|
4233
|
+
}
|
|
4234
|
+
}
|
|
4235
|
+
)
|
|
4085
4236
|
] })
|
|
4086
4237
|
] }),
|
|
4087
4238
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|