{
  "$schema": "https://ai.syncfusion.com/schema/registry-item.json",
  "name": "diagram-organization-chart",
  "framework": "react",
  "type": "registry:component",
  "component": "Diagram",
  "variant": "organization-chart",
  "dependencies": [
    "@syncfusion/ej2-react-diagrams",
    "@syncfusion/ej2-react-inputs",
    "@syncfusion/ej2-data"
  ],
  "description": "Organization chart arranges local employee data in a horizontally aligned hierarchy.",
  "meta": {
    "essentialStudioRelease": "2026 Volume 2 (v34.1.29)",
    "license": "commercial-or-community",
    "licenseNote": "The Syncfusion package is licensed. The composition in this file is source you own and edit. See https://ai.syncfusion.com/licensing.md",
    "requiresLicenseKey": true,
    "requiresServerEndpoint": false,
    "platformIndex": "https://ai.syncfusion.com/react/llms.txt",
    "skillPack": "syncfusion/react-ui-components-skills",
    "docs": "https://ai.syncfusion.com/gallery/react/ts/diagram-organization-chart.md"
  },
  "files": [
    {
      "target": "src/components/diagram-organization-chart/Diagram.tsx",
      "content": "import {\n  type TreeInfo,\n  Node,\n  type SubTreeOrientation,\n  type LayoutOrientation,\n  type SubTreeAlignments,\n  LayoutAnimation,\n  HierarchicalTree,\n  DataBinding,\n  DiagramComponent,\n  Diagram,\n  type NodeModel,\n  type ConnectorModel,\n  ConnectorConstraints,\n  SnapConstraints,\n  Inject,\n  DiagramTools\n} from \"@syncfusion/ej2-react-diagrams\";\nimport { DataManager } from \"@syncfusion/ej2-data\";\nimport { NumericTextBoxComponent } from \"@syncfusion/ej2-react-inputs\";\n\nexport interface EmployeeInfo {\n  Role: string;\n  color: string;\n}\n\nexport interface EmployeeInfo {\n  Name: string;\n}\n\nlet localBindData = [\n    { 'Id': 'parent', 'Role': 'Board', 'color': '#71AF17' },\n    { 'Id': '1', 'Role': 'General Manager', 'Manager': 'parent', 'ChartType': 'right', 'color': '#71AF17' },\n    { 'Id': '11', 'Role': 'Assistant General Manager', 'Manager': '1', 'color': '#71AF17' },\n    { 'Id': '2', 'Role': 'Human Resource Manager', 'Manager': '1', 'ChartType': 'right', 'color': '#1859B7' },\n    { 'Id': '3', 'Role': 'Trainers', 'Manager': '2', 'color': '#2E95D8' },\n    { 'Id': '4', 'Role': 'Recruiting Team', 'Manager': '2', 'color': '#2E95D8' },\n    { 'Id': '5', 'Role': 'Finance Asst. Manager', 'Manager': '2', 'color': '#2E95D8' },\n    { 'Id': '6', 'Role': 'Design Manager', 'Manager': '1', 'ChartType': 'right', 'color': '#1859B7' },\n    { 'Id': '7', 'Role': 'Design Supervisor', 'Manager': '6', 'color': '#2E95D8' },\n    { 'Id': '8', 'Role': 'Development Supervisor', 'Manager': '6', 'color': '#2E95D8' },\n    { 'Id': '9', 'Role': 'Drafting Supervisor', 'Manager': '6', 'color': '#2E95D8' },\n    { 'Id': '10', 'Role': 'Operations Manager', 'Manager': '1', 'ChartType': 'right', 'color': '#1859B7' },\n    { 'Id': '11', 'Role': 'Statistics Department', 'Manager': '10', 'color': '#2E95D8' },\n    { 'Id': '12', 'Role': 'Logistics Department', 'Manager': '10', 'color': '#2E95D8' },\n    { 'Id': '16', 'Role': 'Marketing Manager', 'Manager': '1', 'ChartType': 'right', 'color': '#1859B7' },\n    { 'Id': '17', 'Role': 'Overseas Sales Manager', 'Manager': '16', 'color': '#2E95D8' },\n    { 'Id': '18', 'Role': 'Petroleum Manager', 'Manager': '16', 'color': '#2E95D8' },\n    { 'Id': '20', 'Role': 'Service Department Manager', 'Manager': '16', 'color': '#2E95D8' },\n    { 'Id': '21', 'Role': 'Quality Control Department', 'Manager': '16', 'color': '#2E95D8' }\n];\n\nconst SAMPLE_CSS = `\n/* Property panel orientation and sub tree alignment */\n.diagram-organization .image-pattern-style {\n        background-color: white;\n        background-size: contain;\n        background-repeat: no-repeat;\n        height: 75px;\n        width: calc((100% - 18px) / 3);\n        cursor: pointer;\n        border: 1px solid #D5D5D5;\n        background-position: center;\n        float: left;\n    }\n\n    .diagram-organization .image-pattern-style:hover {\n        border-color: gray;\n        border-width: 2px;\n    }\n\n    .diagram-organization .row {\n        margin-left: 0px;\n        margin-right: 0px;\n    }\n\n    .diagram-organization .row-header {\n        font-size: 13px;\n        font-weight: 500;\n    }\n\n    .diagram-organization .property-panel-header {\n      padding-top: 15px;\n      padding-bottom: 15px;\n    }\n\n    .diagram-organization .e-selected-orientation-style {\n        border-color: #006CE6;\n        border-width: 2px;\n    }\n\n    .diagram-organization .e-selected-pattern-style {\n        border-color: #006CE6;\n        border-width: 2px;\n    }\n\n    .diagram-organization .col-xs-6 {\n        padding-left: 0px;\n        padding-right: 0px;\n    }`;\n\nlet diagramInstance: DiagramComponent;\nlet orientation: LayoutOrientation;\nlet type: SubTreeAlignments;\nlet orientationInstance: HTMLElement;\nlet patternInstance: HTMLElement;\n\nfunction OrganizationModel() {\n  function rendereComplete() {\n    //Click Event for orientation of the PropertyPanel.\n    orientationInstance.onclick = (args: MouseEvent) => {\n      let target: HTMLElement = args.target as HTMLElement;\n      let selectedElement: HTMLCollection = document.getElementsByClassName(\n        \"e-selected-orientation-style\"\n      );\n      if (selectedElement.length) {\n        selectedElement[0].classList.remove(\"e-selected-orientation-style\");\n      }\n      if (!target.classList.contains(\"e-selected-orientation-style\")) {\n        target.classList.add(\"e-selected-orientation-style\");\n      }\n      if (\n        target.className === \"image-pattern-style e-selected-orientation-style\"\n      ) {\n        switch (target.id) {\n          case \"toptobottom\":\n            diagramInstance.layout.orientation = \"TopToBottom\";\n            break;\n          case \"bottomtotop\":\n            diagramInstance.layout.orientation = \"BottomToTop\";\n            break;\n          case \"lefttoright\":\n            diagramInstance.layout.orientation = \"LeftToRight\";\n            break;\n          case \"righttoleft\":\n            diagramInstance.layout.orientation = \"RightToLeft\";\n            break;\n          default:\n            if (selectedElement.length) {\n              selectedElement[0].classList.remove(\n                \"e-selected-orientation-style\"\n              );\n            }\n        }\n        diagramInstance.dataBind();\n        diagramInstance.doLayout();\n      }\n    };\n    //Click Event for pattern of the PropertyPanel.\n    patternInstance.onclick = (args: MouseEvent) => {\n      let target: HTMLElement = args.target as HTMLElement;\n      let selectedpatternElement: HTMLCollection = document.getElementsByClassName(\n        \"e-selected-pattern-style\"\n      );\n      if (selectedpatternElement.length) {\n        selectedpatternElement[0].classList.remove(\"e-selected-pattern-style\");\n      }\n      if (!target.classList.contains(\"e-selected-pattern-style\")) {\n        target.classList.add(\"e-selected-pattern-style\");\n      }\n      if (target.className === \"image-pattern-style e-selected-pattern-style\") {\n        switch (target.id) {\n          case \"pattern1\":\n            orientation = \"Vertical\".toString() as LayoutOrientation;\n            type = \"Alternate\" as SubTreeAlignments;\n            break;\n          case \"pattern2\":\n            orientation = \"Vertical\".toString() as LayoutOrientation;\n            type = \"Left\" as SubTreeAlignments;\n            break;\n          case \"pattern3\":\n            orientation = \"Vertical\".toString() as LayoutOrientation;\n            type = \"Left\" as SubTreeAlignments;\n            break;\n          case \"pattern4\":\n            orientation = \"Vertical\".toString() as LayoutOrientation;\n            type = \"Right\" as SubTreeAlignments;\n            break;\n          case \"pattern5\":\n            orientation = \"Vertical\".toString() as LayoutOrientation;\n            type = \"Right\" as SubTreeAlignments;\n            break;\n          case \"pattern6\":\n            orientation = \"Horizontal\".toString() as LayoutOrientation;\n            type = \"Balanced\" as SubTreeAlignments;\n            break;\n          case \"pattern7\":\n            orientation = \"Horizontal\".toString() as LayoutOrientation;\n            type = \"Center\" as SubTreeAlignments;\n            break;\n          case \"pattern8\":\n            orientation = \"Horizontal\".toString() as LayoutOrientation;\n            type = \"Left\" as SubTreeAlignments;\n            break;\n          case \"pattern9\":\n            orientation = \"Horizontal\".toString() as LayoutOrientation;\n            type = \"Right\" as SubTreeAlignments;\n            break;\n          default:\n            if (selectedpatternElement.length) {\n              selectedpatternElement[0].classList.remove(\n                \"e-selected-pattern-style\"\n              );\n            }\n        }\n        diagramInstance.layout.getLayoutInfo = (\n          node: Node,\n          options: TreeInfo\n        ) => {\n          if (target.id === \"pattern4\" || target.id === \"pattern3\") {\n            options.offset = -50;\n          }\n          if (orientation) {\n            getLayoutInfo(node, options, orientation, type);\n          }\n        };\n\n        diagramInstance.dataBind();\n        diagramInstance.doLayout();\n      }\n    };\n  }\n  //set orientation and type of the Layout.\n  function getLayoutInfo(\n    node: Node,\n    options: TreeInfo,\n    orientation: LayoutOrientation,\n    type: SubTreeAlignments\n  ): void {\n    /* tslint:disable:no-string-literal */\n    if ((node.data as DataInfo)[\"Role\"] === \"General Manager\") {\n      options.assistants.push(options.children[0]);\n      options.children.splice(0, 1);\n    }\n    if (!options.hasSubTree) {\n      options.orientation = orientation as SubTreeOrientation;\n      options.type = type;\n    }\n  }\n\n  //sets default value for Node.\n  function nodeDefaults(obj: Node, diagram: Diagram): Node {\n    obj.backgroundColor = (obj.data as EmployeeInfo).color;\n    obj.style = { fill: \"none\", strokeColor: \"none\", color: \"white\" };\n    obj.expandIcon = {\n      height: 10,\n      width: 10,\n      shape: \"None\",\n      fill: \"lightgray\",\n      offset: { x: 0.5, y: 1 }\n    };\n    obj.expandIcon.verticalAlignment = \"Center\";\n    obj.expandIcon.margin = { left: 0, right: 0, top: 0, bottom: 0 };\n    obj.collapseIcon = { height: 10, width: 10, shape: \"None\", fill: \"lightgray\", offset: { x: 0.5, y: 1 } };\n    obj.collapseIcon.verticalAlignment = \"Center\";\n    obj.collapseIcon.margin = { left: 0, right: 0, top: 0, bottom: 0 };\n    obj.width = 120;\n    obj.height = 30;\n    return obj;\n  }\n\n  //sets default value for Connector.\n  function connectorDefaults(\n    connector: ConnectorModel,\n    diagram: Diagram\n  ): ConnectorModel {\n    connector.targetDecorator.shape = \"None\";\n    connector.type = \"Orthogonal\";\n    connector.constraints = ConnectorConstraints.None;\n    connector.cornerRadius = 0;\n    return connector;\n  }\n  // Updates expand and collapse icons of nodes based on args.checked state\n  function onExpandChange (args : ChangeEventArgs): void {\n    for (let node of diagramInstance.nodes) {\n        if (args.checked) {\n            node.expandIcon.shape = 'Minus';\n            node.collapseIcon.shape = 'Plus';\n        } else {\n            node.expandIcon.shape = 'None';\n            node.collapseIcon.shape = 'None';\n        }\n    }\n    diagramInstance.dataBind();\n    diagramInstance.doLayout();\n  }; \n  return (\n    <div className=\"control-pane diagram-organization\">\n      <style>{SAMPLE_CSS}</style>\n      <div className=\"col-lg-8 control-section\">\n        <div  style={{ width: \"100%\" }}>\n          <DiagramComponent\n            id=\"diagram\"\n            ref={(diagram) => (diagramInstance = diagram)}\n            width={\"100%\"}\n            height={\"700px\"}\n            snapSettings={{ constraints: SnapConstraints.None }}\n            //configures data source settings\n            dataSourceSettings={{\n              id: \"Id\",\n              parentId: \"Manager\",\n              dataSource: new DataManager(localBindData as JSON[]),\n              doBinding: (\n                nodeModel: NodeModel,\n                data: object,\n                diagram: Diagram\n              ) => {\n                nodeModel.shape = {\n                  type: \"Text\",\n                  content: (data as EmployeeInfo).Role,\n                  margin: { left: 10, right: 10, top: 10, bottom: 10 },\n                };\n              },\n            }}\n            //Disables all interactions except zoom/pan\n            tool={DiagramTools.ZoomPan}\n            //Configures automatic layout\n            layout={{\n              type: \"OrganizationalChart\",\n              getLayoutInfo: (node: Node, options: TreeInfo) => {\n                /* tslint:disable:no-string-literal */\n                if ((node.data as DataInfo)[\"Role\"] === \"General Manager\") {\n                  options.assistants.push(options.children[0]);\n                  options.children.splice(0, 1);\n                }\n                if (!options.hasSubTree) {\n                  options.type = \"Right\";\n                }\n              },\n            }}\n            //Defines the default node and connector properties\n            getNodeDefaults={(obj: Node, diagram: Diagram) => {\n              /* tslint:disable:no-string-literal */\n              return nodeDefaults(obj, diagram);\n            }}\n            getConnectorDefaults={(\n              connector: ConnectorModel,\n              diagram: Diagram\n            ) => {\n              return connectorDefaults(connector, diagram);\n            }}\n          >\n            <Inject\n              services={[DataBinding, HierarchicalTree, LayoutAnimation]}\n            />\n          </DiagramComponent>\n        </div>\n      </div>\n\n    </div>\n  );\n}\nexport interface DataInfo {\n  [key: string]: string;\n}\nexport default OrganizationModel;"
    }
  ]
}