mirror of
https://github.com/Matysh/houseplan-card
synced 2026-07-31 16:38:31 +00:00
fix v1.18.1: the drawing ruler badge was invisible — .stage.markup hides .devlayer
The v1.18.0 measure label was rendered inside .devlayer, which markup mode hides entirely (display:none) so icons don't obstruct drawing. Moved it to its own .measurelayer. Verified visually on a real segment (3.60 m).
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.18.0"
|
VERSION = "1.18.1"
|
||||||
|
|
||||||
DEFAULT_CONFIG: dict = {
|
DEFAULT_CONFIG: dict = {
|
||||||
"spaces": [],
|
"spaces": [],
|
||||||
|
|||||||
@@ -239,6 +239,11 @@ const t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
.roomlabel:active { cursor: grabbing; }
|
.roomlabel:active { cursor: grabbing; }
|
||||||
|
.measurelayer {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
.measurelabel {
|
.measurelabel {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
transform: translate(12px, -150%);
|
transform: translate(12px, -150%);
|
||||||
@@ -1126,8 +1131,8 @@ const t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow
|
|||||||
<div class="devlayer" style="--icon-size:${(r*i[2]/n.w).toFixed(3)}cqw">
|
<div class="devlayer" style="--icon-size:${(r*i[2]/n.w).toFixed(3)}cqw">
|
||||||
${s.map(t=>this._renderDevice(t,n))}
|
${s.map(t=>this._renderDevice(t,n))}
|
||||||
${a.showNames&&!this._markup?e.rooms.map(t=>this._renderRoomLabel(t,e,n,a)):K}
|
${a.showNames&&!this._markup?e.rooms.map(t=>this._renderRoomLabel(t,e,n,a)):K}
|
||||||
${this._markup&&"draw"===this._tool&&this._path.length&&this._cursorPt&&!this._contourClosed?this._renderMeasureLabel(n):K}
|
|
||||||
</div>
|
</div>
|
||||||
|
${this._markup&&"draw"===this._tool&&this._path.length&&this._cursorPt&&!this._contourClosed?j`<div class="measurelayer">${this._renderMeasureLabel(n)}</div>`:K}
|
||||||
</div>
|
</div>
|
||||||
${this._zoom>1?j`<div class="zoombadge">${Math.round(100*this._zoom)}%</div>`:K}
|
${this._zoom>1?j`<div class="zoombadge">${Math.round(100*this._zoom)}%</div>`:K}
|
||||||
</div>
|
</div>
|
||||||
@@ -1428,4 +1433,4 @@ const t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>`}}ue.properties={hass:{attribute:!1},_config:{state:!0},_space:{state:!0},_layout:{state:!0},_devices:{state:!0},_tip:{state:!0},_selId:{state:!0},_toast:{state:!0},_serverCfg:{state:!0},_markup:{state:!0},_tool:{state:!0},_path:{state:!0},_cursorPt:{state:!0},_areaSel:{state:!0},_nameSel:{state:!0},_roomDialog:{state:!0},_spaceDialog:{state:!0},_infoCard:{state:!0},_rulesDialog:{state:!0},_importDialog:{state:!0},_markerDialog:{state:!0},_zoom:{state:!0},_view:{state:!0}},ue.styles=Vt,customElements.get("houseplan-card")||customElements.define("houseplan-card",ue),window.customCards=window.customCards||[],window.customCards.find(t=>"houseplan-card"===t.type)||window.customCards.push({type:"houseplan-card",name:"House Plan Card",description:"Interactive house plan: spaces, rooms and devices with live states and drag layout."}),console.info("%c HOUSEPLAN-CARD %c v1.18.0 ","background:#3ea6ff;color:#04121f;font-weight:700","");
|
</div>`}}ue.properties={hass:{attribute:!1},_config:{state:!0},_space:{state:!0},_layout:{state:!0},_devices:{state:!0},_tip:{state:!0},_selId:{state:!0},_toast:{state:!0},_serverCfg:{state:!0},_markup:{state:!0},_tool:{state:!0},_path:{state:!0},_cursorPt:{state:!0},_areaSel:{state:!0},_nameSel:{state:!0},_roomDialog:{state:!0},_spaceDialog:{state:!0},_infoCard:{state:!0},_rulesDialog:{state:!0},_importDialog:{state:!0},_markerDialog:{state:!0},_zoom:{state:!0},_view:{state:!0}},ue.styles=Vt,customElements.get("houseplan-card")||customElements.define("houseplan-card",ue),window.customCards=window.customCards||[],window.customCards.find(t=>"houseplan-card"===t.type)||window.customCards.push({type:"houseplan-card",name:"House Plan Card",description:"Interactive house plan: spaces, rooms and devices with live states and drag layout."}),console.info("%c HOUSEPLAN-CARD %c v1.18.1 ","background:#3ea6ff;color:#04121f;font-weight:700","");
|
||||||
|
|||||||
@@ -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.18.0"
|
"version": "1.18.1"
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+7
-2
@@ -239,6 +239,11 @@ const t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
.roomlabel:active { cursor: grabbing; }
|
.roomlabel:active { cursor: grabbing; }
|
||||||
|
.measurelayer {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
.measurelabel {
|
.measurelabel {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
transform: translate(12px, -150%);
|
transform: translate(12px, -150%);
|
||||||
@@ -1126,8 +1131,8 @@ const t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow
|
|||||||
<div class="devlayer" style="--icon-size:${(r*i[2]/n.w).toFixed(3)}cqw">
|
<div class="devlayer" style="--icon-size:${(r*i[2]/n.w).toFixed(3)}cqw">
|
||||||
${s.map(t=>this._renderDevice(t,n))}
|
${s.map(t=>this._renderDevice(t,n))}
|
||||||
${a.showNames&&!this._markup?e.rooms.map(t=>this._renderRoomLabel(t,e,n,a)):K}
|
${a.showNames&&!this._markup?e.rooms.map(t=>this._renderRoomLabel(t,e,n,a)):K}
|
||||||
${this._markup&&"draw"===this._tool&&this._path.length&&this._cursorPt&&!this._contourClosed?this._renderMeasureLabel(n):K}
|
|
||||||
</div>
|
</div>
|
||||||
|
${this._markup&&"draw"===this._tool&&this._path.length&&this._cursorPt&&!this._contourClosed?j`<div class="measurelayer">${this._renderMeasureLabel(n)}</div>`:K}
|
||||||
</div>
|
</div>
|
||||||
${this._zoom>1?j`<div class="zoombadge">${Math.round(100*this._zoom)}%</div>`:K}
|
${this._zoom>1?j`<div class="zoombadge">${Math.round(100*this._zoom)}%</div>`:K}
|
||||||
</div>
|
</div>
|
||||||
@@ -1428,4 +1433,4 @@ const t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>`}}ue.properties={hass:{attribute:!1},_config:{state:!0},_space:{state:!0},_layout:{state:!0},_devices:{state:!0},_tip:{state:!0},_selId:{state:!0},_toast:{state:!0},_serverCfg:{state:!0},_markup:{state:!0},_tool:{state:!0},_path:{state:!0},_cursorPt:{state:!0},_areaSel:{state:!0},_nameSel:{state:!0},_roomDialog:{state:!0},_spaceDialog:{state:!0},_infoCard:{state:!0},_rulesDialog:{state:!0},_importDialog:{state:!0},_markerDialog:{state:!0},_zoom:{state:!0},_view:{state:!0}},ue.styles=Vt,customElements.get("houseplan-card")||customElements.define("houseplan-card",ue),window.customCards=window.customCards||[],window.customCards.find(t=>"houseplan-card"===t.type)||window.customCards.push({type:"houseplan-card",name:"House Plan Card",description:"Interactive house plan: spaces, rooms and devices with live states and drag layout."}),console.info("%c HOUSEPLAN-CARD %c v1.18.0 ","background:#3ea6ff;color:#04121f;font-weight:700","");
|
</div>`}}ue.properties={hass:{attribute:!1},_config:{state:!0},_space:{state:!0},_layout:{state:!0},_devices:{state:!0},_tip:{state:!0},_selId:{state:!0},_toast:{state:!0},_serverCfg:{state:!0},_markup:{state:!0},_tool:{state:!0},_path:{state:!0},_cursorPt:{state:!0},_areaSel:{state:!0},_nameSel:{state:!0},_roomDialog:{state:!0},_spaceDialog:{state:!0},_infoCard:{state:!0},_rulesDialog:{state:!0},_importDialog:{state:!0},_markerDialog:{state:!0},_zoom:{state:!0},_view:{state:!0}},ue.styles=Vt,customElements.get("houseplan-card")||customElements.define("houseplan-card",ue),window.customCards=window.customCards||[],window.customCards.find(t=>"houseplan-card"===t.type)||window.customCards.push({type:"houseplan-card",name:"House Plan Card",description:"Interactive house plan: spaces, rooms and devices with live states and drag layout."}),console.info("%c HOUSEPLAN-CARD %c v1.18.1 ","background:#3ea6ff;color:#04121f;font-weight:700","");
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v1.18.1 — 2026-07-16 (fix: the drawing ruler was invisible)
|
||||||
|
- Fix on top of v1.18.0: the length badge never showed up while drawing. It was rendered
|
||||||
|
inside `.devlayer`, and `.stage.markup .devlayer { display: none }` hides that whole layer
|
||||||
|
in markup mode (so icons do not get in the way) — the badge was in the DOM but invisible.
|
||||||
|
It now lives in its own `.measurelayer` (absolute, `pointer-events: none`), which markup
|
||||||
|
mode does not hide. Verified visually on a real drawn segment ("3.60 m" on screen).
|
||||||
|
- Testing lesson (see docs/TESTING.md): asserting on `textContent` is not enough — a DOM
|
||||||
|
query passes on elements hidden by an ancestor. Check `offsetParent`/rect or look at a
|
||||||
|
screenshot.
|
||||||
|
|
||||||
## v1.18.0 — 2026-07-14 (live measurements while drawing rooms + per-space scale)
|
## v1.18.0 — 2026-07-14 (live measurements while drawing rooms + per-space scale)
|
||||||
- **Ruler while drawing.** In room-markup "draw" mode, a badge follows the cursor showing the
|
- **Ruler while drawing.** In room-markup "draw" mode, a badge follows the cursor showing the
|
||||||
length of the current segment (last placed vertex → cursor). Units come from the HA unit
|
length of the current segment (last placed vertex → cursor). Units come from the HA unit
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
| Item | State |
|
| Item | State |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Version | **v1.18.0** everywhere (manifest, const.py, package.json, CARD_VERSION) |
|
| Version | **v1.18.1** everywhere (manifest, const.py, package.json, CARD_VERSION) |
|
||||||
| GitHub | https://github.com/Matysh/houseplan-card — branch `main`, releases v1.9.3…v1.11.2 |
|
| GitHub | https://github.com/Matysh/houseplan-card — branch `main`, releases v1.9.3…v1.11.2 |
|
||||||
| CI | `.github/workflows/validate.yml` (hacs + hassfest + frontend + backend) — **fully green** since v1.11.1; `release.yml` auto-attaches the card bundle (needs `permissions: contents: write`, fixed) |
|
| CI | `.github/workflows/validate.yml` (hacs + hassfest + frontend + backend) — **fully green** since v1.11.1; `release.yml` auto-attaches the card bundle (needs `permissions: contents: write`, fixed) |
|
||||||
| HACS | Works as custom repository (id 1290210112 on the home instance). **Inclusion PR: https://github.com/hacs/default/pull/9004** (queue ≈2 months as of 2026-07). Lesson: #8995 was auto-closed by hacs-bot — the PR body MUST be their exact template with every checkbox ticked and all 3 links (release, HACS action run, hassfest run); a custom body gets closed without discussion |
|
| HACS | Works as custom repository (id 1290210112 on the home instance). **Inclusion PR: https://github.com/hacs/default/pull/9004** (queue ≈2 months as of 2026-07). Lesson: #8995 was auto-closed by hacs-bot — the PR body MUST be their exact template with every checkbox ticked and all 3 links (release, HACS action run, hassfest run); a custom body gets closed without discussion |
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "houseplan-card",
|
"name": "houseplan-card",
|
||||||
"version": "1.18.0",
|
"version": "1.18.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",
|
||||||
|
|||||||
@@ -27,7 +27,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.18.0';
|
const CARD_VERSION = '1.18.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';
|
||||||
@@ -2025,10 +2025,10 @@ class HouseplanCard extends LitElement {
|
|||||||
${disp.showNames && !this._markup
|
${disp.showNames && !this._markup
|
||||||
? space.rooms.map((r) => this._renderRoomLabel(r, space, view, disp))
|
? space.rooms.map((r) => this._renderRoomLabel(r, space, view, disp))
|
||||||
: nothing}
|
: nothing}
|
||||||
${this._markup && this._tool === 'draw' && this._path.length && this._cursorPt && !this._contourClosed
|
|
||||||
? this._renderMeasureLabel(view)
|
|
||||||
: nothing}
|
|
||||||
</div>
|
</div>
|
||||||
|
${this._markup && this._tool === 'draw' && this._path.length && this._cursorPt && !this._contourClosed
|
||||||
|
? html`<div class="measurelayer">${this._renderMeasureLabel(view)}</div>`
|
||||||
|
: nothing}
|
||||||
</div>
|
</div>
|
||||||
${this._zoom > 1
|
${this._zoom > 1
|
||||||
? html`<div class="zoombadge">${Math.round(this._zoom * 100)}%</div>`
|
? html`<div class="zoombadge">${Math.round(this._zoom * 100)}%</div>`
|
||||||
|
|||||||
@@ -236,6 +236,11 @@ export const cardStyles = css`
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
.roomlabel:active { cursor: grabbing; }
|
.roomlabel:active { cursor: grabbing; }
|
||||||
|
.measurelayer {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
.measurelabel {
|
.measurelabel {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
transform: translate(12px, -150%);
|
transform: translate(12px, -150%);
|
||||||
|
|||||||
Reference in New Issue
Block a user