ng-zorro-antd-graph.mjs 64 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560
  1. import { SelectionModel } from '@angular/cdk/collections';
  2. import { BehaviorSubject, merge, Subject, ReplaySubject, forkJoin } from 'rxjs';
  3. import { map, filter, takeUntil, take, finalize } from 'rxjs/operators';
  4. import * as i0 from '@angular/core';
  5. import { Component, inject, Injector, afterNextRender, Input, ChangeDetectionStrategy, Directive, booleanAttribute, EventEmitter, Output, ElementRef, TemplateRef, forwardRef, ContentChild, ViewChildren, ViewEncapsulation, NgModule } from '@angular/core';
  6. import { NgTemplateOutlet } from '@angular/common';
  7. import { line, curveLinear, curveBasis } from 'd3-shape';
  8. import { drag } from 'd3-drag';
  9. import { select, pointer } from 'd3-selection';
  10. import { zoomIdentity, zoom, zoomTransform } from 'd3-zoom';
  11. import { reqAnimFrame, cancelRequestAnimationFrame } from 'ng-zorro-antd/core/polyfill';
  12. import * as i1 from '@angular/animations';
  13. import { style, query, group, animate } from '@angular/animations';
  14. import { fromEventOutsideAngular, numberAttributeWithOneFallback } from 'ng-zorro-antd/core/util';
  15. import { transition } from 'd3-transition';
  16. import { buildGraph } from 'dagre-compound';
  17. import { NzNoAnimationDirective } from 'ng-zorro-antd/core/no-animation';
  18. /**
  19. * Use of this source code is governed by an MIT-style license that can be
  20. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  21. */
  22. var NzGraphEdgeType;
  23. (function (NzGraphEdgeType) {
  24. NzGraphEdgeType["LINE"] = "line";
  25. NzGraphEdgeType["CURVE"] = "curve";
  26. })(NzGraphEdgeType || (NzGraphEdgeType = {}));
  27. function nzTypeDefinition() {
  28. return item => item;
  29. }
  30. const NZ_GRAPH_LAYOUT_SETTING = {
  31. graph: {
  32. meta: {
  33. nodeSep: 50,
  34. rankSep: 50,
  35. edgeSep: 5
  36. }
  37. },
  38. subScene: {
  39. meta: {
  40. paddingTop: 20,
  41. paddingBottom: 20,
  42. paddingLeft: 20,
  43. paddingRight: 20,
  44. labelHeight: 20
  45. }
  46. },
  47. nodeSize: {
  48. meta: {
  49. width: 50,
  50. maxLabelWidth: 0,
  51. height: 50
  52. },
  53. node: {
  54. width: 50,
  55. height: 50,
  56. labelOffset: 10,
  57. maxLabelWidth: 40
  58. },
  59. bridge: {
  60. width: 5,
  61. height: 5,
  62. radius: 2,
  63. labelOffset: 0
  64. }
  65. }
  66. };
  67. /**
  68. * Use of this source code is governed by an MIT-style license that can be
  69. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  70. */
  71. /**
  72. * Use of this source code is governed by an MIT-style license that can be
  73. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  74. */
  75. class NzGraphData {
  76. _data = new BehaviorSubject({});
  77. dataSource;
  78. /** A selection model with multi-selection to track expansion status. */
  79. expansionModel = new SelectionModel(true);
  80. /** Toggles one single data node's expanded/collapsed state. */
  81. toggle(nodeName) {
  82. this.expansionModel.toggle(nodeName);
  83. }
  84. /** Expands one single data node. */
  85. expand(nodeName) {
  86. const compound = this.dataSource.compound || {};
  87. const toBeSelected = this.findParents(compound, nodeName, [nodeName]);
  88. this.expansionModel.select(...toBeSelected);
  89. }
  90. /** Collapses one single data node. */
  91. collapse(nodeName) {
  92. const compound = this.dataSource.compound || {};
  93. const toBeDeselected = this.findChildren(compound, nodeName, [nodeName]);
  94. this.expansionModel.deselect(...toBeDeselected);
  95. }
  96. /** Whether a given data node is expanded or not. Returns true if the data node is expanded. */
  97. isExpanded(nodeName) {
  98. return this.expansionModel.isSelected(nodeName);
  99. }
  100. /** Collapse all dataNodes in the tree. */
  101. collapseAll() {
  102. this.expansionModel.clear();
  103. }
  104. expandAll() {
  105. this.expansionModel.select(...Object.keys(this._data.value.compound || {}));
  106. }
  107. setData(data) {
  108. this.expansionModel?.clear();
  109. this.dataSource = data;
  110. this._data.next(data);
  111. }
  112. constructor(source) {
  113. if (source) {
  114. this.expansionModel?.clear();
  115. this.dataSource = source;
  116. this._data.next(source);
  117. }
  118. }
  119. connect() {
  120. const changes = [this._data, this.expansionModel.changed];
  121. return merge(...changes).pipe(map(() => this._data.value));
  122. }
  123. disconnect() {
  124. // do nothing for now
  125. }
  126. findParents(data, key, parents = []) {
  127. const parent = Object.keys(data)
  128. .filter(d => d !== key)
  129. .find(d => data[d].includes(key));
  130. if (!parent) {
  131. return parents;
  132. }
  133. else {
  134. return this.findParents(data, parent, [parent, ...parents]);
  135. }
  136. }
  137. findChildren(data, key, children = []) {
  138. const groupIds = Object.keys(data);
  139. const child = (data[key] || []).filter((c) => groupIds.includes(c));
  140. if (child && child.length > 0) {
  141. return child.reduce((pre, cur) => Array.from(new Set([...pre, ...this.findChildren(data, cur, [...children, cur])])), children);
  142. }
  143. return children;
  144. }
  145. }
  146. /**
  147. * Use of this source code is governed by an MIT-style license that can be
  148. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  149. */
  150. class NzGraphDefsComponent {
  151. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzGraphDefsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
  152. static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.2", type: NzGraphDefsComponent, isStandalone: true, selector: "svg:defs[nz-graph-defs]", ngImport: i0, template: `
  153. <svg:marker
  154. class="nz-graph-edge-marker"
  155. id="edge-end-arrow"
  156. viewBox="1 0 20 20"
  157. refX="8"
  158. refY="3.5"
  159. markerWidth="10"
  160. markerHeight="10"
  161. orient="auto"
  162. >
  163. <svg:polygon points="0 0, 10 3.5, 0 7"></svg:polygon>
  164. </svg:marker>
  165. `, isInline: true });
  166. }
  167. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzGraphDefsComponent, decorators: [{
  168. type: Component,
  169. args: [{
  170. selector: 'svg:defs[nz-graph-defs]',
  171. template: `
  172. <svg:marker
  173. class="nz-graph-edge-marker"
  174. id="edge-end-arrow"
  175. viewBox="1 0 20 20"
  176. refX="8"
  177. refY="3.5"
  178. markerWidth="10"
  179. markerHeight="10"
  180. orient="auto"
  181. >
  182. <svg:polygon points="0 0, 10 3.5, 0 7"></svg:polygon>
  183. </svg:marker>
  184. `
  185. }]
  186. }] });
  187. /**
  188. * Use of this source code is governed by an MIT-style license that can be
  189. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  190. */
  191. class NzGraphEdgeComponent {
  192. elementRef;
  193. cdr;
  194. edge;
  195. edgeType;
  196. customTemplate;
  197. get id() {
  198. return this.edge?.id || `${this.edge.v}--${this.edge.w}`;
  199. }
  200. el;
  201. path;
  202. line = line()
  203. .x(d => d.x)
  204. .y(d => d.y)
  205. .curve(curveLinear);
  206. injector = inject(Injector);
  207. constructor(elementRef, cdr) {
  208. this.elementRef = elementRef;
  209. this.cdr = cdr;
  210. this.el = this.elementRef.nativeElement;
  211. }
  212. ngOnInit() {
  213. this.initElementStyle();
  214. }
  215. ngOnChanges(changes) {
  216. const { edge, customTemplate, edgeType } = changes;
  217. if (edge) {
  218. afterNextRender(() => {
  219. // Update path element if customTemplate set
  220. if (customTemplate) {
  221. this.initElementStyle();
  222. }
  223. this.setLine();
  224. this.cdr.markForCheck();
  225. }, { injector: this.injector });
  226. }
  227. if (edgeType) {
  228. const type = this.edgeType === NzGraphEdgeType.LINE ? curveLinear : curveBasis;
  229. this.line = line()
  230. .x(d => d.x)
  231. .y(d => d.y)
  232. .curve(type);
  233. }
  234. }
  235. initElementStyle() {
  236. this.path = this.el.querySelector('path');
  237. this.setElementData();
  238. }
  239. setLine() {
  240. this.setPath(this.line(this.edge.points));
  241. }
  242. setPath(d) {
  243. this.path.setAttribute('d', d);
  244. }
  245. setElementData() {
  246. if (!this.path) {
  247. return;
  248. }
  249. this.path.setAttribute('id', this.id);
  250. this.path.setAttribute('data-edge', this.id);
  251. this.path.setAttribute('data-v', `${this.edge.v}`);
  252. this.path.setAttribute('data-w', `${this.edge.w}`);
  253. }
  254. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzGraphEdgeComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
  255. static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.2", type: NzGraphEdgeComponent, isStandalone: true, selector: "[nz-graph-edge]", inputs: { edge: "edge", edgeType: "edgeType", customTemplate: "customTemplate" }, usesOnChanges: true, ngImport: i0, template: `
  256. @if (customTemplate) {
  257. <ng-container [ngTemplateOutlet]="customTemplate" [ngTemplateOutletContext]="{ $implicit: edge }" />
  258. } @else {
  259. <svg:g>
  260. <path class="nz-graph-edge-line" [attr.marker-end]="'url(#edge-end-arrow)'"></path>
  261. @if (edge.label) {
  262. <svg:text class="nz-graph-edge-text" text-anchor="middle" dy="10">
  263. <textPath [attr.href]="'#' + id" startOffset="50%">{{ edge.label }}</textPath>
  264. </svg:text>
  265. }
  266. </svg:g>
  267. }
  268. `, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
  269. }
  270. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzGraphEdgeComponent, decorators: [{
  271. type: Component,
  272. args: [{
  273. selector: '[nz-graph-edge]',
  274. template: `
  275. @if (customTemplate) {
  276. <ng-container [ngTemplateOutlet]="customTemplate" [ngTemplateOutletContext]="{ $implicit: edge }" />
  277. } @else {
  278. <svg:g>
  279. <path class="nz-graph-edge-line" [attr.marker-end]="'url(#edge-end-arrow)'"></path>
  280. @if (edge.label) {
  281. <svg:text class="nz-graph-edge-text" text-anchor="middle" dy="10">
  282. <textPath [attr.href]="'#' + id" startOffset="50%">{{ edge.label }}</textPath>
  283. </svg:text>
  284. }
  285. </svg:g>
  286. }
  287. `,
  288. changeDetection: ChangeDetectionStrategy.OnPush,
  289. imports: [NgTemplateOutlet]
  290. }]
  291. }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }], propDecorators: { edge: [{
  292. type: Input
  293. }], edgeType: [{
  294. type: Input
  295. }], customTemplate: [{
  296. type: Input
  297. }] } });
  298. /**
  299. * Use of this source code is governed by an MIT-style license that can be
  300. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  301. */
  302. class NzGraphEdgeDirective {
  303. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzGraphEdgeDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
  304. static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.2", type: NzGraphEdgeDirective, isStandalone: true, selector: "[nzGraphEdge]", exportAs: ["nzGraphEdge"], ngImport: i0 });
  305. }
  306. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzGraphEdgeDirective, decorators: [{
  307. type: Directive,
  308. args: [{
  309. selector: '[nzGraphEdge]',
  310. exportAs: 'nzGraphEdge'
  311. }]
  312. }] });
  313. /**
  314. * Use of this source code is governed by an MIT-style license that can be
  315. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  316. */
  317. class NzGraphGroupNodeDirective {
  318. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzGraphGroupNodeDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
  319. static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.2", type: NzGraphGroupNodeDirective, isStandalone: true, selector: "[nzGraphGroupNode]", exportAs: ["nzGraphGroupNode"], ngImport: i0 });
  320. }
  321. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzGraphGroupNodeDirective, decorators: [{
  322. type: Directive,
  323. args: [{
  324. selector: '[nzGraphGroupNode]',
  325. exportAs: 'nzGraphGroupNode'
  326. }]
  327. }] });
  328. /**
  329. * Use of this source code is governed by an MIT-style license that can be
  330. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  331. */
  332. const FRAC_VIEWPOINT_AREA = 0.8;
  333. class Minimap {
  334. ngZone;
  335. svg;
  336. zoomG;
  337. mainZoom;
  338. minimap;
  339. maxWidth;
  340. labelPadding;
  341. canvas;
  342. canvasRect;
  343. canvasBuffer;
  344. minimapSvg;
  345. viewpoint;
  346. scaleMinimap;
  347. scaleMain;
  348. translate;
  349. viewpointCoord;
  350. minimapSize;
  351. unlisteners = [];
  352. constructor(ngZone, svg, zoomG, mainZoom, minimap, maxWidth, labelPadding) {
  353. this.ngZone = ngZone;
  354. this.svg = svg;
  355. this.zoomG = zoomG;
  356. this.mainZoom = mainZoom;
  357. this.minimap = minimap;
  358. this.maxWidth = maxWidth;
  359. this.labelPadding = labelPadding;
  360. const minimapElement = select(minimap);
  361. const minimapSvgElement = minimapElement.select('svg');
  362. const viewpointElement = minimapSvgElement.select('rect');
  363. this.canvas = minimapElement.select('canvas.viewport').node();
  364. this.canvasRect = this.canvas.getBoundingClientRect();
  365. const handleEvent = (event) => {
  366. const minimapOffset = this.minimapOffset();
  367. const width = Number(viewpointElement.attr('width'));
  368. const height = Number(viewpointElement.attr('height'));
  369. const clickCoords = pointer(event, minimapSvgElement.node());
  370. this.viewpointCoord.x = clickCoords[0] - width / 2 - minimapOffset.x;
  371. this.viewpointCoord.y = clickCoords[1] - height / 2 - minimapOffset.y;
  372. this.updateViewpoint();
  373. };
  374. this.viewpointCoord = { x: 0, y: 0 };
  375. const subject = drag().subject(Object);
  376. const dragEvent = subject.on('drag', handleEvent);
  377. viewpointElement.datum(this.viewpointCoord).call(dragEvent);
  378. // Make the minimap clickable.
  379. minimapSvgElement.on('click', event => {
  380. if (event.defaultPrevented) {
  381. // This click was part of a drag event, so suppress it.
  382. return;
  383. }
  384. handleEvent(event);
  385. });
  386. this.unlisteners.push(() => {
  387. subject.on('drag', null);
  388. minimapSvgElement.on('click', null);
  389. });
  390. this.viewpoint = viewpointElement.node();
  391. this.minimapSvg = minimapSvgElement.node();
  392. this.canvasBuffer = minimapElement.select('canvas.buffer').node();
  393. this.update();
  394. }
  395. destroy() {
  396. while (this.unlisteners.length) {
  397. this.unlisteners.pop()();
  398. }
  399. }
  400. minimapOffset() {
  401. return {
  402. x: (this.canvasRect.width - this.minimapSize.width) / 2,
  403. y: (this.canvasRect.height - this.minimapSize.height) / 2
  404. };
  405. }
  406. updateViewpoint() {
  407. // Update the coordinates of the viewpoint rectangle.
  408. select(this.viewpoint).attr('x', this.viewpointCoord.x).attr('y', this.viewpointCoord.y);
  409. // Update the translation vector of the main svg to reflect the
  410. // new viewpoint.
  411. const mainX = (-this.viewpointCoord.x * this.scaleMain) / this.scaleMinimap;
  412. const mainY = (-this.viewpointCoord.y * this.scaleMain) / this.scaleMinimap;
  413. select(this.svg).call(this.mainZoom.transform, zoomIdentity.translate(mainX, mainY).scale(this.scaleMain));
  414. }
  415. update() {
  416. let sceneSize = null;
  417. try {
  418. // Get the size of the entire scene.
  419. sceneSize = this.zoomG.getBBox();
  420. if (sceneSize.width === 0) {
  421. // There is no scene anymore. We have been detached from the dom.
  422. return;
  423. }
  424. }
  425. catch {
  426. // Firefox produced NS_ERROR_FAILURE if we have been
  427. // detached from the dom.
  428. return;
  429. }
  430. const svgSelection = select(this.svg);
  431. // Read all the style rules in the document and embed them into the svg.
  432. // The svg needs to be self contained, i.e. all the style rules need to be
  433. // embedded so the canvas output matches the origin.
  434. let stylesText = '';
  435. for (const k of new Array(document.styleSheets.length).keys()) {
  436. try {
  437. const cssRules = document.styleSheets[k].cssRules || document.styleSheets[k].rules;
  438. if (cssRules == null) {
  439. continue;
  440. }
  441. for (const i of new Array(cssRules.length).keys()) {
  442. // Remove tf-* selectors from the styles.
  443. stylesText += `${cssRules[i].cssText.replace(/ ?tf-[\w-]+ ?/g, '')}\n`;
  444. }
  445. }
  446. catch (e) {
  447. if (e.name !== 'SecurityError') {
  448. throw e;
  449. }
  450. }
  451. }
  452. // Temporarily add the css rules to the main svg.
  453. const svgStyle = svgSelection.append('style');
  454. svgStyle.text(stylesText);
  455. // Temporarily remove the zoom/pan transform from the main svg since we
  456. // want the minimap to show a zoomed-out and centered view.
  457. const zoomGSelection = select(this.zoomG);
  458. const zoomTransform = zoomGSelection.attr('transform');
  459. zoomGSelection.attr('transform', null);
  460. // Since we add padding, account for that here.
  461. sceneSize.height += this.labelPadding * 2;
  462. sceneSize.width += this.labelPadding * 2;
  463. // Temporarily assign an explicit width/height to the main svg, since
  464. // it doesn't have one (uses flex-box), but we need it for the canvas
  465. // to work.
  466. svgSelection.attr('width', sceneSize.width).attr('height', sceneSize.height);
  467. // Since the content inside the svg changed (e.g. a node was expanded),
  468. // the aspect ratio have also changed. Thus, we need to update the scale
  469. // factor of the minimap. The scale factor is determined such that both
  470. // the width and height of the minimap are <= maximum specified w/h.
  471. this.scaleMinimap = this.maxWidth / Math.max(sceneSize.width, sceneSize.height);
  472. this.minimapSize = {
  473. width: sceneSize.width * this.scaleMinimap,
  474. height: sceneSize.height * this.scaleMinimap
  475. };
  476. const minimapOffset = this.minimapOffset();
  477. // Update the size of the minimap's svg, the buffer canvas and the
  478. // viewpoint rect.
  479. select(this.minimapSvg).attr(this.minimapSize);
  480. select(this.canvasBuffer).attr(this.minimapSize);
  481. if (this.translate != null && this.zoom != null) {
  482. // Update the viewpoint rectangle shape since the aspect ratio of the
  483. // map has changed.
  484. this.ngZone.runOutsideAngular(() => reqAnimFrame(() => this.zoom()));
  485. }
  486. // Serialize the main svg to a string which will be used as the rendering
  487. // content for the canvas.
  488. const svgXml = new XMLSerializer().serializeToString(this.svg);
  489. // Now that the svg is serialized for rendering, remove the temporarily
  490. // assigned styles, explicit width and height and bring back the pan/zoom
  491. // transform.
  492. svgStyle.remove();
  493. svgSelection.attr('width', '100%').attr('height', '100%');
  494. zoomGSelection.attr('transform', zoomTransform);
  495. const image = document.createElement('img');
  496. const onLoad = () => {
  497. // Draw the svg content onto the buffer canvas.
  498. const context = this.canvasBuffer.getContext('2d');
  499. context.clearRect(0, 0, this.canvasBuffer.width, this.canvasBuffer.height);
  500. context.drawImage(image, minimapOffset.x, minimapOffset.y, this.minimapSize.width, this.minimapSize.height);
  501. this.ngZone.runOutsideAngular(() => {
  502. reqAnimFrame(() => {
  503. // Hide the old canvas and show the new buffer canvas.
  504. select(this.canvasBuffer).style('display', 'block');
  505. select(this.canvas).style('display', 'none');
  506. // Swap the two canvases.
  507. [this.canvas, this.canvasBuffer] = [this.canvasBuffer, this.canvas];
  508. });
  509. });
  510. };
  511. image.addEventListener('load', onLoad);
  512. image.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgXml)}`;
  513. this.unlisteners.push(() => {
  514. image.removeEventListener('load', onLoad);
  515. });
  516. }
  517. /**
  518. * Handles changes in zooming/panning. Should be called from the main svg
  519. * to notify that a zoom/pan was performed and this minimap will update it's
  520. * viewpoint rectangle.
  521. *
  522. * @param transform
  523. */
  524. zoom(transform) {
  525. if (this.scaleMinimap == null) {
  526. // Scene is not ready yet.
  527. return;
  528. }
  529. // Update the new translate and scale params, only if specified.
  530. if (transform) {
  531. this.translate = [transform.x, transform.y];
  532. this.scaleMain = transform.k;
  533. }
  534. // Update the location of the viewpoint rectangle.
  535. const svgRect = this.svg.getBoundingClientRect();
  536. const minimapOffset = this.minimapOffset();
  537. const viewpointSelection = select(this.viewpoint);
  538. this.viewpointCoord.x = (-this.translate[0] * this.scaleMinimap) / this.scaleMain;
  539. this.viewpointCoord.y = (-this.translate[1] * this.scaleMinimap) / this.scaleMain;
  540. const viewpointWidth = (svgRect.width * this.scaleMinimap) / this.scaleMain;
  541. const viewpointHeight = (svgRect.height * this.scaleMinimap) / this.scaleMain;
  542. viewpointSelection
  543. .attr('x', this.viewpointCoord.x + minimapOffset.x)
  544. .attr('y', this.viewpointCoord.y + minimapOffset.y)
  545. .attr('width', viewpointWidth)
  546. .attr('height', viewpointHeight);
  547. // Show/hide the minimap depending on the viewpoint area as fraction of the
  548. // whole minimap.
  549. const mapWidth = this.minimapSize.width;
  550. const mapHeight = this.minimapSize.height;
  551. const x = this.viewpointCoord.x;
  552. const y = this.viewpointCoord.y;
  553. const w = Math.min(Math.max(0, x + viewpointWidth), mapWidth) - Math.min(Math.max(0, x), mapWidth);
  554. const h = Math.min(Math.max(0, y + viewpointHeight), mapHeight) - Math.min(Math.max(0, y), mapHeight);
  555. const fracIntersect = (w * h) / (mapWidth * mapHeight);
  556. if (fracIntersect < FRAC_VIEWPOINT_AREA) {
  557. this.minimap.classList.remove('hidden');
  558. }
  559. else {
  560. this.minimap.classList.add('hidden');
  561. }
  562. }
  563. }
  564. /**
  565. * Use of this source code is governed by an MIT-style license that can be
  566. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  567. */
  568. class NzGraphMinimapComponent {
  569. elementRef;
  570. ngZone;
  571. minimap;
  572. constructor(elementRef, ngZone) {
  573. this.elementRef = elementRef;
  574. this.ngZone = ngZone;
  575. }
  576. ngOnDestroy() {
  577. this.minimap?.destroy();
  578. }
  579. init(containerEle, zoomBehavior) {
  580. const svgEle = containerEle.nativeElement.querySelector('svg');
  581. const zoomEle = containerEle.nativeElement.querySelector('svg > g');
  582. this.minimap = new Minimap(this.ngZone, svgEle, zoomEle, zoomBehavior, this.elementRef.nativeElement, 150, 0);
  583. }
  584. zoom(transform) {
  585. this.minimap?.zoom(transform);
  586. }
  587. update() {
  588. this.minimap?.update();
  589. }
  590. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzGraphMinimapComponent, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
  591. static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.2", type: NzGraphMinimapComponent, isStandalone: true, selector: "nz-graph-minimap", host: { properties: { "class.nz-graph-minimap": "true" } }, ngImport: i0, template: `
  592. <svg>
  593. <defs>
  594. <filter id="minimapDropShadow" x="-20%" y="-20%" width="150%" height="150%">
  595. <feOffset result="offOut" in="SourceGraphic" dx="1" dy="1"></feOffset>
  596. <feColorMatrix
  597. result="matrixOut"
  598. in="offOut"
  599. type="matrix"
  600. values="0.1 0 0 0 0 0 0.1 0 0 0 0 0 0.1 0 0 0 0 0 0.5 0"
  601. ></feColorMatrix>
  602. <feGaussianBlur result="blurOut" in="matrixOut" stdDeviation="2"></feGaussianBlur>
  603. <feBlend in="SourceGraphic" in2="blurOut" mode="normal"></feBlend>
  604. </filter>
  605. </defs>
  606. <rect></rect>
  607. </svg>
  608. <canvas class="viewport"></canvas>
  609. <!-- Additional canvas to use as buffer to avoid flickering between updates -->
  610. <canvas class="buffer"></canvas>
  611. `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
  612. }
  613. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzGraphMinimapComponent, decorators: [{
  614. type: Component,
  615. args: [{
  616. selector: 'nz-graph-minimap',
  617. template: `
  618. <svg>
  619. <defs>
  620. <filter id="minimapDropShadow" x="-20%" y="-20%" width="150%" height="150%">
  621. <feOffset result="offOut" in="SourceGraphic" dx="1" dy="1"></feOffset>
  622. <feColorMatrix
  623. result="matrixOut"
  624. in="offOut"
  625. type="matrix"
  626. values="0.1 0 0 0 0 0 0.1 0 0 0 0 0 0.1 0 0 0 0 0 0.5 0"
  627. ></feColorMatrix>
  628. <feGaussianBlur result="blurOut" in="matrixOut" stdDeviation="2"></feGaussianBlur>
  629. <feBlend in="SourceGraphic" in2="blurOut" mode="normal"></feBlend>
  630. </filter>
  631. </defs>
  632. <rect></rect>
  633. </svg>
  634. <canvas class="viewport"></canvas>
  635. <!-- Additional canvas to use as buffer to avoid flickering between updates -->
  636. <canvas class="buffer"></canvas>
  637. `,
  638. changeDetection: ChangeDetectionStrategy.OnPush,
  639. host: {
  640. '[class.nz-graph-minimap]': 'true'
  641. }
  642. }]
  643. }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.NgZone }] });
  644. /**
  645. * Use of this source code is governed by an MIT-style license that can be
  646. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  647. */
  648. /**
  649. * https://angular.io/errors/NG3003
  650. * An intermediate interface for {@link NzGraphComponent} & {@link NzGraphNodeComponent}
  651. */
  652. class NzGraph {
  653. }
  654. /**
  655. * Use of this source code is governed by an MIT-style license that can be
  656. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  657. */
  658. class NzGraphNodeComponent {
  659. ngZone;
  660. el;
  661. builder;
  662. renderer2;
  663. graphComponent;
  664. node;
  665. noAnimation;
  666. customTemplate;
  667. animationInfo = null;
  668. initialState = true;
  669. destroy$ = new Subject();
  670. animationPlayer = null;
  671. constructor(ngZone, el, builder, renderer2, graphComponent) {
  672. this.ngZone = ngZone;
  673. this.el = el;
  674. this.builder = builder;
  675. this.renderer2 = renderer2;
  676. this.graphComponent = graphComponent;
  677. }
  678. ngOnInit() {
  679. fromEventOutsideAngular(this.el.nativeElement, 'click')
  680. .pipe(filter(event => {
  681. event.preventDefault();
  682. return this.graphComponent.nzNodeClick.observers.length > 0;
  683. }), takeUntil(this.destroy$))
  684. .subscribe(() => {
  685. // Re-enter the Angular zone and run the change detection only if there're any `nzNodeClick` listeners,
  686. // e.g.: `<nz-graph (nzNodeClick)="..."></nz-graph>`.
  687. this.ngZone.run(() => this.graphComponent.nzNodeClick.emit(this.node));
  688. });
  689. }
  690. ngOnDestroy() {
  691. this.destroy$.next();
  692. }
  693. makeAnimation() {
  694. const cur = this.getAnimationInfo();
  695. if (this.animationPlayer) {
  696. this.animationPlayer.destroy();
  697. }
  698. let animationFactory;
  699. const pre = { ...this.animationInfo };
  700. if (this.initialState) {
  701. animationFactory = this.builder.build([
  702. style({ transform: `translate(${cur.x}px, ${cur.y}px)` }),
  703. query('g', [
  704. style({
  705. width: `${cur.width}px`,
  706. height: `${cur.height}px`
  707. })
  708. ])
  709. ]);
  710. this.initialState = false;
  711. }
  712. else {
  713. animationFactory = this.builder.build([
  714. style({ transform: `translate(${pre.x}px, ${pre.y}px)` }),
  715. query('g', [
  716. style({
  717. width: `${pre.width}px`,
  718. height: `${pre.height}px`
  719. })
  720. ]),
  721. group([
  722. query('g', [
  723. animate('150ms ease-out', style({
  724. width: `${cur.width}px`,
  725. height: `${cur.height}px`
  726. }))
  727. ]),
  728. animate('150ms ease-out', style({ transform: `translate(${cur.x}px, ${cur.y}px)` }))
  729. ])
  730. ]);
  731. }
  732. this.animationInfo = cur;
  733. this.animationPlayer = animationFactory.create(this.el.nativeElement);
  734. this.animationPlayer.play();
  735. const done$ = new Subject();
  736. this.animationPlayer.onDone(() => {
  737. // Need this for canvas for now.
  738. this.renderer2.setAttribute(this.el.nativeElement, 'transform', `translate(${cur.x}, ${cur.y})`);
  739. done$.next();
  740. done$.complete();
  741. });
  742. return done$.asObservable();
  743. }
  744. makeNoAnimation() {
  745. const cur = this.getAnimationInfo();
  746. // Need this for canvas for now.
  747. this.renderer2.setAttribute(this.el.nativeElement, 'transform', `translate(${cur.x}, ${cur.y})`);
  748. }
  749. getAnimationInfo() {
  750. const { x, y } = this.nodeTransform();
  751. return {
  752. width: this.node.width,
  753. height: this.node.height,
  754. x,
  755. y
  756. };
  757. }
  758. nodeTransform() {
  759. const x = this.computeCXPositionOfNodeShape() - this.node.width / 2;
  760. const y = this.node.y - this.node.height / 2;
  761. return { x, y };
  762. }
  763. computeCXPositionOfNodeShape() {
  764. if (this.node.expanded) {
  765. return this.node.x;
  766. }
  767. return this.node.x - this.node.width / 2 + this.node.coreBox.width / 2;
  768. }
  769. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzGraphNodeComponent, deps: [{ token: i0.NgZone }, { token: i0.ElementRef }, { token: i1.AnimationBuilder }, { token: i0.Renderer2 }, { token: NzGraph }], target: i0.ɵɵFactoryTarget.Component });
  770. static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.2", type: NzGraphNodeComponent, isStandalone: true, selector: "[nz-graph-node]", inputs: { node: "node", noAnimation: ["noAnimation", "noAnimation", booleanAttribute], customTemplate: "customTemplate" }, host: { properties: { "id": "node.id || node.name", "class.nz-graph-node-expanded": "node.expanded", "class.nz-graph-group-node": "node.type===0", "class.nz-graph-base-node": "node.type===1" } }, ngImport: i0, template: `
  771. <svg:g>
  772. @if (customTemplate) {
  773. <ng-container [ngTemplateOutlet]="customTemplate" [ngTemplateOutletContext]="{ $implicit: node }" />
  774. } @else {
  775. <svg:rect class="nz-graph-node-rect" [attr.width]="node.width" [attr.height]="node.height"></svg:rect>
  776. <svg:text x="10" y="20">{{ node.id || node.name }}</svg:text>
  777. }
  778. </svg:g>
  779. `, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
  780. }
  781. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzGraphNodeComponent, decorators: [{
  782. type: Component,
  783. args: [{
  784. selector: '[nz-graph-node]',
  785. template: `
  786. <svg:g>
  787. @if (customTemplate) {
  788. <ng-container [ngTemplateOutlet]="customTemplate" [ngTemplateOutletContext]="{ $implicit: node }" />
  789. } @else {
  790. <svg:rect class="nz-graph-node-rect" [attr.width]="node.width" [attr.height]="node.height"></svg:rect>
  791. <svg:text x="10" y="20">{{ node.id || node.name }}</svg:text>
  792. }
  793. </svg:g>
  794. `,
  795. changeDetection: ChangeDetectionStrategy.OnPush,
  796. host: {
  797. '[id]': 'node.id || node.name',
  798. '[class.nz-graph-node-expanded]': 'node.expanded',
  799. '[class.nz-graph-group-node]': 'node.type===0',
  800. '[class.nz-graph-base-node]': 'node.type===1'
  801. },
  802. imports: [NgTemplateOutlet]
  803. }]
  804. }], ctorParameters: () => [{ type: i0.NgZone }, { type: i0.ElementRef }, { type: i1.AnimationBuilder }, { type: i0.Renderer2 }, { type: NzGraph }], propDecorators: { node: [{
  805. type: Input
  806. }], noAnimation: [{
  807. type: Input,
  808. args: [{ transform: booleanAttribute }]
  809. }], customTemplate: [{
  810. type: Input
  811. }] } });
  812. /**
  813. * Use of this source code is governed by an MIT-style license that can be
  814. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  815. */
  816. class NzGraphNodeDirective {
  817. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzGraphNodeDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
  818. static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.2", type: NzGraphNodeDirective, isStandalone: true, selector: "[nzGraphNode]", exportAs: ["nzGraphNode"], ngImport: i0 });
  819. }
  820. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzGraphNodeDirective, decorators: [{
  821. type: Directive,
  822. args: [{
  823. selector: '[nzGraphNode]',
  824. exportAs: 'nzGraphNode'
  825. }]
  826. }] });
  827. /**
  828. * Use of this source code is governed by an MIT-style license that can be
  829. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  830. */
  831. /**
  832. * Calculate position and scale
  833. *
  834. * @param containerEle
  835. * @param targetEle
  836. * @param scale: if scale is set, skip calculate scale value
  837. */
  838. const calculateTransform = (containerEle, targetEle, scale) => {
  839. const containerEleSize = containerEle.getBoundingClientRect();
  840. const targetEleSize = targetEle.getBBox();
  841. if (!targetEleSize.width) {
  842. // There is no g element anymore.
  843. return null;
  844. }
  845. // TODO
  846. // leave some place when re-scale
  847. const scaleUnit = (containerEleSize.width - 48) / containerEleSize.width;
  848. const k = scale ||
  849. Math.min(containerEleSize.width / targetEleSize.width, containerEleSize.height / targetEleSize.height, 1) *
  850. scaleUnit;
  851. const x = (containerEleSize.width - targetEleSize.width * k) / 2;
  852. const y = (containerEleSize.height - targetEleSize.height * k) / 2;
  853. return {
  854. x,
  855. y,
  856. k
  857. };
  858. };
  859. /**
  860. * Use of this source code is governed by an MIT-style license that can be
  861. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  862. */
  863. class NzGraphZoomDirective {
  864. element;
  865. cdr;
  866. nzZoom;
  867. nzMinZoom = 0.1;
  868. nzMaxZoom = 10;
  869. nzTransformEvent = new EventEmitter();
  870. nzZoomChange = new EventEmitter();
  871. svgSelection;
  872. zoomBehavior;
  873. // TODO
  874. // Support svg element only now
  875. svgElement;
  876. gZoomElement;
  877. destroy$ = new Subject();
  878. constructor(element, cdr) {
  879. this.element = element;
  880. this.cdr = cdr;
  881. }
  882. ngAfterViewInit() {
  883. this.bind();
  884. }
  885. ngOnDestroy() {
  886. this.unbind();
  887. this.destroy$.next();
  888. this.destroy$.complete();
  889. }
  890. bind() {
  891. this.svgElement = this.element.nativeElement.querySelector('svg');
  892. this.gZoomElement = this.element.nativeElement.querySelector('svg > g');
  893. const { width, height } = this.element.nativeElement.getBoundingClientRect();
  894. this.svgSelection = transition()
  895. .selection()
  896. .select(() => this.svgElement);
  897. this.zoomBehavior = zoom()
  898. .extent([
  899. [0, 0],
  900. [width, height]
  901. ])
  902. .scaleExtent([this.nzMinZoom, this.nzMaxZoom])
  903. .on('zoom', e => {
  904. this.zoomed(e);
  905. });
  906. this.svgSelection.call(this.zoomBehavior, zoomIdentity.translate(0, 0).scale(this.nzZoom || 1));
  907. // Init with nzZoom
  908. this.reScale(0, this.nzZoom);
  909. }
  910. unbind() {
  911. // Destroy listener
  912. this.svgSelection?.interrupt().selectAll('*').interrupt();
  913. if (this.zoomBehavior) {
  914. this.zoomBehavior.on('end', null).on('zoom', null);
  915. }
  916. }
  917. // Methods
  918. fitCenter(duration = 0) {
  919. this.reScale(duration);
  920. }
  921. focus(id, duration = 0) {
  922. // Make sure this node is under SVG container
  923. if (!this.svgElement.getElementById(`${id}`)) {
  924. return;
  925. }
  926. const node = this.svgElement.getElementById(`${id}`);
  927. const svgRect = this.svgElement.getBoundingClientRect();
  928. const position = this.getRelativePositionInfo(node);
  929. const svgTransform = zoomTransform(this.svgElement);
  930. const centerX = (position.topLeft.x + position.bottomRight.x) / 2;
  931. const centerY = (position.topLeft.y + position.bottomRight.y) / 2;
  932. const dx = svgRect.left + svgRect.width / 2 - centerX;
  933. const dy = svgRect.top + svgRect.height / 2 - centerY;
  934. this.svgSelection
  935. .transition()
  936. .duration(duration)
  937. .call(this.zoomBehavior.translateBy, dx / svgTransform.k, dy / svgTransform.k);
  938. }
  939. /**
  940. * Handle zoom event
  941. *
  942. * @param transform
  943. */
  944. zoomed({ transform }) {
  945. const { x, y, k } = transform;
  946. // Update g element transform
  947. this.gZoomElement.setAttribute('transform', `translate(${x}, ${y})scale(${k})`);
  948. this.nzZoom = k;
  949. this.nzZoomChange.emit(this.nzZoom);
  950. this.nzTransformEvent.emit(transform);
  951. this.cdr.markForCheck();
  952. }
  953. /**
  954. * Scale with zoom and duration
  955. *
  956. * @param duration
  957. * @param scale
  958. * @private
  959. */
  960. reScale(duration, scale) {
  961. const transform = calculateTransform(this.svgElement, this.gZoomElement, scale);
  962. if (!transform) {
  963. return;
  964. }
  965. const { x, y, k } = transform;
  966. const zTransform = zoomIdentity.translate(x, y).scale(Math.max(k, this.nzMinZoom));
  967. this.svgSelection
  968. .transition()
  969. .duration(duration)
  970. .call(this.zoomBehavior.transform, zTransform)
  971. .on('end.fitted', () => {
  972. this.zoomBehavior.on('end.fitted', null);
  973. });
  974. }
  975. getRelativePositionInfo(node) {
  976. const nodeBox = node.getBBox();
  977. const nodeCtm = node.getScreenCTM();
  978. let pointTL = this.svgElement.createSVGPoint();
  979. let pointBR = this.svgElement.createSVGPoint();
  980. pointTL.x = nodeBox.x;
  981. pointTL.y = nodeBox.y;
  982. pointBR.x = nodeBox.x + nodeBox.width;
  983. pointBR.y = nodeBox.y + nodeBox.height;
  984. pointTL = pointTL.matrixTransform(nodeCtm);
  985. pointBR = pointBR.matrixTransform(nodeCtm);
  986. return {
  987. topLeft: pointTL,
  988. bottomRight: pointBR
  989. };
  990. }
  991. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzGraphZoomDirective, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive });
  992. static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "19.2.2", type: NzGraphZoomDirective, isStandalone: true, selector: "[nz-graph-zoom]", inputs: { nzZoom: ["nzZoom", "nzZoom", numberAttributeWithOneFallback], nzMinZoom: "nzMinZoom", nzMaxZoom: "nzMaxZoom" }, outputs: { nzTransformEvent: "nzTransformEvent", nzZoomChange: "nzZoomChange" }, exportAs: ["nzGraphZoom"], ngImport: i0 });
  993. }
  994. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzGraphZoomDirective, decorators: [{
  995. type: Directive,
  996. args: [{
  997. selector: '[nz-graph-zoom]',
  998. exportAs: 'nzGraphZoom'
  999. }]
  1000. }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }], propDecorators: { nzZoom: [{
  1001. type: Input,
  1002. args: [{ transform: numberAttributeWithOneFallback }]
  1003. }], nzMinZoom: [{
  1004. type: Input
  1005. }], nzMaxZoom: [{
  1006. type: Input
  1007. }], nzTransformEvent: [{
  1008. type: Output
  1009. }], nzZoomChange: [{
  1010. type: Output
  1011. }] } });
  1012. /**
  1013. * Use of this source code is governed by an MIT-style license that can be
  1014. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  1015. */
  1016. /** Checks whether an object is a data source. */
  1017. function isDataSource(value) {
  1018. // Check if the value is a DataSource by observing if it has a connect function. Cannot
  1019. // be checked as an `instanceof DataSource` since people could create their own sources
  1020. // that match the interface, but don't extend DataSource.
  1021. return value && typeof value.connect === 'function';
  1022. }
  1023. class NzGraphComponent {
  1024. cdr;
  1025. elementRef;
  1026. listOfNodeElement;
  1027. listOfNodeComponent;
  1028. nodeTemplate;
  1029. groupNodeTemplate;
  1030. customGraphEdgeTemplate;
  1031. /**
  1032. * Provides a stream containing the latest data array to render.
  1033. * Data source can be an observable of NzGraphData, or a NzGraphData to render.
  1034. */
  1035. nzGraphData;
  1036. nzRankDirection = 'LR';
  1037. nzGraphLayoutConfig;
  1038. nzAutoSize = false;
  1039. nzGraphInitialized = new EventEmitter();
  1040. nzGraphRendered = new EventEmitter();
  1041. nzNodeClick = new EventEmitter();
  1042. requestId = -1;
  1043. transformStyle = '';
  1044. graphRenderedSubject$ = new ReplaySubject(1);
  1045. renderInfo = { labelHeight: 0 };
  1046. mapOfNodeAttr = {};
  1047. mapOfEdgeAttr = {};
  1048. zoom = 1;
  1049. typedNodes = nzTypeDefinition();
  1050. dataSource;
  1051. layoutSetting = NZ_GRAPH_LAYOUT_SETTING;
  1052. /** Data subscription */
  1053. _dataSubscription;
  1054. destroy$ = new Subject();
  1055. edgeTrackByFun = (edge) => `${edge.v}-${edge.w}`;
  1056. subGraphTransform = (node) => {
  1057. const x = node.x - node.coreBox.width / 2.0;
  1058. const y = node.y - node.height / 2.0 + node.paddingTop;
  1059. return `translate(${x}, ${y})`;
  1060. };
  1061. $asNzGraphEdges = (data) => data;
  1062. coreTransform = (node) => `translate(0, ${node.parentNodeName ? node.labelHeight : 0})`;
  1063. noAnimation = inject(NzNoAnimationDirective, { host: true, optional: true });
  1064. nzGraphZoom = inject(NzGraphZoomDirective, { optional: true });
  1065. constructor(cdr, elementRef) {
  1066. this.cdr = cdr;
  1067. this.elementRef = elementRef;
  1068. }
  1069. ngOnInit() {
  1070. this.graphRenderedSubject$.pipe(take(1), takeUntil(this.destroy$)).subscribe(() => {
  1071. // Only zooming is not set, move graph to center
  1072. if (!this.nzGraphZoom) {
  1073. this.fitCenter();
  1074. }
  1075. this.nzGraphInitialized.emit(this);
  1076. });
  1077. }
  1078. ngOnChanges(changes) {
  1079. const { nzAutoFit, nzRankDirection, nzGraphData, nzGraphLayoutConfig } = changes;
  1080. if (nzGraphLayoutConfig) {
  1081. this.layoutSetting = this.mergeConfig(nzGraphLayoutConfig.currentValue);
  1082. }
  1083. if (nzGraphData) {
  1084. if (this.dataSource !== this.nzGraphData) {
  1085. this._switchDataSource(this.nzGraphData);
  1086. }
  1087. }
  1088. if ((nzAutoFit && !nzAutoFit.firstChange) || (nzRankDirection && !nzRankDirection.firstChange)) {
  1089. // Render graph
  1090. if (this.dataSource.dataSource) {
  1091. this.drawGraph(this.dataSource.dataSource, {
  1092. rankDirection: this.nzRankDirection,
  1093. expanded: this.dataSource.expansionModel.selected || []
  1094. }).then(() => {
  1095. this.cdr.markForCheck();
  1096. });
  1097. }
  1098. }
  1099. this.cdr.markForCheck();
  1100. }
  1101. ngAfterContentChecked() {
  1102. if (this.dataSource && !this._dataSubscription) {
  1103. this.observeRenderChanges();
  1104. }
  1105. }
  1106. ngOnDestroy() {
  1107. this.destroy$.next();
  1108. this.destroy$.complete();
  1109. if (this.dataSource && typeof this.dataSource.disconnect === 'function') {
  1110. this.dataSource.disconnect();
  1111. }
  1112. if (this._dataSubscription) {
  1113. this._dataSubscription.unsubscribe();
  1114. this._dataSubscription = null;
  1115. }
  1116. cancelRequestAnimationFrame(this.requestId);
  1117. }
  1118. /**
  1119. * Move graph to center and scale automatically
  1120. */
  1121. fitCenter() {
  1122. const { x, y, k } = calculateTransform(this.elementRef.nativeElement.querySelector('svg'), this.elementRef.nativeElement.querySelector('svg > g'));
  1123. if (k) {
  1124. this.zoom = k;
  1125. this.transformStyle = `translate(${x}, ${y})scale(${k})`;
  1126. }
  1127. this.cdr.markForCheck();
  1128. }
  1129. /**
  1130. * re-Draw graph
  1131. *
  1132. * @param data
  1133. * @param options
  1134. * @param needResize
  1135. */
  1136. drawGraph(data, options, needResize = false) {
  1137. return new Promise(resolve => {
  1138. this.requestId = requestAnimationFrame(() => {
  1139. const renderInfo = this.buildGraphInfo(data, options);
  1140. // TODO
  1141. // Need better performance
  1142. this.renderInfo = renderInfo;
  1143. this.cdr.markForCheck();
  1144. this.requestId = requestAnimationFrame(() => {
  1145. this.drawNodes(!this.noAnimation?.nzNoAnimation).then(() => {
  1146. // Update element
  1147. this.cdr.markForCheck();
  1148. if (needResize) {
  1149. this.resizeNodeSize().then(() => {
  1150. const dataSource = this.dataSource.dataSource;
  1151. this.drawGraph(dataSource, options, false).then(() => resolve());
  1152. });
  1153. }
  1154. else {
  1155. this.graphRenderedSubject$.next();
  1156. this.nzGraphRendered.emit(this);
  1157. resolve();
  1158. }
  1159. });
  1160. });
  1161. });
  1162. this.cdr.markForCheck();
  1163. });
  1164. }
  1165. /**
  1166. * Redraw all nodes
  1167. *
  1168. * @param animate
  1169. */
  1170. drawNodes(animate = true) {
  1171. return new Promise(resolve => {
  1172. if (animate) {
  1173. this.makeNodesAnimation().subscribe(() => {
  1174. resolve();
  1175. });
  1176. }
  1177. else {
  1178. this.listOfNodeComponent.map(node => {
  1179. node.makeNoAnimation();
  1180. });
  1181. resolve();
  1182. }
  1183. });
  1184. }
  1185. resizeNodeSize() {
  1186. return new Promise(resolve => {
  1187. const dataSource = this.dataSource.dataSource;
  1188. let scale = this.nzGraphZoom?.nzZoom || this.zoom || 1;
  1189. this.listOfNodeElement.forEach(nodeEle => {
  1190. const contentEle = nodeEle.nativeElement;
  1191. if (contentEle) {
  1192. let width;
  1193. let height;
  1194. // Check if foreignObject is set
  1195. const clientRect = contentEle.querySelector('foreignObject > :first-child')?.getBoundingClientRect();
  1196. if (clientRect) {
  1197. width = clientRect.width;
  1198. height = clientRect.height;
  1199. }
  1200. else {
  1201. const bBoxRect = contentEle.getBBox();
  1202. width = bBoxRect.width;
  1203. height = bBoxRect.height;
  1204. // getBBox will return actual value
  1205. scale = 1;
  1206. }
  1207. // Element id type is string
  1208. const node = dataSource.nodes.find(n => `${n.id}` === nodeEle.nativeElement.id);
  1209. if (node && width && height) {
  1210. node.height = height / scale;
  1211. node.width = width / scale;
  1212. }
  1213. }
  1214. });
  1215. resolve();
  1216. });
  1217. }
  1218. /**
  1219. * Switch to the provided data source by resetting the data and unsubscribing from the current
  1220. * render change subscription if one exists. If the data source is null, interpret this by
  1221. * clearing the node outlet. Otherwise start listening for new data.
  1222. */
  1223. _switchDataSource(dataSource) {
  1224. if (this.dataSource && typeof this.dataSource.disconnect === 'function') {
  1225. this.nzGraphData.disconnect();
  1226. }
  1227. if (this._dataSubscription) {
  1228. this._dataSubscription.unsubscribe();
  1229. this._dataSubscription = null;
  1230. }
  1231. this.dataSource = dataSource;
  1232. this.observeRenderChanges();
  1233. }
  1234. /** Set up a subscription for the data provided by the data source. */
  1235. observeRenderChanges() {
  1236. let dataStream;
  1237. let graphOptions = {
  1238. rankDirection: this.nzRankDirection
  1239. };
  1240. if (isDataSource(this.dataSource)) {
  1241. dataStream = this.dataSource.connect();
  1242. }
  1243. if (dataStream) {
  1244. this._dataSubscription = dataStream.pipe(takeUntil(this.destroy$)).subscribe(data => {
  1245. graphOptions = {
  1246. rankDirection: this.nzRankDirection,
  1247. expanded: this.nzGraphData.expansionModel.selected
  1248. };
  1249. this.drawGraph(data, graphOptions, this.nzAutoSize).then(() => {
  1250. this.cdr.detectChanges();
  1251. });
  1252. });
  1253. }
  1254. else {
  1255. throw Error(`A valid data source must be provided.`);
  1256. }
  1257. }
  1258. /**
  1259. * Get renderInfo and prepare some data
  1260. *
  1261. * @param data
  1262. * @param options
  1263. * @private
  1264. */
  1265. buildGraphInfo(data, options) {
  1266. this.parseInfo(data);
  1267. const renderInfo = buildGraph(data, options, this.layoutSetting);
  1268. const dig = (nodes) => {
  1269. nodes.forEach(node => {
  1270. const { x, y } = node;
  1271. node.xOffset = x;
  1272. node.yOffset = y;
  1273. if (node.type === 1 && this.mapOfNodeAttr.hasOwnProperty(node.name)) {
  1274. Object.assign(node, this.mapOfNodeAttr[node.name]);
  1275. }
  1276. else if (node.type === 0) {
  1277. node.edges.forEach(edge => {
  1278. if (this.mapOfEdgeAttr.hasOwnProperty(`${edge.v}-${edge.w}`)) {
  1279. Object.assign(edge, this.mapOfEdgeAttr[`${edge.v}-${edge.w}`]);
  1280. }
  1281. });
  1282. dig(node.nodes);
  1283. }
  1284. });
  1285. };
  1286. dig(renderInfo.nodes);
  1287. // Assign data to edges of root graph
  1288. renderInfo.edges.forEach(edge => {
  1289. if (this.mapOfEdgeAttr.hasOwnProperty(`${edge.v}-${edge.w}`)) {
  1290. Object.assign(edge, this.mapOfEdgeAttr[`${edge.v}-${edge.w}`]);
  1291. }
  1292. });
  1293. return renderInfo;
  1294. }
  1295. /**
  1296. * Play with animation
  1297. *
  1298. * @private
  1299. */
  1300. makeNodesAnimation() {
  1301. return forkJoin(this.listOfNodeComponent.map(node => node.makeAnimation())).pipe(finalize(() => {
  1302. this.cdr.detectChanges();
  1303. }));
  1304. }
  1305. parseInfo(data) {
  1306. data.nodes.forEach(n => {
  1307. this.mapOfNodeAttr[n.id] = n;
  1308. });
  1309. data.edges.forEach(e => {
  1310. this.mapOfEdgeAttr[`${e.v}-${e.w}`] = e;
  1311. });
  1312. }
  1313. /**
  1314. * Merge config with user inputs
  1315. *
  1316. * @param config
  1317. * @private
  1318. */
  1319. mergeConfig(config) {
  1320. const graphMeta = config?.layout || {};
  1321. const subSceneMeta = config?.subScene || {};
  1322. const defaultNodeMeta = config?.defaultNode || {};
  1323. const defaultCompoundNodeMeta = config?.defaultCompoundNode || {};
  1324. const bridge = NZ_GRAPH_LAYOUT_SETTING.nodeSize.bridge;
  1325. const graph = { meta: { ...NZ_GRAPH_LAYOUT_SETTING.graph.meta, ...graphMeta } };
  1326. const subScene = {
  1327. meta: { ...NZ_GRAPH_LAYOUT_SETTING.subScene.meta, ...subSceneMeta }
  1328. };
  1329. const nodeSize = {
  1330. meta: { ...NZ_GRAPH_LAYOUT_SETTING.nodeSize.meta, ...defaultCompoundNodeMeta },
  1331. node: { ...NZ_GRAPH_LAYOUT_SETTING.nodeSize.node, ...defaultNodeMeta },
  1332. bridge
  1333. };
  1334. return { graph, subScene, nodeSize };
  1335. }
  1336. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzGraphComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
  1337. static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.2", type: NzGraphComponent, isStandalone: true, selector: "nz-graph", inputs: { nzGraphData: "nzGraphData", nzRankDirection: "nzRankDirection", nzGraphLayoutConfig: "nzGraphLayoutConfig", nzAutoSize: ["nzAutoSize", "nzAutoSize", booleanAttribute] }, outputs: { nzGraphInitialized: "nzGraphInitialized", nzGraphRendered: "nzGraphRendered", nzNodeClick: "nzNodeClick" }, host: { properties: { "class.nz-graph": "true", "class.nz-graph-auto-size": "nzAutoSize" } }, providers: [{ provide: NzGraph, useExisting: forwardRef(() => NzGraphComponent) }], queries: [{ propertyName: "nodeTemplate", first: true, predicate: NzGraphNodeDirective, descendants: true, read: TemplateRef, static: true }, { propertyName: "groupNodeTemplate", first: true, predicate: NzGraphGroupNodeDirective, descendants: true, read: TemplateRef, static: true }, { propertyName: "customGraphEdgeTemplate", first: true, predicate: NzGraphEdgeDirective, descendants: true, read: TemplateRef, static: true }], viewQueries: [{ propertyName: "listOfNodeElement", predicate: NzGraphNodeComponent, descendants: true, read: ElementRef }, { propertyName: "listOfNodeComponent", predicate: NzGraphNodeComponent, descendants: true }], exportAs: ["nzGraph"], usesOnChanges: true, ngImport: i0, template: `
  1338. <ng-content></ng-content>
  1339. <svg width="100%" height="100%">
  1340. <svg:defs nz-graph-defs></svg:defs>
  1341. <svg:g [attr.transform]="transformStyle">
  1342. <ng-container
  1343. [ngTemplateOutlet]="groupTemplate"
  1344. [ngTemplateOutletContext]="{ renderNode: renderInfo, type: 'root' }"
  1345. ></ng-container>
  1346. </svg:g>
  1347. </svg>
  1348. <ng-template #groupTemplate let-renderNode="renderNode" let-type="type">
  1349. <svg:g [attr.transform]="type === 'sub' ? subGraphTransform(renderNode) : null">
  1350. <svg:g class="core" [attr.transform]="coreTransform(renderNode)">
  1351. <svg:g class="nz-graph-edges">
  1352. @for (edge of $asNzGraphEdges(renderNode.edges); track edgeTrackByFun(edge)) {
  1353. <g
  1354. class="nz-graph-edge"
  1355. nz-graph-edge
  1356. [edge]="edge"
  1357. [edgeType]="nzGraphLayoutConfig?.defaultEdge?.type"
  1358. [customTemplate]="customGraphEdgeTemplate"
  1359. ></g>
  1360. }
  1361. </svg:g>
  1362. <svg:g class="nz-graph-nodes">
  1363. @for (node of typedNodes(renderNode.nodes); track node.name) {
  1364. @if (node.type === 1) {
  1365. <g class="nz-graph-node" nz-graph-node [node]="node" [customTemplate]="nodeTemplate"></g>
  1366. }
  1367. @if (node.type === 0) {
  1368. <g class="nz-graph-node" nz-graph-node [node]="node" [customTemplate]="groupNodeTemplate"></g>
  1369. }
  1370. @if (node.expanded) {
  1371. <ng-container
  1372. [ngTemplateOutlet]="groupTemplate"
  1373. [ngTemplateOutletContext]="{ renderNode: node, type: 'sub' }"
  1374. />
  1375. }
  1376. }
  1377. </svg:g>
  1378. </svg:g>
  1379. </svg:g>
  1380. </ng-template>
  1381. `, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: NzGraphEdgeComponent, selector: "[nz-graph-edge]", inputs: ["edge", "edgeType", "customTemplate"] }, { kind: "component", type: NzGraphNodeComponent, selector: "[nz-graph-node]", inputs: ["node", "noAnimation", "customTemplate"] }, { kind: "component", type: NzGraphDefsComponent, selector: "svg:defs[nz-graph-defs]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
  1382. }
  1383. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzGraphComponent, decorators: [{
  1384. type: Component,
  1385. args: [{
  1386. changeDetection: ChangeDetectionStrategy.OnPush,
  1387. encapsulation: ViewEncapsulation.None,
  1388. selector: 'nz-graph',
  1389. exportAs: 'nzGraph',
  1390. providers: [{ provide: NzGraph, useExisting: forwardRef(() => NzGraphComponent) }],
  1391. template: `
  1392. <ng-content></ng-content>
  1393. <svg width="100%" height="100%">
  1394. <svg:defs nz-graph-defs></svg:defs>
  1395. <svg:g [attr.transform]="transformStyle">
  1396. <ng-container
  1397. [ngTemplateOutlet]="groupTemplate"
  1398. [ngTemplateOutletContext]="{ renderNode: renderInfo, type: 'root' }"
  1399. ></ng-container>
  1400. </svg:g>
  1401. </svg>
  1402. <ng-template #groupTemplate let-renderNode="renderNode" let-type="type">
  1403. <svg:g [attr.transform]="type === 'sub' ? subGraphTransform(renderNode) : null">
  1404. <svg:g class="core" [attr.transform]="coreTransform(renderNode)">
  1405. <svg:g class="nz-graph-edges">
  1406. @for (edge of $asNzGraphEdges(renderNode.edges); track edgeTrackByFun(edge)) {
  1407. <g
  1408. class="nz-graph-edge"
  1409. nz-graph-edge
  1410. [edge]="edge"
  1411. [edgeType]="nzGraphLayoutConfig?.defaultEdge?.type"
  1412. [customTemplate]="customGraphEdgeTemplate"
  1413. ></g>
  1414. }
  1415. </svg:g>
  1416. <svg:g class="nz-graph-nodes">
  1417. @for (node of typedNodes(renderNode.nodes); track node.name) {
  1418. @if (node.type === 1) {
  1419. <g class="nz-graph-node" nz-graph-node [node]="node" [customTemplate]="nodeTemplate"></g>
  1420. }
  1421. @if (node.type === 0) {
  1422. <g class="nz-graph-node" nz-graph-node [node]="node" [customTemplate]="groupNodeTemplate"></g>
  1423. }
  1424. @if (node.expanded) {
  1425. <ng-container
  1426. [ngTemplateOutlet]="groupTemplate"
  1427. [ngTemplateOutletContext]="{ renderNode: node, type: 'sub' }"
  1428. />
  1429. }
  1430. }
  1431. </svg:g>
  1432. </svg:g>
  1433. </svg:g>
  1434. </ng-template>
  1435. `,
  1436. host: {
  1437. '[class.nz-graph]': 'true',
  1438. '[class.nz-graph-auto-size]': 'nzAutoSize'
  1439. },
  1440. imports: [NgTemplateOutlet, NzGraphEdgeComponent, NzGraphNodeComponent, NzGraphDefsComponent]
  1441. }]
  1442. }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }], propDecorators: { listOfNodeElement: [{
  1443. type: ViewChildren,
  1444. args: [NzGraphNodeComponent, { read: ElementRef }]
  1445. }], listOfNodeComponent: [{
  1446. type: ViewChildren,
  1447. args: [NzGraphNodeComponent]
  1448. }], nodeTemplate: [{
  1449. type: ContentChild,
  1450. args: [NzGraphNodeDirective, { static: true, read: TemplateRef }]
  1451. }], groupNodeTemplate: [{
  1452. type: ContentChild,
  1453. args: [NzGraphGroupNodeDirective, { static: true, read: TemplateRef }]
  1454. }], customGraphEdgeTemplate: [{
  1455. type: ContentChild,
  1456. args: [NzGraphEdgeDirective, { static: true, read: TemplateRef }]
  1457. }], nzGraphData: [{
  1458. type: Input
  1459. }], nzRankDirection: [{
  1460. type: Input
  1461. }], nzGraphLayoutConfig: [{
  1462. type: Input
  1463. }], nzAutoSize: [{
  1464. type: Input,
  1465. args: [{ transform: booleanAttribute }]
  1466. }], nzGraphInitialized: [{
  1467. type: Output
  1468. }], nzGraphRendered: [{
  1469. type: Output
  1470. }], nzNodeClick: [{
  1471. type: Output
  1472. }] } });
  1473. /**
  1474. * Use of this source code is governed by an MIT-style license that can be
  1475. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  1476. */
  1477. class NzGraphModule {
  1478. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzGraphModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
  1479. static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.2", ngImport: i0, type: NzGraphModule, imports: [NzGraphComponent,
  1480. NzGraphMinimapComponent,
  1481. NzGraphDefsComponent,
  1482. NzGraphNodeDirective,
  1483. NzGraphGroupNodeDirective,
  1484. NzGraphZoomDirective,
  1485. NzGraphNodeComponent,
  1486. NzGraphEdgeComponent,
  1487. NzGraphEdgeDirective], exports: [NzGraphComponent,
  1488. NzGraphMinimapComponent,
  1489. NzGraphDefsComponent,
  1490. NzGraphNodeDirective,
  1491. NzGraphGroupNodeDirective,
  1492. NzGraphZoomDirective,
  1493. NzGraphNodeComponent,
  1494. NzGraphEdgeComponent,
  1495. NzGraphEdgeDirective] });
  1496. static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzGraphModule });
  1497. }
  1498. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzGraphModule, decorators: [{
  1499. type: NgModule,
  1500. args: [{
  1501. imports: [
  1502. NzGraphComponent,
  1503. NzGraphMinimapComponent,
  1504. NzGraphDefsComponent,
  1505. NzGraphNodeDirective,
  1506. NzGraphGroupNodeDirective,
  1507. NzGraphZoomDirective,
  1508. NzGraphNodeComponent,
  1509. NzGraphEdgeComponent,
  1510. NzGraphEdgeDirective
  1511. ],
  1512. exports: [
  1513. NzGraphComponent,
  1514. NzGraphMinimapComponent,
  1515. NzGraphDefsComponent,
  1516. NzGraphNodeDirective,
  1517. NzGraphGroupNodeDirective,
  1518. NzGraphZoomDirective,
  1519. NzGraphNodeComponent,
  1520. NzGraphEdgeComponent,
  1521. NzGraphEdgeDirective
  1522. ]
  1523. }]
  1524. }] });
  1525. /**
  1526. * Use of this source code is governed by an MIT-style license that can be
  1527. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  1528. */
  1529. /**
  1530. * Generated bundle index. Do not edit.
  1531. */
  1532. export { NZ_GRAPH_LAYOUT_SETTING, NzGraphComponent, NzGraphData, NzGraphDefsComponent, NzGraphEdgeComponent, NzGraphEdgeDirective, NzGraphEdgeType, NzGraphGroupNodeDirective, NzGraphMinimapComponent, NzGraphModule, NzGraphNodeComponent, NzGraphNodeDirective, NzGraphZoomDirective, isDataSource, nzTypeDefinition };
  1533. //# sourceMappingURL=ng-zorro-antd-graph.mjs.map