fix: разрешить перекрытия целей маркеров (#564)

Issue: #564
User-Visible: yes
This commit is contained in:
Sergey Matyunin
2026-09-14 02:57:50 +03:00
parent fcc6c747a3
commit 6de854a03d
59 changed files with 1105 additions and 491 deletions
+10 -2
View File
@@ -255,14 +255,22 @@ export const LOW_HEADROOM_WARNING_BYTES = 15_000;
* измеренный факт 288 236 → 288 399 Б gzip; упрощённый публичный контракт
* помощника оставляет в графе только реально используемое состояние. Новый
* центр даёт 701 Б сверху и 1 299 Б до нижней границы полосы.
*
* 2026-09-14, #564: потолок перецентрирован 289 100 → 290 900 без изменения
* общего бюджета. В initial View появился screen-space resolver плотных
* маркеров: 44 px spatial index, painted-capsule priority и pointer-owner latch
* для hover/click/long-press/drag. Основная реализация вынесена из карточки в
* отдельный модуль; механизм обязан быть синхронным на первом касании и потому
* не может жить в lazy editor graph. Измеренный факт 290 181 Б оставляет 719 Б
* сверху и 1 281 Б до нижней границы полосы.
*/
export const INITIAL_VIEW_GZIP_CEILING = 289_100;
export const INITIAL_VIEW_GZIP_CEILING = 290_900;
export const INITIAL_VIEW_CEILING_BAND = 2_000;
/**
* До какого потолка предупреждение о запасе погашено владельцем.
*
* `null` — не погашено, и это текущее состояние: запас 8 931 Б при пороге
* `null` — не погашено, и это текущее состояние: запас 10 885 Б при пороге
* 15 000, долг живёт в #367. Предупреждение, которое нельзя погасить, читается
* как выключенное, поэтому его можно погасить — одной строкой здесь, со
* ссылкой на решение. Признание привязано к ЗНАЧЕНИЮ потолка: как только
+21 -7
View File
@@ -110,6 +110,20 @@ const MUTANT_DEFINITIONS = [
replace: " : false ? 'absent'",
}],
},
{
id: 'dense-device-hit-falls-back-to-input-order',
guard: 'npx tsc -p tsconfig.test.json && node scripts/fix-test-build.mjs '
+ '&& node --test test/device-hit-owner.test.mjs',
because: '#564: при перекрытии целей владелец выбирается по экранной геометрии, а не '
+ 'по порядку DOM/массива; иначе сосед снова крадёт hover, click и drag',
patches: [{
file: 'src/device-hit-owner.ts',
find: ' if (distance < bestDistance - EPSILON\n'
+ ' || (Math.abs(distance - bestDistance) <= EPSILON\n'
+ ' && (best === null || candidate.id < best.id))) {',
replace: ' if (best === null) {',
}],
},
{
id: 'radar-sources-compared-as-text',
guard: 'node --test --test-name-pattern="#567" test/radar-editor.test.mjs',
@@ -5555,8 +5569,8 @@ const MUTANT_DEFINITIONS = [
+ 'which makes an offline device look live',
patches: [{
file: 'src/styles/devices.styles.ts',
find: '.dev:not(.unavail):hover {',
replace: '.dev.unavail:hover {',
find: '.dev:not(.unavail)[data-hp-device-hover] {',
replace: '.dev.unavail[data-hp-device-hover] {',
}],
},
{
@@ -5937,8 +5951,8 @@ const MUTANT_DEFINITIONS = [
+ 'has already been cleared',
patches: [{
file: 'src/styles/devices.styles.ts',
find: ' :host([data-pointer-hover]) .dev:not(.unavail):hover {',
replace: ' .dev:not(.unavail):hover {',
find: ' :host([data-pointer-hover]) .dev:not(.unavail)[data-hp-device-hover] {',
replace: ' .dev:not(.unavail)[data-hp-device-hover] {',
}],
},
{
@@ -7336,12 +7350,12 @@ const MUTANT_DEFINITIONS = [
{
id: 'zigbee-topology-hovered-endpoint-elevation-removed',
guard: 'node demo/smoke_zigbee_topology_hover.mjs',
because: 'a real CSS :hover has higher specificity than the base endpoint rule; the source '
because: 'semantic device hover has higher specificity than the base endpoint rule; the source '
+ 'must still remain above its active topology line (#464 AC1, code-review r1)',
patches: [{
file: 'src/styles/devices.styles.ts',
find: ':host([data-pointer-hover]) .dev[data-hp-zigbee-topology-endpoint]:hover { z-index: 8; }',
replace: ':host([data-pointer-hover]) .dev[data-hp-zigbee-topology-endpoint]:hover { z-index: 1; }',
find: ':host([data-pointer-hover]) .dev[data-hp-zigbee-topology-endpoint][data-hp-device-hover] { z-index: 8; }',
replace: ':host([data-pointer-hover]) .dev[data-hp-zigbee-topology-endpoint][data-hp-device-hover] { z-index: 1; }',
}],
},
{