@glasshome/widget-sdk 1.2.0 → 1.2.1

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/index.js CHANGED
@@ -1,1413 +1,1290 @@
1
- import { z as A } from "zod";
2
- import { widgetManifestSchema as xn, formatSchemaError as yn } from "@glasshome/widget-contract";
3
- import { effect as W, className as I, style as le, template as x, insert as p, createComponent as k, memo as T, setStyleProperty as ee, addEventListener as K, use as Ce, delegateEvents as Se } from "solid-js/web";
4
- import { createElementSize as Me } from "@solid-primitives/resize-observer";
5
- import { createContext as De, useContext as B, Show as E, createSignal as V, onMount as Te, createMemo as j, splitProps as _e, createEffect as se, on as ge, onCleanup as ce } from "solid-js";
6
- import { clsx as Oe } from "clsx";
7
- import { twMerge as ze } from "tailwind-merge";
8
- import { useService as Ee, useToggle as Ne, useTurnOff as Ae, useTurnOn as Ve } from "@glasshome/sync-layer/solid";
9
- import { byDomain as kn, useArea as Cn, useCamera as Sn, useConnection as Mn, useCurrency as Dn, useEntities as Tn, useEntity as _n, useEntityHistory as On, useEntityStatistics as zn, useForecast as En, useHassConfig as Nn, useLocale as An, useStore as Vn, useTemperatureUnit as Wn, useUnitSystem as Rn } from "@glasshome/sync-layer/solid";
10
- import { getForecasts as Pn, getStream as In, getWebRtcClientConfig as Ln, sendWebRtcCandidate as Un, startWebRtcSession as jn, state as Bn, trackEntityHistory as Fn, untrackEntityHistory as Gn } from "@glasshome/sync-layer";
11
- function me(e) {
12
- return A.toJSONSchema(e, {
13
- override: (t) => {
14
- const i = A.globalRegistry.get(t.zodSchema);
15
- return i && typeof i == "object" && Object.keys(i).length > 0 ? { ...t.jsonSchema, ...i } : t.jsonSchema;
16
- }
17
- });
18
- }
19
- function We(e) {
20
- try {
21
- return e.parse({});
22
- } catch {
23
- return {};
24
- }
25
- }
26
- function Jt(e) {
27
- return e.configSchema && (e.manifest.schema || (e.manifest.schema = me(e.configSchema)), e.manifest.defaultConfig || (e.manifest.defaultConfig = We(e.configSchema))), e;
28
- }
29
- const P = De();
30
- function Qt() {
31
- const e = B(P);
32
- if (!e)
33
- throw new Error("useWidgetContext must be used within a Widget component");
34
- return e;
35
- }
36
- function Re(e) {
37
- const t = Array.isArray(e) ? e[0] : e, i = t?.split(".")[0];
38
- if (!i) throw new Error(`Invalid entity ID: ${String(t)}`);
39
- return i;
40
- }
41
- function G(e, t) {
42
- return (i, r = {}) => e(Re(i), t, r, { entity_id: i });
43
- }
44
- function Zt() {
45
- const e = B(P)?.callService;
46
- return e ? {
47
- callService: e,
48
- turnOn: G(e, "turn_on"),
49
- turnOff: G(e, "turn_off"),
50
- toggle: G(e, "toggle")
51
- } : Ee();
52
- }
53
- function en() {
54
- const e = B(P)?.callService;
55
- return e ? G(e, "turn_on") : Ve();
56
- }
57
- function tn() {
58
- const e = B(P)?.callService;
59
- return e ? G(e, "turn_off") : Ae();
60
- }
61
- function nn() {
62
- const e = B(P)?.callService;
63
- return e ? G(e, "toggle") : Ne();
64
- }
65
- const J = {
66
- /** Background layer (gradients, images, glows) */
67
- BACKGROUND: 0,
68
- /** Main content layer (icon, title, text) */
69
- CONTENT: 10,
70
- /** Overlay layer (loading states, volume indicators) */
71
- OVERLAY: 20,
72
- /** Action layer (buttons, edit controls) */
73
- ACTIONS: 30
74
- }, ve = `/* Authoritative SDK CSS contract. Injected once on first Widget mount
75
- * via framework/theming/tokens.ts.
76
- *
77
- * All widget-internal visual scale is driven from CSS custom properties +
78
- * container queries on the \`.glasshome-widget\` shell (\`container-type: size\`).
79
- * No JS classifier, no size tier enum.
80
- */
81
-
82
- :root {
83
- --tone-success: oklch(0.70 0.18 145);
84
- --tone-warning: oklch(0.80 0.17 75);
85
- --tone-danger: oklch(0.64 0.22 27);
86
- --tone-info: oklch(0.66 0.20 245);
87
- --tone-neutral: oklch(0.65 0.02 250);
88
- --tone-accent: oklch(0.74 0.18 60);
89
-
90
- --widget-grad-strength: 1;
91
- --widget-glow-default: 0.4;
92
- --widget-border-highlight: oklch(0.98 0 0 / 0.4);
93
- }
94
-
95
- .dark {
96
- --tone-success: oklch(0.74 0.18 145);
97
- --tone-warning: oklch(0.82 0.17 75);
98
- --tone-danger: oklch(0.68 0.22 27);
99
- --tone-info: oklch(0.70 0.20 245);
100
- --tone-neutral: oklch(0.69 0.02 250);
101
- --tone-accent: oklch(0.78 0.18 60);
102
-
103
- --widget-grad-strength: 1.1;
104
- --widget-glow-default: 0.5;
105
- --widget-border-highlight: oklch(1 0 0 / 0.08);
106
- }
107
-
108
- @property --widget-color {
109
- syntax: "<color>";
110
- inherits: true;
111
- initial-value: oklch(0.65 0.02 250);
112
- }
113
-
114
- /* === Widget shell ===
115
- * Fluid scale tokens — tied to the shell's own container box (cqmin/cqi/cqb).
116
- * Same input box → same output, so two widgets at the same grid cell match
117
- * exactly. Tune multipliers / clamps to adjust density. */
118
- .glasshome-widget {
119
- --widget-color: var(--tone-neutral);
120
- --widget-glow-strength: var(--widget-glow-default);
121
-
122
- --widget-icon-box: clamp(28px, 22cqmin, 64px);
123
- --widget-icon-glyph: clamp(16px, 13cqmin, 36px);
124
- --widget-pad: clamp(8px, 4cqmin, 24px);
125
- --widget-gap: clamp(6px, 2cqmin, 16px);
126
- --widget-title-size: clamp(12px, 2cqi, 18px);
127
- --widget-subtitle: clamp(12px, 2.5cqi, 20px);
128
- --widget-status-size: clamp(14px, 5cqi, 36px);
129
- --widget-value-size: clamp(18px, 7cqi, 48px);
130
- --widget-badge-size: clamp(11px, 1.6cqi, 14px);
131
- }
132
-
133
- .glasshome-widget {
134
- background: var(--widget-gradient,
135
- linear-gradient(135deg,
136
- color-mix(in oklch, var(--widget-color) calc(22% * var(--widget-grad-strength)), transparent),
137
- color-mix(in oklch, var(--widget-color-to, var(--widget-color)) calc(11% * var(--widget-grad-strength)), transparent)
138
- )
139
- );
140
- box-shadow: inset 0 1px 0 var(--widget-border-highlight);
141
- }
142
-
143
- /* === Slot: content layout === */
144
- /* Default: column. Flip to row only on wide-and-short widgets (matches the
145
- * old contentLayout heuristic: aspect > 1 AND height < 150px). */
146
- .glasshome-widget-content {
147
- position: relative;
148
- display: flex;
149
- flex-direction: column;
150
- justify-content: space-between;
151
- width: 100%;
152
- height: 100%;
153
- padding: var(--widget-pad);
154
- gap: var(--widget-gap);
155
- overflow: hidden;
156
- }
157
- @container widget (min-aspect-ratio: 1) and (max-height: 149px) {
158
- .glasshome-widget-content {
159
- flex-direction: row;
160
- align-items: center;
161
- justify-content: flex-start;
162
- }
163
- }
164
- .glasshome-widget-content [class*="ml-auto"] {
165
- position: relative;
166
- z-index: 30;
167
- }
168
-
169
- /* === Slot: icon === */
170
- .glasshome-widget-icon {
171
- width: var(--widget-icon-box);
172
- height: var(--widget-icon-box);
173
- border-radius: var(--radius-sm, 12px);
174
- background: var(--widget-icon-color, var(--widget-color));
175
- box-shadow: 0 0 calc(var(--widget-glow-strength) * 30px)
176
- color-mix(in oklch, var(--widget-icon-color, var(--widget-color)) 50%, transparent);
177
- color: oklch(from var(--widget-icon-color, var(--widget-color)) calc(0.52 + sign(0.5 - l) * 0.43) calc(c * 0.2) h);
178
- }
179
- .glasshome-widget-icon-glyph {
180
- font-size: var(--widget-icon-glyph);
181
- line-height: 1;
182
- }
183
- .glasshome-widget-icon-stack {
184
- position: absolute;
185
- width: 102%;
186
- height: 102%;
187
- border-radius: var(--radius-sm, 12px);
188
- }
189
- .glasshome-widget-icon-stack-2 { bottom: -14%; right: -10%; opacity: 0.45; z-index: -2; }
190
- .glasshome-widget-icon-stack-3 { bottom: -28%; right: -20%; opacity: 0.20; z-index: -3; }
191
-
192
- /* === Slot: text === */
193
- .glasshome-widget-title {
194
- font-size: var(--widget-title-size);
195
- line-height: 1.2;
196
- color: color-mix(in oklch, var(--color-foreground, currentColor) 60%, transparent);
197
- overflow: hidden;
198
- text-overflow: ellipsis;
199
- white-space: nowrap;
200
- }
201
- .glasshome-widget-subtitle {
202
- font-size: var(--widget-subtitle);
203
- color: color-mix(in oklch, var(--color-foreground, currentColor) 60%, transparent);
204
- }
205
- .glasshome-widget-status {
206
- font-size: var(--widget-status-size);
207
- font-weight: 700;
208
- color: var(--color-foreground, currentColor);
209
- line-height: 1.1;
210
- }
211
- .glasshome-widget-value {
212
- font-size: var(--widget-value-size);
213
- font-weight: 700;
214
- color: var(--color-foreground, currentColor);
215
- line-height: 1.05;
216
- }
217
- .glasshome-widget-badge {
218
- font-size: var(--widget-badge-size);
219
- font-weight: 500;
220
- padding: 0.125rem 0.5rem;
221
- border-radius: 9999px;
222
- background: color-mix(in oklch, var(--color-foreground, currentColor) 20%, transparent);
223
- color: var(--color-foreground, currentColor);
224
- }
225
-
226
- .glasshome-widget-loading {
227
- background: color-mix(in oklch, var(--widget-color) 20%, transparent);
228
- }
229
-
230
- /* === Slider fill ===
231
- * Value flows in via --widget-fill-value (0-100). Vertical orientation auto-
232
- * detected via container query. */
233
- .glasshome-widget-slider-fill {
234
- --widget-fill-value: 0;
235
- background: color-mix(in oklch, var(--widget-icon-color, var(--widget-color)) 30%, transparent);
236
- box-shadow: 0 0 calc(var(--widget-glow-strength) * 40px)
237
- color-mix(in oklch, var(--widget-icon-color, var(--widget-color)) 40%, transparent);
238
- clip-path: inset(0 calc((100 - var(--widget-fill-value)) * 1%) 0 0);
239
- }
240
- @container widget (max-aspect-ratio: 1) {
241
- .glasshome-widget-slider-fill {
242
- clip-path: inset(calc((100 - var(--widget-fill-value)) * 1%) 0 0 0);
243
- }
244
- }
245
- `;
246
- let re = !1, Q;
247
- const he = /* @__PURE__ */ new WeakSet();
248
- function He() {
249
- return Q || (Q = new CSSStyleSheet(), Q.replaceSync(
250
- ve.replace(/:root\b/g, ":host").replace(/^\.dark\b/gm, ":host(.dark)")
251
- )), Q;
1
+ import { WidgetManifestSchema as e, formatSchemaError as t } from "./schemas.js";
2
+ import { z as n } from "zod";
3
+ import { getForecasts as r, getStream as i, getWebRtcClientConfig as a, sendWebRtcCandidate as o, startWebRtcSession as s, state as c, trackEntityHistory as l, untrackEntityHistory as u } from "@glasshome/sync-layer";
4
+ import { byDomain as d, useArea as f, useCamera as p, useConnection as m, useCurrency as h, useEntities as g, useEntity as _, useEntityHistory as v, useEntityStatistics as ee, useForecast as y, useHassConfig as b, useLocale as te, useService as x, useStore as ne, useTemperatureUnit as re, useToggle as ie, useTurnOff as S, useTurnOn as ae, useUnitSystem as oe } from "@glasshome/sync-layer/solid";
5
+ import { Show as C, createContext as se, createEffect as ce, createMemo as w, createSignal as T, on as le, onCleanup as E, onMount as ue, splitProps as de, useContext as D } from "solid-js";
6
+ import { addEventListener as O, className as k, createComponent as A, delegateEvents as fe, effect as j, insert as M, memo as N, setStyleProperty as P, style as pe, template as F, use as me } from "solid-js/web";
7
+ import { createElementSize as he } from "@solid-primitives/resize-observer";
8
+ import { clsx as ge } from "clsx";
9
+ import { twMerge as _e } from "tailwind-merge";
10
+ //#region src/framework/to-form-schema.ts
11
+ function ve(e) {
12
+ return n.toJSONSchema(e, { override: (e) => {
13
+ let t = n.globalRegistry.get(e.zodSchema);
14
+ return t && typeof t == "object" && Object.keys(t).length > 0 ? {
15
+ ...e.jsonSchema,
16
+ ...t
17
+ } : e.jsonSchema;
18
+ } });
19
+ }
20
+ function ye(e) {
21
+ try {
22
+ return e.parse({});
23
+ } catch {
24
+ return {};
25
+ }
26
+ }
27
+ //#endregion
28
+ //#region src/define-widget.ts
29
+ function be(e) {
30
+ return e.configSchema && (e.manifest.schema || (e.manifest.schema = ve(e.configSchema)), e.manifest.defaultConfig || (e.manifest.defaultConfig = ye(e.configSchema))), e;
31
+ }
32
+ //#endregion
33
+ //#region src/framework/hooks/use-widget-context.ts
34
+ var I = se();
35
+ function xe() {
36
+ let e = D(I);
37
+ if (!e) throw Error("useWidgetContext must be used within a Widget component");
38
+ return e;
39
+ }
40
+ //#endregion
41
+ //#region src/framework/hooks/use-service.ts
42
+ function Se(e) {
43
+ let t = Array.isArray(e) ? e[0] : e, n = t?.split(".")[0];
44
+ if (!n) throw Error(`Invalid entity ID: ${String(t)}`);
45
+ return n;
46
+ }
47
+ function L(e, t) {
48
+ return (n, r = {}) => e(Se(n), t, r, { entity_id: n });
49
+ }
50
+ function Ce() {
51
+ let e = D(I)?.callService;
52
+ return e ? {
53
+ callService: e,
54
+ turnOn: L(e, "turn_on"),
55
+ turnOff: L(e, "turn_off"),
56
+ toggle: L(e, "toggle")
57
+ } : x();
58
+ }
59
+ function we() {
60
+ let e = D(I)?.callService;
61
+ return e ? L(e, "turn_on") : ae();
62
+ }
63
+ function Te() {
64
+ let e = D(I)?.callService;
65
+ return e ? L(e, "turn_off") : S();
66
+ }
67
+ function Ee() {
68
+ let e = D(I)?.callService;
69
+ return e ? L(e, "toggle") : ie();
70
+ }
71
+ //#endregion
72
+ //#region src/framework/design-system/z-index.ts
73
+ var R = {
74
+ BACKGROUND: 0,
75
+ CONTENT: 10,
76
+ OVERLAY: 20,
77
+ ACTIONS: 30
78
+ }, De = "/* 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 (cqmin/cqi/cqb).\n * Same input box → same output, so two widgets at the same grid cell match\n * exactly. Tune 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(28px, 22cqmin, 64px);\n --widget-icon-glyph: clamp(16px, 13cqmin, 36px);\n --widget-pad: clamp(8px, 4cqmin, 24px);\n --widget-gap: clamp(6px, 2cqmin, 16px);\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.glasshome-widget {\n background: 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 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.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", z = !1, B, Oe = /* @__PURE__ */ new WeakSet();
79
+ function ke() {
80
+ return B || (B = new CSSStyleSheet(), B.replaceSync(De.replace(/:root\b/g, ":host").replace(/^\.dark\b/gm, ":host(.dark)"))), B;
81
+ }
82
+ function Ae(e) {
83
+ if (typeof ShadowRoot < "u" && e instanceof ShadowRoot) {
84
+ if (Oe.has(e)) return;
85
+ let t = ke();
86
+ e.adoptedStyleSheets.includes(t) || (e.adoptedStyleSheets = [...e.adoptedStyleSheets, t]), Oe.add(e);
87
+ return;
88
+ }
89
+ if (z) return;
90
+ let t = e ?? (typeof document > "u" ? void 0 : document);
91
+ if (!t) return;
92
+ if (t.head.querySelector?.("style[data-glasshome-tokens]")) {
93
+ z = !0;
94
+ return;
95
+ }
96
+ let n = t.createElement("style");
97
+ n.setAttribute("data-glasshome-tokens", ""), n.textContent = De, t.head.appendChild(n), z = !0;
98
+ }
99
+ //#endregion
100
+ //#region src/framework/utils/cn.ts
101
+ function V(...e) {
102
+ return _e(ge(e));
103
+ }
104
+ var je = {
105
+ "classic-glass": {
106
+ id: "classic-glass",
107
+ name: "Classic Glass",
108
+ description: "Default glassmorphism design with blur background and gradient",
109
+ styles: {
110
+ cssVars: {
111
+ "--widget-bg": "rgba(255, 255, 255, 0.1)",
112
+ "--widget-border": "rgba(255, 255, 255, 0.2)",
113
+ "--widget-blur": "12px",
114
+ "--widget-shadow": "0 8px 32px rgba(0, 0, 0, 0.2)",
115
+ "--widget-padding": "1.5rem"
116
+ },
117
+ class: "backdrop-blur-xl"
118
+ },
119
+ layout: {
120
+ type: "flex",
121
+ direction: "column",
122
+ align: "start",
123
+ justify: "start",
124
+ gap: "0.75rem"
125
+ },
126
+ interactions: {
127
+ hover: !0,
128
+ active: !0,
129
+ focus: !0,
130
+ hoverScale: 1.02,
131
+ activeScale: .98
132
+ }
133
+ },
134
+ minimal: {
135
+ id: "minimal",
136
+ name: "Minimal",
137
+ description: "Clean, minimal design with no background effects",
138
+ styles: { cssVars: {
139
+ "--widget-bg": "transparent",
140
+ "--widget-border": "rgba(255, 255, 255, 0.1)",
141
+ "--widget-padding": "1rem"
142
+ } },
143
+ layout: {
144
+ type: "flex",
145
+ direction: "column",
146
+ align: "start",
147
+ justify: "start",
148
+ gap: "0.5rem"
149
+ },
150
+ elements: { visible: {
151
+ background: !1,
152
+ decorations: !1
153
+ } },
154
+ interactions: {
155
+ hover: !1,
156
+ active: !1,
157
+ focus: !0
158
+ }
159
+ },
160
+ "compact-horizontal": {
161
+ id: "compact-horizontal",
162
+ name: "Compact Horizontal",
163
+ description: "Horizontal layout for compact widgets",
164
+ styles: {
165
+ cssVars: {
166
+ "--widget-bg": "rgba(255, 255, 255, 0.08)",
167
+ "--widget-border": "rgba(255, 255, 255, 0.15)",
168
+ "--widget-blur": "10px",
169
+ "--widget-padding": "1rem",
170
+ "--widget-icon-size": "2.5rem"
171
+ },
172
+ class: "backdrop-blur-lg"
173
+ },
174
+ layout: {
175
+ type: "flex",
176
+ direction: "row",
177
+ align: "center",
178
+ justify: "start",
179
+ gap: "1rem"
180
+ },
181
+ interactions: {
182
+ hover: !0,
183
+ active: !0,
184
+ focus: !0,
185
+ hoverScale: 1.02,
186
+ activeScale: .98
187
+ }
188
+ }
189
+ };
190
+ function Me(e) {
191
+ return je[e];
252
192
  }
193
+ //#endregion
194
+ //#region src/framework/backgrounds/WidgetSliderFill.tsx
195
+ var Ne = /*#__PURE__*/ F("<div>");
253
196
  function Pe(e) {
254
- if (typeof ShadowRoot < "u" && e instanceof ShadowRoot) {
255
- if (he.has(e)) return;
256
- const r = He();
257
- e.adoptedStyleSheets.includes(r) || (e.adoptedStyleSheets = [...e.adoptedStyleSheets, r]), he.add(e);
258
- return;
259
- }
260
- if (re) return;
261
- const t = e ?? (typeof document > "u" ? void 0 : document);
262
- if (!t) return;
263
- if (t.head.querySelector?.("style[data-glasshome-tokens]")) {
264
- re = !0;
265
- return;
266
- }
267
- const i = t.createElement("style");
268
- i.setAttribute("data-glasshome-tokens", ""), i.textContent = ve, t.head.appendChild(i), re = !0;
269
- }
270
- function R(...e) {
271
- return ze(Oe(e));
272
- }
273
- const Ie = {
274
- id: "classic-glass",
275
- name: "Classic Glass",
276
- description: "Default glassmorphism design with blur background and gradient",
277
- styles: {
278
- cssVars: {
279
- "--widget-bg": "rgba(255, 255, 255, 0.1)",
280
- "--widget-border": "rgba(255, 255, 255, 0.2)",
281
- "--widget-blur": "12px",
282
- "--widget-shadow": "0 8px 32px rgba(0, 0, 0, 0.2)",
283
- "--widget-padding": "1.5rem"
284
- },
285
- class: "backdrop-blur-xl"
286
- },
287
- layout: {
288
- type: "flex",
289
- direction: "column",
290
- align: "start",
291
- justify: "start",
292
- gap: "0.75rem"
293
- },
294
- interactions: {
295
- hover: !0,
296
- active: !0,
297
- focus: !0,
298
- hoverScale: 1.02,
299
- activeScale: 0.98
300
- }
301
- }, Le = {
302
- id: "minimal",
303
- name: "Minimal",
304
- description: "Clean, minimal design with no background effects",
305
- styles: {
306
- cssVars: {
307
- "--widget-bg": "transparent",
308
- "--widget-border": "rgba(255, 255, 255, 0.1)",
309
- "--widget-padding": "1rem"
310
- }
311
- },
312
- layout: {
313
- type: "flex",
314
- direction: "column",
315
- align: "start",
316
- justify: "start",
317
- gap: "0.5rem"
318
- },
319
- elements: {
320
- visible: {
321
- background: !1,
322
- decorations: !1
323
- }
324
- },
325
- interactions: {
326
- hover: !1,
327
- active: !1,
328
- focus: !0
329
- }
330
- }, Ue = {
331
- id: "compact-horizontal",
332
- name: "Compact Horizontal",
333
- description: "Horizontal layout for compact widgets",
334
- styles: {
335
- cssVars: {
336
- "--widget-bg": "rgba(255, 255, 255, 0.08)",
337
- "--widget-border": "rgba(255, 255, 255, 0.15)",
338
- "--widget-blur": "10px",
339
- "--widget-padding": "1rem",
340
- "--widget-icon-size": "2.5rem"
341
- },
342
- class: "backdrop-blur-lg"
343
- },
344
- layout: {
345
- type: "flex",
346
- direction: "row",
347
- align: "center",
348
- justify: "start",
349
- gap: "1rem"
350
- },
351
- interactions: {
352
- hover: !0,
353
- active: !0,
354
- focus: !0,
355
- hoverScale: 1.02,
356
- activeScale: 0.98
357
- }
358
- }, je = {
359
- "classic-glass": Ie,
360
- minimal: Le,
361
- "compact-horizontal": Ue
362
- };
197
+ return (() => {
198
+ var t = Ne();
199
+ return j((n) => {
200
+ 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 = {
201
+ "--widget-fill-value": e.value,
202
+ "z-index": R.BACKGROUND,
203
+ ...e.color ? { "--widget-icon-color": e.color } : {}
204
+ };
205
+ return r !== n.e && k(t, n.e = r), n.t = pe(t, i, n.t), n;
206
+ }, {
207
+ e: void 0,
208
+ t: void 0
209
+ }), t;
210
+ })();
211
+ }
212
+ //#endregion
213
+ //#region src/framework/components/WidgetContent.tsx
214
+ var Fe = /*#__PURE__*/ F("<div>");
215
+ function Ie(e) {
216
+ return (() => {
217
+ var t = Fe();
218
+ return M(t, () => e.children), j(() => k(t, V("glasshome-widget-content", e.class))), t;
219
+ })();
220
+ }
221
+ //#endregion
222
+ //#region src/framework/components/WidgetIcon.tsx
223
+ var Le = /*#__PURE__*/ F("<div class=\"glasshome-widget-icon glasshome-widget-icon-stack glasshome-widget-icon-stack-2\">"), Re = /*#__PURE__*/ F("<div class=\"glasshome-widget-icon glasshome-widget-icon-stack glasshome-widget-icon-stack-3\">"), ze = /*#__PURE__*/ F("<div><div class=\"glasshome-widget-icon-glyph flex items-center justify-center\">");
363
224
  function Be(e) {
364
- return je[e];
365
- }
366
- var Fe = /* @__PURE__ */ x("<div>");
225
+ let t = () => e.entityCount ?? 1;
226
+ return (() => {
227
+ var n = ze(), r = n.firstChild;
228
+ return M(n, A(C, {
229
+ get when() {
230
+ return t() >= 2;
231
+ },
232
+ get children() {
233
+ return Le();
234
+ }
235
+ }), r), M(n, A(C, {
236
+ get when() {
237
+ return t() >= 3;
238
+ },
239
+ get children() {
240
+ return Re();
241
+ }
242
+ }), r), M(r, () => e.icon), j((t) => {
243
+ 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;
244
+ return r !== t.e && k(n, t.e = r), t.t = pe(n, i, t.t), t;
245
+ }, {
246
+ e: void 0,
247
+ t: void 0
248
+ }), n;
249
+ })();
250
+ }
251
+ //#endregion
252
+ //#region src/framework/components/WidgetStatus.tsx
253
+ var Ve = /*#__PURE__*/ F("<p>");
254
+ function He(e) {
255
+ return (() => {
256
+ var t = Ve();
257
+ return M(t, (() => {
258
+ var t = N(() => !!e.isUnavailable);
259
+ return () => t() ? "Unavailable" : e.children;
260
+ })()), j((n) => {
261
+ var r = V("glasshome-widget-status", "relative", e.dimmed && "opacity-40", e.class), i = R.ACTIONS;
262
+ return r !== n.e && k(t, n.e = r), i !== n.t && P(t, "z-index", n.t = i), n;
263
+ }, {
264
+ e: void 0,
265
+ t: void 0
266
+ }), t;
267
+ })();
268
+ }
269
+ //#endregion
270
+ //#region src/framework/components/WidgetTitle.tsx
271
+ var Ue = /*#__PURE__*/ F("<span class=\"glasshome-widget-badge shrink-0\">"), We = /*#__PURE__*/ F("<div><h3 class=glasshome-widget-title>");
367
272
  function Ge(e) {
368
- return (() => {
369
- var t = Fe();
370
- return W((i) => {
371
- var r = R("glasshome-widget-slider-fill pointer-events-none absolute inset-0", e.isDragging ? "duration-0" : "transition-all duration-300 ease-out", e.class), n = {
372
- "--widget-fill-value": e.value,
373
- "z-index": J.BACKGROUND,
374
- ...e.color ? {
375
- "--widget-icon-color": e.color
376
- } : {}
377
- };
378
- return r !== i.e && I(t, i.e = r), i.t = le(t, n, i.t), i;
379
- }, {
380
- e: void 0,
381
- t: void 0
382
- }), t;
383
- })();
384
- }
385
- var qe = /* @__PURE__ */ x("<div>");
273
+ return (() => {
274
+ var t = We(), n = t.firstChild;
275
+ return M(n, () => e.children), M(t, A(C, {
276
+ get when() {
277
+ return N(() => e.badge !== void 0)() && e.badge > 0;
278
+ },
279
+ get children() {
280
+ var t = Ue();
281
+ return M(t, () => e.badge), t;
282
+ }
283
+ }), null), j((n) => {
284
+ var r = V("relative flex items-center gap-2", e.class), i = R.ACTIONS;
285
+ return r !== n.e && k(t, n.e = r), i !== n.t && P(t, "z-index", n.t = i), n;
286
+ }, {
287
+ e: void 0,
288
+ t: void 0
289
+ }), t;
290
+ })();
291
+ }
292
+ //#endregion
293
+ //#region src/framework/utils/entity-aggregation.ts
294
+ function Ke(e, t = !1) {
295
+ if (e.length === 0) return {
296
+ isGroup: !1,
297
+ state: "unknown",
298
+ isOn: !1,
299
+ isUnavailable: !0,
300
+ brightness: 0,
301
+ brightnessPercent: 0,
302
+ color: "rgb(100, 100, 100)",
303
+ onCount: 0,
304
+ totalCount: 0,
305
+ description: "No entities"
306
+ };
307
+ let n = e.length > 1;
308
+ if (!n) {
309
+ let t = e[0], n = t.state === "on", r = t.attributes?.brightness || 0, i = Math.round(r / 255 * 100);
310
+ return {
311
+ isGroup: !1,
312
+ state: t.state,
313
+ isOn: n,
314
+ isUnavailable: t.state === "unavailable",
315
+ brightness: r,
316
+ brightnessPercent: i,
317
+ color: Je(t),
318
+ onCount: +!!n,
319
+ totalCount: 1,
320
+ description: n ? "On" : "Off"
321
+ };
322
+ }
323
+ let r = 0, i = 0, a = 0, o = 0, s = 0, c = 0, l = [];
324
+ for (let t of e) switch (t.state) {
325
+ case "on":
326
+ r++, t.attributes?.brightness !== void 0 && (s += t.attributes.brightness, c++), t.attributes?.rgb_color && l.push(t.attributes.rgb_color);
327
+ break;
328
+ case "off":
329
+ i++;
330
+ break;
331
+ case "unknown":
332
+ a++;
333
+ break;
334
+ case "unavailable":
335
+ o++;
336
+ break;
337
+ }
338
+ let u = e.length, d = o === u, f = a + o === u, p = r > 0, m = r === u, h = i === u, g, _;
339
+ t ? d ? (g = "unavailable", _ = !1) : a > 0 || o > 0 ? (g = "unknown", _ = !1) : i > 0 ? (g = "off", _ = !1) : (g = "on", _ = !0) : d ? (g = "unavailable", _ = !1) : f ? (g = "unknown", _ = !1) : p ? (g = "on", _ = !0) : (g = "off", _ = !1);
340
+ let v = c > 0 ? Math.round(s / c) : 0, ee = Math.round(v / 255 * 100), y;
341
+ if (l.length > 0) {
342
+ 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;
343
+ y = `rgb(${Math.round(e * r)}, ${Math.round(t * r)}, ${Math.round(n * r)})`;
344
+ } else y = Je(e[0]);
345
+ let b;
346
+ return b = m ? "All on" : h ? "All off" : r > 0 ? `${r} of ${u} on` : "Off", {
347
+ isGroup: n,
348
+ state: g,
349
+ isOn: _,
350
+ isUnavailable: g === "unavailable",
351
+ brightness: v,
352
+ brightnessPercent: ee,
353
+ color: y,
354
+ onCount: r,
355
+ totalCount: u,
356
+ description: b
357
+ };
358
+ }
359
+ function qe(e, t = "mean", n = !0) {
360
+ if (e.length === 0) return {
361
+ isGroup: !1,
362
+ state: "unknown",
363
+ numericValue: null,
364
+ isUnavailable: !0,
365
+ description: "No entities"
366
+ };
367
+ let r = e.length > 1;
368
+ if (!r) {
369
+ let t = e[0], n = Number.parseFloat(t.state), r = t.state;
370
+ return Number.isNaN(n) || (r = Number.isInteger(n) ? n.toString() : n.toFixed(1)), {
371
+ isGroup: !1,
372
+ state: r,
373
+ numericValue: Number.isNaN(n) ? null : n,
374
+ isUnavailable: t.state === "unavailable",
375
+ unit: t.unitOfMeasurement ?? void 0,
376
+ description: r
377
+ };
378
+ }
379
+ let i = [], a = [], o = 0, s;
380
+ for (let t of e) {
381
+ if (!s && t.unitOfMeasurement && (s = t.unitOfMeasurement), t.state === "unavailable") {
382
+ o++, a.push({
383
+ entityId: t.id,
384
+ value: "unavailable",
385
+ friendly_name: t.friendlyName
386
+ });
387
+ continue;
388
+ }
389
+ let e = Number.parseFloat(t.state);
390
+ isNaN(e) ? n || a.push({
391
+ entityId: t.id,
392
+ value: t.state,
393
+ friendly_name: t.friendlyName
394
+ }) : (i.push(e), a.push({
395
+ entityId: t.id,
396
+ value: e,
397
+ friendly_name: t.friendlyName
398
+ }));
399
+ }
400
+ let c = o === e.length, l = i.length === 0;
401
+ if (c || l) return {
402
+ isGroup: r,
403
+ state: c ? "unavailable" : "unknown",
404
+ numericValue: null,
405
+ isUnavailable: c,
406
+ unit: s,
407
+ description: c ? "Unavailable" : "No numeric values",
408
+ memberValues: a
409
+ };
410
+ let u, d;
411
+ switch (t) {
412
+ case "min":
413
+ u = Math.min(...i), d = "Minimum";
414
+ break;
415
+ case "max":
416
+ u = Math.max(...i), d = "Maximum";
417
+ break;
418
+ case "mean":
419
+ u = i.reduce((e, t) => e + t, 0) / i.length, d = "Average";
420
+ break;
421
+ case "median": {
422
+ let e = [...i].sort((e, t) => e - t), t = Math.floor(e.length / 2);
423
+ u = e.length % 2 == 0 ? (e[t - 1] + e[t]) / 2 : e[t], d = "Median";
424
+ break;
425
+ }
426
+ case "sum":
427
+ u = i.reduce((e, t) => e + t, 0), d = "Sum";
428
+ break;
429
+ case "last":
430
+ u = i[i.length - 1], d = "Latest";
431
+ break;
432
+ case "range":
433
+ u = Math.max(...i) - Math.min(...i), d = "Range";
434
+ break;
435
+ case "product":
436
+ u = i.reduce((e, t) => e * t, 1), d = "Product";
437
+ break;
438
+ case "std_dev": {
439
+ let e = i.reduce((e, t) => e + t, 0) / i.length, t = i.reduce((t, n) => t + (n - e) ** 2, 0) / i.length;
440
+ u = Math.sqrt(t), d = "Std Dev";
441
+ break;
442
+ }
443
+ default: u = i.reduce((e, t) => e + t, 0) / i.length, d = "Average";
444
+ }
445
+ return {
446
+ isGroup: r,
447
+ state: Number.isInteger(u) ? u.toString() : u.toFixed(1),
448
+ numericValue: u,
449
+ isUnavailable: !1,
450
+ unit: s,
451
+ description: `${d} of ${i.length}`,
452
+ memberValues: a
453
+ };
454
+ }
455
+ function Je(e) {
456
+ if (e.state !== "on") return "rgb(100, 100, 100)";
457
+ let t = (e.attributes?.brightness ?? 255) / 255;
458
+ if (e.attributes?.rgb_color) {
459
+ let [n, r, i] = e.attributes.rgb_color;
460
+ return `rgb(${Math.round(n * t)}, ${Math.round(r * t)}, ${Math.round(i * t)})`;
461
+ }
462
+ if (e.attributes?.color_temp) {
463
+ let n = 1e6 / e.attributes.color_temp / 100, r, i, a;
464
+ return n <= 66 ? (r = 255, i = n <= 19 ? 0 : 99.4708025861 * Math.log(n - 10) - 161.1195681661, a = n <= 19 ? 0 : n <= 66 ? 138.5177312231 * Math.log(n - 10) - 305.0447927307 : 255) : (r = 329.698727446 * (n - 60) ** -.1332047592, i = 288.1221695283 * (n - 60) ** -.0755148492, a = 255), r = Math.max(0, Math.min(255, r)) * t, i = Math.max(0, Math.min(255, i)) * t, a = Math.max(0, Math.min(255, a)) * t, `rgb(${Math.round(r)}, ${Math.round(i)}, ${Math.round(a)})`;
465
+ }
466
+ return `rgb(${Math.round(255 * t)}, ${Math.round(220 * t)}, ${Math.round(180 * t)})`;
467
+ }
468
+ //#endregion
469
+ //#region src/framework/utils/entity-state.ts
386
470
  function Ye(e) {
387
- return (() => {
388
- var t = qe();
389
- return p(t, () => e.children), W(() => I(t, R("glasshome-widget-content", e.class))), t;
390
- })();
391
- }
392
- var Ke = /* @__PURE__ */ x('<div class="glasshome-widget-icon glasshome-widget-icon-stack glasshome-widget-icon-stack-2">'), Xe = /* @__PURE__ */ x('<div class="glasshome-widget-icon glasshome-widget-icon-stack glasshome-widget-icon-stack-3">'), Je = /* @__PURE__ */ x('<div><div class="glasshome-widget-icon-glyph flex items-center justify-center">');
393
- function Qe(e) {
394
- const t = () => e.entityCount ?? 1;
395
- return (() => {
396
- var i = Je(), r = i.firstChild;
397
- return p(i, k(E, {
398
- get when() {
399
- return t() >= 2;
400
- },
401
- get children() {
402
- return Ke();
403
- }
404
- }), r), p(i, k(E, {
405
- get when() {
406
- return t() >= 3;
407
- },
408
- get children() {
409
- return Xe();
410
- }
411
- }), r), p(r, () => e.icon), W((n) => {
412
- var o = R("glasshome-widget-icon", "relative flex shrink-0 items-center justify-center pointer-events-none transition-all", e.dimmed && "opacity-50", e.class), u = e.color ? {
413
- "--widget-icon-color": e.color
414
- } : void 0;
415
- return o !== n.e && I(i, n.e = o), n.t = le(i, u, n.t), n;
416
- }, {
417
- e: void 0,
418
- t: void 0
419
- }), i;
420
- })();
471
+ if (!e) return !1;
472
+ if ([
473
+ "on",
474
+ "open",
475
+ "locked",
476
+ "home",
477
+ "playing",
478
+ "active"
479
+ ].includes(e.state)) return !0;
480
+ if (e.domain === "sensor") {
481
+ let t = Number.parseFloat(e.state);
482
+ return !isNaN(t) && t > 0;
483
+ }
484
+ return !1;
485
+ }
486
+ function Xe(e, t, n) {
487
+ return e?.attributes ? e.attributes[t] ?? n : n;
488
+ }
489
+ function Ze(e) {
490
+ return e.filter(Ye).length;
491
+ }
492
+ //#endregion
493
+ //#region src/framework/utils/format-value.ts
494
+ function Qe(e, t, n) {
495
+ let { decimals: r, scale: i = !0 } = n || {};
496
+ if (typeof e == "string") return t ? `${e}${t}` : e;
497
+ if (e == null || Number.isNaN(e)) return t ? `--${t}` : "--";
498
+ let a = e, o = t || "";
499
+ i && t && (t === "W" || t === "kW" || t === "MW") && (e >= 1e6 ? (a = e / 1e6, o = "MW") : e >= 1e3 ? (a = e / 1e3, o = "kW") : o = "W"), i && t && (t === "B" || t === "KB" || t === "MB" || t === "GB") && (e >= 1073741824 ? (a = e / 1073741824, o = "GB") : e >= 1048576 ? (a = e / 1048576, o = "MB") : e >= 1024 ? (a = e / 1024, o = "KB") : o = "B");
500
+ let s;
501
+ return s = r === void 0 ? a === e ? Number.isInteger(e) ? e.toString() : Number.parseFloat(e.toFixed(2)).toString() : a.toFixed(1) : a.toFixed(r), o ? `${s}${o}` : s;
502
+ }
503
+ //#endregion
504
+ //#region src/framework/utils/interpret-value.ts
505
+ function $e(e, t) {
506
+ 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;
507
+ }
508
+ //#endregion
509
+ //#region src/framework/components/WidgetValue.tsx
510
+ var et = /*#__PURE__*/ F("<div class=glasshome-widget-subtitle>"), tt = /*#__PURE__*/ F("<div><div class=glasshome-widget-value>");
511
+ function nt(e) {
512
+ return (() => {
513
+ var t = tt(), n = t.firstChild;
514
+ return M(n, () => Qe(e.value, e.unit)), M(t, A(C, {
515
+ get when() {
516
+ return N(() => !!e.interpret)() && typeof e.value == "number";
517
+ },
518
+ get children() {
519
+ var t = et();
520
+ return M(t, () => $e(e.value, e.unit)), t;
521
+ }
522
+ }), null), j(() => k(t, V("flex flex-col", e.class))), t;
523
+ })();
524
+ }
525
+ //#endregion
526
+ //#region src/framework/core/Widget.tsx
527
+ var rt = /*#__PURE__*/ F("<div><div class=\"relative h-full w-full\">"), it = /*#__PURE__*/ F("<div class=\"glasshome-widget-loading pointer-events-none absolute inset-0 animate-pulse\">"), at = /*#__PURE__*/ F("<div class=\"flex h-full w-full flex-col items-center justify-center gap-2 text-center\">"), ot = /*#__PURE__*/ F("<div class=\"flex items-center justify-center text-white/30\">"), st = /*#__PURE__*/ F("<h3 class=\"font-semibold text-sm text-white/60\">"), ct = /*#__PURE__*/ F("<p class=\"text-white/50 text-xs\">");
528
+ function lt(e) {
529
+ let t = D(I), [n, r] = T(), i = he(n);
530
+ ue(() => {
531
+ let e = n()?.getRootNode();
532
+ Ae(typeof ShadowRoot < "u" && e instanceof ShadowRoot || typeof Document < "u" && e instanceof Document ? e : void 0);
533
+ });
534
+ let a = {
535
+ isEditMode: () => e.isEditMode ?? !1,
536
+ updateConfig: t?.updateConfig ?? (() => {}),
537
+ registerDialogOpener: t?.registerDialogOpener,
538
+ callService: t?.callService,
539
+ dimensions: () => ({
540
+ width: i.width ?? 0,
541
+ height: i.height ?? 0
542
+ })
543
+ }, o = w(() => {
544
+ if (e.variant) return typeof e.variant == "string" ? Me(e.variant) : e.variant;
545
+ }), s = w(() => ({
546
+ "container-type": "size",
547
+ "container-name": "widget",
548
+ "touch-action": e.gestures && !e.isEditMode ? e.gestures.touchAction() : void 0,
549
+ ...o()?.styles?.container,
550
+ ...o()?.styles?.cssVars || {},
551
+ ...e.tone ? { "--widget-color": `var(--tone-${e.tone})` } : {},
552
+ ...e.color ? { "--widget-color": e.color } : {},
553
+ ...e.colorTo ? { "--widget-color-to": e.colorTo } : {},
554
+ ...e.gradient ? { "--widget-gradient": e.gradient } : {}
555
+ })), c = () => !!e.gestures && !e.isEditMode, l = (t) => {
556
+ c() && e.gestures?.onPointerEnter(t);
557
+ }, u = (t) => {
558
+ c() && e.gestures?.onPointerDown(t);
559
+ }, d = (t) => {
560
+ c() && e.gestures?.onPointerMove(t);
561
+ }, f = (t) => {
562
+ c() && e.gestures?.onPointerUp(t);
563
+ }, p = (t) => {
564
+ c() && e.gestures?.onPointerCancel(t);
565
+ };
566
+ return A(I.Provider, {
567
+ value: a,
568
+ get children() {
569
+ var t = rt(), n = t.firstChild;
570
+ return O(t, "pointercancel", p), O(t, "pointerup", f), O(t, "pointermove", d), O(t, "pointerdown", u), O(t, "pointerenter", l), me((t) => {
571
+ r(t), e.gestures?.bindElement(t);
572
+ }, t), M(n, (() => {
573
+ var t = N(() => !!e.emptyState);
574
+ return () => t() ? A(ut, {
575
+ get icon() {
576
+ return e.emptyState.icon;
577
+ },
578
+ get title() {
579
+ return e.emptyState.title;
580
+ },
581
+ get message() {
582
+ return e.emptyState.message;
583
+ }
584
+ }) : e.children;
585
+ })()), M(t, (() => {
586
+ var t = N(() => !!e.loading);
587
+ return () => t() && (() => {
588
+ var e = it();
589
+ return j((t) => P(e, "z-index", R.OVERLAY)), e;
590
+ })();
591
+ })(), null), j((r) => {
592
+ var i = V("glasshome-widget", "relative h-full w-full select-none overflow-hidden rounded-xl border border-border/50", o()?.styles?.class, e.class), a = s(), c = R.CONTENT;
593
+ return i !== r.e && k(t, r.e = i), r.t = pe(t, a, r.t), c !== r.a && P(n, "z-index", r.a = c), r;
594
+ }, {
595
+ e: void 0,
596
+ t: void 0,
597
+ a: void 0
598
+ }), t;
599
+ }
600
+ });
421
601
  }
422
- var Ze = /* @__PURE__ */ x("<p>");
423
- function et(e) {
424
- return (() => {
425
- var t = Ze();
426
- return p(t, (() => {
427
- var i = T(() => !!e.isUnavailable);
428
- return () => i() ? "Unavailable" : e.children;
429
- })()), W((i) => {
430
- var r = R("glasshome-widget-status", "relative", e.dimmed && "opacity-40", e.class), n = J.ACTIONS;
431
- return r !== i.e && I(t, i.e = r), n !== i.t && ee(t, "z-index", i.t = n), i;
432
- }, {
433
- e: void 0,
434
- t: void 0
435
- }), t;
436
- })();
437
- }
438
- var tt = /* @__PURE__ */ x('<span class="glasshome-widget-badge shrink-0">'), nt = /* @__PURE__ */ x("<div><h3 class=glasshome-widget-title>");
439
- function it(e) {
440
- return (() => {
441
- var t = nt(), i = t.firstChild;
442
- return p(i, () => e.children), p(t, k(E, {
443
- get when() {
444
- return T(() => e.badge !== void 0)() && e.badge > 0;
445
- },
446
- get children() {
447
- var r = tt();
448
- return p(r, () => e.badge), r;
449
- }
450
- }), null), W((r) => {
451
- var n = R("relative flex items-center gap-2", e.class), o = J.ACTIONS;
452
- return n !== r.e && I(t, r.e = n), o !== r.t && ee(t, "z-index", r.t = o), r;
453
- }, {
454
- e: void 0,
455
- t: void 0
456
- }), t;
457
- })();
458
- }
459
- function rt(e, t = !1) {
460
- if (e.length === 0)
461
- return {
462
- isGroup: !1,
463
- state: "unknown",
464
- isOn: !1,
465
- isUnavailable: !0,
466
- brightness: 0,
467
- brightnessPercent: 0,
468
- color: "rgb(100, 100, 100)",
469
- onCount: 0,
470
- totalCount: 0,
471
- description: "No entities"
472
- };
473
- const i = e.length > 1;
474
- if (!i) {
475
- const s = e[0], f = s.state === "on", b = s.attributes?.brightness || 0, C = Math.round(b / 255 * 100);
476
- return {
477
- isGroup: !1,
478
- state: s.state,
479
- isOn: f,
480
- isUnavailable: s.state === "unavailable",
481
- brightness: b,
482
- brightnessPercent: C,
483
- color: fe(s),
484
- onCount: f ? 1 : 0,
485
- totalCount: 1,
486
- description: f ? "On" : "Off"
487
- };
488
- }
489
- let r = 0, n = 0, o = 0, u = 0, d = 0, $ = 0;
490
- const m = [];
491
- for (const s of e)
492
- switch (s.state) {
493
- case "on":
494
- r++, s.attributes?.brightness !== void 0 && (d += s.attributes.brightness, $++), s.attributes?.rgb_color && m.push(s.attributes.rgb_color);
495
- break;
496
- case "off":
497
- n++;
498
- break;
499
- case "unknown":
500
- o++;
501
- break;
502
- case "unavailable":
503
- u++;
504
- break;
505
- }
506
- const h = e.length, v = u === h, y = o + u === h, g = r > 0, a = r === h, S = n === h;
507
- let w, M;
508
- t ? v ? (w = "unavailable", M = !1) : o > 0 || u > 0 ? (w = "unknown", M = !1) : n > 0 ? (w = "off", M = !1) : (w = "on", M = !0) : v ? (w = "unavailable", M = !1) : y ? (w = "unknown", M = !1) : g ? (w = "on", M = !0) : (w = "off", M = !1);
509
- const O = $ > 0 ? Math.round(d / $) : 0, L = Math.round(O / 255 * 100);
510
- let F;
511
- if (m.length > 0) {
512
- const s = Math.round(m.reduce((z, D) => z + D[0], 0) / m.length), f = Math.round(m.reduce((z, D) => z + D[1], 0) / m.length), b = Math.round(m.reduce((z, D) => z + D[2], 0) / m.length), C = O / 255;
513
- F = `rgb(${Math.round(s * C)}, ${Math.round(f * C)}, ${Math.round(b * C)})`;
514
- } else
515
- F = fe(e[0]);
516
- let H;
517
- return a ? H = "All on" : S ? H = "All off" : r > 0 ? H = `${r} of ${h} on` : H = "Off", {
518
- isGroup: i,
519
- state: w,
520
- isOn: M,
521
- isUnavailable: w === "unavailable",
522
- brightness: O,
523
- brightnessPercent: L,
524
- color: F,
525
- onCount: r,
526
- totalCount: h,
527
- description: H
528
- };
529
- }
530
- function ot(e, t = "mean", i = !0) {
531
- if (e.length === 0)
532
- return {
533
- isGroup: !1,
534
- state: "unknown",
535
- numericValue: null,
536
- isUnavailable: !0,
537
- description: "No entities"
538
- };
539
- const r = e.length > 1;
540
- if (!r) {
541
- const g = e[0], a = Number.parseFloat(g.state);
542
- let S = g.state;
543
- return Number.isNaN(a) || (S = Number.isInteger(a) ? a.toString() : a.toFixed(1)), {
544
- isGroup: !1,
545
- state: S,
546
- numericValue: Number.isNaN(a) ? null : a,
547
- isUnavailable: g.state === "unavailable",
548
- unit: g.unitOfMeasurement ?? void 0,
549
- description: S
550
- };
551
- }
552
- const n = [], o = [];
553
- let u = 0, d;
554
- for (const g of e) {
555
- if (!d && g.unitOfMeasurement && (d = g.unitOfMeasurement), g.state === "unavailable") {
556
- u++, o.push({
557
- entityId: g.id,
558
- value: "unavailable",
559
- friendly_name: g.friendlyName
560
- });
561
- continue;
562
- }
563
- const a = Number.parseFloat(g.state);
564
- isNaN(a) ? i || o.push({
565
- entityId: g.id,
566
- value: g.state,
567
- friendly_name: g.friendlyName
568
- }) : (n.push(a), o.push({
569
- entityId: g.id,
570
- value: a,
571
- friendly_name: g.friendlyName
572
- }));
573
- }
574
- const $ = u === e.length, m = n.length === 0;
575
- if ($ || m)
576
- return {
577
- isGroup: r,
578
- state: $ ? "unavailable" : "unknown",
579
- numericValue: null,
580
- isUnavailable: $,
581
- unit: d,
582
- description: $ ? "Unavailable" : "No numeric values",
583
- memberValues: o
584
- };
585
- let h, v;
586
- switch (t) {
587
- case "min":
588
- h = Math.min(...n), v = "Minimum";
589
- break;
590
- case "max":
591
- h = Math.max(...n), v = "Maximum";
592
- break;
593
- case "mean":
594
- h = n.reduce((g, a) => g + a, 0) / n.length, v = "Average";
595
- break;
596
- case "median": {
597
- const g = [...n].sort((S, w) => S - w), a = Math.floor(g.length / 2);
598
- h = g.length % 2 === 0 ? (g[a - 1] + g[a]) / 2 : g[a], v = "Median";
599
- break;
600
- }
601
- case "sum":
602
- h = n.reduce((g, a) => g + a, 0), v = "Sum";
603
- break;
604
- case "last":
605
- h = n[n.length - 1], v = "Latest";
606
- break;
607
- case "range":
608
- h = Math.max(...n) - Math.min(...n), v = "Range";
609
- break;
610
- case "product":
611
- h = n.reduce((g, a) => g * a, 1), v = "Product";
612
- break;
613
- case "std_dev": {
614
- const g = n.reduce((S, w) => S + w, 0) / n.length, a = n.reduce((S, w) => S + (w - g) ** 2, 0) / n.length;
615
- h = Math.sqrt(a), v = "Std Dev";
616
- break;
617
- }
618
- default:
619
- h = n.reduce((g, a) => g + a, 0) / n.length, v = "Average";
620
- }
621
- const y = Number.isInteger(h) ? h.toString() : h.toFixed(1);
622
- return {
623
- isGroup: r,
624
- state: y,
625
- numericValue: h,
626
- isUnavailable: !1,
627
- unit: d,
628
- description: `${v} of ${n.length}`,
629
- memberValues: o
630
- };
631
- }
632
- function fe(e) {
633
- if (e.state !== "on") return "rgb(100, 100, 100)";
634
- const i = (e.attributes?.brightness ?? 255) / 255;
635
- if (e.attributes?.rgb_color) {
636
- const [r, n, o] = e.attributes.rgb_color;
637
- return `rgb(${Math.round(r * i)}, ${Math.round(n * i)}, ${Math.round(o * i)})`;
638
- }
639
- if (e.attributes?.color_temp) {
640
- const n = 1e6 / e.attributes.color_temp / 100;
641
- let o, u, d;
642
- return n <= 66 ? (o = 255, u = n <= 19 ? 0 : 99.4708025861 * Math.log(n - 10) - 161.1195681661, d = n <= 19 ? 0 : n <= 66 ? 138.5177312231 * Math.log(n - 10) - 305.0447927307 : 255) : (o = 329.698727446 * (n - 60) ** -0.1332047592, u = 288.1221695283 * (n - 60) ** -0.0755148492, d = 255), o = Math.max(0, Math.min(255, o)) * i, u = Math.max(0, Math.min(255, u)) * i, d = Math.max(0, Math.min(255, d)) * i, `rgb(${Math.round(o)}, ${Math.round(u)}, ${Math.round(d)})`;
643
- }
644
- return `rgb(${Math.round(255 * i)}, ${Math.round(220 * i)}, ${Math.round(180 * i)})`;
645
- }
646
- function at(e) {
647
- if (!e) return !1;
648
- if (["on", "open", "locked", "home", "playing", "active"].includes(e.state))
649
- return !0;
650
- if (e.domain === "sensor") {
651
- const t = Number.parseFloat(e.state);
652
- return !isNaN(t) && t > 0;
653
- }
654
- return !1;
655
- }
656
- function rn(e, t, i) {
657
- return e?.attributes ? e.attributes[t] ?? i : i;
658
- }
659
- function on(e) {
660
- return e.filter(at).length;
661
- }
662
- function st(e, t, i) {
663
- const { decimals: r, scale: n = !0 } = {};
664
- if (typeof e == "string")
665
- return t ? `${e}${t}` : e;
666
- if (e == null || Number.isNaN(e))
667
- return t ? `--${t}` : "--";
668
- let o = e, u = t || "";
669
- n && t && (t === "W" || t === "kW" || t === "MW") && (e >= 1e6 ? (o = e / 1e6, u = "MW") : e >= 1e3 ? (o = e / 1e3, u = "kW") : u = "W"), n && t && (t === "B" || t === "KB" || t === "MB" || t === "GB") && (e >= 1073741824 ? (o = e / 1073741824, u = "GB") : e >= 1048576 ? (o = e / 1048576, u = "MB") : e >= 1024 ? (o = e / 1024, u = "KB") : u = "B");
670
- let d;
671
- return r !== void 0 ? d = o.toFixed(r) : o !== e ? d = o.toFixed(1) : Number.isInteger(e) ? d = e.toString() : d = Number.parseFloat(e.toFixed(2)).toString(), u ? `${d}${u}` : d;
672
- }
673
- function lt(e, t) {
674
- 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;
675
- }
676
- var ct = /* @__PURE__ */ x("<div class=glasshome-widget-subtitle>"), dt = /* @__PURE__ */ x("<div><div class=glasshome-widget-value>");
677
602
  function ut(e) {
678
- return (() => {
679
- var t = dt(), i = t.firstChild;
680
- return p(i, () => st(e.value, e.unit)), p(t, k(E, {
681
- get when() {
682
- return T(() => !!e.interpret)() && typeof e.value == "number";
683
- },
684
- get children() {
685
- var r = ct();
686
- return p(r, () => lt(e.value, e.unit)), r;
687
- }
688
- }), null), W(() => I(t, R("flex flex-col", e.class))), t;
689
- })();
690
- }
691
- var gt = /* @__PURE__ */ x('<div><div class="relative h-full w-full">'), ht = /* @__PURE__ */ x('<div class="glasshome-widget-loading pointer-events-none absolute inset-0 animate-pulse">'), ft = /* @__PURE__ */ x('<div class="flex h-full w-full flex-col items-center justify-center gap-2 text-center">'), mt = /* @__PURE__ */ x('<div class="flex items-center justify-center text-white/30">'), vt = /* @__PURE__ */ x('<h3 class="font-semibold text-sm text-white/60">'), wt = /* @__PURE__ */ x('<p class="text-white/50 text-xs">');
692
- function pt(e) {
693
- const t = B(P), [i, r] = V(), n = Me(i);
694
- Te(() => {
695
- const a = i()?.getRootNode();
696
- Pe(typeof ShadowRoot < "u" && a instanceof ShadowRoot || typeof Document < "u" && a instanceof Document ? a : void 0);
697
- });
698
- const o = {
699
- isEditMode: () => e.isEditMode ?? !1,
700
- updateConfig: t?.updateConfig ?? (() => {
701
- }),
702
- registerDialogOpener: t?.registerDialogOpener,
703
- callService: t?.callService,
704
- dimensions: () => ({
705
- width: n.width ?? 0,
706
- height: n.height ?? 0
707
- })
708
- }, u = j(() => {
709
- if (e.variant)
710
- return typeof e.variant == "string" ? Be(e.variant) : e.variant;
711
- }), d = j(() => ({
712
- "container-type": "size",
713
- "container-name": "widget",
714
- "touch-action": e.gestures && !e.isEditMode ? e.gestures.touchAction() : void 0,
715
- ...u()?.styles?.container,
716
- ...u()?.styles?.cssVars || {},
717
- ...e.tone ? {
718
- "--widget-color": `var(--tone-${e.tone})`
719
- } : {},
720
- ...e.color ? {
721
- "--widget-color": e.color
722
- } : {},
723
- ...e.colorTo ? {
724
- "--widget-color-to": e.colorTo
725
- } : {},
726
- ...e.gradient ? {
727
- "--widget-gradient": e.gradient
728
- } : {}
729
- })), $ = () => !!e.gestures && !e.isEditMode, m = (a) => {
730
- $() && e.gestures?.onPointerEnter(a);
731
- }, h = (a) => {
732
- $() && e.gestures?.onPointerDown(a);
733
- }, v = (a) => {
734
- $() && e.gestures?.onPointerMove(a);
735
- }, y = (a) => {
736
- $() && e.gestures?.onPointerUp(a);
737
- }, g = (a) => {
738
- $() && e.gestures?.onPointerCancel(a);
739
- };
740
- return k(P.Provider, {
741
- value: o,
742
- get children() {
743
- var a = gt(), S = a.firstChild;
744
- return K(a, "pointercancel", g), K(a, "pointerup", y), K(a, "pointermove", v), K(a, "pointerdown", h), K(a, "pointerenter", m), Ce((w) => {
745
- r(w), e.gestures?.bindElement(w);
746
- }, a), p(S, (() => {
747
- var w = T(() => !!e.emptyState);
748
- return () => w() ? k(bt, {
749
- get icon() {
750
- return e.emptyState.icon;
751
- },
752
- get title() {
753
- return e.emptyState.title;
754
- },
755
- get message() {
756
- return e.emptyState.message;
757
- }
758
- }) : e.children;
759
- })()), p(a, (() => {
760
- var w = T(() => !!e.loading);
761
- return () => w() && (() => {
762
- var M = ht();
763
- return W((O) => ee(M, "z-index", J.OVERLAY)), M;
764
- })();
765
- })(), null), W((w) => {
766
- var M = R("glasshome-widget", "relative h-full w-full select-none overflow-hidden rounded-xl border border-border/50", u()?.styles?.class, e.class), O = d(), L = J.CONTENT;
767
- return M !== w.e && I(a, w.e = M), w.t = le(a, O, w.t), L !== w.a && ee(S, "z-index", w.a = L), w;
768
- }, {
769
- e: void 0,
770
- t: void 0,
771
- a: void 0
772
- }), a;
773
- }
774
- });
775
- }
776
- function bt(e) {
777
- return (() => {
778
- var t = ft();
779
- return p(t, (() => {
780
- var i = T(() => !!e.icon);
781
- return () => i() && (() => {
782
- var r = mt();
783
- return p(r, () => e.icon), r;
784
- })();
785
- })(), null), p(t, (() => {
786
- var i = T(() => !!e.title);
787
- return () => i() && (() => {
788
- var r = vt();
789
- return p(r, () => e.title), r;
790
- })();
791
- })(), null), p(t, (() => {
792
- var i = T(() => !!e.message);
793
- return () => i() && (() => {
794
- var r = wt();
795
- return p(r, () => e.message), r;
796
- })();
797
- })(), null), t;
798
- })();
799
- }
800
- const q = pt;
801
- q.Content = Ye;
802
- q.Icon = Qe;
803
- q.Title = it;
804
- q.Status = et;
805
- q.Value = ut;
806
- q.SliderFill = Ge;
807
- var xt = /* @__PURE__ */ x('<span class="inline-flex size-3.5 shrink-0 items-center">'), yt = /* @__PURE__ */ x("<button type=button>"), $t = /* @__PURE__ */ x('<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">'), kt = /* @__PURE__ */ x('<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'), Ct = /* @__PURE__ */ x('<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>'), St = /* @__PURE__ */ x('<div class="rounded-lg bg-muted/30 p-2 text-center md:p-6"><p class="text-muted-foreground text-sm">No additional controls'), Mt = /* @__PURE__ */ x('<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">'), Dt = /* @__PURE__ */ x('<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'), Tt = /* @__PURE__ */ x('<div class="min-w-0 shrink-0">'), _t = /* @__PURE__ */ x('<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">'), Ot = /* @__PURE__ */ x('<div class="min-h-0 flex-1 overflow-y-auto [scrollbar-gutter:stable]">'), zt = /* @__PURE__ */ x('<div class="flex shrink-0 items-center justify-end gap-2 border-border/50 border-t pt-3">');
808
- function Et(e) {
809
- return (() => {
810
- var t = yt();
811
- return t.$$click = () => e.onClick(), p(t, k(E, {
812
- get when() {
813
- return e.isActive;
814
- },
815
- get children() {
816
- var i = xt();
817
- return p(i, () => e.icon), i;
818
- }
819
- }), null), p(t, () => e.label, null), W(() => I(t, R("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;
820
- })();
821
- }
822
- function an(e) {
823
- const [t] = _e(e, ["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"]), i = () => !!t.configSchema && !!t.config && !!t.onConfigSave && !!t.SchemaForm, [r, n] = V({}), [o, u] = V(null);
824
- se(ge(() => t.config, (c) => {
825
- c && n({
826
- ...c
827
- });
828
- })), se(ge(() => t.configSchema, (c) => {
829
- c && u(me(c));
830
- }));
831
- const d = () => i() && JSON.stringify(r()) !== JSON.stringify(t.config), $ = (c) => {
832
- !c && t.config && n({
833
- ...t.config
834
- }), t.onOpenChange(c);
835
- }, m = () => {
836
- t.onConfigSave?.(r());
837
- }, [h, v] = V(t.defaultTab ?? "controls"), y = () => t.activeTab ?? h(), g = (c) => {
838
- t.onActiveTabChange ? t.onActiveTabChange(c) : v(c);
839
- }, a = () => {
840
- const c = t.maxWidth ?? "3xl";
841
- return {
842
- sm: "max-w-sm",
843
- md: "max-w-md",
844
- lg: "max-w-lg",
845
- xl: "max-w-xl",
846
- "2xl": "max-w-2xl",
847
- "3xl": "max-w-3xl",
848
- "4xl": "max-w-4xl"
849
- }[c];
850
- }, S = () => {
851
- if (t.tabs) return t.tabs;
852
- const c = [];
853
- return c.push({
854
- id: "edit",
855
- label: "Edit",
856
- icon: $t(),
857
- content: t.editContent ?? (i() && o() ? k(b, {
858
- get schema() {
859
- return o();
860
- },
861
- get data() {
862
- return r();
863
- },
864
- onChange: n
865
- }) : kt())
866
- }), c.push({
867
- id: "controls",
868
- label: "Controls",
869
- icon: Ct(),
870
- content: t.controlsContent ?? St()
871
- }), c.push({
872
- id: "debug",
873
- label: "Debug",
874
- icon: Mt(),
875
- content: t.debugContent ?? Dt()
876
- }), c;
877
- }, w = async () => {
878
- if (t.debugData !== void 0)
879
- try {
880
- const c = typeof t.debugData == "string" ? t.debugData : JSON.stringify(t.debugData, null, 2);
881
- await navigator.clipboard.writeText(c);
882
- } catch {
883
- }
884
- }, M = () => {
885
- const c = S();
886
- return c.find((N) => N.id === y())?.content ?? c[0]?.content;
887
- }, O = t.ResponsiveDialog, L = t.ResponsiveDialogContent, F = t.ResponsiveDialogHeader, H = t.ResponsiveDialogTitle, s = t.ResponsiveDialogDescription, f = t.Button, b = t.SchemaForm, C = (c) => i() ? $(c) : t.onOpenChange(c), z = () => i() ? d() : t.hasUnsavedChanges, D = () => i() ? m : t.onSave;
888
- return k(O, {
889
- get open() {
890
- return t.open;
891
- },
892
- onOpenChange: (c) => C(c),
893
- get children() {
894
- return k(L, {
895
- get class() {
896
- return R(a(), t.class);
897
- },
898
- get children() {
899
- return [k(F, {
900
- class: "flex flex-row items-center justify-between gap-3",
901
- get children() {
902
- return [(() => {
903
- var c = Tt();
904
- return p(c, k(H, {
905
- class: "truncate leading-tight",
906
- get children() {
907
- return t.title;
908
- }
909
- }), null), p(c, k(s, {
910
- class: "sr-only",
911
- children: "Widget configuration dialog"
912
- }), null), c;
913
- })(), (() => {
914
- var c = _t(), Y = c.firstChild;
915
- return p(Y, () => S().map((N) => k(Et, {
916
- get icon() {
917
- return N.icon;
918
- },
919
- get label() {
920
- return N.label;
921
- },
922
- get isActive() {
923
- return y() === N.id;
924
- },
925
- onClick: () => g(N.id)
926
- }))), p(c, k(E, {
927
- get when() {
928
- return t.headerActions;
929
- },
930
- get children() {
931
- return t.headerActions;
932
- }
933
- }), null), c;
934
- })()];
935
- }
936
- }), (() => {
937
- var c = Ot();
938
- return p(c, M), c;
939
- })(), k(E, {
940
- get when() {
941
- return T(() => y() === "edit")() && (D() || t.onDelete) || y() === "debug" && t.debugData !== void 0;
942
- },
943
- get children() {
944
- var c = zt();
945
- return p(c, k(E, {
946
- get when() {
947
- return T(() => y() === "edit")() && t.onDelete;
948
- },
949
- get children() {
950
- return k(f, {
951
- size: "sm",
952
- variant: "destructive",
953
- onClick: () => t.onDelete?.(),
954
- children: "Delete"
955
- });
956
- }
957
- }), null), p(c, k(E, {
958
- get when() {
959
- return T(() => y() === "edit")() && D();
960
- },
961
- get children() {
962
- return k(f, {
963
- size: "sm",
964
- get disabled() {
965
- return !z();
966
- },
967
- onClick: () => D()?.(),
968
- children: "Save"
969
- });
970
- }
971
- }), null), p(c, k(E, {
972
- get when() {
973
- return T(() => y() === "debug")() && t.debugData !== void 0;
974
- },
975
- get children() {
976
- return k(f, {
977
- size: "sm",
978
- variant: "outline",
979
- onClick: w,
980
- children: "Copy"
981
- });
982
- }
983
- }), null), c;
984
- }
985
- })];
986
- }
987
- });
988
- }
989
- });
990
- }
991
- Se(["click"]);
992
- function sn(e) {
993
- if (typeof IntersectionObserver > "u")
994
- return () => !1;
995
- const [t, i] = V(!1), r = new IntersectionObserver((n) => {
996
- const o = n[0];
997
- o && i(!o.isIntersecting);
998
- });
999
- return se(() => {
1000
- const n = e();
1001
- r.disconnect(), n && r.observe(n);
1002
- }), ce(() => r.disconnect()), t;
1003
- }
1004
- function ln() {
1005
- if (typeof window > "u" || typeof window.matchMedia != "function")
1006
- return () => !1;
1007
- const e = window.matchMedia("(prefers-reduced-motion: reduce)"), [t, i] = V(e.matches), r = (n) => i(n.matches);
1008
- return e.addEventListener("change", r), ce(() => e.removeEventListener("change", r)), t;
1009
- }
1010
- function cn(e = "controls") {
1011
- const [t, i] = V(!1), [r, n] = V(e), o = (d) => {
1012
- n(d ?? e), i(!0);
1013
- }, u = B(P);
1014
- return u?.registerDialogOpener?.(o), ce(() => u?.registerDialogOpener?.(null)), {
1015
- showDialog: t,
1016
- setShowDialog: i,
1017
- openDialog: o,
1018
- closeDialog: () => i(!1),
1019
- activeTab: r,
1020
- setActiveTab: n,
1021
- dialogProps: {
1022
- get open() {
1023
- return t();
1024
- },
1025
- onOpenChange: i,
1026
- get activeTab() {
1027
- return r();
1028
- },
1029
- onActiveTabChange: n
1030
- }
1031
- };
1032
- }
1033
- function dn(e) {
1034
- const t = e.minEntities ?? 1, i = j(() => e.entities().length), r = j(() => i() >= t), n = j(() => !r() || !e.calculateGroupData ? null : e.calculateGroupData(e.entities())), o = j(() => {
1035
- if (!r()) return;
1036
- const d = e.aggregationMode?.();
1037
- if (!d || d === "none") return;
1038
- const $ = e.entities();
1039
- if (d === "light" || d === "binary-sensor" || d === "switch")
1040
- return rt($, e.allEntitiesMode);
1041
- if (d === "sensor") {
1042
- const m = e.sensorGroupType?.() ?? "mean";
1043
- return ot($, m, !0);
1044
- }
1045
- }), u = j(() => r() ? void 0 : e.emptyStateConfig);
1046
- return {
1047
- entities: e.entities,
1048
- groupData: n,
1049
- aggregatedData: o,
1050
- emptyState: u,
1051
- hasEntities: r,
1052
- count: i
1053
- };
1054
- }
1055
- const X = 32, l = X / 2, _ = "white", te = "rgba(0,0,0,0.4)", de = 2, ne = 3;
1056
- function Nt(e) {
1057
- return `url("data:image/svg+xml,${encodeURIComponent(e)}")`;
1058
- }
1059
- function ie(e) {
1060
- return `<svg xmlns="http://www.w3.org/2000/svg" width="${X}" height="${X}" viewBox="0 0 ${X} ${X}">${e}</svg>`;
1061
- }
1062
- const At = ie(`
603
+ return (() => {
604
+ var t = at();
605
+ return M(t, (() => {
606
+ var t = N(() => !!e.icon);
607
+ return () => t() && (() => {
608
+ var t = ot();
609
+ return M(t, () => e.icon), t;
610
+ })();
611
+ })(), null), M(t, (() => {
612
+ var t = N(() => !!e.title);
613
+ return () => t() && (() => {
614
+ var t = st();
615
+ return M(t, () => e.title), t;
616
+ })();
617
+ })(), null), M(t, (() => {
618
+ var t = N(() => !!e.message);
619
+ return () => t() && (() => {
620
+ var t = ct();
621
+ return M(t, () => e.message), t;
622
+ })();
623
+ })(), null), t;
624
+ })();
625
+ }
626
+ var H = lt;
627
+ H.Content = Ie, H.Icon = Be, H.Title = Ge, H.Status = He, H.Value = nt, H.SliderFill = Pe;
628
+ //#endregion
629
+ //#region src/framework/dialogs/WidgetDialog.tsx
630
+ var dt = /*#__PURE__*/ F("<span class=\"inline-flex size-3.5 shrink-0 items-center\">"), ft = /*#__PURE__*/ F("<button type=button>"), pt = /*#__PURE__*/ F("<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\">"), mt = /*#__PURE__*/ F("<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"), ht = /*#__PURE__*/ F("<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__*/ F("<div class=\"rounded-lg bg-muted/30 p-2 text-center md:p-6\"><p class=\"text-muted-foreground text-sm\">No additional controls"), _t = /*#__PURE__*/ F("<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\">"), vt = /*#__PURE__*/ F("<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__*/ F("<div class=\"min-w-0 shrink-0\">"), bt = /*#__PURE__*/ F("<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__*/ F("<div class=\"min-h-0 flex-1 overflow-y-auto [scrollbar-gutter:stable]\">"), St = /*#__PURE__*/ F("<div class=\"flex shrink-0 items-center justify-end gap-2 border-border/50 border-t pt-3\">");
631
+ function Ct(e) {
632
+ return (() => {
633
+ var t = ft();
634
+ return t.$$click = () => e.onClick(), M(t, A(C, {
635
+ get when() {
636
+ return e.isActive;
637
+ },
638
+ get children() {
639
+ var t = dt();
640
+ return M(t, () => e.icon), t;
641
+ }
642
+ }), null), M(t, () => e.label, null), j(() => k(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;
643
+ })();
644
+ }
645
+ function wt(e) {
646
+ let [t] = de(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] = T({}), [a, o] = T(null);
647
+ ce(le(() => t.config, (e) => {
648
+ e && i({ ...e });
649
+ })), ce(le(() => t.configSchema, (e) => {
650
+ e && o(ve(e));
651
+ }));
652
+ let s = () => n() && JSON.stringify(r()) !== JSON.stringify(t.config), c = (e) => {
653
+ !e && t.config && i({ ...t.config }), t.onOpenChange(e);
654
+ }, l = () => {
655
+ t.onConfigSave?.(r());
656
+ }, [u, d] = T(t.defaultTab ?? "controls"), f = () => t.activeTab ?? u(), p = (e) => {
657
+ t.onActiveTabChange ? t.onActiveTabChange(e) : d(e);
658
+ }, m = () => ({
659
+ sm: "max-w-sm",
660
+ md: "max-w-md",
661
+ lg: "max-w-lg",
662
+ xl: "max-w-xl",
663
+ "2xl": "max-w-2xl",
664
+ "3xl": "max-w-3xl",
665
+ "4xl": "max-w-4xl"
666
+ })[t.maxWidth ?? "3xl"], h = () => {
667
+ if (t.tabs) return t.tabs;
668
+ let e = [];
669
+ return e.push({
670
+ id: "edit",
671
+ label: "Edit",
672
+ icon: pt(),
673
+ content: t.editContent ?? (n() && a() ? A(ne, {
674
+ get schema() {
675
+ return a();
676
+ },
677
+ get data() {
678
+ return r();
679
+ },
680
+ onChange: i
681
+ }) : mt())
682
+ }), e.push({
683
+ id: "controls",
684
+ label: "Controls",
685
+ icon: ht(),
686
+ content: t.controlsContent ?? gt()
687
+ }), e.push({
688
+ id: "debug",
689
+ label: "Debug",
690
+ icon: _t(),
691
+ content: t.debugContent ?? vt()
692
+ }), e;
693
+ }, g = async () => {
694
+ if (t.debugData !== void 0) try {
695
+ let e = typeof t.debugData == "string" ? t.debugData : JSON.stringify(t.debugData, null, 2);
696
+ await navigator.clipboard.writeText(e);
697
+ } catch {}
698
+ }, _ = () => {
699
+ let e = h();
700
+ return e.find((e) => e.id === f())?.content ?? e[0]?.content;
701
+ }, v = t.ResponsiveDialog, ee = t.ResponsiveDialogContent, y = t.ResponsiveDialogHeader, b = t.ResponsiveDialogTitle, te = t.ResponsiveDialogDescription, x = t.Button, ne = t.SchemaForm, re = (e) => n() ? c(e) : t.onOpenChange(e), ie = () => n() ? s() : t.hasUnsavedChanges, S = () => n() ? l : t.onSave;
702
+ return A(v, {
703
+ get open() {
704
+ return t.open;
705
+ },
706
+ onOpenChange: (e) => re(e),
707
+ get children() {
708
+ return A(ee, {
709
+ get class() {
710
+ return V(m(), t.class);
711
+ },
712
+ get children() {
713
+ return [
714
+ A(y, {
715
+ class: "flex flex-row items-center justify-between gap-3",
716
+ get children() {
717
+ return [(() => {
718
+ var e = yt();
719
+ return M(e, A(b, {
720
+ class: "truncate leading-tight",
721
+ get children() {
722
+ return t.title;
723
+ }
724
+ }), null), M(e, A(te, {
725
+ class: "sr-only",
726
+ children: "Widget configuration dialog"
727
+ }), null), e;
728
+ })(), (() => {
729
+ var e = bt(), n = e.firstChild;
730
+ return M(n, () => h().map((e) => A(Ct, {
731
+ get icon() {
732
+ return e.icon;
733
+ },
734
+ get label() {
735
+ return e.label;
736
+ },
737
+ get isActive() {
738
+ return f() === e.id;
739
+ },
740
+ onClick: () => p(e.id)
741
+ }))), M(e, A(C, {
742
+ get when() {
743
+ return t.headerActions;
744
+ },
745
+ get children() {
746
+ return t.headerActions;
747
+ }
748
+ }), null), e;
749
+ })()];
750
+ }
751
+ }),
752
+ (() => {
753
+ var e = xt();
754
+ return M(e, _), e;
755
+ })(),
756
+ A(C, {
757
+ get when() {
758
+ return N(() => f() === "edit")() && (S() || t.onDelete) || f() === "debug" && t.debugData !== void 0;
759
+ },
760
+ get children() {
761
+ var e = St();
762
+ return M(e, A(C, {
763
+ get when() {
764
+ return N(() => f() === "edit")() && t.onDelete;
765
+ },
766
+ get children() {
767
+ return A(x, {
768
+ size: "sm",
769
+ variant: "destructive",
770
+ onClick: () => t.onDelete?.(),
771
+ children: "Delete"
772
+ });
773
+ }
774
+ }), null), M(e, A(C, {
775
+ get when() {
776
+ return N(() => f() === "edit")() && S();
777
+ },
778
+ get children() {
779
+ return A(x, {
780
+ size: "sm",
781
+ get disabled() {
782
+ return !ie();
783
+ },
784
+ onClick: () => S()?.(),
785
+ children: "Save"
786
+ });
787
+ }
788
+ }), null), M(e, A(C, {
789
+ get when() {
790
+ return N(() => f() === "debug")() && t.debugData !== void 0;
791
+ },
792
+ get children() {
793
+ return A(x, {
794
+ size: "sm",
795
+ variant: "outline",
796
+ onClick: g,
797
+ children: "Copy"
798
+ });
799
+ }
800
+ }), null), e;
801
+ }
802
+ })
803
+ ];
804
+ }
805
+ });
806
+ }
807
+ });
808
+ }
809
+ fe(["click"]);
810
+ //#endregion
811
+ //#region src/framework/hooks/use-intersection-pause.ts
812
+ function Tt(e) {
813
+ if (typeof IntersectionObserver > "u") return () => !1;
814
+ let [t, n] = T(!1), r = new IntersectionObserver((e) => {
815
+ let t = e[0];
816
+ t && n(!t.isIntersecting);
817
+ });
818
+ return ce(() => {
819
+ let t = e();
820
+ r.disconnect(), t && r.observe(t);
821
+ }), E(() => r.disconnect()), t;
822
+ }
823
+ //#endregion
824
+ //#region src/framework/hooks/use-reduced-motion.ts
825
+ function Et() {
826
+ if (typeof window > "u" || typeof window.matchMedia != "function") return () => !1;
827
+ let e = window.matchMedia("(prefers-reduced-motion: reduce)"), [t, n] = T(e.matches), r = (e) => n(e.matches);
828
+ return e.addEventListener("change", r), E(() => e.removeEventListener("change", r)), t;
829
+ }
830
+ //#endregion
831
+ //#region src/framework/hooks/use-widget-dialog.ts
832
+ function Dt(e = "controls") {
833
+ let [t, n] = T(!1), [r, i] = T(e), a = (t) => {
834
+ i(t ?? e), n(!0);
835
+ }, o = D(I);
836
+ return o?.registerDialogOpener?.(a), E(() => o?.registerDialogOpener?.(null)), {
837
+ showDialog: t,
838
+ setShowDialog: n,
839
+ openDialog: a,
840
+ closeDialog: () => n(!1),
841
+ activeTab: r,
842
+ setActiveTab: i,
843
+ dialogProps: {
844
+ get open() {
845
+ return t();
846
+ },
847
+ onOpenChange: n,
848
+ get activeTab() {
849
+ return r();
850
+ },
851
+ onActiveTabChange: i
852
+ }
853
+ };
854
+ }
855
+ //#endregion
856
+ //#region src/framework/hooks/use-widget-entity-group.ts
857
+ function Ot(e) {
858
+ let t = e.minEntities ?? 1, n = w(() => e.entities().length), r = w(() => n() >= t), i = w(() => !r() || !e.calculateGroupData ? null : e.calculateGroupData(e.entities())), a = w(() => {
859
+ if (!r()) return;
860
+ let t = e.aggregationMode?.();
861
+ if (!t || t === "none") return;
862
+ let n = e.entities();
863
+ if (t === "light" || t === "binary-sensor" || t === "switch") return Ke(n, e.allEntitiesMode);
864
+ if (t === "sensor") return qe(n, e.sensorGroupType?.() ?? "mean", !0);
865
+ }), o = w(() => r() ? void 0 : e.emptyStateConfig);
866
+ return {
867
+ entities: e.entities,
868
+ groupData: i,
869
+ aggregatedData: a,
870
+ emptyState: o,
871
+ hasEntities: r,
872
+ count: n
873
+ };
874
+ }
875
+ //#endregion
876
+ //#region src/framework/gestures/cursors.ts
877
+ var U = 32, W = U / 2, G = "white", K = "rgba(0,0,0,0.4)", q = 2, J = 3;
878
+ function kt(e) {
879
+ return `url("data:image/svg+xml,${encodeURIComponent(e)}")`;
880
+ }
881
+ function Y(e) {
882
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="${U}" height="${U}" viewBox="0 0 ${U} ${U}">${e}</svg>`;
883
+ }
884
+ var At = Y(`
1063
885
  <g transform="translate(6, 2)">
1064
886
  <!-- shadow -->
1065
- <g stroke="${te}" stroke-width="${ne}" fill="none" stroke-linecap="round" stroke-linejoin="round">
887
+ <g stroke="${K}" stroke-width="${J}" fill="none" stroke-linecap="round" stroke-linejoin="round">
1066
888
  <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"/>
1067
889
  </g>
1068
890
  <!-- main -->
1069
- <g stroke="${_}" stroke-width="${de}" fill="none" stroke-linecap="round" stroke-linejoin="round">
891
+ <g stroke="${G}" stroke-width="${q}" fill="none" stroke-linecap="round" stroke-linejoin="round">
1070
892
  <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"/>
1071
893
  </g>
1072
894
  </g>
1073
- `), Vt = ie(`
895
+ `), jt = Y(`
1074
896
  <g>
1075
- <circle cx="${l}" cy="${l}" r="8" stroke="${te}" stroke-width="${ne}" fill="none"/>
1076
- <circle cx="${l}" cy="${l}" r="8" stroke="${_}" stroke-width="1.5" fill="none"/>
1077
- <circle cx="${l}" cy="${l}" r="1.5" fill="${_}"/>
897
+ <circle cx="${W}" cy="${W}" r="8" stroke="${K}" stroke-width="${J}" fill="none"/>
898
+ <circle cx="${W}" cy="${W}" r="8" stroke="${G}" stroke-width="1.5" fill="none"/>
899
+ <circle cx="${W}" cy="${W}" r="1.5" fill="${G}"/>
1078
900
  </g>
1079
- `), Wt = ie(`
901
+ `), Mt = Y(`
1080
902
  <g>
1081
903
  <!-- shadow -->
1082
- <g stroke="${te}" stroke-width="${ne}" fill="none" stroke-linecap="round" stroke-linejoin="round">
1083
- <line x1="6" y1="${l}" x2="26" y2="${l}"/>
1084
- <polyline points="10,${l - 4} 6,${l} 10,${l + 4}"/>
1085
- <polyline points="22,${l - 4} 26,${l} 22,${l + 4}"/>
904
+ <g stroke="${K}" stroke-width="${J}" fill="none" stroke-linecap="round" stroke-linejoin="round">
905
+ <line x1="6" y1="${W}" x2="26" y2="${W}"/>
906
+ <polyline points="10,${W - 4} 6,${W} 10,20"/>
907
+ <polyline points="22,${W - 4} 26,${W} 22,20"/>
1086
908
  </g>
1087
909
  <!-- main -->
1088
- <g stroke="${_}" stroke-width="${de}" fill="none" stroke-linecap="round" stroke-linejoin="round">
1089
- <line x1="6" y1="${l}" x2="26" y2="${l}"/>
1090
- <polyline points="10,${l - 4} 6,${l} 10,${l + 4}"/>
1091
- <polyline points="22,${l - 4} 26,${l} 22,${l + 4}"/>
910
+ <g stroke="${G}" stroke-width="${q}" fill="none" stroke-linecap="round" stroke-linejoin="round">
911
+ <line x1="6" y1="${W}" x2="26" y2="${W}"/>
912
+ <polyline points="10,${W - 4} 6,${W} 10,20"/>
913
+ <polyline points="22,${W - 4} 26,${W} 22,20"/>
1092
914
  </g>
1093
915
  <!-- center grip dots -->
1094
- <circle cx="${l}" cy="${l}" r="1.5" fill="${_}"/>
1095
- <circle cx="${l - 5}" cy="${l}" r="1" fill="${_}" opacity="0.6"/>
1096
- <circle cx="${l + 5}" cy="${l}" r="1" fill="${_}" opacity="0.6"/>
916
+ <circle cx="${W}" cy="${W}" r="1.5" fill="${G}"/>
917
+ <circle cx="${W - 5}" cy="${W}" r="1" fill="${G}" opacity="0.6"/>
918
+ <circle cx="21" cy="${W}" r="1" fill="${G}" opacity="0.6"/>
1097
919
  </g>
1098
- `), Rt = ie(`
920
+ `), Nt = Y(`
1099
921
  <g>
1100
922
  <!-- shadow -->
1101
- <g stroke="${te}" stroke-width="${ne}" fill="none" stroke-linecap="round" stroke-linejoin="round">
1102
- <line x1="${l}" y1="6" x2="${l}" y2="26"/>
1103
- <polyline points="${l - 4},10 ${l},6 ${l + 4},10"/>
1104
- <polyline points="${l - 4},22 ${l},26 ${l + 4},22"/>
923
+ <g stroke="${K}" stroke-width="${J}" fill="none" stroke-linecap="round" stroke-linejoin="round">
924
+ <line x1="${W}" y1="6" x2="${W}" y2="26"/>
925
+ <polyline points="${W - 4},10 ${W},6 20,10"/>
926
+ <polyline points="${W - 4},22 ${W},26 20,22"/>
1105
927
  </g>
1106
928
  <!-- main -->
1107
- <g stroke="${_}" stroke-width="${de}" fill="none" stroke-linecap="round" stroke-linejoin="round">
1108
- <line x1="${l}" y1="6" x2="${l}" y2="26"/>
1109
- <polyline points="${l - 4},10 ${l},6 ${l + 4},10"/>
1110
- <polyline points="${l - 4},22 ${l},26 ${l + 4},22"/>
929
+ <g stroke="${G}" stroke-width="${q}" fill="none" stroke-linecap="round" stroke-linejoin="round">
930
+ <line x1="${W}" y1="6" x2="${W}" y2="26"/>
931
+ <polyline points="${W - 4},10 ${W},6 20,10"/>
932
+ <polyline points="${W - 4},22 ${W},26 20,22"/>
1111
933
  </g>
1112
934
  <!-- center grip dots -->
1113
- <circle cx="${l}" cy="${l}" r="1.5" fill="${_}"/>
1114
- <circle cx="${l}" cy="${l - 5}" r="1" fill="${_}" opacity="0.6"/>
1115
- <circle cx="${l}" cy="${l + 5}" r="1" fill="${_}" opacity="0.6"/>
935
+ <circle cx="${W}" cy="${W}" r="1.5" fill="${G}"/>
936
+ <circle cx="${W}" cy="${W - 5}" r="1" fill="${G}" opacity="0.6"/>
937
+ <circle cx="${W}" cy="21" r="1" fill="${G}" opacity="0.6"/>
938
+ </g>
939
+ `), Pt = Y(`
940
+ <g>
941
+ <!-- shadow -->
942
+ <g stroke="${K}" stroke-width="${J}" fill="none" stroke-linecap="round" stroke-linejoin="round">
943
+ <line x1="7" y1="${W}" x2="25" y2="${W}"/>
944
+ <line x1="${W}" y1="7" x2="${W}" y2="25"/>
945
+ <polyline points="11,${W - 3} 7,${W} 11,19"/>
946
+ <polyline points="21,${W - 3} 25,${W} 21,19"/>
947
+ <polyline points="${W - 3},11 ${W},7 19,11"/>
948
+ <polyline points="${W - 3},21 ${W},25 19,21"/>
949
+ </g>
950
+ <!-- main -->
951
+ <g stroke="${G}" stroke-width="${q}" fill="none" stroke-linecap="round" stroke-linejoin="round">
952
+ <line x1="7" y1="${W}" x2="25" y2="${W}"/>
953
+ <line x1="${W}" y1="7" x2="${W}" y2="25"/>
954
+ <polyline points="11,${W - 3} 7,${W} 11,19"/>
955
+ <polyline points="21,${W - 3} 25,${W} 21,19"/>
956
+ <polyline points="${W - 3},11 ${W},7 19,11"/>
957
+ <polyline points="${W - 3},21 ${W},25 19,21"/>
958
+ </g>
959
+ <!-- center dot -->
960
+ <circle cx="${W}" cy="${W}" r="2" fill="${G}"/>
1116
961
  </g>
1117
962
  `);
1118
- function Z(e, t, i) {
1119
- return { css: `${Nt(e)} ${t} ${i}, auto`, hotspotX: t, hotspotY: i };
1120
- }
1121
- const U = {
1122
- tap: Z(At, 12, 4),
1123
- hold: Z(Vt, 16, 16),
1124
- slideHorizontal: Z(Wt, l, l),
1125
- slideVertical: Z(Rt, l, l)
1126
- };
1127
- function oe() {
1128
- if (typeof window > "u") return null;
1129
- const e = window;
1130
- return e.Capacitor?.isNativePlatform?.() ? e.Capacitor.Plugins?.Haptics ?? null : null;
1131
- }
1132
- function ae(e) {
1133
- if (!(typeof navigator > "u" || typeof navigator.vibrate != "function"))
1134
- try {
1135
- navigator.vibrate(e);
1136
- } catch {
1137
- }
1138
- }
1139
- const Ht = {
1140
- /** Light confirmation — fires when slide gesture arms after user holds still. */
1141
- tick() {
1142
- const e = oe();
1143
- if (e) {
1144
- e.impact({ style: "Light" }).catch(() => {
1145
- });
1146
- return;
1147
- }
1148
- ae(8);
1149
- },
1150
- /** Medium bump — fires when hold gesture commits (detail opening). */
1151
- bump() {
1152
- const e = oe();
1153
- if (e) {
1154
- e.impact({ style: "Medium" }).catch(() => {
1155
- });
1156
- return;
1157
- }
1158
- ae(20);
1159
- },
1160
- /** Stronger pulse — reserved for edit-mode pickup (future use). */
1161
- pulse() {
1162
- const e = oe();
1163
- if (e) {
1164
- e.impact({ style: "Heavy" }).catch(() => {
1165
- });
1166
- return;
1167
- }
1168
- ae([0, 15, 40, 15]);
1169
- }
963
+ function X(e, t, n) {
964
+ return {
965
+ css: `${kt(e)} ${t} ${n}, auto`,
966
+ hotspotX: t,
967
+ hotspotY: n
968
+ };
969
+ }
970
+ var Z = {
971
+ tap: X(At, 12, 4),
972
+ hold: X(jt, 16, 16),
973
+ slideHorizontal: X(Mt, W, W),
974
+ slideVertical: X(Nt, W, W),
975
+ slideAuto: X(Pt, W, W)
1170
976
  };
1171
- function un(e, t) {
1172
- const n = {
1173
- isDown: !1,
1174
- isTouch: !1,
1175
- startX: 0,
1176
- startY: 0,
1177
- startTime: 0,
1178
- hasMoved: !1,
1179
- sliding: !1,
1180
- holdTimer: null,
1181
- element: null
1182
- };
1183
- let o = null, u = null, d = null;
1184
- const [$, m] = V(null);
1185
- function h(s) {
1186
- s !== u && (d && d.disconnect(), d = new ResizeObserver((f) => {
1187
- const b = f[0];
1188
- if (b) {
1189
- const C = b.borderBoxSize?.[0];
1190
- C ? o = { width: C.inlineSize, height: C.blockSize } : o = { width: b.contentRect.width, height: b.contentRect.height }, m(o.height > o.width);
1191
- }
1192
- }), u = s, d.observe(s), o = { width: s.clientWidth, height: s.clientHeight }, m(o.height > o.width));
1193
- }
1194
- const v = () => {
1195
- n.holdTimer && (clearTimeout(n.holdTimer), n.holdTimer = null);
1196
- }, y = () => {
1197
- n.isDown = !1, n.hasMoved = !1, n.sliding = !1;
1198
- }, g = (s) => {
1199
- const b = e().slide;
1200
- return b?.orientation === "horizontal" ? "horizontal" : b?.orientation === "vertical" ? "vertical" : s && (o || h(s), o) ? o.height > o.width ? "vertical" : "horizontal" : (t?.() ?? "horizontal") === "horizontal" ? "horizontal" : "vertical";
1201
- }, a = (s) => {
1202
- const f = e();
1203
- if (!(!f.tap && !f.hold && !f.slide)) {
1204
- if (n.isDown = !0, n.isTouch = s.pointerType === "touch", n.element = s.currentTarget, h(n.element), n.startX = s.clientX, n.startY = s.clientY, n.startTime = Date.now(), n.hasMoved = !1, n.sliding = !1, f.hold) {
1205
- const b = f.hold.delay ?? 300;
1206
- n.holdTimer = setTimeout(() => {
1207
- n.holdTimer = null, !(!n.isDown || n.hasMoved) && (Ht.bump(), f.hold?.action(), n.isDown = !1);
1208
- }, b);
1209
- }
1210
- if (!n.isTouch && f.slide)
1211
- try {
1212
- s.currentTarget.setPointerCapture(s.pointerId);
1213
- } catch {
1214
- }
1215
- }
1216
- }, S = (s) => {
1217
- if (!n.isDown) return;
1218
- const f = e(), b = s.clientX - n.startX, C = s.clientY - n.startY;
1219
- if (Math.sqrt(b * b + C * C) > 10 && (v(), n.hasMoved = !0), f.slide && n.hasMoved) {
1220
- const D = s.currentTarget, c = g(D);
1221
- if (n.isTouch && !n.sliding) {
1222
- const $e = Math.abs(c === "vertical" ? C : b), ke = Math.abs(c === "vertical" ? b : C);
1223
- if ($e < ke) return;
1224
- }
1225
- n.sliding = !0;
1226
- const Y = f.slide.min ?? 0, N = f.slide.max ?? 100, we = N - Y, pe = c === "vertical" ? -C : b, ue = o ?? { width: D.clientWidth, height: D.clientHeight }, be = c === "vertical" ? ue.height : ue.width, xe = pe / be * we, ye = Math.max(Y, Math.min(N, f.slide.value + xe));
1227
- f.slide.onChange(Math.round(ye)), n.startX = s.clientX, n.startY = s.clientY, s.preventDefault();
1228
- }
1229
- }, w = (s) => {
1230
- const f = e(), b = n.isDown, C = Date.now() - n.startTime, z = f.hold?.delay ?? 300;
1231
- v(), b && f.tap && !n.hasMoved && C < z && f.tap();
1232
- try {
1233
- s.currentTarget.releasePointerCapture(s.pointerId);
1234
- } catch {
1235
- }
1236
- y();
1237
- }, M = (s) => {
1238
- v();
1239
- try {
1240
- s.currentTarget.releasePointerCapture(s.pointerId);
1241
- } catch {
1242
- }
1243
- y();
1244
- }, O = (s) => {
1245
- const f = e();
1246
- if (f.slide) {
1247
- const b = f.slide.orientation;
1248
- return b === "horizontal" ? U.slideHorizontal.css : b === "vertical" ? U.slideVertical.css : (o || h(s), o && o.height > o.width ? U.slideVertical.css : U.slideHorizontal.css);
1249
- }
1250
- return f.tap ? U.tap.css : f.hold ? U.hold.css : "";
1251
- };
1252
- return {
1253
- onPointerDown: a,
1254
- onPointerMove: S,
1255
- onPointerUp: w,
1256
- onPointerCancel: M,
1257
- onPointerEnter: (s) => {
1258
- const f = s.currentTarget;
1259
- n.element = f, f.style.cursor = O(f);
1260
- },
1261
- bindElement: (s) => {
1262
- s && (n.element = s, h(s));
1263
- },
1264
- touchAction: () => {
1265
- const s = e();
1266
- if (s.slide) {
1267
- const f = s.slide.orientation;
1268
- return f === "vertical" || f !== "horizontal" && ($() ?? (t?.() ?? "horizontal") !== "horizontal") ? "pan-x" : "pan-y";
1269
- }
1270
- return s.tap || s.hold ? "manipulation" : "auto";
1271
- },
1272
- dispose: () => {
1273
- v(), d && (d.disconnect(), d = null), u = null, o = null;
1274
- }
1275
- };
1276
- }
1277
- const Pt = {
1278
- solar: "oklch(0.74 0.18 60)",
1279
- grid: "oklch(0.62 0.12 245)",
1280
- battery: "oklch(0.70 0.18 145)",
1281
- ev: "oklch(0.70 0.14 190)",
1282
- home: "oklch(0.68 0.06 250)",
1283
- positive: "oklch(0.70 0.14 160)",
1284
- // Fault red-orange; used only for faults, never normal consumption.
1285
- negative: "oklch(0.64 0.22 27)"
977
+ //#endregion
978
+ //#region src/framework/gestures/haptics.ts
979
+ function Q() {
980
+ if (typeof window > "u") return null;
981
+ let e = window;
982
+ return e.Capacitor?.isNativePlatform?.() ? e.Capacitor.Plugins?.Haptics ?? null : null;
983
+ }
984
+ function $(e) {
985
+ if (!(typeof navigator > "u" || typeof navigator.vibrate != "function")) try {
986
+ navigator.vibrate(e);
987
+ } catch {}
988
+ }
989
+ var Ft = {
990
+ tick() {
991
+ let e = Q();
992
+ if (e) {
993
+ e.impact({ style: "Light" }).catch(() => {});
994
+ return;
995
+ }
996
+ $(8);
997
+ },
998
+ bump() {
999
+ let e = Q();
1000
+ if (e) {
1001
+ e.impact({ style: "Medium" }).catch(() => {});
1002
+ return;
1003
+ }
1004
+ $(20);
1005
+ },
1006
+ pulse() {
1007
+ let e = Q();
1008
+ if (e) {
1009
+ e.impact({ style: "Heavy" }).catch(() => {});
1010
+ return;
1011
+ }
1012
+ $([
1013
+ 0,
1014
+ 15,
1015
+ 40,
1016
+ 15
1017
+ ]);
1018
+ }
1286
1019
  };
1287
- function It(e) {
1288
- return {
1289
- fill: `color-mix(in oklch, ${e} 20%, transparent)`,
1290
- stroke: e,
1291
- solid: e
1292
- };
1293
- }
1294
- const gn = Object.fromEntries(
1295
- Object.entries(Pt).map(([e, t]) => [e, It(t)])
1296
- ), hn = A.enum([
1297
- "success",
1298
- "warning",
1299
- "danger",
1300
- "info",
1301
- "neutral",
1302
- "accent"
1303
- ]), fn = {
1304
- /** Optional display name override (renders as text input) */
1305
- title: () => A.string().optional().meta({ title: "Title", description: "Optional display name override" }),
1306
- /** Multi-select entity picker for a HA domain */
1307
- entityIds: (e, t) => A.array(A.string()).default([]).meta({
1308
- domain: e,
1309
- title: "Entities",
1310
- ...t?.deviceClass ? { deviceClass: t.deviceClass } : {}
1311
- }),
1312
- /** Single-select entity picker for a HA domain */
1313
- singleEntity: (e, t) => A.array(A.string()).default([]).meta({
1314
- domain: e,
1315
- title: "Entity",
1316
- singleSelect: !0,
1317
- ...t?.deviceClass ? { deviceClass: t.deviceClass } : {}
1318
- }),
1319
- /** Area picker dropdown */
1320
- areaId: () => A.string().optional().meta({ formType: "area-picker", title: "Area" })
1020
+ //#endregion
1021
+ //#region src/framework/gestures/use-widget-gestures.ts
1022
+ function It(e, t) {
1023
+ let n = {
1024
+ isDown: !1,
1025
+ isTouch: !1,
1026
+ startX: 0,
1027
+ startY: 0,
1028
+ startTime: 0,
1029
+ hasMoved: !1,
1030
+ sliding: !1,
1031
+ holdTimer: null,
1032
+ element: null
1033
+ }, r = null, i = null, a = null, [o, s] = T(null);
1034
+ function c(e) {
1035
+ e !== i && (a && a.disconnect(), a = new ResizeObserver((e) => {
1036
+ let t = e[0];
1037
+ if (t) {
1038
+ let e = t.borderBoxSize?.[0];
1039
+ r = e ? {
1040
+ width: e.inlineSize,
1041
+ height: e.blockSize
1042
+ } : {
1043
+ width: t.contentRect.width,
1044
+ height: t.contentRect.height
1045
+ }, s(r.height > r.width);
1046
+ }
1047
+ }), i = e, a.observe(e), r = {
1048
+ width: e.clientWidth,
1049
+ height: e.clientHeight
1050
+ }, s(r.height > r.width));
1051
+ }
1052
+ let l = () => {
1053
+ n.holdTimer &&= (clearTimeout(n.holdTimer), null);
1054
+ }, u = () => {
1055
+ n.isDown = !1, n.hasMoved = !1, n.sliding = !1;
1056
+ }, d = (n) => {
1057
+ let i = e().slide;
1058
+ return i?.orientation === "horizontal" ? "horizontal" : i?.orientation === "vertical" ? "vertical" : n && (r || c(n), r) ? r.height > r.width ? "vertical" : "horizontal" : (t?.() ?? "horizontal") === "horizontal" ? "horizontal" : "vertical";
1059
+ }, f = (t) => {
1060
+ let r = e();
1061
+ if (!(!r.tap && !r.hold && !r.slide)) {
1062
+ 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) {
1063
+ let e = r.hold.delay ?? 300;
1064
+ n.holdTimer = setTimeout(() => {
1065
+ n.holdTimer = null, !(!n.isDown || n.hasMoved) && (Ft.bump(), r.hold?.action(), n.isDown = !1);
1066
+ }, e);
1067
+ }
1068
+ if (!n.isTouch && r.slide) try {
1069
+ t.currentTarget.setPointerCapture(t.pointerId);
1070
+ } catch {}
1071
+ }
1072
+ }, p = (t) => {
1073
+ if (!n.isDown) return;
1074
+ let i = e(), a = t.clientX - n.startX, o = t.clientY - n.startY;
1075
+ if (Math.sqrt(a * a + o * o) > 10 && (l(), n.hasMoved = !0), i.slide && n.hasMoved) {
1076
+ let e = t.currentTarget, s = d(e);
1077
+ if (n.isTouch && !n.sliding && Math.abs(s === "vertical" ? o : a) < Math.abs(s === "vertical" ? a : o)) return;
1078
+ n.sliding = !0;
1079
+ let c = i.slide.min ?? 0, l = i.slide.max ?? 100, u = l - c, f = s === "vertical" ? -o : a, p = r ?? {
1080
+ width: e.clientWidth,
1081
+ height: e.clientHeight
1082
+ }, m = f / (s === "vertical" ? p.height : p.width) * u, h = Math.max(c, Math.min(l, i.slide.value + m));
1083
+ i.slide.onChange(Math.round(h)), n.startX = t.clientX, n.startY = t.clientY, t.preventDefault();
1084
+ }
1085
+ }, m = (t) => {
1086
+ let r = e(), i = n.isDown, a = Date.now() - n.startTime, o = r.hold?.delay ?? 300;
1087
+ l(), i && r.tap && !n.hasMoved && a < o && r.tap();
1088
+ try {
1089
+ t.currentTarget.releasePointerCapture(t.pointerId);
1090
+ } catch {}
1091
+ u();
1092
+ }, h = (e) => {
1093
+ l();
1094
+ try {
1095
+ e.currentTarget.releasePointerCapture(e.pointerId);
1096
+ } catch {}
1097
+ u();
1098
+ }, g = (t) => {
1099
+ let n = e();
1100
+ if (n.slide) {
1101
+ let e = n.slide.orientation;
1102
+ return e === "horizontal" ? Z.slideHorizontal.css : e === "vertical" ? Z.slideVertical.css : (r || c(t), r && r.height > r.width ? Z.slideVertical.css : Z.slideHorizontal.css);
1103
+ }
1104
+ return n.tap ? Z.tap.css : n.hold ? Z.hold.css : "";
1105
+ };
1106
+ return {
1107
+ onPointerDown: f,
1108
+ onPointerMove: p,
1109
+ onPointerUp: m,
1110
+ onPointerCancel: h,
1111
+ onPointerEnter: (e) => {
1112
+ let t = e.currentTarget;
1113
+ n.element = t, t.style.cursor = g(t);
1114
+ },
1115
+ bindElement: (e) => {
1116
+ e && (n.element = e, c(e));
1117
+ },
1118
+ touchAction: () => {
1119
+ let n = e();
1120
+ if (n.slide) {
1121
+ let e = n.slide.orientation;
1122
+ return e === "vertical" || e !== "horizontal" && (o() ?? (t?.() ?? "horizontal") !== "horizontal") ? "pan-x" : "pan-y";
1123
+ }
1124
+ return n.tap || n.hold ? "manipulation" : "auto";
1125
+ },
1126
+ dispose: () => {
1127
+ l(), a &&= (a.disconnect(), null), i = null, r = null;
1128
+ }
1129
+ };
1130
+ }
1131
+ //#endregion
1132
+ //#region src/framework/theming/svg-colors.ts
1133
+ var Lt = {
1134
+ solar: "oklch(0.74 0.18 60)",
1135
+ grid: "oklch(0.62 0.12 245)",
1136
+ battery: "oklch(0.70 0.18 145)",
1137
+ ev: "oklch(0.70 0.14 190)",
1138
+ home: "oklch(0.68 0.06 250)",
1139
+ positive: "oklch(0.70 0.14 160)",
1140
+ negative: "oklch(0.64 0.22 27)"
1321
1141
  };
1322
- function mn(e) {
1323
- if (e.length < 2) return "";
1324
- const t = e[0], i = e[1];
1325
- if (!t || !i) return "";
1326
- if (e.length === 2) return `M ${t.x} ${t.y} L ${i.x} ${i.y}`;
1327
- const r = e.length, n = [], o = [], u = [];
1328
- for (let m = 0; m < r - 1; m++) {
1329
- const h = e[m], v = e[m + 1];
1330
- !h || !v || (n.push(v.x - h.x), o.push(v.y - h.y), u.push((v.y - h.y) / (v.x - h.x)));
1331
- }
1332
- const d = [u[0] ?? 0];
1333
- for (let m = 1; m < r - 1; m++) {
1334
- const h = u[m - 1] ?? 0, v = u[m] ?? 0, y = n[m - 1] ?? 0, g = n[m] ?? 0;
1335
- h * v <= 0 ? d.push(0) : d.push(
1336
- 3 * (y + g) / ((2 * g + y) / h + (g + 2 * y) / v)
1337
- );
1338
- }
1339
- d.push(u[r - 2] ?? 0);
1340
- let $ = `M ${t.x} ${t.y}`;
1341
- for (let m = 0; m < r - 1; m++) {
1342
- const h = e[m], v = e[m + 1];
1343
- if (!h || !v) continue;
1344
- const y = (n[m] ?? 0) / 3, g = d[m] ?? 0, a = d[m + 1] ?? 0;
1345
- $ += ` C ${h.x + y} ${h.y + g * y}, ${v.x - y} ${v.y - a * y}, ${v.x} ${v.y}`;
1346
- }
1347
- return $;
1348
- }
1349
- function vn() {
1350
- return document.documentElement.classList.contains("dark");
1351
- }
1352
- const Lt = "1.2.0", Ut = {
1353
- version: Lt
1354
- }, wn = Ut.version;
1355
- export {
1356
- wn as SDK_VERSION,
1357
- hn as ToneSchema,
1358
- q as Widget,
1359
- Ye as WidgetContent,
1360
- P as WidgetCtx,
1361
- an as WidgetDialog,
1362
- Qe as WidgetIcon,
1363
- xn as WidgetManifestSchema,
1364
- Ge as WidgetSliderFill,
1365
- et as WidgetStatus,
1366
- it as WidgetTitle,
1367
- ut as WidgetValue,
1368
- kn as byDomain,
1369
- rt as calculateLightGroup,
1370
- ot as calculateSensorGroup,
1371
- on as countActiveEntities,
1372
- Jt as defineWidget,
1373
- yn as formatSchemaError,
1374
- rn as getEntityAttribute,
1375
- Pn as getForecasts,
1376
- In as getStream,
1377
- Ln as getWebRtcClientConfig,
1378
- Pe as injectTokens,
1379
- vn as isDark,
1380
- at as isEntityActive,
1381
- mn as monotoneCubicPath,
1382
- Un as sendWebRtcCandidate,
1383
- jn as startWebRtcSession,
1384
- Bn as state,
1385
- gn as svgColors,
1386
- Fn as trackEntityHistory,
1387
- Gn as untrackEntityHistory,
1388
- Cn as useArea,
1389
- Sn as useCamera,
1390
- Mn as useConnection,
1391
- Dn as useCurrency,
1392
- Tn as useEntities,
1393
- _n as useEntity,
1394
- On as useEntityHistory,
1395
- zn as useEntityStatistics,
1396
- En as useForecast,
1397
- Nn as useHassConfig,
1398
- sn as useIntersectionPause,
1399
- An as useLocale,
1400
- ln as useReducedMotion,
1401
- Zt as useService,
1402
- Vn as useStore,
1403
- Wn as useTemperatureUnit,
1404
- nn as useToggle,
1405
- tn as useTurnOff,
1406
- en as useTurnOn,
1407
- Rn as useUnitSystem,
1408
- Qt as useWidgetContext,
1409
- cn as useWidgetDialog,
1410
- dn as useWidgetEntityGroup,
1411
- un as useWidgetGestures,
1412
- fn as widgetFields
1142
+ function Rt(e) {
1143
+ return {
1144
+ fill: `color-mix(in oklch, ${e} 20%, transparent)`,
1145
+ stroke: e,
1146
+ solid: e
1147
+ };
1148
+ }
1149
+ var zt = Object.fromEntries(Object.entries(Lt).map(([e, t]) => [e, Rt(t)])), Bt = n.enum([
1150
+ "success",
1151
+ "warning",
1152
+ "danger",
1153
+ "info",
1154
+ "neutral",
1155
+ "accent"
1156
+ ]), Vt = {
1157
+ title: () => n.string().optional().meta({
1158
+ title: "Title",
1159
+ description: "Optional display name override"
1160
+ }),
1161
+ entityIds: (e, t) => n.array(n.string()).default([]).meta({
1162
+ domain: e,
1163
+ title: "Entities",
1164
+ ...t?.deviceClass ? { deviceClass: t.deviceClass } : {}
1165
+ }),
1166
+ singleEntity: (e, t) => n.array(n.string()).default([]).meta({
1167
+ domain: e,
1168
+ title: "Entity",
1169
+ singleSelect: !0,
1170
+ ...t?.deviceClass ? { deviceClass: t.deviceClass } : {}
1171
+ }),
1172
+ areaId: () => n.string().optional().meta({
1173
+ formType: "area-picker",
1174
+ title: "Area"
1175
+ })
1413
1176
  };
1177
+ //#endregion
1178
+ //#region src/shared/spline.ts
1179
+ function Ht(e) {
1180
+ if (e.length < 2) return "";
1181
+ let t = e[0], n = e[1];
1182
+ if (!t || !n) return "";
1183
+ if (e.length === 2) return `M ${t.x} ${t.y} L ${n.x} ${n.y}`;
1184
+ let r = e.length, i = [], a = [], o = [];
1185
+ for (let t = 0; t < r - 1; t++) {
1186
+ let n = e[t], r = e[t + 1];
1187
+ !n || !r || (i.push(r.x - n.x), a.push(r.y - n.y), o.push((r.y - n.y) / (r.x - n.x)));
1188
+ }
1189
+ let s = [o[0] ?? 0];
1190
+ for (let e = 1; e < r - 1; e++) {
1191
+ let t = o[e - 1] ?? 0, n = o[e] ?? 0, r = i[e - 1] ?? 0, a = i[e] ?? 0;
1192
+ t * n <= 0 ? s.push(0) : s.push(3 * (r + a) / ((2 * a + r) / t + (a + 2 * r) / n));
1193
+ }
1194
+ s.push(o[r - 2] ?? 0);
1195
+ let c = `M ${t.x} ${t.y}`;
1196
+ for (let t = 0; t < r - 1; t++) {
1197
+ let n = e[t], r = e[t + 1];
1198
+ if (!n || !r) continue;
1199
+ let a = (i[t] ?? 0) / 3, o = s[t] ?? 0, l = s[t + 1] ?? 0;
1200
+ c += ` C ${n.x + a} ${n.y + o * a}, ${r.x - a} ${r.y - l * a}, ${r.x} ${r.y}`;
1201
+ }
1202
+ return c;
1203
+ }
1204
+ //#endregion
1205
+ //#region src/theme.ts
1206
+ function Ut() {
1207
+ return document.documentElement.classList.contains("dark");
1208
+ }
1209
+ //#endregion
1210
+ //#region src/version.ts
1211
+ var Wt = {
1212
+ name: "@glasshome/widget-sdk",
1213
+ version: "1.2.1",
1214
+ description: "SDK for building GlassHome dashboard widgets with SolidJS",
1215
+ keywords: [
1216
+ "glasshome",
1217
+ "widget",
1218
+ "sdk",
1219
+ "solidjs",
1220
+ "vite",
1221
+ "home-assistant",
1222
+ "dashboard",
1223
+ "smart-home"
1224
+ ],
1225
+ type: "module",
1226
+ sideEffects: !1,
1227
+ main: "./dist/index.js",
1228
+ types: "./dist/index.d.ts",
1229
+ exports: {
1230
+ ".": {
1231
+ "@glasshome/source": "./src/index.ts",
1232
+ types: "./dist/index.d.ts",
1233
+ import: "./dist/index.js"
1234
+ },
1235
+ "./schemas": {
1236
+ "@glasshome/source": "./src/schemas.ts",
1237
+ types: "./dist/schemas.d.ts",
1238
+ import: "./dist/schemas.js"
1239
+ },
1240
+ "./vite": {
1241
+ "@glasshome/source": "./src/vite/index.ts",
1242
+ types: "./dist/vite/index.d.ts",
1243
+ import: "./dist/vite/index.js"
1244
+ },
1245
+ "./tailwind-sources": "./tailwind-sources.css",
1246
+ "./package.json": "./package.json"
1247
+ },
1248
+ files: [
1249
+ "dist",
1250
+ "preview",
1251
+ "tailwind-sources.css"
1252
+ ],
1253
+ scripts: {
1254
+ build: "vite build && tsc",
1255
+ dev: "vite build --watch"
1256
+ },
1257
+ peerDependencies: {
1258
+ "@glasshome/sync-layer": "0.2.0",
1259
+ "solid-js": "^1.9.11"
1260
+ },
1261
+ dependencies: {
1262
+ "@glasshome/widget-contract": "0.1.0",
1263
+ "@modular-forms/solid": "^0.25.1",
1264
+ "@solid-primitives/resize-observer": "^2.1.5",
1265
+ clsx: "^2.1.1",
1266
+ "tailwind-merge": "^3.5.0",
1267
+ zod: "^4.1.13",
1268
+ "@tailwindcss/vite": "^4.1.13",
1269
+ tailwindcss: "^4.1.13"
1270
+ },
1271
+ devDependencies: {
1272
+ "@types/bun": "latest",
1273
+ "@types/node": "^25.2.2",
1274
+ typescript: "^5",
1275
+ vite: "^8.1.0",
1276
+ "vite-plugin-solid": "^2.11.12"
1277
+ },
1278
+ repository: {
1279
+ type: "git",
1280
+ url: "https://github.com/glasshome/widget-sdk.git"
1281
+ },
1282
+ homepage: "https://github.com/glasshome/widget-sdk#readme",
1283
+ bugs: { url: "https://github.com/glasshome/widget-sdk/issues" },
1284
+ author: "GlassHome Labs",
1285
+ license: "MIT",
1286
+ publishConfig: { access: "public" },
1287
+ engines: { node: ">=18" }
1288
+ }.version;
1289
+ //#endregion
1290
+ export { Wt as SDK_VERSION, Bt as ToneSchema, H as Widget, Ie as WidgetContent, I as WidgetCtx, wt as WidgetDialog, Be as WidgetIcon, e as WidgetManifestSchema, Pe as WidgetSliderFill, He as WidgetStatus, Ge as WidgetTitle, nt as WidgetValue, d as byDomain, Ke as calculateLightGroup, qe as calculateSensorGroup, Ze as countActiveEntities, be as defineWidget, t as formatSchemaError, Xe as getEntityAttribute, r as getForecasts, i as getStream, a as getWebRtcClientConfig, Ae as injectTokens, Ut as isDark, Ye as isEntityActive, Ht as monotoneCubicPath, o as sendWebRtcCandidate, s as startWebRtcSession, c as state, zt as svgColors, l as trackEntityHistory, u as untrackEntityHistory, f as useArea, p as useCamera, m as useConnection, h as useCurrency, g as useEntities, _ as useEntity, v as useEntityHistory, ee as useEntityStatistics, y as useForecast, b as useHassConfig, Tt as useIntersectionPause, te as useLocale, Et as useReducedMotion, Ce as useService, ne as useStore, re as useTemperatureUnit, Ee as useToggle, Te as useTurnOff, we as useTurnOn, oe as useUnitSystem, xe as useWidgetContext, Dt as useWidgetDialog, Ot as useWidgetEntityGroup, It as useWidgetGestures, Vt as widgetFields };