Skip to content

Commit b6c6611

Browse files
committed
Refactor: extract managers from GridLayout god object
Split the 1387-line GridLayout class into a coordinator (~526 lines) plus three focused manager classes: - BackgroundManager: background image lifecycle, template evaluation - OverlayManager: overlay DOM, state-driven activation, tester panel - SectionConfigManager: section CRUD, YAML editor modal Also extracted static CSS to grid-styles.ts (~451 lines), added shared constants.ts for CSS class names/IDs, removed 8 pass-through wrapper methods, and added 56 new manager tests (215 total, up from 159).
1 parent 29cdb63 commit b6c6611

13 files changed

Lines changed: 2399 additions & 967 deletions

CLAUDE.md

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,19 @@ The project registers one custom element (`sections-grid-layout`) and two patche
2424
├── src/
2525
│ ├── main.ts # Entry point
2626
│ ├── types.ts # Shared TypeScript interfaces
27+
│ ├── constants.ts # CSS class names, IDs, data attributes
2728
│ ├── helpers.ts # Selector options constant
2829
│ ├── template.ts # Template evaluation (pure functions)
2930
│ ├── grid-utils.ts # Grid area parsing and section helpers (pure functions)
3031
│ ├── yaml.ts # YAML serializer/parser (pure functions)
3132
│ ├── styles.ts # CSS generation, section/overlay style computation (pure functions)
3233
│ ├── layouts/
33-
│ │ └── grid.ts # <sections-grid-layout> -- main file
34+
│ │ ├── grid.ts # <sections-grid-layout> -- main coordinator
35+
│ │ └── grid-styles.ts # Static CSS for the component
36+
│ ├── managers/
37+
│ │ ├── background-manager.ts # Background image lifecycle
38+
│ │ ├── overlay-manager.ts # Overlay creation, state, tester panel
39+
│ │ └── section-config-manager.ts # Section CRUD, YAML editor modal
3440
│ └── patches/
3541
│ ├── hui-view-editor.ts # Adds "Sections Grid" to view type dropdown
3642
│ └── hui-card-element-editor.ts # Preserves view_layout on card save
@@ -39,7 +45,10 @@ The project registers one custom element (`sections-grid-layout`) and two patche
3945
│ ├── grid-utils.test.ts
4046
│ ├── yaml.test.ts
4147
│ ├── styles.test.ts
42-
│ └── build-output.test.ts
48+
│ ├── build-output.test.ts
49+
│ ├── background-manager.test.ts
50+
│ ├── overlay-manager.test.ts
51+
│ └── section-config-manager.test.ts
4352
├── rollup.config.js
4453
├── tsconfig.json
4554
├── vitest.config.ts
@@ -68,27 +77,38 @@ npm run test:watch # Watch mode for tests
6877

6978
```
7079
LitElement
71-
└── GridLayout (src/layouts/grid.ts)
80+
└── GridLayout (src/layouts/grid.ts) ← coordinator
81+
├── BackgroundManager (src/managers/background-manager.ts)
82+
├── OverlayManager (src/managers/overlay-manager.ts)
83+
└── SectionConfigManager (src/managers/section-config-manager.ts)
7284
```
7385

74-
`GridLayout` extends `LitElement` directly (no base class).
86+
`GridLayout` extends `LitElement` directly (no base class). It coordinates three managers that own distinct subsystems.
7587

76-
### `grid.ts`
88+
### `grid.ts` (coordinator)
7789
- **CSS Grid rendering**: Applies `grid-template-areas/columns/rows` from `layout` config
78-
- **Section management**: Creates/destroys `hui-section` wrappers; maintains `_sectionsCache`; auto-saves new sections to lovelace config
79-
- **Jinja template evaluation**: Calls pure functions from `template.ts` for `{{ states() }}`, `{{ state_attr() }}`, `{% if %}` in `custom_css`; tracks entities in `_trackedEntities`; debounced via `requestAnimationFrame`
80-
- **Background images**: Fixed positioning, blur, opacity, template support
81-
- **Kiosk mode**: `layout.kiosk: true` makes `#root` fixed-position, filling viewport below HA header; edit-mode offset adjusts for tab bar
90+
- **Section placement**: Creates `hui-section` wrappers; maintains `_sectionsCache`
91+
- **Jinja template evaluation**: Calls pure functions from `template.ts`; tracks entities in `_trackedEntities`; debounced via `requestAnimationFrame`
92+
- **Kiosk mode**: `layout.kiosk: true` makes `#root` fixed-position
8293
- **Layout zoom**: `layout.zoom` applies CSS `zoom` to `#root`
83-
- **Per-section styling**: `scrollable`, `background`, `backdrop_blur`, `zoom`, `overflow`, `padding`, `tint`, `variables`, `mediaquery` on each section
84-
- **Edit mode UI**: Section labels with grid-area name; loose-cards container for orphan cards; overlay tester panel
94+
- **Per-section styling**: `scrollable`, `background`, `backdrop_blur`, `zoom`, `overflow`, `padding`, `tint`, `variables`, `mediaquery`
95+
- **Edit mode UI**: Section labels with grid-area name; loose-cards container
8596
- **`_updateSectionsLovelace()`**: Pushes fresh `lovelace` AND fresh `config` to each `hui-section`
8697

98+
### `grid-styles.ts`
99+
Static CSS for the component (~450 lines). Includes section containers, YAML editor modal, overlay animations, and overlay tester panel styling.
100+
101+
### Managers
102+
- **`BackgroundManager`**: Owns background image lifecycle — creates a fixed-position div on `document.body`, handles template evaluation for dynamic URLs, manages blur/opacity. State: `_lastBackgroundImage`, `_bgElementId`.
103+
- **`OverlayManager`**: Owns overlay DOM elements, state-driven activation/deactivation, animation triggering, and the edit-mode test panel. State: `_overlayStates`, `_dialogObserver`.
104+
- **`SectionConfigManager`**: Owns section config CRUD (create/update/delete sections in lovelace config), auto-creation of missing sections for grid areas, and the YAML editor modal. State: `_savingConfig`.
105+
87106
### Extracted utility modules (pure functions, testable without DOM)
88107
- **`template.ts`**: `evaluateCssTemplates()`, `evaluateOverlayContent()`, `extractEntitiesFromTemplate()`
89108
- **`grid-utils.ts`**: `detectAllGridAreas()`, `formatAreaName()`, `ensureSectionsForAllAreas()`
90109
- **`yaml.ts`**: `sectionConfigToYaml()`, `yamlScalar()`, `parseYaml()`
91110
- **`styles.ts`**: CSS generators (kiosk, tint, blur, zoom, variables, mediaquery), section/overlay style computation, breakpoint resolution
111+
- **`constants.ts`**: Shared CSS class names, element IDs, data attributes, and selectors
92112

93113
### `patches/hui-view-editor.ts`
94114
Adds `sections-grid-layout` to the view type dropdown. Guard flag `_sectionsGridLayoutPatched` prevents double-patching when layout-card is also loaded.
@@ -101,11 +121,13 @@ Preserves `view_layout` when the card element editor saves changes.
101121
## Code Conventions
102122

103123
- Private methods/props: `_` prefix
104-
- Constants: `UPPER_SNAKE_CASE`
124+
- Constants: `UPPER_SNAKE_CASE` (in `constants.ts`)
105125
- `@property()` for external props, `@state()` for internal state
106126
- Clean up observers in `disconnectedCallback()`
107127
- Debounce heavy ops with `requestAnimationFrame`
108128
- Lit 3 only
129+
- Manager classes are instantiated in `firstUpdated()` and cleaned up in `disconnectedCallback()`
130+
- CSS class names used in JS should reference constants from `constants.ts`
109131

110132
---
111133

@@ -124,11 +146,16 @@ Preserves `view_layout` when the card element editor saves changes.
124146

125147
| Task | File |
126148
|---|---|
127-
| Grid rendering / section logic | `src/layouts/grid.ts` |
149+
| Grid rendering / section placement | `src/layouts/grid.ts` |
150+
| Component CSS | `src/layouts/grid-styles.ts` |
151+
| Background image handling | `src/managers/background-manager.ts` |
152+
| Overlay creation & state | `src/managers/overlay-manager.ts` |
153+
| Section config CRUD & YAML editor | `src/managers/section-config-manager.ts` |
128154
| Template evaluation | `src/template.ts` |
129155
| Grid area parsing | `src/grid-utils.ts` |
130156
| YAML serializer/parser | `src/yaml.ts` |
131157
| CSS generation / styling | `src/styles.ts` |
158+
| CSS class/ID constants | `src/constants.ts` |
132159
| Shared types | `src/types.ts` |
133160
| View type dropdown | `src/patches/hui-view-editor.ts` |
134161
| view_layout preservation | `src/patches/hui-card-element-editor.ts` |

0 commit comments

Comments
 (0)