@teambit/graph 0.0.752 → 0.0.755

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.
Files changed (87) hide show
  1. package/dist/graph.compare.section.d.ts +13 -0
  2. package/dist/graph.compare.section.js +57 -0
  3. package/dist/graph.compare.section.js.map +1 -0
  4. package/dist/graph.ui.runtime.d.ts +2 -1
  5. package/dist/graph.ui.runtime.js +28 -2
  6. package/dist/graph.ui.runtime.js.map +1 -1
  7. package/dist/index.d.ts +12 -7
  8. package/dist/index.js +149 -9
  9. package/dist/index.js.map +1 -1
  10. package/dist/ui/component-node/component-node.js +27 -1
  11. package/dist/ui/component-node/component-node.js.map +1 -1
  12. package/dist/ui/component-node/component-node.module.scss +8 -0
  13. package/dist/ui/component-node/index.d.ts +12 -1
  14. package/dist/ui/component-node/index.js +56 -0
  15. package/dist/ui/component-node/index.js.map +1 -1
  16. package/dist/ui/component-node/variants.d.ts +2 -2
  17. package/dist/ui/component-node/variants.js +3 -1
  18. package/dist/ui/component-node/variants.js.map +1 -1
  19. package/dist/ui/dependencies-compare/compare-graph-model.d.ts +7 -0
  20. package/dist/ui/dependencies-compare/compare-graph-model.js +29 -0
  21. package/dist/ui/dependencies-compare/compare-graph-model.js.map +1 -0
  22. package/dist/ui/dependencies-compare/compare-node-model.d.ts +9 -0
  23. package/dist/ui/dependencies-compare/compare-node-model.js +45 -0
  24. package/dist/ui/dependencies-compare/compare-node-model.js.map +1 -0
  25. package/dist/ui/dependencies-compare/dependencies-compare.d.ts +2 -0
  26. package/dist/ui/dependencies-compare/dependencies-compare.js +205 -0
  27. package/dist/ui/dependencies-compare/dependencies-compare.js.map +1 -0
  28. package/dist/ui/dependencies-compare/dependencies-compare.module.scss +12 -0
  29. package/dist/ui/dependencies-compare/dependency-compare-node.d.ts +7 -0
  30. package/dist/ui/dependencies-compare/dependency-compare-node.js +271 -0
  31. package/dist/ui/dependencies-compare/dependency-compare-node.js.map +1 -0
  32. package/dist/ui/dependencies-compare/dependency-compare-node.module.scss +21 -0
  33. package/dist/ui/dependencies-compare/dependency-compare-variants.module.scss +21 -0
  34. package/dist/ui/dependencies-compare/diff-graph.d.ts +4 -0
  35. package/dist/ui/dependencies-compare/diff-graph.js +96 -0
  36. package/dist/ui/dependencies-compare/diff-graph.js.map +1 -0
  37. package/dist/ui/dependencies-compare/index.d.ts +1 -0
  38. package/dist/ui/dependencies-compare/index.js +23 -0
  39. package/dist/ui/dependencies-compare/index.js.map +1 -0
  40. package/dist/ui/dependencies-graph/calc-elements.d.ts +3 -3
  41. package/dist/ui/dependencies-graph/calc-elements.js.map +1 -1
  42. package/dist/ui/dependencies-graph/calc-layout.d.ts +2 -2
  43. package/dist/ui/dependencies-graph/calc-layout.js.map +1 -1
  44. package/dist/ui/dependencies-graph/dependencies-graph.d.ts +2 -2
  45. package/dist/ui/dependencies-graph/dependencies-graph.js.map +1 -1
  46. package/dist/ui/dependencies-graph/index.d.ts +9 -0
  47. package/dist/ui/dependencies-graph/index.js +96 -0
  48. package/dist/ui/dependencies-graph/index.js.map +1 -1
  49. package/dist/ui/graph-page/index.d.ts +5 -0
  50. package/dist/ui/graph-page/index.js +40 -0
  51. package/dist/ui/graph-page/index.js.map +1 -1
  52. package/dist/ui/query/graph-model.d.ts +5 -5
  53. package/dist/ui/query/graph-model.js.map +1 -1
  54. package/dist/ui/query/index.d.ts +1 -0
  55. package/dist/ui/query/index.js +16 -0
  56. package/dist/ui/query/index.js.map +1 -1
  57. package/dist/ui/query/use-graph-query.d.ts +2 -2
  58. package/dist/ui/query/use-graph-query.js +2 -1
  59. package/dist/ui/query/use-graph-query.js.map +1 -1
  60. package/dist/ui/query/use-graph.d.ts +1 -1
  61. package/graph.compare.section.tsx +16 -0
  62. package/graph.ui.runtime.tsx +14 -4
  63. package/package-tar/teambit-graph-0.0.755.tgz +0 -0
  64. package/package.json +15 -8
  65. package/{preview-1654399579544.js → preview-1654697373869.js} +2 -2
  66. package/ui/component-node/component-node.module.scss +8 -0
  67. package/ui/component-node/component-node.tsx +5 -1
  68. package/ui/component-node/index.ts +6 -1
  69. package/ui/component-node/variants.ts +2 -2
  70. package/ui/dependencies-compare/compare-graph-model.ts +8 -0
  71. package/ui/dependencies-compare/compare-node-model.ts +11 -0
  72. package/ui/dependencies-compare/dependencies-compare.module.scss +12 -0
  73. package/ui/dependencies-compare/dependencies-compare.tsx +109 -0
  74. package/ui/dependencies-compare/dependency-compare-node.module.scss +21 -0
  75. package/ui/dependencies-compare/dependency-compare-node.tsx +99 -0
  76. package/ui/dependencies-compare/dependency-compare-variants.module.scss +21 -0
  77. package/ui/dependencies-compare/diff-graph.ts +69 -0
  78. package/ui/dependencies-compare/index.ts +1 -0
  79. package/ui/dependencies-graph/calc-elements.tsx +3 -3
  80. package/ui/dependencies-graph/calc-layout.tsx +2 -2
  81. package/ui/dependencies-graph/dependencies-graph.tsx +8 -8
  82. package/ui/dependencies-graph/index.ts +9 -0
  83. package/ui/graph-page/index.ts +6 -0
  84. package/ui/query/graph-model.ts +3 -2
  85. package/ui/query/index.ts +1 -0
  86. package/ui/query/use-graph-query.ts +3 -2
  87. package/package-tar/teambit-graph-0.0.752.tgz +0 -0
@@ -1,10 +1,11 @@
1
1
  import { ComponentType } from 'react';
2
2
  import { UIRuntime } from '@teambit/ui';
3
3
  import { Slot, SlotRegistry } from '@teambit/harmony';
4
-
4
+ import { ComponentCompareUI, ComponentCompareAspect } from '@teambit/component-compare';
5
5
  import { ComponentAspect, ComponentUI, ComponentModel } from '@teambit/component';
6
6
  import { GraphAspect } from './graph.aspect';
7
7
  import { GraphSection } from './ui/graph.section';
8
+ import { GraphCompareSection } from './graph.compare.section';
8
9
 
9
10
  export interface ComponentWidgetProps extends React.HTMLAttributes<HTMLDivElement> {
10
11
  component: ComponentModel;
@@ -25,15 +26,24 @@ export class GraphUI {
25
26
  }
26
27
 
27
28
  constructor(private componentWidgetSlot: ComponentWidgetSlot) {}
28
- static dependencies = [ComponentAspect];
29
+ static dependencies = [ComponentAspect, ComponentCompareAspect];
29
30
  static runtime = UIRuntime;
30
31
  static slots = [Slot.withType<ComponentWidget>()];
31
- static async provider([componentUI]: [ComponentUI], config, [componentWidgetSlot]: [ComponentWidgetSlot]) {
32
+ static async provider(
33
+ [componentUI, componentCompare]: [ComponentUI, ComponentCompareUI],
34
+ config,
35
+ [componentWidgetSlot]: [ComponentWidgetSlot]
36
+ ) {
32
37
  const graphUI = new GraphUI(componentWidgetSlot);
33
38
  const section = new GraphSection(componentWidgetSlot);
39
+ const graphSection = new GraphCompareSection();
34
40
  componentUI.registerNavigation(section.navigationLink, section.order);
35
41
  componentUI.registerRoute(section.route);
36
-
42
+ componentCompare.registerNavigation({
43
+ props: graphSection.navigationLink,
44
+ order: graphSection.navigationLink.order,
45
+ });
46
+ componentCompare.registerRoutes([graphSection.route]);
37
47
  return graphUI;
38
48
  }
39
49
  }
package/package.json CHANGED
@@ -1,35 +1,41 @@
1
1
  {
2
2
  "name": "@teambit/graph",
3
- "version": "0.0.752",
3
+ "version": "0.0.755",
4
4
  "homepage": "https://bit.dev/teambit/component/graph",
5
5
  "main": "dist/index.js",
6
6
  "componentId": {
7
7
  "scope": "teambit.component",
8
8
  "name": "graph",
9
- "version": "0.0.752"
9
+ "version": "0.0.755"
10
10
  },
11
11
  "dependencies": {
12
12
  "graphql-tag": "2.12.1",
13
13
  "lodash": "4.17.21",
14
14
  "classnames": "2.2.6",
15
15
  "react-flow-renderer": "8.3.7",
16
+ "semver": "7.3.4",
16
17
  "dagre": "0.8.5",
17
18
  "@babel/runtime": "7.12.18",
18
19
  "core-js": "^3.0.0",
19
20
  "@teambit/graph.cleargraph": "0.0.1",
20
21
  "@teambit/harmony": "0.3.3",
22
+ "@teambit/base-ui.routing.nav-link": "1.0.0",
21
23
  "@teambit/base-ui.surfaces.card": "1.0.1",
22
24
  "@teambit/base-ui.text.muted-text": "1.0.1",
23
25
  "@teambit/evangelist.input.checkbox.label": "1.0.3",
24
26
  "@teambit/documenter.ui.heading": "4.1.1",
25
- "@teambit/component": "0.0.752",
26
- "@teambit/graphql": "0.0.752",
27
- "@teambit/cli": "0.0.496",
28
- "@teambit/ui": "0.0.752",
27
+ "@teambit/component": "0.0.755",
28
+ "@teambit/graphql": "0.0.755",
29
+ "@teambit/cli": "0.0.498",
30
+ "@teambit/component-compare": "0.0.3",
31
+ "@teambit/ui": "0.0.755",
29
32
  "@teambit/legacy-bit-id": "0.0.399",
33
+ "@teambit/component.modules.component-url": "0.0.124",
30
34
  "@teambit/component.ui.deprecation-icon": "0.0.493",
31
35
  "@teambit/design.ui.styles.ellipsis": "0.0.347",
32
36
  "@teambit/envs.ui.env-icon": "0.0.486",
37
+ "@teambit/component.ui.compare": "0.0.3",
38
+ "@teambit/design.ui.round-loader": "0.0.346",
33
39
  "@teambit/design.ui.pages.not-found": "0.0.355",
34
40
  "@teambit/design.ui.pages.server-error": "0.0.355",
35
41
  "@teambit/ui-foundation.ui.full-loader": "0.0.486",
@@ -40,6 +46,7 @@
40
46
  "@types/react": "^17.0.8",
41
47
  "@types/lodash": "4.14.165",
42
48
  "@types/classnames": "2.2.11",
49
+ "@types/semver": "7.3.4",
43
50
  "@types/dagre": "0.7.44",
44
51
  "@types/mocha": "9.1.0",
45
52
  "@types/testing-library__jest-dom": "5.9.5",
@@ -49,7 +56,7 @@
49
56
  },
50
57
  "peerDependencies": {
51
58
  "@apollo/client": "^3.0.0",
52
- "@teambit/legacy": "1.0.276",
59
+ "@teambit/legacy": "1.0.278",
53
60
  "react-dom": "^16.8.0 || ^17.0.0",
54
61
  "react": "^16.8.0 || ^17.0.0"
55
62
  },
@@ -77,7 +84,7 @@
77
84
  "react": "-"
78
85
  },
79
86
  "peerDependencies": {
80
- "@teambit/legacy": "1.0.276",
87
+ "@teambit/legacy": "1.0.278",
81
88
  "react-dom": "^16.8.0 || ^17.0.0",
82
89
  "react": "^16.8.0 || ^17.0.0"
83
90
  }
@@ -1,2 +1,2 @@
1
- export const compositions = [require('/home/circleci/Library/Caches/Bit/capsules/8891be5ad3d35bfc38b9cd90c0e05b598a5a55af/teambit.component_graph@0.0.752/dist/graph.composition.js')]
2
- export const overview = [require('/home/circleci/Library/Caches/Bit/capsules/8891be5ad3d35bfc38b9cd90c0e05b598a5a55af/teambit.component_graph@0.0.752/dist/graph.docs.md')]
1
+ export const compositions = [require('/home/circleci/Library/Caches/Bit/capsules/8891be5ad3d35bfc38b9cd90c0e05b598a5a55af/teambit.component_graph@0.0.755/dist/graph.composition.js')]
2
+ export const overview = [require('/home/circleci/Library/Caches/Bit/capsules/8891be5ad3d35bfc38b9cd90c0e05b598a5a55af/teambit.component_graph@0.0.755/dist/graph.docs.md')]
@@ -61,3 +61,11 @@
61
61
  display: none;
62
62
  }
63
63
  }
64
+
65
+ .link {
66
+ text-decoration: none;
67
+ color: var(--bit-text-color-heavyed);
68
+ &:hover {
69
+ text-decoration: underline;
70
+ }
71
+ }
@@ -6,6 +6,8 @@ import { DeprecationIcon } from '@teambit/component.ui.deprecation-icon';
6
6
  import { EnvIcon } from '@teambit/envs.ui.env-icon';
7
7
  import { ellipsis } from '@teambit/design.ui.styles.ellipsis';
8
8
  import { Card, CardProps } from '@teambit/base-ui.surfaces.card';
9
+ import { NavLink } from '@teambit/base-ui.routing.nav-link';
10
+ import { ComponentUrl } from '@teambit/component.modules.component-url';
9
11
  import { NodeModel } from '../query/node-model';
10
12
  import { ComponentGraphContext } from '../dependencies-graph/';
11
13
 
@@ -30,7 +32,9 @@ export function ComponentNode({ node, type = 'defaultNode', ...rest }: Component
30
32
  <Breadcrumbs componentId={id} className={mutedText} />
31
33
  </div>
32
34
  <div className={styles.nameLine}>
33
- <span className={classnames(styles.name, ellipsis)}>{id.name}</span>
35
+ <NavLink className={styles.link} external={true} href={ComponentUrl.toUrl(id, { includeVersion: false })}>
36
+ <span className={classnames(styles.name, ellipsis)}>{id.name}</span>
37
+ </NavLink>
34
38
  {id.version && <span className={classnames(styles.version, ellipsis)}>{id.version}</span>}
35
39
 
36
40
  <div className={styles.buffs}>
@@ -1,3 +1,8 @@
1
+ import componentStyles from './component-node.module.scss';
2
+
1
3
  export { ComponentNode } from './component-node';
2
4
 
3
- export { defaultNodeColor, rootNodeColor, externalNodeColor } from './variants';
5
+ export { defaultNodeColor, rootNodeColor, externalNodeColor, root, defaultNode, external } from './variants';
6
+
7
+ const { compNode, firstRow, envIcon, breadcrumbs, nameLine, name, version, buffs, link } = componentStyles;
8
+ export const styles = { compNode, firstRow, envIcon, breadcrumbs, nameLine, name, version, buffs, link };
@@ -1,5 +1,5 @@
1
1
  import variants from './variants.module.scss';
2
2
 
3
- const { root, defaultNode, rootNodeColor, defaultNodeColor, externalNodeColor } = variants;
3
+ const { root, defaultNode, external, rootNodeColor, defaultNodeColor, externalNodeColor } = variants;
4
4
 
5
- export { root, defaultNode, rootNodeColor, defaultNodeColor, externalNodeColor };
5
+ export { root, defaultNode, external, rootNodeColor, defaultNodeColor, externalNodeColor };
@@ -0,0 +1,8 @@
1
+ import { EdgeModel, GraphModel } from '@teambit/graph';
2
+ import { CompareNodeModel } from './compare-node-model';
3
+
4
+ export class CompareGraphModel extends GraphModel<CompareNodeModel, EdgeModel> {
5
+ constructor(public nodes: CompareNodeModel[], public edges: EdgeModel[]) {
6
+ super(nodes, edges);
7
+ }
8
+ }
@@ -0,0 +1,11 @@
1
+ import { ComponentModel } from '@teambit/component';
2
+ import { NodeModel } from '@teambit/graph';
3
+
4
+ export type CompareStatus = 'modified' | 'new' | 'deleted' | undefined;
5
+
6
+ export class CompareNodeModel extends NodeModel {
7
+ id: string;
8
+ component: ComponentModel;
9
+ compareVersion: string;
10
+ status: CompareStatus;
11
+ }
@@ -0,0 +1,12 @@
1
+ $d30: #878c9a;
2
+ $b70: #0d2de3;
3
+
4
+ .page {
5
+ margin-top: 16px; // not exported
6
+ }
7
+
8
+ .loader {
9
+ display: flex;
10
+ align-items: center;
11
+ height: 100%;
12
+ }
@@ -0,0 +1,109 @@
1
+ import classNames from 'classnames';
2
+ import { useComponentCompare } from '@teambit/component.ui.compare';
3
+ import { RoundLoader } from '@teambit/design.ui.round-loader';
4
+ import {
5
+ calcElements,
6
+ calcMinimapColors,
7
+ dependenciesGraphStyles,
8
+ GraphFilter,
9
+ GraphFilters,
10
+ graphPageStyles,
11
+ useGraphQuery,
12
+ } from '@teambit/graph';
13
+ import React, { useEffect, useRef, useState } from 'react';
14
+ import ReactFlow, {
15
+ Background,
16
+ Controls,
17
+ Handle,
18
+ MiniMap,
19
+ NodeProps,
20
+ NodeTypesType,
21
+ OnLoadParams,
22
+ Position,
23
+ ReactFlowProvider,
24
+ } from 'react-flow-renderer';
25
+ import styles from './dependencies-compare.module.scss';
26
+ import { DependencyCompareNode } from './dependency-compare-node';
27
+ import { diffGraph } from './diff-graph';
28
+
29
+ function ComponentNodeContainer(props: NodeProps) {
30
+ const { sourcePosition = Position.Top, targetPosition = Position.Bottom, data, id } = props;
31
+
32
+ return (
33
+ <div key={id}>
34
+ <Handle type="target" position={targetPosition} isConnectable={false} />
35
+ <Handle type="source" position={sourcePosition} isConnectable={false} />
36
+ <DependencyCompareNode node={data.node} type={data.type} />
37
+ </div>
38
+ );
39
+ }
40
+
41
+ const NodeTypes: NodeTypesType = { ComponentNode: ComponentNodeContainer };
42
+
43
+ export function DependenciesCompare() {
44
+ const graphRef = useRef<OnLoadParams>();
45
+ const componentCompare = useComponentCompare();
46
+
47
+ const baseId = componentCompare?.base?.id;
48
+ const compareId = componentCompare?.compare?.id;
49
+
50
+ const [filter, setFilter] = useState<GraphFilter>('runtimeOnly');
51
+ const isFiltered = filter === 'runtimeOnly';
52
+ const { loading: baseLoading, graph: baseGraph } = useGraphQuery(baseId && [baseId.toString()], filter);
53
+ const { loading: compareLoading, graph: compareGraph } = useGraphQuery(compareId && [compareId.toString()], filter);
54
+ const loading = baseLoading || compareLoading;
55
+ const graph = diffGraph(baseGraph, compareGraph, baseId) ?? undefined;
56
+ const elements = calcElements(graph, { rootNode: baseId });
57
+
58
+ useEffect(() => {
59
+ graphRef.current?.fitView();
60
+ }, [elements]);
61
+
62
+ function handleLoad(instance: OnLoadParams) {
63
+ graphRef.current = instance;
64
+ graphRef.current?.fitView();
65
+ }
66
+
67
+ const onCheckFilter = (_isFiltered: boolean) => {
68
+ setFilter(_isFiltered ? 'runtimeOnly' : undefined);
69
+ };
70
+
71
+ if (!loading && (!baseGraph || !compareGraph)) {
72
+ return <></>;
73
+ }
74
+
75
+ return (
76
+ <div className={classNames([styles.page, graphPageStyles.graph])}>
77
+ {loading && (
78
+ <div className={styles.loader}>
79
+ <RoundLoader />
80
+ </div>
81
+ )}
82
+ <ReactFlowProvider>
83
+ <ReactFlow
84
+ draggable={false}
85
+ nodesDraggable={true}
86
+ selectNodesOnDrag={false}
87
+ nodesConnectable={false}
88
+ zoomOnDoubleClick={false}
89
+ elementsSelectable={false}
90
+ maxZoom={1}
91
+ className={dependenciesGraphStyles.graph}
92
+ elements={elements}
93
+ nodeTypes={NodeTypes}
94
+ onLoad={handleLoad}
95
+ >
96
+ <Background />
97
+ <Controls className={dependenciesGraphStyles.controls} />
98
+ <MiniMap nodeColor={calcMinimapColors} className={dependenciesGraphStyles.minimap} />
99
+ <GraphFilters
100
+ className={graphPageStyles.filters}
101
+ disable={loading}
102
+ isFiltered={isFiltered}
103
+ onChangeFilter={onCheckFilter}
104
+ />
105
+ </ReactFlow>
106
+ </ReactFlowProvider>
107
+ </div>
108
+ );
109
+ }
@@ -0,0 +1,21 @@
1
+ .arrowIcon {
2
+ height: 16px;
3
+ padding-right: 8px;
4
+ }
5
+
6
+ .versionUp {
7
+ color: var(--positive-color, #37b26c);
8
+ }
9
+
10
+ .versionDown {
11
+ color: var(--negative-color, #e62e5c);
12
+ }
13
+
14
+ .link {
15
+ text-decoration: none;
16
+ color: var(--bit-text-color-heavyed);
17
+
18
+ &:hover {
19
+ text-decoration: underline;
20
+ }
21
+ }
@@ -0,0 +1,99 @@
1
+ import { NavLink } from '@teambit/base-ui.routing.nav-link';
2
+ import { Card } from '@teambit/base-ui.surfaces.card';
3
+ import { mutedText } from '@teambit/base-ui.text.muted-text';
4
+ import { ComponentID } from '@teambit/component';
5
+ import { ComponentUrl } from '@teambit/component.modules.component-url';
6
+ import { CompareStatusResolver } from '@teambit/component.ui.compare';
7
+ import { DeprecationIcon } from '@teambit/component.ui.deprecation-icon';
8
+ import { ellipsis } from '@teambit/design.ui.styles.ellipsis';
9
+ import { EnvIcon } from '@teambit/envs.ui.env-icon';
10
+ import { componentNodeStyles, defaultNode, external } from '@teambit/graph';
11
+ import classnames from 'classnames';
12
+ import React, { useMemo } from 'react';
13
+ import { compare, valid } from 'semver';
14
+ import { CompareNodeModel } from './compare-node-model';
15
+ import styles from './dependency-compare-node.module.scss';
16
+ import variants from './dependency-compare-variants.module.scss';
17
+
18
+ function getVariant(nodeType?: string) {
19
+ switch (nodeType) {
20
+ case 'defaultNode':
21
+ return defaultNode;
22
+ case 'root':
23
+ return variants[nodeType];
24
+ case 'external':
25
+ return external;
26
+ default:
27
+ return null;
28
+ }
29
+ }
30
+
31
+ export type DependencyCompareNodeProps = {
32
+ node: CompareNodeModel;
33
+ type?: string;
34
+ };
35
+
36
+ export function DependencyCompareNode(props: DependencyCompareNodeProps) {
37
+ const { node, type = 'defaultNode' } = props;
38
+ const { id: baseIdStr, component: baseComponent, compareVersion, status } = node;
39
+ const { version: baseVersion } = baseComponent;
40
+ const baseId = ComponentID.fromString(baseIdStr);
41
+ const versionDiff = useMemo(
42
+ () => valid(baseVersion) && valid(compareVersion) && compare(baseVersion, compareVersion),
43
+ [baseVersion, compareVersion]
44
+ );
45
+
46
+ return (
47
+ <Card className={classnames(componentNodeStyles.compNode, getVariant(type))} elevation="none">
48
+ <div className={componentNodeStyles.firstRow}>
49
+ <EnvIcon component={baseComponent} className={componentNodeStyles.envIcon} />
50
+ <Breadcrumbs componentId={baseId} className={mutedText} />
51
+ </div>
52
+ <div className={componentNodeStyles.nameLine}>
53
+ <NavLink className={styles.link} external={true} href={ComponentUrl.toUrl(baseId, { includeVersion: false })}>
54
+ <span className={classnames(componentNodeStyles.name, ellipsis)}>{baseId.name}</span>
55
+ </NavLink>
56
+ {baseId.version && <span className={classnames(componentNodeStyles.version, ellipsis)}>{baseId.version}</span>}
57
+ {versionDiff !== 0 && (
58
+ <img
59
+ className={classnames([styles.arrowIcon, styles.versionUp])}
60
+ src="https://static.bit.dev/bit-icons/version-bump.svg"
61
+ />
62
+ )}
63
+ {compareVersion && versionDiff !== 0 && (
64
+ <span
65
+ className={classnames(
66
+ styles.version,
67
+ componentNodeStyles.version,
68
+ ellipsis,
69
+ versionDiff === -1 && styles.versionUp,
70
+ versionDiff === 1 && styles.versionDown
71
+ )}
72
+ >
73
+ {compareVersion}
74
+ </span>
75
+ )}
76
+
77
+ <div className={styles.buffs}>
78
+ <DeprecationIcon component={baseComponent} />
79
+ {status !== undefined && <CompareStatusResolver status={status} />}
80
+ </div>
81
+ </div>
82
+ </Card>
83
+ );
84
+ }
85
+
86
+ type BreadcrumbsProps = { componentId: ComponentID } & React.HTMLAttributes<HTMLDivElement>;
87
+
88
+ function Breadcrumbs({ componentId, className, ...rest }: BreadcrumbsProps) {
89
+ const { scope, namespace } = componentId;
90
+ const showSep = !!scope && !!namespace;
91
+
92
+ return (
93
+ <div {...rest} className={classnames(styles.breadcrumbs, ellipsis, className)}>
94
+ {scope}
95
+ {showSep && '/'}
96
+ {namespace}
97
+ </div>
98
+ );
99
+ }
@@ -0,0 +1,21 @@
1
+ $success: #37b26c;
2
+ $borderLabelHeight: 20px;
3
+
4
+ .root {
5
+ border-color: $success;
6
+ border-top-width: 20px;
7
+
8
+ border-radius: 10px;
9
+ box-shadow: 0px 0px 0px 2px #d0f1de, var(--bit-shadow-hover-medium);
10
+
11
+ &:before {
12
+ content: 'Current component';
13
+ position: absolute;
14
+ top: 1px;
15
+ left: 10px;
16
+
17
+ font-size: $borderLabelHeight * 0.5;
18
+ color: white;
19
+ line-height: $borderLabelHeight;
20
+ }
21
+ }
@@ -0,0 +1,69 @@
1
+ import { ComponentID } from '@teambit/component';
2
+ import { EdgeModel, GraphModel, NodeModel } from '@teambit/graph';
3
+ import { CompareGraphModel } from './compare-graph-model';
4
+ import { CompareNodeModel } from './compare-node-model';
5
+
6
+ const toShortId = (node: NodeModel) => node.component.id.toStringWithoutVersion();
7
+
8
+ // this is to get a key with versions ignored so that we'll have a unique set of component nodes
9
+ const toShortIdFromNodeId = (nodeId: string) => nodeId.split('@')[0];
10
+
11
+ const delim = '::';
12
+
13
+ const getEdgeId = (_e: EdgeModel) => {
14
+ return `${toShortIdFromNodeId(_e.sourceId)}${delim}${toShortIdFromNodeId(_e.targetId)}`;
15
+ };
16
+
17
+ export function diffGraph(
18
+ baseGraph?: GraphModel<NodeModel, EdgeModel>,
19
+ compareGraph?: GraphModel<NodeModel, EdgeModel>,
20
+ baseId?: ComponentID
21
+ ) {
22
+ if (!baseGraph || !compareGraph || !baseId) return null;
23
+
24
+ const baseNodes = baseGraph.nodes;
25
+ const compareNodes = compareGraph.nodes;
26
+
27
+ const baseNodesMap = new Map<string, NodeModel>(baseNodes.map((n) => [toShortId(n), n]));
28
+ const compareNodesMap = new Map<string, NodeModel>(compareNodes.map((n) => [toShortId(n), n]));
29
+
30
+ const allNodes: Array<CompareNodeModel> = [];
31
+ for (const baseNode of baseNodes) {
32
+ const compareNode = compareNodesMap.get(toShortId(baseNode));
33
+ if (compareNode) {
34
+ allNodes.push({
35
+ ...baseNode,
36
+ compareVersion: compareNode.component.version,
37
+ status: compareNode.component.id.isEqual(baseNode.component.id) ? undefined : 'modified',
38
+ });
39
+ } else {
40
+ allNodes.push({
41
+ ...baseNode,
42
+ compareVersion: baseNode.component.version,
43
+ status: 'deleted',
44
+ });
45
+ }
46
+ }
47
+
48
+ const newNodes = compareNodes.filter((n) => !baseNodesMap.has(toShortId(n)));
49
+
50
+ for (const node of newNodes) {
51
+ allNodes.push({
52
+ ...node,
53
+ compareVersion: '',
54
+ status: 'new',
55
+ });
56
+ }
57
+ const allNodesMap = new Map<string, CompareNodeModel>(allNodes.map((n) => [toShortId(n), n]));
58
+
59
+ const baseEdgesMap = new Map<string, EdgeModel>(baseGraph.edges.map((baseEdge) => [getEdgeId(baseEdge), baseEdge]));
60
+ const edgesOnlyInCompare = compareGraph.edges
61
+ .filter((compareEdge) => !baseEdgesMap.has(getEdgeId(compareEdge)))
62
+ .map((compareEdge) => ({
63
+ ...compareEdge,
64
+ sourceId: allNodesMap.get(toShortIdFromNodeId(compareEdge.sourceId))?.id.toString() || baseId.toString(),
65
+ targetId: allNodesMap.get(toShortIdFromNodeId(compareEdge.targetId))?.id.toString() || baseId.toString(),
66
+ }));
67
+ const allEdges = [...baseGraph.edges, ...edgesOnlyInCompare];
68
+ return new CompareGraphModel(allNodes, allEdges);
69
+ }
@@ -0,0 +1 @@
1
+ export { DependenciesCompare } from './dependencies-compare';
@@ -1,8 +1,8 @@
1
1
  import { useMemo } from 'react';
2
- import { Node, Edge, ArrowHeadType } from 'react-flow-renderer';
2
+ import { ArrowHeadType, Edge, Node } from 'react-flow-renderer';
3
3
  import { ComponentID } from '@teambit/component';
4
4
  import { calcLayout } from './calc-layout';
5
- import { GraphModel } from '../query';
5
+ import { EdgeModel, GraphModel, NodeModel } from '../query';
6
6
 
7
7
  import { depTypeToClass, depTypeToLabel } from './dep-edge';
8
8
 
@@ -13,7 +13,7 @@ type ElementsOptions = {
13
13
  /**
14
14
  * generate Nodes and Edges for the ReactFlowRenderer graph renderer
15
15
  */
16
- export function calcElements(graph: GraphModel | undefined, { rootNode }: ElementsOptions) {
16
+ export function calcElements(graph: GraphModel<NodeModel, EdgeModel> | undefined, { rootNode }: ElementsOptions) {
17
17
  return useMemo(() => {
18
18
  if (!graph) return [];
19
19
 
@@ -1,5 +1,5 @@
1
1
  import dagre, { graphlib } from 'dagre';
2
- import { GraphModel } from '../query';
2
+ import { EdgeModel, GraphModel, NodeModel } from '../query';
3
3
 
4
4
  const NODE_WIDTH = 260;
5
5
  const NODE_HEIGHT = 90;
@@ -9,7 +9,7 @@ const BOTTOM_TO_TOP = 'BT';
9
9
  /**
10
10
  * calculate the specific location of each node in the graph
11
11
  */
12
- export function calcLayout(graph: GraphModel) {
12
+ export function calcLayout(graph: GraphModel<NodeModel, EdgeModel>) {
13
13
  const g = new graphlib.Graph();
14
14
  g.setGraph({ rankdir: BOTTOM_TO_TOP });
15
15
  g.setDefaultEdgeLabel(() => ({}));
@@ -1,22 +1,22 @@
1
- import React, { useMemo, useCallback, useRef, useEffect } from 'react';
1
+ import React, { useCallback, useEffect, useMemo, useRef } from 'react';
2
2
  import classnames from 'classnames';
3
3
  import ReactFlow, {
4
- ReactFlowProvider,
5
- Controls,
6
4
  Background,
5
+ Controls,
6
+ Handle,
7
7
  MiniMap,
8
- OnLoadParams,
8
+ NodeProps,
9
9
  NodeTypesType,
10
- Handle,
10
+ OnLoadParams,
11
11
  Position,
12
- NodeProps,
13
12
  ReactFlowProps,
13
+ ReactFlowProvider,
14
14
  } from 'react-flow-renderer';
15
15
  import { ComponentID } from '@teambit/component';
16
16
 
17
17
  import { ComponentWidgetSlot } from '../../graph.ui.runtime';
18
18
  import { ComponentNode } from '../component-node';
19
- import { GraphModel } from '../query';
19
+ import { EdgeModel, GraphModel, NodeModel } from '../query';
20
20
  import { calcElements } from './calc-elements';
21
21
  import { calcMinimapColors } from './minimap';
22
22
  import { ComponentGraphContext } from './graph-context';
@@ -40,7 +40,7 @@ const NodeTypes: NodeTypesType = { ComponentNode: ComponentNodeContainer };
40
40
 
41
41
  export type DependenciesGraphProps = {
42
42
  rootNode: ComponentID;
43
- graph: GraphModel;
43
+ graph: GraphModel<NodeModel, EdgeModel>;
44
44
  componentWidgets: ComponentWidgetSlot;
45
45
  onLoad?: (instance: OnLoadParams) => void;
46
46
  } & Omit<ReactFlowProps, 'elements'>;
@@ -1,3 +1,12 @@
1
+ import componentStyles from './dependencies-graph.module.scss';
2
+
1
3
  export { DependenciesGraph } from './dependencies-graph';
2
4
  export { ComponentGraphContext, ComponentGraph } from './graph-context';
3
5
  export type { DependenciesGraphProps } from './dependencies-graph';
6
+ export { depTypeToClass, depTypeToLabel } from './dep-edge';
7
+ export { calcMinimapColors } from './minimap';
8
+ export { calcLayout } from './calc-layout';
9
+ export { calcElements } from './calc-elements';
10
+
11
+ const { graph, minimap, controls } = componentStyles;
12
+ export const styles = { graph, minimap, controls };
@@ -1 +1,7 @@
1
+ import pageStyles from './graph-page.module.scss';
2
+
1
3
  export { GraphPage } from './graph-page';
4
+ export { GraphFilters } from './graph-filters';
5
+
6
+ const { graph, filters } = pageStyles;
7
+ export const styles = { graph, filters };
@@ -2,8 +2,9 @@ import { RawGraph } from './get-graph.query';
2
2
  import { NodeModel } from './node-model';
3
3
  import { EdgeModel } from './edge-model';
4
4
 
5
- export class GraphModel {
6
- constructor(public nodes: NodeModel[], public edges: EdgeModel[]) {}
5
+ export class GraphModel<N extends NodeModel, E extends EdgeModel> {
6
+ constructor(public nodes: N[], public edges: E[]) {}
7
+
7
8
  static from(rawGraph: RawGraph) {
8
9
  const nodes = rawGraph.nodes.map(NodeModel.from);
9
10
  const edges = rawGraph.edges.map(EdgeModel.from);
package/ui/query/index.ts CHANGED
@@ -4,3 +4,4 @@ export { useGraph } from './use-graph';
4
4
  export { GraphModel } from './graph-model';
5
5
  export { EdgeModel } from './edge-model';
6
6
  export { NodeModel } from './node-model';
7
+ export { RawGraph } from './get-graph.query';