Skip to content

Запасные концы ​

Соединение, чьего блока нет в setBlocks(), пропускается. Это проблема, когда блок отсутствует лишь временно: строка свёрнутого узла дерева или строка, которую виртуализированный список ещё не отрисовал. Соединение не должно исчезать — оно должно идти к ближайшему видимому блоку, например к свёрнутому родителю.

Такие блоки конец перечисляет в fallback:

ts
{
  id: 'first>fullName',
  from: { blockId: 'user.name.first', fallback: ['user.name', 'user'] },
  to: { blockId: 'person.fullName' },
}

Правила ​

  • Если собственного блока конца нет среди зарегистрированных, вместо него берётся первый зарегистрированный блок из fallback. Элемент запасного списка — id блока или { blockId, portId? }.
  • Если собственный блок зарегистрирован, но его порт прокручен за пределы видимости (и clipToScrollParents равно 'pin' или 'hide'), берётся первый запасной блок, который виден, вместо прижатия линии к краю. Если не виден и никто из запасных, действует обычное прижатие или скрытие.
  • Если в цепочке нет ни одного зарегистрированного блока, соединение пропускается, как и раньше.
  • Конец, которому запасной не понадобился, рисуется точно так же, как без этого поля.

Состояние proxied ​

Соединение, использующее запасной конец, находится в состоянии proxied — чтобы вы могли показать его иначе: пунктиром, бледнее. Оно ложится поверх базового вида и под selected, highlight, hover и focus:

ts
lines: { proxied: { dashed: true, opacity: 0.55 } },
// или у одного соединения
style: { proxied: { color: '#9aa0b8' } },

proxied — «ведро» каждой группы, знающей о состояниях (lines, markers, ports, labels), как и hover.

Что сообщает движок ​

  • Событие layout кладёт в каждый ConnectionLayout поле proxied: { from?: boolean; to?: boolean }, если конец был перенесён.
  • getStats().proxied считает такие соединения.
  • Подписи и маркеры подчиняются обычным правилам; для запасного конца ничего отдельного не рисуется.

В Vue ​

Поле проходит через проп connections без изменений. Дерево, свёрнутые строки которого удаляются из DOM:

ts
function endpoint(side: 'source' | 'target', id: string) {
  return {
    blockId: `${side}:${id}`,
    fallback: ancestorsOf(id).map((parent) => `${side}:${parent}`),
  }
}

См. демо-страницу «Mapping» в playground репозитория.