preact-homeassistant 0.2.3 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -15,7 +15,7 @@ pnpm add preact preact-homeassistant
15
15
  ## Quick start
16
16
 
17
17
  ```tsx
18
- import { registerPreactCard, useEntity, css } from 'preact-homeassistant';
18
+ import { registerPreactCard, HACard, useEntity, css } from 'preact-homeassistant';
19
19
 
20
20
  css`
21
21
  .my-card { padding: 16px; }
@@ -26,11 +26,11 @@ function MyCardContent({ config }: { config: { entity: string } }) {
26
26
  const weather = useEntity(config.entity);
27
27
 
28
28
  return (
29
- <ha-card>
29
+ <HACard>
30
30
  <div class="card-content my-card">
31
31
  <span class="temperature">{weather?.state ?? '...'}</span>
32
32
  </div>
33
- </ha-card>
33
+ </HACard>
34
34
  );
35
35
  }
36
36
 
@@ -87,6 +87,33 @@ prop and uses hooks for everything else.
87
87
  The card renders into a Shadow DOM root. The editor renders into the light DOM
88
88
  (required for HA's own custom elements like `<ha-select>` to work).
89
89
 
90
+ ## `<HACard>`
91
+
92
+ Use `HACard` as the root of your card instead of a raw `<ha-card>`. It makes the
93
+ card fill the height Home Assistant assigns it.
94
+
95
+ In HA's **sections (grid)** layout, when a card is resized (e.g. to 3 rows) HA
96
+ gives the card's host element a definite height. A plain `<ha-card>` collapses to
97
+ its natural content height and renders slightly short, leaving a gap. `HACard`
98
+ sets the host and the `ha-card` to fill that height, so the card matches the slot
99
+ exactly. In layouts with no fixed height (masonry, auto rows) it safely collapses
100
+ back to natural height, so it's a drop-in replacement everywhere.
101
+
102
+ ```tsx
103
+ <HACard class="size-large" align="space-between">
104
+ <div class="card-content my-card">…</div>
105
+ </HACard>
106
+ ```
107
+
108
+ | Prop | Type | Default | Description |
109
+ |---|---|---|---|
110
+ | `align` | `HACardAlign` | `'top'` | How content is distributed vertically when the slot is taller than the content. Friendly aliases `top` / `center` / `bottom`, or any flex `justify-content` value (`space-between`, `space-around`, `space-evenly`, `flex-start`, `flex-end`). |
111
+ | `class` | `string` | — | Class applied to the underlying `ha-card`. |
112
+ | `children` | `ComponentChildren` | — | Card contents. |
113
+
114
+ `align` only positions content as a block. To make an inner section *stretch* to
115
+ absorb the extra height, give it `flex: 1` in your card's CSS.
116
+
90
117
  ## Hooks
91
118
 
92
119
  ### `useEntity(entityId)`
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { ComponentChildren } from 'preact';
2
2
  import { ComponentType } from 'preact';
3
3
  import { Connection } from 'home-assistant-js-websocket';
4
+ import { createElement } from 'preact';
4
5
  import { HassConfig } from 'home-assistant-js-websocket';
5
6
  import { HassEntities } from 'home-assistant-js-websocket';
6
7
  import { HassEntity } from 'home-assistant-js-websocket';
@@ -10,6 +11,12 @@ import { HassServices } from 'home-assistant-js-websocket';
10
11
  import { JSX } from 'preact';
11
12
  import { RefObject } from 'preact';
12
13
 
14
+ declare type Cache_2 = Map<string, CacheEntry<unknown>>;
15
+
16
+ declare interface CacheEntry<T> {
17
+ data: T;
18
+ }
19
+
13
20
  /**
14
21
  * Calendar entity - only exposes the current/next event.
15
22
  * Use useCalendarEvents() to fetch a list of events.
@@ -147,11 +154,23 @@ export declare type ForecastType = 'daily' | 'hourly' | 'twice_daily';
147
154
  */
148
155
  export declare function getAllStyles(): string;
149
156
 
150
- export declare function HAProvider({ hass, subscribeToEntity, children }: HAProviderProps): JSX.Element;
157
+ export declare function HACard({ align, class: className, children }: HACardProps): createElement.JSX.Element;
158
+
159
+ export declare type HACardAlign = 'top' | 'center' | 'bottom' | 'flex-start' | 'flex-end' | 'space-between' | 'space-around' | 'space-evenly';
160
+
161
+ declare interface HACardProps {
162
+ align?: HACardAlign;
163
+ class?: string;
164
+ children?: ComponentChildren;
165
+ }
166
+
167
+ export declare function HAProvider({ hass, subscribeToEntity, subscribeToHass, cache, children, }: HAProviderProps): JSX.Element;
151
168
 
152
169
  declare interface HAProviderProps {
153
170
  hass: HomeAssistant | undefined;
154
171
  subscribeToEntity: (entityId: string, callback: (entity: any) => void) => () => void;
172
+ subscribeToHass?: SubscribeToHass;
173
+ cache?: Cache_2;
155
174
  children: ComponentChildren;
156
175
  }
157
176
 
@@ -174,8 +193,6 @@ declare type KnownDomain = keyof DomainEntityMap;
174
193
 
175
194
  declare type KnownServiceDomain = keyof DomainServiceMap;
176
195
 
177
- export declare function loadFromCache<T>(key: string): T | undefined;
178
-
179
196
  export declare function registerPreactCard<TConfig>(options: RegisterPreactCardOptions<TConfig>): void;
180
197
 
181
198
  declare interface RegisterPreactCardOptions<TConfig> {
@@ -202,8 +219,6 @@ export declare function registerRawStyles(styles: string): void;
202
219
 
203
220
  export declare type ResizeCallback = (size: ElementSize) => void;
204
221
 
205
- export declare function saveToCache<T>(key: string, data: T): void;
206
-
207
222
  declare type ServiceCaller<T extends string> = <S extends keyof ServicesForId<T> & string>(service: S, ...args: ServicesForId<T>[S] extends undefined ? [] : Record<string, never> extends Exclude<ServicesForId<T>[S], undefined> ? [data?: ServicesForId<T>[S]] : [data: ServicesForId<T>[S]]) => Promise<void>;
208
223
 
209
224
  /**
@@ -214,6 +229,8 @@ declare type ServiceCaller<T extends string> = <S extends keyof ServicesForId<T>
214
229
  */
215
230
  export declare type ServicesForId<T extends string> = T extends `${infer D}.${string}` ? D extends KnownServiceDomain ? DomainServiceMap[D] : Record<string, Record<string, unknown> | undefined> : Record<string, Record<string, unknown> | undefined>;
216
231
 
232
+ declare type SubscribeToHass = (callback: () => void) => () => void;
233
+
217
234
  /**
218
235
  * Sun entity - provides sunrise/sunset and elevation information.
219
236
  */
@@ -247,18 +264,29 @@ declare interface UseCachedFetchResult<T> {
247
264
  }
248
265
 
249
266
  /**
250
- * Fetch calendar events for a date range from a single calendar.
267
+ * Fetch events from one or more calendars for a date range, with in-memory
268
+ * (per-card) caching and stale-while-revalidate behavior. Events are tagged
269
+ * with their source calendar ID. Returns `prefetch` to warm adjacent ranges.
251
270
  */
252
- export declare function useCalendarEvents(entityId: `calendar.${string}`, options: {
271
+ export declare function useCalendarEvents(entityIds: `calendar.${string}`[], options: {
253
272
  start: Date;
254
273
  end: Date;
255
274
  }): UseCalendarEventsResult;
256
275
 
257
276
  declare interface UseCalendarEventsResult {
258
- events: CalendarEvent[] | undefined;
259
- loading: boolean;
277
+ events: CalendarEventWithSource[] | undefined;
278
+ status: FetchStatus;
260
279
  error: Error | undefined;
261
280
  refetch: () => void;
281
+ /**
282
+ * Warm the cache for an arbitrary range (e.g. adjacent months) without
283
+ * touching component state. Best-effort: skips ranges already cached and
284
+ * swallows failures.
285
+ */
286
+ prefetch: (range: {
287
+ start: Date;
288
+ end: Date;
289
+ }) => void;
262
290
  }
263
291
 
264
292
  /**
@@ -270,6 +298,9 @@ declare interface UseCalendarEventsResult {
270
298
  */
271
299
  export declare function useCallbackStable<T extends (...args: never[]) => unknown>(callback: T): T;
272
300
 
301
+ /** Re-renders when the active theme's dark mode flips. */
302
+ export declare function useDarkMode(): boolean;
303
+
273
304
  /**
274
305
  * Subscribe to a specific entity by ID. Re-renders only when that entity changes.
275
306
  *
@@ -289,21 +320,17 @@ export declare function useHass(): {
289
320
  getHass: () => HomeAssistant | undefined;
290
321
  };
291
322
 
323
+ /** Re-renders when `hass.config` changes (units, latitude/longitude, etc.). */
324
+ export declare function useHassConfig(): HomeAssistant['config'] | undefined;
325
+
292
326
  /**
293
- * Fetch events from multiple calendars for a date range, with localStorage
294
- * caching. Events are tagged with their source calendar ID.
327
+ * Subscribe to a derived slice of the `hass` object (e.g. config, themes) and
328
+ * re-render only when that slice changes. Use this for non-entity values —
329
+ * entity state goes through `useEntity`. The selector runs on every hass update
330
+ * but only re-renders the consumer when `isEqual` reports a change, so it's
331
+ * cheap for rarely-changing values like config/themes.
295
332
  */
296
- export declare function useMultiCalendarEvents(entityIds: `calendar.${string}`[], options: {
297
- start: Date;
298
- end: Date;
299
- }): UseMultiCalendarEventsResult;
300
-
301
- declare interface UseMultiCalendarEventsResult {
302
- events: CalendarEventWithSource[] | undefined;
303
- status: FetchStatus;
304
- error: Error | undefined;
305
- refetch: () => void;
306
- }
333
+ export declare function useHassValue<T>(selector: (hass: HomeAssistant | undefined) => T, isEqual?: (a: T, b: T) => boolean): T;
307
334
 
308
335
  /**
309
336
  * Observe an element's size via ResizeObserver. The callback fires: