# @design.estate/dees-element
A powerful custom element base class that extends Lit's `LitElement` with integrated theming, responsive CSS utilities, RxJS-powered directives, and DOM tooling — so you can build web components that look great and stay reactive out of the box.
## Issue Reporting and Security
For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
## Install
```bash
npm install @design.estate/dees-element
# or
pnpm install @design.estate/dees-element
```
This package ships as ESM and is written in TypeScript. Make sure your project targets ES2022+ with a modern module resolution strategy (e.g. `NodeNext`).
## Usage
Everything you need is exported from the main entry point:
```typescript
import {
DeesElement,
customElement,
property,
state,
html,
css,
cssManager,
directives,
} from '@design.estate/dees-element';
```
### 🧱 Creating a Custom Element
Extend `DeesElement` and apply the `@customElement` decorator:
```typescript
import { DeesElement, customElement, html, css, cssManager } from '@design.estate/dees-element';
@customElement('my-button')
class MyButton extends DeesElement {
static styles = [
cssManager.defaultStyles,
css`
.btn {
padding: 8px 16px;
border-radius: 4px;
background: ${cssManager.bdTheme('#0060df', '#3a8fff')};
color: ${cssManager.bdTheme('#fff', '#fff')};
border: none;
cursor: pointer;
}
`,
];
render() {
return html``;
}
}
```
That single `bdTheme()` call generates a CSS variable that automatically flips between the bright and dark values when the user's theme changes — no manual toggling needed.
### 🎨 Theme Management with `cssManager`
The singleton `cssManager` is the central hub for theming and responsive layout:
| Method | Purpose |
|---|---|
| `cssManager.defaultStyles` | Base styles for consistent element rendering |
| `cssManager.bdTheme(bright, dark)` | Returns a `CSSResult` that auto-switches between bright/dark values |
| `cssManager.cssForDesktop(css)` | Media-query wrapper for desktop breakpoints |
| `cssManager.cssForNotebook(css)` | Media-query wrapper for notebook breakpoints |
| `cssManager.cssForTablet(css)` | Media-query wrapper for tablet breakpoints |
| `cssManager.cssForPhablet(css)` | Media-query wrapper for phablet breakpoints |
| `cssManager.cssForPhone(css)` | Media-query wrapper for phone breakpoints |
| `cssManager.cssGridColumns(cols, gap)` | Generates CSS grid column widths |
Example — responsive + themed styles:
```typescript
@customElement('my-card')
class MyCard extends DeesElement {
static styles = [
cssManager.defaultStyles,
css`
:host {
display: block;
padding: 16px;
background: ${cssManager.bdTheme('#ffffff', '#1e1e1e')};
color: ${cssManager.bdTheme('#111', '#eee')};
border-radius: 8px;
}
`,
cssManager.cssForPhone(css`
:host { padding: 8px; }
`),
];
render() {
return html`
Current theme: ${this.goBright ? 'bright' : 'dark'}
`; } } ``` ### 🚀 Lifecycle Helpers `DeesElement` adds lifecycle utilities on top of LitElement: ```typescript @customElement('my-widget') class MyWidget extends DeesElement { constructor() { super(); // Runs once after the element is connected to the DOM this.registerStartupFunction(async () => { console.log('Widget connected!'); }); // Runs when the element is disconnected — perfect for cleanup this.registerGarbageFunction(() => { console.log('Widget removed'); }); } render() { return html`Hello World
`; } } ``` Additionally, `this.elementDomReady` is a promise that resolves after `firstUpdated`, which is handy when you need to wait for the initial render: ```typescript await this.elementDomReady; // The element's shadow DOM is now fully rendered ``` ### 📡 Directives The `directives` namespace includes powerful template helpers, accessible via `directives.*`: #### `resolve` — Render a Promise ```typescript import { html, directives } from '@design.estate/dees-element'; render() { return html`${directives.resolve(this.fetchData())}`; } ``` #### `resolveExec` — Resolve a lazy async function ```typescript render() { return html`${directives.resolveExec(() => this.loadContent())}`; } ``` #### `subscribe` — Render an RxJS Observable ```typescript import { html, directives } from '@design.estate/dees-element'; render() { return html`${directives.subscribe(this.count$)}`; } ``` #### `subscribeWithTemplate` — Observable + template transform ```typescript render() { return html` ${directives.subscribeWithTemplate( this.items$, (items) => html`