This commit is contained in:
Matysh
2026-08-01 15:45:14 +03:00
parent f49ac613b5
commit 6ff79106b8
13 changed files with 109 additions and 13 deletions
+2 -1
View File
@@ -28,7 +28,8 @@ right on your Lovelace dashboard.
**Feature highlights**
- 🖱 **GUI-first floorplan editor** — rooms, doors & windows, island rooms,
virtual walls and a visual decor layer, all drawn with clicks; smart
virtual walls and a visual decor layer, all drawn with clicks; room resize
by dragging walls, with live lengths and areas as you drag; smart
alignment guides and a live ruler in real meters/feet.
- 💡 **Lights toggle on click** out of the box; wall-switch markers can control
whole groups of lights (works for dumb switches and stateless remotes too).
+2 -1
View File
@@ -26,7 +26,8 @@
**Главное**
- 🖱 **Редакторы прямо в карточке** — комнаты, двери и окна, комнаты-острова,
виртуальные стены и декор-слой рисуются кликами; помощник выравнивания и
виртуальные стены и декор-слой рисуются кликами; размеры комнат меняются
перетаскиванием стен с живыми длинами и площадями; помощник выравнивания и
линейка в реальных метрах.
- 💡 **Свет переключается кликом** из коробки; значок выключателя может
управлять группой ламп (в т.ч. «тупые» выключатели и кнопки-пульты).
+1 -1
View File
@@ -45,7 +45,7 @@ PLAN_ORPHAN_TTL_S = 3600
SCHEDULED_GRACE_S = 30 * 24 * 3600
FILES_DIR = "houseplan/files"
CONF_ADMIN_ONLY = "admin_only"
VERSION = "1.54.3"
VERSION = "1.55.0"
DEFAULT_CONFIG: dict = {
"spaces": [],
@@ -2989,4 +2989,4 @@ const t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow
</button>`}
</div>
</div>
</div>`}}io.properties={_hdrH:{state:!0},_tapConfirm:{state:!0},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},_mode:{state:!0},_tool:{state:!0},_rszSel:{state:!0},_rszLive:{state:!0},_path:{state:!0},_cursorPt:{state:!0},_mergeSel:{state:!0},_openingDialog:{state:!0},_openingInfo:{state:!0},_mergeDialog:{state:!0},_splitSel:{state:!0},_decorTool:{state:!0},_decorStyle:{state:!0},_decorDraft:{state:!0},_decorSel:{state:!0},_decorTextDialog:{state:!0},_kioskDialog:{state:!0},_vacFit:{state:!0},_kioskDots:{state:!0},_areaSel:{state:!0},_nameSel:{state:!0},_roomDialog:{state:!0},_roomEditId:{state:!0},_roomFill:{state:!0},_roomTempSrc:{state:!0},_roomHumSrc:{state:!0},_roomSrcOpen:{state:!0},_roomSrcFilter:{state:!0},_roomNameScale:{state:!0},_roomLabelScale:{state:!0},_spaceDialog:{state:!0},_infoCard:{state:!0},_rulesDialog:{state:!0},_settingsDialog:{state:!0},_importDialog:{state:!0},_markerDialog:{state:!0},_zoom:{state:!0},_view:{state:!0}},io.ZOOM_MAX=8,io.ZOOM_MIN=.4,io._touchSeen=!1,io._noHoverMq="undefined"!=typeof window&&"function"==typeof window.matchMedia&&window.matchMedia("(hover: none)").matches,io.styles=Ts,customElements.get("houseplan-card")||customElements.define("houseplan-card",io),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.54.3 ","background:#3ea6ff;color:#04121f;font-weight:700","");
</div>`}}io.properties={_hdrH:{state:!0},_tapConfirm:{state:!0},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},_mode:{state:!0},_tool:{state:!0},_rszSel:{state:!0},_rszLive:{state:!0},_path:{state:!0},_cursorPt:{state:!0},_mergeSel:{state:!0},_openingDialog:{state:!0},_openingInfo:{state:!0},_mergeDialog:{state:!0},_splitSel:{state:!0},_decorTool:{state:!0},_decorStyle:{state:!0},_decorDraft:{state:!0},_decorSel:{state:!0},_decorTextDialog:{state:!0},_kioskDialog:{state:!0},_vacFit:{state:!0},_kioskDots:{state:!0},_areaSel:{state:!0},_nameSel:{state:!0},_roomDialog:{state:!0},_roomEditId:{state:!0},_roomFill:{state:!0},_roomTempSrc:{state:!0},_roomHumSrc:{state:!0},_roomSrcOpen:{state:!0},_roomSrcFilter:{state:!0},_roomNameScale:{state:!0},_roomLabelScale:{state:!0},_spaceDialog:{state:!0},_infoCard:{state:!0},_rulesDialog:{state:!0},_settingsDialog:{state:!0},_importDialog:{state:!0},_markerDialog:{state:!0},_zoom:{state:!0},_view:{state:!0}},io.ZOOM_MAX=8,io.ZOOM_MIN=.4,io._touchSeen=!1,io._noHoverMq="undefined"!=typeof window&&"function"==typeof window.matchMedia&&window.matchMedia("(hover: none)").matches,io.styles=Ts,customElements.get("houseplan-card")||customElements.define("houseplan-card",io),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.55.0 ","background:#3ea6ff;color:#04121f;font-weight:700","");
+1 -1
View File
@@ -16,5 +16,5 @@
"issue_tracker": "https://github.com/Matysh/houseplan-card/issues",
"requirements": [],
"single_config_entry": true,
"version": "1.54.3"
"version": "1.55.0"
}
+1 -1
View File
@@ -2989,4 +2989,4 @@ const t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow
</button>`}
</div>
</div>
</div>`}}io.properties={_hdrH:{state:!0},_tapConfirm:{state:!0},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},_mode:{state:!0},_tool:{state:!0},_rszSel:{state:!0},_rszLive:{state:!0},_path:{state:!0},_cursorPt:{state:!0},_mergeSel:{state:!0},_openingDialog:{state:!0},_openingInfo:{state:!0},_mergeDialog:{state:!0},_splitSel:{state:!0},_decorTool:{state:!0},_decorStyle:{state:!0},_decorDraft:{state:!0},_decorSel:{state:!0},_decorTextDialog:{state:!0},_kioskDialog:{state:!0},_vacFit:{state:!0},_kioskDots:{state:!0},_areaSel:{state:!0},_nameSel:{state:!0},_roomDialog:{state:!0},_roomEditId:{state:!0},_roomFill:{state:!0},_roomTempSrc:{state:!0},_roomHumSrc:{state:!0},_roomSrcOpen:{state:!0},_roomSrcFilter:{state:!0},_roomNameScale:{state:!0},_roomLabelScale:{state:!0},_spaceDialog:{state:!0},_infoCard:{state:!0},_rulesDialog:{state:!0},_settingsDialog:{state:!0},_importDialog:{state:!0},_markerDialog:{state:!0},_zoom:{state:!0},_view:{state:!0}},io.ZOOM_MAX=8,io.ZOOM_MIN=.4,io._touchSeen=!1,io._noHoverMq="undefined"!=typeof window&&"function"==typeof window.matchMedia&&window.matchMedia("(hover: none)").matches,io.styles=Ts,customElements.get("houseplan-card")||customElements.define("houseplan-card",io),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.54.3 ","background:#3ea6ff;color:#04121f;font-weight:700","");
</div>`}}io.properties={_hdrH:{state:!0},_tapConfirm:{state:!0},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},_mode:{state:!0},_tool:{state:!0},_rszSel:{state:!0},_rszLive:{state:!0},_path:{state:!0},_cursorPt:{state:!0},_mergeSel:{state:!0},_openingDialog:{state:!0},_openingInfo:{state:!0},_mergeDialog:{state:!0},_splitSel:{state:!0},_decorTool:{state:!0},_decorStyle:{state:!0},_decorDraft:{state:!0},_decorSel:{state:!0},_decorTextDialog:{state:!0},_kioskDialog:{state:!0},_vacFit:{state:!0},_kioskDots:{state:!0},_areaSel:{state:!0},_nameSel:{state:!0},_roomDialog:{state:!0},_roomEditId:{state:!0},_roomFill:{state:!0},_roomTempSrc:{state:!0},_roomHumSrc:{state:!0},_roomSrcOpen:{state:!0},_roomSrcFilter:{state:!0},_roomNameScale:{state:!0},_roomLabelScale:{state:!0},_spaceDialog:{state:!0},_infoCard:{state:!0},_rulesDialog:{state:!0},_settingsDialog:{state:!0},_importDialog:{state:!0},_markerDialog:{state:!0},_zoom:{state:!0},_view:{state:!0}},io.ZOOM_MAX=8,io.ZOOM_MIN=.4,io._touchSeen=!1,io._noHoverMq="undefined"!=typeof window&&"function"==typeof window.matchMedia&&window.matchMedia("(hover: none)").matches,io.styles=Ts,customElements.get("houseplan-card")||customElements.define("houseplan-card",io),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.55.0 ","background:#3ea6ff;color:#04121f;font-weight:700","");
+1 -1
View File
@@ -2989,4 +2989,4 @@ const t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow
</button>`}
</div>
</div>
</div>`}}io.properties={_hdrH:{state:!0},_tapConfirm:{state:!0},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},_mode:{state:!0},_tool:{state:!0},_rszSel:{state:!0},_rszLive:{state:!0},_path:{state:!0},_cursorPt:{state:!0},_mergeSel:{state:!0},_openingDialog:{state:!0},_openingInfo:{state:!0},_mergeDialog:{state:!0},_splitSel:{state:!0},_decorTool:{state:!0},_decorStyle:{state:!0},_decorDraft:{state:!0},_decorSel:{state:!0},_decorTextDialog:{state:!0},_kioskDialog:{state:!0},_vacFit:{state:!0},_kioskDots:{state:!0},_areaSel:{state:!0},_nameSel:{state:!0},_roomDialog:{state:!0},_roomEditId:{state:!0},_roomFill:{state:!0},_roomTempSrc:{state:!0},_roomHumSrc:{state:!0},_roomSrcOpen:{state:!0},_roomSrcFilter:{state:!0},_roomNameScale:{state:!0},_roomLabelScale:{state:!0},_spaceDialog:{state:!0},_infoCard:{state:!0},_rulesDialog:{state:!0},_settingsDialog:{state:!0},_importDialog:{state:!0},_markerDialog:{state:!0},_zoom:{state:!0},_view:{state:!0}},io.ZOOM_MAX=8,io.ZOOM_MIN=.4,io._touchSeen=!1,io._noHoverMq="undefined"!=typeof window&&"function"==typeof window.matchMedia&&window.matchMedia("(hover: none)").matches,io.styles=Ts,customElements.get("houseplan-card")||customElements.define("houseplan-card",io),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.54.3 ","background:#3ea6ff;color:#04121f;font-weight:700","");
</div>`}}io.properties={_hdrH:{state:!0},_tapConfirm:{state:!0},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},_mode:{state:!0},_tool:{state:!0},_rszSel:{state:!0},_rszLive:{state:!0},_path:{state:!0},_cursorPt:{state:!0},_mergeSel:{state:!0},_openingDialog:{state:!0},_openingInfo:{state:!0},_mergeDialog:{state:!0},_splitSel:{state:!0},_decorTool:{state:!0},_decorStyle:{state:!0},_decorDraft:{state:!0},_decorSel:{state:!0},_decorTextDialog:{state:!0},_kioskDialog:{state:!0},_vacFit:{state:!0},_kioskDots:{state:!0},_areaSel:{state:!0},_nameSel:{state:!0},_roomDialog:{state:!0},_roomEditId:{state:!0},_roomFill:{state:!0},_roomTempSrc:{state:!0},_roomHumSrc:{state:!0},_roomSrcOpen:{state:!0},_roomSrcFilter:{state:!0},_roomNameScale:{state:!0},_roomLabelScale:{state:!0},_spaceDialog:{state:!0},_infoCard:{state:!0},_rulesDialog:{state:!0},_settingsDialog:{state:!0},_importDialog:{state:!0},_markerDialog:{state:!0},_zoom:{state:!0},_view:{state:!0}},io.ZOOM_MAX=8,io.ZOOM_MIN=.4,io._touchSeen=!1,io._noHoverMq="undefined"!=typeof window&&"function"==typeof window.matchMedia&&window.matchMedia("(hover: none)").matches,io.styles=Ts,customElements.get("houseplan-card")||customElements.define("houseplan-card",io),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.55.0 ","background:#3ea6ff;color:#04121f;font-weight:700","");
+47
View File
@@ -1,5 +1,52 @@
# Changelog
## v1.55.0 — 2026-08-01
Minor release: rooms are no longer set in stone — a dedicated Resize
tool in the plan editor changes their size by dragging walls; plus the
two findings of the v1.54.3 audit (HP-1543-01/02).
- **Room resize — a new «Размер» tool in the plan editor** (spec:
docs/RESIZE.md). Every wall gets a handle at its midpoint; drag it
and the whole wall moves, staying parallel to itself, with grid
snap. Works for polygons (L-shapes included) and for legacy
rectangles alike.
- **Shared walls always move together.** If the dragged wall coincides
with a neighbour's boundary, the neighbour follows: your room grows,
the neighbour shrinks — gaps and overlaps cannot appear by
construction. At T-junctions only the coinciding stretch follows,
inserting new corners into the neighbour's outline where needed.
- **Live numbers while you drag.** The dragged wall and its two
adjacent walls show their lengths in real meters/feet, and the room
area in m² updates live at the room centre — for a shared wall, the
areas of both rooms.
- **The wall stops where it must.** Rooms cannot get thinner than
~30 cm (neither yours nor the neighbour's), an outline never crosses
itself, a growing wall stops at foreign rooms and island rooms, and
doors and windows are anchors: an opening travels with its wall, and
a wall carrying openings can never get too short for them.
- **A scale frame for the whole room.** Click a room in the resize
tool to select it: dragging a corner of the dashed frame scales the
outline proportionally, with the same stops applied.
- **Esc and Ctrl+Z.** Esc cancels the current drag and puts the
original geometry back; one released drag is one undo step, and
Ctrl+Z walks back up to 30 of them while the tool is active.
- **Fix: room overlap detection missed equal-height rectangles slid
over each other.** Found while building the resize stops; the
slide-over case now counts as an overlap everywhere the check is
consulted, including the draw tool.
- **Fix (HP-1543-01): editor zoom stayed on screen after a floor
switch made inside the editor.** Exiting an editor on a different
floor than the one you started on skipped the viewport restore and
left the editor working zoom in view mode. Such an exit now falls
back to the current floor's saved view zoom.
- **Fix (HP-1543-02): a motion sensor re-tripped mid-flash stayed
invisible.** A rapid off→on before the current flash ended kept the
old CSS animation timeline, so the second detection played nothing.
Every witnessed trip now gets a fresh animation identity and the
flash restarts; under reduced motion the static ring stays, as
before.
## v1.54.3 — 2026-08-01
Patch release: three quality-of-life rounds — icon satellites now follow
+47
View File
@@ -6,6 +6,53 @@
> **Правило проекта:** оба файла пополняются в одном коммите с самим
> изменением — как и остальная документация (см. docs/STATUS.md).
## v1.55.0 — 2026-08-01
Минорный релиз: комнаты больше не высечены в камне — новый инструмент
«Размер» в редакторе плана меняет их габариты перетаскиванием стен;
плюс обе находки аудита v1.54.3 (HP-1543-01/02).
- **Ресайз комнат — новый инструмент «Размер» в редакторе плана**
(спека: docs/RESIZE.md). У каждой стены появляется ручка в середине;
тяните её — и стена едет целиком, оставаясь параллельной себе, с
привязкой к сетке. Работает и для полигонов (включая Г-образные), и
для старых прямоугольников.
- **Общие стены всегда двигаются вместе.** Если перетаскиваемая стена
совпадает с границей соседа, сосед следует за ней: ваша комната
растёт — соседняя сжимается, щели и наложения не появляются по
построению. На Т-стыках следует только совпадающий отрезок, при
необходимости в контур соседа вставляются новые вершины.
- **Живые цифры во время перетаскивания.** Перетаскиваемая стена и две
смежные показывают длины в реальных метрах/футах, а площадь комнаты
в м² обновляется в центре комнаты вживую — для общей стены — площади
обеих комнат.
- **Стена упирается там, где должна.** Комната не может стать тоньше
~30 см (ни своя, ни соседская), контур не пересекает сам себя,
растущая стена останавливается о чужие комнаты и острова, а двери и
окна — якоря: проём едет вместе со стеной, и стена с проёмами не
может стать для них слишком короткой.
- **Рамка масштабирования всей комнаты.** Клик по комнате в
инструменте выбирает её: перетаскивание уголка пунктирной рамки
пропорционально масштабирует контур — с теми же упорами.
- **Esc и Ctrl+Z.** Esc отменяет текущее перетаскивание и возвращает
исходную геометрию; одно отпускание ручки — один шаг отмены, Ctrl+Z
откатывает до 30 шагов, пока инструмент активен.
- **Исправлено: детекция наложения комнат пропускала равновысокие
прямоугольники, надвинутые друг на друга.** Найдено при постройке
упоров ресайза; slide-over теперь считается наложением везде, где
используется эта проверка, включая инструмент рисования.
- **Исправлено (HP-1543-01): редакторский зум оставался на экране
после смены этажа внутри редактора.** Выход из редактора на другом
этаже, чем тот, где начинали, пропускал восстановление вьюпорта и
оставлял рабочий зум редактора в режиме просмотра. Теперь такой
выход откатывается к сохранённому view-зуму текущего этажа.
- **Исправлено (HP-1543-02): датчик движения, сработавший повторно
посреди вспышки, оставался невидимым.** Быстрое off→on до конца
текущей вспышки не перезапускало CSS-анимацию — второе срабатывание
ничего не проигрывало. Теперь каждый зафиксированный trip получает
новую идентичность анимации, и вспышка стартует заново; при
prefers-reduced-motion остаётся статичное кольцо, как и раньше.
## v1.54.3 — 2026-08-01
Патч-релиз: три раунда качества жизни — спутники значка теперь слушаются
+2 -2
View File
@@ -15,12 +15,12 @@
| Item | State |
|---|---|
| Version | **v1.54.3** everywhere (manifest, const.py, package.json, CARD_VERSION); deployed to the home instance |
| Version | **v1.55.0** everywhere (manifest, const.py, package.json, CARD_VERSION); deployed to the home instance |
| Workflow | Since 2026-07-22: minor changes go to branch **`dev`** (build + smokes → deploy home → commit → push, NO release); releases are batched on the owner's command (merge dev→main, one tag, one release with a summary changelog, CI checked on dev beforehand) |
| GitHub | https://github.com/Matysh/houseplan-card — **`main` carries every published release, the latest tag is the current version above**; `dev` is where work lands and is merged into `main` at release time (so `dev` is normally equal to or ahead of `main`, never behind). Push via SSH key `ha_jb` (remote git@github.com:…); API releases via the fine-grained PAT in `~/.git-credentials` (Contents R/W, issued 2026-07-23) |
| CI | validate.yml (hacs + hassfest + frontend + backend) green; release.yml attaches the bundle on release publish |
| HACS | Custom repository works. **Inclusion PR: hacs/default#9004** — open, valid, labeled, mergeable clean, never drafted. Queue: 1212 open, 835 older than ours. Merge rate COLLAPSED: 75 in July but almost all in the first decade, 0 in the last week (checked 2026-07-29) — maintainers process in rare bursts; ETA unknowable, months at best. Nothing actionable on our side |
| Home instance | ha.jbstudio.pro (SSH port **22222**, key `ha_jb`; HA config root is `/mnt/data/supervisor/homeassistant` — `/config` does NOT exist in this SSH environment), deployed **v1.54.3** via direct copy (HACS custom repo also installed) |
| Home instance | ha.jbstudio.pro (SSH port **22222**, key `ha_jb`; HA config root is `/mnt/data/supervisor/homeassistant` — `/config` does NOT exist in this SSH environment), deployed **v1.55.0** via direct copy (HACS custom repo also installed) |
| Localization | UI en/ru (src/i18n/*.json), everything user-visible localized incl. kiosk popover |
| Tests | Four layers: frontend unit (`npm test`, node:test over `test-build/`), pure backend (`pytest tests_backend`, runs anywhere), HA-harness backend (same folder, CI only — needs py3.13 + pytest-homeassistant-custom-component), and browser smokes (`demo/smoke_*.mjs`, headless chromium). **Counts are not written down here** — they went stale within two releases while the version line beside them was kept current, which reads as less coverage than exists (review R5-2). Run `npm run inventory` for the current numbers, or read them off the last CI run |
| Vacuums | Live robot vacuums shipped (docs/VACUUM.md): puck, server-side trails with display modes, fit-panel calibration. Verified on a live Dreame X50 Master |
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "houseplan-card",
"version": "1.54.3",
"version": "1.55.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "houseplan-card",
"version": "1.54.3",
"version": "1.55.0",
"license": "MIT",
"dependencies": {
"lit": "^3.1.3",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "houseplan-card",
"version": "1.54.3",
"version": "1.55.0",
"description": "Interactive house plan Lovelace card for Home Assistant",
"license": "MIT",
"type": "module",
+1 -1
View File
@@ -46,7 +46,7 @@ import { cardStyles } from './styles';
import { fitInSquare, contentBounds, spaceModels } from './space-geometry';
import { langOf, t, type I18nKey } from './i18n';
const CARD_VERSION = '1.54.3';
const CARD_VERSION = '1.55.0';
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_ZOOM = 'houseplan_card_zoom_v1';