40 | }
41 | }
42 |
43 | export default Sample;
44 |
--------------------------------------------------------------------------------
/docs/SelectionPathModeInFamilyChart.md:
--------------------------------------------------------------------------------
1 | # Selection path nodes in Family Diagram
2 |
3 | ## Selected items
4 |
5 | Suppose the total square size of items exceeds the available screen size. There is no possibility to show all of them, and the chart should use various strategies to display essential information. By default family diagram shows `cursorItem` and all its neighbors in full size using templates. The same rule applies to selected items and annotated items. For all other non-selected items, the chart conditionally minimizes them into dots or lines.
6 |
7 | ## Selection path items
8 |
9 | The selection path is nodes between selected items and top row nodes in the layered diagram. The developer can show selection path items in full size with property `selectionPathMode` set to `SelectionPathMode.FullStack` or let the layout manager hide them and show them as dots or lines with `SelectionPathMode.None`.
10 |
11 |
12 | ```JavaScript
13 | import { FamDiagram } from basicprimitivesreact;
14 | import { SelectionPathMode } from basicprimitives;
15 |
16 |
20 | ```
21 |
22 | [React](../src/Samples/SelectionPathModeInFamilyChart.jsx)
23 |
--------------------------------------------------------------------------------
/docs/Labels.md:
--------------------------------------------------------------------------------
1 | # Labels
2 |
3 | ## Minimized items labels
4 | Chart supports rendering labels for minimized dotted items. The following properties on `config` used to control labels rendering:
5 | * `showLabels`
6 | * `labelSize`
7 | * `labelOffset`
8 | * `labelOrientation`
9 | * `labelPlacement`
10 |
11 | User can customize labels per individual item with `ItemConfig` properties:
12 | * `label`
13 | * `showLabel`
14 |
15 | ```JavaScript
16 | import { OrgDiagram } from basicprimitivesreact;
17 | import { Enabled } from basicprimitives;
18 |
31 | ```
32 |
33 | [React](../src/Samples/Labels.jsx)
34 |
35 | ## Adding labels to the item template
36 | If we need to draw labels for visible items, we can add them to templates. The following example demonstrates how to add an extra property "percent" to the item and render it a label over the item connection line.
37 |
38 | [React](../src/Samples/ItemTemplateLabel.jsx)
39 |
--------------------------------------------------------------------------------
/src/Diagrams/Schemas/CalloutAnnotationComponentConfigShape.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import { LineType, PlacementType } from 'basicprimitives';
3 |
4 | const RectShape = PropTypes.shape({
5 | x: PropTypes.number.isRequired,
6 | y: PropTypes.number.isRequired,
7 | width: PropTypes.number.isRequired,
8 | height: PropTypes.number.isRequired
9 | });
10 |
11 | const PointShape = PropTypes.shape({
12 | x: PropTypes.number.isRequired,
13 | y: PropTypes.number.isRequired
14 | });
15 |
16 | const CalloutAnnotationControlConfigShape = PropTypes.shape({
17 | pointerPlacement: PropTypes.oneOf(Object.values(PlacementType)),
18 | position: RectShape,
19 | snapPoint: PointShape,
20 | cornerRadius: PropTypes.oneOfType([
21 | PropTypes.string, // e.g. "10%"
22 | PropTypes.number // in case pixel radius is supported
23 | ]),
24 | offset: PropTypes.number,
25 | opacity: PropTypes.number,
26 | lineWidth: PropTypes.number,
27 | lineType: PropTypes.oneOf(Object.values(LineType)),
28 | pointerWidth: PropTypes.oneOfType([
29 | PropTypes.string, // e.g. "10%"
30 | PropTypes.number // e.g. 10
31 | ]),
32 | borderColor: PropTypes.string,
33 | fillColor: PropTypes.string
34 | });
35 |
36 | export default CalloutAnnotationControlConfigShape;
37 |
--------------------------------------------------------------------------------
/src/Diagrams/index.js:
--------------------------------------------------------------------------------
1 | export { default as OrgDiagram } from './OrgDiagram';
2 | export { default as FamDiagram } from './FamDiagram';
3 |
4 | export { default as RotatedText } from './Templates/RotatedText';
5 |
6 | export { default as BackgroundAnnotationConfigShape } from './Schemas/BackgroundAnnotationConfigShape';
7 | export { default as ConnectorAnnotationConfigShape } from './Schemas/ConnectorAnnotationConfigShape';
8 | export { default as FamConfigShape } from './Schemas/FamConfigShape';
9 | export { default as FamItemConfigShape } from './Schemas/FamItemConfigShape';
10 | export { default as HighlightPathAnnotationConfigShape } from './Schemas/HighlightPathAnnotationConfigShape';
11 | export { default as LabelAnnotationConfigShape } from './Schemas/LabelAnnotationConfigShape';
12 | export { default as OrgConfigShape } from './Schemas/OrgConfigShape';
13 | export { default as OrgItemConfigShape } from './Schemas/OrgItemConfigShape';
14 | export { default as PaletteItemConfigShape } from './Schemas/PaletteItemConfigShape';
15 | export { default as ShapeAnnotationConfigShape } from './Schemas/ShapeAnnotationConfigShape';
16 | export { default as LevelAnnotationConfigShape } from './Schemas/LevelAnnotationConfigShape';
17 | export { default as TemplateConfigShape } from './Schemas/TemplateConfigShape';
18 |
--------------------------------------------------------------------------------
/src/Diagrams/Schemas/ShapeAnnotationConfigShape.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import { AnnotationType, ZOrderType, ShapeType, LineType, PlacementType } from 'basicprimitives';
3 |
4 | const ShapeAnnotationConfigShape = PropTypes.shape({
5 | annotationType: PropTypes.oneOf([AnnotationType.Shape]),
6 | zOrderType: PropTypes.oneOf(Object.values(ZOrderType)),
7 | items: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.string])),
8 | shapeType: PropTypes.oneOf(Object.values(ShapeType)),
9 | offset: PropTypes.shape({
10 | left: PropTypes.number.isRequired,
11 | top: PropTypes.number.isRequired,
12 | right: PropTypes.number.isRequired,
13 | bottom: PropTypes.number.isRequired
14 | }),
15 | lineWidth: PropTypes.number,
16 | cornerRadius: PropTypes.string,
17 | opacity: PropTypes.number,
18 | borderColor: PropTypes.string,
19 | fillColor: PropTypes.string,
20 | lineType: PropTypes.oneOf(Object.values(LineType)),
21 | selectItems: PropTypes.bool,
22 | label: PropTypes.any,
23 | labelSize: PropTypes.shape({
24 | width: PropTypes.number.isRequired,
25 | height: PropTypes.number.isRequired
26 | }),
27 | labelPlacement: PropTypes.oneOf(Object.values(PlacementType)),
28 | labelOffset: PropTypes.number
29 | });
30 |
31 | export default ShapeAnnotationConfigShape;
32 |
--------------------------------------------------------------------------------
/docs/LabelsCascadesInFamilyChart.md:
--------------------------------------------------------------------------------
1 | # Labels cascades over connection lines in family chart
2 | Label annotations are family diagram specific annotations. Label annotations are placed inside the diagram layout between nodes so they don't overlap nodes, can occupy relatively large space. Still, they require the control to rerender nodes when we add label annotations to the diagram.
3 |
4 | Label annotations can bind multiple nodes together, so visually label annotation can define aggregate value for several nodes bundled together. In the following example, we create a cascade of labels from the common parent down to its children. If two labels create mutually exclusive bundles, the first label wins.
5 |
6 | See LabelAnnotationConfig for details. By default, label annotations display regular text labels, but we can use node templates to define their content. So from this perspective, they are regular diagram nodes, having complex placement logic in the diagram. See `templateName` option of `LabelAnnotationConfig` and `defaultLabelAnnotationTemplate` of `FamConfig` class.
7 |
8 | [React](../src/Samples/LabelsCascadesInFamilyChart.jsx)
9 |
10 | # Labels over connection lines in matrix-shaped family chart
11 | The following sample demonstrates how matrix layout places labels around nodes.
12 |
13 | [React](../src/Samples/LabelsNMatrixInFamilyChart.jsx)
--------------------------------------------------------------------------------
/src/Diagrams/Templates/LevelBackgroundTemplate.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import AbstractTemplate from './AbstractTemplate';
3 | import { LineType } from 'basicprimitives';
4 |
5 | function getBorderStyle(lineType) {
6 | var result = null;
7 | switch (lineType) {
8 | case LineType.Dotted:
9 | result = "dotted";
10 | break;
11 | case LineType.Dashed:
12 | result = "dashed";
13 | break;
14 | default:
15 | result = "solid";
16 | break;
17 | }
18 | return result;
19 | }
20 |
21 |
22 | class LevelBackgroundTemplate extends AbstractTemplate {
23 | constructor(options) {
24 | super();
25 |
26 | this.options = options;
27 |
28 | this.render = this.render.bind(this);
29 |
30 | this.style = {
31 | position: "absolute",
32 | width: "100%",
33 | height: "100%"
34 | }
35 | }
36 |
37 | render(data) {
38 | var annotationConfig = data.context;
39 | var style = {
40 | opacity: annotationConfig.opacity,
41 | borderColor: annotationConfig.borderColor,
42 | backgroundColor: annotationConfig.fillColor,
43 | borderWidth: annotationConfig.lineWidth.toString(),
44 | borderStyle: getBorderStyle(annotationConfig.lineType),
45 | ...this.style
46 | }
47 | return ;
48 | }
49 | };
50 |
51 | export default LevelBackgroundTemplate;
--------------------------------------------------------------------------------
/docs/MultipleRootItemsInChart.md:
--------------------------------------------------------------------------------
1 | # Multiple root items in the chart
2 |
3 | Multiple root items are convenient to display tree structure having missing parent relations for some nodes. The component would render such hierarchy using multiple tree fragments placed side by side in the diagram.
4 |
5 | Following example shows two disconnected hierarchies:
6 |
7 | [React](../src/Samples/MultipleRootItemsInChart.jsx)
8 |
9 | ## Matrix layout of multiple root items
10 | It is an extreme example when nodes don't have parent relations at all. So the control displays them in the form of a long horizontal list of nodes. It isn't easy to scroll and arrange them. The suggested solution is to shape root items into the matrixed formation, so our fragments take less space and fit into the available screen space.
11 | The matrixed formation works best when we use drag and drop to merge nodes back to the tree structure, so we need to place our nodes close to each other.
12 | In the following example, we create an invisible root item and use it as a parent node for all our parentless nodes in the structure. Then we set its `childrenPlacementType` option to `ChildrenPlacementType.Matrix`, so our nine nodes form compact 3 * 3 matrix formation.
13 |
14 |
15 | See Children Layout example to place fragments vertically or horizontally.
16 |
17 | [React](../src/Samples/MatrixLayoutOfMultipleRootItemsInChart.jsx)
--------------------------------------------------------------------------------
/docs/LevelAnnotation.md:
--------------------------------------------------------------------------------
1 | # Level Annotations
2 |
3 | Basic Primitives Diagrams render layered hierarchies and dependency diagrams. Level annotation decorates the level of nodes with title and background stripe drawn across the diagram's whole level. The title is placed outside the diagram's view area and occupies screen space. Optionally you can place level annotation titles inside the diagram's view area in the background.
4 |
5 | Level Annotations reference logical levels of the diagram. The first node placed into the logical level defines the level index. So if you have manager nodes vertically aligned under their CEO, you will have multiple managerial level annotations alternating with direct reports level annotations. See vertical organizational chart demo application.
6 | The node's children types and layout options change the number of visual levels in the hierarchy; use the `alignBranches` option to align children having the same logical level at one visual level.
7 |
8 | [React](../src/Samples/LevelAnnotation.jsx)
9 |
10 | # Templates
11 |
12 | Use the following options to modify level annotation default content and mouse events:
13 |
14 | * `onLevelTitleRender` - callback function to render level title
15 | * `onLevelBackgroundRender` - callback function to render level background
16 |
17 | Click on the level annotation title to see a popup message.
18 |
19 | [React](../src/Samples/LevelAnnotationTemplate.jsx)
--------------------------------------------------------------------------------
/src/Diagrams/Templates/HighlightTemplate.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import AbstractTemplate from './AbstractTemplate';
3 |
4 | class HighlightTemplate extends AbstractTemplate {
5 | constructor(options, config) {
6 | super();
7 |
8 | this.options = options;
9 | this.config = config;
10 |
11 | this.render = this.render.bind(this);
12 |
13 | this.style = {
14 | position: "absolute",
15 | fontFamily: "Trebuchet MS, Tahoma, Verdana, Arial, sans-serif",
16 | WebkitTapHighlightColor: "rgba(0,0,0,0)",
17 | WebkitUserSelect: "none",
18 | WebkitTouchCallout: "none",
19 | KhtmlUserSelect: "none",
20 | MozUserSelect: "none",
21 | msUserSelect: "none",
22 | userSelect: "none",
23 | boxSizing: "content-box",
24 |
25 | MozBorderRadius: "4px",
26 | WebkitBorderRadius: "4px",
27 | KhtmlBorderRadius: "4px",
28 | BorderRadius: "4px",
29 |
30 | border: "1px solid #fbcb09",
31 | background: "#fdf5ce",
32 | color: "#c77405",
33 |
34 | width: "100%",
35 | height: "100%",
36 | left: "-1px",
37 | top: "-1px"
38 | }
39 | }
40 |
41 | render(data) {
42 | const { highlightBorderWidth } = this.config;
43 | return ;
47 | }
48 | };
49 |
50 | export default HighlightTemplate;
--------------------------------------------------------------------------------
/docs/ShapeAndBackgroundAnnotations.md:
--------------------------------------------------------------------------------
1 | # Shape & Background Annotations
2 | ## Shape
3 | Diagrams support on-screen annotations for visualization of non - hierarchical relations between nodes. Components use SVG elements to render geometrical figures depending on user options. If you need some specific custom shapes, you have to make changes to the source code or use images and custom items templates. Shape annotation supports the following figures:
4 | * Rounded Rectangle
5 | * Oval
6 | * Triangle
7 | * Cross Out
8 | * Circle
9 | * Rhombus
10 |
11 | If you define multiple nodes, then annotation draws one large shape on top of them. If you need numerous individual figures for a list of nodes, you have to create shape annotation for every node. If you don't define background or borderline color, then they are not drawn. Annotation can render a text label on the side of the geometrical figure.
12 |
13 | ## Background Annotation
14 | This visual is a common background area having borderline and fill color. When we render the same background annotation for multiple items, control automatically blends them into a single continuous shape. Increase background offset around nodes if they don't merge. Merging annotations improves visualization and minimizes visual clutter in the diagram. Use `includeChildren` option to expand the background around the item down to all of its descendants.
15 |
16 | [React](../src/Samples/ShapeAnnotation.jsx)
17 |
--------------------------------------------------------------------------------
/docs/ItemAndGroupTitleColors.md:
--------------------------------------------------------------------------------
1 | # Item & group title colors
2 |
3 | Item's title background color may be used for indicating the group of nodes in the diagram and may vary in a wide range of colors. At the same time, the title font color should always be readable on every background. So taking these considerations into account, the control has two options setting font color for node titles: `itemTitleFirstFontColor` and `itemTitleSecondFontColor`. The control selects the most readable font color using the `highestContrast` function. It returns the highest contrast color from two on the given background color.
4 |
5 | See reference for group title size, placement, and orientation.
6 |
7 | ```JavaScript
8 | import { OrgDiagram } from basicprimitivesreact;
9 | import { Enabled, Colors, TextOrientationType } from basicprimitives;
10 |
28 | ```
29 |
30 | [React](../src/Samples/ItemAndGroupTitleColors.jsx)
31 |
--------------------------------------------------------------------------------
/src/Diagrams/Templates/EndPointTemplate.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import AbstractTemplate from './AbstractTemplate';
3 |
4 | class EndPointTemplate extends AbstractTemplate {
5 | constructor(options) {
6 | super();
7 | this.render = this.render.bind(this);
8 |
9 | this.options = options;
10 |
11 | this.style = {
12 | position: "absolute",
13 | fontFamily: "Trebuchet MS, Tahoma, Verdana, Arial, sans-serif",
14 | WebkitTapHighlightColor: "rgba(0,0,0,0)",
15 | WebkitUserSelect: "none",
16 | WebkitTouchCallout: "none",
17 | KhtmlUserSelect: "none",
18 | MozUserSelect: "none",
19 | msUserSelect: "none",
20 | userSelect: "none",
21 | boxSizing: "content-box",
22 |
23 | borderWidth: "0px",
24 | width: "100%",
25 | height: "100%",
26 | left: "0px",
27 | top: "0px"
28 | }
29 | }
30 |
31 | render(data) {
32 | const { endPointCornerRadius, endPointFillColor, endPointOpacity } = this.options;
33 |
34 | const style = {
35 | ...this.style,
36 | MozBorderRadius: endPointCornerRadius + "px",
37 | WebkitBorderRadius: endPointCornerRadius + "px",
38 | KhtmlBorderRadius: endPointCornerRadius + "px",
39 | borderRadius: endPointCornerRadius + "px",
40 | background: endPointFillColor,
41 | opacity: endPointOpacity
42 | }
43 | return ;
44 | }
45 | };
46 |
47 | export default EndPointTemplate;
--------------------------------------------------------------------------------
/src/Diagrams/Schemas/RotatedTextComponentConfigShape.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import {
3 | VerticalAlignmentType,
4 | TextOrientationType,
5 | HorizontalAlignmentType
6 | } from 'basicprimitives'; // Adjust this import path as needed
7 |
8 | const RotatedTextControlConfigShape = PropTypes.shape({
9 | /**
10 | * Label orientation.
11 | */
12 | orientation: PropTypes.oneOf(Object.values(TextOrientationType)),
13 |
14 | /**
15 | * The text content to display.
16 | */
17 | text: PropTypes.string,
18 |
19 | /**
20 | * Label vertical alignment inside bounding rectangle.
21 | */
22 | verticalAlignment: PropTypes.oneOf(Object.values(VerticalAlignmentType)),
23 |
24 | /**
25 | * Label horizontal alignment inside bounding rectangle.
26 | */
27 | horizontalAlignment: PropTypes.oneOf(Object.values(HorizontalAlignmentType)),
28 |
29 | /**
30 | * Font size (e.g., "16px")
31 | */
32 | fontSize: PropTypes.string,
33 |
34 | /**
35 | * Font family (e.g., "Arial")
36 | */
37 | fontFamily: PropTypes.string,
38 |
39 | /**
40 | * Font color (e.g., Colors.Black)
41 | */
42 | color: PropTypes.string,
43 |
44 | /**
45 | * Font weight (e.g., "normal", "bold")
46 | */
47 | fontWeight: PropTypes.oneOf(['normal', 'bold']),
48 |
49 | /**
50 | * Font style (e.g., "normal", "italic")
51 | */
52 | fontStyle: PropTypes.oneOf(['normal', 'italic'])
53 | });
54 |
55 | export default RotatedTextControlConfigShape;
56 |
--------------------------------------------------------------------------------
/docs/SelectionPathMode.md:
--------------------------------------------------------------------------------
1 | # Selection path nodes in Organizational Chart
2 | Suppose the total square size of items exceeds the available screen size. There is no possibility to show all of them, and the chart should use various strategies to display the essential information. By default organizational chart shows the current cursor item and all its children and parents up to the root of the hierarchy. The same rule applies to the list of selected items. All other less essential nodes, chart is allowed to display in the form of markers and lines.
3 |
4 | The selection path is a collection of parents between any node and the root of the hierarchy. The control can show the selection path for the current cursor node and selected nodes as well. If you need to show selection path nodes, set the option `selectionPathMode` to `SelectionPathMode.FullStack` or hide them to markers with `SelectionPathMode.None` option.
5 |
6 | ```JavaScript
7 | import { OrgDiagram } from basicprimitivesreact;
8 | import { SelectionPathMode } from basicprimitives;
9 |
13 | ```
14 |
15 | When we need to compare two or three selected items in the organizational chart, it is essential to show their selection paths. It gives you context for nodes comparison: immediate managers, departments, and relative levels in the organization. In the case of many selected items, it is better to hide selection paths to save valuable space and fit the chart into the screen.
16 |
17 | [React](../src/Samples/SelectionPathMode.jsx)
18 |
--------------------------------------------------------------------------------
/docs/ZoomWithItemTemplate.md:
--------------------------------------------------------------------------------
1 | # Zoom using Item template
2 | When we scale our diagram, the primary objective is to enlarge or downsize nodes to fit the chart into available screen space and overview its layout.
3 |
4 | We design our components primarily for business applications, where usability requirements constrain text size. If the text is too small and unreadable, it is a UI bug. When we design our nodes templates for various zoom levels, we can change their size, but we have to keep minimal font size unchanged, so nodes become small and contain less text. The same happens when we increase nodes in size, we don't increase fonts endlessly. It is not needed. Instead, we pack more content into the template, so our nodes become more informative.
5 |
6 | Usage of custom node templates for various scales guarantees that users see node content, regardless of the zoom level. You design, tune and test templates for every zoom level individually.
7 |
8 | You protect yourself against UX support tickets caused by misuse of the zoom. Users may accidentally scroll the mouse over the diagram and zoom it out into a meaningless graphics element. The user would not comprehend that it is the diagram on the screen anymore.
9 |
10 | Scaling diagrams with custom templates is very similar to developing responsive web applications for desktop and mobile. The screen space is so different that desktop application is not readable on mobile phone screen without adjustments.
11 |
12 | See item template use case for more details about templates usage.
13 |
14 | [React](../src/Samples/ZoomWithItemTemplate.jsx)
15 |
--------------------------------------------------------------------------------
/src/Diagrams/Schemas/ConnectorAnnotationConfigShape.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import { ConnectorLabelPlacementType, ConnectorPlacementType,
3 | ConnectorShapeType, ZOrderType, AnnotationType, LineType, Enabled } from 'basicprimitives';
4 |
5 | const ConnectorAnnotationConfigShape = PropTypes.shape({
6 | annotationType: PropTypes.oneOf([AnnotationType.Connector]),
7 | zOrderType: PropTypes.oneOf(Object.values(ZOrderType)),
8 | fromItem: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
9 | toItem: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
10 | connectorShapeType: PropTypes.oneOf(Object.values(ConnectorShapeType)),
11 | connectorPlacementType: PropTypes.oneOf(Object.values(ConnectorPlacementType)),
12 | labelPlacementType: PropTypes.oneOf(Object.values(ConnectorLabelPlacementType)),
13 | offset: PropTypes.oneOfType([
14 | PropTypes.number,
15 | PropTypes.shape({
16 | left: PropTypes.number.isRequired,
17 | top: PropTypes.number.isRequired,
18 | right: PropTypes.number.isRequired,
19 | bottom: PropTypes.number.isRequired
20 | })
21 | ]),
22 | lineWidth: PropTypes.number,
23 | color: PropTypes.string,
24 | lineType: PropTypes.oneOf(Object.values(LineType)),
25 | selectItems: PropTypes.bool,
26 | label: PropTypes.any,
27 | labelSize: PropTypes.shape({
28 | width: PropTypes.number.isRequired,
29 | height: PropTypes.number.isRequired
30 | }),
31 | showFromEndpoint: PropTypes.oneOf(Object.values(Enabled)),
32 | showToEndpoint: PropTypes.oneOf(Object.values(Enabled)),
33 | context: PropTypes.any
34 | });
35 |
36 | export default ConnectorAnnotationConfigShape;
37 |
--------------------------------------------------------------------------------
/src/Diagrams/Templates/CursorTemplate.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import AbstractTemplate from './AbstractTemplate';
3 |
4 | class CursorTemplate extends AbstractTemplate {
5 | constructor(options, itemTemplateConfig) {
6 | super();
7 |
8 | this.options = options;
9 | this.itemTemplateConfig = itemTemplateConfig;
10 |
11 | this.render = this.render.bind(this);
12 |
13 | this.style = {
14 | position: "absolute",
15 | fontFamily: "Trebuchet MS, Tahoma, Verdana, Arial, sans-serif",
16 | WebkitTapHighlightColor: "rgba(0,0,0,0)",
17 | WebkitUserSelect: "none",
18 | WebkitTouchCallout: "none",
19 | KhtmlUserSelect: "none",
20 | MozUserSelect: "none",
21 | msUserSelect: "none",
22 | userSelect: "none",
23 | boxSizing: "content-box",
24 |
25 | MozBorderRadius: "4px",
26 | WebkitBorderRadius: "4px",
27 | KhtmlBorderRadius: "4px",
28 | BorderRadius: "4px",
29 |
30 | border: "2px solid #fbd850",
31 | background: "#ffffff",
32 | color: "#eb8f00",
33 |
34 | width: "100%",
35 | height: "100%",
36 | left: "-2px",
37 | top: "-2px"
38 | }
39 | }
40 |
41 | render(data) {
42 | const { cursorPadding, itemSize, cursorBorderWidth } = this.itemTemplateConfig;
43 | const style = {
44 | ...this.style,
45 | width: (itemSize.width + cursorPadding.left + cursorPadding.right) + "px",
46 | height: (itemSize.height + cursorPadding.top + cursorPadding.bottom) + "px",
47 | borderWidth: cursorBorderWidth + "px"
48 | }
49 | return ;
50 | }
51 | };
52 |
53 | export default CursorTemplate;
--------------------------------------------------------------------------------
/src/Diagrams/Schemas/ConnectorAnnotationComponentConfigShape.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import {
3 | OrientationType,
4 | ConnectorPlacementType,
5 | ConnectorShapeType,
6 | ConnectorLabelPlacementType,
7 | LineType
8 | } from 'basicprimitives';
9 |
10 | const RectShape = PropTypes.shape({
11 | x: PropTypes.number.isRequired,
12 | y: PropTypes.number.isRequired,
13 | width: PropTypes.number.isRequired,
14 | height: PropTypes.number.isRequired
15 | });
16 |
17 | const ThicknessShape = PropTypes.shape({
18 | left: PropTypes.number.isRequired,
19 | top: PropTypes.number.isRequired,
20 | right: PropTypes.number.isRequired,
21 | bottom: PropTypes.number.isRequired
22 | });
23 |
24 | const SizeShape = PropTypes.shape({
25 | width: PropTypes.number.isRequired,
26 | height: PropTypes.number.isRequired
27 | });
28 |
29 | const ConnectorAnnotationControlConfigShape = PropTypes.shape({
30 | orientationType: PropTypes.oneOf(Object.values(OrientationType)),
31 | connectorPlacementType: PropTypes.oneOf(Object.values(ConnectorPlacementType)),
32 | connectorShapeType: PropTypes.oneOf(Object.values(ConnectorShapeType)),
33 | fromRectangle: RectShape,
34 | toRectangle: RectShape,
35 | offset: ThicknessShape,
36 | lineWidth: PropTypes.number,
37 | color: PropTypes.string,
38 | lineType: PropTypes.oneOf(Object.values(LineType)),
39 | label:PropTypes.oneOfType([
40 | PropTypes.string,
41 | PropTypes.object
42 | ]),
43 | labelSize: SizeShape,
44 | labelOffset: PropTypes.number,
45 | labelPlacementType: PropTypes.oneOf(Object.values(ConnectorLabelPlacementType))
46 | });
47 |
48 | export default ConnectorAnnotationControlConfigShape;
--------------------------------------------------------------------------------
/src/Diagrams/Schemas/TemplateConfigShape.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import { ShapeType, LineType } from 'basicprimitives';
3 |
4 | const TemplateConfigShape = PropTypes.shape({
5 | name: PropTypes.string,
6 | isActive: PropTypes.bool,
7 | itemSize: PropTypes.shape({
8 | width: PropTypes.number.isRequired,
9 | height: PropTypes.number.isRequired
10 | }),
11 | itemBorderWidth: PropTypes.number,
12 | onItemRender: PropTypes.func,
13 | minimizedItemShapeType: PropTypes.oneOf(Object.values(ShapeType)),
14 | minimizedItemSize: PropTypes.shape({
15 | width: PropTypes.number.isRequired,
16 | height: PropTypes.number.isRequired
17 | }),
18 | minimizedItemCornerRadius: PropTypes.number,
19 | minimizedItemLineWidth: PropTypes.number,
20 | minimizedItemBorderColor: PropTypes.string,
21 | minimizedItemLineType: PropTypes.oneOf(Object.values(LineType)),
22 | minimizedItemFillColor: PropTypes.string,
23 | minimizedItemOpacity: PropTypes.number,
24 | highlightPadding: PropTypes.shape({
25 | left: PropTypes.number.isRequired,
26 | top: PropTypes.number.isRequired,
27 | right: PropTypes.number.isRequired,
28 | bottom: PropTypes.number.isRequired
29 | }),
30 | highlightBorderWidth: PropTypes.number,
31 | onHighlightRender: PropTypes.func,
32 | cursorPadding: PropTypes.shape({
33 | left: PropTypes.number.isRequired,
34 | top: PropTypes.number.isRequired,
35 | right: PropTypes.number.isRequired,
36 | bottom: PropTypes.number.isRequired
37 | }),
38 | cursorBorderWidth: PropTypes.number,
39 | onCursorRender: PropTypes.func,
40 | onButtonsRender: PropTypes.func
41 | });
42 |
43 | export default TemplateConfigShape;
44 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
22 | React App
23 |
24 |
25 |
26 |
27 |
28 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/App.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import SamplesList from './SamplesList';
3 | import './global.css';
4 |
5 |
6 | class App extends Component {
7 | constructor(props) {
8 | super(props);
9 |
10 | this.onChange = this.onChange.bind(this);
11 |
12 | let key = 1;
13 | this.hash = SamplesList.reduce((agg, group) => {
14 | group.key = key;
15 | key += 1;
16 | group.items.reduce((agg, item) => {
17 | item.key = key;
18 | key += 1;
19 | agg[item.key] = item;
20 | return agg;
21 | }, agg)
22 | return agg;
23 | }, {});
24 |
25 | this.state = {
26 | activeItem: (SamplesList[0].items[0])
27 | };
28 | }
29 |
30 | onChange({ target }) {
31 | const { activeItem } = this.state;
32 | const newItem = this.hash[target.value];
33 | if (activeItem.key !== newItem.key) {
34 | this.setState({
35 | activeItem: newItem
36 | });
37 | }
38 | }
39 |
40 | render() {
41 | const { activeItem } = this.state;
42 | return (
43 |
55 | }
56 | }
57 |
58 | export default Sample;
59 |
--------------------------------------------------------------------------------
/docs/HighlightTemplate.md:
--------------------------------------------------------------------------------
1 | # Highlight template
2 | The diagram component provides built-in support of mouse over visual feedback over nodes. Minimized nodes have no HTML content, so the only way to create highlight is to have a custom HTML element dedicated to the mouse over visual feedback.
3 | The default highlight template is `div`, having a solid `1px` borderline around.
4 |
5 | ## Properties:
6 | The component customizes the visual representation of items with `templates`. Every template has customization properties for item content, cursor, and highlight visualizations. By default, if properties are nulls, then the component uses built-in default functionality. The following properties customize highlight template:
7 | * `highlightPadding` - reserves space around item, for example: `{left: 3, top: 3, right: 50, bottom: 3}` will provide extra 50 pixel on right side of item for highlight content.
8 | * `highlightBorderWidth` is a legacy property. We use it to align highlight position around item properly.
9 | * `onHighlightRender` - callback method to render highlight content for given item of diagram
10 |
11 | See the Item template for more details.
12 |
13 | ```JavaScript
14 | import { OrgDiagram } from basicprimitivesreact;
15 | {
22 | return ;
23 | }
24 | }]
25 | }
26 | />
27 | ```
28 |
29 | ## Custom highlight template border
30 | The following example demonstrates how to create a custom highlight border having item dependent color and tag element.
31 |
32 | [React](../src/Samples/HighlightTemplate.jsx)
--------------------------------------------------------------------------------
/src/Diagrams/Templates/DotHighlightTemplate.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import AbstractTemplate from './AbstractTemplate';
3 |
4 | class DotHighlightTemplate extends AbstractTemplate {
5 | constructor(options, itemTemplateConfig) {
6 | super();
7 | this.render = this.render.bind(this);
8 |
9 | this.config = itemTemplateConfig;
10 |
11 | this.style = {
12 | position: "absolute",
13 | fontFamily: "Trebuchet MS, Tahoma, Verdana, Arial, sans-serif",
14 | WebkitTapHighlightColor: "rgba(0,0,0,0)",
15 | WebkitUserSelect: "none",
16 | WebkitTouchCallout: "none",
17 | KhtmlUserSelect: "none",
18 | MozUserSelect: "none",
19 | msUserSelect: "none",
20 | userSelect: "none",
21 | boxSizing: "content-box",
22 |
23 | border: "1px solid #fbcb09",
24 | background: "#fdf5ce",
25 | color: "#c77405",
26 | width: "100%",
27 | height: "100%",
28 | left: "0px",
29 | top: "0px"
30 | }
31 | }
32 |
33 | render(data) {
34 | const { minimizedItemCornerRadius, highlightPadding, highlightBorderWidth, minimizedItemSize } = this.config;
35 | let radius = 0;
36 | if (minimizedItemCornerRadius === null) {
37 | radius = Math.max(minimizedItemSize.width / 2, minimizedItemSize.height / 2) + highlightPadding.left;
38 | } else {
39 | radius = minimizedItemCornerRadius + highlightPadding.left;
40 | }
41 | const style = {
42 | ...this.style,
43 | borderWidth: highlightBorderWidth + "px",
44 | left: - highlightBorderWidth + "px",
45 | top: - highlightBorderWidth + "px",
46 | MozBorderRadius: radius + "px",
47 | WebkitBorderRadius: radius + "px",
48 | KhtmlBorderRadius: radius + "px",
49 | borderRadius: radius + "px"
50 | }
51 | return ;
52 | }
53 | };
54 |
55 | export default DotHighlightTemplate;
--------------------------------------------------------------------------------
/docs/SelectedItems.md:
--------------------------------------------------------------------------------
1 | # Selected items & Checkboxes
2 | Selected items property is the standard UI control option for multi-select of items in collection control. The selected items property is a collection of item ids:
3 |
4 | ```JavaScript
5 | import { OrgDiagram } from basicprimitivesreact;
6 |
10 | ```
11 |
12 | The control displays selected items with checked checkboxes and in the full-size form. So this can be convenient for navigation. Users can browse diagram and checkmark nodes, so they stay pinned and visible.
13 |
14 | Use selected items property when you need to display cross-functional working groups in the organization hierarchy or visualize extensive mail recipients list in the organization by groups and seniority. Usually, when the number of people exceeds ten, it is hard to say who is in the subscription except for active participants.
15 |
16 | Collection of `OrgConfig.selectedItems` contains item id's. The control notifies about changes in this collection with `OrgConfig.onSelectionChanged` event.
17 |
18 | The following example demonstrates how to programmatically select items in the organizational chart and be notified about selection changes.
19 |
20 | [React](../src/Samples/SelectedItems.jsx)
21 |
22 | # Showing selected items on the frame
23 |
24 | The control displays selected items invisible in the current viewport on the control's frame as markers. The control uses the same marker properties defined by item templates for markers in the diagram. Marker's placement on the frame indicates the direction towards the selected item outside the control view area. The frame takes as much space as the largest marker in the diagram. Use `fameInnerPadding` and `frameOuterPadding` configuration properties to add extra padding around frame markers.
25 |
26 | [React](../src/Samples/ShowFrame.jsx)
--------------------------------------------------------------------------------
/src/Samples/SkippedLevels.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { OrgDiagram } from '../Diagrams';
3 | import { PageFitMode, Enabled } from 'basicprimitives';
4 |
5 | class Sample extends Component {
6 | render() {
7 | const config = {
8 | pageFitMode: PageFitMode.None,
9 | cursorItem: 0,
10 | hasSelectorCheckbox: Enabled.True,
11 | items: [
12 | {
13 | id: 0,
14 | parent: null,
15 | title: "James Smith",
16 | description: "VP, Public Sector",
17 | image: "./photos/a.png"
18 | },
19 | {
20 | id: 1,
21 | parent: 0,
22 | title: "Ted Lucas",
23 | description: "VP, Human Resources",
24 | image: "./photos/b.png"
25 | },
26 | {
27 | id: 4,
28 | parent: 1,
29 | title: "Ted Lucas 2",
30 | description: "VP, Human Resources",
31 | image: "./photos/b.png"
32 | },
33 | {
34 | id: 5,
35 | parent: 1,
36 | title: "Ted Lucas 3",
37 | description: "VP, Human Resources",
38 | image: "./photos/b.png"
39 | },
40 | { id: 2, parent: 0, isVisible: false },
41 | {
42 | id: 3,
43 | parent: 2,
44 | title: "Fritz Stuger",
45 | description: "Business Solutions, US",
46 | image: "./photos/c.png"
47 | },
48 | { id: 6, parent: null, isVisible: false },
49 | { id: 7, parent: 6, isVisible: false },
50 | {
51 | id: 8,
52 | parent: 7,
53 | title: "Fritz Stuger 2",
54 | description: "Business Solutions, US",
55 | image: "./photos/c.png"
56 | }
57 | ]
58 | };
59 |
60 | return
61 |
62 |
63 | }
64 | }
65 |
66 | export default Sample;
67 |
--------------------------------------------------------------------------------
/docs/FamilyChartItemsOrdering.md:
--------------------------------------------------------------------------------
1 | # Family Items Ordering
2 | The family diagram supports multiple parents and children per node, so there is no way to define groups of items and their order in the group. The family diagram provides API options helping to guide the layout engine to order nodes. That means if items expected to be in one layout group, then the developer can use the following properties to guide the layout engine about user preferred relative order of items:
3 |
4 | * `relativeItem` - item position and placement type defined relative to the node referenced by this property
5 | * `placementType` - this property defines placement on the left or right side of the relative item. The property has the following values:
6 | * `AdviserPlacementType.Left`
7 | * `AdviserPlacementType.Right`
8 | * `position` - if several items reference the same relative item and relative offset, then this property defines the order of them.
9 |
10 | If the item has no relative node defined, then the layout engine will try to find optimal placement based on its relations.
11 |
12 | Please, pay attention that control ignores looped references between nodes, so it is the developer's responsibility to avoid them.
13 |
14 | ## Family Items Ordering Sample
15 |
16 | [React](../src/Samples/FamilyChartItemsOrdering.jsx)
17 |
18 | ## Multiple Families Ordering Sample
19 |
20 | [React](../src/Samples/MultipleFamiliesOrdering.jsx)
21 |
22 | ## Primary Parent
23 |
24 | If a node has multiple parents and belongs to distant branches of the diagram, then the `primaryParent` property can give higher priority to one of them. So the control would place the node to the hierarchy of that primary parent.
25 |
26 | * `primaryParent` - defines the primary parent of the node. The control would place the node into the hierarchy of the primary node. If there is no parent found, then the layout engine will ignore it.
27 |
28 | [React](../src/Samples/FamilyChartPrimaryParent.jsx)
--------------------------------------------------------------------------------
/docs/InactiveItems.md:
--------------------------------------------------------------------------------
1 | # Inactive family items
2 | Inactive items are regular items excluded from the navigation. End-user cannot click on them and move the cursor to them. In the auto fit mode, selecting the neighboring node next to the inactive item makes all nodes of the inactive item visible. The inactive items play a role in layout annotations having no user interaction and templated with HTML the same way as other diagram nodes. For example, we can add titles into family diagram layout to separate groups of nodes. We can add inactive terminator items indicating that the diagram would load extra nodes into the structure upon reaching them.
3 |
4 | Control provides two ways to make nodes inactive. The first one is to set the `isActive` property of the node to false. The other one is more generic. It is where we make all nodes having some particular template inactive. An adequately structured application should have some item templates, so making stationery items with template options is the most appropriate.
5 |
6 | See following configuration classes:
7 |
8 | * `FamItemConfig`
9 | * `TemplateConfig`
10 |
11 | They have the following option:
12 |
13 | * `isActive` - Setting it to false makes items inactive in diagram layout, so they become irresponsive to mouse and keyboard navigation events.
14 |
15 | If you need to disable controls interactivity, it provides global scope options to disable mouse highlights and cursor navigation.
16 |
17 | ```JavaScript
18 | import { OrgDiagram } from basicprimitivesreact;
19 |
36 | ```
37 |
38 | [React](../src/Samples/InactiveItems.jsx)
39 |
--------------------------------------------------------------------------------
/src/Samples/LimitedPartnerItemType.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { OrgDiagram } from '../Diagrams';
3 | import { PageFitMode, GroupByType, Enabled, ItemType, AdviserPlacementType } from 'basicprimitives';
4 |
5 | class Sample extends Component {
6 | render() {
7 | const config = {
8 | pageFitMode: PageFitMode.None,
9 | cursorItem: 0,
10 | highlightItem: 0,
11 | arrowsDirection: GroupByType.Parents,
12 | hasSelectorCheckbox: Enabled.True,
13 | items: [
14 | {
15 | id: 0,
16 | parent: null,
17 | title: "James Smith",
18 | description: "VP, Public Sector",
19 | image: "./photos/a.png"
20 | },
21 | {
22 | id: 1,
23 | parent: 0,
24 | title: "Robert Canon",
25 | description: "General Partner",
26 | image: "./photos/z.png",
27 | itemType: ItemType.LimitedPartner,
28 | adviserPlacementType: AdviserPlacementType.Right,
29 | groupTitle: "Partner"
30 | },
31 | {
32 | id: 2,
33 | parent: 0,
34 | title: "Ted Lucas",
35 | description: "VP, Human Resources",
36 | image: "./photos/b.png"
37 | },
38 | {
39 | id: 3,
40 | parent: 2,
41 | title: "Fritz Stuger",
42 | description: "General Partner item",
43 | image: "./photos/z.png",
44 | itemType: ItemType.LimitedPartner,
45 | adviserPlacementType: AdviserPlacementType.Right,
46 | groupTitle: "Partner"
47 | },
48 | {
49 | id: 4,
50 | parent: 2,
51 | title: "Ted Lucas 2",
52 | description: "VP, Human Resources",
53 | image: "./photos/b.png"
54 | }
55 | ]
56 | };
57 |
58 | return
46 | }
47 | }
48 |
49 | export default Sample;
50 |
--------------------------------------------------------------------------------
/docs/InactiveFamilyItems.md:
--------------------------------------------------------------------------------
1 | # Inactive family items
2 | Inactive items are regular items excluded from the navigation. End-user cannot click on them and move the cursor to them. In the auto fit mode, selecting the neighboring node next to the inactive item makes all nodes of the inactive item visible. The inactive items play a role in layout annotations having no user interaction and templated with HTML the same way as other diagram nodes. For example, we can add titles into family diagram layout to separate groups of nodes. We can add inactive terminator items indicating that the diagram would load extra nodes into the structure upon reaching them.
3 |
4 | Control provides two ways to make nodes inactive. The first one is to set the `isActive` property of the node to false. The other one is more generic. It is where we make all nodes having some particular template inactive. An adequately structured application should have some item templates, so making stationery items with template options is the most appropriate.
5 |
6 | See following configuration classes:
7 |
8 | * `FamItemConfig`
9 | * `TemplateConfig`
10 |
11 | They have the following option:
12 |
13 | * `isActive` - Setting it to false makes items inactive in diagram layout, so they become irresponsive to mouse and keyboard navigation events.
14 |
15 | If you need to disable controls interactivity, it provides global scope options to disable mouse highlights and cursor navigation.
16 |
17 | ```JavaScript
18 | import { FamDiagram } from basicprimitivesreact;
19 |
36 | ```
37 |
38 | [React](../src/Samples/InactiveFamilyItems.jsx)
39 |
--------------------------------------------------------------------------------
/docs/HighlightPathAnnotation.md:
--------------------------------------------------------------------------------
1 | # Highlight Path Annotation
2 |
3 | Highlight Path annotation highlights connections between a group of items in the hierarchy with distinct line properties. The highlight path annotation supports only one type of highlighting, use the following configuration object properties to style it: `highlightLinesColor`, `highlightLinesWidth`, `highlightLinesType`.
4 |
5 | See family diagram and organizational chart partners demos for more use usage scenarios.
6 |
7 | ```JavaScript
8 | import { OrgDiagram } from basicprimitivesreact;
9 | import { LineType, Colors } from basicprimitives;
10 |
16 | ```
17 | [React](../src/Samples/HighlightPathAnnotation.jsx)
18 |
19 | ## PERT - Program evaluation and review technique chart & Critical Path Visualization
20 | PERT chart critical path visualization with Highlight Path Annotation. The chart does not provide any means to find a critical path. It is the developer's responsibility to trace items and visualize critical path with Highlight Path Annotation. The application should sequence the Critical path nodes and set them in the annotation.
21 |
22 | [React](../src/Samples/PERTChart.jsx)
23 |
24 | ## Routing Highlight Path Annotation for hidden grandparents connections
25 |
26 | The connection lines are hard to trace on the screen visually. They make sense for traditional paper form diagrams visualization when we have no interactivity. But they bring no value for interactive applications, so the main point is to remove redundant connection lines giving no visual value and replace them with dynamic highlight path annotations and custom node templates for compensation.
27 |
28 | ```JavaScript
29 | import { FamDiagram } from basicprimitivesreact;
30 |
34 | ```
35 |
36 | [React](../src/Samples/FamilyHideGrandParentsConnections.jsx)
--------------------------------------------------------------------------------
/src/Samples/ButtonsPanel.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
3 | import { faCoffee, faSitemap } from '@fortawesome/free-solid-svg-icons'
4 | import { OrgDiagram } from '../Diagrams';
5 | import { Enabled } from 'basicprimitives';
6 |
7 | class Sample extends Component {
8 | render() {
9 | const config = {
10 | cursorItem: 0,
11 | highlightItem: 0,
12 | items: [
13 | {
14 | id: 0,
15 | parent: null,
16 | title: "James Smith",
17 | description: "VP, Public Sector",
18 | image: "./photos/a.png"
19 | },
20 | {
21 | id: 1,
22 | parent: 0,
23 | title: "Ted Lucas",
24 | description: "VP, Human Resources",
25 | image: "./photos/b.png"
26 | },
27 | {
28 | id: 2,
29 | parent: 0,
30 | title: "Fritz Stuger",
31 | description: "Business Solutions, US",
32 | image: "./photos/c.png"
33 | }
34 | ],
35 | hasSelectorCheckbox: Enabled.True,
36 | hasButtons: Enabled.True,
37 | buttonsPanelSize: 40,
38 | onButtonsRender: (({ context: itemConfig }) => {
39 | return <>
40 |
47 |
54 | >
55 | })
56 | };
57 |
58 | return
38 | }
39 | }
40 |
41 | export default Sample;
42 |
--------------------------------------------------------------------------------
/docs/CustomLayoutWithInvisibleItems.md:
--------------------------------------------------------------------------------
1 | # Custom layout with Invisible items
2 | The logical parent-children relations between items define chart navigation. When we select the new cursor item, all its children and parents become visible in the diagram so that the user can continue navigation further down or up in the hierarchy. When children or parents are invisible, we display children of children and parents of parents. This feature, combined with custom item types and children layouts, provides excellent flexibility for the custom children's configurations.
3 |
4 | The following example demonstrates how to use invisible items to arrange children attached to one parent item into multiple groups. It has two rows of assistants and two levels of children. To implement this layout, we create two hidden nodes of the regular item type. Set the `isVisible` property of the item configuration object to false to make the node invisible. Children of invisible items logically belong to their parents. In our case, it is the organizational chart's root item. When we set the cursor to the root node, all items in the diagram become logical children of the root node and visible. So the end-user may move the cursor to them directly.
5 |
6 | ```JavaScript
7 | import { OrgDiagram } from basicprimitivesreact;
8 |
21 | ```
22 |
23 | See custom item types, children layout, and inactive items samples as well.
24 |
25 | [React](../src/Samples/CustomLayoutWithInvisibleItems.jsx)
26 |
27 | ## Skipped Levels
28 |
29 | We can use hidden items to skip levels in the organizational chart as well. The hidden nodes occupy space, so we can use them to shift child items down one row relative to their parents.
30 |
31 | Use the `levelOffset` option of the item configuration object to arrange regular children into rows.
32 |
33 | [React](../src/Samples/SkippedLevels.jsx)
34 |
35 |
--------------------------------------------------------------------------------
/docs/PartnerItemTypes.md:
--------------------------------------------------------------------------------
1 | # Partner Item Types
2 | In the organizational structures, we have many exceptions from traditional tree structure visualization. The partner item types allow elevating child nodes to the level of their parents. So visually, they non-distinguishable from their parents and displayed side by side with them. For example, we can use partner item types when we need to show co-CEOs. We add our second CEO item as a child item of the first CEO and set its item type to Partner. Partner item is placed at the same level as its logical parent and shares its parent's children, so visually, children equally belong to both of them. Optionally the parent node and its partner child have a horizontal line connecting them visually into one group.
3 |
4 | Chart supports three types of partner types:
5 |
6 | * GeneralPartner
7 | * LimitedPartner
8 | * AdviserPartner
9 |
10 | They all share their parents' children, and the difference is in how they connect to their logical parent. The following example shows GeneralPartner, which shares children and parents of the logical parent, so visually, they are 100% equal on the org chart.
11 |
12 | For the sake of simplicity, the Partner node can not have its logical children by design, so if you add children to the partner node, they would be auto-converted into partner's assistants.
13 |
14 | Use ItemConfig.adviserPlacementType option to place partners to the left or right side of their logical parent;
15 |
16 | ## General Partner
17 |
18 | [React](../src/Samples/GeneralPartnerItemType.jsx)
19 |
20 | ## Limited Partner
21 |
22 | Limited Partner is a variation of GeneralPartner having no connection to the parent of the logical parent. Limited Partner shares children of the logical parent, but it does not share its parents.
23 |
24 | [React](../src/Samples/LimitedPartnerItemType.jsx)
25 |
26 | ## Adviser Partner
27 |
28 | Adviser Partner item type is a combination of Partner and Adviser types. It has an in-row horizontal connection to its logical parent, it shares children of the logical parent, but it has no links to its parents.
29 |
30 | [React](../src/Samples/AdviserPartnerItemType.jsx)
--------------------------------------------------------------------------------
/docs/readme.md:
--------------------------------------------------------------------------------
1 | # How To Use
2 | ## Create & Update Use Cases
3 | * [First Organizational Chart](FirstOrganizationalChart.md)
4 | * [First Family Chart](FirstFamilyChart.md)
5 | * [Adding new items to chart at runtime](AddingNewItemsToChartAtRuntime.md)
6 | * [Diagram Sizing](DiagramSizing.md)
7 |
8 | ## User Interface Events & Options
9 | * [Selecting cursor item & Mouse click](SelectingCursorItem.md)
10 | * [Selecting highlight item & Mouse over](SelectingHighlightItem.md)
11 | * [Selected items & Check boxes](SelectedItems.md)
12 | * [Buttons Panel](Buttons.md)
13 | * [Item & Group title colors](ItemAndGroupTitleColors.md)
14 | * [Labels](Labels.md)
15 |
16 | ## Integration
17 | * [Drag & Drop](DragNDrop.md)
18 |
19 | ## Organizational Chart Layout Options
20 | * [Regular Children Layout](ChildrenLayout.md)
21 | * [Cross-Branch Alignment](CrossBranchAlignment.md)
22 | * [Adviser & Assistant item types](AdviserAndAssistantItemTypes.md)
23 | * [Partner item types](PartnerItemTypes.md)
24 | * [Multiple root items](MultipleRootItemsInChart.md)
25 | * [Selection path mode](SelectionPathMode.md)
26 | * [Inactive items in layout](InactiveItems.md)
27 | * [Custom layout using invisible items](CustomLayoutWithInvisibleItems.md)
28 |
29 | ## Family Diagram Layout Use Cases
30 | * [Connectors Visualization](FamilyConnectorsVisualization.md)
31 | * [Matrix Layout](MatrixLayoutInFamilyChart.md)
32 | * [Inactive family items](InactiveFamilyItems.md)
33 | * [Family Items Ordering](FamilyChartItemsOrdering.md)
34 | * [Loops Layout Optimization](LoopsInFamily.md)
35 | * [Selection path mode](SelectionPathModeInFamilyChart.md)
36 |
37 | ## Item Template Use Cases
38 | * [Item Template](ItemTemplates.md)
39 | * [Zoom Using Item templates](ZoomWithItemTemplate.md)
40 | * [Zoom Using CSS Scale Transform](ZoomWithCSSScaleTransform.md)
41 | * [Cursor Template](CursorTemplate.md)
42 | * [Highlight Template](HighlightTemplate.md)
43 |
44 | ## Annotations
45 | * [On-screen Connector Annotation](ConnectorAnnotation.md)
46 | * [Shape & Background Annotations](ShapeAndBackgroundAnnotations.md)
47 | * [Level Annotation](LevelAnnotation.md)
48 | * [Highlight Path Annotation](HighlightPathAnnotation.md)
49 | * [Labels cascades in Family Chart](LabelsCascadesInFamilyChart.md)
--------------------------------------------------------------------------------
/docs/AddingNewItemsToChartAtRuntime.md:
--------------------------------------------------------------------------------
1 | # Updating configuration properties in ReactJS diagrams
2 |
3 | We do fast updates, so we don't flush and recreate diagrams for every configuration object change. We reuse transformations and visual elements if they are not affected by configuration changes. For example, to render on-screen annotations, the control does not need to layout nodes, so when we add new on-screen annotations, we show them instantly. There are some exceptions when annotations may affect nodes layout, see reference for more details. The same applies to all other visual elements. The component updates the diagram by comparing the current copy of the configuration object with the new one. If any changes are detected, the control triggers the rendering cycle for the affected visual elements only.
4 |
5 | The rendering engine does not track individual items. If we make changes to one of the nodes layout options, then the whole collection of nodes is considered as changed. As a result, the component will re-render the entire diagram. So there is no difference if you change the entire array of nodes or just a single one. The result is the same, we layout nodes and render the whole collection of items again.
6 |
7 | The component ignores changes in node options, not affecting the diagram layout. In other words, if an application changes the `title`, `description`, or `image` item properties, then the component would not trigger layout changes.
8 |
9 | ## The following example demonstrates adding new items to an organizational chart using component state:
10 |
11 | The application stores the collection of items in the application component: `state`. The diagram component updates its layout every time it gets a new configuration object reference. The diagram keeps the internal state between rendering cycles and tracks property changes for individual configuration objects. The configuration object properties may affect different visuals and transformations of the graph. The component tracks every property individually and optimizes rendering time. For the more complex implementation of chart editing functionality, see the matrixed organizational chart structure editor demo at this site.
12 |
13 | [React](../src/Samples/AddingNewItemsToChartAtRuntime.jsx)
14 |
--------------------------------------------------------------------------------
/src/Samples/CursorTemplate.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { OrgDiagram } from '../Diagrams';
3 | import { PageFitMode, Enabled } from 'basicprimitives';
4 |
5 | class Sample extends Component {
6 | render() {
7 | const config = {
8 | pageFitMode: PageFitMode.FitToPage,
9 | cursorItem: 0,
10 | highlightItem: 0,
11 | hasSelectorCheckbox: Enabled.True,
12 | defaultTemplateName: "contactTemplate",
13 | templates: [{
14 | name: "contactTemplate",
15 | itemSize: { width: 120, height: 100 },
16 | minimizedItemSize: { width: 3, height: 3 },
17 | cursorPadding: { left: 3, top: 3, right: 3, bottom: 3 },
18 | cursorBorderWidth: 2,
19 | highlightPadding: { left: 4, top: 4, right: 4, bottom: 4 },
20 | onCursorRender: ({ context: itemConfig }) => {
21 | return
55 | >
56 | }
57 | }
58 |
59 | export default Sample;
60 |
--------------------------------------------------------------------------------
/docs/AdviserAndAssistantItemTypes.md:
--------------------------------------------------------------------------------
1 | # Custom Placement of Children
2 | ## Adviser & Assistant Item Types:
3 |
4 | The organizational chart structure is a regular tree. That means that every node can only have one logical parent in the hierarchy. That makes the organizational chart conceptually easy to work with for the end-user who edits the organizational chart and the software developer to maintain the database's required structures and the application.
5 |
6 | In reality, pure hierarchical relations are rare. So in our organizational chart, we provide the means to represent non-hierarchical relations by using different child item types and on-screen annotations.
7 |
8 | The component has the following child positions in diagram layout relative to the parent node:
9 | * Regular
10 | * Adviser
11 | * Assistant
12 | * Sub Adviser
13 | * Sub Assistant
14 | * General Partner
15 | * Limited Partner
16 | * Adviser Partner
17 |
18 | All of them affect child placement relative to its parent in the hierarchy. The following example demonstrates Adviser and Assistant types. The adviser item is placed at the same level as its parent and connected to it horizontally. The assistant occupies the row between the parent and all other regular children. It has a horizontal connection to the vertical line going from the parent to the remaining children.
19 |
20 | Use the `adviserPlacementType` option to place an adviser or assistant on the parent's node hierarchy's left or right side.
21 |
22 | Use the `levelOffset` option to arrange assistants into multiple rows. See the regular children layout sample.
23 |
24 | [React](../src/Samples/AdviserAndAssistantItemTypes.jsx)
25 |
26 | ## Sub Adviser & Sub Assistant item types
27 |
28 | Sub Adviser & Sub Assistant item types are variations of regular Adviser & Assistant types. The only difference is that they have the connection line going from the top edge of the node, and they are shift down one level relative to their parents.
29 |
30 | Use the `adviserPlacementType` option to place them on the parent's hierarchy's left or right side.
31 |
32 | [React](../src/Samples/SubAdviserAndSubAssistantItemTypes.jsx)
33 |
34 | ## Adviser child nodes placement above parent's node children
35 |
36 | If the adviser node has its children, then control adds extra levels, so it places advisers children at rows above the parent's children. You can alter this layout schema with the `placeAdvisersAboveChildren` option. If you set it to false, control would place advisers and the parent's children at the same row of the diagram.
37 |
38 | [React](../src/Samples/PlaceAdvisersAboveChildren.jsx)
39 |
40 | ## Assistant child nodes placement above parent's node children
41 | If the assistant node has its children, then control pushes the parent's children down, placing assistant children at rows above the parent's children. You can alter this layout schema with the `placeAssistantsAboveChildren` option. If you set it to false, then the parent's and assistant's node children would be rendered side by side at the same level.
42 |
43 | [React](../src/Samples/PlaceAssistantsAboveChildren.jsx)
--------------------------------------------------------------------------------
/src/Samples/FamilyChartItemsOrdering.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { FamDiagram } from '../Diagrams';
3 | import { AdviserPlacementType, PageFitMode, Enabled, GroupByType } from 'basicprimitives';
4 |
5 | class Sample extends Component {
6 | constructor(props) {
7 | super(props);
8 |
9 | this.onClick = this.onClick.bind(this);
10 |
11 | this.state = {
12 | items: [
13 | { id: 10, relativeItem: 2, placementType: AdviserPlacementType.Left, position: 1, title: "Roger Dalton", label: "Roger Dalton", description: "Id: 10", image: "./photos/a.png", itemTitleColor: "#4169e1" },
14 | { id: 2, title: "Steven Lacombe", label: "Steven Lacombe", description: "Id: 2", image: "./photos/b.png", itemTitleColor: "#4b0082" },
15 | { id: 11, relativeItem: 2, placementType: AdviserPlacementType.Right, position: 1, title: "Bill Dalton", label: "Bill Dalton", description: "Id: 11", image: "./photos/c.png", itemTitleColor: "#4b0082" },
16 | { id: 1, parents: [11], title: "David Dalton", label: "David Dalton", description: "Id: 1", image: "./photos/c.png", itemTitleColor: "#4b0082" },
17 | { id: 3, parents: [10], title: "Ann Smith", label: "Ann Smith", description: "Id: 3", image: "./photos/a.png", itemTitleColor: "#4169e1" },
18 | { id: 4, parents: [2], title: "Nancy Smith", label: "Nancy Smith", description: "Id: 4", image: "./photos/c.png", itemTitleColor: "#4b0082" },
19 | { id: 5, parents: [2], title: "Helly Smith", label: "Helly Smith", description: "Id: 5", image: "./photos/a.png", itemTitleColor: "#4169e1" },
20 | { id: 6, parents: [1, 4], title: "Kelly Smith", label: "Kelly Smith", description: "Id: 6", image: "./photos/c.png", itemTitleColor: "#4b0082" },
21 | { id: 7, parents: [5, 3], title: "Sally Smith", label: "Sally Smith", description: "Id: 7", image: "./photos/a.png", itemTitleColor: "#4169e1" }
22 | ]
23 | }
24 | }
25 |
26 | onClick() {
27 | const { items } = this.state;
28 |
29 | const newItems = items.map(item => {
30 | if (item.id === 10 || item.id === 11) {
31 | let { placementType } = item;
32 | if (placementType === AdviserPlacementType.Right) {
33 | placementType = AdviserPlacementType.Left;
34 | } else {
35 | placementType = AdviserPlacementType.Right;
36 | }
37 | return {
38 | ...item,
39 | placementType
40 | }
41 | }
42 | return item;
43 | })
44 | this.setState({
45 | items: newItems
46 | })
47 | }
48 |
49 | render() {
50 | const { items } = this.state;
51 | const config = {
52 | items,
53 | pageFitMode: PageFitMode.None,
54 | cursorItem: 2,
55 | linesWidth: 1,
56 | linesColor: "black",
57 | hasSelectorCheckbox: Enabled.False,
58 | arrowsDirection: GroupByType.Parents,
59 | showExtraArrows: false
60 | };
61 |
62 | return <>
63 |
64 |
: null}
101 | >;
102 | }
103 | }
104 |
105 | export default Sample;
106 |
--------------------------------------------------------------------------------
/docs/ConnectorAnnotation.md:
--------------------------------------------------------------------------------
1 | # Connector Annotations
2 |
3 | Connector annotation is an on-screen direct connection line between two nodes of the diagram. It supports simple conflict resolution. If multiple connector annotations overlap each other between the same pair of nodes, the control offsets them and draws them parallel.
4 |
5 | The following sample demonstrates connection annotation drawn in the offbeat style. This way, connection annotation should not overlap diagram's base connection lines and block the primary diagram hierarchy view. The offbeat connector annotation compensates for the lack of space between nodes via drawing its curve outside of connected nodes.
6 |
7 | ## Styles
8 | * `ConnectorPlacementType.Offbeat` - Free hand drawing of connector annotation
9 | * `ConnectorPlacementType.Straight` - Straight line between nodes
10 |
11 | ## Shapes
12 | In general, shape of connector annotation may indicate various relations, so component supports following simple use case:
13 | * `ConnectorShapeType.OneWay` - The arrow line between `fromItem` and `toItem` nodes
14 | * `ConnectorShapeType.TwoWay` - Two opposite direction arrow lines between `fromItem` and `toItem` nodes
15 | * `ConnectorShapeType.BothWay` - One line having arrows on both ends
16 |
17 | ## Labels
18 | Connector annotations labels are plain text or JSX elements. Please, pay attention that component does not resolve connector annotations labels overlapping, so many annotations labels can clutter view and diagram in general.
19 |
20 | [React](../src/Samples/ConnectorAnnotation.jsx)
21 |
22 | # Connector Annotations Drag & Drop
23 |
24 | The following sample demonstrates how drag-and-drop can be used to create or modify connector annotations in a diagram.
25 |
26 | * Drag nodes to create new annotations.
27 | * Drag annotation endpoints to reconnect them to different nodes.
28 | * Drag an endpoint to the origin node to delete the annotation.
29 |
30 | [React](../src/Samples/ConnectorAnnotationDragNDropHooks.jsx)
31 |
32 | ## Drag and Drop Implementation
33 |
34 | The drag-and-drop behavior is implemented using **React DnD** library:
35 |
36 | - **Node drag source:** allows users to drag nodes and create new annotations by dropping on other nodes.
37 | - **Endpoint drag source:** allows users to reconnect existing annotations by dragging endpoints to different nodes.
38 | - **Custom drag layer:** provides real-time visual feedback by rendering a temporary live connector annotation between drag start and current mouse position.
39 |
40 | ## Limitations
41 |
42 | Due to [React Drag & Drop](http://react-dnd.github.io/react-dnd/about) being implemented using the HTML5 drag and drop API, there is an important technical limitation:
43 |
44 | - While dragging an annotation or its endpoint, the original annotation remains visible in the diagram.
45 | - Simultaneously, the custom drag layer renders a live preview of the dragged annotation.
46 | - As a result, both the original annotation and its live copy are temporarily visible during drag.
47 |
48 | The root cause is that HTML5 drag-and-drop requires the dragged DOM element to remain mounted during the drag operation. If we attempt to modify or remove the dragged annotation from OrgDiagram while dragging, the corresponding DOM element is unmounted from the document, which aborts the drag-and-drop operation. In order to overcome this problem, we have to use non-native drag & drop frameworks.
49 |
50 |
--------------------------------------------------------------------------------
/src/Diagrams/Templates/LevelTitleTemplate.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import AbstractTemplate from './AbstractTemplate';
3 | import RotatedText from './RotatedText';
4 | import { OrientationType, TextOrientationType } from 'basicprimitives';
5 |
6 | class LevelTitleTemplate extends AbstractTemplate {
7 | constructor(options, orientation) {
8 | super();
9 | this.render = this.render.bind(this);
10 |
11 | this.options = options;
12 | this.orientation = orientation;
13 |
14 | this.style = {
15 | position: "absolute",
16 | fontFamily: "Trebuchet MS, Tahoma, Verdana, Arial, sans-serif",
17 | WebkitTapHighlightColor: "rgba(0,0,0,0)",
18 | WebkitUserSelect: "none",
19 | WebkitTouchCallout: "none",
20 | KhtmlUserSelect: "none",
21 | MozUserSelect: "none",
22 | msUserSelect: "none",
23 | userSelect: "none",
24 | boxSizing: "content-box",
25 |
26 | MozBorderRadius: "4px",
27 | WebkitBorderRadius: "4px",
28 | KhtmlBorderRadius: "4px",
29 | BorderRadius: "4px",
30 |
31 | background: "royalblue",
32 | borderWidth: 0,
33 | color: "white",
34 | padding: 0,
35 | width: "100%",
36 | height: "100%",
37 | left: "-1px",
38 | top: "-1px"
39 | }
40 | }
41 |
42 | render(data) {
43 | var {
44 | levelTitleFontSize,
45 | levelTitleFontFamily,
46 | levelTitleFontWeight,
47 | levelTitleFontStyle,
48 | levelTitleOrientation,
49 | levelTitleHorizontalAlignment,
50 | levelTitleVerticalAlignment,
51 | levelTitleFontColor,
52 | levelTitleColor
53 | } = this.options;
54 |
55 | if(levelTitleOrientation === TextOrientationType.Auto) {
56 | switch (this.orientation) {
57 | case OrientationType.Top:
58 | levelTitleOrientation = TextOrientationType.RotateRight;
59 | break;
60 | case OrientationType.Bottom:
61 | levelTitleOrientation = TextOrientationType.RotateRight;
62 | break;
63 | default:
64 | break;
65 | }
66 | }
67 |
68 | const {
69 | context: annotationConfig,
70 | width,
71 | height
72 | } = data;
73 |
74 | const backgroundColor = annotationConfig.titleColor || levelTitleColor;
75 | const label = (annotationConfig.title || "").replace("\n", " ");
76 | const color = annotationConfig.titleFontColor || levelTitleFontColor;
77 |
78 | const orientations = ['Horizontal', 'RotateLeft', 'RotateRight', 'Horizontal'],
79 | horizontalAlignments = ['center', 'left', 'right'],
80 | verticalAlignments = ['top', 'middle', 'bottom'];
81 | const style = {
82 | ...this.style,
83 | backgroundColor,
84 | color,
85 | fontSize: levelTitleFontSize,
86 | fontFamily: levelTitleFontFamily,
87 | fontWeight: levelTitleFontWeight,
88 | fontStyle: levelTitleFontStyle
89 | }
90 | return
Hide direct connections to grand parents:
62 |
63 |
73 |
74 |
84 |
85 |
86 |
87 |
88 | >
89 | }
90 | }
91 |
92 | export default Sample;
93 |
--------------------------------------------------------------------------------
/docs/CursorTemplate.md:
--------------------------------------------------------------------------------
1 | # Cursor template
2 | Our component is a generic collection control, which supports basic features like single item selection, highlight, and multiple items checking.
3 | The cursor item is a single item selection. The navigation of the diagram depends on the current cursor item. The cursor is supposed to have some visual elements. By default, it is `div` having a solid `2px` border line around it.
4 |
5 | ## Properties:
6 | The component customizes the visual representation of items with `templates`. Every template has customization properties for item content, cursor, and highlight visualizations. By default, if properties are nulls, then the component uses built in default functionality. The following properties customize cursor template:
7 | * `cursorPadding` - Reserves space around item, for example: `{left: 3, top: 3, right: 50, bottom: 3}` will provide extra `50px` on right side of item for cursor content.
8 | * `cursorBorderWidth` - some legacy property, it is used to align cursor position around item properly.
9 | * `onCursorRender` - callback method to render cursor for the current cursor item of the diagram
10 |
11 | See the Item template for more details.
12 |
13 | ## Cursor item & preserving space for context control panel
14 | The cursor template's general idea is to provide a convenient API to place the context control panel as close to the current cursor node as possible. The conventional approach puts the control panel on the diagram's side and changes its content as the user selects a new cursor item. That approach cutoff screen space out of the diagram layout. A similar approach is to draw a context menu panel on top of the diagram on the selected node's side, but this will obstruct other diagram nodes' view. The compromise design expands space around the cursor node and places context controls into that space, so the cursor template provides a padding option to preserve that required space around the cursor node.
15 |
16 | ```JavaScript
17 | import { OrgDiagram } from basicprimitivesreact;
18 | {
24 | return ;
25 | }
26 | }]
27 | }
28 | />
29 | ```
30 |
31 | ## Avoiding conflicts between custom controls & annotations
32 | User controls inside the cursor item template serve as the in-layout annotation, non-blocking neighboring items in the chart. If you consider adding the same UI elements into every visible node, then you need to customize the item template instead.
33 |
34 | Use the z-index style attribute to layer controls properly so other diagram visuals do not block them.
35 |
36 | Every time we select a cursor node, the control recalculates the layout, which takes time. The component has many optimizations in this regard. If nothing helps, use dynamic nodes loading, limiting the total number of simultaneously layout nodes. See the Dynamic Data Loading demo. We permanently show only the top three levels or the diagram and dynamically load and discard nodes in all other rows as the end-user enters and leaves them.
37 |
38 | ## Custom cursor template border
39 | The following example demonstrates how to create a custom cursor border having item specific color and tag element.
40 |
41 | [React](../src/Samples/CursorTemplate.jsx)
42 |
43 |
--------------------------------------------------------------------------------
/src/Samples/PlaceAdvisersAboveChildren.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { OrgDiagram } from '../Diagrams';
3 | import { Enabled, PageFitMode, GroupByType, OrgItemConfig, ItemType, AdviserPlacementType } from 'basicprimitives';
4 |
5 | class Sample extends Component {
6 | constructor(props) {
7 | super(props);
8 |
9 | this.state = {
10 | placeAdvisersAboveChildren: false
11 | }
12 | }
13 |
14 | onplaceAdvisersAboveChildrenChanged(placeAdvisersAboveChildren) {
15 | this.setState({ placeAdvisersAboveChildren });
16 | }
17 |
18 | render() {
19 | const { placeAdvisersAboveChildren } = this.state;
20 | const config = {
21 | placeAdvisersAboveChildren,
22 | hasSelectorCheckbox: Enabled.False,
23 | pageFitMode: PageFitMode.None,
24 | arrowsDirection: GroupByType.Children,
25 | items: [
26 | new OrgItemConfig({
27 | id: 0,
28 | parent: null,
29 | title: "James Smith",
30 | description: "Parent Item",
31 | image: "./photos/a.png"
32 | }),
33 | new OrgItemConfig({
34 | id: 1,
35 | parent: 0,
36 | itemType: ItemType.Adviser,
37 | adviserPlacementType: AdviserPlacementType.Right,
38 | title: "Robert Canon",
39 | description: "Adviser item",
40 | groupTitle: "Adviser",
41 | image: "./photos/b.png"
42 | }),
43 | new OrgItemConfig({
44 | id: 3,
45 | parent: 1,
46 | title: "Fritz Stuger",
47 | description: "Regular Item",
48 | image: "./photos/d.png"
49 | }),
50 | new OrgItemConfig({
51 | id: 4,
52 | parent: 1,
53 | title: "Ted Lucas",
54 | description: "Regular Item",
55 | image: "./photos/d.png"
56 | }),
57 | new OrgItemConfig({
58 | id: 5,
59 | parent: 0,
60 | title: "James Nunnally",
61 | description: "Regular Item",
62 | groupTitle: "Regular",
63 | image: "./photos/d.png"
64 | }),
65 | new OrgItemConfig({
66 | id: 6,
67 | parent: 0,
68 | title: "Harry Harter",
69 | description: "Regular Item",
70 | groupTitle: "Regular",
71 | image: "./photos/d.png"
72 | })
73 | ]
74 | };
75 |
76 | return <>
77 |
;
50 | }
51 | }
52 |
53 | export default Sample;
54 |
--------------------------------------------------------------------------------
/docs/SelectingHighlightItem.md:
--------------------------------------------------------------------------------
1 | # Highlight item & Mouse over feedback
2 | Highlight provides visual feedback for mouseover and indicates the current node of keyboard focus in the chart. It is a lightweight operation that does not change the diagram layout. Your application can use highlight API to display some node context information in the side panel.
3 |
4 | Use `OrgConfig.highlightItem` property to set or get the currently highlighted node in the diagram.
5 |
6 | When the end-user moves the mouse cursor, the control may highlight nodes within some space around the cursor defined with the option `highlightGravityRadius`. It is handy when we need to click on a small marker. Still, at the same time, it may decrease the control's performance if the radius is too big because the component finds the nearest node within the area of that radius, and that radius may cover hundreds or thousands of nodes.
7 |
8 | If the user clicks outside of the highlighted item, then control moves the cursor item to it. See `cursorItem` property of the `OrgConfig` or `FamConfig` configuration objects.
9 |
10 | Every node must have a unique id. See `id` property of `OrgItemConfig` configuration object. Use those ids when you set the highlightItem option value.
11 |
12 |
13 | If you need to hide highlight, you have to set the highlightItem option to null. If you need to disable highlight functionality in control, it is useless on mobile devices; you have to change the `navigationMode` option to `NavigationMode.CursorOnly`.
14 |
15 | ```JavaScript
16 | import { OrgDiagram } from basicprimitivesreact;
17 | import { NavigationMode } from basicprimitives;
18 |
24 | ```
25 |
26 | ## Keyboard navigation
27 | The control is keyboard focusable. So when it gets focus with TAB or mouse click, there is a blue "outline" around it indicating active keyboard focus.
28 |
29 | The control supports keyboard arrows keys to choose highlighted node and `Enter` key to set cursor for it. So when the component gets focused, you have to see the blue outline, then you have to use Arrows keys to highlight the item you want to move the cursor to, and then press Enter key to set the cursor to it. Don't forget that if you need to expand marker nodes, you need to move the cursor node close.
30 |
31 | Suppose your node templates contain HTML elements supporting keyboard focus and keyboard interactivity. All of them are going to have their TAB order along with the component itself.
32 |
33 | Use buttons panel to place HTML elements having a keyboard or mouse interactivity elements above all other diagram elements, so they are not blocked. See the context buttons sample for more details.
34 |
35 | ## Events
36 | The following example shows how to set highlighted items programmatically and handle notifications about the user's mouse cursor moves in the chart with `onHighlightChange` event. It has a preceding `onHighlightChanging` event, which is needed to make application state changes and avoid unnecessary components' internal state change and the following layout updates.
37 |
38 | If you want to avoid internal component state update and the following rendering cycle, then you have to return 'true' from the `onHighlightChanging` event handler:
39 |
40 | ```JavaScript
41 | import { OrgDiagram } from basicprimitivesreact;
42 | {
43 | const { context } = data;
44 | setHighlightItem(context.id);
45 | // Return true in order to suppress set highlight item change in control
46 | // it will be updated via subsequent state change of application
47 | return true;
48 | }} />
49 | ```
50 |
51 | [React](../src/Samples/SelectingHighlightItem.jsx)
52 |
--------------------------------------------------------------------------------
/src/Samples/ShapeAnnotation.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { OrgDiagram } from '../Diagrams';
3 | import { Size, Thickness, ShapeAnnotationConfig, BackgroundAnnotationConfig, AnnotationType, Colors, PlacementType, ShapeType, LineType, GroupByType, PageFitMode, Enabled } from 'basicprimitives';
4 |
5 | class Sample extends Component {
6 | render() {
7 | const config = {
8 | items: [
9 | /* JSON noname objects equivalent to OrgItemConfig */
10 | { id: 0, parent: null, title: "James Smith", description: "VP, Public Sector", image: "./photos/a.png" },
11 | { id: 1, parent: 0, title: "Ted Lucas", description: "VP, Human Resources", image: "./photos/b.png" },
12 | { id: 2, parent: 0, title: "Fritz Stuger", description: "Business Solutions, US", image: "./photos/c.png" },
13 | { id: 3, parent: 0, title: "Mike Wazowski", description: "Business Analyst, Canada", image: "./photos/o.png" },
14 | { id: 4, parent: 3, title: "Best Friend", description: "Business Analyst, Mexico", image: "./photos/f.png" }
15 | ],
16 | annotations: [
17 | /* JSON noname object equivalent to ConnectorAnnotationConfig */
18 | {
19 | annotationType: AnnotationType.Shape,
20 | items: [0],
21 | label: <>
87 | >
88 | }
89 | }
90 |
91 | export default Sample;
92 |
--------------------------------------------------------------------------------
/docs/FamilyConnectorsVisualization.md:
--------------------------------------------------------------------------------
1 | # Family Connectors Visualization
2 | The core difference between the Family diagram and Organizational Chart is the support of multiple parents. This feature derives a lot of complexity and problems. If we look at the organizational chart, we may see that connection lines play no role in the visualization. We don't need to visually trace connection lines between nodes with our eyes to understand their mutual relations. This fact dramatically simplifies the reading of the diagram. The relative node placement on a hierarchical chart, additional spaces between branches, gives a strong visual indication of mutual relations between nodes. When we look at family diagrams supporting multiple parents, this is not the case anymore. Connectors are not secondary elements anymore, now they provide information about relations between nodes, and their excessive number creates visual clutter in the diagram, which makes their visualization virtually useless. Look at the following example of the complete bipartite graph. It has every parent node connected with every child node.
3 |
4 | 
5 |
6 | The complete bipartite graph is an extreme example of family relations. Still, in the case of support of the multiple parents, it is a valid use case, so to eliminate this connection lines mass and make relations more understandable, the control automatically groups connectors into bundles, so it produces the following set of links:
7 |
8 | 
9 |
10 | This visualization is better, but it uncovers another problem. Many parents and children do not let us see them together within screen boundaries, so to make the diagram more compact, our component supports the clustering of the nodes into matrixed formation to occupy the least space possible. To enable nodes clustering into matrixed shape, set the enableMatrixLayout option to true.
11 |
12 | ```JavaScript
13 | import { FamDiagram } from basicprimitivesreact;
14 |
19 | ```
20 |
21 | [React](../src/Samples/MatrixLayoutInFamilyChart.jsx)
22 |
23 | Another typical problem in connectors visualization is excessive grandparents relations. It is the situation when an item has direct links to all its grandparents. Usually, when we draw the family diagram, we are more interested in showing dependencies over actual relations. We know that the grandparent precedes the parent, the great grandparent precedes the grandparent, and so on. So this precedence defines the indirect link between the child node and grand-grandparent. So direct relation visualization between the child node and its grandparents can be omitted from the diagram and replaced with dynamic annotations. Look at the following example where every child references all preceding parents:
24 |
25 | 
26 |
27 | As you may see, the control already eliminated many connections via making bundles, so we don't see every connection between nodes, but still, this diagram has a lot of connections to trace. To hide direct connections to grandparents, set option the hideGrandParentsConnectors to true and get the following layout:
28 |
29 | ```JavaScript
30 | import { FamDiagram } from basicprimitivesreact;
31 |
35 | ```
36 |
37 | [React](../src/Samples/FamilyHideGrandParentsConnections.jsx)
38 |
39 | So we got a relatively clean relations diagram between nodes. We still have all relations in place. The only difference is that grandparent's connections go through actual parents, so we need to visualize them dynamically with highlight path annotations. As we browse the diagram nodes, we can highlight all directly linked parents and children with Connector Path Annotations and set dynamically custom Item Template for them.
--------------------------------------------------------------------------------
/docs/FirstOrganizationalChart.md:
--------------------------------------------------------------------------------
1 | # First Organizational Chart for ReactJS
2 |
3 | Basic Primitives Diagrams for React - data visualization component library that implements organizational chart and multi-parent dependency tree diagrams. It renders nodes using ReactJS Virtual DOM without direct DOM manipulations, so it compliant with all React features and popular react extensions like [React Drag & Drop](http://react-dnd.github.io/react-dnd/about) and [React Context](https://reactjs.org/docs/context.html)
4 |
5 | Our site contains samples and demo published on GitHub. The recommended way to get familiar with our library is to clone our GitHub [react](https://github.com/BasicPrimitives/react) repository and run it locally. It contains simple, single-page examples. If you need to see more complex end to end applications developed in ReactJS using hooks and Redux state management, then clone our GitHub [react-demos](https://github.com/BasicPrimitives/react-demo) repository
6 |
7 | ## NPM packages:
8 | Use the following commands to import our components from npm packages.
9 | ```JavaScript
10 | import React, { Component } from 'react';
11 | import { OrgDiagram } from 'basicprimitivesreact';
12 | import { Enabled, PageFitMode } from 'basicprimitives';
13 | ```
14 | * `basicprimitivesreact` - react components
15 | * `basicprimitives` - the core of the library which contains common configuration objects and enumerations.
16 |
17 | [React](../src/Samples/FirstOrganizationalChart.jsx)
18 |
19 | ## Create React App Sample
20 | The diagramming components work in React applications created with [`create-react-app`](https://facebook.github.io/create-react-app/), use the following steps to create and run the first diagram:
21 |
22 | ```
23 | npx create-react-app test1
24 | cd test1
25 |
26 | yarn add basicprimitivesreact
27 |
28 | yarn start
29 | ```
30 |
31 | Add following changes into App.js
32 |
33 | ```JavaScript
34 | import React from 'react';
35 | import { OrgDiagram } from 'basicprimitivesreact';
36 | import { PageFitMode, Enabled } from 'basicprimitives';
37 |
38 | var photos = {
39 | a: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAA8CAIAAACrV36WAAAAAXNSR0IArs4c6QAAAARn' +
40 | 'QU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGnSURBVGhD7dnBbQJBDAVQk1o2QjlQwKYGzpSwKQfq4IxIC' +
41 | 'RTB9jLZHCJFwWv7/7EiDt6zmX2yPYMHNq01eb7n5flI36JiIXWpbFW2kAwgsdVblS0kA0hs9db/ZWs+vW/Wno9PxPE3dh' +
42 | 'ls6Od+HI1XT1d64Sb8R5utEulwdbA8VY+LZ/kqkfF456pBHxDz5Xxze/p2vsxukBbAshTVOE0PO4B2cUlWKrgUTKsrV0e' +
43 | 'ut3RVU/cm5aKKqPXVbjuIDPtDUh2JImq1+jmjkupIFNFStXadHncWXkecpb3393me4oJZnionXyjLV6W4QFZEleHCWNG+' +
44 | '0eKggQJiRVV6vhAXwoqrul0AC1H1uuIsTLUyukYH1jBL7WJ8lgq6oqwkVXSQDrLSVEFXjJWoirlCrFRVyBVhJasirgCr6' +
45 | '5tEv7a5A5jL0tcN7vNl9OVcHqtXRbocVr+Kc9k3H/3qPL69Ise7dh0SsS+2JmtFddgvdy/gGbY7Jdp2GRcyrlu1BfUjxt' +
46 | 'iPRm/lqVbGHOMHnU39zQm0I/UbBLA+GVosJHGVrcoWkgEktnoLydYXkF/LiXG21MwAAAAASUVORK5CYII='
47 | };
48 |
49 | function App() {
50 | const config = {
51 | pageFitMode: PageFitMode.AutoSize,
52 | autoSizeMinimum: { width: 100, height: 100 },
53 | cursorItem: 0,
54 | highlightItem: 0,
55 | hasSelectorCheckbox: Enabled.True,
56 | items: [
57 | {
58 | id: 0,
59 | parent: null,
60 | title: 'James Smith',
61 | description: 'VP, Public Sector',
62 | image: photos.a
63 | },
64 | {
65 | id: 1,
66 | parent: 0,
67 | title: 'Ted Lucas',
68 | description: 'VP, Human Resources',
69 | image: photos.a
70 | },
71 | {
72 | id: 2,
73 | parent: 0,
74 | title: 'Fritz Stuger',
75 | description: 'Business Solutions, US',
76 | image: photos.a
77 | }
78 | ]
79 | };
80 |
81 | return (
82 |