|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Commands |
| 6 | + |
| 7 | +```bash |
| 8 | +npm install # install dependencies |
| 9 | +npm run build # production build → dist/house-card.js |
| 10 | +npm run dev # watch mode (rebuilds on save) |
| 11 | +npm run lint # lint src/**/*.js with eslint |
| 12 | +``` |
| 13 | + |
| 14 | +After building, copy `dist/house-card.js` to `/config/www/house-card.js` on the Home Assistant instance. |
| 15 | + |
| 16 | +## Architecture |
| 17 | + |
| 18 | +This is a HACS-compatible Lovelace custom card for Home Assistant, built with **Lit 3** and bundled by **Rollup**. |
| 19 | + |
| 20 | +### Source files (`src/`) |
| 21 | + |
| 22 | +- **`src/house-card.js`** — Main display card (`house-card` custom element). Extends `LitElement`. Receives `hass` (HA state object) and `_config` as properties. Renders a grid-based floorplan using percentage-positioned `div` elements; no canvas or SVG. Reads entity states via `this._hass.states[entityId]`. Registers itself in `window.customCards` for HA discovery. |
| 23 | + |
| 24 | +- **`src/house-card-editor.js`** — Visual config editor (`house-card-editor` custom element). Returned by `HouseCard.getConfigElement()`. Manages a three-state internal UI (`floors` → `grid` → `room`) with mouse-drag room painting. Fires `config-changed` custom events (bubbling, composed) to communicate config updates back to HA. |
| 25 | + |
| 26 | +### Build output |
| 27 | + |
| 28 | +Rollup bundles both source files plus the Lit library into a single **`dist/house-card.js`** ES module. The root-level `house-card.js` is also a fully bundled artifact (minified). |
| 29 | + |
| 30 | +### Config schema |
| 31 | + |
| 32 | +``` |
| 33 | +{ |
| 34 | + type: 'custom:house-card', |
| 35 | + title: string, |
| 36 | + floors: [{ id, name, cols, rows, rooms: [{ id, name, col, row, width, height, color, entities: { light?, occupancy?, temperature? } }] }] |
| 37 | +} |
| 38 | +``` |
| 39 | + |
| 40 | +Rooms use percentage-based positioning derived from `col/cols` and `row/rows`. The grid canvas uses `padding-bottom: (rows/cols * 100)%` to maintain aspect ratio, so the card scales automatically to any card width with no configuration. |
| 41 | + |
| 42 | +### HA integration points |
| 43 | + |
| 44 | +- `set hass(value)` — called by HA on every state change; triggers re-render |
| 45 | +- `setConfig(config)` — called by HA when card config changes |
| 46 | +- `static getConfigElement()` — returns editor element |
| 47 | +- `static getStubConfig()` — returns a valid starting config with one empty ground floor (shown in card picker) |
| 48 | +- Entity states checked: `light.*` (on/off), `binary_sensor.*` (on/off for occupancy), `sensor.*` (numeric state + `unit_of_measurement` attribute for temperature) |
| 49 | + |
| 50 | +### Key implementation patterns |
| 51 | + |
| 52 | +**Config-changed pattern:** The editor fires `config-changed` on every mutation (add/delete floor, add/delete room, update entity). The config object is always deep-cloned before mutation to avoid reference issues. This is the standard HA editor contract — HA catches the event and updates dashboard YAML in real time. |
| 53 | + |
| 54 | +**Overlap detection:** On drag complete, the new rectangle is checked against all existing rooms using AABB intersection before prompting for a name. Overlapping drags are silently discarded. |
| 55 | + |
| 56 | +**Room colour assignment:** Auto-assigned from an 8-colour palette (`ROOM_COLORS` array in `house-card-editor.js`) using modulo on current room count. Stored in the room config object; used for editor overlays. |
| 57 | + |
| 58 | +**HACS release:** `.github/workflows/release.yml` auto-builds and attaches `dist/house-card.js` to any published GitHub release. HACS downloads this single file. |
| 59 | + |
| 60 | +## Build status & roadmap |
| 61 | + |
| 62 | +**Phase 1 (grid editor) — complete.** Floor tabs, grid size picker, click-drag room drawing, overlap detection, room colour assignment, delete rooms. |
| 63 | + |
| 64 | +**Phase 2 (entity binding + runtime display) — complete.** Per-room entity binding in editor; runtime light/occupancy/temperature state display. |
| 65 | + |
| 66 | +**Phase 3 — TODO:** |
| 67 | + |
| 68 | +| Task | Notes | |
| 69 | +|------|-------| |
| 70 | +| `ha-entity-picker` swap | Replace the three text inputs in the ROOM editor state with `ha-entity-picker`. Import from `../../components/ha-entity-picker.js` — check HA version for correct import path. | |
| 71 | +| Touch/pointer events | Grid painter uses `mousedown/mousemove/mouseup`. Add `pointerdown/pointermove/pointerup` equivalents for tablet/touchscreen. | |
| 72 | +| Room rename | Add name input to the ROOM editor state — currently the name is fixed at creation time. | |
| 73 | +| Side-by-side wallboard layout | Currently always shows tabs; add a mode where floors render side-by-side for large displays. | |
| 74 | +| Light group support | Currently expects a single light entity; extend to handle `group` on/off aggregate. | |
| 75 | + |
| 76 | +## Environment |
| 77 | + |
| 78 | +HA instance runs on an M2 Mac Mini via Docker. After building, symlink or copy `dist/house-card.js` to `/config/www/house-card.js`, then add the resource in HA: |
| 79 | + |
| 80 | +```yaml |
| 81 | +resources: |
| 82 | + - url: /local/house-card.js |
| 83 | + type: module |
| 84 | +``` |
0 commit comments