@yanqirenshi/d3.deployment 0.8.5 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/js/Rectum.js CHANGED
@@ -64,9 +64,13 @@ var Rectum = exports["default"] = /*#__PURE__*/function (_Colon) {
64
64
  value: function initCallbacks(params) {
65
65
  var callbacks = params && params.callbacks || {};
66
66
  var node = callbacks.node || {};
67
+ var edge = callbacks.edge || {};
67
68
  return {
68
69
  node: {
69
70
  click: node.click || null
71
+ },
72
+ edge: {
73
+ click: edge.click || null
70
74
  }
71
75
  };
72
76
  }
@@ -411,6 +415,7 @@ var Rectum = exports["default"] = /*#__PURE__*/function (_Colon) {
411
415
  }
412
416
  this.attachNodeDrag(place, data);
413
417
  this.attachNodeClick(place);
418
+ this.attachEdgeClick(place);
414
419
  }
415
420
  /**
416
421
  * ノードのクリック通知(callbacks.node.click)。
@@ -435,6 +440,75 @@ var Rectum = exports["default"] = /*#__PURE__*/function (_Colon) {
435
440
  callback(d._core, d);
436
441
  });
437
442
  }
443
+ /**
444
+ * エッジのクリック通知(callbacks.edge.click)。
445
+ * エッジ path のほか、両端のポート円からも同じエッジを通知する
446
+ * (細い線より円のほうが掴みやすい)。(core, edge) を渡す契約は
447
+ * node.click と同じ(core = 入力のエッジオブジェクトそのまま)。
448
+ */
449
+ }, {
450
+ key: "attachEdgeClick",
451
+ value: function attachEdgeClick(place) {
452
+ var _this5 = this;
453
+ var callback = this._callbacks.edge.click;
454
+ if (!callback) return;
455
+ place.selectAll('path.edge').style('cursor', 'pointer').on('click', function (event) {
456
+ // path の datum は線分データのため data-edge-id からエッジを引く
457
+ var el = event.currentTarget;
458
+ var id = el && el.getAttribute && el.getAttribute('data-edge-id');
459
+ var edge = _this5.findEdge(id);
460
+ if (!edge) return;
461
+ event.stopPropagation();
462
+ callback(edge._core, edge);
463
+ });
464
+ place.selectAll('circle.port').style('cursor', 'pointer').on('click', function (event, d) {
465
+ event.stopPropagation();
466
+ callback(d.edge._core, d.edge);
467
+ });
468
+ }
469
+ /** id(入力 id。DOM の data-edge-id は文字列)からエッジを引く。 */
470
+ }, {
471
+ key: "findEdge",
472
+ value: function findEdge(id) {
473
+ var data = this.data();
474
+ if (!data || id === null || id === undefined) return null;
475
+ return data.edges.ht[id] || data.edges.ht[Number(id)] || null;
476
+ }
477
+ /**
478
+ * エッジのポート位置(角度)を変更して再フィットし、DOM があれば
479
+ * その場で再描画する(remount 不要)。角度は入力と同じ規約
480
+ * (ノード中心から見て 0=真下・時計回り。90=左, 180=真上, 270=右)。
481
+ *
482
+ * @param {*} edge_id 対象エッジの id(入力の id)
483
+ * @param {object} positions { from?: 角度, to?: 角度 } 省略側は変更しない
484
+ */
485
+ }, {
486
+ key: "setEdgePorts",
487
+ value: function setEdgePorts(edge_id) {
488
+ var positions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
489
+ var edge = this.findEdge(edge_id);
490
+ if (!edge) return this;
491
+
492
+ // 入力(_core)の角度を更新する。fittingPort は _core を読むので
493
+ // そのまま再フィットでき、以後の再描画・remount でも維持される。
494
+ if (positions.from !== undefined && positions.from !== null) edge._core.from.position = positions.from;
495
+ if (positions.to !== undefined && positions.to !== null) edge._core.to.position = positions.to;
496
+ this.fittingPort(edge.from.port);
497
+ this.fittingPort(edge.to.port);
498
+ this.fittingEdge(edge);
499
+ var place = this.d3Element();
500
+ if (place) {
501
+ place.selectAll('circle.port').filter(function (d) {
502
+ return d === edge.from.port || d === edge.to.port;
503
+ }).attr('cx', function (d) {
504
+ return d.position.x;
505
+ }).attr('cy', function (d) {
506
+ return d.position.y;
507
+ });
508
+ this._painter.EDGE.redraw(place, edge);
509
+ }
510
+ return this;
511
+ }
438
512
  ///// ////////////////////////////////////////////////////////////////
439
513
  ///// Drag (grab + drag でノードを移動)
440
514
  ///// ////////////////////////////////////////////////////////////////
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yanqirenshi/d3.deployment",
3
- "version": "0.8.5",
3
+ "version": "0.9.0",
4
4
  "description": "See [Documents](https://yanqirenshi.github.io/D3.Deployment/)",
5
5
  "main": "dist/index.js",
6
6
  "directories": {
@@ -182,3 +182,43 @@ test('id 0 is a valid node reference in edges (same class as sitemap issue #11)'
182
182
  expect(typeof edge.from.position.x).toBe('number');
183
183
  expect(typeof edge.from.position.y).toBe('number');
184
184
  });
185
+
186
+ // issue #13: エッジのポート位置(角度)を描画後に変更する公開 API。
187
+ // setEdgePorts は _core の角度を更新してポートを再フィットする(DOM 不要でテスト可能)。
188
+ test('setEdgePorts refits ports to the new angles (issue #13)', () => {
189
+ const rectum = new Rectum({});
190
+ rectum.data(NESTED_SAMPLE());
191
+ const data = rectum.data();
192
+
193
+ const edge = data.edges.ht[100];
194
+ const node1 = data.nodes.ht[1];
195
+ const node2 = data.nodes.ht[2];
196
+
197
+ // 初期: from は角度 0(真下) → node 1 の下辺中央(マージン 8)
198
+ expect(edge.from.port.position.x).toBeCloseTo(node1._position.x + node1._size.w / 2, 0);
199
+ expect(edge.from.port.position.y).toBeCloseTo(node1._position.y + node1._size.h + 8, 0);
200
+
201
+ rectum.setEdgePorts(100, { from: 180, to: 90 });
202
+
203
+ // _core が更新され、from ポートは上辺中央へ、to ポートは左辺中央へ再フィット
204
+ expect(edge._core.from.position).toBe(180);
205
+ expect(edge._core.to.position).toBe(90);
206
+
207
+ expect(edge.from.port.position.x).toBeCloseTo(node1._position.x + node1._size.w / 2, 0);
208
+ expect(edge.from.port.position.y).toBeCloseTo(node1._position.y - 8, 0);
209
+
210
+ expect(edge.to.port.position.x).toBeCloseTo(node2._position.x - 8, 0);
211
+ expect(edge.to.port.position.y).toBeCloseTo(node2._position.y + node2._size.h / 2, 0);
212
+
213
+ // エッジ端点もポートに追従
214
+ expect(edge.from.position).toEqual(edge.from.port.position);
215
+ expect(edge.to.position).toEqual(edge.to.port.position);
216
+
217
+ // 片側のみの変更(from は 180 のまま)
218
+ rectum.setEdgePorts(100, { to: 270 });
219
+ expect(edge._core.from.position).toBe(180);
220
+ expect(edge.to.port.position.x).toBeCloseTo(node2._position.x + node2._size.w + 8, 0);
221
+
222
+ // 未知のエッジ id は無視される(例外なし)
223
+ expect(() => rectum.setEdgePorts(999, { from: 0 })).not.toThrow();
224
+ });