mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-02 21:01:21 +00:00
File diff suppressed because one or more lines are too long
@@ -0,0 +1,152 @@
|
||||
// #203: `show_names:false` means no permanent room labels in every read-only
|
||||
// renderer. Plan keeps its editor-only card and saving never discards layout.
|
||||
import { launch, checkAll, finish } from './serve.mjs';
|
||||
|
||||
const { page, browser } = await launch({ width: 1000, height: 850 });
|
||||
const out = await page.evaluate(async () => {
|
||||
const card = window.__card;
|
||||
const root = (node = card) => node.renderRoot || node.shadowRoot;
|
||||
const frame = () => new Promise((done) => requestAnimationFrame(() => requestAnimationFrame(done)));
|
||||
const settle = async () => { await card.updateComplete; await frame(); };
|
||||
const waitMode = async () => {
|
||||
await settle();
|
||||
while (card._modeTransitionBusy) await frame();
|
||||
};
|
||||
const labels = (node = card) => root(node).querySelectorAll('[data-hp="room-label"]');
|
||||
const htmlLabels = (node = card) => root(node).querySelectorAll('div.roomlabel[data-hp="room-label"]');
|
||||
const svgLabels = (node = card) => root(node).querySelectorAll('text.rlabel[data-hp="room-label"]');
|
||||
|
||||
card._setMode('view');
|
||||
await waitMode();
|
||||
const space = card._serverCfg.spaces.find((item) => item.id === card._space);
|
||||
delete space.plan_url;
|
||||
delete space.plan_aspect;
|
||||
const room = space.rooms.find((item) => item.name && item.id && item.area)
|
||||
|| space.rooms.find((item) => item.name && item.id);
|
||||
if (!room) throw new Error('fixture has no named room');
|
||||
space.settings = {
|
||||
...(space.settings || {}), show_borders: true, show_names: true,
|
||||
label_temp: true, label_hum: true, label_lqi: true, label_light: true,
|
||||
};
|
||||
const layoutKey = `rl_${room.id}`;
|
||||
card._layout[layoutKey] = { s: space.id, x: 0.23, y: 0.31, k: 1.6 };
|
||||
card._cfgEpoch++;
|
||||
card._regSignature = '';
|
||||
card.requestUpdate();
|
||||
await settle();
|
||||
|
||||
const first = root().querySelector(`[data-hp="room-label"][data-id="${room.id}"]`);
|
||||
const savedLayout = JSON.stringify(card._layout[layoutKey]);
|
||||
const trueState = {
|
||||
oneHtmlPerNamedRoom: htmlLabels().length === space.rooms.filter((item) => item.name).length,
|
||||
noLegacySvg: svgLabels().length === 0,
|
||||
savedScaleApplied: first?.getAttribute('style')?.includes('--rl-scale:1.6') === true,
|
||||
areaIconKept: !room.area || !!first?.querySelector('.rlgo'),
|
||||
};
|
||||
|
||||
// Cancel: the live preview follows the pending false, but persisted config
|
||||
// and the room-label layout return untouched when the dialog is dismissed.
|
||||
card._openSpaceDialog('edit', space.id);
|
||||
card._spaceDialog = { ...card._spaceDialog, showNames: false };
|
||||
card.requestUpdate();
|
||||
await settle();
|
||||
const livePreviewHidesAll = labels().length === 0;
|
||||
card._spaceDialog = null;
|
||||
card.requestUpdate();
|
||||
await settle();
|
||||
const cancelRestoresTrue = space.settings.show_names === true && htmlLabels().length > 0
|
||||
&& JSON.stringify(card._layout[layoutKey]) === savedLayout;
|
||||
|
||||
// Save + reopen: exercise the real existing-space persistence path.
|
||||
card._openSpaceDialog('edit', space.id);
|
||||
card._spaceDialog = { ...card._spaceDialog, showNames: false };
|
||||
await card._saveSpaceDialog();
|
||||
await settle();
|
||||
card._openSpaceDialog('edit', space.id);
|
||||
const reopenReadsFalse = card._spaceDialog?.showNames === false
|
||||
&& space.settings.show_names === false;
|
||||
card._spaceDialog = null;
|
||||
card.requestUpdate();
|
||||
await settle();
|
||||
|
||||
const flatFalseHasNoLabels = labels().length === 0
|
||||
&& htmlLabels().length === 0 && svgLabels().length === 0;
|
||||
|
||||
card._setMode('plan');
|
||||
await waitMode();
|
||||
const planFalseKeepsEditorCard = htmlLabels().length > 0
|
||||
&& svgLabels().length === 0 && !!root().querySelector('.rlgearbtn');
|
||||
card._setMode('view');
|
||||
await waitMode();
|
||||
const viewAfterPlanStillHidden = labels().length === 0;
|
||||
|
||||
// The Labs registry flag is intentionally expired; use the same dormant
|
||||
// renderer fixture hook as the canonical Stage 2 smokes.
|
||||
const active = Object.freeze(['iso']);
|
||||
card._onLabsSnapshot({ active, space: '' });
|
||||
window.__hpLabs = active;
|
||||
await settle();
|
||||
card._setProjection('iso');
|
||||
await settle();
|
||||
const isoFalseHasNoLabels = !!root().querySelector('[data-hp="iso-walls"]')
|
||||
&& labels().length === 0;
|
||||
card._setProjection('flat');
|
||||
await settle();
|
||||
|
||||
await customElements.whenDefined('houseplan-space-card');
|
||||
const cfgFalse = structuredClone(card._serverCfg);
|
||||
const layout = structuredClone(card._layout);
|
||||
const staticHass = {
|
||||
...card.hass,
|
||||
callWS: async (message) => {
|
||||
if (message.type === 'houseplan/config/get') return { config: cfgFalse, rev: 1 };
|
||||
if (message.type === 'houseplan/layout/get') return { layout, rev: 1 };
|
||||
return { ok: true };
|
||||
},
|
||||
};
|
||||
const host = document.createElement('div');
|
||||
document.body.appendChild(host);
|
||||
const compact = document.createElement('houseplan-space-card');
|
||||
compact.setConfig({ type: 'custom:houseplan-space-card', space: space.id, show_button: false });
|
||||
compact.hass = staticHass;
|
||||
host.appendChild(compact);
|
||||
const deadline = Date.now() + 6000;
|
||||
while (!root(compact)?.querySelector('.hp-static-stage') && Date.now() < deadline) {
|
||||
await new Promise((done) => setTimeout(done, 60));
|
||||
}
|
||||
await compact.updateComplete;
|
||||
const compactFalseHasNoLabels = labels(compact).length === 0
|
||||
&& htmlLabels(compact).length === 0 && svgLabels(compact).length === 0;
|
||||
|
||||
// Turning names back on restores the existing HTML card and saved layout.
|
||||
space.settings.show_names = true;
|
||||
card._cfgEpoch++;
|
||||
card.requestUpdate();
|
||||
await settle();
|
||||
const restored = root().querySelector(`[data-hp="room-label"][data-id="${room.id}"]`);
|
||||
const trueRestoresExistingCard = !!restored
|
||||
&& restored.tagName.toLowerCase() === 'div'
|
||||
&& restored.getAttribute('style')?.includes('--rl-scale:1.6') === true
|
||||
&& JSON.stringify(card._layout[layoutKey]) === savedLayout;
|
||||
|
||||
host.remove();
|
||||
card._onLabsSnapshot({ active: Object.freeze([]), space: '' });
|
||||
window.__hpLabs = Object.freeze([]);
|
||||
await settle();
|
||||
|
||||
return {
|
||||
...trueState,
|
||||
livePreviewHidesAll,
|
||||
cancelRestoresTrue,
|
||||
reopenReadsFalse,
|
||||
flatFalseHasNoLabels,
|
||||
planFalseKeepsEditorCard,
|
||||
viewAfterPlanStillHidden,
|
||||
isoFalseHasNoLabels,
|
||||
compactFalseHasNoLabels,
|
||||
trueRestoresExistingCard,
|
||||
};
|
||||
});
|
||||
|
||||
checkAll(out);
|
||||
await finish(browser, out);
|
||||
@@ -3,7 +3,7 @@
|
||||
// НАХОДЯТСЯ через querySelector — ровно так, как их будет искать чужой CSS.
|
||||
// 1) устройство: data-hp="device" + data-id + data-entity + data-area;
|
||||
// 2) комната: data-hp="room" + data-id + data-area;
|
||||
// 3) подпись комнаты: data-hp="room-label" + data-id (и в SVG, и в HTML-карточке);
|
||||
// 3) видимая подпись комнаты: data-hp="room-label" + data-id на HTML-карточке;
|
||||
// 4) проём: data-hp="opening" + data-id + data-kind (door/window/gate);
|
||||
// 5) декор: data-hp="decor" + data-id + data-kind (line/rect/ellipse/text);
|
||||
// 6) вкладка пространства: data-hp="space-tab" + data-id;
|
||||
@@ -50,8 +50,8 @@ const res = await page.evaluate(async () => {
|
||||
out.roomIsAnSvgShape = !!kitchen && ['polygon', 'rect', 'path'].includes(kitchen.tagName.toLowerCase());
|
||||
|
||||
// ============ 3. подписи комнат ============
|
||||
// одно имя — две разные реализации: <text> в SVG на плане без подложки и
|
||||
// HTML-карточка, когда включены «имена на плане». Хук на обеих один и тот же.
|
||||
// #203: false означает отсутствие подписи, а не вторую SVG-реализацию.
|
||||
// При true единственный публичный hook живёт на HTML-карточке.
|
||||
const disp = c._curSpaceCfg.settings || (c._curSpaceCfg.settings = {});
|
||||
const wasNames = disp.show_names;
|
||||
const planUrl = c._curSpaceCfg.plan_url;
|
||||
@@ -60,11 +60,8 @@ const res = await page.evaluate(async () => {
|
||||
await c.updateComplete; await sleep(60); await c.updateComplete;
|
||||
};
|
||||
delete c._curSpaceCfg.plan_url; disp.show_names = false; await redraw();
|
||||
const svgLabels = qa('text.rlabel[data-hp="room-label"]');
|
||||
out.svgRoomLabelHooked = svgLabels.length > 0
|
||||
&& svgLabels.every((e) => !!e.getAttribute('data-id'));
|
||||
out.svgRoomLabelFoundById = !!q('text[data-hp="room-label"][data-id="r1"]');
|
||||
out.svgRoomLabelHasArea = q('text[data-hp="room-label"][data-id="r1"]')?.getAttribute('data-area') === 'living_room';
|
||||
out.hiddenRoomLabelsAreAbsent = qa('[data-hp="room-label"]').length === 0
|
||||
&& qa('text.rlabel').length === 0;
|
||||
c._curSpaceCfg.plan_url = planUrl; disp.show_names = true; await redraw();
|
||||
const htmlLabel = q('div.roomlabel[data-hp="room-label"][data-id="r2"]');
|
||||
out.htmlRoomLabelHooked = !!htmlLabel;
|
||||
|
||||
File diff suppressed because one or more lines are too long
Vendored
+25
-39
File diff suppressed because one or more lines are too long
@@ -2,6 +2,13 @@
|
||||
|
||||
## v1.65.0-beta.4 — 2026-08-19
|
||||
|
||||
- Turning off **Show names** now removes room names completely in View, kiosk,
|
||||
the static card and hidden isometric mode, while Plan still exposes the
|
||||
existing draggable card for positioning. Re-enabling names restores its
|
||||
saved layout. **Breaking styling-hook change:** the fallback SVG
|
||||
`text.rlabel` / `.rlabel` public hook has been removed; enabled room names
|
||||
use `[data-hp="room-label"].roomlabel`
|
||||
([#203](https://github.com/Matysh/houseplan-card/issues/203)).
|
||||
- Closing a virtual room boundary now inherits the real thickness of an
|
||||
adjacent wall even when another room splits that saved wall into smaller
|
||||
atomic stretches. A 20/22 cm wall therefore no longer receives an accidental
|
||||
|
||||
@@ -8,6 +8,14 @@
|
||||
|
||||
## v1.65.0-beta.4 — 2026-08-19
|
||||
|
||||
- Выключение **«Показывать названия»** теперь полностью убирает названия комнат
|
||||
из Просмотра, киоска, статической карточки и скрытой изометрии, а редактор
|
||||
Плана по-прежнему временно показывает существующую карточку для настройки
|
||||
позиции. Повторное включение восстанавливает сохранённую компоновку.
|
||||
**Несовместимое изменение styling-hook:** публичный резервный SVG-хук
|
||||
`text.rlabel` / `.rlabel` удалён; включённые названия используют
|
||||
`[data-hp="room-label"].roomlabel`
|
||||
([#203](https://github.com/Matysh/houseplan-card/issues/203)).
|
||||
- При закрытии виртуальной границы теперь наследуется реальная толщина соседней
|
||||
стены, даже если другая комната разделила сохранённую стену на несколько
|
||||
атомарных участков. Поэтому на стене 20/22 см больше не появляется случайная
|
||||
|
||||
@@ -92,7 +92,6 @@ Everything in this table is **public API**.
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Device marker | `div` (HTML, marker layer) | `device` | `data-id` = marker/device id, `data-entity` = primary entity id, `data-area` = area id, `data-binding-status` = `active` \| `ha-disabled` \| `orphaned` \| `unverified`, `data-disabled-reason` = `device` \| `entity` \| `all-entities` when applicable | `.dev` |
|
||||
| Room shape | `polygon` / `rect` / `path` (SVG) | `room` | `data-id` = room id, `data-area` = area id | `.room` |
|
||||
| Room name (no metrics) | `text` (SVG) | `room-label` | `data-id` = room id, `data-area` | `.rlabel` |
|
||||
| Room card (name + metrics) | `div` (HTML, marker layer) | `room-label` | `data-id` = room id, `data-area` | `.roomlabel` |
|
||||
| Door / window / gate | `g` (SVG) | `opening` | `data-id` = opening id, `data-kind` = `door` \| `window` \| `gate` | `.opening` |
|
||||
| Coloured tunnel inside a thick opening | `path` / `g` (SVG) | `opening-tunnel` | `data-id` = opening id, `data-kind` = `door` \| `window` \| `gate` | `.opening-tunnel` |
|
||||
@@ -132,6 +131,13 @@ usually wants:
|
||||
Inside a room card: `.rlname` (the name) and `.rlmetrics` / `.rlm` (the
|
||||
metric row and one metric in it).
|
||||
|
||||
**Breaking hook change in #203.** The former SVG fallback
|
||||
`text.rlabel[data-hp="room-label"]` has been removed. A space with
|
||||
`show_names: false` now emits no permanent room-label element at all, as the
|
||||
setting promises. Target the HTML room-card hook
|
||||
`[data-hp="room-label"].roomlabel` when room names are enabled. Plan editor
|
||||
temporarily renders the same HTML card so it can still be positioned.
|
||||
|
||||
### 3.2 Public state classes
|
||||
|
||||
These are set on `.dev` and describe **live state**, so a rule may key off
|
||||
|
||||
+16
-2
@@ -2081,7 +2081,7 @@ require hands on real hardware — they remain for the human pass.
|
||||
carries `data-hp="device"`, `data-id`, `data-entity` and `data-area`; a
|
||||
room `data-hp="room"` + `data-id` + `data-area`; a door/window/gate
|
||||
`data-hp="opening"` + `data-kind`; a decor shape `data-hp="decor"` +
|
||||
`data-kind`; a room caption `data-hp="room-label"`; a floor tab
|
||||
`data-kind`; a visible room card `data-hp="room-label"`; a floor tab
|
||||
`data-hp="space-tab"`. The ids are the ones in your config, not DOM
|
||||
positions — they survive a reload [auto: smoke_styling_hooks]
|
||||
- [ ] **Absent is absent**: a virtual marker has NO `data-entity` at all, and a
|
||||
@@ -2092,7 +2092,7 @@ require hands on real hardware — they remain for the human pass.
|
||||
signal badges disappear and nothing else moves. Then target one marker by
|
||||
`[data-entity="…"]` and confirm it is the only one affected [manual]
|
||||
- [ ] **The static card carries the same hooks**: a `houseplan-space-card`
|
||||
has `data-hp` on its rooms, room labels and markers (it draws no openings
|
||||
has `data-hp` on its rooms, visible room labels and markers (it draws no openings
|
||||
and no decor, so those are simply absent), and it needs its OWN card-mod
|
||||
block — it is a different card with its own shadow root
|
||||
[auto: smoke_styling_hooks]
|
||||
@@ -2359,6 +2359,20 @@ require hands on real hardware — they remain for the human pass.
|
||||
|
||||
## Hiding layers: decor, openings, virtual walls (docs/UX-MODES.md, dev, unreleased)
|
||||
|
||||
- [ ] **Room names have one literal off state (#203)**: disable «Показывать
|
||||
названия» in the live space dialog, save and reopen it. Full View, kiosk,
|
||||
hidden isometric and `houseplan-space-card` contain no
|
||||
`[data-hp="room-label"]` and no legacy `text.rlabel`. Plan temporarily
|
||||
shows the same draggable HTML card and gear; returning to View hides it.
|
||||
Cancel restores the previous setting, while re-enabling names restores
|
||||
the saved card position and area icon
|
||||
[auto: `smoke_hide_room_names`, `smoke_styling_hooks`].
|
||||
- [ ] **Each renderer can fail independently**: restoring the old full-card SVG
|
||||
fallback, compact-card SVG fallback or hidden-isometric override makes
|
||||
the dedicated smoke red
|
||||
[mutation: `hidden-room-names-full-svg-fallback`,
|
||||
`hidden-room-names-compact-svg-fallback`,
|
||||
`hidden-room-names-iso-override`].
|
||||
- [ ] **«Скрыть декоративный слой»** (owner 2026-08-05): a space with lines,
|
||||
labels or furniture on it → space settings → Display → tick the box, save.
|
||||
The plan loses all of it, in View, in the Plan editor and in the Device
|
||||
|
||||
@@ -268,7 +268,7 @@ desktop: для точного рисования, Resize, модификато
|
||||
|---|---|---|
|
||||
| Масштаб | Сантиметров на клетку | Переводит сетку в реальные размеры и площади; начальное значение 5 см |
|
||||
| Отображение | Всегда показывать границы | Рисует контуры комнат в просмотре |
|
||||
| Отображение | Показывать названия | Рисует карточки/названия комнат; их можно двигать в редакторе плана |
|
||||
| Отображение | Показывать названия | Рисует карточки комнат в Просмотре, киоске и статической карточке; при выключении не оставляет упрощённых подписей |
|
||||
| Отображение | Показывать LQI | Переопределяет базовую настройку карточки для этого пространства |
|
||||
| Отображение | Скрыть декоративный слой | Не рисует линии, фигуры, текст и мебель в просмотре; в редакторе подложки они остаются видимыми |
|
||||
| Отображение | Скрыть проёмы | Скрывает только символы дверей, окон и ворот; свет, солнечные лучи и датчики проёмов продолжают работать |
|
||||
@@ -277,6 +277,10 @@ desktop: для точного рисования, Resize, модификато
|
||||
|
||||
Карточка комнаты остаётся частью плана: её можно перемещать и масштабировать в
|
||||
редакторе, а в просмотре она собирает только включённые метрики.
|
||||
Если «Показывать названия» выключено, редактор Плана временно показывает
|
||||
карточку только для настройки её позиции. После возврата в Просмотр она снова
|
||||
исчезает; сохранённая позиция не теряется и используется при повторном
|
||||
включении названий.
|
||||
|
||||

|
||||
| Стиль | Цвет и прозрачность | Общий цвет границ и названий |
|
||||
|
||||
+10
-3
@@ -111,7 +111,7 @@ Header in View: space tabs, device count, zoom cluster. Nothing else.
|
||||
|
||||
### What a space may choose not to draw (2026-08-05)
|
||||
|
||||
Three switches in the space's Display section decide how much of the plan is
|
||||
Four switches in the space's Display section decide how much of the plan is
|
||||
inked. All of them are **display only** — nothing is deleted, nothing changes
|
||||
meaning, and each layer stays visible in the editor that owns it, because a
|
||||
layer you cannot see is a layer you cannot edit.
|
||||
@@ -119,6 +119,7 @@ layer you cannot see is a layer you cannot edit.
|
||||
| Setting | Off (default) | On | Always drawn in |
|
||||
|---|---|---|---|
|
||||
| `show_borders` — «Всегда отображать границы комнат» | in View, borders and dashed **virtual walls** are hidden | both are drawn | room borders: Plan; virtual walls: all editors |
|
||||
| `show_names` — «Показывать названия» | no room name/card is drawn in View, kiosk or the static card | the HTML room card is drawn | Plan, for positioning only |
|
||||
| `hide_decor` — «Скрыть декоративный слой» | decor is drawn | lines, shapes, labels and furniture are hidden | the Background editor |
|
||||
| `hide_openings` — «Скрыть проёмы» | doors, windows and gates are drawn | their symbols are hidden | the Plan editor |
|
||||
|
||||
@@ -127,6 +128,11 @@ layer you cannot see is a layer you cannot edit.
|
||||
only walls were a few floating dashed stretches. Every editor deliberately
|
||||
shows them regardless of the switch: hiding geometry while editing a plan,
|
||||
device placement or its underlay makes those modes visually ambiguous.
|
||||
- **`show_names: false` means no permanent fallback label.** View, kiosk,
|
||||
hidden isometric and `houseplan-space-card` all omit the room name. Plan may
|
||||
show the same HTML card temporarily so its saved position remains editable;
|
||||
returning to View hides it again. Re-enabling names restores the saved
|
||||
layout rather than creating a new one.
|
||||
- **Their geometry and their presentation are separate.** Every virtual span
|
||||
still ends on the real wall centreline. In View the thick wall body is
|
||||
painted over the dash ends, so they visually stop at its faces; editors paint
|
||||
@@ -135,9 +141,10 @@ layer you cannot see is a layer you cannot edit.
|
||||
through it, the sun still enters at a window, a contact sensor still opens
|
||||
it, and the resize tool still anchors to it. Anything else would be a second
|
||||
meaning for one setting.
|
||||
- Both new switches store **nothing when off** (the key is omitted, as
|
||||
- Both hide switches store **nothing when off** (the key is omitted, as
|
||||
`bg_color` is), so a plan written before this reads back byte-for-byte.
|
||||
Backend: `hide_decor` / `hide_openings`, strictly `bool`, both optional.
|
||||
Backend: `show_names`, `hide_decor` and `hide_openings` are strictly `bool`
|
||||
and optional.
|
||||
|
||||
## Devices — placement and marker configuration
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": 1,
|
||||
"fixture": "synthetic-only",
|
||||
"sourceFingerprint": "51c4bdb005b2539779085578bcce5ee1b4b3e3137542ef1aeb440232344c3105",
|
||||
"sourceFingerprint": "49963a7758df03d7aaaa3af3b9f198d629f4ca44af5c8ef9834c7afce5fda8ba",
|
||||
"captureScriptSha256": "34f2219790d46efd8250e7a1bd829cb8fc0b0547e1260635fefa52407551b41b",
|
||||
"command": "npm run build && node demo/docs/capture.mjs",
|
||||
"scenarios": {
|
||||
@@ -13,7 +13,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "51c4bdb005b2539779085578bcce5ee1b4b3e3137542ef1aeb440232344c3105",
|
||||
"sourceSha256": "49963a7758df03d7aaaa3af3b9f198d629f4ca44af5c8ef9834c7afce5fda8ba",
|
||||
"imageSha256": "d36b6f9f8139f31ef73a780c6511a640a26055efd9d7a24c24fd48b1d8379bf0"
|
||||
},
|
||||
"view-touch": {
|
||||
@@ -24,7 +24,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "51c4bdb005b2539779085578bcce5ee1b4b3e3137542ef1aeb440232344c3105",
|
||||
"sourceSha256": "49963a7758df03d7aaaa3af3b9f198d629f4ca44af5c8ef9834c7afce5fda8ba",
|
||||
"imageSha256": "358e25ff9984d0fb0c03cfbb848df40c425fdfe64cd5f4f613b1e754ca9d4249"
|
||||
},
|
||||
"space-create": {
|
||||
@@ -35,7 +35,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "51c4bdb005b2539779085578bcce5ee1b4b3e3137542ef1aeb440232344c3105",
|
||||
"sourceSha256": "49963a7758df03d7aaaa3af3b9f198d629f4ca44af5c8ef9834c7afce5fda8ba",
|
||||
"imageSha256": "c53db2e5c642a5549c13f3c93a5b359fed69bdb2621bf71a243a877ffcb95e6b"
|
||||
},
|
||||
"room-contour-close": {
|
||||
@@ -46,7 +46,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "51c4bdb005b2539779085578bcce5ee1b4b3e3137542ef1aeb440232344c3105",
|
||||
"sourceSha256": "49963a7758df03d7aaaa3af3b9f198d629f4ca44af5c8ef9834c7afce5fda8ba",
|
||||
"imageSha256": "2f13ea645af306eee9cc7c52699c928377b72f412b08c1a3db6beb848ace1b51"
|
||||
},
|
||||
"plan-context-tray": {
|
||||
@@ -57,7 +57,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "51c4bdb005b2539779085578bcce5ee1b4b3e3137542ef1aeb440232344c3105",
|
||||
"sourceSha256": "49963a7758df03d7aaaa3af3b9f198d629f4ca44af5c8ef9834c7afce5fda8ba",
|
||||
"imageSha256": "a6c526fede11bc3503fd2384bd4a3f6afa008f481c5c47578f06cae6c81c6f9b"
|
||||
},
|
||||
"device-editor": {
|
||||
@@ -68,7 +68,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "51c4bdb005b2539779085578bcce5ee1b4b3e3137542ef1aeb440232344c3105",
|
||||
"sourceSha256": "49963a7758df03d7aaaa3af3b9f198d629f4ca44af5c8ef9834c7afce5fda8ba",
|
||||
"imageSha256": "7c3e25534fc819c45431907616c3d523961505859ee68af27cce2daec9f04fb0"
|
||||
},
|
||||
"device-display-preview": {
|
||||
@@ -79,7 +79,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "51c4bdb005b2539779085578bcce5ee1b4b3e3137542ef1aeb440232344c3105",
|
||||
"sourceSha256": "49963a7758df03d7aaaa3af3b9f198d629f4ca44af5c8ef9834c7afce5fda8ba",
|
||||
"imageSha256": "df3a54395c83bffd7a161f1fb3de0143e12e76567535aedf9883873ead74df91"
|
||||
},
|
||||
"background-editor": {
|
||||
@@ -90,7 +90,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "51c4bdb005b2539779085578bcce5ee1b4b3e3137542ef1aeb440232344c3105",
|
||||
"sourceSha256": "49963a7758df03d7aaaa3af3b9f198d629f4ca44af5c8ef9834c7afce5fda8ba",
|
||||
"imageSha256": "d7cfe70551d9260169df8efd832e32ed7df99c7f60b55d1fd4a8322bd4c47175"
|
||||
},
|
||||
"room-card": {
|
||||
@@ -101,7 +101,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "51c4bdb005b2539779085578bcce5ee1b4b3e3137542ef1aeb440232344c3105",
|
||||
"sourceSha256": "49963a7758df03d7aaaa3af3b9f198d629f4ca44af5c8ef9834c7afce5fda8ba",
|
||||
"imageSha256": "176abba71d41cfb045a33f82a794d9fbb2a5d3c48e6df66e6ec3a8e448311b11"
|
||||
},
|
||||
"device-info": {
|
||||
@@ -112,7 +112,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "51c4bdb005b2539779085578bcce5ee1b4b3e3137542ef1aeb440232344c3105",
|
||||
"sourceSha256": "49963a7758df03d7aaaa3af3b9f198d629f4ca44af5c8ef9834c7afce5fda8ba",
|
||||
"imageSha256": "2199ed88b215bf2bff63bf665028f78b2aa6a92c3032b803931790f2ef071893"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,6 +404,56 @@ export const MUTANTS = [
|
||||
replace: ' if (!replacingRemoved && prevPos && prevPos.s === targetSpaceId && !roomChanged) {',
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'hidden-room-names-full-svg-fallback',
|
||||
guard: 'node demo/smoke_hide_room_names.mjs',
|
||||
because: 'show_names:false must remove every permanent label from the full flat renderer; '
|
||||
+ 'the smoke must reject the legacy centred SVG substitute independently of compact and iso',
|
||||
patches: [{
|
||||
file: 'src/houseplan-card.ts',
|
||||
find: " ${this._renderOpeningTunnelFills(space, glowBase, 'glow-base')}\n"
|
||||
+ ' ${glowLayerVisible ? this._renderGlowLayer(space, disp) : nothing}',
|
||||
replace: " ${this._renderOpeningTunnelFills(space, glowBase, 'glow-base')}\n"
|
||||
+ ' ${!space.bg && !disp.showNames && !this._markup ? svg`<g class="room-svg-labels" pointer-events="none">${space.rooms.map((room) => {\n'
|
||||
+ ' const center = this._roomCenter(room);\n'
|
||||
+ ' return svg`<text class="rlabel" data-hp="room-label" data-id=${room.id || nothing}\n'
|
||||
+ ' data-area=${room.area || nothing} x=${center[0]} y=${center[1]}>${room.name}</text>`;\n'
|
||||
+ ' })}</g>` : nothing}\n'
|
||||
+ ' ${glowLayerVisible ? this._renderGlowLayer(space, disp) : nothing}',
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'hidden-room-names-compact-svg-fallback',
|
||||
guard: 'node demo/smoke_hide_room_names.mjs',
|
||||
because: 'the compact card is an independent renderer and must not replace a disabled HTML '
|
||||
+ 'room card with the old SVG name even when the full card is correct',
|
||||
patches: [{
|
||||
file: 'src/space-render.ts',
|
||||
find: ' spaceModels, defaultPositions, markerPos, labelPos, spaceFrame, iconCqw, NORM_W,',
|
||||
replace: ' spaceModels, roomCenter, defaultPositions, markerPos, labelPos, spaceFrame, iconCqw, NORM_W,',
|
||||
}, {
|
||||
file: 'src/space-render.ts',
|
||||
find: ' ${passageGlowTunnels}\n ${wallUnion',
|
||||
replace: ' ${passageGlowTunnels}\n'
|
||||
+ ' ${!space.bg && !disp.showNames ? svg`<g class="room-svg-labels" pointer-events="none">${space.rooms.map((room) => {\n'
|
||||
+ ' const center = roomCenter(room);\n'
|
||||
+ ' return svg`<text class="rlabel" data-hp="room-label" data-id=${room.id || nothing}\n'
|
||||
+ ' data-area=${room.area || nothing} x=${center[0]} y=${center[1]}>${room.name}</text>`;\n'
|
||||
+ ' })}</g>` : nothing}\n'
|
||||
+ ' ${wallUnion',
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'hidden-room-names-iso-override',
|
||||
guard: 'node demo/smoke_hide_room_names.mjs',
|
||||
because: 'hidden isometric View must obey the same show_names:false contract instead of '
|
||||
+ 'forcing an HTML room card solely because the space has no backdrop',
|
||||
patches: [{
|
||||
file: 'src/houseplan-card.ts',
|
||||
find: ' ${disp.showNames || this._markup\n',
|
||||
replace: ' ${disp.showNames || (iso && !space.bg) || this._markup\n',
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'plan-room-area-icon-hidden',
|
||||
guard: 'node demo/smoke_room_link.mjs',
|
||||
|
||||
+1
-13
@@ -10907,17 +10907,6 @@ class HouseplanCard extends LitElement {
|
||||
return svg`<g class="glow-base-layer" aria-hidden="true" pointer-events="none">${shapes}</g>` as unknown as TemplateResult;
|
||||
}
|
||||
|
||||
private _renderSvgRoomLabels(space: SpaceModel, disp: SpaceDisplay): TemplateResult {
|
||||
if (this._renderProjection === 'iso' || space.bg || disp.showNames || this._markup)
|
||||
return svg`` as unknown as TemplateResult;
|
||||
return svg`<g class="room-svg-labels" pointer-events="none">${space.rooms.map((room) => {
|
||||
const center = this._roomCenter(room);
|
||||
return svg`<text class="rlabel" data-hp="room-label"
|
||||
data-id=${room.id || nothing} data-area=${room.area || nothing}
|
||||
x=${center[0]} y=${center[1]}>${room.name}</text>`;
|
||||
})}</g>` as unknown as TemplateResult;
|
||||
}
|
||||
|
||||
private _renderWallBodies(disp: SpaceDisplay): TemplateResult {
|
||||
if (this._renderProjection === 'iso') return svg`` as unknown as TemplateResult;
|
||||
if (disp && !disp.showBorders && (this._mode === 'view' || this._mode === 'devices'))
|
||||
@@ -15754,7 +15743,6 @@ class HouseplanCard extends LitElement {
|
||||
${this._renderOpeningTunnelFills(space, roomFills)}
|
||||
${this._renderGlowBaseRooms(space, glowBase)}
|
||||
${this._renderOpeningTunnelFills(space, glowBase, 'glow-base')}
|
||||
${this._renderSvgRoomLabels(space, disp)}
|
||||
${glowLayerVisible ? this._renderGlowLayer(space, disp) : nothing}
|
||||
${this._renderSunRays(space)}
|
||||
${this._editing ? svg`<g class="hp-editor-only-layer"
|
||||
@@ -15822,7 +15810,7 @@ class HouseplanCard extends LitElement {
|
||||
${this._renderVacuums(devs, view)}
|
||||
${this._renderVacFit(view)}
|
||||
${this._renderOpeningLocks(view)}
|
||||
${disp.showNames || (iso && !space.bg) || this._markup
|
||||
${disp.showNames || this._markup
|
||||
? space.rooms.map((r) => this._renderRoomLabel(r, space, view, disp))
|
||||
: nothing}
|
||||
${this._markup ? space.rooms.map((r) => this._renderRoomGear(r, space, view)) : nothing}
|
||||
|
||||
+1
-11
@@ -42,7 +42,7 @@ import { contentFingerprint } from './visual-continuity';
|
||||
import type { VirtualLightSnapshot } from './virtual-light-state';
|
||||
import { renderOpeningTunnelFills } from './render/opening-tunnels';
|
||||
import {
|
||||
spaceModels, roomCenter, defaultPositions, markerPos, labelPos, spaceFrame, iconCqw, NORM_W,
|
||||
spaceModels, defaultPositions, markerPos, labelPos, spaceFrame, iconCqw, NORM_W,
|
||||
GRID_STEP_N, GRID_PITCH, staticPassageOpenings,
|
||||
type Layout, type ContentItem,
|
||||
} from './space-geometry';
|
||||
@@ -342,15 +342,6 @@ export function renderSpaceStatic(o: StaticRenderOpts): TemplateResult | null {
|
||||
? { color: colors.glow_base.c, opacity: colors.glow_base.a, mode: 'glow' }
|
||||
: null);
|
||||
}
|
||||
const staticSvgLabels = !space.bg && !disp.showNames
|
||||
? space.rooms.map((room) => {
|
||||
const center = roomCenter(room);
|
||||
return svg`<text class="rlabel" data-hp="room-label"
|
||||
data-id=${room.id || nothing} data-area=${room.area || nothing}
|
||||
x=${center[0]} y=${center[1]}>${room.name}</text>`;
|
||||
})
|
||||
: [];
|
||||
|
||||
const planLightSources = resolvedLightSources(planHass, devs, null, o.virtualLights);
|
||||
const markers = devs.map((d) => {
|
||||
const p = markerPos(d, o.layout, o.cfg, defPos, space);
|
||||
@@ -529,7 +520,6 @@ export function renderSpaceStatic(o: StaticRenderOpts): TemplateResult | null {
|
||||
? svg`<g class="glow-base-layer" aria-hidden="true" pointer-events="none">${glowBaseShapes}</g>`
|
||||
: nothing}
|
||||
${passageGlowTunnels}
|
||||
<g class="room-svg-labels" pointer-events="none">${staticSvgLabels}</g>
|
||||
${wallUnion
|
||||
? svg`<g class="wallbodies" style="--room-stroke:${wallStroke}">
|
||||
<path class="wallbody-fill" d="${wallUnion.d}"
|
||||
|
||||
@@ -1328,7 +1328,6 @@ export const cardStyles = css`
|
||||
.stage .room,
|
||||
.stage .devlayer,
|
||||
.stage .opening,
|
||||
.stage .rlabel,
|
||||
.stage .room-outline,
|
||||
.stage .wallbodies,
|
||||
.stage .opening-tunnels,
|
||||
@@ -1395,13 +1394,6 @@ export const cardStyles = css`
|
||||
fill: var(--hp-open, #ff9800);
|
||||
pointer-events: none;
|
||||
}
|
||||
.rlabel {
|
||||
fill: var(--hp-muted);
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
pointer-events: none;
|
||||
text-anchor: middle;
|
||||
}
|
||||
.stage.edit .room {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user