@principal-ai/principal-view-react 0.13.6 → 0.13.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@principal-ai/principal-view-react",
3
- "version": "0.13.6",
3
+ "version": "0.13.7",
4
4
  "description": "React components for graph-based principal view framework",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,7 +1,7 @@
1
1
  import React, { useState, useEffect } from 'react';
2
2
  import type { Meta, StoryObj } from '@storybook/react';
3
3
  import { GraphRenderer } from '../components/GraphRenderer';
4
- import type { ExtendedCanvas, GraphEvent } from '@principal-ai/principal-view-core';
4
+ import type { ExtendedCanvas, GraphEvent, ComponentLibrary } from '@principal-ai/principal-view-core';
5
5
  import { ThemeProvider, defaultEditorTheme } from '@principal-ade/industry-theme';
6
6
 
7
7
  // Helper component that sets initial node states via events
@@ -638,3 +638,256 @@ Higher priority always wins when multiple values are specified.
638
638
  },
639
639
  },
640
640
  };
641
+
642
+ // ============================================================================
643
+ // Library Color Priority Story
644
+ // Priority: library.nodeComponents.color → node.color → pv.fill → state.color
645
+ // ============================================================================
646
+
647
+ const libraryColorTestLibrary: ComponentLibrary = {
648
+ version: '1.0.0',
649
+ name: 'Color Test Library',
650
+ description: 'Library for testing color inheritance',
651
+ resources: {},
652
+ nodeComponents: {
653
+ 'service-red': {
654
+ description: 'Service with red color from library',
655
+ shape: 'rectangle',
656
+ color: '#FF0000', // RED from library
657
+ icon: 'Server',
658
+ },
659
+ 'service-green': {
660
+ description: 'Service with green color from library',
661
+ shape: 'rectangle',
662
+ color: '#00FF00', // GREEN from library
663
+ icon: 'Database',
664
+ },
665
+ 'service-blue': {
666
+ description: 'Service with blue color from library',
667
+ shape: 'rectangle',
668
+ color: '#0000FF', // BLUE from library
669
+ icon: 'Settings',
670
+ },
671
+ 'service-purple': {
672
+ description: 'Service with purple color from library',
673
+ shape: 'rectangle',
674
+ color: '#8B00FF', // PURPLE from library
675
+ icon: 'Zap',
676
+ },
677
+ },
678
+ edgeComponents: {
679
+ 'flow-orange': {
680
+ description: 'Flow edge with orange color from library',
681
+ style: 'solid',
682
+ color: '#FFA500', // ORANGE from library
683
+ directed: true,
684
+ },
685
+ 'flow-cyan': {
686
+ description: 'Flow edge with cyan color from library',
687
+ style: 'solid',
688
+ color: '#00FFFF', // CYAN from library
689
+ directed: true,
690
+ },
691
+ },
692
+ };
693
+
694
+ const libraryColorPriorityCanvas: ExtendedCanvas = {
695
+ nodes: [
696
+ // 1. Library color only (nodeType references library, no other colors)
697
+ {
698
+ id: 'library-only',
699
+ type: 'text',
700
+ x: 100,
701
+ y: 100,
702
+ width: 180,
703
+ height: 100,
704
+ text: 'SOURCE: library\nEXPECT: RED\n(from service-red)',
705
+ pv: {
706
+ nodeType: 'service-red', // Should get RED from library
707
+ shape: 'rectangle',
708
+ },
709
+ },
710
+ // 2. Library color overridden by node.color
711
+ {
712
+ id: 'library-vs-node-color',
713
+ type: 'text',
714
+ x: 320,
715
+ y: 100,
716
+ width: 180,
717
+ height: 100,
718
+ text: 'SOURCE: node.color\nEXPECT: YELLOW\n(library GREEN ignored)',
719
+ color: '#FFFF00', // YELLOW - should override library GREEN
720
+ pv: {
721
+ nodeType: 'service-green', // Would be GREEN, but overridden
722
+ shape: 'rectangle',
723
+ },
724
+ },
725
+ // 3. Library color overridden by pv.fill
726
+ {
727
+ id: 'library-vs-pv-fill',
728
+ type: 'text',
729
+ x: 540,
730
+ y: 100,
731
+ width: 180,
732
+ height: 100,
733
+ text: 'SOURCE: pv.fill\nEXPECT: CYAN\n(library BLUE ignored)',
734
+ pv: {
735
+ nodeType: 'service-blue', // Would be BLUE, but overridden
736
+ shape: 'rectangle',
737
+ fill: '#00FFFF', // CYAN - should override library BLUE
738
+ },
739
+ },
740
+ // 4. Library color overridden by state color
741
+ {
742
+ id: 'library-vs-state',
743
+ type: 'text',
744
+ x: 760,
745
+ y: 100,
746
+ width: 180,
747
+ height: 100,
748
+ text: 'SOURCE: state.color\nEXPECT: ORANGE\n(library PURPLE ignored)',
749
+ pv: {
750
+ nodeType: 'service-purple', // Would be PURPLE, but overridden by state
751
+ shape: 'rectangle',
752
+ states: {
753
+ active: { label: 'Active', color: '#FFA500' }, // ORANGE
754
+ },
755
+ },
756
+ },
757
+ // 5. Another library color node for comparison
758
+ {
759
+ id: 'library-green',
760
+ type: 'text',
761
+ x: 100,
762
+ y: 250,
763
+ width: 180,
764
+ height: 100,
765
+ text: 'SOURCE: library\nEXPECT: GREEN\n(from service-green)',
766
+ pv: {
767
+ nodeType: 'service-green',
768
+ shape: 'rectangle',
769
+ },
770
+ },
771
+ // 6. Library blue for comparison
772
+ {
773
+ id: 'library-blue',
774
+ type: 'text',
775
+ x: 320,
776
+ y: 250,
777
+ width: 180,
778
+ height: 100,
779
+ text: 'SOURCE: library\nEXPECT: BLUE\n(from service-blue)',
780
+ pv: {
781
+ nodeType: 'service-blue',
782
+ shape: 'rectangle',
783
+ },
784
+ },
785
+ ],
786
+ edges: [
787
+ // Edge using library color
788
+ {
789
+ id: 'edge-library-orange',
790
+ fromNode: 'library-green',
791
+ toNode: 'library-blue',
792
+ pv: {
793
+ edgeType: 'flow-orange', // Should get ORANGE from library
794
+ },
795
+ },
796
+ // Edge with library color overridden
797
+ {
798
+ id: 'edge-override',
799
+ fromNode: 'library-only',
800
+ toNode: 'library-vs-node-color',
801
+ color: '#FF00FF', // MAGENTA - overrides library
802
+ pv: {
803
+ edgeType: 'flow-cyan', // Would be CYAN, but overridden
804
+ },
805
+ },
806
+ ],
807
+ pv: {
808
+ version: '1.0.0',
809
+ name: 'Library Color Priority Demo',
810
+ description: 'Shows how library.yaml colors are applied and overridden',
811
+ edgeTypes: {},
812
+ },
813
+ };
814
+
815
+ // Helper component for library color test
816
+ const GraphWithLibrary: React.FC<{
817
+ canvas: ExtendedCanvas;
818
+ library: ComponentLibrary;
819
+ width: number;
820
+ height: number;
821
+ showMinimap: boolean;
822
+ initialStates?: Record<string, string>;
823
+ }> = ({ canvas, library, width, height, showMinimap, initialStates }) => {
824
+ const [events, setEvents] = useState<GraphEvent[]>([]);
825
+
826
+ useEffect(() => {
827
+ if (initialStates) {
828
+ const stateEvents: GraphEvent[] = Object.entries(initialStates).map(
829
+ ([nodeId, newState], idx) => ({
830
+ id: `init-state-${idx}`,
831
+ type: 'state_changed',
832
+ timestamp: Date.now(),
833
+ category: 'state' as const,
834
+ payload: { nodeId, newState },
835
+ })
836
+ );
837
+ setEvents(stateEvents);
838
+ }
839
+ }, []);
840
+
841
+ return (
842
+ <GraphRenderer
843
+ canvas={canvas}
844
+ library={library}
845
+ width={width}
846
+ height={height}
847
+ showMinimap={showMinimap}
848
+ events={events}
849
+ />
850
+ );
851
+ };
852
+
853
+ export const LibraryColorPriority: Story = {
854
+ render: () => (
855
+ <GraphWithLibrary
856
+ canvas={libraryColorPriorityCanvas}
857
+ library={libraryColorTestLibrary}
858
+ width={1050}
859
+ height={450}
860
+ showMinimap={false}
861
+ initialStates={{ 'library-vs-state': 'active' }}
862
+ />
863
+ ),
864
+ parameters: {
865
+ docs: {
866
+ description: {
867
+ story: `
868
+ **Library Color Priority** - Tests colors from library.yaml nodeComponents
869
+
870
+ This story validates that the \`library\` prop correctly provides colors to nodes via nodeType lookup.
871
+
872
+ **Full Fill Color Priority Chain** (lowest to highest):
873
+ 1. **Default** - Falls back to #888 gray
874
+ 2. **Library nodeComponent color** - Color from library.yaml nodeComponents[nodeType].color
875
+ 3. **node.color** - The standard canvas node color property
876
+ 4. **pv.fill** - Explicit fill color in the PV extension
877
+ 5. **state.color** - When a node has an active state with a color defined
878
+
879
+ **In this demo:**
880
+ - Row 1 Node 1: Uses \`service-red\` nodeType → gets RED from library
881
+ - Row 1 Node 2: Uses \`service-green\` nodeType but has node.color=YELLOW → YELLOW wins
882
+ - Row 1 Node 3: Uses \`service-blue\` nodeType but has pv.fill=CYAN → CYAN wins
883
+ - Row 1 Node 4: Uses \`service-purple\` nodeType but is in "active" state → ORANGE wins
884
+ - Row 2: Pure library colors (GREEN, BLUE) for visual comparison
885
+
886
+ **Edge Colors:**
887
+ - Bottom edge: Uses \`flow-orange\` edgeType → gets ORANGE from library
888
+ - Top edge: Uses \`flow-cyan\` but has edge.color=MAGENTA → MAGENTA wins
889
+ `,
890
+ },
891
+ },
892
+ },
893
+ };