From bffb8e47b766181e651f6b39031393b1cae05d27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=A1=D0=BE?= =?UTF-8?q?=D0=BB=D0=BE=D0=B2=D1=8C=D0=B5=D0=B2?= Date: Mon, 15 Jun 2026 14:38:34 +0300 Subject: [PATCH] =?UTF-8?q?fix(tgu-ui):=20=D0=B4=D0=B2=D1=83=D1=80=D1=83?= =?UTF-8?q?=D1=87=D0=B5=D0=B9=D0=BD=D1=8B=D0=B9=20=D1=81=D0=BB=D0=B0=D0=B9?= =?UTF-8?q?=D0=B4=D0=B5=D1=80=20=E2=80=94=20=D0=B2=D1=8B=D0=B1=D0=BE=D1=80?= =?UTF-8?q?=20=D0=BF=D0=BE=D0=BB=D0=B7=D1=83=D0=BD=D0=BA=D0=B0=20=D0=BF?= =?UTF-8?q?=D0=BE=20=D0=BD=D0=B0=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8E=20=D0=BF=D1=80=D0=B8=20=D0=BD=D0=B0=D0=BB=D0=BE?= =?UTF-8?q?=D0=B6=D0=B5=D0=BD=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit При наложении в крайней точке хват попадал на верхний ползунок to, который на правом краю заперт fromIndex и не уходит влево, а нижний from был недоступен. Теперь при fromIndex === toIndex управляемый ползунок выбирается по направлению движения (влево → from, вправо → to). Чинит и «Сутки» (SlotDaySelector), и «Витки» (MapPassSelector). --- .../features/tgu-editor/MapPassSelector.tsx | 21 +++++++++++++++---- .../features/tgu-slots/SlotDaySelector.tsx | 21 +++++++++++++++---- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/services/pcp-tgu-ui-service/src/features/tgu-editor/MapPassSelector.tsx b/services/pcp-tgu-ui-service/src/features/tgu-editor/MapPassSelector.tsx index a7eaaf3..e8ab98e 100644 --- a/services/pcp-tgu-ui-service/src/features/tgu-editor/MapPassSelector.tsx +++ b/services/pcp-tgu-ui-service/src/features/tgu-editor/MapPassSelector.tsx @@ -42,21 +42,34 @@ export function MapPassSelector({ passes, fromIndex, toIndex, onFromChange, onTo return Math.round(Math.max(0, Math.min(1, (clientX - rect.left) / rect.width)) * (n - 1)) + 1; }; - const makeHandlers = (isFrom: boolean) => ({ + // Какой ползунок реально тянем. При наложении (fromIndex === toIndex) хват попадает на верхний + // (to), но на правом краю он заперт fromIndex и не может уйти влево — поэтому при наложении + // выбираем ползунок по направлению движения: влево → from (открыть диапазон), вправо → to. + const dragRef = useRef<"from" | "to" | null>(null); + + const makeHandlers = (which: "from" | "to") => ({ onPointerDown(e: React.PointerEvent) { e.stopPropagation(); + dragRef.current = which; (e.currentTarget as HTMLDivElement).setPointerCapture(e.pointerId); }, onPointerMove(e: React.PointerEvent) { if (!(e.currentTarget as HTMLDivElement).hasPointerCapture(e.pointerId)) return; const idx = indexAt(e.clientX); - if (isFrom) { + let active = dragRef.current; + if (fromIndex === toIndex) { + if (idx < fromIndex) active = "from"; + else if (idx > toIndex) active = "to"; + dragRef.current = active; + } + if (active === "from") { onFromChange(Math.max(1, Math.min(idx, toIndex))); } else { onToChange(Math.min(n, Math.max(idx, fromIndex))); } }, onPointerUp(e: React.PointerEvent) { + dragRef.current = null; (e.currentTarget as HTMLDivElement).releasePointerCapture(e.pointerId); }, }); @@ -111,13 +124,13 @@ export function MapPassSelector({ passes, fromIndex, toIndex, onFromChange, onTo
{/* To handle */}
diff --git a/services/pcp-tgu-ui-service/src/features/tgu-slots/SlotDaySelector.tsx b/services/pcp-tgu-ui-service/src/features/tgu-slots/SlotDaySelector.tsx index 915616e..24c3269 100644 --- a/services/pcp-tgu-ui-service/src/features/tgu-slots/SlotDaySelector.tsx +++ b/services/pcp-tgu-ui-service/src/features/tgu-slots/SlotDaySelector.tsx @@ -37,21 +37,34 @@ export function SlotDaySelector({ days, fromIndex, toIndex, onFromChange, onToCh return Math.round(Math.max(0, Math.min(1, (clientX - rect.left) / rect.width)) * (n - 1)) + 1; }; - const makeHandlers = (isFrom: boolean) => ({ + // Какой ползунок реально тянем. При наложении (fromIndex === toIndex) хват попадает на верхний + // (to), но на правом краю он заперт fromIndex и не может уйти влево — поэтому при наложении + // выбираем ползунок по направлению движения: влево → from (открыть диапазон), вправо → to. + const dragRef = useRef<"from" | "to" | null>(null); + + const makeHandlers = (which: "from" | "to") => ({ onPointerDown(e: React.PointerEvent) { e.stopPropagation(); + dragRef.current = which; (e.currentTarget as HTMLDivElement).setPointerCapture(e.pointerId); }, onPointerMove(e: React.PointerEvent) { if (!(e.currentTarget as HTMLDivElement).hasPointerCapture(e.pointerId)) return; const idx = indexAt(e.clientX); - if (isFrom) { + let active = dragRef.current; + if (fromIndex === toIndex) { + if (idx < fromIndex) active = "from"; + else if (idx > toIndex) active = "to"; + dragRef.current = active; + } + if (active === "from") { onFromChange(Math.max(1, Math.min(idx, toIndex))); } else { onToChange(Math.min(n, Math.max(idx, fromIndex))); } }, onPointerUp(e: React.PointerEvent) { + dragRef.current = null; (e.currentTarget as HTMLDivElement).releasePointerCapture(e.pointerId); }, }); @@ -101,12 +114,12 @@ export function SlotDaySelector({ days, fromIndex, toIndex, onFromChange, onToCh