feat(tgu-ui): запрет выбора конфликтных слотов + прохождение без подсветки

- конфликтные слоты нельзя добавить в выбор под бронь (клик по строке,
  Shift-диапазон, выбор полосы на карте, «выбрать все») — жёсткая блокировка;
  снятие выбора не блокируется (конфликт считается только для невыбранных)
- слоты одной полосы между собой не конфликтуют (groupOf) — иначе нельзя было
  бы набрать полосу поштучным кликом
- чекбокс «Конфликты» теперь и гасит, и блокирует выбор; выкл. — выбирать любые
- переход на прохождение (◀/▶) больше не подсвечивает никакой слот: активная
  подсветка строки — только по явному клику; добавлена прокрутка к началу прохода
- повторный Shift+клик по тому же концу снимает выделение (таблица и карта)
This commit is contained in:
Дмитрий Соловьев
2026-06-17 14:07:03 +03:00
parent c402f376c5
commit 354730fb6c
7 changed files with 220 additions and 63 deletions
@@ -72,6 +72,32 @@ export function selectStripRange(
return next
}
/**
* Снимает выбор с диапазона полосы [fromKey..toKey] (в порядке времени). Зеркало selectStripRange:
* убирает ровно члены диапазона, не трогая остальной выбор. Нужно для повторного Shift+клика по тому
* же концу — он снимает выделенный диапазон. Если fromKey/toKey не из members — выбор не меняется.
*
* @param current Текущее множество выбранных ключей.
* @param members Ключи членов полосы в порядке времени.
* @param fromKey Ключ якоря (первый клик).
* @param toKey Ключ второго клика.
*/
export function deselectStripRange(
current: ReadonlySet<string>,
members: readonly string[],
fromKey: string,
toKey: string,
): Set<string> {
const next = new Set(current)
const from = members.indexOf(fromKey)
const to = members.indexOf(toKey)
if (from < 0 || to < 0) return next
const lo = Math.min(from, to)
const hi = Math.max(from, to)
for (let i = lo; i <= hi; i++) next.delete(members[i])
return next
}
/**
* Разбивает массив на чанки заданного размера (для чанкованной брони крупных наборов).
* @param items Исходный массив.