@glasshome/widget-sdk 0.4.1 → 0.5.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.
@@ -1,44 +1,12 @@
1
- /**
2
- * WidgetSliderFill Component
3
- *
4
- * Animated fill overlay that follows a slider value. Background and glow are
5
- * rendered by the `.glasshome-widget-slider-fill` CSS rule in tokens.css via
6
- * the channel vars (`--widget-icon-color` with fallback to `--widget-color`).
7
- * The `color` prop is the optional per-fill override: when provided it is
8
- * written inline as `--widget-icon-color`, mirroring `Widget.Icon.color`
9
- * (Phase 26 VIS-A05). Orientation is inherited from the parent Widget context
10
- * and drives the `clip-path` direction.
11
- *
12
- * @example Default, inherits parent Widget channel color
13
- * ```tsx
14
- * <Widget tone="info" gestures={{ slide: { value, onChange } }}>
15
- * <Widget.SliderFill value={position} />
16
- * <Widget.Content>...</Widget.Content>
17
- * </Widget>
18
- * ```
19
- *
20
- * @example Per-fill override (sets --widget-icon-color, not background directly)
21
- * ```tsx
22
- * <Widget.SliderFill value={brightness} color={bulbColor} />
23
- * ```
24
- */
25
1
  import type { JSX } from "solid-js";
26
2
  interface WidgetSliderFillProps {
27
3
  /** Current value (0-100) */
28
4
  value: number;
29
- /**
30
- * Optional channel override: sets `--widget-icon-color` inline on the fill
31
- * root. When omitted the fill renders in the parent Widget's channel color
32
- * (var(--widget-color)). Mirrors Widget.Icon.color (Phase 26 VIS-A05).
33
- */
5
+ /** Per-fill channel override; sets --widget-icon-color inline. */
34
6
  color?: string;
35
- /** Whether the slider is currently being dragged (disables transition) */
7
+ /** Disables the fill transition while the user is dragging. */
36
8
  isDragging?: boolean;
37
- /** Additional CSS classes */
38
9
  class?: string;
39
10
  }
40
- /**
41
- * Animated slider fill that adapts to widget orientation.
42
- */
43
11
  export declare function WidgetSliderFill(props: WidgetSliderFillProps): JSX.Element;
44
12
  export {};
@@ -1,30 +1,7 @@
1
- /**
2
- * WidgetContent Component
3
- *
4
- * Standard content container for widgets with consistent padding, gap, and layout direction.
5
- *
6
- * Uses contentLayout (not orientation) for UI arrangement:
7
- * - Tall widgets (150px+) -> vertical layout (stacked)
8
- * - Other widgets -> follows aspect ratio
9
- *
10
- * @example
11
- * ```tsx
12
- * <Widget.Content>
13
- * <Widget.Icon icon={<Power />} />
14
- * <Widget.Title>Living Room</Widget.Title>
15
- * </Widget.Content>
16
- * ```
17
- */
18
1
  import type { JSX } from "solid-js";
19
2
  interface WidgetContentProps {
20
- /** Additional CSS classes */
21
3
  class?: string;
22
- /** Content children */
23
4
  children: JSX.Element;
24
5
  }
25
- /**
26
- * Widget content container with auto-responsive layout
27
- * Ensures proper z-index layering for title, status, and controls
28
- */
29
6
  export declare function WidgetContent(props: WidgetContentProps): JSX.Element;
30
7
  export {};
@@ -1,46 +1,12 @@
1
- /**
2
- * WidgetIcon Component
3
- *
4
- * Channel-driven icon. Background and glow read from `--widget-icon-color`
5
- * (with fallback to `--widget-color`) and `--widget-glow-strength` via the
6
- * `.glasshome-widget-icon` CSS rule in tokens.css. The `color` prop is the
7
- * optional per-icon override, pass any CSS color string (oklch, rgb, hex,
8
- * hsl, var(...)).
9
- *
10
- * @example Default, inherits the parent Widget's channel color
11
- * ```tsx
12
- * <Widget tone="info">
13
- * <Widget.Icon icon={<Power />} />
14
- * </Widget>
15
- * ```
16
- *
17
- * @example Per-icon override (e.g. light bulb showing its actual rgb_color)
18
- * ```tsx
19
- * <Widget.Icon icon={<Lightbulb />} color="oklch(0.85 0.2 60)" />
20
- * ```
21
- */
22
1
  import type { JSX } from "solid-js";
23
2
  interface WidgetIconProps {
24
- /** Icon component (JSX.Element) */
25
3
  icon: JSX.Element;
26
- /**
27
- * Optional CSS color string (oklch, hsl, rgb, hex, var()).
28
- * Sets `--widget-icon-color` inline on the icon root, overriding the
29
- * channel base color for the icon only. When omitted the channel's
30
- * `--widget-color` flows through via the tokens.css rule.
31
- * BREAKING (Phase 26): previously accepted Tailwind class strings.
32
- */
4
+ /** Per-icon channel override; sets --widget-icon-color inline. */
33
5
  color?: string;
34
- /** Reduce opacity */
35
6
  dimmed?: boolean;
36
7
  /** Number of entities, creates stacked background effect (1 = single, 2+ = stacked backgrounds) */
37
8
  entityCount?: number;
38
- /** Additional CSS classes */
39
9
  class?: string;
40
10
  }
41
- /**
42
- * Widget icon component with auto-responsive sizing.
43
- * Background + glow rendered by the `.glasshome-widget-icon` CSS rule.
44
- */
45
11
  export declare function WidgetIcon(props: WidgetIconProps): JSX.Element;
46
12
  export {};
@@ -1,27 +1,9 @@
1
- /**
2
- * WidgetStatus Component
3
- *
4
- * Status text component with auto-responsive typography.
5
- *
6
- * @example
7
- * ```tsx
8
- * <Widget.Status>{entity.state}</Widget.Status>
9
- * ```
10
- */
11
1
  import type { JSX } from "solid-js";
12
2
  interface WidgetStatusProps {
13
- /** Reduce opacity further */
14
3
  dimmed?: boolean;
15
- /** Additional CSS classes */
16
4
  class?: string;
17
- /** Show "Unavailable" text instead of children */
18
5
  isUnavailable?: boolean;
19
- /** Status text */
20
6
  children: JSX.Element;
21
7
  }
22
- /**
23
- * Widget status component with auto-responsive typography
24
- * Positioned above other content with proper z-index
25
- */
26
8
  export declare function WidgetStatus(props: WidgetStatusProps): JSX.Element;
27
9
  export {};
@@ -1,30 +1,8 @@
1
- /**
2
- * WidgetTitle Component
3
- *
4
- * Title component with automatic typography scaling and optional badge.
5
- *
6
- * @example
7
- * ```tsx
8
- * <Widget.Title>{config.title}</Widget.Title>
9
- * ```
10
- *
11
- * @example With badge
12
- * ```tsx
13
- * <Widget.Title badge={3}>Living Room</Widget.Title>
14
- * ```
15
- */
16
1
  import type { JSX } from "solid-js";
17
2
  interface WidgetTitleProps {
18
- /** Optional badge count */
19
3
  badge?: number;
20
- /** Additional CSS classes */
21
4
  class?: string;
22
- /** Title text */
23
5
  children: JSX.Element;
24
6
  }
25
- /**
26
- * Widget title component with auto-responsive typography
27
- * Positioned above other content with proper z-index
28
- */
29
7
  export declare function WidgetTitle(props: WidgetTitleProps): JSX.Element;
30
8
  export {};
@@ -1,32 +1,10 @@
1
- /**
2
- * WidgetValue Component
3
- *
4
- * Numeric value display with optional unit and semantic interpretation.
5
- *
6
- * @example
7
- * ```tsx
8
- * <Widget.Value value={22} unit="C" />
9
- * ```
10
- *
11
- * @example With interpretation
12
- * ```tsx
13
- * <Widget.Value value={22} unit="C" interpret />
14
- * // Displays: "22C Warm"
15
- * ```
16
- */
17
1
  import type { JSX } from "solid-js";
18
2
  interface WidgetValueProps {
19
- /** The value to display */
20
3
  value: number | string;
21
- /** Unit of measurement */
22
4
  unit?: string;
23
- /** Show semantic interpretation */
5
+ /** Show semantic interpretation (e.g. "Warm" for 22°C) */
24
6
  interpret?: boolean;
25
- /** Additional CSS classes */
26
7
  class?: string;
27
8
  }
28
- /**
29
- * Widget value component with auto-formatting and interpretation
30
- */
31
9
  export declare function WidgetValue(props: WidgetValueProps): JSX.Element;
32
10
  export {};
@@ -1,23 +1,12 @@
1
1
  /**
2
- * Widget - Main Container Component
2
+ * Widget main container component.
3
3
  *
4
- * The primary container for all widgets. Provides context, gesture handling,
5
- * and base styling.
6
- *
7
- * @example Simple widget
8
- * ```tsx
9
- * <Widget gestures={{ tap: handleTap }}>
10
- * <Widget.Icon icon={<Power />} />
11
- * <Widget.Title>{title}</Widget.Title>
12
- * </Widget>
13
- * ```
14
- *
15
- * @example With CSS gradient and loading
16
- * ```tsx
17
- * <Widget gradient="linear-gradient(135deg, oklch(0.7 0.2 30), oklch(0.5 0.18 270))" loading={isLoading}>
18
- * {children}
19
- * </Widget>
20
- * ```
4
+ * Renders the shell (gradient, border highlight, channel vars) and provides
5
+ * a minimal context (isEditMode, updateConfig) for slot components and host
6
+ * RPC. All visual scale (icon size, text size, padding, gap, content layout
7
+ * direction, slider fill orientation) lives in pure CSS via container queries
8
+ * on `.glasshome-widget`. The widget reacts to its own rendered box without
9
+ * any JS measurement.
21
10
  */
22
11
  import { type JSX } from "solid-js";
23
12
  import type { WidgetSliderFill as WidgetSliderFillType } from "../backgrounds/WidgetSliderFill";
@@ -27,58 +16,30 @@ import type { WidgetStatus as WidgetStatusType } from "../components/WidgetStatu
27
16
  import type { WidgetTitle as WidgetTitleType } from "../components/WidgetTitle";
28
17
  import type { WidgetValue as WidgetValueType } from "../components/WidgetValue";
29
18
  import type { GestureHandlers } from "../gestures/use-widget-gestures";
30
- import type { WidgetVariantConfig } from "../types";
31
19
  import type { Tone } from "../theming/tone";
20
+ import type { WidgetVariantConfig } from "../types";
32
21
  interface WidgetEmptyStateConfig {
33
- /** Icon to display */
34
22
  icon?: JSX.Element;
35
- /** Main title/heading */
36
23
  title?: string;
37
- /** Descriptive message */
38
24
  message?: string;
39
25
  }
40
26
  interface WidgetProps {
41
- /** Widget variant (string ID or inline config) */
42
27
  variant?: string | WidgetVariantConfig;
43
- /**
44
- * Semantic tone (success, warning, danger, info, neutral, accent).
45
- * Resolves to `--widget-color: var(--tone-{name})` inline on the widget root.
46
- * Phase 26 channel API, preferred path for state-driven semantic widgets.
47
- */
28
+ /** Semantic tone; resolves to `--widget-color: var(--tone-{name})`. */
48
29
  tone?: Tone;
49
- /**
50
- * CSS color string (oklch, hsl, hex, rgb, var()).
51
- * Sets `--widget-color` directly. Overrides `tone` when both supplied.
52
- */
30
+ /** CSS color override for `--widget-color`. Overrides `tone`. */
53
31
  color?: string;
54
- /**
55
- * Optional second-stop CSS color string for two-stop gradient identity.
56
- * Sets `--widget-color-to`. When omitted the shell formula falls back to `--widget-color`.
57
- */
32
+ /** Second-stop gradient color (`--widget-color-to`). */
58
33
  colorTo?: string;
59
- /**
60
- * Full CSS gradient string (e.g. `linear-gradient(135deg, oklch(...), oklch(...))`).
61
- * Sets `--widget-gradient` and overrides the auto-derived shell gradient verbatim.
62
- * BREAKING (Phase 26): previously accepted Tailwind class strings; now expects raw CSS.
63
- */
34
+ /** Full CSS gradient string (`--widget-gradient`); overrides the auto-shell. */
64
35
  gradient?: string;
65
- /** Show loading overlay */
66
36
  loading?: boolean;
67
- /** Additional CSS classes */
68
37
  class?: string;
69
- /** Is edit mode (disables gestures) */
70
38
  isEditMode?: boolean;
71
- /** Called when delete button is clicked (only shown in edit mode) */
72
39
  onDelete?: () => void;
73
- /** Empty state configuration, when provided shows empty state UI inside the shell */
74
40
  emptyState?: WidgetEmptyStateConfig;
75
- /**
76
- * Gesture handlers from `useWidgetGestures`. When provided, Widget binds
77
- * pointer events on its outer container and wires the size observer so
78
- * widget authors don't need a gesture wrapper div. Suppressed in edit mode.
79
- */
41
+ /** Gesture handlers from `useWidgetGestures`. */
80
42
  gestures?: GestureHandlers;
81
- /** Child elements */
82
43
  children?: JSX.Element;
83
44
  }
84
45
  interface WidgetComponent {
@@ -18,7 +18,8 @@
18
18
  * Pointer type is decided per press at pointerdown. A hybrid device (tablet
19
19
  * + bluetooth mouse) gets the right grammar based on which input fired.
20
20
  */
21
- import type { GestureConfig, WidgetOrientation } from "../types";
21
+ import type { GestureConfig } from "../types";
22
+ type GestureOrientation = "horizontal" | "vertical" | "square";
22
23
  export interface GestureHandlers {
23
24
  onPointerDown: (e: PointerEvent) => void;
24
25
  onPointerMove: (e: PointerEvent) => void;
@@ -41,4 +42,5 @@ export interface GestureHandlers {
41
42
  /** Cancel any pending hold timer. Call on component unmount via onCleanup. */
42
43
  dispose: () => void;
43
44
  }
44
- export declare function useWidgetGestures(config: () => GestureConfig, orientation?: () => WidgetOrientation): GestureHandlers;
45
+ export declare function useWidgetGestures(config: () => GestureConfig, orientation?: () => GestureOrientation): GestureHandlers;
46
+ export {};
@@ -3,6 +3,6 @@
3
3
  *
4
4
  * Hooks for widget development: context, dialog, entity group.
5
5
  */
6
- export { type BridgeableWidgetContext, type BridgeFns, type ReactiveWidgetContext, useWidgetContext, WidgetCtx, } from "./use-widget-context";
6
+ export { type ReactiveWidgetContext, useWidgetContext, WidgetCtx, } from "./use-widget-context";
7
7
  export { useWidgetDialog, type WidgetDialogReturn } from "./use-widget-dialog";
8
8
  export { type AggregationPreset, type UseWidgetEntityGroupOptions, type UseWidgetEntityGroupResult, useWidgetEntityGroup, } from "./use-widget-entity-group";
@@ -1,69 +1,25 @@
1
1
  /**
2
- * Widget Context Hook
2
+ * Reactive widget context.
3
3
  *
4
- * Provides access to widget context (size, orientation, dimensions, edit mode).
4
+ * Visual scale (icon size, text size, padding, layout direction) lives in
5
+ * CSS via container queries on `.glasshome-widget`. This context only
6
+ * carries:
7
+ * - host RPC (updateConfig)
8
+ * - edit-mode flag
9
+ * - raw measured dimensions (for widgets that branch rendered content
10
+ * based on size — e.g. hide a forecast strip on small chips).
5
11
  *
6
- * @example
7
- * ```tsx
8
- * const ctx = useWidgetContext();
9
- *
10
- * return (
11
- * <div>
12
- * {ctx.size() !== "xs" && <DetailedMetrics />}
13
- * {ctx.orientation() === "vertical" && <VerticalLayout />}
14
- * </div>
15
- * );
16
- * ```
17
- */
18
- import type { WidgetDimensions, WidgetOrientation, WidgetSize } from "../types";
19
- /**
20
- * Reactive widget context value
21
- * Uses accessor functions for SolidJS fine-grained reactivity
12
+ * Widgets decide their own thresholds; there is no shared size tier.
22
13
  */
14
+ export interface WidgetDimensions {
15
+ width: number;
16
+ height: number;
17
+ }
23
18
  export interface ReactiveWidgetContext {
24
- /** Widget size classification accessor */
25
- size: () => WidgetSize;
26
- /** Widget orientation accessor (for gestures - pure aspect ratio) */
27
- orientation: () => WidgetOrientation;
28
- /** Content layout direction accessor (for UI arrangement - considers height) */
29
- contentLayout: () => WidgetOrientation;
30
- /** Widget dimensions accessor */
31
- dimensions: () => WidgetDimensions;
32
- /** Whether widget is in edit mode */
33
19
  isEditMode: () => boolean;
34
- /** Update widget config (persists to host) */
35
20
  updateConfig: (config: Record<string, unknown>) => void;
21
+ /** Measured shell dimensions in CSS px. (0,0) before first layout. */
22
+ dimensions: () => WidgetDimensions;
36
23
  }
37
- /**
38
- * Setter functions used by Widget.tsx to write real measured values into
39
- * the stub context created by WidgetSlot before Widget mounts and measures.
40
- */
41
- export interface BridgeFns {
42
- setSize: (v: WidgetSize) => void;
43
- setOrientation: (v: WidgetOrientation) => void;
44
- setContentLayout: (v: WidgetOrientation) => void;
45
- setDimensions: (v: WidgetDimensions) => void;
46
- setIsStub: (v: boolean) => void;
47
- }
48
- /**
49
- * Bridgeable widget context — extends ReactiveWidgetContext with internal
50
- * fields used by the host (WidgetSlot + Widget.tsx) to make stub accessors
51
- * reactive. Widget authors never see or use these fields; useWidgetContext()
52
- * still returns ReactiveWidgetContext.
53
- */
54
- export interface BridgeableWidgetContext extends ReactiveWidgetContext {
55
- /** True while Widget has not yet measured and updated the stub values */
56
- _isStub: () => boolean;
57
- /** Setter functions called by Widget.tsx createEffect to push real values */
58
- _bridge: BridgeFns;
59
- }
60
- /**
61
- * Widget context
62
- * Uses reactive accessor pattern for SolidJS
63
- */
64
24
  export declare const WidgetCtx: import("solid-js").Context<ReactiveWidgetContext | undefined>;
65
- /**
66
- * Access widget context
67
- * @throws Error if used outside Widget component
68
- */
69
25
  export declare function useWidgetContext(): ReactiveWidgetContext;
@@ -37,9 +37,9 @@ export { WidgetTitle } from "./components/WidgetTitle";
37
37
  export { WidgetValue } from "./components/WidgetValue";
38
38
  export { WidgetSliderFill } from "./backgrounds/WidgetSliderFill";
39
39
  export { WidgetDialog, type WidgetDialogProps, type WidgetDialogTab } from "./dialogs";
40
- export { type AggregationPreset, type BridgeableWidgetContext, type BridgeFns, type ReactiveWidgetContext, type UseWidgetEntityGroupOptions, type UseWidgetEntityGroupResult, useWidgetContext, useWidgetDialog, useWidgetEntityGroup, WidgetCtx, type WidgetDialogReturn, } from "./hooks";
40
+ export { type AggregationPreset, type ReactiveWidgetContext, type UseWidgetEntityGroupOptions, type UseWidgetEntityGroupResult, useWidgetContext, useWidgetDialog, useWidgetEntityGroup, WidgetCtx, type WidgetDialogReturn, } from "./hooks";
41
41
  export { type GestureHandlers, useWidgetGestures } from "./gestures/use-widget-gestures";
42
42
  export { injectTokens, type Tone, ToneSchema, } from "./theming";
43
43
  export { widgetFields } from "./fields";
44
44
  export { calculateLightGroup, calculateSensorGroup, countActiveEntities, getEntityAttribute, isEntityActive, type LightGroupResult, type SensorGroupResult, type SensorGroupType, } from "./utils";
45
- export type { EntityView, WidgetContextValue, WidgetDimensions, WidgetOrientation, WidgetSize, WidgetStyles, WidgetVariantConfig, } from "./types";
45
+ export type { EntityView, WidgetStyles, WidgetVariantConfig, } from "./types";
@@ -1,54 +1,6 @@
1
1
  /** Core type definitions for the Widget Framework. */
2
2
  import type { JSX } from "solid-js";
3
- /**
4
- * Widget size classification based on grid dimensions
5
- * - xs: Small widgets (1x1, 1x2)
6
- * - sm: Medium-small widgets (2x1, 2x2)
7
- * - md: Medium widgets (2x3, 2x4)
8
- * - lg: Large widgets (2x6, 3x6, 4x2)
9
- * - xl: Extra large widgets (4x4)
10
- */
11
- export type WidgetSize = "xs" | "sm" | "md" | "lg" | "xl";
12
- /**
13
- * Widget orientation based on aspect ratio
14
- * - horizontal: width > height
15
- * - vertical: height > width
16
- * - square: width === height
17
- */
18
- export type WidgetOrientation = "horizontal" | "vertical" | "square";
19
- /**
20
- * Widget dimensions in both pixels and grid units
21
- */
22
- export interface WidgetDimensions {
23
- /** Pixel width */
24
- width: number;
25
- /** Pixel height */
26
- height: number;
27
- /** Grid columns (1-4) */
28
- gridWidth: number;
29
- /** Grid rows (1-6) */
30
- gridHeight: number;
31
- }
32
- /**
33
- * Widget context provided to all child components.
34
- * Values are plain (not accessors) -- the context provider
35
- * will supply reactive accessors wrapping these.
36
- */
37
- export interface WidgetContextValue {
38
- /** Widget size classification */
39
- size: WidgetSize;
40
- /** Widget orientation (for gestures - pure aspect ratio) */
41
- orientation: WidgetOrientation;
42
- /** Content layout direction (for UI arrangement - considers height) */
43
- contentLayout: WidgetOrientation;
44
- /** Widget dimensions */
45
- dimensions: WidgetDimensions;
46
- /** Whether widget is in edit mode */
47
- isEditMode: boolean;
48
- }
49
- /**
50
- * Slide gesture configuration
51
- */
3
+ /** Slide gesture configuration */
52
4
  export interface SlideGestureConfig {
53
5
  /** Current value */
54
6
  value: number;
@@ -83,10 +35,6 @@ export interface GestureConfig {
83
35
  /** Slide gesture configuration */
84
36
  slide?: SlideGestureConfig;
85
37
  }
86
- /**
87
- * Spacing scale
88
- */
89
- export type SpacingScale = "S1" | "S2" | "S3" | "S4";
90
38
  /**
91
39
  * CSS variable-based styling configuration
92
40
  */
@@ -221,8 +169,13 @@ export interface EntityView {
221
169
  domain: EntityDomain;
222
170
  /** Current state value */
223
171
  state: string;
224
- /** Entity attributes */
225
- attributes: Record<string, any>;
172
+ /**
173
+ * Entity attributes from Home Assistant, excluding keys that are
174
+ * surfaced as canonical resolved fields elsewhere on EntityView
175
+ * (`deviceClass`, `unitOfMeasurement`, `friendlyName`, `icon`).
176
+ * Use those fields instead of reaching into `attributes`.
177
+ */
178
+ attributes: Omit<Record<string, any>, "device_class" | "unit_of_measurement" | "friendly_name" | "icon">;
226
179
  /** When the state last changed */
227
180
  lastChanged: Date;
228
181
  /** When the state was last updated (even if unchanged) */