mirror of
https://github.com/Matysh/houseplan-card
synced 2026-07-31 08:28:31 +00:00
ux v1.40.1: room click removed — link icon on the room card instead
- rooms inert in View (default cursor); mdi:open-in-new after the room name (View, rooms with an area) navigates to the HA area - smoke_room_link.mjs (7 checks); TESTING/CHANGELOG/UX-MODES same-commit
This commit is contained in:
@@ -11,7 +11,7 @@ PLANS_DIR = "houseplan/plans" # relative to the HA configuration directory
|
|||||||
FILES_URL = "/houseplan_files/files"
|
FILES_URL = "/houseplan_files/files"
|
||||||
FILES_DIR = "houseplan/files"
|
FILES_DIR = "houseplan/files"
|
||||||
CONF_ADMIN_ONLY = "admin_only"
|
CONF_ADMIN_ONLY = "admin_only"
|
||||||
VERSION = "1.40.0"
|
VERSION = "1.40.1"
|
||||||
|
|
||||||
DEFAULT_CONFIG: dict = {
|
DEFAULT_CONFIG: dict = {
|
||||||
"spaces": [],
|
"spaces": [],
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -16,5 +16,5 @@
|
|||||||
"issue_tracker": "https://github.com/Matysh/houseplan-card/issues",
|
"issue_tracker": "https://github.com/Matysh/houseplan-card/issues",
|
||||||
"requirements": [],
|
"requirements": [],
|
||||||
"single_config_entry": true,
|
"single_config_entry": true,
|
||||||
"version": "1.40.0"
|
"version": "1.40.1"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import { launch } from './serve.mjs';
|
||||||
|
const { page, browser } = await launch();
|
||||||
|
const res = await page.evaluate(async () => {
|
||||||
|
const out = {};
|
||||||
|
const c = window.__card;
|
||||||
|
const sr = () => c.shadowRoot || c.renderRoot;
|
||||||
|
// включить имена комнат
|
||||||
|
c._serverCfg = { ...c._serverCfg, spaces: c._serverCfg.spaces.map((s) => s.id !== c._space ? s : ({
|
||||||
|
...s, settings: { ...(s.settings || {}), show_names: true } })) };
|
||||||
|
c._setMode('view'); c.requestUpdate(); await c.updateComplete;
|
||||||
|
await new Promise((r) => setTimeout(r, 250));
|
||||||
|
// 1) комната не кликабельна: cursor default, обработчика клика нет
|
||||||
|
const room = sr().querySelector('.room');
|
||||||
|
out.roomCursor = getComputedStyle(room).cursor === 'default';
|
||||||
|
// 2) значок ссылки у комнат с зоной, кликабелен, ведёт в зону
|
||||||
|
const links = sr().querySelectorAll('.rlgo');
|
||||||
|
out.linksShown = links.length > 0;
|
||||||
|
const withArea = c._spaceModel().rooms.filter((r) => r.name && r.area).length;
|
||||||
|
out.linkPerArearoom = links.length === withArea;
|
||||||
|
const icon = links[0];
|
||||||
|
out.linkCursor = getComputedStyle(icon).cursor === 'pointer';
|
||||||
|
out.linkClickable = getComputedStyle(icon).pointerEvents === 'auto';
|
||||||
|
// навигация: перехват history
|
||||||
|
let navTo = null;
|
||||||
|
const orig = history.pushState.bind(history);
|
||||||
|
history.pushState = (a, b, url) => { navTo = url; };
|
||||||
|
icon.dispatchEvent(new MouseEvent('click', { bubbles: true, composed: true }));
|
||||||
|
await c.updateComplete;
|
||||||
|
history.pushState = orig;
|
||||||
|
out.navigates = typeof navTo === 'string' && navTo.includes('/config/areas/area/');
|
||||||
|
// 3) комнаты без зоны — без значка (проверено соотношением выше); в разметке значков нет
|
||||||
|
c._setMode('plan'); await c.updateComplete;
|
||||||
|
out.noneInPlan = sr().querySelectorAll('.rlgo').length === 0;
|
||||||
|
c._setMode('view'); await c.updateComplete;
|
||||||
|
return out;
|
||||||
|
});
|
||||||
|
console.log(JSON.stringify(res, null, 1));
|
||||||
|
await browser.close();
|
||||||
File diff suppressed because one or more lines are too long
Vendored
+21
-7
File diff suppressed because one or more lines are too long
@@ -1,5 +1,11 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v1.40.1 — 2026-07-23
|
||||||
|
- Rooms are no longer clickable in View (default cursor, empty space does
|
||||||
|
nothing). Instead the room card shows a small **open-in-new icon** after
|
||||||
|
the name — clicking it opens the HA area. Rooms without an area (and all
|
||||||
|
editors) have no icon.
|
||||||
|
|
||||||
## v1.40.0 — 2026-07-23 (smart guides)
|
## v1.40.0 — 2026-07-23 (smart guides)
|
||||||
- **Alignment helper in every editor**: while drawing an outline, a cut or a
|
- **Alignment helper in every editor**: while drawing an outline, a cut or a
|
||||||
decor shape, and while dragging icons, room cards or decor, thin dashed
|
decor shape, and while dragging icons, room cards or decor, thin dashed
|
||||||
|
|||||||
@@ -140,6 +140,10 @@ Run the *core flows* (marked ★ below) in each environment at least once per mi
|
|||||||
(explicit ripple color still wins); off/white lights unchanged [auto]
|
(explicit ripple color still wins); off/white lights unchanged [auto]
|
||||||
- [ ] Alarm pulse (v1.27.0): leak/smoke/gas/CO/siren in 'on' pulse a red ring over any
|
- [ ] Alarm pulse (v1.27.0): leak/smoke/gas/CO/siren in 'on' pulse a red ring over any
|
||||||
display mode; clears on 'off'; unavailable never alarms [auto]; reduced-motion static
|
display mode; clears on 'off'; unavailable never alarms [auto]; reduced-motion static
|
||||||
|
- [ ] Room link icon (v1.40.1): clicking empty room space in View does
|
||||||
|
nothing (default cursor); an open-in-new icon after the room name (rooms
|
||||||
|
with an HA area, View only) navigates to the area; no icon in editors or
|
||||||
|
on area-less rooms [auto]
|
||||||
- [ ] Smart guides (v1.40.0): while drawing (outline, cut, decor shapes) or
|
- [ ] Smart guides (v1.40.0): while drawing (outline, cut, decor shapes) or
|
||||||
dragging (icons, room cards, decor) dashed accent guides appear from the
|
dragging (icons, room cards, decor) dashed accent guides appear from the
|
||||||
nearest object sharing the X and/or Y (max two, with a dot at the
|
nearest object sharing the X and/or Y (max two, with a dot at the
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@ Allowed: pan/zoom (wheel, pinch, buttons), switching spaces, device tap
|
|||||||
(info / more-info / toggle per settings), long-press → info card, opening tap →
|
(info / more-info / toggle per settings), long-press → info card, opening tap →
|
||||||
door/lock info card (with an explicit Unlock/Lock button when a lock is bound —
|
door/lock info card (with an explicit Unlock/Lock button when a lock is bound —
|
||||||
the only way to operate a lock from the card; plan-icon taps never toggle locks),
|
the only way to operate a lock from the card; plan-icon taps never toggle locks),
|
||||||
room tap → HA area, hover tooltips (name, temperature, signal).
|
room-card link icon → HA area (room taps do nothing since v1.40.1), hover tooltips (name, temperature, signal).
|
||||||
|
|
||||||
Removed from this mode (they move, not die):
|
Removed from this mode (they move, not die):
|
||||||
- icon dragging ("drag anywhere", v1.9 — consciously reversed),
|
- icon dragging ("drag anywhere", v1.9 — consciously reversed),
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "houseplan-card",
|
"name": "houseplan-card",
|
||||||
"version": "1.40.0",
|
"version": "1.40.1",
|
||||||
"description": "Interactive house plan Lovelace card for Home Assistant",
|
"description": "Interactive house plan Lovelace card for Home Assistant",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
+10
-5
@@ -32,7 +32,7 @@ import './space-card';
|
|||||||
import { cardStyles } from './styles';
|
import { cardStyles } from './styles';
|
||||||
import { langOf, t, type I18nKey } from './i18n';
|
import { langOf, t, type I18nKey } from './i18n';
|
||||||
|
|
||||||
const CARD_VERSION = '1.40.0';
|
const CARD_VERSION = '1.40.1';
|
||||||
const LS_KEY = 'houseplan_card_layout_v1';
|
const LS_KEY = 'houseplan_card_layout_v1';
|
||||||
const LS_CFG = 'houseplan_card_cfg_v1'; // cache of the server config+layout for instant rendering
|
const LS_CFG = 'houseplan_card_cfg_v1'; // cache of the server config+layout for instant rendering
|
||||||
const LS_ZOOM = 'houseplan_card_zoom_v1';
|
const LS_ZOOM = 'houseplan_card_zoom_v1';
|
||||||
@@ -3223,15 +3223,15 @@ class HouseplanCard extends LitElement {
|
|||||||
const shape = holes.length && myPoly
|
const shape = holes.length && myPoly
|
||||||
? svg`<path class="${cls}" style="${style}" fill-rule="evenodd"
|
? svg`<path class="${cls}" style="${style}" fill-rule="evenodd"
|
||||||
d="${[myPoly, ...holes].map(pathD).join(' ')}"
|
d="${[myPoly, ...holes].map(pathD).join(' ')}"
|
||||||
@click=${() => this._clickRoom(r)} @mousemove=${tip}
|
@mousemove=${tip}
|
||||||
@mouseleave=${() => (this._tip = null)}></path>`
|
@mouseleave=${() => (this._tip = null)}></path>`
|
||||||
: r.poly
|
: r.poly
|
||||||
? svg`<polygon class="${cls}" style="${style}" points="${r.poly.map((p) => p.join(',')).join(' ')}"
|
? svg`<polygon class="${cls}" style="${style}" points="${r.poly.map((p) => p.join(',')).join(' ')}"
|
||||||
@click=${() => this._clickRoom(r)} @mousemove=${tip}
|
@mousemove=${tip}
|
||||||
@mouseleave=${() => (this._tip = null)}></polygon>`
|
@mouseleave=${() => (this._tip = null)}></polygon>`
|
||||||
: svg`<rect class="${cls}" style="${style}"
|
: svg`<rect class="${cls}" style="${style}"
|
||||||
x="${r.x}" y="${r.y}" width="${r.w}" height="${r.h}" rx="${Math.min(r.w!, r.h!) * 0.03}"
|
x="${r.x}" y="${r.y}" width="${r.w}" height="${r.h}" rx="${Math.min(r.w!, r.h!) * 0.03}"
|
||||||
@click=${() => this._clickRoom(r)} @mousemove=${tip}
|
@mousemove=${tip}
|
||||||
@mouseleave=${() => (this._tip = null)}></rect>`;
|
@mouseleave=${() => (this._tip = null)}></rect>`;
|
||||||
const trimmed = openCuts.length && myPoly
|
const trimmed = openCuts.length && myPoly
|
||||||
? outlineWithout(myPoly, openCuts, this._gridPitch * 0.02)
|
? outlineWithout(myPoly, openCuts, this._gridPitch * 0.02)
|
||||||
@@ -3510,7 +3510,12 @@ class HouseplanCard extends LitElement {
|
|||||||
@pointermove=${(e: PointerEvent) => this._labelMove(e, r, space.id)}
|
@pointermove=${(e: PointerEvent) => this._labelMove(e, r, space.id)}
|
||||||
@pointerup=${() => this._labelUp(r)}
|
@pointerup=${() => this._labelUp(r)}
|
||||||
@pointercancel=${() => this._labelUp(r)}
|
@pointercancel=${() => this._labelUp(r)}
|
||||||
><span class="rlname">${r.name}</span>
|
><span class="rlname">${r.name}${!this._markup && r.area
|
||||||
|
? html`<ha-icon class="rlgo" icon="mdi:open-in-new"
|
||||||
|
title=${this._t('room.open_area')}
|
||||||
|
@click=${(e: Event) => { e.stopPropagation(); this._clickRoom(r); }}
|
||||||
|
@pointerdown=${(e: Event) => e.stopPropagation()}></ha-icon>`
|
||||||
|
: nothing}</span>
|
||||||
${rows.length ? html`<span class="rlmetrics">${rows}</span>` : nothing}
|
${rows.length ? html`<span class="rlmetrics">${rows}</span>` : nothing}
|
||||||
${this._mode === 'plan'
|
${this._mode === 'plan'
|
||||||
? ['tl', 'tr', 'bl', 'br'].map(
|
? ['tl', 'tr', 'bl', 'br'].map(
|
||||||
|
|||||||
+2
-1
@@ -300,5 +300,6 @@
|
|||||||
"marker.from_ha_option": "Pick from the HA list",
|
"marker.from_ha_option": "Pick from the HA list",
|
||||||
"marker.show_entities": "Show entities",
|
"marker.show_entities": "Show entities",
|
||||||
"marker.show_entities_tip": "Adds not only devices to the list, but all their entities too",
|
"marker.show_entities_tip": "Adds not only devices to the list, but all their entities too",
|
||||||
"marker.pick_ph": "Choose a device…"
|
"marker.pick_ph": "Choose a device…",
|
||||||
|
"room.open_area": "Open the HA area"
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -300,5 +300,6 @@
|
|||||||
"marker.from_ha_option": "Выбрать из списка HA",
|
"marker.from_ha_option": "Выбрать из списка HA",
|
||||||
"marker.show_entities": "Отображать сущности",
|
"marker.show_entities": "Отображать сущности",
|
||||||
"marker.show_entities_tip": "Добавляет в список не только устройства, но и все их сущности",
|
"marker.show_entities_tip": "Добавляет в список не только устройства, но и все их сущности",
|
||||||
"marker.pick_ph": "Выберите устройство…"
|
"marker.pick_ph": "Выберите устройство…",
|
||||||
|
"room.open_area": "Открыть зону в HA"
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-1
@@ -189,7 +189,7 @@ export const cardStyles = css`
|
|||||||
}
|
}
|
||||||
.room {
|
.room {
|
||||||
transition: 0.12s;
|
transition: 0.12s;
|
||||||
cursor: pointer;
|
cursor: default; /* v1.40.1: rooms are not clickable — the label's link icon is */
|
||||||
}
|
}
|
||||||
.room.overlay {
|
.room.overlay {
|
||||||
fill: transparent;
|
fill: transparent;
|
||||||
@@ -377,6 +377,17 @@ export const cardStyles = css`
|
|||||||
gap: 0.15em;
|
gap: 0.15em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
.rlname { display: inline-flex; align-items: center; gap: 0.25em; }
|
||||||
|
.rlgo {
|
||||||
|
--mdc-icon-size: 0.85em;
|
||||||
|
display: inline-flex;
|
||||||
|
opacity: 0.55;
|
||||||
|
}
|
||||||
|
.stage.mode-view .rlgo {
|
||||||
|
pointer-events: auto;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.stage.mode-view .rlgo:hover { opacity: 1; }
|
||||||
.roomlabel .rlmetrics {
|
.roomlabel .rlmetrics {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
Reference in New Issue
Block a user