@glasshome/widget-sdk 1.9.3 → 1.10.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/dist/data.d.ts CHANGED
@@ -6,6 +6,6 @@
6
6
  * store. Phase 4 routes these through capability checks.
7
7
  */
8
8
  export { getForecasts, getStream, getWebRtcClientConfig, hassMediaUrl, sendWebRtcCandidate, startWebRtcSession, state, trackEntityHistory, untrackEntityHistory, } from "@glasshome/sync-layer";
9
- export type { AreaView } from "@glasshome/sync-layer";
10
- export { byDomain, useArea, useCamera, useConnection, useCurrency, useEntities, useEntity, useEntityHistory, useEntityStatistics, useForecast, useHassConfig, useLocale, useStore, useTemperatureUnit, useUnitSystem, } from "@glasshome/sync-layer/solid";
9
+ export type { AreaView, CalendarEvent, CalendarEventsData, CalendarWindowOptions, } from "@glasshome/sync-layer";
10
+ export { byDomain, useArea, useCalendarEvents, useCamera, useConnection, useCurrency, useEntities, useEntity, useEntityHistory, useEntityStatistics, useForecast, useHassConfig, useLocale, useStore, useTemperatureUnit, useUnitSystem, } from "@glasshome/sync-layer/solid";
11
11
  export { useService, useToggle, useTurnOff, useTurnOn } from "./framework/hooks/use-service";
@@ -1,4 +1,5 @@
1
- import { type Component, type JSX } from "solid-js";
1
+ import type { Button as UIButton, ResponsiveDialog as UIResponsiveDialog, ResponsiveDialogContent as UIResponsiveDialogContent, ResponsiveDialogDescription as UIResponsiveDialogDescription, ResponsiveDialogHeader as UIResponsiveDialogHeader, ResponsiveDialogTitle as UIResponsiveDialogTitle, SchemaForm as UISchemaForm } from "@glasshome/ui/solid";
2
+ import { type JSX } from "solid-js";
2
3
  import type { ZodType } from "zod";
3
4
  export interface WidgetDialogTab {
4
5
  id: string;
@@ -28,12 +29,12 @@ export interface WidgetDialogProps {
28
29
  configSchema?: ZodType;
29
30
  config?: Record<string, unknown>;
30
31
  onConfigSave?: (config: Record<string, unknown>) => void;
31
- ResponsiveDialog: Component<any>;
32
- ResponsiveDialogContent: Component<any>;
33
- ResponsiveDialogHeader: Component<any>;
34
- ResponsiveDialogTitle: Component<any>;
35
- ResponsiveDialogDescription: Component<any>;
36
- Button: Component<any>;
37
- SchemaForm?: Component<any>;
32
+ ResponsiveDialog: typeof UIResponsiveDialog;
33
+ ResponsiveDialogContent: typeof UIResponsiveDialogContent;
34
+ ResponsiveDialogHeader: typeof UIResponsiveDialogHeader;
35
+ ResponsiveDialogTitle: typeof UIResponsiveDialogTitle;
36
+ ResponsiveDialogDescription: typeof UIResponsiveDialogDescription;
37
+ Button: typeof UIButton;
38
+ SchemaForm?: typeof UISchemaForm;
38
39
  }
39
40
  export declare function WidgetDialog(props: WidgetDialogProps): JSX.Element;
@@ -12,8 +12,13 @@ export interface WidgetDimensions {
12
12
  height: number;
13
13
  }
14
14
  /** Capability-routed service call: an RPC into the host's HA bridge worker,
15
- validated there against the widget's granted capabilities. */
16
- export type ServiceCallFn = (domain: string, service: string, serviceData?: Record<string, unknown>, target?: Record<string, unknown>) => Promise<void>;
15
+ validated there against the widget's granted capabilities. Pass
16
+ `{ returnResponse: true }` for services that return data (e.g.
17
+ `todo.get_items`); the resolved value is the HA service response, else
18
+ `undefined`. */
19
+ export type ServiceCallFn = (domain: string, service: string, serviceData?: Record<string, unknown>, target?: Record<string, unknown>, options?: {
20
+ returnResponse?: boolean;
21
+ }) => Promise<unknown>;
17
22
  export interface ReactiveWidgetContext {
18
23
  updateConfig: (config: Record<string, unknown>) => void;
19
24
  /**
package/dist/index.js CHANGED
@@ -2,14 +2,14 @@ import { deprecate as e, deprecations as t, formatDeprecation as n } from "./dep
2
2
  import { WidgetManifestSchema as r, formatSchemaError as i } from "./schemas.js";
3
3
  import { z as a, z as o } from "zod";
4
4
  import { getForecasts as s, getStream as c, getWebRtcClientConfig as l, hassMediaUrl as u, sendWebRtcCandidate as d, startWebRtcSession as f, state as p, trackEntityHistory as m, untrackEntityHistory as h } from "@glasshome/sync-layer";
5
- import { byDomain as g, useArea as _, useCamera as v, useConnection as ee, useCurrency as y, useEntities as b, useEntity as te, useEntityHistory as ne, useEntityStatistics as re, useForecast as x, useHassConfig as ie, useLocale as ae, useService as oe, useStore as se, useTemperatureUnit as S, useToggle as ce, useTurnOff as le, useTurnOn as ue, useUnitSystem as de } from "@glasshome/sync-layer/solid";
6
- import { Show as C, createContext as fe, createEffect as w, createMemo as T, createSignal as E, on as pe, onCleanup as D, onMount as me, splitProps as he, useContext as O } from "solid-js";
7
- import { addEventListener as k, className as A, createComponent as j, delegateEvents as ge, effect as M, insert as N, memo as P, setStyleProperty as F, style as _e, template as I, use as ve } from "solid-js/web";
8
- import { clsx as ye } from "clsx";
9
- import { twMerge as be } from "tailwind-merge";
10
- import { Badge as xe, Button as Se, ColorSlider as Ce, ColorWheel as we, Input as Te, Label as Ee, ResponsiveDialog as De, ResponsiveDialogContent as Oe, ResponsiveDialogDescription as ke, ResponsiveDialogHeader as Ae, ResponsiveDialogTitle as je, SchemaForm as Me, Select as Ne, SelectContent as Pe, SelectItem as Fe, SelectTrigger as Ie, SelectValue as Le, Slider as Re, Switch as ze, parseColor as Be } from "@glasshome/ui/solid";
5
+ import { byDomain as g, useArea as _, useCalendarEvents as v, useCamera as ee, useConnection as y, useCurrency as b, useEntities as te, useEntity as ne, useEntityHistory as re, useEntityStatistics as x, useForecast as ie, useHassConfig as ae, useLocale as oe, useService as S, useStore as se, useTemperatureUnit as ce, useToggle as le, useTurnOff as ue, useTurnOn as de, useUnitSystem as fe } from "@glasshome/sync-layer/solid";
6
+ import { Show as C, createContext as pe, createEffect as w, createMemo as T, createSignal as E, on as me, onCleanup as D, onMount as he, splitProps as ge, useContext as O } from "solid-js";
7
+ import { addEventListener as k, className as A, createComponent as j, delegateEvents as _e, effect as M, insert as N, memo as P, setStyleProperty as F, style as ve, template as I, use as ye } from "solid-js/web";
8
+ import { clsx as be } from "clsx";
9
+ import { twMerge as xe } from "tailwind-merge";
10
+ import { Badge as Se, Button as Ce, ColorSlider as we, ColorWheel as Te, Input as Ee, Label as De, ResponsiveDialog as Oe, ResponsiveDialogContent as ke, ResponsiveDialogDescription as Ae, ResponsiveDialogHeader as je, ResponsiveDialogTitle as Me, SchemaForm as Ne, Select as Pe, SelectContent as Fe, SelectItem as Ie, SelectTrigger as Le, SelectValue as Re, Slider as ze, Switch as Be, parseColor as Ve } from "@glasshome/ui/solid";
11
11
  //#region src/framework/to-form-schema.ts
12
- function Ve(e) {
12
+ function He(e) {
13
13
  return o.toJSONSchema(e, { override: (e) => {
14
14
  let t = o.globalRegistry.get(e.zodSchema);
15
15
  return t && typeof t == "object" && Object.keys(t).length > 0 ? {
@@ -18,7 +18,7 @@ function Ve(e) {
18
18
  } : e.jsonSchema;
19
19
  } });
20
20
  }
21
- function He(e) {
21
+ function Ue(e) {
22
22
  try {
23
23
  return e.parse({});
24
24
  } catch {
@@ -27,47 +27,49 @@ function He(e) {
27
27
  }
28
28
  //#endregion
29
29
  //#region src/define-widget.ts
30
- function Ue(e) {
31
- return e.configSchema && (e.manifest.schema || (e.manifest.schema = Ve(e.configSchema)), e.manifest.defaultConfig || (e.manifest.defaultConfig = He(e.configSchema))), e;
30
+ function We(e) {
31
+ return e.configSchema && (e.manifest.schema || (e.manifest.schema = He(e.configSchema)), e.manifest.defaultConfig || (e.manifest.defaultConfig = Ue(e.configSchema))), e;
32
32
  }
33
33
  //#endregion
34
34
  //#region src/framework/hooks/use-widget-context.ts
35
- var L = fe();
36
- function We() {
35
+ var L = pe();
36
+ function Ge() {
37
37
  let e = O(L);
38
38
  if (!e) throw Error("useWidgetContext must be used within a Widget component");
39
39
  return e;
40
40
  }
41
41
  //#endregion
42
42
  //#region src/framework/hooks/use-service.ts
43
- function Ge(e) {
43
+ function Ke(e) {
44
44
  let t = Array.isArray(e) ? e[0] : e, n = t?.split(".")[0];
45
45
  if (!n) throw Error(`Invalid entity ID: ${String(t)}`);
46
46
  return n;
47
47
  }
48
48
  function R(e, t) {
49
- return (n, r = {}) => e(Ge(n), t, r, { entity_id: n });
49
+ return async (n, r = {}) => {
50
+ await e(Ke(n), t, r, { entity_id: n });
51
+ };
50
52
  }
51
- function Ke() {
53
+ function qe() {
52
54
  let e = O(L)?.callService;
53
55
  return e ? {
54
56
  callService: e,
55
57
  turnOn: R(e, "turn_on"),
56
58
  turnOff: R(e, "turn_off"),
57
59
  toggle: R(e, "toggle")
58
- } : oe();
59
- }
60
- function qe() {
61
- let e = O(L)?.callService;
62
- return e ? R(e, "turn_on") : ue();
60
+ } : S();
63
61
  }
64
62
  function Je() {
65
63
  let e = O(L)?.callService;
66
- return e ? R(e, "turn_off") : le();
64
+ return e ? R(e, "turn_on") : de();
67
65
  }
68
66
  function Ye() {
69
67
  let e = O(L)?.callService;
70
- return e ? R(e, "toggle") : ce();
68
+ return e ? R(e, "turn_off") : ue();
69
+ }
70
+ function Xe() {
71
+ let e = O(L)?.callService;
72
+ return e ? R(e, "toggle") : le();
71
73
  }
72
74
  //#endregion
73
75
  //#region src/framework/design-system/z-index.ts
@@ -76,41 +78,41 @@ var z = {
76
78
  CONTENT: 10,
77
79
  OVERLAY: 20,
78
80
  ACTIONS: 30
79
- }, Xe = fe();
80
- function Ze() {
81
- let e = O(Xe);
81
+ }, Ze = pe();
82
+ function Qe() {
83
+ let e = O(Ze);
82
84
  if (!e) throw Error("useWidgetDimensions must be called inside <Widget>: move the call into a component rendered within <Widget> (the top-level widget scope only sees the host stub).");
83
85
  return e;
84
86
  }
85
87
  //#endregion
86
88
  //#region src/framework/theming/tokens.css?raw
87
- var Qe = "/* Authoritative SDK CSS contract. Injected once on first Widget mount\n * via framework/theming/tokens.ts.\n *\n * All widget-internal visual scale is driven from CSS custom properties +\n * container queries on the `.glasshome-widget` shell (`container-type: size`).\n * No JS classifier, no size tier enum.\n */\n\n:root {\n --tone-success: oklch(0.70 0.18 145);\n --tone-warning: oklch(0.80 0.17 75);\n --tone-danger: oklch(0.64 0.22 27);\n --tone-info: oklch(0.66 0.20 245);\n --tone-neutral: oklch(0.65 0.02 250);\n --tone-accent: oklch(0.74 0.18 60);\n\n --widget-grad-strength: 1;\n --widget-glow-default: 0.4;\n --widget-border-highlight: oklch(0.98 0 0 / 0.4);\n}\n\n.dark {\n --tone-success: oklch(0.74 0.18 145);\n --tone-warning: oklch(0.82 0.17 75);\n --tone-danger: oklch(0.68 0.22 27);\n --tone-info: oklch(0.70 0.20 245);\n --tone-neutral: oklch(0.69 0.02 250);\n --tone-accent: oklch(0.78 0.18 60);\n\n --widget-grad-strength: 1.1;\n --widget-glow-default: 0.5;\n --widget-border-highlight: oklch(1 0 0 / 0.08);\n}\n\n@property --widget-color {\n syntax: \"<color>\";\n inherits: true;\n initial-value: oklch(0.65 0.02 250);\n}\n\n/* === Widget shell ===\n * Fluid scale tokens — tied to the shell's own container box (cqb=height, cqi=width).\n * Icon/pad/gap track HEIGHT (cqb) not the shortest side: two widgets of equal\n * height match regardless of width (a 2×2 and a 4×2 get the same icon). cqmin\n * starved portrait tiles by pinning the icon to the narrow width. Tune\n * multipliers / clamps to adjust density. */\n.glasshome-widget {\n --widget-color: var(--tone-neutral);\n --widget-glow-strength: var(--widget-glow-default);\n\n --widget-icon-box: clamp(44px, 25cqb, 58px);\n --widget-icon-glyph: clamp(24px, 14cqb, 33px);\n --widget-pad: clamp(8px, 3.5cqb, 22px);\n --widget-gap: clamp(6px, 2cqb, 14px);\n --widget-title-size: clamp(12px, 2cqi, 18px);\n --widget-subtitle: clamp(12px, 2.5cqi, 20px);\n --widget-status-size: clamp(14px, 5cqi, 36px);\n --widget-value-size: clamp(18px, 7cqi, 48px);\n --widget-badge-size: clamp(11px, 1.6cqi, 14px);\n}\n\n/* Shell material. Two channels, both host/variant-driven:\n * - `--widget-backdrop`: the live backdrop filter (the shared glass recipe is\n * blur + saturate, matching ui's CARD_BLUR). Default none — a variant opts\n * in (classic-glass), and a performant-blur host disables it via override\n * sheet when it paints a precomputed frost instead.\n * - `--glass-frost`: one full background layer (image + position / size +\n * repeat) composited at the BOTTOM, under the accent gradient — the same\n * frost slot ui's `.glass` formula ends its background list with. Unset →\n * none. A performant-blur host sets it per shell with the viewport-aligned\n * slice of its pre-blurred bitmap. */\n.glasshome-widget {\n background:\n var(--widget-gradient,\n linear-gradient(135deg,\n color-mix(in oklch, var(--widget-color) calc(22% * var(--widget-grad-strength)), transparent),\n color-mix(in oklch, var(--widget-color-to, var(--widget-color)) calc(11% * var(--widget-grad-strength)), transparent)\n )\n ),\n var(--glass-frost, none);\n backdrop-filter: var(--widget-backdrop, none);\n -webkit-backdrop-filter: var(--widget-backdrop, none);\n box-shadow: inset 0 1px 0 var(--widget-border-highlight);\n}\n\n/* === Slot: content layout === */\n/* Default: column. Flip to row only on wide-and-short widgets (matches the\n * old contentLayout heuristic: aspect > 1 AND height < 150px). */\n.glasshome-widget-content {\n position: relative;\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n width: 100%;\n height: 100%;\n padding: var(--widget-pad);\n gap: var(--widget-gap);\n overflow: hidden;\n}\n@container widget (min-aspect-ratio: 1) and (max-height: 149px) {\n .glasshome-widget-content {\n flex-direction: row;\n align-items: center;\n justify-content: flex-start;\n }\n}\n\n/* === Compact 1×1 ===\n * Small in BOTH axes → stack the tile: icon on top, label + status centered\n * under it. Icon stays moderate (not a hero) so the text keeps room. Wide\n * tiles (2×1) fail the width test and keep the row layout above. Placed after\n * the row-flip so it wins. */\n@container widget (max-width: 189px) and (max-height: 189px) {\n .glasshome-widget-content {\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n gap: clamp(4px, 2.5cqmin, 8px);\n }\n .glasshome-widget-content > * { align-items: center; text-align: center; }\n .glasshome-widget-icon {\n --widget-icon-box: clamp(36px, 30cqmin, 56px);\n --widget-icon-glyph: clamp(20px, 17cqmin, 32px);\n }\n .glasshome-widget-title { font-size: clamp(11px, 6cqmin, 14px); max-width: 100%; }\n .glasshome-widget-status,\n .glasshome-widget-value { font-size: clamp(13px, 7cqmin, 17px); }\n .glasshome-widget-content [class*=\"ml-auto\"] { margin-left: 0 !important; }\n}\n.glasshome-widget-content [class*=\"ml-auto\"] {\n position: relative;\n z-index: 30;\n}\n\n/* === Slot: icon === */\n.glasshome-widget-icon {\n width: var(--widget-icon-box);\n height: var(--widget-icon-box);\n border-radius: var(--radius-sm, 12px);\n background: var(--widget-icon-color, var(--widget-color));\n box-shadow: 0 0 calc(var(--widget-glow-strength) * 30px)\n color-mix(in oklch, var(--widget-icon-color, var(--widget-color)) 50%, transparent);\n color: oklch(from var(--widget-icon-color, var(--widget-color)) calc(0.52 + sign(0.5 - l) * 0.43) calc(c * 0.2) h);\n}\n.glasshome-widget-icon-glyph {\n font-size: var(--widget-icon-glyph);\n line-height: 1;\n}\n.glasshome-widget-icon-stack {\n position: absolute;\n width: 102%;\n height: 102%;\n border-radius: var(--radius-sm, 12px);\n}\n.glasshome-widget-icon-stack-2 { bottom: -14%; right: -10%; opacity: 0.45; z-index: -2; }\n.glasshome-widget-icon-stack-3 { bottom: -28%; right: -20%; opacity: 0.20; z-index: -3; }\n\n/* === Slot: text === */\n.glasshome-widget-title {\n font-size: var(--widget-title-size);\n line-height: 1.2;\n color: color-mix(in oklch, var(--color-foreground, currentColor) 60%, transparent);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.glasshome-widget-subtitle {\n font-size: var(--widget-subtitle);\n color: color-mix(in oklch, var(--color-foreground, currentColor) 60%, transparent);\n}\n.glasshome-widget-status {\n font-size: var(--widget-status-size);\n font-weight: 700;\n color: var(--color-foreground, currentColor);\n line-height: 1.1;\n}\n.glasshome-widget-value {\n font-size: var(--widget-value-size);\n font-weight: 700;\n color: var(--color-foreground, currentColor);\n line-height: 1.05;\n}\n.glasshome-widget-badge {\n font-size: var(--widget-badge-size);\n font-weight: 500;\n padding: 0.125rem 0.5rem;\n border-radius: 9999px;\n background: color-mix(in oklch, var(--color-foreground, currentColor) 20%, transparent);\n color: var(--color-foreground, currentColor);\n}\n\n.glasshome-widget-loading {\n background: color-mix(in oklch, var(--widget-color) 20%, transparent);\n}\n\n/* === Slider fill ===\n * Value flows in via --widget-fill-value (0-100). Vertical orientation auto-\n * detected via container query. */\n.glasshome-widget-slider-fill {\n --widget-fill-value: 0;\n background: color-mix(in oklch, var(--widget-icon-color, var(--widget-color)) 30%, transparent);\n box-shadow: 0 0 calc(var(--widget-glow-strength) * 40px)\n color-mix(in oklch, var(--widget-icon-color, var(--widget-color)) 40%, transparent);\n clip-path: inset(0 calc((100 - var(--widget-fill-value)) * 1%) 0 0);\n}\n@container widget (max-aspect-ratio: 1) {\n .glasshome-widget-slider-fill {\n clip-path: inset(calc((100 - var(--widget-fill-value)) * 1%) 0 0 0);\n }\n}\n", $e = !1, B, et = /* @__PURE__ */ new WeakSet();
88
- function tt() {
89
- return B || (B = new CSSStyleSheet(), B.replaceSync(Qe.replace(/:root\b/g, ":host").replace(/^\.dark\b/gm, ":host(.dark)"))), B;
89
+ var $e = "/* Authoritative SDK CSS contract. Injected once on first Widget mount\n * via framework/theming/tokens.ts.\n *\n * All widget-internal visual scale is driven from CSS custom properties +\n * container queries on the `.glasshome-widget` shell (`container-type: size`).\n * No JS classifier, no size tier enum.\n */\n\n:root {\n --tone-success: oklch(0.70 0.18 145);\n --tone-warning: oklch(0.80 0.17 75);\n --tone-danger: oklch(0.64 0.22 27);\n --tone-info: oklch(0.66 0.20 245);\n --tone-neutral: oklch(0.65 0.02 250);\n --tone-accent: oklch(0.74 0.18 60);\n\n --widget-grad-strength: 1;\n --widget-glow-default: 0.4;\n --widget-border-highlight: oklch(0.98 0 0 / 0.4);\n}\n\n.dark {\n --tone-success: oklch(0.74 0.18 145);\n --tone-warning: oklch(0.82 0.17 75);\n --tone-danger: oklch(0.68 0.22 27);\n --tone-info: oklch(0.70 0.20 245);\n --tone-neutral: oklch(0.69 0.02 250);\n --tone-accent: oklch(0.78 0.18 60);\n\n --widget-grad-strength: 1.1;\n --widget-glow-default: 0.5;\n --widget-border-highlight: oklch(1 0 0 / 0.08);\n}\n\n@property --widget-color {\n syntax: \"<color>\";\n inherits: true;\n initial-value: oklch(0.65 0.02 250);\n}\n\n/* === Widget shell ===\n * Fluid scale tokens — tied to the shell's own container box (cqb=height, cqi=width).\n * Icon/pad/gap track HEIGHT (cqb) not the shortest side: two widgets of equal\n * height match regardless of width (a 2×2 and a 4×2 get the same icon). cqmin\n * starved portrait tiles by pinning the icon to the narrow width. Tune\n * multipliers / clamps to adjust density. */\n.glasshome-widget {\n --widget-color: var(--tone-neutral);\n --widget-glow-strength: var(--widget-glow-default);\n\n --widget-icon-box: clamp(44px, 25cqb, 58px);\n --widget-icon-glyph: clamp(24px, 14cqb, 33px);\n --widget-pad: clamp(8px, 3.5cqb, 22px);\n --widget-gap: clamp(6px, 2cqb, 14px);\n --widget-title-size: clamp(12px, 2cqi, 18px);\n --widget-subtitle: clamp(12px, 2.5cqi, 20px);\n --widget-status-size: clamp(14px, 5cqi, 36px);\n --widget-value-size: clamp(18px, 7cqi, 48px);\n --widget-badge-size: clamp(11px, 1.6cqi, 14px);\n}\n\n/* Shell material. Two channels, both host/variant-driven:\n * - `--widget-backdrop`: the live backdrop filter (the shared glass recipe is\n * blur + saturate, matching ui's CARD_BLUR). Default none — a variant opts\n * in (classic-glass), and a performant-blur host disables it via override\n * sheet when it paints a precomputed frost instead.\n * - `--glass-frost`: one full background layer (image + position / size +\n * repeat) composited at the BOTTOM, under the accent gradient — the same\n * frost slot ui's `.glass` formula ends its background list with. Unset →\n * none. A performant-blur host sets it per shell with the viewport-aligned\n * slice of its pre-blurred bitmap. */\n.glasshome-widget {\n background:\n var(--widget-gradient,\n linear-gradient(135deg,\n color-mix(in oklch, var(--widget-color) calc(22% * var(--widget-grad-strength)), transparent),\n color-mix(in oklch, var(--widget-color-to, var(--widget-color)) calc(11% * var(--widget-grad-strength)), transparent)\n )\n ),\n var(--glass-frost, none);\n backdrop-filter: var(--widget-backdrop, none);\n -webkit-backdrop-filter: var(--widget-backdrop, none);\n box-shadow: inset 0 1px 0 var(--widget-border-highlight);\n}\n\n/* === Slot: content layout === */\n/* Default: column. Flip to row only on wide-and-short widgets (matches the\n * old contentLayout heuristic: aspect > 1 AND height < 150px). */\n.glasshome-widget-content {\n position: relative;\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n width: 100%;\n height: 100%;\n padding: var(--widget-pad);\n gap: var(--widget-gap);\n overflow: hidden;\n}\n@container widget (min-aspect-ratio: 1) and (max-height: 149px) {\n .glasshome-widget-content {\n flex-direction: row;\n align-items: center;\n justify-content: flex-start;\n }\n}\n\n/* === Compact 1×1 ===\n * Small in BOTH axes → stack the tile: icon on top, label + status centered\n * under it. Icon stays moderate (not a hero) so the text keeps room. Wide\n * tiles (2×1) fail the width test and keep the row layout above. Placed after\n * the row-flip so it wins. */\n@container widget (max-width: 189px) and (max-height: 189px) {\n .glasshome-widget-content {\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n gap: clamp(4px, 2.5cqmin, 8px);\n }\n .glasshome-widget-content > * { align-items: center; text-align: center; }\n .glasshome-widget-icon {\n --widget-icon-box: clamp(36px, 30cqmin, 56px);\n --widget-icon-glyph: clamp(20px, 17cqmin, 32px);\n }\n .glasshome-widget-title { font-size: clamp(11px, 6cqmin, 14px); max-width: 100%; }\n .glasshome-widget-status,\n .glasshome-widget-value { font-size: clamp(13px, 7cqmin, 17px); }\n .glasshome-widget-content [class*=\"ml-auto\"] { margin-left: 0 !important; }\n}\n.glasshome-widget-content [class*=\"ml-auto\"] {\n position: relative;\n z-index: 30;\n}\n\n/* === Slot: icon === */\n.glasshome-widget-icon {\n width: var(--widget-icon-box);\n height: var(--widget-icon-box);\n border-radius: var(--radius-sm, 12px);\n background: var(--widget-icon-color, var(--widget-color));\n box-shadow: 0 0 calc(var(--widget-glow-strength) * 30px)\n color-mix(in oklch, var(--widget-icon-color, var(--widget-color)) 50%, transparent);\n color: oklch(from var(--widget-icon-color, var(--widget-color)) calc(0.52 + sign(0.5 - l) * 0.43) calc(c * 0.2) h);\n}\n.glasshome-widget-icon-glyph {\n font-size: var(--widget-icon-glyph);\n line-height: 1;\n}\n.glasshome-widget-icon-stack {\n position: absolute;\n width: 102%;\n height: 102%;\n border-radius: var(--radius-sm, 12px);\n}\n.glasshome-widget-icon-stack-2 { bottom: -14%; right: -10%; opacity: 0.45; z-index: -2; }\n.glasshome-widget-icon-stack-3 { bottom: -28%; right: -20%; opacity: 0.20; z-index: -3; }\n\n/* === Slot: text === */\n.glasshome-widget-title {\n font-size: var(--widget-title-size);\n line-height: 1.2;\n color: color-mix(in oklch, var(--color-foreground, currentColor) 60%, transparent);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.glasshome-widget-subtitle {\n font-size: var(--widget-subtitle);\n color: color-mix(in oklch, var(--color-foreground, currentColor) 60%, transparent);\n}\n.glasshome-widget-status {\n font-size: var(--widget-status-size);\n font-weight: 700;\n color: var(--color-foreground, currentColor);\n line-height: 1.1;\n}\n.glasshome-widget-value {\n font-size: var(--widget-value-size);\n font-weight: 700;\n color: var(--color-foreground, currentColor);\n line-height: 1.05;\n}\n.glasshome-widget-badge {\n font-size: var(--widget-badge-size);\n font-weight: 500;\n padding: 0.125rem 0.5rem;\n border-radius: 9999px;\n background: color-mix(in oklch, var(--color-foreground, currentColor) 20%, transparent);\n color: var(--color-foreground, currentColor);\n}\n\n.glasshome-widget-loading {\n background: color-mix(in oklch, var(--widget-color) 20%, transparent);\n}\n\n/* === Slider fill ===\n * Value flows in via --widget-fill-value (0-100). Vertical orientation auto-\n * detected via container query. */\n.glasshome-widget-slider-fill {\n --widget-fill-value: 0;\n background: color-mix(in oklch, var(--widget-icon-color, var(--widget-color)) 30%, transparent);\n box-shadow: 0 0 calc(var(--widget-glow-strength) * 40px)\n color-mix(in oklch, var(--widget-icon-color, var(--widget-color)) 40%, transparent);\n clip-path: inset(0 calc((100 - var(--widget-fill-value)) * 1%) 0 0);\n}\n@container widget (max-aspect-ratio: 1) {\n .glasshome-widget-slider-fill {\n clip-path: inset(calc((100 - var(--widget-fill-value)) * 1%) 0 0 0);\n }\n}\n", et = !1, B, tt = /* @__PURE__ */ new WeakSet();
90
+ function nt() {
91
+ return B || (B = new CSSStyleSheet(), B.replaceSync($e.replace(/:root\b/g, ":host").replace(/^\.dark\b/gm, ":host(.dark)"))), B;
90
92
  }
91
- function nt(e) {
93
+ function rt(e) {
92
94
  if (typeof ShadowRoot < "u" && e instanceof ShadowRoot) {
93
- if (et.has(e)) return;
94
- let t = tt();
95
- e.adoptedStyleSheets.includes(t) || (e.adoptedStyleSheets = [...e.adoptedStyleSheets, t]), et.add(e);
95
+ if (tt.has(e)) return;
96
+ let t = nt();
97
+ e.adoptedStyleSheets.includes(t) || (e.adoptedStyleSheets = [...e.adoptedStyleSheets, t]), tt.add(e);
96
98
  return;
97
99
  }
98
- if ($e) return;
100
+ if (et) return;
99
101
  let t = e ?? (typeof document > "u" ? void 0 : document);
100
102
  if (!t) return;
101
103
  if (t.head.querySelector?.("style[data-glasshome-tokens]")) {
102
- $e = !0;
104
+ et = !0;
103
105
  return;
104
106
  }
105
107
  let n = t.createElement("style");
106
- n.setAttribute("data-glasshome-tokens", ""), n.textContent = Qe, t.head.appendChild(n), $e = !0;
108
+ n.setAttribute("data-glasshome-tokens", ""), n.textContent = $e, t.head.appendChild(n), et = !0;
107
109
  }
108
110
  //#endregion
109
111
  //#region src/framework/utils/cn.ts
110
112
  function V(...e) {
111
- return be(ye(e));
113
+ return xe(be(e));
112
114
  }
113
- var rt = {
115
+ var it = {
114
116
  "classic-glass": {
115
117
  id: "classic-glass",
116
118
  name: "Classic Glass",
@@ -192,22 +194,22 @@ var rt = {
192
194
  }
193
195
  }
194
196
  };
195
- function it(e) {
196
- return rt[e];
197
+ function at(e) {
198
+ return it[e];
197
199
  }
198
200
  //#endregion
199
201
  //#region src/framework/backgrounds/WidgetSliderFill.tsx
200
- var at = /*#__PURE__*/ I("<div>");
201
- function ot(e) {
202
+ var ot = /*#__PURE__*/ I("<div>");
203
+ function st(e) {
202
204
  return (() => {
203
- var t = at();
205
+ var t = ot();
204
206
  return M((n) => {
205
207
  var r = V("glasshome-widget-slider-fill pointer-events-none absolute inset-0", e.isDragging ? "duration-0" : "transition-all duration-300 ease-out", e.class), i = {
206
208
  "--widget-fill-value": e.value,
207
209
  "z-index": z.BACKGROUND,
208
210
  ...e.color ? { "--widget-icon-color": e.color } : {}
209
211
  };
210
- return r !== n.e && A(t, n.e = r), n.t = _e(t, i, n.t), n;
212
+ return r !== n.e && A(t, n.e = r), n.t = ve(t, i, n.t), n;
211
213
  }, {
212
214
  e: void 0,
213
215
  t: void 0
@@ -216,37 +218,37 @@ function ot(e) {
216
218
  }
217
219
  //#endregion
218
220
  //#region src/framework/components/WidgetContent.tsx
219
- var st = /*#__PURE__*/ I("<div>");
220
- function ct(e) {
221
+ var ct = /*#__PURE__*/ I("<div>");
222
+ function lt(e) {
221
223
  return (() => {
222
- var t = st();
224
+ var t = ct();
223
225
  return N(t, () => e.children), M(() => A(t, V("glasshome-widget-content", e.class))), t;
224
226
  })();
225
227
  }
226
228
  //#endregion
227
229
  //#region src/framework/components/WidgetIcon.tsx
228
- var lt = /*#__PURE__*/ I("<div class=\"glasshome-widget-icon glasshome-widget-icon-stack glasshome-widget-icon-stack-2\">"), ut = /*#__PURE__*/ I("<div class=\"glasshome-widget-icon glasshome-widget-icon-stack glasshome-widget-icon-stack-3\">"), dt = /*#__PURE__*/ I("<div><div class=\"glasshome-widget-icon-glyph flex items-center justify-center\">");
229
- function ft(e) {
230
+ var ut = /*#__PURE__*/ I("<div class=\"glasshome-widget-icon glasshome-widget-icon-stack glasshome-widget-icon-stack-2\">"), dt = /*#__PURE__*/ I("<div class=\"glasshome-widget-icon glasshome-widget-icon-stack glasshome-widget-icon-stack-3\">"), ft = /*#__PURE__*/ I("<div><div class=\"glasshome-widget-icon-glyph flex items-center justify-center\">");
231
+ function pt(e) {
230
232
  let t = () => e.entityCount ?? 1;
231
233
  return (() => {
232
- var n = dt(), r = n.firstChild;
234
+ var n = ft(), r = n.firstChild;
233
235
  return N(n, j(C, {
234
236
  get when() {
235
237
  return t() >= 2;
236
238
  },
237
239
  get children() {
238
- return lt();
240
+ return ut();
239
241
  }
240
242
  }), r), N(n, j(C, {
241
243
  get when() {
242
244
  return t() >= 3;
243
245
  },
244
246
  get children() {
245
- return ut();
247
+ return dt();
246
248
  }
247
249
  }), r), N(r, () => e.icon), M((t) => {
248
250
  var r = V("glasshome-widget-icon", "relative flex shrink-0 items-center justify-center pointer-events-none transition-all", e.dimmed && "opacity-50", e.class), i = e.color ? { "--widget-icon-color": e.color } : void 0;
249
- return r !== t.e && A(n, t.e = r), t.t = _e(n, i, t.t), t;
251
+ return r !== t.e && A(n, t.e = r), t.t = ve(n, i, t.t), t;
250
252
  }, {
251
253
  e: void 0,
252
254
  t: void 0
@@ -255,10 +257,10 @@ function ft(e) {
255
257
  }
256
258
  //#endregion
257
259
  //#region src/framework/components/WidgetStatus.tsx
258
- var pt = /*#__PURE__*/ I("<p>");
259
- function mt(e) {
260
+ var mt = /*#__PURE__*/ I("<p>");
261
+ function ht(e) {
260
262
  return (() => {
261
- var t = pt();
263
+ var t = mt();
262
264
  return N(t, (() => {
263
265
  var t = P(() => !!e.isUnavailable);
264
266
  return () => t() ? "Unavailable" : e.children;
@@ -273,16 +275,16 @@ function mt(e) {
273
275
  }
274
276
  //#endregion
275
277
  //#region src/framework/components/WidgetTitle.tsx
276
- var ht = /*#__PURE__*/ I("<span class=\"glasshome-widget-badge shrink-0\">"), gt = /*#__PURE__*/ I("<div><h3 class=glasshome-widget-title>");
277
- function _t(e) {
278
+ var gt = /*#__PURE__*/ I("<span class=\"glasshome-widget-badge shrink-0\">"), _t = /*#__PURE__*/ I("<div><h3 class=glasshome-widget-title>");
279
+ function vt(e) {
278
280
  return (() => {
279
- var t = gt(), n = t.firstChild;
281
+ var t = _t(), n = t.firstChild;
280
282
  return N(n, () => e.children), N(t, j(C, {
281
283
  get when() {
282
284
  return P(() => e.badge !== void 0)() && e.badge > 0;
283
285
  },
284
286
  get children() {
285
- var t = ht();
287
+ var t = gt();
286
288
  return N(t, () => e.badge), t;
287
289
  }
288
290
  }), null), M((n) => {
@@ -296,7 +298,7 @@ function _t(e) {
296
298
  }
297
299
  //#endregion
298
300
  //#region src/framework/utils/entity-aggregation.ts
299
- function vt(e, t = !1) {
301
+ function yt(e, t = !1) {
300
302
  if (e.length === 0) return {
301
303
  isGroup: !1,
302
304
  state: "unknown",
@@ -319,7 +321,7 @@ function vt(e, t = !1) {
319
321
  isUnavailable: t.state === "unavailable",
320
322
  brightness: r,
321
323
  brightnessPercent: i,
322
- color: xt(t),
324
+ color: St(t),
323
325
  onCount: +!!n,
324
326
  totalCount: 1,
325
327
  description: n ? "On" : "Off"
@@ -331,7 +333,7 @@ function vt(e, t = !1) {
331
333
  if (r++, t.attributes?.brightness !== void 0 && (s += t.attributes.brightness, c++), t.attributes?.rgb_color) l.push(t.attributes.rgb_color);
332
334
  else if (t.attributes?.hs_color) {
333
335
  let [e, n] = t.attributes.hs_color;
334
- l.push(bt(e, n));
336
+ l.push(xt(e, n));
335
337
  }
336
338
  break;
337
339
  case "off":
@@ -348,7 +350,7 @@ function vt(e, t = !1) {
348
350
  if (l.length > 0) {
349
351
  let e = Math.round(l.reduce((e, t) => e + t[0], 0) / l.length), t = Math.round(l.reduce((e, t) => e + t[1], 0) / l.length), n = Math.round(l.reduce((e, t) => e + t[2], 0) / l.length), r = v / 255;
350
352
  y = `rgb(${Math.round(e * r)}, ${Math.round(t * r)}, ${Math.round(n * r)})`;
351
- } else y = xt(e[0]);
353
+ } else y = St(e[0]);
352
354
  let b;
353
355
  return b = m ? "All on" : h ? "All off" : r > 0 ? `${r} of ${u} on` : "Off", {
354
356
  isGroup: n,
@@ -363,7 +365,7 @@ function vt(e, t = !1) {
363
365
  description: b
364
366
  };
365
367
  }
366
- function yt(e, t = "mean", n = !0) {
368
+ function bt(e, t = "mean", n = !0) {
367
369
  if (e.length === 0) return {
368
370
  isGroup: !1,
369
371
  state: "unknown",
@@ -459,7 +461,7 @@ function yt(e, t = "mean", n = !0) {
459
461
  memberValues: a
460
462
  };
461
463
  }
462
- function bt(e, t) {
464
+ function xt(e, t) {
463
465
  let n = t / 100, r = n * (1 - Math.abs(e / 60 % 2 - 1)), i = 1 - n, a = 0, o = 0, s = 0;
464
466
  return e < 60 ? [a, o] = [n, r] : e < 120 ? [a, o] = [r, n] : e < 180 ? [o, s] = [n, r] : e < 240 ? [o, s] = [r, n] : e < 300 ? [a, s] = [r, n] : [a, s] = [n, r], [
465
467
  (a + i) * 255,
@@ -467,7 +469,7 @@ function bt(e, t) {
467
469
  (s + i) * 255
468
470
  ];
469
471
  }
470
- function xt(e) {
472
+ function St(e) {
471
473
  if (e.state !== "on") return "rgb(100, 100, 100)";
472
474
  let t = (e.attributes?.brightness ?? 255) / 255;
473
475
  if (e.attributes?.rgb_color) {
@@ -475,7 +477,7 @@ function xt(e) {
475
477
  return `rgb(${Math.round(n * t)}, ${Math.round(r * t)}, ${Math.round(i * t)})`;
476
478
  }
477
479
  if (e.attributes?.hs_color) {
478
- let [n, r] = e.attributes.hs_color, [i, a, o] = bt(n, r);
480
+ let [n, r] = e.attributes.hs_color, [i, a, o] = xt(n, r);
479
481
  return `rgb(${Math.round(i * t)}, ${Math.round(a * t)}, ${Math.round(o * t)})`;
480
482
  }
481
483
  if (e.attributes?.color_temp) {
@@ -486,7 +488,7 @@ function xt(e) {
486
488
  }
487
489
  //#endregion
488
490
  //#region src/framework/utils/entity-state.ts
489
- function St(e) {
491
+ function Ct(e) {
490
492
  if (!e) return !1;
491
493
  if ([
492
494
  "on",
@@ -502,15 +504,15 @@ function St(e) {
502
504
  }
503
505
  return !1;
504
506
  }
505
- function Ct(e, t, n) {
507
+ function wt(e, t, n) {
506
508
  return e?.attributes ? e.attributes[t] ?? n : n;
507
509
  }
508
- function wt(e) {
509
- return e.filter(St).length;
510
+ function Tt(e) {
511
+ return e.filter(Ct).length;
510
512
  }
511
513
  //#endregion
512
514
  //#region src/framework/utils/format-value.ts
513
- function Tt(e, t, n) {
515
+ function Et(e, t, n) {
514
516
  let { decimals: r, scale: i = !0 } = n || {};
515
517
  if (typeof e == "string") return t ? `${e}${t}` : e;
516
518
  if (e == null || Number.isNaN(e)) return t ? `--${t}` : "--";
@@ -521,30 +523,30 @@ function Tt(e, t, n) {
521
523
  }
522
524
  //#endregion
523
525
  //#region src/framework/utils/interpret-value.ts
524
- function Et(e, t) {
526
+ function Dt(e, t) {
525
527
  return e == null || isNaN(e) ? null : t === "°C" ? e < 10 ? "Cold" : e < 18 ? "Cool" : e < 24 ? "Comfortable" : e < 28 ? "Warm" : "Hot" : t === "°F" ? e < 50 ? "Cold" : e < 64 ? "Cool" : e < 75 ? "Comfortable" : e < 82 ? "Warm" : "Hot" : t === "%" ? e < 20 ? "Very Low" : e < 40 ? "Low" : e < 60 ? "Medium" : e < 80 ? "High" : "Very High" : t === "ppm" ? e < 400 ? "Excellent" : e < 600 ? "Good" : e < 1e3 ? "Acceptable" : e < 1500 ? "Mediocre" : "Poor" : t === "lx" ? e < 50 ? "Dark" : e < 200 ? "Dim" : e < 500 ? "Moderate" : e < 1e3 ? "Bright" : "Very Bright" : t === "AQI" ? e <= 50 ? "Good" : e <= 100 ? "Moderate" : e <= 150 ? "Unhealthy for Sensitive" : e <= 200 ? "Unhealthy" : e <= 300 ? "Very Unhealthy" : "Hazardous" : t === "dB" ? e < 30 ? "Very Quiet" : e < 50 ? "Quiet" : e < 70 ? "Moderate" : e < 85 ? "Loud" : "Very Loud" : null;
526
528
  }
527
529
  //#endregion
528
530
  //#region src/framework/components/WidgetValue.tsx
529
- var Dt = /*#__PURE__*/ I("<div class=glasshome-widget-subtitle>"), Ot = /*#__PURE__*/ I("<div><div class=glasshome-widget-value>");
530
- function kt(e) {
531
+ var Ot = /*#__PURE__*/ I("<div class=glasshome-widget-subtitle>"), kt = /*#__PURE__*/ I("<div><div class=glasshome-widget-value>");
532
+ function At(e) {
531
533
  return (() => {
532
- var t = Ot(), n = t.firstChild;
533
- return N(n, () => Tt(e.value, e.unit)), N(t, j(C, {
534
+ var t = kt(), n = t.firstChild;
535
+ return N(n, () => Et(e.value, e.unit)), N(t, j(C, {
534
536
  get when() {
535
537
  return P(() => !!e.interpret)() && typeof e.value == "number";
536
538
  },
537
539
  get children() {
538
- var t = Dt();
539
- return N(t, () => Et(e.value, e.unit)), t;
540
+ var t = Ot();
541
+ return N(t, () => Dt(e.value, e.unit)), t;
540
542
  }
541
543
  }), null), M(() => A(t, V("flex flex-col", e.class))), t;
542
544
  })();
543
545
  }
544
546
  //#endregion
545
547
  //#region src/framework/core/Widget.tsx
546
- var At = /*#__PURE__*/ I("<div><div class=\"relative h-full w-full\">"), jt = /*#__PURE__*/ I("<div class=\"glasshome-widget-loading pointer-events-none absolute inset-0 animate-pulse\">"), Mt = /*#__PURE__*/ I("<div class=\"flex h-full w-full flex-col items-center justify-center gap-2 text-center\">"), Nt = /*#__PURE__*/ I("<div class=\"flex items-center justify-center text-white/30\">"), Pt = /*#__PURE__*/ I("<h3 class=\"font-semibold text-sm text-white/60\">"), Ft = /*#__PURE__*/ I("<p class=\"text-white/50 text-xs\">");
547
- function It(t) {
548
+ var jt = /*#__PURE__*/ I("<div><div class=\"relative h-full w-full\">"), Mt = /*#__PURE__*/ I("<div class=\"glasshome-widget-loading pointer-events-none absolute inset-0 animate-pulse\">"), Nt = /*#__PURE__*/ I("<div class=\"flex h-full w-full flex-col items-center justify-center gap-2 text-center\">"), Pt = /*#__PURE__*/ I("<div class=\"flex items-center justify-center text-white/30\">"), Ft = /*#__PURE__*/ I("<h3 class=\"font-semibold text-sm text-white/60\">"), It = /*#__PURE__*/ I("<p class=\"text-white/50 text-xs\">");
549
+ function Lt(t) {
548
550
  let n = O(L), [r, i] = E(), [a, o] = E({
549
551
  width: 0,
550
552
  height: 0
@@ -564,9 +566,9 @@ function It(t) {
564
566
  });
565
567
  });
566
568
  t.observe(e), D(() => t.disconnect());
567
- }), me(() => {
569
+ }), he(() => {
568
570
  let e = r()?.getRootNode();
569
- nt(typeof ShadowRoot < "u" && e instanceof ShadowRoot || typeof Document < "u" && e instanceof Document ? e : void 0);
571
+ rt(typeof ShadowRoot < "u" && e instanceof ShadowRoot || typeof Document < "u" && e instanceof Document ? e : void 0);
570
572
  });
571
573
  let s = {
572
574
  updateConfig: n?.updateConfig ?? (() => {}),
@@ -574,7 +576,7 @@ function It(t) {
574
576
  callService: n?.callService,
575
577
  dimensions: e(() => a(), "ctx.dimensions")
576
578
  }, c = T(() => {
577
- if (t.variant) return typeof t.variant == "string" ? it(t.variant) : t.variant;
579
+ if (t.variant) return typeof t.variant == "string" ? at(t.variant) : t.variant;
578
580
  }), l = T(() => ({
579
581
  "container-type": "size",
580
582
  "container-name": "widget",
@@ -599,15 +601,15 @@ function It(t) {
599
601
  return j(L.Provider, {
600
602
  value: s,
601
603
  get children() {
602
- return j(Xe.Provider, {
604
+ return j(Ze.Provider, {
603
605
  value: a,
604
606
  get children() {
605
- var e = At(), n = e.firstChild;
606
- return k(e, "pointercancel", h), k(e, "pointerup", m), k(e, "pointermove", p), k(e, "pointerdown", f), k(e, "pointerenter", d), ve((e) => {
607
+ var e = jt(), n = e.firstChild;
608
+ return k(e, "pointercancel", h), k(e, "pointerup", m), k(e, "pointermove", p), k(e, "pointerdown", f), k(e, "pointerenter", d), ye((e) => {
607
609
  i(e), t.gestures?.bindElement(e);
608
610
  }, e), N(n, (() => {
609
611
  var e = P(() => !!t.emptyState);
610
- return () => e() ? j(Lt, {
612
+ return () => e() ? j(Rt, {
611
613
  get icon() {
612
614
  return t.emptyState.icon;
613
615
  },
@@ -621,12 +623,12 @@ function It(t) {
621
623
  })()), N(e, (() => {
622
624
  var e = P(() => !!t.loading);
623
625
  return () => e() && (() => {
624
- var e = jt();
626
+ var e = Mt();
625
627
  return M((t) => F(e, "z-index", z.OVERLAY)), e;
626
628
  })();
627
629
  })(), null), M((r) => {
628
630
  var i = V("glasshome-widget", "relative h-full w-full select-none overflow-hidden rounded-xl border border-border/50", c()?.styles?.class, t.class), a = l(), o = z.CONTENT;
629
- return i !== r.e && A(e, r.e = i), r.t = _e(e, a, r.t), o !== r.a && F(n, "z-index", r.a = o), r;
631
+ return i !== r.e && A(e, r.e = i), r.t = ve(e, a, r.t), o !== r.a && F(n, "z-index", r.a = o), r;
630
632
  }, {
631
633
  e: void 0,
632
634
  t: void 0,
@@ -637,76 +639,76 @@ function It(t) {
637
639
  }
638
640
  });
639
641
  }
640
- function Lt(e) {
642
+ function Rt(e) {
641
643
  return (() => {
642
- var t = Mt();
644
+ var t = Nt();
643
645
  return N(t, (() => {
644
646
  var t = P(() => !!e.icon);
645
647
  return () => t() && (() => {
646
- var t = Nt();
648
+ var t = Pt();
647
649
  return N(t, () => e.icon), t;
648
650
  })();
649
651
  })(), null), N(t, (() => {
650
652
  var t = P(() => !!e.title);
651
653
  return () => t() && (() => {
652
- var t = Pt();
654
+ var t = Ft();
653
655
  return N(t, () => e.title), t;
654
656
  })();
655
657
  })(), null), N(t, (() => {
656
658
  var t = P(() => !!e.message);
657
659
  return () => t() && (() => {
658
- var t = Ft();
660
+ var t = It();
659
661
  return N(t, () => e.message), t;
660
662
  })();
661
663
  })(), null), t;
662
664
  })();
663
665
  }
664
- var H = It;
665
- H.Content = ct, H.Icon = ft, H.Title = _t, H.Status = mt, H.Value = kt, H.SliderFill = ot;
666
+ var H = Lt;
667
+ H.Content = lt, H.Icon = pt, H.Title = vt, H.Status = ht, H.Value = At, H.SliderFill = st;
666
668
  //#endregion
667
669
  //#region src/framework/dialogs/validate-config.ts
668
- function Rt(e) {
670
+ function zt(e) {
669
671
  let t = "";
670
672
  for (let n of e) t += typeof n == "number" ? `[${n}]` : t ? `.${String(n)}` : String(n);
671
673
  return t;
672
674
  }
673
- function zt(e, t) {
675
+ function Bt(e, t) {
674
676
  let n = e.safeParse(t);
675
677
  return n.success ? null : n.error.issues.map((e) => {
676
- let t = Rt(e.path);
678
+ let t = zt(e.path);
677
679
  return t ? `${t}: ${e.message}` : e.message;
678
680
  });
679
681
  }
680
682
  //#endregion
681
683
  //#region src/framework/dialogs/WidgetDialog.tsx
682
- var Bt = /*#__PURE__*/ I("<span class=\"inline-flex size-3.5 shrink-0 items-center\">"), Vt = /*#__PURE__*/ I("<button type=button>"), Ht = /*#__PURE__*/ I("<svg xmlns=http://www.w3.org/2000/svg class=size-3.5 fill=none viewBox=\"0 0 24 24\"stroke=currentColor stroke-width=2><path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\"></path><path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\">"), Ut = /*#__PURE__*/ I("<div class=\"rounded-lg bg-muted/30 p-2 text-center md:p-6\"><p class=\"text-muted-foreground text-sm\">No edit options available"), Wt = /*#__PURE__*/ I("<svg xmlns=http://www.w3.org/2000/svg class=size-3.5 fill=none viewBox=\"0 0 24 24\"stroke=currentColor stroke-width=2><line x1=4 y1=21 x2=4 y2=14></line><line x1=4 y1=10 x2=4 y2=3></line><line x1=12 y1=21 x2=12 y2=12></line><line x1=12 y1=8 x2=12 y2=3></line><line x1=20 y1=21 x2=20 y2=16></line><line x1=20 y1=12 x2=20 y2=3></line><line x1=1 y1=14 x2=7 y2=14></line><line x1=9 y1=8 x2=15 y2=8></line><line x1=17 y1=16 x2=23 y2=16>"), Gt = /*#__PURE__*/ I("<div class=\"rounded-lg bg-muted/30 p-2 text-center md:p-6\"><p class=\"text-muted-foreground text-sm\">No additional controls"), Kt = /*#__PURE__*/ I("<svg xmlns=http://www.w3.org/2000/svg class=size-3.5 fill=none viewBox=\"0 0 24 24\"stroke=currentColor stroke-width=2><path d=\"m8 2 1.88 1.88\"></path><path d=\"M14.12 3.88 16 2\"></path><path d=\"M9 7.13v-1a3.003 3.003 0 1 1 6 0v1\"></path><path d=\"M12 20c-3.3 0-6-2.7-6-6v-3a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v3c0 3.3-2.7 6-6 6\"></path><path d=\"M12 20v-9\"></path><path d=\"M6.53 9C4.6 8.8 3 7.1 3 5\"></path><path d=\"M6 13H2\"></path><path d=\"M3 21c0-2.1 1.7-3.9 3.8-4\"></path><path d=\"M20.97 5c0 2.1-1.6 3.8-3.5 4\"></path><path d=\"M22 13h-4\"></path><path d=\"M17.2 17c2.1.1 3.8 1.9 3.8 4\">"), qt = /*#__PURE__*/ I("<div class=\"rounded-lg bg-muted/30 p-2 text-center md:p-6\"><p class=\"text-muted-foreground text-sm\">No debug information available"), Jt = /*#__PURE__*/ I("<div class=\"min-w-0 shrink-0\">"), Yt = /*#__PURE__*/ I("<div class=\"flex items-center gap-2\"><div class=\"flex h-8 items-center rounded-lg border border-border/50 bg-muted/30 p-0.5\">"), Xt = /*#__PURE__*/ I("<div class=\"gh-scroll min-h-0 flex-1 overflow-y-auto px-6\">"), Zt = /*#__PURE__*/ I("<div class=\"flex shrink-0 items-center justify-end gap-2 border-border/50 border-t px-6 pt-3\">");
683
- function Qt(e) {
684
+ var Vt = /*#__PURE__*/ I("<span class=\"inline-flex size-3.5 shrink-0 items-center\">"), Ht = /*#__PURE__*/ I("<button type=button>"), Ut = /*#__PURE__*/ I("<svg xmlns=http://www.w3.org/2000/svg class=size-3.5 fill=none viewBox=\"0 0 24 24\"stroke=currentColor stroke-width=2><path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\"></path><path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\">"), Wt = /*#__PURE__*/ I("<div class=\"rounded-lg bg-muted/30 p-2 text-center md:p-6\"><p class=\"text-muted-foreground text-sm\">No edit options available"), Gt = /*#__PURE__*/ I("<svg xmlns=http://www.w3.org/2000/svg class=size-3.5 fill=none viewBox=\"0 0 24 24\"stroke=currentColor stroke-width=2><line x1=4 y1=21 x2=4 y2=14></line><line x1=4 y1=10 x2=4 y2=3></line><line x1=12 y1=21 x2=12 y2=12></line><line x1=12 y1=8 x2=12 y2=3></line><line x1=20 y1=21 x2=20 y2=16></line><line x1=20 y1=12 x2=20 y2=3></line><line x1=1 y1=14 x2=7 y2=14></line><line x1=9 y1=8 x2=15 y2=8></line><line x1=17 y1=16 x2=23 y2=16>"), Kt = /*#__PURE__*/ I("<div class=\"rounded-lg bg-muted/30 p-2 text-center md:p-6\"><p class=\"text-muted-foreground text-sm\">No additional controls"), qt = /*#__PURE__*/ I("<svg xmlns=http://www.w3.org/2000/svg class=size-3.5 fill=none viewBox=\"0 0 24 24\"stroke=currentColor stroke-width=2><path d=\"m8 2 1.88 1.88\"></path><path d=\"M14.12 3.88 16 2\"></path><path d=\"M9 7.13v-1a3.003 3.003 0 1 1 6 0v1\"></path><path d=\"M12 20c-3.3 0-6-2.7-6-6v-3a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v3c0 3.3-2.7 6-6 6\"></path><path d=\"M12 20v-9\"></path><path d=\"M6.53 9C4.6 8.8 3 7.1 3 5\"></path><path d=\"M6 13H2\"></path><path d=\"M3 21c0-2.1 1.7-3.9 3.8-4\"></path><path d=\"M20.97 5c0 2.1-1.6 3.8-3.5 4\"></path><path d=\"M22 13h-4\"></path><path d=\"M17.2 17c2.1.1 3.8 1.9 3.8 4\">"), Jt = /*#__PURE__*/ I("<div class=\"rounded-lg bg-muted/30 p-2 text-center md:p-6\"><p class=\"text-muted-foreground text-sm\">No debug information available"), Yt = /*#__PURE__*/ I("<div class=\"min-w-0 shrink-0\">"), Xt = /*#__PURE__*/ I("<div class=\"flex items-center gap-2\"><div class=\"flex h-8 items-center rounded-lg border border-border/50 bg-muted/30 p-0.5\">"), Zt = /*#__PURE__*/ I("<div class=\"gh-scroll min-h-0 flex-1 overflow-y-auto px-6\">"), Qt = /*#__PURE__*/ I("<div class=\"flex shrink-0 items-center justify-end gap-2 border-border/50 border-t px-6 pt-3\">"), $t = (e) => He(e);
685
+ function en(e) {
684
686
  return (() => {
685
- var t = Vt();
687
+ var t = Ht();
686
688
  return t.$$click = () => e.onClick(), N(t, j(C, {
687
689
  get when() {
688
690
  return e.isActive;
689
691
  },
690
692
  get children() {
691
- var t = Bt();
693
+ var t = Vt();
692
694
  return N(t, () => e.icon), t;
693
695
  }
694
696
  }), null), N(t, () => e.label, null), M(() => A(t, V("flex cursor-pointer items-center justify-center rounded-md px-3 py-1.5 text-xs transition-all duration-300 ease-in-out", e.isActive ? "gap-1.5 bg-foreground/10 font-semibold text-foreground shadow-sm" : "gap-0 text-muted-foreground hover:bg-foreground/5 hover:text-foreground"))), t;
695
697
  })();
696
698
  }
697
- function $t(e) {
698
- let [t] = he(e, /* @__PURE__ */ "open.onOpenChange.title.onSave.hasUnsavedChanges.onDelete.editContent.controlsContent.debugContent.debugData.tabs.class.maxWidth.defaultTab.activeTab.onActiveTabChange.headerActions.configSchema.config.onConfigSave.ResponsiveDialog.ResponsiveDialogContent.ResponsiveDialogHeader.ResponsiveDialogTitle.ResponsiveDialogDescription.Button.SchemaForm".split(".")), n = () => !!t.configSchema && !!t.config && !!t.onConfigSave && !!t.SchemaForm, [r, i] = E({}), [a, o] = E(null), [s, c] = E([]);
699
- w(pe(() => t.config, (e) => {
699
+ function tn(e) {
700
+ let [t] = ge(e, /* @__PURE__ */ "open.onOpenChange.title.onSave.hasUnsavedChanges.onDelete.editContent.controlsContent.debugContent.debugData.tabs.class.maxWidth.defaultTab.activeTab.onActiveTabChange.headerActions.configSchema.config.onConfigSave.ResponsiveDialog.ResponsiveDialogContent.ResponsiveDialogHeader.ResponsiveDialogTitle.ResponsiveDialogDescription.Button.SchemaForm".split(".")), n = () => !!t.configSchema && !!t.config && !!t.onConfigSave && !!t.SchemaForm, [r, i] = E({}), [a, o] = E(null), [s, c] = E([]);
701
+ w(me(() => t.config, (e) => {
700
702
  e && i({ ...e });
701
- })), w(pe(() => t.configSchema, (e) => {
702
- e && o(Ve(e));
703
+ })), w(me(() => t.configSchema, (e) => {
704
+ e && o($t(e));
703
705
  }));
704
706
  let l = () => n() && JSON.stringify(r()) !== JSON.stringify(t.config), u = (e) => {
705
707
  !e && t.config && (i({ ...t.config }), c([])), t.onOpenChange(e);
706
708
  }, d = () => {
707
709
  let e = t.configSchema;
708
710
  if (e) {
709
- let t = zt(e, r());
711
+ let t = Bt(e, r());
710
712
  if (t) {
711
713
  c(t);
712
714
  return;
@@ -729,11 +731,11 @@ function $t(e) {
729
731
  return e.push({
730
732
  id: "edit",
731
733
  label: "Edit",
732
- icon: Ht(),
734
+ icon: Ut(),
733
735
  content: t.editContent ?? (() => {
734
- let e = n() ? a() : void 0;
735
- return e ? j(ie, {
736
- schema: e,
736
+ let e = t.SchemaForm, o = n() ? a() : void 0;
737
+ return !o || !e ? Wt() : j(e, {
738
+ schema: o,
737
739
  get data() {
738
740
  return r();
739
741
  },
@@ -741,18 +743,18 @@ function $t(e) {
741
743
  get errors() {
742
744
  return s();
743
745
  }
744
- }) : Ut();
746
+ });
745
747
  })()
746
748
  }), e.push({
747
749
  id: "controls",
748
750
  label: "Controls",
749
- icon: Wt(),
750
- content: t.controlsContent ?? Gt()
751
+ icon: Gt(),
752
+ content: t.controlsContent ?? Kt()
751
753
  }), e.push({
752
754
  id: "debug",
753
755
  label: "Debug",
754
- icon: Kt(),
755
- content: t.debugContent ?? qt()
756
+ icon: qt(),
757
+ content: t.debugContent ?? Jt()
756
758
  }), e;
757
759
  }, v = async () => {
758
760
  if (t.debugData !== void 0) try {
@@ -760,19 +762,19 @@ function $t(e) {
760
762
  await navigator.clipboard.writeText(e);
761
763
  } catch {}
762
764
  }, ee = () => {
763
- let e = ae();
765
+ let e = ie();
764
766
  return e.find((e) => e.id === m())?.content ?? e[0]?.content;
765
- }, y = t.ResponsiveDialog, b = t.ResponsiveDialogContent, te = t.ResponsiveDialogHeader, ne = t.ResponsiveDialogTitle, re = t.ResponsiveDialogDescription, x = t.Button, ie = t.SchemaForm, ae = T(pe([
767
+ }, y = t.ResponsiveDialog, b = t.ResponsiveDialogContent, te = t.ResponsiveDialogHeader, ne = t.ResponsiveDialogTitle, re = t.ResponsiveDialogDescription, x = t.Button, ie = T(me([
766
768
  () => t.open,
767
769
  a,
768
770
  () => t.config,
769
771
  () => t.tabs
770
- ], () => _())), oe = (e) => n() ? u(e) : t.onOpenChange(e), se = () => n() ? l() : t.hasUnsavedChanges, S = () => n() ? d : t.onSave;
772
+ ], () => _())), ae = (e) => n() ? u(e) : t.onOpenChange(e), oe = () => n() ? l() : t.hasUnsavedChanges, S = () => n() ? d : t.onSave;
771
773
  return j(y, {
772
774
  get open() {
773
775
  return t.open;
774
776
  },
775
- onOpenChange: (e) => oe(e),
777
+ onOpenChange: (e) => ae(e),
776
778
  get children() {
777
779
  return j(b, {
778
780
  get class() {
@@ -784,7 +786,7 @@ function $t(e) {
784
786
  class: "flex flex-row items-center justify-between gap-3 px-6",
785
787
  get children() {
786
788
  return [(() => {
787
- var e = Jt();
789
+ var e = Yt();
788
790
  return N(e, j(ne, {
789
791
  class: "truncate leading-tight",
790
792
  get children() {
@@ -795,8 +797,8 @@ function $t(e) {
795
797
  children: "Widget configuration dialog"
796
798
  }), null), e;
797
799
  })(), (() => {
798
- var e = Yt(), n = e.firstChild;
799
- return N(n, () => ae().map((e) => j(Qt, {
800
+ var e = Xt(), n = e.firstChild;
801
+ return N(n, () => ie().map((e) => j(en, {
800
802
  get icon() {
801
803
  return e.icon;
802
804
  },
@@ -819,7 +821,7 @@ function $t(e) {
819
821
  }
820
822
  }),
821
823
  (() => {
822
- var e = Xt();
824
+ var e = Zt();
823
825
  return N(e, ee), e;
824
826
  })(),
825
827
  j(C, {
@@ -827,7 +829,7 @@ function $t(e) {
827
829
  return P(() => m() === "edit")() && (S() || t.onDelete) || m() === "debug" && t.debugData !== void 0;
828
830
  },
829
831
  get children() {
830
- var e = Zt();
832
+ var e = Qt();
831
833
  return N(e, j(C, {
832
834
  get when() {
833
835
  return P(() => m() === "edit")() && t.onDelete;
@@ -848,7 +850,7 @@ function $t(e) {
848
850
  return j(x, {
849
851
  size: "sm",
850
852
  get disabled() {
851
- return !se();
853
+ return !oe();
852
854
  },
853
855
  onClick: () => S()?.(),
854
856
  children: "Save"
@@ -875,10 +877,10 @@ function $t(e) {
875
877
  }
876
878
  });
877
879
  }
878
- ge(["click"]);
880
+ _e(["click"]);
879
881
  //#endregion
880
882
  //#region src/framework/hooks/use-intersection-pause.ts
881
- function en(e) {
883
+ function nn(e) {
882
884
  if (typeof IntersectionObserver > "u") return () => !1;
883
885
  let [t, n] = E(!1), r = new IntersectionObserver((e) => {
884
886
  let t = e[0];
@@ -891,14 +893,14 @@ function en(e) {
891
893
  }
892
894
  //#endregion
893
895
  //#region src/framework/hooks/use-reduced-motion.ts
894
- function tn() {
896
+ function rn() {
895
897
  if (typeof window > "u" || typeof window.matchMedia != "function") return () => !1;
896
898
  let e = window.matchMedia("(prefers-reduced-motion: reduce)"), [t, n] = E(e.matches), r = (e) => n(e.matches);
897
899
  return e.addEventListener("change", r), D(() => e.removeEventListener("change", r)), t;
898
900
  }
899
901
  //#endregion
900
902
  //#region src/framework/hooks/use-widget-dialog.ts
901
- function nn(e = "controls") {
903
+ function an(e = "controls") {
902
904
  let [t, n] = E(!1), [r, i] = E(e), a = (t) => {
903
905
  i(t ?? e), n(!0);
904
906
  }, o = O(L);
@@ -923,14 +925,14 @@ function nn(e = "controls") {
923
925
  }
924
926
  //#endregion
925
927
  //#region src/framework/hooks/use-widget-entity-group.ts
926
- function rn(e) {
928
+ function on(e) {
927
929
  let t = e.minEntities ?? 1, n = T(() => e.entities().length), r = T(() => n() >= t), i = T(() => !r() || !e.calculateGroupData ? null : e.calculateGroupData(e.entities())), a = T(() => {
928
930
  if (!r()) return;
929
931
  let t = e.aggregationMode?.();
930
932
  if (!t || t === "none") return;
931
933
  let n = e.entities();
932
- if (t === "light" || t === "binary-sensor" || t === "switch") return vt(n, e.allEntitiesMode);
933
- if (t === "sensor") return yt(n, e.sensorGroupType?.() ?? "mean", !0);
934
+ if (t === "light" || t === "binary-sensor" || t === "switch") return yt(n, e.allEntitiesMode);
935
+ if (t === "sensor") return bt(n, e.sensorGroupType?.() ?? "mean", !0);
934
936
  }), o = T(() => r() ? void 0 : e.emptyStateConfig);
935
937
  return {
936
938
  entities: e.entities,
@@ -944,13 +946,13 @@ function rn(e) {
944
946
  //#endregion
945
947
  //#region src/framework/gestures/cursors.ts
946
948
  var U = 32, W = U / 2, G = "white", K = "rgba(0,0,0,0.4)", q = 2, J = 3;
947
- function an(e) {
949
+ function sn(e) {
948
950
  return `url("data:image/svg+xml,${encodeURIComponent(e)}")`;
949
951
  }
950
952
  function Y(e) {
951
953
  return `<svg xmlns="http://www.w3.org/2000/svg" width="${U}" height="${U}" viewBox="0 0 ${U} ${U}">${e}</svg>`;
952
954
  }
953
- var on = Y(`
955
+ var cn = Y(`
954
956
  <g transform="translate(6, 2)">
955
957
  <!-- shadow -->
956
958
  <g stroke="${K}" stroke-width="${J}" fill="none" stroke-linecap="round" stroke-linejoin="round">
@@ -961,13 +963,13 @@ var on = Y(`
961
963
  <path d="M10 8V3a2 2 0 0 1 4 0v10l4.5-4.5a2 2 0 0 1 2.83 2.83L14 18.5c-2 2-4 3.5-8 3.5-3 0-5-2-5-5v-6a2 2 0 0 1 4 0v2"/>
962
964
  </g>
963
965
  </g>
964
- `), sn = Y(`
966
+ `), ln = Y(`
965
967
  <g>
966
968
  <circle cx="${W}" cy="${W}" r="8" stroke="${K}" stroke-width="${J}" fill="none"/>
967
969
  <circle cx="${W}" cy="${W}" r="8" stroke="${G}" stroke-width="1.5" fill="none"/>
968
970
  <circle cx="${W}" cy="${W}" r="1.5" fill="${G}"/>
969
971
  </g>
970
- `), cn = Y(`
972
+ `), un = Y(`
971
973
  <g>
972
974
  <!-- shadow -->
973
975
  <g stroke="${K}" stroke-width="${J}" fill="none" stroke-linecap="round" stroke-linejoin="round">
@@ -986,7 +988,7 @@ var on = Y(`
986
988
  <circle cx="11" cy="${W}" r="1" fill="${G}" opacity="0.6"/>
987
989
  <circle cx="21" cy="${W}" r="1" fill="${G}" opacity="0.6"/>
988
990
  </g>
989
- `), ln = Y(`
991
+ `), dn = Y(`
990
992
  <g>
991
993
  <!-- shadow -->
992
994
  <g stroke="${K}" stroke-width="${J}" fill="none" stroke-linecap="round" stroke-linejoin="round">
@@ -1005,7 +1007,7 @@ var on = Y(`
1005
1007
  <circle cx="${W}" cy="11" r="1" fill="${G}" opacity="0.6"/>
1006
1008
  <circle cx="${W}" cy="21" r="1" fill="${G}" opacity="0.6"/>
1007
1009
  </g>
1008
- `), un = Y(`
1010
+ `), fn = Y(`
1009
1011
  <g>
1010
1012
  <!-- shadow -->
1011
1013
  <g stroke="${K}" stroke-width="${J}" fill="none" stroke-linecap="round" stroke-linejoin="round">
@@ -1031,54 +1033,54 @@ var on = Y(`
1031
1033
  `);
1032
1034
  function X(e, t, n) {
1033
1035
  return {
1034
- css: `${an(e)} ${t} ${n}, auto`,
1036
+ css: `${sn(e)} ${t} ${n}, auto`,
1035
1037
  hotspotX: t,
1036
1038
  hotspotY: n
1037
1039
  };
1038
1040
  }
1039
1041
  var Z = {
1040
- tap: X(on, 12, 4),
1041
- hold: X(sn, 16, 16),
1042
- slideHorizontal: X(cn, W, W),
1043
- slideVertical: X(ln, W, W),
1044
- slideAuto: X(un, W, W)
1042
+ tap: X(cn, 12, 4),
1043
+ hold: X(ln, 16, 16),
1044
+ slideHorizontal: X(un, W, W),
1045
+ slideVertical: X(dn, W, W),
1046
+ slideAuto: X(fn, W, W)
1045
1047
  };
1046
1048
  //#endregion
1047
1049
  //#region src/framework/gestures/haptics.ts
1048
- function dn() {
1050
+ function pn() {
1049
1051
  if (typeof window > "u") return null;
1050
1052
  let e = window;
1051
1053
  return e.Capacitor?.isNativePlatform?.() ? e.Capacitor.Plugins?.Haptics ?? null : null;
1052
1054
  }
1053
- function fn(e) {
1055
+ function mn(e) {
1054
1056
  if (!(typeof navigator > "u" || typeof navigator.vibrate != "function")) try {
1055
1057
  navigator.vibrate(e);
1056
1058
  } catch {}
1057
1059
  }
1058
- var pn = {
1060
+ var hn = {
1059
1061
  tick() {
1060
- let e = dn();
1062
+ let e = pn();
1061
1063
  if (e) {
1062
1064
  e.impact({ style: "Light" }).catch(() => {});
1063
1065
  return;
1064
1066
  }
1065
- fn(8);
1067
+ mn(8);
1066
1068
  },
1067
1069
  bump() {
1068
- let e = dn();
1070
+ let e = pn();
1069
1071
  if (e) {
1070
1072
  e.impact({ style: "Medium" }).catch(() => {});
1071
1073
  return;
1072
1074
  }
1073
- fn(20);
1075
+ mn(20);
1074
1076
  },
1075
1077
  pulse() {
1076
- let e = dn();
1078
+ let e = pn();
1077
1079
  if (e) {
1078
1080
  e.impact({ style: "Heavy" }).catch(() => {});
1079
1081
  return;
1080
1082
  }
1081
- fn([
1083
+ mn([
1082
1084
  0,
1083
1085
  15,
1084
1086
  40,
@@ -1088,7 +1090,7 @@ var pn = {
1088
1090
  };
1089
1091
  //#endregion
1090
1092
  //#region src/framework/gestures/use-widget-gestures.ts
1091
- function mn(e, t) {
1093
+ function gn(e, t) {
1092
1094
  let n = {
1093
1095
  isDown: !1,
1094
1096
  isTouch: !1,
@@ -1131,7 +1133,7 @@ function mn(e, t) {
1131
1133
  if (n.isDown = !0, n.isTouch = t.pointerType === "touch", n.element = t.currentTarget, c(n.element), n.startX = t.clientX, n.startY = t.clientY, n.startTime = Date.now(), n.hasMoved = !1, n.sliding = !1, r.hold) {
1132
1134
  let e = r.hold.delay ?? 300;
1133
1135
  n.holdTimer = setTimeout(() => {
1134
- n.holdTimer = null, !(!n.isDown || n.hasMoved) && (pn.bump(), r.hold?.action(), n.isDown = !1);
1136
+ n.holdTimer = null, !(!n.isDown || n.hasMoved) && (hn.bump(), r.hold?.action(), n.isDown = !1);
1135
1137
  }, e);
1136
1138
  }
1137
1139
  if (!n.isTouch && r.slide) try {
@@ -1199,7 +1201,7 @@ function mn(e, t) {
1199
1201
  }
1200
1202
  //#endregion
1201
1203
  //#region src/framework/theming/svg-colors.ts
1202
- var hn = {
1204
+ var _n = {
1203
1205
  solar: "oklch(0.74 0.18 60)",
1204
1206
  grid: "oklch(0.62 0.12 245)",
1205
1207
  battery: "oklch(0.70 0.18 145)",
@@ -1208,21 +1210,21 @@ var hn = {
1208
1210
  positive: "oklch(0.70 0.14 160)",
1209
1211
  negative: "oklch(0.64 0.22 27)"
1210
1212
  };
1211
- function gn(e) {
1213
+ function vn(e) {
1212
1214
  return {
1213
1215
  fill: `color-mix(in oklch, ${e} 20%, transparent)`,
1214
1216
  stroke: e,
1215
1217
  solid: e
1216
1218
  };
1217
1219
  }
1218
- var _n = Object.fromEntries(Object.entries(hn).map(([e, t]) => [e, gn(t)])), vn = o.enum([
1220
+ var yn = Object.fromEntries(Object.entries(_n).map(([e, t]) => [e, vn(t)])), bn = o.enum([
1219
1221
  "success",
1220
1222
  "warning",
1221
1223
  "danger",
1222
1224
  "info",
1223
1225
  "neutral",
1224
1226
  "accent"
1225
- ]), yn = {
1227
+ ]), xn = {
1226
1228
  title: e(() => o.string().optional().meta({
1227
1229
  title: "Title",
1228
1230
  description: "Optional display name override"
@@ -1242,45 +1244,45 @@ var _n = Object.fromEntries(Object.entries(hn).map(([e, t]) => [e, gn(t)])), vn
1242
1244
  formType: "area-picker",
1243
1245
  title: "Area"
1244
1246
  }), "widgetFields.areaId")
1245
- }, bn = 24;
1247
+ }, Sn = 24;
1246
1248
  function Q(e) {
1247
1249
  let t = {};
1248
1250
  for (let [n, r] of Object.entries(e)) r !== void 0 && (t[n] = r);
1249
1251
  return t;
1250
1252
  }
1251
- function xn() {
1253
+ function Cn() {
1252
1254
  return o.string().optional().meta({
1253
1255
  title: "Title",
1254
1256
  description: "Optional display name override"
1255
1257
  });
1256
1258
  }
1257
- function Sn(e) {
1259
+ function wn(e) {
1258
1260
  return (e.default === void 0 ? o.string().optional() : o.string().default(e.default)).meta(Q({
1259
1261
  title: e.title,
1260
1262
  description: e.description
1261
1263
  }));
1262
1264
  }
1263
- function Cn(e) {
1265
+ function Tn(e) {
1264
1266
  let t = o.number();
1265
1267
  return e.min !== void 0 && (t = t.min(e.min)), e.max !== void 0 && (t = t.max(e.max)), (e.default === void 0 ? t.optional() : t.default(e.default)).meta(Q({
1266
1268
  title: e.title,
1267
1269
  description: e.description
1268
1270
  }));
1269
1271
  }
1270
- function wn(e) {
1272
+ function En(e) {
1271
1273
  return o.boolean().default(e.default ?? !1).meta(Q({
1272
1274
  title: e.title,
1273
1275
  description: e.description
1274
1276
  }));
1275
1277
  }
1276
- function Tn(e, t) {
1278
+ function Dn(e, t) {
1277
1279
  let n = o.enum(e);
1278
1280
  return (t.default === void 0 ? n.optional() : n.default(t.default)).meta(Q({
1279
1281
  title: t.title,
1280
1282
  description: t.description
1281
1283
  }));
1282
1284
  }
1283
- function En(e, t) {
1285
+ function On(e, t) {
1284
1286
  return o.array(o.string()).default([]).meta(Q({
1285
1287
  domain: e,
1286
1288
  title: t?.title ?? "Entities",
@@ -1288,7 +1290,7 @@ function En(e, t) {
1288
1290
  deviceClass: t?.deviceClass
1289
1291
  }));
1290
1292
  }
1291
- function Dn(e, t) {
1293
+ function kn(e, t) {
1292
1294
  return o.array(o.string()).default([]).meta(Q({
1293
1295
  domain: e,
1294
1296
  title: t?.title ?? "Entity",
@@ -1297,49 +1299,49 @@ function Dn(e, t) {
1297
1299
  singleSelect: !0
1298
1300
  }));
1299
1301
  }
1300
- function On(e) {
1302
+ function An(e) {
1301
1303
  return o.string().optional().meta({
1302
1304
  formType: "area-picker",
1303
1305
  title: e?.title ?? "Area"
1304
1306
  });
1305
1307
  }
1306
- function kn(e) {
1308
+ function jn(e) {
1307
1309
  let t = o.string().meta({
1308
1310
  formType: "icon-picker",
1309
1311
  title: e?.title ?? "Icon"
1310
1312
  });
1311
1313
  return e?.default === void 0 ? t.optional() : t.default(e.default);
1312
1314
  }
1313
- function An(e) {
1315
+ function Mn(e) {
1314
1316
  return o.array(o.string()).default([]).meta(Q({
1315
1317
  title: e.title,
1316
1318
  description: e.description
1317
1319
  }));
1318
1320
  }
1319
- function jn(e, t) {
1321
+ function Nn(e, t) {
1320
1322
  let n = o.object(e);
1321
- return n.default(He(n)).meta({ title: t.title });
1323
+ return n.default(Ue(n)).meta({ title: t.title });
1322
1324
  }
1323
- function Mn(e) {
1325
+ function Pn(e) {
1324
1326
  return e.def;
1325
1327
  }
1326
1328
  function $(e) {
1327
1329
  if (o.globalRegistry.get(e)?.formType === "list") return !0;
1328
- let t = Mn(e);
1330
+ let t = Pn(e);
1329
1331
  return t.shape ? Object.values(t.shape).some($) : t.options ? t.options.some($) : t.element ? $(t.element) : t.innerType ? $(t.innerType) : !1;
1330
1332
  }
1331
- function Nn(e) {
1332
- let t = e, n = Mn(t).innerType;
1333
- for (; n;) t = n, n = Mn(t).innerType;
1333
+ function Fn(e) {
1334
+ let t = e, n = Pn(t).innerType;
1335
+ for (; n;) t = n, n = Pn(t).innerType;
1334
1336
  return t;
1335
1337
  }
1336
- function Pn(e) {
1337
- let t = Mn(Nn(e));
1338
+ function In(e) {
1339
+ let t = Pn(Fn(e));
1338
1340
  if (t.shape) return new Set(Object.keys(t.shape));
1339
1341
  if (t.options) {
1340
1342
  let e = [];
1341
1343
  for (let n of t.options) {
1342
- let t = Pn(n);
1344
+ let t = In(n);
1343
1345
  if (!t) return null;
1344
1346
  e.push(t);
1345
1347
  }
@@ -1351,7 +1353,7 @@ function Pn(e) {
1351
1353
  }
1352
1354
  return null;
1353
1355
  }
1354
- function Fn(e, t, n) {
1356
+ function Ln(e, t, n) {
1355
1357
  let r = { [t]: n };
1356
1358
  try {
1357
1359
  return e.parse(r);
@@ -1359,12 +1361,12 @@ function Fn(e, t, n) {
1359
1361
  return r;
1360
1362
  }
1361
1363
  }
1362
- function In(e, t) {
1364
+ function Rn(e, t) {
1363
1365
  if (!Number.isInteger(t.max) || t.max < 1) throw Error(`field.list: max must be a positive integer, got ${t.max}`);
1364
- if (t.max > bn) throw Error(`field.list: max ${t.max} exceeds the ceiling of ${bn}`);
1366
+ if (t.max > Sn) throw Error(`field.list: max ${t.max} exceeds the ceiling of ${Sn}`);
1365
1367
  if (t.min !== void 0 && (!Number.isInteger(t.min) || t.min < 0 || t.min > t.max)) throw Error(`field.list: min must be an integer between 0 and max, got ${t.min}`);
1366
1368
  if ($(e)) throw Error("field.list: a list item cannot contain another field.list (depth 1 only)");
1367
- if (t.labelField !== void 0 && !Pn(e)?.has(t.labelField)) throw Error(`field.list: labelField "${t.labelField}" must name a field present in every item`);
1369
+ if (t.labelField !== void 0 && !In(e)?.has(t.labelField)) throw Error(`field.list: labelField "${t.labelField}" must name a field present in every item`);
1368
1370
  let n = o.array(e);
1369
1371
  return t.min !== void 0 && (n = n.min(t.min)), n = n.max(t.max), n.default([]).meta(Q({
1370
1372
  formType: "list",
@@ -1374,7 +1376,7 @@ function In(e, t) {
1374
1376
  labelField: t.labelField
1375
1377
  }));
1376
1378
  }
1377
- function Ln(e, t, n) {
1379
+ function zn(e, t, n) {
1378
1380
  let r = Object.keys(t)[0];
1379
1381
  if (r === void 0) throw Error("field.variants: at least one variant is required");
1380
1382
  if (n.shared && e in n.shared) throw Error(`field.variants: shared fields cannot redefine the discriminator "${e}"`);
@@ -1387,7 +1389,7 @@ function Ln(e, t, n) {
1387
1389
  ...r,
1388
1390
  [e]: o.literal(t)
1389
1391
  })), a = o.discriminatedUnion(e, i), s = i[0];
1390
- return a.default(s ? Fn(s, e, r) : {}).meta(Q({
1392
+ return a.default(s ? Ln(s, e, r) : {}).meta(Q({
1391
1393
  formType: "variants",
1392
1394
  discriminator: e,
1393
1395
  title: n.title,
@@ -1395,27 +1397,27 @@ function Ln(e, t, n) {
1395
1397
  labels: n.labels
1396
1398
  }));
1397
1399
  }
1398
- var Rn = {
1399
- title: xn,
1400
- text: Sn,
1401
- number: Cn,
1402
- toggle: wn,
1403
- choice: Tn,
1404
- entities: En,
1405
- entity: Dn,
1406
- area: On,
1407
- icon: kn,
1408
- stringList: An,
1409
- group: jn,
1410
- list: In,
1411
- variants: Ln
1400
+ var Bn = {
1401
+ title: Cn,
1402
+ text: wn,
1403
+ number: Tn,
1404
+ toggle: En,
1405
+ choice: Dn,
1406
+ entities: On,
1407
+ entity: kn,
1408
+ area: An,
1409
+ icon: jn,
1410
+ stringList: Mn,
1411
+ group: Nn,
1412
+ list: Rn,
1413
+ variants: zn
1412
1414
  };
1413
- function zn(e) {
1415
+ function Vn(e) {
1414
1416
  return o.object(e);
1415
1417
  }
1416
1418
  //#endregion
1417
1419
  //#region src/shared/spline.ts
1418
- function Bn(e) {
1420
+ function Hn(e) {
1419
1421
  if (e.length < 2) return "";
1420
1422
  let t = e[0], n = e[1];
1421
1423
  if (!t || !n) return "";
@@ -1442,14 +1444,14 @@ function Bn(e) {
1442
1444
  }
1443
1445
  //#endregion
1444
1446
  //#region src/theme.ts
1445
- function Vn() {
1447
+ function Un() {
1446
1448
  return document.documentElement.classList.contains("dark");
1447
1449
  }
1448
1450
  //#endregion
1449
1451
  //#region src/version.ts
1450
- var Hn = {
1452
+ var Wn = {
1451
1453
  name: "@glasshome/widget-sdk",
1452
- version: "1.9.3",
1454
+ version: "1.10.0",
1453
1455
  description: "SDK for building GlassHome dashboard widgets with SolidJS",
1454
1456
  keywords: [
1455
1457
  "glasshome",
@@ -1508,7 +1510,7 @@ var Hn = {
1508
1510
  "typecheck:test": "tsc --noEmit -p tsconfig.test.json"
1509
1511
  },
1510
1512
  peerDependencies: {
1511
- "@glasshome/sync-layer": "0.6.0",
1513
+ "@glasshome/sync-layer": "0.7.0",
1512
1514
  "@glasshome/ui": "1.3.0",
1513
1515
  "solid-js": "^1.9.11"
1514
1516
  },
@@ -1545,4 +1547,4 @@ var Hn = {
1545
1547
  engines: { node: ">=18" }
1546
1548
  }.version;
1547
1549
  //#endregion
1548
- export { xe as Badge, Se as Button, Ce as ColorSlider, we as ColorWheel, Te as Input, Ee as Label, De as ResponsiveDialog, Oe as ResponsiveDialogContent, ke as ResponsiveDialogDescription, Ae as ResponsiveDialogHeader, je as ResponsiveDialogTitle, Hn as SDK_VERSION, Me as SchemaForm, Ne as Select, Pe as SelectContent, Fe as SelectItem, Ie as SelectTrigger, Le as SelectValue, Re as Slider, ze as Switch, vn as ToneSchema, H as Widget, ct as WidgetContent, L as WidgetCtx, $t as WidgetDialog, ft as WidgetIcon, r as WidgetManifestSchema, Xe as WidgetSizeCtx, ot as WidgetSliderFill, mt as WidgetStatus, _t as WidgetTitle, kt as WidgetValue, g as byDomain, vt as calculateLightGroup, yt as calculateSensorGroup, wt as countActiveEntities, zn as defineConfig, Ue as defineWidget, t as deprecations, Rn as field, n as formatDeprecation, i as formatSchemaError, Ct as getEntityAttribute, s as getForecasts, c as getStream, l as getWebRtcClientConfig, u as hassMediaUrl, nt as injectTokens, Vn as isDark, St as isEntityActive, Bn as monotoneCubicPath, Be as parseColor, d as sendWebRtcCandidate, f as startWebRtcSession, p as state, _n as svgColors, m as trackEntityHistory, h as untrackEntityHistory, _ as useArea, v as useCamera, ee as useConnection, y as useCurrency, b as useEntities, te as useEntity, ne as useEntityHistory, re as useEntityStatistics, x as useForecast, ie as useHassConfig, en as useIntersectionPause, ae as useLocale, tn as useReducedMotion, Ke as useService, se as useStore, S as useTemperatureUnit, Ye as useToggle, Je as useTurnOff, qe as useTurnOn, de as useUnitSystem, We as useWidgetContext, nn as useWidgetDialog, Ze as useWidgetDimensions, rn as useWidgetEntityGroup, mn as useWidgetGestures, yn as widgetFields, a as z };
1550
+ export { Se as Badge, Ce as Button, we as ColorSlider, Te as ColorWheel, Ee as Input, De as Label, Oe as ResponsiveDialog, ke as ResponsiveDialogContent, Ae as ResponsiveDialogDescription, je as ResponsiveDialogHeader, Me as ResponsiveDialogTitle, Wn as SDK_VERSION, Ne as SchemaForm, Pe as Select, Fe as SelectContent, Ie as SelectItem, Le as SelectTrigger, Re as SelectValue, ze as Slider, Be as Switch, bn as ToneSchema, H as Widget, lt as WidgetContent, L as WidgetCtx, tn as WidgetDialog, pt as WidgetIcon, r as WidgetManifestSchema, Ze as WidgetSizeCtx, st as WidgetSliderFill, ht as WidgetStatus, vt as WidgetTitle, At as WidgetValue, g as byDomain, yt as calculateLightGroup, bt as calculateSensorGroup, Tt as countActiveEntities, Vn as defineConfig, We as defineWidget, t as deprecations, Bn as field, n as formatDeprecation, i as formatSchemaError, wt as getEntityAttribute, s as getForecasts, c as getStream, l as getWebRtcClientConfig, u as hassMediaUrl, rt as injectTokens, Un as isDark, Ct as isEntityActive, Hn as monotoneCubicPath, Ve as parseColor, d as sendWebRtcCandidate, f as startWebRtcSession, p as state, yn as svgColors, m as trackEntityHistory, h as untrackEntityHistory, _ as useArea, v as useCalendarEvents, ee as useCamera, y as useConnection, b as useCurrency, te as useEntities, ne as useEntity, re as useEntityHistory, x as useEntityStatistics, ie as useForecast, ae as useHassConfig, nn as useIntersectionPause, oe as useLocale, rn as useReducedMotion, qe as useService, se as useStore, ce as useTemperatureUnit, Xe as useToggle, Ye as useTurnOff, Je as useTurnOn, fe as useUnitSystem, Ge as useWidgetContext, an as useWidgetDialog, Qe as useWidgetDimensions, on as useWidgetEntityGroup, gn as useWidgetGestures, xn as widgetFields, a as z };
@@ -80,7 +80,14 @@ var D = [
80
80
  "schema",
81
81
  "defaultConfig",
82
82
  "examples",
83
- "configVersion"
83
+ "configVersion",
84
+ "defaultSize",
85
+ "capabilities",
86
+ "name",
87
+ "description",
88
+ "icon",
89
+ "minSize",
90
+ "maxSize"
84
91
  ];
85
92
  function O(e, t, n) {
86
93
  let r = l(e, "utf-8"), i = JSON.parse(r), a = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glasshome/widget-sdk",
3
- "version": "1.9.3",
3
+ "version": "1.10.0",
4
4
  "description": "SDK for building GlassHome dashboard widgets with SolidJS",
5
5
  "keywords": [
6
6
  "glasshome",
@@ -59,7 +59,7 @@
59
59
  "typecheck:test": "tsc --noEmit -p tsconfig.test.json"
60
60
  },
61
61
  "peerDependencies": {
62
- "@glasshome/sync-layer": "0.6.0",
62
+ "@glasshome/sync-layer": "0.7.0",
63
63
  "@glasshome/ui": "1.3.0",
64
64
  "solid-js": "^1.9.11"
65
65
  },