@procaaso/alphinity-ui-components 1.0.3 → 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/dist/index.cjs +92 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -1
- package/dist/index.d.ts +20 -1
- package/dist/index.js +92 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -683,6 +683,15 @@ interface UseViewBoxResult {
|
|
|
683
683
|
zoomIn: () => void;
|
|
684
684
|
/** Zoom out (increase viewBox size) */
|
|
685
685
|
zoomOut: () => void;
|
|
686
|
+
/** Fit viewBox to content bounds with optional padding */
|
|
687
|
+
fitToContent: (bounds: {
|
|
688
|
+
minX: number;
|
|
689
|
+
minY: number;
|
|
690
|
+
maxX: number;
|
|
691
|
+
maxY: number;
|
|
692
|
+
}, padding?: number) => void;
|
|
693
|
+
/** Set viewBox directly */
|
|
694
|
+
setViewBox: (viewBox: ViewBox) => void;
|
|
686
695
|
/** Convert screen coordinates to world (SVG) coordinates */
|
|
687
696
|
screenToWorld: (screenX: number, screenY: number) => {
|
|
688
697
|
x: number;
|
|
@@ -927,9 +936,19 @@ interface PIDCanvasProps extends react__default.HTMLAttributes<HTMLDivElement> {
|
|
|
927
936
|
}) => void;
|
|
928
937
|
/** Callback when a pipe is created via connection mode */
|
|
929
938
|
onPipeCreated?: (sourceNodeId: string, targetNodeId: string, sourcePortId?: string, targetPortId?: string) => void;
|
|
939
|
+
/** Callback when canvas is mounted, provides control functions */
|
|
940
|
+
onMounted?: (controls: PIDCanvasControls) => void;
|
|
930
941
|
/** Telemetry data bindings for live values */
|
|
931
942
|
telemetry?: TelemetryMap;
|
|
932
943
|
}
|
|
944
|
+
interface PIDCanvasControls {
|
|
945
|
+
/** Fit view to show all diagram content */
|
|
946
|
+
fitToContent: (padding?: number) => void;
|
|
947
|
+
/** Set zoom level (1 = 100%, 2 = 200%, etc.) */
|
|
948
|
+
setZoom: (zoomLevel: number) => void;
|
|
949
|
+
/** Get current zoom level */
|
|
950
|
+
getZoom: () => number;
|
|
951
|
+
}
|
|
933
952
|
/**
|
|
934
953
|
* PIDCanvas - Interactive canvas for rendering P&ID diagrams
|
|
935
954
|
*
|
|
@@ -939,7 +958,7 @@ interface PIDCanvasProps extends react__default.HTMLAttributes<HTMLDivElement> {
|
|
|
939
958
|
*
|
|
940
959
|
* Future: Editing tools, symbol library UI
|
|
941
960
|
*/
|
|
942
|
-
declare function PIDCanvas({ diagram, className, style, features, onSelectionChange, onNodeClick, onPipeClick, onNodeMove, onDiagramChange, onDelete, onItemsCopied, onPaste, onSymbolDrop, onPipeCreated, telemetry, ...props }: PIDCanvasProps): react__default.ReactElement;
|
|
961
|
+
declare function PIDCanvas({ diagram, className, style, features, onSelectionChange, onNodeClick, onPipeClick, onNodeMove, onDiagramChange, onDelete, onItemsCopied, onPaste, onSymbolDrop, onPipeCreated, onMounted, telemetry, ...props }: PIDCanvasProps): react__default.ReactElement;
|
|
943
962
|
|
|
944
963
|
interface SymbolLibraryProps {
|
|
945
964
|
/** Optional className for styling */
|
package/dist/index.d.ts
CHANGED
|
@@ -683,6 +683,15 @@ interface UseViewBoxResult {
|
|
|
683
683
|
zoomIn: () => void;
|
|
684
684
|
/** Zoom out (increase viewBox size) */
|
|
685
685
|
zoomOut: () => void;
|
|
686
|
+
/** Fit viewBox to content bounds with optional padding */
|
|
687
|
+
fitToContent: (bounds: {
|
|
688
|
+
minX: number;
|
|
689
|
+
minY: number;
|
|
690
|
+
maxX: number;
|
|
691
|
+
maxY: number;
|
|
692
|
+
}, padding?: number) => void;
|
|
693
|
+
/** Set viewBox directly */
|
|
694
|
+
setViewBox: (viewBox: ViewBox) => void;
|
|
686
695
|
/** Convert screen coordinates to world (SVG) coordinates */
|
|
687
696
|
screenToWorld: (screenX: number, screenY: number) => {
|
|
688
697
|
x: number;
|
|
@@ -927,9 +936,19 @@ interface PIDCanvasProps extends react__default.HTMLAttributes<HTMLDivElement> {
|
|
|
927
936
|
}) => void;
|
|
928
937
|
/** Callback when a pipe is created via connection mode */
|
|
929
938
|
onPipeCreated?: (sourceNodeId: string, targetNodeId: string, sourcePortId?: string, targetPortId?: string) => void;
|
|
939
|
+
/** Callback when canvas is mounted, provides control functions */
|
|
940
|
+
onMounted?: (controls: PIDCanvasControls) => void;
|
|
930
941
|
/** Telemetry data bindings for live values */
|
|
931
942
|
telemetry?: TelemetryMap;
|
|
932
943
|
}
|
|
944
|
+
interface PIDCanvasControls {
|
|
945
|
+
/** Fit view to show all diagram content */
|
|
946
|
+
fitToContent: (padding?: number) => void;
|
|
947
|
+
/** Set zoom level (1 = 100%, 2 = 200%, etc.) */
|
|
948
|
+
setZoom: (zoomLevel: number) => void;
|
|
949
|
+
/** Get current zoom level */
|
|
950
|
+
getZoom: () => number;
|
|
951
|
+
}
|
|
933
952
|
/**
|
|
934
953
|
* PIDCanvas - Interactive canvas for rendering P&ID diagrams
|
|
935
954
|
*
|
|
@@ -939,7 +958,7 @@ interface PIDCanvasProps extends react__default.HTMLAttributes<HTMLDivElement> {
|
|
|
939
958
|
*
|
|
940
959
|
* Future: Editing tools, symbol library UI
|
|
941
960
|
*/
|
|
942
|
-
declare function PIDCanvas({ diagram, className, style, features, onSelectionChange, onNodeClick, onPipeClick, onNodeMove, onDiagramChange, onDelete, onItemsCopied, onPaste, onSymbolDrop, onPipeCreated, telemetry, ...props }: PIDCanvasProps): react__default.ReactElement;
|
|
961
|
+
declare function PIDCanvas({ diagram, className, style, features, onSelectionChange, onNodeClick, onPipeClick, onNodeMove, onDiagramChange, onDelete, onItemsCopied, onPaste, onSymbolDrop, onPipeCreated, onMounted, telemetry, ...props }: PIDCanvasProps): react__default.ReactElement;
|
|
943
962
|
|
|
944
963
|
interface SymbolLibraryProps {
|
|
945
964
|
/** Optional className for styling */
|
package/dist/index.js
CHANGED
|
@@ -2347,6 +2347,34 @@ function useViewBox(options) {
|
|
|
2347
2347
|
};
|
|
2348
2348
|
});
|
|
2349
2349
|
}, [initialViewBox, maxZoom]);
|
|
2350
|
+
const fitToContent = useCallback3((bounds, padding = 50) => {
|
|
2351
|
+
const contentWidth = bounds.maxX - bounds.minX;
|
|
2352
|
+
const contentHeight = bounds.maxY - bounds.minY;
|
|
2353
|
+
if (contentWidth === 0 || contentHeight === 0) {
|
|
2354
|
+
return;
|
|
2355
|
+
}
|
|
2356
|
+
const paddedWidth = contentWidth + padding * 2;
|
|
2357
|
+
const paddedHeight = contentHeight + padding * 2;
|
|
2358
|
+
const aspectRatio = initialViewBox.width / initialViewBox.height;
|
|
2359
|
+
const contentAspectRatio = paddedWidth / paddedHeight;
|
|
2360
|
+
let newWidth;
|
|
2361
|
+
let newHeight;
|
|
2362
|
+
if (contentAspectRatio > aspectRatio) {
|
|
2363
|
+
newWidth = paddedWidth;
|
|
2364
|
+
newHeight = paddedWidth / aspectRatio;
|
|
2365
|
+
} else {
|
|
2366
|
+
newHeight = paddedHeight;
|
|
2367
|
+
newWidth = paddedHeight * aspectRatio;
|
|
2368
|
+
}
|
|
2369
|
+
const centerX = bounds.minX + contentWidth / 2;
|
|
2370
|
+
const centerY = bounds.minY + contentHeight / 2;
|
|
2371
|
+
setViewBox({
|
|
2372
|
+
x: centerX - newWidth / 2,
|
|
2373
|
+
y: centerY - newHeight / 2,
|
|
2374
|
+
width: newWidth,
|
|
2375
|
+
height: newHeight
|
|
2376
|
+
});
|
|
2377
|
+
}, [initialViewBox]);
|
|
2350
2378
|
useEffect4(() => {
|
|
2351
2379
|
if (!enableZoom || !svgRef.current) return;
|
|
2352
2380
|
const svg = svgRef.current;
|
|
@@ -2578,6 +2606,8 @@ function useViewBox(options) {
|
|
|
2578
2606
|
resetViewBox,
|
|
2579
2607
|
zoomIn,
|
|
2580
2608
|
zoomOut,
|
|
2609
|
+
fitToContent,
|
|
2610
|
+
setViewBox,
|
|
2581
2611
|
screenToWorld,
|
|
2582
2612
|
svgRef
|
|
2583
2613
|
};
|
|
@@ -3232,6 +3262,7 @@ function PIDCanvas({
|
|
|
3232
3262
|
onPaste,
|
|
3233
3263
|
onSymbolDrop,
|
|
3234
3264
|
onPipeCreated,
|
|
3265
|
+
onMounted,
|
|
3235
3266
|
telemetry,
|
|
3236
3267
|
...props
|
|
3237
3268
|
}) {
|
|
@@ -3249,12 +3280,72 @@ function PIDCanvas({
|
|
|
3249
3280
|
const {
|
|
3250
3281
|
viewBox: controlledViewBox,
|
|
3251
3282
|
svgRef,
|
|
3252
|
-
screenToWorld
|
|
3283
|
+
screenToWorld,
|
|
3284
|
+
fitToContent: fitToContentViewBox,
|
|
3285
|
+
setViewBox
|
|
3253
3286
|
} = useViewBox({
|
|
3254
3287
|
initialViewBox: diagram.viewBox,
|
|
3255
3288
|
enablePan: features.pan ?? true,
|
|
3256
3289
|
enableZoom: features.zoom ?? true
|
|
3257
3290
|
});
|
|
3291
|
+
const calculateContentBounds = useCallback7(() => {
|
|
3292
|
+
const nodes2 = localDiagram.nodes.filter((n) => n.visible !== false);
|
|
3293
|
+
if (nodes2.length === 0) {
|
|
3294
|
+
return null;
|
|
3295
|
+
}
|
|
3296
|
+
let minX = Infinity;
|
|
3297
|
+
let minY = Infinity;
|
|
3298
|
+
let maxX = -Infinity;
|
|
3299
|
+
let maxY = -Infinity;
|
|
3300
|
+
nodes2.forEach((node) => {
|
|
3301
|
+
const symbol = getSymbolDefinition(node.symbolId);
|
|
3302
|
+
if (!symbol) return;
|
|
3303
|
+
const nodeMinX = node.transform.x;
|
|
3304
|
+
const nodeMinY = node.transform.y;
|
|
3305
|
+
const nodeMaxX = node.transform.x + symbol.viewBox.width;
|
|
3306
|
+
const nodeMaxY = node.transform.y + symbol.viewBox.height;
|
|
3307
|
+
minX = Math.min(minX, nodeMinX);
|
|
3308
|
+
minY = Math.min(minY, nodeMinY);
|
|
3309
|
+
maxX = Math.max(maxX, nodeMaxX);
|
|
3310
|
+
maxY = Math.max(maxY, nodeMaxY);
|
|
3311
|
+
});
|
|
3312
|
+
return { minX, minY, maxX, maxY };
|
|
3313
|
+
}, [localDiagram.nodes]);
|
|
3314
|
+
useEffect8(() => {
|
|
3315
|
+
if (onMounted) {
|
|
3316
|
+
const controls = {
|
|
3317
|
+
fitToContent: (padding = 50) => {
|
|
3318
|
+
const bounds = calculateContentBounds();
|
|
3319
|
+
if (bounds) {
|
|
3320
|
+
fitToContentViewBox(bounds, padding);
|
|
3321
|
+
}
|
|
3322
|
+
},
|
|
3323
|
+
setZoom: (zoomLevel) => {
|
|
3324
|
+
const centerX = controlledViewBox.x + controlledViewBox.width / 2;
|
|
3325
|
+
const centerY = controlledViewBox.y + controlledViewBox.height / 2;
|
|
3326
|
+
const newWidth = diagram.viewBox.width / zoomLevel;
|
|
3327
|
+
const newHeight = diagram.viewBox.height / zoomLevel;
|
|
3328
|
+
setViewBox({
|
|
3329
|
+
x: centerX - newWidth / 2,
|
|
3330
|
+
y: centerY - newHeight / 2,
|
|
3331
|
+
width: newWidth,
|
|
3332
|
+
height: newHeight
|
|
3333
|
+
});
|
|
3334
|
+
},
|
|
3335
|
+
getZoom: () => {
|
|
3336
|
+
return diagram.viewBox.width / controlledViewBox.width;
|
|
3337
|
+
}
|
|
3338
|
+
};
|
|
3339
|
+
onMounted(controls);
|
|
3340
|
+
}
|
|
3341
|
+
}, [
|
|
3342
|
+
onMounted,
|
|
3343
|
+
calculateContentBounds,
|
|
3344
|
+
fitToContentViewBox,
|
|
3345
|
+
setViewBox,
|
|
3346
|
+
controlledViewBox,
|
|
3347
|
+
diagram.viewBox
|
|
3348
|
+
]);
|
|
3258
3349
|
const { selection, selectNode, selectPipe, clearSelection } = useSelection({
|
|
3259
3350
|
multiSelect: features.multiSelect ?? true,
|
|
3260
3351
|
onSelectionChange
|