@glasshome/widget-sdk 1.15.1 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2,14 +2,14 @@ import { deprecate as e, deprecations as t, formatDeprecation as n } from "./dep
2
2
  import { WidgetManifestSchema as r, formatSchemaError as i } from "./schemas.js";
3
3
  import { z as a, z as o } from "zod";
4
4
  import { getForecasts as s, getStream as c, getWebRtcClientConfig as l, hassMediaUrl as u, sendWebRtcCandidate as d, startWebRtcSession as f, state as p, trackEntityHistory as m, untrackEntityHistory as h } from "@glasshome/sync-layer";
5
- import { byDomain as g, useArea as _, useCalendarEvents as v, useCamera as ee, useConnection as y, useCurrency as b, useEntities as te, useEntity as ne, useEntityHistory as re, useEntityStatistics as ie, useForecast as ae, useHassConfig as oe, useLocale as se, useService as ce, useStore as x, useTemperatureUnit as S, useToggle as le, useTurnOff as ue, useTurnOn as C, useUnitSystem as w } from "@glasshome/sync-layer/solid";
6
- import { For as de, Show as T, createContext as fe, createEffect as E, createMemo as D, createSignal as O, on as pe, onCleanup as me, onMount as he, splitProps as ge, useContext as k } from "solid-js";
7
- import { addEventListener as A, className as j, createComponent as M, effect as N, insert as P, memo as F, setStyleProperty as I, style as _e, template as L, use as ve } from "solid-js/web";
8
- import { clsx as ye } from "clsx";
9
- import { twMerge as be } from "tailwind-merge";
10
- import { Badge as xe, Button as Se, Carousel as Ce, CarouselContent as we, CarouselDots as Te, CarouselItem as Ee, CarouselNext as De, CarouselPrevious as Oe, ColorSlider as ke, ColorWheel as Ae, CountPill as je, Icon as Me, Input as Ne, Label as Pe, ResponsiveDialog as Fe, ResponsiveDialogBody as Ie, ResponsiveDialogBody as Le, ResponsiveDialogClose as Re, ResponsiveDialogContent as ze, ResponsiveDialogDescription as Be, ResponsiveDialogFooter as Ve, ResponsiveDialogFooter as He, ResponsiveDialogHeader as Ue, ResponsiveDialogTitle as We, SchemaForm as Ge, SectionIcon as Ke, SectionTitle as qe, Select as Je, SelectContent as Ye, SelectItem as Xe, SelectTrigger as Ze, SelectValue as Qe, Slider as $e, Switch as et, Tabs as tt, Tabs as nt, TabsContent as rt, TabsContent as it, TabsList as at, TabsList as ot, TabsTrigger as st, TabsTrigger as ct, imageUrl as lt, mediaUrl as ut, parseColor as dt } from "@glasshome/ui/solid";
5
+ import { byDomain as g, useArea as _, useCalendarEvents as v, useCamera as y, useConnection as b, useCurrency as x, useEntities as S, useEntity as ee, useEntity as te, useEntityHistory as ne, useEntityStatistics as re, useForecast as ie, useHassConfig as ae, useLocale as oe, useService as se, useStore as ce, useTemperatureUnit as le, useToggle as ue, useTurnOff as de, useTurnOn as fe, useUnitSystem as pe } from "@glasshome/sync-layer/solid";
6
+ import { For as C, Show as w, children as T, createContext as me, createEffect as E, createMemo as D, createSignal as O, on as he, onCleanup as k, onMount as ge, splitProps as _e, useContext as A } from "solid-js";
7
+ import { addEventListener as j, className as M, createComponent as N, delegateEvents as ve, effect as P, insert as F, memo as I, setAttribute as L, setStyleProperty as R, style as z, template as B, use as V } from "solid-js/web";
8
+ import { Accordion as ye, AccordionContent as be, AccordionItem as xe, AccordionTrigger as Se, Badge as Ce, Badge as we, Button as Te, Button as Ee, ButtonGroup as De, ButtonGroup as Oe, Carousel as ke, CarouselContent as Ae, CarouselDots as je, CarouselItem as Me, CarouselNext as Ne, CarouselPrevious as Pe, ColorDisc as Fe, ColorSlider as Ie, ColorWheel as Le, CountPill as Re, CountPill as ze, Empty as Be, EmptyDescription as Ve, EmptyHeader as He, EmptyTitle as Ue, FactRow as H, FieldGroup as We, FieldTitle as Ge, Icon as Ke, Icon as U, Input as qe, Label as Je, Progress as Ye, ResponsiveDialog as Xe, ResponsiveDialogBody as Ze, ResponsiveDialogBody as Qe, ResponsiveDialogClose as $e, ResponsiveDialogContent as et, ResponsiveDialogDescription as tt, ResponsiveDialogFooter as nt, ResponsiveDialogFooter as rt, ResponsiveDialogHeader as it, ResponsiveDialogTitle as at, SchemaForm as ot, SectionIcon as st, SectionIcon as ct, SectionMeta as lt, SectionRow as ut, SectionTitle as dt, Select as ft, SelectContent as pt, SelectItem as mt, SelectTrigger as ht, SelectValue as gt, Slider as _t, SwatchPicker as vt, Switch as yt, Tabs as bt, Tabs as xt, TabsContent as St, TabsContent as Ct, TabsList as wt, TabsList as Tt, TabsTrigger as Et, TabsTrigger as Dt, TemperatureBar as Ot, Toggle as kt, ToggleGroup as At, ToggleGroup as jt, ToggleGroupItem as Mt, ToggleGroupItem as Nt, buttonVariants as Pt, imagePreset as Ft, imagePreset as It, imageUrl as Lt, imageUrl as Rt, mediaUrl as zt, parseColor as Bt, presetValue as Vt } from "@glasshome/ui/solid";
9
+ import { clsx as Ht } from "clsx";
10
+ import { twMerge as Ut } from "tailwind-merge";
11
11
  //#region src/framework/to-form-schema.ts
12
- function ft(e) {
12
+ function Wt(e) {
13
13
  return o.toJSONSchema(e, { override: (e) => {
14
14
  let t = o.globalRegistry.get(e.zodSchema);
15
15
  return t && typeof t == "object" && Object.keys(t).length > 0 ? {
@@ -18,7 +18,7 @@ function ft(e) {
18
18
  } : e.jsonSchema;
19
19
  } });
20
20
  }
21
- function pt(e) {
21
+ function Gt(e) {
22
22
  try {
23
23
  return e.parse({});
24
24
  } catch {
@@ -27,103 +27,714 @@ function pt(e) {
27
27
  }
28
28
  //#endregion
29
29
  //#region src/define-widget.ts
30
- function mt(e) {
31
- return e.configSchema && (e.manifest.schema || (e.manifest.schema = ft(e.configSchema)), e.manifest.defaultConfig || (e.manifest.defaultConfig = pt(e.configSchema))), e;
30
+ function Kt(e) {
31
+ return e.configSchema && (e.manifest.schema || (e.manifest.schema = Wt(e.configSchema)), e.manifest.defaultConfig || (e.manifest.defaultConfig = Gt(e.configSchema))), e;
32
32
  }
33
33
  //#endregion
34
34
  //#region src/framework/hooks/use-widget-context.ts
35
- var R = fe();
36
- function ht() {
37
- let e = k(R);
35
+ var W = me();
36
+ function qt() {
37
+ let e = A(W);
38
38
  if (!e) throw Error("useWidgetContext must be used within a Widget component");
39
39
  return e;
40
40
  }
41
41
  //#endregion
42
42
  //#region src/framework/hooks/use-service.ts
43
- function gt(e) {
43
+ function Jt(e) {
44
44
  let t = Array.isArray(e) ? e[0] : e, n = t?.split(".")[0];
45
45
  if (!n) throw Error(`Invalid entity ID: ${String(t)}`);
46
46
  return n;
47
47
  }
48
- function z(e, t) {
48
+ function G(e, t) {
49
49
  return async (n, r = {}) => {
50
- await e(gt(n), t, r, { entity_id: n });
50
+ await e(Jt(n), t, r, { entity_id: n });
51
51
  };
52
52
  }
53
- function _t() {
54
- let e = k(R)?.callService;
53
+ function Yt() {
54
+ let e = A(W)?.callService;
55
55
  return e ? {
56
56
  callService: e,
57
- turnOn: z(e, "turn_on"),
58
- turnOff: z(e, "turn_off"),
59
- toggle: z(e, "toggle")
60
- } : ce();
57
+ turnOn: G(e, "turn_on"),
58
+ turnOff: G(e, "turn_off"),
59
+ toggle: G(e, "toggle")
60
+ } : se();
61
+ }
62
+ function Xt() {
63
+ let e = A(W)?.callService;
64
+ return e ? G(e, "turn_on") : fe();
65
+ }
66
+ function Zt() {
67
+ let e = A(W)?.callService;
68
+ return e ? G(e, "turn_off") : de();
69
+ }
70
+ function Qt() {
71
+ let e = A(W)?.callService;
72
+ return e ? G(e, "toggle") : ue();
73
+ }
74
+ //#endregion
75
+ //#region src/framework/design-system/z-index.ts
76
+ var K = {
77
+ BACKGROUND: 0,
78
+ CONTENT: 10,
79
+ OVERLAY: 20,
80
+ ACTIONS: 30
81
+ }, q = /* @__PURE__ */ new WeakMap();
82
+ function $t(e = "controls") {
83
+ let [t, n] = O(!1), [r, i] = O(e), a = (t) => {
84
+ i(t ?? e), n(!0);
85
+ }, o = A(W);
86
+ return o?.registerDialogOpener?.(a), o && q.set(o, a), k(() => {
87
+ o?.registerDialogOpener?.(null), o && q.get(o) === a && q.delete(o);
88
+ }), {
89
+ showDialog: t,
90
+ setShowDialog: n,
91
+ openDialog: a,
92
+ closeDialog: () => n(!1),
93
+ activeTab: r,
94
+ setActiveTab: i,
95
+ dialogProps: {
96
+ get open() {
97
+ return t();
98
+ },
99
+ onOpenChange: n,
100
+ get activeTab() {
101
+ return r();
102
+ },
103
+ onActiveTabChange: i
104
+ }
105
+ };
106
+ }
107
+ //#endregion
108
+ //#region src/framework/hooks/widget-registry.ts
109
+ var en = /* @__PURE__ */ new WeakMap(), tn = Symbol("glasshome.widget.registry");
110
+ function nn(e) {
111
+ return e[tn] ?? e;
112
+ }
113
+ function rn(e) {
114
+ if (!e) return;
115
+ let t = nn(e), n = en.get(t);
116
+ if (!n) {
117
+ let [e, r] = O(!1), [i, a] = O(), [o, s] = O(), [c, l] = O();
118
+ n = {
119
+ hasSheet: e,
120
+ setHasSheet: r,
121
+ tone: i,
122
+ setTone: a,
123
+ accent: o,
124
+ setAccent: s,
125
+ icon: c,
126
+ setIcon: l
127
+ }, en.set(t, n);
128
+ }
129
+ return n;
61
130
  }
62
- function vt() {
63
- let e = k(R)?.callService;
64
- return e ? z(e, "turn_on") : C();
131
+ //#endregion
132
+ //#region src/framework/gestures/cursors.ts
133
+ var an = 32, J = an / 2, Y = "white", on = "rgba(0,0,0,0.4)", sn = 2, cn = 3;
134
+ function ln(e) {
135
+ return `url("data:image/svg+xml,${encodeURIComponent(e)}")`;
136
+ }
137
+ function un(e) {
138
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="${an}" height="${an}" viewBox="0 0 ${an} ${an}">${e}</svg>`;
139
+ }
140
+ var dn = un(`
141
+ <g transform="translate(6, 2)">
142
+ <!-- shadow -->
143
+ <g stroke="${on}" stroke-width="${cn}" fill="none" stroke-linecap="round" stroke-linejoin="round">
144
+ <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"/>
145
+ </g>
146
+ <!-- main -->
147
+ <g stroke="${Y}" stroke-width="${sn}" fill="none" stroke-linecap="round" stroke-linejoin="round">
148
+ <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"/>
149
+ </g>
150
+ </g>
151
+ `), fn = un(`
152
+ <g>
153
+ <circle cx="${J}" cy="${J}" r="8" stroke="${on}" stroke-width="${cn}" fill="none"/>
154
+ <circle cx="${J}" cy="${J}" r="8" stroke="${Y}" stroke-width="1.5" fill="none"/>
155
+ <circle cx="${J}" cy="${J}" r="1.5" fill="${Y}"/>
156
+ </g>
157
+ `), pn = un(`
158
+ <g>
159
+ <!-- shadow -->
160
+ <g stroke="${on}" stroke-width="${cn}" fill="none" stroke-linecap="round" stroke-linejoin="round">
161
+ <line x1="6" y1="${J}" x2="26" y2="${J}"/>
162
+ <polyline points="10,12 6,${J} 10,20"/>
163
+ <polyline points="22,12 26,${J} 22,20"/>
164
+ </g>
165
+ <!-- main -->
166
+ <g stroke="${Y}" stroke-width="${sn}" fill="none" stroke-linecap="round" stroke-linejoin="round">
167
+ <line x1="6" y1="${J}" x2="26" y2="${J}"/>
168
+ <polyline points="10,12 6,${J} 10,20"/>
169
+ <polyline points="22,12 26,${J} 22,20"/>
170
+ </g>
171
+ <!-- center grip dots -->
172
+ <circle cx="${J}" cy="${J}" r="1.5" fill="${Y}"/>
173
+ <circle cx="11" cy="${J}" r="1" fill="${Y}" opacity="0.6"/>
174
+ <circle cx="21" cy="${J}" r="1" fill="${Y}" opacity="0.6"/>
175
+ </g>
176
+ `), mn = un(`
177
+ <g>
178
+ <!-- shadow -->
179
+ <g stroke="${on}" stroke-width="${cn}" fill="none" stroke-linecap="round" stroke-linejoin="round">
180
+ <line x1="${J}" y1="6" x2="${J}" y2="26"/>
181
+ <polyline points="12,10 ${J},6 20,10"/>
182
+ <polyline points="12,22 ${J},26 20,22"/>
183
+ </g>
184
+ <!-- main -->
185
+ <g stroke="${Y}" stroke-width="${sn}" fill="none" stroke-linecap="round" stroke-linejoin="round">
186
+ <line x1="${J}" y1="6" x2="${J}" y2="26"/>
187
+ <polyline points="12,10 ${J},6 20,10"/>
188
+ <polyline points="12,22 ${J},26 20,22"/>
189
+ </g>
190
+ <!-- center grip dots -->
191
+ <circle cx="${J}" cy="${J}" r="1.5" fill="${Y}"/>
192
+ <circle cx="${J}" cy="11" r="1" fill="${Y}" opacity="0.6"/>
193
+ <circle cx="${J}" cy="21" r="1" fill="${Y}" opacity="0.6"/>
194
+ </g>
195
+ `), hn = un(`
196
+ <g>
197
+ <!-- shadow -->
198
+ <g stroke="${on}" stroke-width="${cn}" fill="none" stroke-linecap="round" stroke-linejoin="round">
199
+ <line x1="7" y1="${J}" x2="25" y2="${J}"/>
200
+ <line x1="${J}" y1="7" x2="${J}" y2="25"/>
201
+ <polyline points="11,13 7,${J} 11,19"/>
202
+ <polyline points="21,13 25,${J} 21,19"/>
203
+ <polyline points="13,11 ${J},7 19,11"/>
204
+ <polyline points="13,21 ${J},25 19,21"/>
205
+ </g>
206
+ <!-- main -->
207
+ <g stroke="${Y}" stroke-width="${sn}" fill="none" stroke-linecap="round" stroke-linejoin="round">
208
+ <line x1="7" y1="${J}" x2="25" y2="${J}"/>
209
+ <line x1="${J}" y1="7" x2="${J}" y2="25"/>
210
+ <polyline points="11,13 7,${J} 11,19"/>
211
+ <polyline points="21,13 25,${J} 21,19"/>
212
+ <polyline points="13,11 ${J},7 19,11"/>
213
+ <polyline points="13,21 ${J},25 19,21"/>
214
+ </g>
215
+ <!-- center dot -->
216
+ <circle cx="${J}" cy="${J}" r="2" fill="${Y}"/>
217
+ </g>
218
+ `);
219
+ function gn(e, t, n) {
220
+ return {
221
+ css: `${ln(e)} ${t} ${n}, auto`,
222
+ hotspotX: t,
223
+ hotspotY: n
224
+ };
225
+ }
226
+ var _n = {
227
+ tap: gn(dn, 12, 4),
228
+ hold: gn(fn, 16, 16),
229
+ slideHorizontal: gn(pn, J, J),
230
+ slideVertical: gn(mn, J, J),
231
+ slideAuto: gn(hn, J, J)
232
+ };
233
+ //#endregion
234
+ //#region src/framework/gestures/haptics.ts
235
+ function vn() {
236
+ if (typeof window > "u") return null;
237
+ let e = window;
238
+ return e.Capacitor?.isNativePlatform?.() ? e.Capacitor.Plugins?.Haptics ?? null : null;
239
+ }
240
+ function yn(e) {
241
+ if (typeof navigator < "u" && typeof navigator.vibrate == "function") try {
242
+ navigator.vibrate(e);
243
+ } catch {}
244
+ }
245
+ var bn = {
246
+ tick() {
247
+ let e = vn();
248
+ if (e) {
249
+ e.impact({ style: "Light" }).catch(() => {});
250
+ return;
251
+ }
252
+ yn(8);
253
+ },
254
+ bump() {
255
+ let e = vn();
256
+ if (e) {
257
+ e.impact({ style: "Medium" }).catch(() => {});
258
+ return;
259
+ }
260
+ yn(20);
261
+ },
262
+ pulse() {
263
+ let e = vn();
264
+ if (e) {
265
+ e.impact({ style: "Heavy" }).catch(() => {});
266
+ return;
267
+ }
268
+ yn([
269
+ 0,
270
+ 15,
271
+ 40,
272
+ 15
273
+ ]);
274
+ }
275
+ };
276
+ //#endregion
277
+ //#region src/framework/gestures/use-widget-gestures.ts
278
+ function xn(e, t) {
279
+ let n = A(W), r = rn(n), i = () => {
280
+ let t = e();
281
+ return t.hold || !n || !r?.hasSheet() ? t : {
282
+ ...t,
283
+ hold: { action: () => q.get(n)?.() }
284
+ };
285
+ }, a = {
286
+ isDown: !1,
287
+ isTouch: !1,
288
+ startX: 0,
289
+ startY: 0,
290
+ startTime: 0,
291
+ hasMoved: !1,
292
+ sliding: !1,
293
+ holdTimer: null,
294
+ graceTimer: null,
295
+ element: null
296
+ }, [o, s] = O(null), c = null, l = null, u = null, [d, f] = O(null);
297
+ function p(e) {
298
+ e !== l && (u && u.disconnect(), u = new ResizeObserver((e) => {
299
+ let t = e[0];
300
+ if (t) {
301
+ let e = t.borderBoxSize?.[0];
302
+ c = e ? {
303
+ width: e.inlineSize,
304
+ height: e.blockSize
305
+ } : {
306
+ width: t.contentRect.width,
307
+ height: t.contentRect.height
308
+ }, f(c.height > c.width);
309
+ }
310
+ }), l = e, u.observe(e), c = {
311
+ width: e.clientWidth,
312
+ height: e.clientHeight
313
+ }, f(c.height > c.width));
314
+ }
315
+ let m = () => {
316
+ a.holdTimer &&= (clearTimeout(a.holdTimer), null), a.graceTimer &&= (clearTimeout(a.graceTimer), null), s(null);
317
+ }, h = (e) => {
318
+ let t = (e) => {
319
+ e.stopPropagation(), e.preventDefault();
320
+ }, n = () => e.removeEventListener("click", t, !0);
321
+ e.addEventListener("click", t, !0), window.addEventListener("pointerup", () => setTimeout(n, 0), {
322
+ capture: !0,
323
+ once: !0
324
+ });
325
+ }, g = () => {
326
+ a.isDown = !1, a.hasMoved = !1, a.sliding = !1;
327
+ }, _ = (e) => {
328
+ let n = i().slide;
329
+ return n?.orientation === "horizontal" ? "horizontal" : n?.orientation === "vertical" ? "vertical" : e && (c || p(e), c) ? c.height > c.width ? "vertical" : "horizontal" : (t?.() ?? "horizontal") === "horizontal" ? "horizontal" : "vertical";
330
+ }, v = (e) => {
331
+ let t = i();
332
+ if (t.tap || t.hold || t.slide) {
333
+ if (a.isDown = !0, a.isTouch = e.pointerType === "touch", a.element = e.currentTarget, p(a.element), a.startX = e.clientX, a.startY = e.clientY, a.startTime = Date.now(), a.hasMoved = !1, a.sliding = !1, t.hold) {
334
+ let n = t.hold.delay ?? 550, r = a.element.getBoundingClientRect(), i = e.clientX - r.left, o = e.clientY - r.top, c = Math.hypot(Math.max(i, r.width - i), Math.max(o, r.height - o));
335
+ a.graceTimer = setTimeout(() => {
336
+ a.graceTimer = null, s({
337
+ x: i,
338
+ y: o,
339
+ r: c,
340
+ fired: !1
341
+ });
342
+ }, Math.min(150, n)), a.holdTimer = setTimeout(() => {
343
+ a.holdTimer = null, a.isDown && !a.hasMoved && (s((e) => e && {
344
+ ...e,
345
+ fired: !0
346
+ }), bn.bump(), a.element && h(a.element), t.hold?.action(), a.isDown = !1);
347
+ }, n);
348
+ }
349
+ if (!a.isTouch && t.slide) try {
350
+ e.currentTarget.setPointerCapture(e.pointerId);
351
+ } catch {}
352
+ }
353
+ }, y = (e) => {
354
+ if (!a.isDown) return;
355
+ let t = i(), n = e.clientX - a.startX, r = e.clientY - a.startY;
356
+ if (Math.sqrt(n * n + r * r) > 10 && (m(), a.hasMoved = !0), t.slide && a.hasMoved) {
357
+ let i = e.currentTarget, o = _(i);
358
+ if (a.isTouch && !a.sliding && Math.abs(o === "vertical" ? r : n) < Math.abs(o === "vertical" ? n : r)) return;
359
+ a.sliding = !0;
360
+ let s = t.slide.min ?? 0, l = t.slide.max ?? 100, u = l - s, d = o === "vertical" ? -r : n, f = c ?? {
361
+ width: i.clientWidth,
362
+ height: i.clientHeight
363
+ }, p = d / (o === "vertical" ? f.height : f.width) * u, m = Math.max(s, Math.min(l, t.slide.value + p));
364
+ t.slide.onChange(Math.round(m)), a.startX = e.clientX, a.startY = e.clientY, e.preventDefault();
365
+ }
366
+ }, b = (e) => {
367
+ let t = i(), n = a.isDown, r = Date.now() - a.startTime, o = t.hold?.delay ?? 550;
368
+ m(), n && t.tap && !a.hasMoved && r < o && t.tap();
369
+ try {
370
+ e.currentTarget.releasePointerCapture(e.pointerId);
371
+ } catch {}
372
+ g();
373
+ }, x = (e) => {
374
+ m();
375
+ try {
376
+ e.currentTarget.releasePointerCapture(e.pointerId);
377
+ } catch {}
378
+ g();
379
+ }, S = (e) => {
380
+ let t = i();
381
+ if (t.slide) {
382
+ let n = t.slide.orientation;
383
+ return n === "horizontal" ? _n.slideHorizontal.css : n === "vertical" ? _n.slideVertical.css : (c || p(e), c && c.height > c.width ? _n.slideVertical.css : _n.slideHorizontal.css);
384
+ }
385
+ return t.tap ? _n.tap.css : t.hold ? _n.hold.css : "";
386
+ };
387
+ return {
388
+ onKeyDown: (e) => {
389
+ if (e.target !== e.currentTarget) return;
390
+ let t = i();
391
+ (e.key === "Enter" || e.key === " ") && t.tap ? (e.preventDefault(), t.tap()) : (e.key === "ContextMenu" || e.shiftKey && e.key === "F10") && t.hold && (e.preventDefault(), t.hold.action());
392
+ },
393
+ onPointerDown: v,
394
+ onPointerMove: y,
395
+ onPointerUp: b,
396
+ onPointerCancel: x,
397
+ onPointerEnter: (e) => {
398
+ let t = e.currentTarget;
399
+ a.element = t, t.style.cursor = S(t);
400
+ },
401
+ bindElement: (e) => {
402
+ e && (a.element = e, p(e));
403
+ },
404
+ touchAction: () => {
405
+ let e = i();
406
+ if (e.slide) {
407
+ let n = e.slide.orientation;
408
+ return n === "vertical" || n !== "horizontal" && (d() ?? (t?.() ?? "horizontal") !== "horizontal") ? "pan-x" : "pan-y";
409
+ }
410
+ return e.tap || e.hold ? "manipulation" : "auto";
411
+ },
412
+ hold: o,
413
+ dispose: () => {
414
+ m(), u &&= (u.disconnect(), null), l = null, c = null;
415
+ }
416
+ };
417
+ }
418
+ //#endregion
419
+ //#region src/framework/hooks/use-widget-dimensions.ts
420
+ var Sn = me();
421
+ function Cn() {
422
+ let e = A(Sn);
423
+ if (!e) throw Error("useWidgetDimensions must be called inside <Widget>: move the call into a component rendered within <Widget> (the top-level widget scope only sees the host stub).");
424
+ return e;
425
+ }
426
+ //#endregion
427
+ //#region src/framework/hooks/use-confirm.ts
428
+ var wn = 1600;
429
+ function Tn() {
430
+ let [e, t] = O(/* @__PURE__ */ new Set()), n;
431
+ return k(() => clearTimeout(n)), {
432
+ has: (t) => e().has(t),
433
+ any: () => e().size > 0,
434
+ run: async (e, r) => {
435
+ try {
436
+ await r();
437
+ } catch {
438
+ return !1;
439
+ }
440
+ return t(new Set(e)), clearTimeout(n), n = setTimeout(() => t(/* @__PURE__ */ new Set()), wn), !0;
441
+ }
442
+ };
443
+ }
444
+ //#endregion
445
+ //#region src/framework/utils/cn.ts
446
+ function X(...e) {
447
+ return Ut(Ht(e));
448
+ }
449
+ //#endregion
450
+ //#region src/framework/components/WidgetIcon.tsx
451
+ var En = /*#__PURE__*/ B("<div class=\"glasshome-widget-icon glasshome-widget-icon-stack glasshome-widget-icon-stack-2 glass glass-tint\">"), Dn = /*#__PURE__*/ B("<div class=\"glasshome-widget-icon glasshome-widget-icon-stack glasshome-widget-icon-stack-3 glass glass-tint\">"), On = /*#__PURE__*/ B("<div><div class=\"glasshome-widget-icon-glyph flex items-center justify-center\">");
452
+ function kn(e) {
453
+ let t = () => e.entityCount ?? 1;
454
+ return (() => {
455
+ var n = On(), r = n.firstChild;
456
+ return F(n, N(w, {
457
+ get when() {
458
+ return t() >= 2;
459
+ },
460
+ get children() {
461
+ return En();
462
+ }
463
+ }), r), F(n, N(w, {
464
+ get when() {
465
+ return t() >= 3;
466
+ },
467
+ get children() {
468
+ return Dn();
469
+ }
470
+ }), r), F(r, () => e.icon), P((t) => {
471
+ var r = X("glasshome-widget-icon glass glass-tint", "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;
472
+ return r !== t.e && M(n, t.e = r), t.t = z(n, i, t.t), t;
473
+ }, {
474
+ e: void 0,
475
+ t: void 0
476
+ }), n;
477
+ })();
478
+ }
479
+ //#endregion
480
+ //#region src/framework/components/anatomy.tsx
481
+ var An = /*#__PURE__*/ B("<span class=glasshome-widget-eyebrow>"), jn = /*#__PURE__*/ B("<div class=glasshome-widget-head-aside>"), Mn = /*#__PURE__*/ B("<div class=glasshome-widget-head><div class=glasshome-widget-head-text><span class=glasshome-widget-name>"), Nn = /*#__PURE__*/ B("<span class=glasshome-widget-sub>"), Pn = /*#__PURE__*/ B("<span class=glasshome-widget-unit>"), Fn = /*#__PURE__*/ B("<div class=glasshome-widget-art>"), In = /*#__PURE__*/ B("<div><div class=glasshome-widget-reading><span class=glasshome-widget-reading-value>"), Ln = /*#__PURE__*/ B("<div class=glasshome-widget-controls>"), Rn = /*#__PURE__*/ B("<div>"), zn = /*#__PURE__*/ B("<div class=glasshome-widget-backdrop>"), Bn = /*#__PURE__*/ B("<div class=glasshome-widget-glyph aria-hidden=true>"), Vn = me(() => !1), Hn = "mdi:check";
482
+ function Un(e) {
483
+ let t = A(Vn), n = rn(A(W));
484
+ E(() => n?.setIcon(e.icon)), k(() => {
485
+ n?.icon() === e.icon && n?.setIcon(void 0);
486
+ });
487
+ let r = T(() => e.eyebrow), i = T(() => e.aside), a = () => {
488
+ let t = r();
489
+ return typeof t == "string" && typeof e.name == "string" && t.trim().toLowerCase() === e.name.trim().toLowerCase();
490
+ };
491
+ return (() => {
492
+ var n = Mn(), o = n.firstChild, s = o.firstChild;
493
+ return F(n, N(w, {
494
+ get when() {
495
+ return e.icon;
496
+ },
497
+ children: (n) => N(kn, {
498
+ get icon() {
499
+ return N(U, { get icon() {
500
+ return I(() => !!t())() ? Hn : n();
501
+ } });
502
+ },
503
+ get entityCount() {
504
+ return e.count;
505
+ },
506
+ get color() {
507
+ return e.active || t() ? void 0 : "var(--muted-foreground)";
508
+ },
509
+ class: "glasshome-widget-head-icon"
510
+ })
511
+ }), o), F(o, N(w, {
512
+ get when() {
513
+ return I(() => !!r())() && !a();
514
+ },
515
+ get children() {
516
+ var e = An();
517
+ return F(e, r), e;
518
+ }
519
+ }), s), F(s, () => e.name), F(n, N(w, {
520
+ get when() {
521
+ return i();
522
+ },
523
+ get children() {
524
+ var e = jn();
525
+ return F(e, i), e;
526
+ }
527
+ }), null), n;
528
+ })();
529
+ }
530
+ function Wn(e) {
531
+ let t = T(() => e.sub), n = T(() => e.art), r = D(() => typeof e.value == "string" ? e.value.replace(/[\d\s.,:/%°+\-−]/g, "") : void 0), i = () => typeof e.value == "string" || typeof e.value == "number" ? String(e.value).length + (e.unit ? .5 : 0) : void 0, [a, o] = O();
532
+ return E(he(r, () => o((e) => e === "a" ? "b" : "a"), { defer: !0 })), (() => {
533
+ var r = In(), o = r.firstChild, s = o.firstChild;
534
+ return F(o, N(w, {
535
+ get when() {
536
+ return t();
537
+ },
538
+ get children() {
539
+ var e = Nn();
540
+ return F(e, t), e;
541
+ }
542
+ }), s), F(s, () => e.value, null), F(s, N(w, {
543
+ get when() {
544
+ return e.unit;
545
+ },
546
+ get children() {
547
+ var t = Pn();
548
+ return F(t, () => e.unit), P(() => L(t, "data-degree", e.unit === "°" || void 0)), t;
549
+ }
550
+ }), null), F(r, N(w, {
551
+ get when() {
552
+ return n();
553
+ },
554
+ get children() {
555
+ var e = Fn();
556
+ return F(e, n), e;
557
+ }
558
+ }), null), P((o) => {
559
+ var c = X("glasshome-widget-hero", e.class), l = n() ? "" : void 0, u = e.value === "" && !t() ? "" : void 0, d = a(), f = i();
560
+ return c !== o.e && M(r, o.e = c), l !== o.t && L(r, "data-art", o.t = l), u !== o.a && L(r, "data-empty", o.a = u), d !== o.o && L(s, "data-turn", o.o = d), f !== o.i && R(s, "--value-len", o.i = f), o;
561
+ }, {
562
+ e: void 0,
563
+ t: void 0,
564
+ a: void 0,
565
+ o: void 0,
566
+ i: void 0
567
+ }), r;
568
+ })();
569
+ }
570
+ function Gn(e) {
571
+ return (() => {
572
+ var t = Ln();
573
+ return j(t, "pointerdown", (e) => e.stopPropagation()), F(t, () => e.children), t;
574
+ })();
575
+ }
576
+ function Kn(e) {
577
+ return N(Oe, {
578
+ get "aria-label"() {
579
+ return e.label;
580
+ },
581
+ class: "glasshome-widget-stepper",
582
+ get children() {
583
+ return [N(Ee, {
584
+ variant: "outline",
585
+ size: "icon",
586
+ "aria-label": "Lower",
587
+ class: "glasshome-widget-control",
588
+ onClick: () => e.onStep(-1),
589
+ get children() {
590
+ return N(U, { icon: "mdi:minus" });
591
+ }
592
+ }), N(Ee, {
593
+ variant: "outline",
594
+ size: "icon",
595
+ "aria-label": "Raise",
596
+ class: "glasshome-widget-control",
597
+ onClick: () => e.onStep(1),
598
+ get children() {
599
+ return N(U, { icon: "mdi:plus" });
600
+ }
601
+ })];
602
+ }
603
+ });
604
+ }
605
+ function qn(e) {
606
+ return N(jt, {
607
+ get "aria-label"() {
608
+ return e.label;
609
+ },
610
+ get tone() {
611
+ return e.tone;
612
+ },
613
+ get value() {
614
+ return e.value;
615
+ },
616
+ onChange: (t) => t && e.onChange(t),
617
+ class: "glasshome-widget-choice",
618
+ get children() {
619
+ return N(C, {
620
+ get each() {
621
+ return e.options;
622
+ },
623
+ children: (t) => N(Nt, {
624
+ get value() {
625
+ return t.value;
626
+ },
627
+ get "aria-label"() {
628
+ return t.label;
629
+ },
630
+ class: "glasshome-widget-control",
631
+ get "data-optional"() {
632
+ return t.value === e.value ? void 0 : "";
633
+ },
634
+ get children() {
635
+ return N(U, { get icon() {
636
+ return t.icon;
637
+ } });
638
+ }
639
+ })
640
+ });
641
+ }
642
+ });
643
+ }
644
+ function Jn(e) {
645
+ let t = Tn(), n = () => e.confirm ?? t, r = () => e.id ?? e["aria-label"] ?? e.icon, i = () => n().has(r());
646
+ return N(Ee, {
647
+ variant: "outline",
648
+ get size() {
649
+ return e.children ? "default" : "icon";
650
+ },
651
+ get "aria-label"() {
652
+ return e["aria-label"];
653
+ },
654
+ get class() {
655
+ return X(e.children ? "glasshome-widget-control-wide" : "glasshome-widget-control", e.class);
656
+ },
657
+ get "data-confirmed"() {
658
+ return i() || void 0;
659
+ },
660
+ onClick: () => void n().run([r()], e.run),
661
+ get children() {
662
+ return [N(U, { get icon() {
663
+ return I(() => !!i())() ? Hn : e.icon;
664
+ } }), I(() => e.children)];
665
+ }
666
+ });
667
+ }
668
+ function Yn(e) {
669
+ return N(we, {
670
+ get tone() {
671
+ return e.tone ?? "var(--muted-foreground)";
672
+ },
673
+ class: "gap-1 tabular-nums",
674
+ get children() {
675
+ return [N(w, {
676
+ get when() {
677
+ return e.icon;
678
+ },
679
+ children: (e) => N(U, { get icon() {
680
+ return e();
681
+ } })
682
+ }), I(() => e.children)];
683
+ }
684
+ });
65
685
  }
66
- function yt() {
67
- let e = k(R)?.callService;
68
- return e ? z(e, "turn_off") : ue();
686
+ function Xn(e) {
687
+ return (() => {
688
+ var t = Rn();
689
+ return F(t, () => e.children), P(() => M(t, X("glasshome-widget-layer", e.class))), t;
690
+ })();
69
691
  }
70
- function bt() {
71
- let e = k(R)?.callService;
72
- return e ? z(e, "toggle") : le();
692
+ function Zn(e) {
693
+ return (() => {
694
+ var t = zn();
695
+ return F(t, () => e.children), t;
696
+ })();
73
697
  }
74
- //#endregion
75
- //#region src/framework/design-system/z-index.ts
76
- var B = {
77
- BACKGROUND: 0,
78
- CONTENT: 10,
79
- OVERLAY: 20,
80
- ACTIONS: 30
81
- }, xt = fe();
82
- function St() {
83
- let e = k(xt);
84
- if (!e) throw Error("useWidgetDimensions must be called inside <Widget>: move the call into a component rendered within <Widget> (the top-level widget scope only sees the host stub).");
85
- return e;
698
+ function Qn(e) {
699
+ let t = A(Vn);
700
+ return (() => {
701
+ var n = Bn();
702
+ return F(n, N(U, { get icon() {
703
+ return I(() => !!t())() ? Hn : e.icon;
704
+ } })), n;
705
+ })();
86
706
  }
87
707
  //#endregion
88
708
  //#region src/framework/theming/tokens.css?raw
89
- var Ct = "/* Authoritative SDK CSS contract. Injected once on first Widget mount\n * via framework/theming/tokens.ts.\n *\n * All widget-internal visual scale is driven from CSS custom properties +\n * container queries on the `.glasshome-widget` shell (`container-type: size`).\n * No JS classifier, no size tier enum.\n */\n\n:root {\n --tone-success: oklch(0.70 0.18 145);\n --tone-warning: oklch(0.80 0.17 75);\n --tone-danger: oklch(0.64 0.22 27);\n --tone-info: oklch(0.66 0.20 245);\n --tone-neutral: oklch(0.65 0.02 250);\n --tone-accent: oklch(0.74 0.18 60);\n\n --widget-grad-strength: 1;\n --widget-glow-default: 0.4;\n --widget-border-highlight: oklch(0.98 0 0 / 0.4);\n}\n\n.dark {\n --tone-success: oklch(0.74 0.18 145);\n --tone-warning: oklch(0.82 0.17 75);\n --tone-danger: oklch(0.68 0.22 27);\n --tone-info: oklch(0.70 0.20 245);\n --tone-neutral: oklch(0.69 0.02 250);\n --tone-accent: oklch(0.78 0.18 60);\n\n --widget-grad-strength: 1.1;\n --widget-glow-default: 0.5;\n --widget-border-highlight: oklch(1 0 0 / 0.08);\n}\n\n@property --widget-color {\n syntax: \"<color>\";\n inherits: true;\n initial-value: oklch(0.65 0.02 250);\n}\n\n/* === Widget shell ===\n * Fluid scale tokens — tied to the shell's own container box (cqb=height, cqi=width).\n * Icon/pad/gap track HEIGHT (cqb) not the shortest side: two widgets of equal\n * height match regardless of width (a 2×2 and a 4×2 get the same icon). cqmin\n * starved portrait tiles by pinning the icon to the narrow width. Tune\n * multipliers / clamps to adjust density. */\n.glasshome-widget {\n --widget-color: var(--tone-neutral);\n --widget-glow-strength: var(--widget-glow-default);\n --widget-radius: var(--radius-xl, 12px);\n\n --widget-icon-box: clamp(44px, 25cqb, 58px);\n --widget-icon-glyph: clamp(24px, 14cqb, 33px);\n --widget-pad: clamp(8px, 3.5cqb, 22px);\n --widget-gap: clamp(6px, 2cqb, 14px);\n --widget-title-size: clamp(12px, 2cqi, 18px);\n --widget-subtitle: clamp(12px, 2.5cqi, 20px);\n --widget-status-size: clamp(14px, 5cqi, 36px);\n --widget-value-size: clamp(18px, 7cqi, 48px);\n --widget-badge-size: clamp(11px, 1.6cqi, 14px);\n}\n\n/* Shell material. Two channels, both host/variant-driven:\n * - `--widget-backdrop`: the live backdrop filter (the shared glass recipe is\n * blur + saturate, matching ui's CARD_BLUR). Default none — a variant opts\n * in (classic-glass), and a performant-blur host disables it via override\n * sheet when it paints a precomputed frost instead.\n * - `--glass-frost`: one full background layer (image + position / size +\n * repeat) composited at the BOTTOM, under the accent gradient — the same\n * frost slot ui's `.glass` formula ends its background list with. Unset →\n * none. A performant-blur host sets it per shell with the viewport-aligned\n * slice of its pre-blurred bitmap. */\n.glasshome-widget {\n background:\n var(--widget-gradient,\n linear-gradient(135deg,\n color-mix(in oklch, var(--widget-color) calc(22% * var(--widget-grad-strength)), transparent),\n color-mix(in oklch, var(--widget-color-to, var(--widget-color)) calc(11% * var(--widget-grad-strength)), transparent)\n )\n ),\n var(--glass-frost, none);\n backdrop-filter: var(--widget-backdrop, none);\n -webkit-backdrop-filter: var(--widget-backdrop, none);\n box-shadow: inset 0 1px 0 var(--widget-border-highlight);\n}\n\n/* === Slot: content layout === */\n/* Default: column. Flip to row only on wide-and-short widgets (matches the\n * old contentLayout heuristic: aspect > 1 AND height < 150px). */\n.glasshome-widget-content {\n position: relative;\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n width: 100%;\n height: 100%;\n padding: var(--widget-pad);\n gap: var(--widget-gap);\n overflow: hidden;\n border-radius: var(--widget-radius);\n}\n@container widget (min-aspect-ratio: 1) and (max-height: 149px) {\n .glasshome-widget-content {\n flex-direction: row;\n align-items: center;\n justify-content: flex-start;\n }\n}\n\n/* === Compact 1×1 ===\n * Small in BOTH axes → stack the tile: icon on top, label + status centered\n * under it. Icon stays moderate (not a hero) so the text keeps room. Wide\n * tiles (2×1) fail the width test and keep the row layout above. Placed after\n * the row-flip so it wins. */\n@container widget (max-width: 189px) and (max-height: 189px) {\n .glasshome-widget-content {\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n gap: clamp(4px, 2.5cqmin, 8px);\n }\n .glasshome-widget-content > * { align-items: center; text-align: center; }\n .glasshome-widget-icon {\n --widget-icon-box: clamp(36px, 30cqmin, 56px);\n --widget-icon-glyph: clamp(20px, 17cqmin, 32px);\n }\n .glasshome-widget-title { font-size: clamp(11px, 6cqmin, 14px); max-width: 100%; }\n .glasshome-widget-status,\n .glasshome-widget-value { font-size: clamp(13px, 7cqmin, 17px); }\n .glasshome-widget-content [class*=\"ml-auto\"] { margin-left: 0 !important; }\n}\n.glasshome-widget-content [class*=\"ml-auto\"] {\n position: relative;\n z-index: 30;\n}\n\n/* === Slot: icon === */\n.glasshome-widget-icon {\n width: var(--widget-icon-box);\n height: var(--widget-icon-box);\n border-radius: var(--radius-sm, 12px);\n background: var(--widget-icon-color, var(--widget-color));\n box-shadow: 0 0 calc(var(--widget-glow-strength) * 30px)\n color-mix(in oklch, var(--widget-icon-color, var(--widget-color)) 50%, transparent);\n color: oklch(from var(--widget-icon-color, var(--widget-color)) calc(0.52 + sign(0.5 - l) * 0.43) calc(c * 0.2) h);\n}\n.glasshome-widget-icon-glyph {\n font-size: var(--widget-icon-glyph);\n line-height: 1;\n}\n.glasshome-widget-icon-stack {\n position: absolute;\n width: 102%;\n height: 102%;\n border-radius: var(--radius-sm, 12px);\n}\n.glasshome-widget-icon-stack-2 { bottom: -14%; right: -10%; opacity: 0.45; z-index: -2; }\n.glasshome-widget-icon-stack-3 { bottom: -28%; right: -20%; opacity: 0.20; z-index: -3; }\n\n/* === Slot: text === */\n.glasshome-widget-title {\n font-size: var(--widget-title-size);\n line-height: 1.2;\n color: var(--color-muted-foreground, currentColor);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.glasshome-widget-subtitle {\n font-size: var(--widget-subtitle);\n color: var(--color-muted-foreground, currentColor);\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 round var(--widget-radius));\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 round var(--widget-radius));\n }\n}\n", wt = !1, Tt, Et = /* @__PURE__ */ new WeakSet();
90
- function Dt() {
91
- return Tt || (Tt = new CSSStyleSheet(), Tt.replaceSync(Ct.replace(/:root\b/g, ":host").replace(/^\.dark\b/gm, ":host(.dark)"))), Tt;
709
+ var $n = "/* 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-glow-default: 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-glow-default: 0.5;\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 * One scale: --widget-unit is 1% of the shell's short side. Each size is a floor,\n * a line through the designed 2x2 and 4x4 sizes, and past 4x4 the share it has\n * at 4x4. A widget sizes its own text with these tokens and scales with every tile. */\n.glasshome-widget {\n --widget-color: var(--tone-neutral);\n --widget-glow-strength: var(--widget-glow-default);\n --widget-radius: var(--radius-xl, 12px);\n\n --widget-unit: 1cqmin;\n --widget-text-value: max(22px, calc(8.5px + 13.4 * var(--widget-unit)), calc(16 * var(--widget-unit)));\n --widget-text-name: max(14px, calc(8.9px + 4.37 * var(--widget-unit)), calc(7.07 * var(--widget-unit)));\n --widget-text-meta: max(11px, calc(8px + 2.44 * var(--widget-unit)), calc(4.88 * var(--widget-unit)));\n --widget-text-sub: max(12px, calc(10.1px + 1.22 * var(--widget-unit)), calc(4.3 * var(--widget-unit)));\n --widget-text-caption: max(11px, calc(3.6 * var(--widget-unit)));\n --widget-control-h: max(36px, calc(30px + 3.84 * var(--widget-unit)));\n --widget-grid-pad: max(10px, calc(1.2px + 5.64 * var(--widget-unit)), calc(6 * var(--widget-unit)));\n --widget-grid-gap: max(6px, calc(2.5px + 2.23 * var(--widget-unit)));\n --widget-icon-box: max(44px, calc(31.3px + 8.14 * var(--widget-unit)), calc(17.7 * var(--widget-unit)));\n --widget-icon-glyph: max(24px, calc(16px + 5.12 * var(--widget-unit)), calc(10 * var(--widget-unit)));\n --widget-pad: clamp(8px, 3.5cqb, 22px);\n --widget-gap: clamp(6px, 2cqb, 14px);\n --widget-title-size: clamp(12px, 2cqi, 18px);\n --widget-subtitle: clamp(12px, 2.5cqi, 20px);\n --widget-status-size: clamp(14px, 5cqi, 36px);\n --widget-value-size: clamp(18px, 7cqi, 48px);\n --widget-badge-size: clamp(11px, 1.6cqi, 14px);\n}\n\n/* Shell material: ui's .glass, worn through the class Widget.tsx carries.\n * Unlayered and class-specific, so these beat the formula's :where() defaults\n * (wash-2 is re-declared there and cannot be set from a utility). The tone\n * stays the formula's transparent default until Widget.tsx sets one inline:\n * a widget without a tone is the plain card, never a neutral-grey wash. */\n.glasshome-widget {\n --widget-wash: 22%;\n --widget-wash-2: 11%;\n --glass-wash: var(--widget-wash);\n --glass-wash-2: var(--widget-wash-2);\n --glass-wash-angle: 135deg;\n --glass-base: color-mix(in srgb, var(--card) var(--material-clarity, 60%), transparent);\n --glass-rim: 0.3;\n --glass-lift: 0.45;\n --glass-shade: 0.05;\n backdrop-filter: var(--widget-backdrop, none);\n -webkit-backdrop-filter: var(--widget-backdrop, none);\n}\n/* A fill widget keeps a neutral card; the fill carries the tone, so a full fill is the toned card. */\n.glasshome-widget:has(.glasshome-widget-slider-fill) {\n --glass-wash: 0%;\n --glass-wash-2: 0%;\n}\n.dark .glasshome-widget {\n --glass-shade: 0;\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 border-radius: var(--widget-radius);\n}\n@container widget (min-aspect-ratio: 1) and (max-height: 149px) {\n .glasshome-widget-content {\n flex-direction: row;\n align-items: center;\n justify-content: flex-start;\n }\n}\n\n/* === Compact 1×1 ===\n * Small in BOTH axes → stack the tile: icon on top, label + status centered\n * under it. Icon stays moderate (not a hero) so the text keeps room. Wide\n * tiles (2×1) fail the width test and keep the row layout above. Placed after\n * the row-flip so it wins. */\n@container widget (max-width: 189px) and (max-height: 189px) {\n .glasshome-widget-content {\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n gap: clamp(4px, 2.5cqmin, 8px);\n }\n .glasshome-widget-content > * { align-items: center; text-align: center; }\n .glasshome-widget-icon {\n --widget-icon-box: clamp(36px, 30cqmin, 56px);\n --widget-icon-glyph: clamp(20px, 17cqmin, 32px);\n }\n .glasshome-widget-title { font-size: clamp(11px, 6cqmin, 14px); max-width: 100%; }\n .glasshome-widget-status,\n .glasshome-widget-value { font-size: clamp(13px, 7cqmin, 17px); }\n .glasshome-widget-content [class*=\"ml-auto\"] { margin-left: 0 !important; }\n}\n.glasshome-widget-content [class*=\"ml-auto\"] {\n position: relative;\n z-index: 30;\n}\n\n/* === Slot: icon ===\n * ui's tinted icon pill (ICON_PILL_TINT): the disc is .glass, so the material shapes it. */\n.glasshome-widget-icon {\n width: var(--widget-icon-box);\n height: var(--widget-icon-box);\n border-radius: var(--radius-sm, 12px);\n --glass-tone: var(--widget-icon-color, var(--widget-color));\n --glass-rim: 0.4;\n --glass-wash: 18%;\n}\n.glasshome-widget-icon-glyph {\n font-size: var(--widget-icon-glyph);\n line-height: 1;\n}\n.glasshome-widget-icon-stack {\n --stack-step: calc(var(--widget-icon-box) * 0.12);\n position: absolute;\n /* The pill's border would otherwise shrink each plate and widen the first step. */\n inset: -1px;\n width: auto;\n height: auto;\n border-radius: var(--radius-sm, 12px);\n}\n.glasshome-widget-icon-stack-2 { translate: var(--stack-step) var(--stack-step); opacity: 0.45; z-index: -2; }\n.glasshome-widget-icon-stack-3 { translate: calc(2 * var(--stack-step)) calc(2 * var(--stack-step)); opacity: 0.2; 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: var(--color-muted-foreground, currentColor);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.glasshome-widget-subtitle {\n font-size: var(--widget-subtitle);\n color: var(--color-muted-foreground, currentColor);\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: linear-gradient(\n 135deg,\n color-mix(in srgb, var(--widget-color) calc(var(--widget-wash) * var(--material-tint, 1)), transparent),\n color-mix(\n in srgb,\n var(--widget-color-to, var(--widget-color)) calc(var(--widget-wash-2) * var(--material-tint, 1)),\n transparent\n )\n );\n /* Inset: the clip-path cuts any outer shadow. */\n box-shadow: inset 0 0 calc(var(--material-glow, 0px) * 1.2)\n oklch(from var(--widget-color) l c h / 0.55);\n clip-path: inset(0 calc((100 - var(--widget-fill-value)) * 1%) 0 0 round var(--widget-radius));\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 round var(--widget-radius));\n }\n}\n\n/* === Anatomy: Widget.Content with a Widget.Head lays its parts out as a tile === */\n.glasshome-widget-grid {\n position: relative;\n display: grid;\n grid-template-columns: max-content minmax(0, 1fr);\n grid-template-rows: auto minmax(0, 1fr) auto;\n gap: var(--widget-grid-gap);\n height: 100%;\n padding: var(--widget-grid-pad);\n overflow: hidden;\n isolation: isolate;\n color: var(--foreground);\n}\n\n/* In-flow content spans the tile (the max-content first column would collapse it); absolute parts keep the padding box. */\n.glasshome-widget-grid > :where(:not(.glasshome-widget-backdrop, .glasshome-widget-layer, .glasshome-widget-glyph)) {\n grid-column: 1 / -1;\n}\n.glasshome-widget-layer {\n position: absolute;\n inset: 0;\n z-index: -1;\n overflow: hidden;\n}\n.glasshome-widget-head {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n min-width: 0;\n}\n.glasshome-widget-head-text {\n min-height: var(--widget-icon-box);\n justify-content: center;\n display: flex;\n flex-direction: column;\n gap: 1px;\n min-width: 0;\n flex: 1;\n}\n.glasshome-widget-head-aside {\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-end;\n gap: 6px;\n max-height: 26px;\n overflow: hidden;\n flex-shrink: 1;\n}\n.glasshome-widget-eyebrow {\n font-size: var(--widget-text-meta);\n font-weight: 500;\n line-height: 1.25;\n color: var(--muted-foreground);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.glasshome-widget-name {\n font-size: var(--widget-text-name);\n font-weight: 650;\n line-height: 1.2;\n letter-spacing: -0.01em;\n color: var(--foreground);\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n overflow: hidden;\n overflow-wrap: break-word;\n}\n\n.glasshome-widget-hero {\n display: flex;\n align-items: flex-end;\n justify-content: space-between;\n gap: var(--widget-grid-gap);\n min-height: 0;\n min-width: 0;\n}\n.glasshome-widget-reading {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n z-index: 1;\n}\n.glasshome-widget-reading-value {\n font-size: var(--widget-text-value);\n font-weight: 650;\n line-height: 1;\n letter-spacing: -0.03em;\n font-variant-numeric: tabular-nums;\n color: var(--foreground);\n white-space: nowrap;\n}\n/* Alternating names restart the rise on each change without rebuilding the text. */\n.glasshome-widget-reading-value[data-turn=\"a\"] {\n animation: tile-value-in-a var(--duration-morph) var(--ease-morph);\n}\n.glasshome-widget-reading-value[data-turn=\"b\"] {\n animation: tile-value-in-b var(--duration-morph) var(--ease-morph);\n}\n@keyframes tile-value-in-a {\n from {\n opacity: 0;\n transform: translateY(0.25em);\n }\n}\n@keyframes tile-value-in-b {\n from {\n opacity: 0;\n transform: translateY(0.25em);\n }\n}\n.glasshome-widget-unit {\n font-size: 0.5em;\n font-weight: 550;\n letter-spacing: 0;\n margin-left: 0.08em;\n color: var(--muted-foreground);\n}\n.glasshome-widget-sub {\n font-size: var(--widget-text-sub);\n font-weight: 500;\n color: var(--muted-foreground);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* Placed on the tile, not the hero, so a control row never moves or shrinks it. */\n.glasshome-widget-art {\n position: absolute;\n right: var(--widget-grid-pad);\n bottom: var(--widget-grid-pad);\n height: min(calc(100% - 2 * var(--widget-grid-pad) - var(--widget-icon-box) - var(--widget-grid-gap)), 48cqi);\n display: flex;\n align-items: flex-end;\n justify-content: flex-end;\n pointer-events: none;\n}\n/* Beside art a long word (\"Unlocked\") shrinks to end where the art starts, at about 50cqi; short values keep full size. */\n@container widget (min-width: 180px) and (min-height: 130px) {\n .glasshome-widget-hero[data-art] .glasshome-widget-reading-value {\n font-size: max(18px, min(var(--widget-text-value), calc(50cqi / (var(--value-len, 1) * 0.56))));\n }\n}\n.glasshome-widget-backdrop > img {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n/* Art keeps its shape and clears a state word at its largest (15cqi, about 3.4em); each art sets --art-aspect. */\n.glasshome-widget-grid .glasshome-widget-art > * {\n height: min(100%, calc((52cqi - 2 * var(--widget-grid-pad) - var(--widget-grid-gap)) / var(--art-aspect, 1)));\n flex-shrink: 0;\n}\n.glasshome-widget-grid .glasshome-widget-art > img {\n width: auto;\n height: auto;\n max-height: 100%;\n max-width: calc(52cqi - 2 * var(--widget-grid-pad) - var(--widget-grid-gap));\n}\n\n.glasshome-widget-controls {\n display: flex;\n gap: 8px;\n min-width: 0;\n}\n\n.glasshome-widget-glyph {\n display: none;\n position: absolute;\n right: -8%;\n bottom: -22%;\n font-size: min(130cqb, 80cqi);\n line-height: 1;\n color: var(--widget-color);\n opacity: 0.16;\n pointer-events: none;\n z-index: -1;\n}\n\n/* Controls sit on the bottom row beside the value, or under it on a narrow tile; the art lifts above them. */\n.glasshome-widget-head {\n grid-column: 1 / -1;\n}\n.glasshome-widget-hero {\n grid-row: 3;\n grid-column: 1 / -1;\n}\n.glasshome-widget-grid:has(> .glasshome-widget-controls) > .glasshome-widget-hero {\n grid-column: 1;\n}\n.glasshome-widget-controls {\n grid-row: 3;\n grid-column: 2;\n align-self: end;\n position: relative;\n z-index: 1;\n}\n.glasshome-widget-grid:has(> .glasshome-widget-hero[data-empty]) > .glasshome-widget-controls {\n grid-column: 1 / -1;\n}\n@container widget (max-width: 519px) {\n .glasshome-widget-grid:has(> .glasshome-widget-controls) {\n grid-template-rows: auto minmax(0, 1fr) auto auto;\n }\n .glasshome-widget-grid:has(> .glasshome-widget-controls) > .glasshome-widget-hero {\n grid-column: 1 / -1;\n }\n .glasshome-widget-controls {\n grid-row: 4;\n grid-column: 1 / -1;\n }\n .glasshome-widget-grid:has(> .glasshome-widget-controls) .glasshome-widget-art {\n bottom: calc(var(--widget-grid-pad) + var(--widget-control-h) + var(--widget-grid-gap));\n height: min(\n calc(\n 100% -\n 2 *\n var(--widget-grid-pad) -\n var(--widget-icon-box) -\n 2 *\n var(--widget-grid-gap) -\n var(--widget-control-h)\n ),\n 48cqi\n );\n }\n}\n@container widget (max-height: 229px) {\n .glasshome-widget-controls {\n display: none;\n }\n .glasshome-widget-grid:has(> .glasshome-widget-controls) {\n grid-template-rows: auto minmax(0, 1fr) auto;\n }\n .glasshome-widget-grid:has(> .glasshome-widget-controls) .glasshome-widget-art {\n bottom: var(--widget-grid-pad);\n height: min(calc(100% - 2 * var(--widget-grid-pad) - var(--widget-icon-box) - var(--widget-grid-gap)), 48cqi);\n }\n}\n@container widget (max-width: 179px) {\n .glasshome-widget-art {\n display: none;\n }\n}\n@container widget (max-height: 169px) {\n .glasshome-widget-head-aside {\n display: none;\n }\n}\n@container widget ((max-height: 129px) or (max-width: 139px)) {\n .glasshome-widget-head-text {\n min-height: 0;\n }\n .glasshome-widget-name {\n -webkit-line-clamp: 1;\n }\n .glasshome-widget-grid {\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n gap: 2px;\n }\n .glasshome-widget-head-icon,\n .glasshome-widget-art,\n .glasshome-widget-eyebrow,\n .glasshome-widget-sub {\n display: none;\n }\n .glasshome-widget-glyph {\n display: block;\n }\n .glasshome-widget-reading-value {\n font-size: clamp(18px, min(34cqb, 20cqi), 30px);\n }\n .glasshome-widget-name {\n font-size: clamp(12px, min(18cqb, 11cqi), 15px);\n font-weight: 550;\n color: var(--muted-foreground);\n }\n}\n@container widget (max-height: 129px) and (min-width: 260px) {\n .glasshome-widget-grid {\n flex-direction: row;\n align-items: center;\n justify-content: space-between;\n gap: var(--widget-grid-gap);\n }\n .glasshome-widget-name {\n font-size: clamp(14px, 22cqb, 18px);\n font-weight: 650;\n color: var(--foreground);\n }\n .glasshome-widget-eyebrow {\n display: block;\n }\n}\n\n.glasshome-widget-backdrop {\n position: absolute;\n inset: 0;\n z-index: -2;\n overflow: hidden;\n}\n.glasshome-widget-backdrop > img.area-night {\n opacity: 0;\n transition: opacity 700ms ease;\n}\n.glasshome-widget-backdrop > img.area-night[data-visible] {\n opacity: 1;\n}\n.glasshome-widget-backdrop > .glasshome-widget-backdrop-light {\n position: absolute;\n inset: 0;\n background: radial-gradient(90% 80% at 25% 30%, oklch(0.8 0.14 70), transparent 70%);\n mix-blend-mode: soft-light;\n opacity: var(--backdrop-light, 0);\n transition: opacity 500ms ease;\n}\n.glasshome-widget-backdrop::after {\n content: \"\";\n position: absolute;\n inset: 0;\n background: linear-gradient(\n to bottom,\n color-mix(in oklch, var(--card) 82%, transparent) 0%,\n color-mix(in oklch, var(--card) 40%, transparent) 22%,\n transparent 42%,\n transparent 62%,\n color-mix(in oklch, var(--card) 45%, transparent) 82%,\n color-mix(in oklch, var(--card) 80%, transparent) 100%\n );\n}\n\n@container widget (max-width: 239px) {\n .glasshome-widget-choice [data-optional] {\n display: none;\n }\n}\n@container widget (max-width: 259px) {\n .glasshome-widget-head-aside {\n display: none;\n }\n}\n@container widget (max-width: 139px) {\n .glasshome-widget-controls {\n display: none;\n }\n}\n\n.glasshome-widget-controls {\n justify-content: flex-start;\n align-items: center;\n}\n.glasshome-widget-control.glasshome-widget-control {\n width: var(--widget-control-h);\n height: var(--widget-control-h);\n}\n.glasshome-widget-choice .glasshome-widget-control.glasshome-widget-control {\n width: calc(var(--widget-control-h) - 8px);\n height: calc(var(--widget-control-h) - 8px);\n}\n@container widget (max-width: 179px) and (min-height: 130px) {\n .glasshome-widget-grid:not(:has(> .glasshome-widget-backdrop)) .glasshome-widget-head-text {\n min-height: 0;\n }\n .glasshome-widget-grid:not(:has(> .glasshome-widget-backdrop)) .glasshome-widget-head {\n flex-direction: column;\n gap: 6px;\n }\n}\n.glasshome-widget-unit[data-degree] {\n vertical-align: top;\n margin-left: 0.02em;\n color: var(--foreground);\n}\n.glasshome-widget-control-wide.glasshome-widget-control-wide {\n height: var(--widget-control-h);\n gap: 6px;\n padding: 0 14px;\n}\n@container widget (max-width: 179px) {\n .glasshome-widget-grid:has(> .glasshome-widget-backdrop) .glasshome-widget-head-icon {\n display: none;\n }\n}\n.glasshome-widget-grid:has(> .glasshome-widget-backdrop) :is(.glasshome-widget-reading-value, .glasshome-widget-sub, .glasshome-widget-name, .glasshome-widget-eyebrow) {\n text-shadow: 0 1px 8px color-mix(in oklch, var(--card) 75%, transparent);\n}\n.glasshome-widget-grid:has(> .glasshome-widget-backdrop) :is(.glasshome-widget-sub, .glasshome-widget-eyebrow) {\n color: color-mix(in oklch, var(--foreground) 82%, transparent);\n}\n/* Control glyphs and words keep their share of a control as it grows past 4x4. */\n.glasshome-widget-grid :is(.glasshome-widget-control, .glasshome-widget-control-wide) :is(iconify-icon, svg) {\n font-size: calc(var(--widget-control-h) * 0.43);\n width: 1em;\n height: 1em;\n}\n:is(.glasshome-widget-controls, .glasshome-widget-control-wide) {\n font-size: max(13px, calc(var(--widget-control-h) * 0.3));\n}\n/* A big tile with no art of its own carries its icon large and faint, so the glass is not an empty box. */\n@container widget (min-width: 300px) and (min-height: 260px) {\n .glasshome-widget-grid:not(:has(> .glasshome-widget-backdrop), :has(> .glasshome-widget-hero[data-art], > .glasshome-widget-art, > .glasshome-widget-layer))\n > .glasshome-widget-glyph {\n display: block;\n right: -3%;\n bottom: -12%;\n font-size: min(78cqb, 52cqi);\n opacity: 0.1;\n }\n}\n/* A one-shot action confirms on its control and on the glyph, the one thing a compact tile shows. */\n.glasshome-widget-grid > .glasshome-widget-glyph {\n transition: opacity var(--duration-state) var(--ease-morph);\n}\n.glasshome-widget[data-confirmed] .glasshome-widget-glyph {\n opacity: 0.5;\n}\n.glasshome-widget-grid [data-confirmed]:is(.glasshome-widget-control, .glasshome-widget-control-wide) {\n --glass-base: color-mix(in srgb, var(--widget-color) 35%, transparent);\n transition: background-color var(--duration-state) var(--ease-morph);\n}\n\n/* === Sheet: what a held tile opens (framework/panel) ===\n * Rendered in a popover or dialog outside the widget's shadow root, so every rule\n * the sheet needs lives here, never in a widget's own utilities. */\n.glasshome-sheet {\n display: flex;\n flex-direction: column;\n gap: 18px;\n color: var(--foreground);\n}\n.glasshome-sheet [data-slot=\"swatch-picker\"] {\n max-width: 360px;\n}\n.glasshome-panel-section {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n.glasshome-panel-label {\n margin: 0;\n font-size: 13px;\n font-weight: 500;\n color: var(--muted-foreground);\n}\n.glasshome-panel-rows {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 8px;\n}\n.glasshome-panel-row-wrap {\n position: relative;\n min-width: 0;\n}\n.glasshome-panel-row {\n --widget-wash: 22%;\n --widget-wash-2: 11%;\n --widget-radius: var(--radius-lg, 16px);\n --widget-icon-box: 34px;\n --widget-icon-glyph: 19px;\n position: relative;\n width: 100%;\n height: 56px;\n justify-content: flex-start;\n gap: 10px;\n padding: 0 12px 0 10px;\n overflow: hidden;\n text-align: left;\n touch-action: pan-y;\n}\n.glasshome-panel-row-static {\n cursor: default;\n scale: none;\n}\n.glasshome-panel-row-fill {\n position: absolute;\n inset: 0;\n pointer-events: none;\n}\n.glasshome-panel-row-icon {\n position: relative;\n display: flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n}\n.glasshome-panel-row-icon-off {\n color: var(--muted-foreground);\n}\n.glasshome-panel-row-text {\n position: relative;\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n.glasshome-panel-row-name,\n.glasshome-panel-row-state,\n.glasshome-panel-fact-label {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n/* A reading may take a second line rather than lose its end (\"3 Moderate\"). */\n.glasshome-panel-fact-value {\n overflow: hidden;\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n}\n.glasshome-panel-row-name,\n.glasshome-panel-fact-value {\n font-size: 14px;\n font-weight: 500;\n color: var(--foreground);\n}\n.glasshome-panel-row-state,\n.glasshome-panel-fact-label {\n font-size: 12px;\n font-weight: 400;\n color: var(--muted-foreground);\n}\n.glasshome-panel-row-trailing {\n position: absolute;\n top: 50%;\n right: 10px;\n translate: 0 -50%;\n}\n.glasshome-panel-facts {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));\n row-gap: 10px;\n padding: 10px 4px 10px 0;\n overflow: hidden;\n border-radius: var(--radius-lg, 16px);\n --glass-base: color-mix(in srgb, var(--card) var(--material-clarity, 60%), transparent);\n backdrop-filter: blur(calc(var(--material-blur, 24px) * 0.6)) saturate(1.6);\n -webkit-backdrop-filter: blur(calc(var(--material-blur, 24px) * 0.6)) saturate(1.6);\n}\n/* Without blur a see-through strip is just see-through: it takes the card fill. */\n.reduce-blur .glasshome-panel-facts {\n --glass-base: var(--card);\n}\n.glasshome-panel-fact {\n display: flex;\n min-width: 0;\n align-items: center;\n gap: 8px;\n padding: 0 12px;\n box-shadow: -1px 0 0 color-mix(in oklch, var(--foreground) 10%, transparent);\n}\n.glasshome-panel-fact-icon {\n flex-shrink: 0;\n font-size: 18px;\n color: var(--muted-foreground);\n}\n\n/* Inset: the grid cell clips anything drawn outside the tile. */\n.glasshome-widget:focus-visible {\n outline: 2px solid var(--ring);\n outline-offset: -2px;\n}\n\n/* === Hold flood: the dock's hold fill (ui HOLD_MOTION), grown from the finger === */\n.glasshome-widget-hold-flood {\n position: absolute;\n translate: -50% -50%;\n border-radius: 9999px;\n background: color-mix(in oklch, var(--primary) 45%, transparent);\n pointer-events: none;\n scale: 0;\n opacity: 0;\n transition:\n scale var(--duration-state, 200ms) var(--ease-contract, ease-in),\n opacity var(--duration-state, 200ms) var(--ease-contract, ease-in);\n}\n.glasshome-widget-hold-flood[data-hold] {\n scale: 1;\n opacity: 1;\n transition-duration: var(--duration-morph, 400ms);\n transition-timing-function: linear;\n}\n.glasshome-widget-hold-flood[data-fired] {\n scale: 1;\n opacity: 0;\n}\n/* A row of ui buttons in a sheet (scenes, one-tap actions). */\n.glasshome-sheet-actions {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n/* The sheet wears its tile: the tile's tone washed into the glass, its picture as a band behind\n the head that fades into the glass, so the tile reads as having grown open. */\n.glasshome-sheet-surface {\n --glass-wash: 20%;\n --glass-wash-2: 7%;\n --widget-icon-box: 48px;\n --widget-icon-glyph: 26px;\n}\n.glasshome-sheet-band {\n position: absolute;\n inset: 0 0 auto;\n height: 150px;\n overflow: hidden;\n pointer-events: none;\n mask-image: linear-gradient(180deg, #000 30%, transparent);\n}\n.glasshome-sheet-band > img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n opacity: 0.55;\n}\n.glasshome-sheet-surface > [data-slot$=\"-header\"],\n.glasshome-sheet-surface > [data-slot$=\"-body\"] {\n position: relative;\n}\n.glasshome-sheet-icon {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n", er = !1, tr, nr = /* @__PURE__ */ new WeakSet();
710
+ function rr() {
711
+ return tr || (tr = new CSSStyleSheet(), tr.replaceSync($n.replace(/:root\b/g, ":host").replace(/^\.dark\b/gm, ":host(.dark)"))), tr;
92
712
  }
93
- function Ot(e) {
713
+ function ir(e) {
94
714
  if (typeof ShadowRoot < "u" && e instanceof ShadowRoot) {
95
- if (Et.has(e)) return;
96
- let t = Dt();
97
- e.adoptedStyleSheets.includes(t) || (e.adoptedStyleSheets = [...e.adoptedStyleSheets, t]), Et.add(e);
715
+ if (nr.has(e)) return;
716
+ let t = rr();
717
+ e.adoptedStyleSheets.includes(t) || (e.adoptedStyleSheets = [...e.adoptedStyleSheets, t]), nr.add(e);
98
718
  return;
99
719
  }
100
- if (wt) return;
720
+ if (er) return;
101
721
  let t = e ?? (typeof document > "u" ? void 0 : document);
102
722
  if (!t) return;
103
723
  if (t.head.querySelector?.("style[data-glasshome-tokens]")) {
104
- wt = !0;
724
+ er = !0;
105
725
  return;
106
726
  }
107
727
  let n = t.createElement("style");
108
- n.setAttribute("data-glasshome-tokens", ""), n.textContent = Ct, t.head.appendChild(n), wt = !0;
109
- }
110
- //#endregion
111
- //#region src/framework/utils/cn.ts
112
- function V(...e) {
113
- return be(ye(e));
728
+ n.setAttribute("data-glasshome-tokens", ""), n.textContent = $n, t.head.appendChild(n), er = !0;
114
729
  }
115
- var kt = {
730
+ var ar = {
116
731
  "classic-glass": {
117
732
  id: "classic-glass",
118
733
  name: "Classic Glass",
119
734
  description: "Default glassmorphism design with blur background and gradient",
120
735
  styles: { cssVars: {
121
- "--widget-bg": "rgba(255, 255, 255, 0.1)",
122
- "--widget-border": "rgba(255, 255, 255, 0.2)",
123
- "--widget-blur": "12px",
124
- "--widget-shadow": "0 8px 32px rgba(0, 0, 0, 0.2)",
125
736
  "--widget-padding": "1.5rem",
126
- "--widget-backdrop": "blur(var(--glass-blur, 24px)) saturate(1.8)"
737
+ "--widget-backdrop": "blur(var(--glass-blur, var(--material-blur, 24px))) saturate(1.8)"
127
738
  } },
128
739
  layout: {
129
740
  type: "flex",
@@ -145,9 +756,13 @@ var kt = {
145
756
  name: "Minimal",
146
757
  description: "Clean, minimal design with no background effects",
147
758
  styles: { cssVars: {
148
- "--widget-bg": "transparent",
149
- "--widget-border": "rgba(255, 255, 255, 0.1)",
150
- "--widget-padding": "1rem"
759
+ "--widget-padding": "1rem",
760
+ "--glass-base": "transparent",
761
+ "--glass-wash": "0%",
762
+ "--glass-light": "0",
763
+ "--glass-rim": "0",
764
+ "--glass-lift": "0",
765
+ "--glass-edge": "transparent"
151
766
  } },
152
767
  layout: {
153
768
  type: "flex",
@@ -171,9 +786,6 @@ var kt = {
171
786
  name: "Compact Horizontal",
172
787
  description: "Horizontal layout for compact widgets",
173
788
  styles: { cssVars: {
174
- "--widget-bg": "rgba(255, 255, 255, 0.08)",
175
- "--widget-border": "rgba(255, 255, 255, 0.15)",
176
- "--widget-blur": "10px",
177
789
  "--widget-padding": "1rem",
178
790
  "--widget-icon-size": "2.5rem",
179
791
  "--widget-backdrop": "blur(16px) saturate(1.8)"
@@ -194,22 +806,21 @@ var kt = {
194
806
  }
195
807
  }
196
808
  };
197
- function At(e) {
198
- return kt[e];
809
+ function or(e) {
810
+ return ar[e];
199
811
  }
200
812
  //#endregion
201
813
  //#region src/framework/backgrounds/WidgetSliderFill.tsx
202
- var jt = /*#__PURE__*/ L("<div>");
203
- function Mt(e) {
204
- return (() => {
205
- var t = jt();
206
- return N((n) => {
207
- var r = V("glasshome-widget-slider-fill pointer-events-none absolute inset-0", e.isDragging ? "duration-0" : "transition-all duration-300 ease-out", e.class), i = {
814
+ var sr = /*#__PURE__*/ B("<div>"), cr = e(() => void 0, "sliderFill.color");
815
+ function lr(e) {
816
+ return e.color !== void 0 && cr(), (() => {
817
+ var t = sr();
818
+ return P((n) => {
819
+ var r = X("glasshome-widget-slider-fill pointer-events-none absolute inset-0", e.isDragging ? "duration-0" : "transition-all duration-300 ease-out", e.class), i = {
208
820
  "--widget-fill-value": e.value,
209
- "z-index": B.BACKGROUND,
210
- ...e.color ? { "--widget-icon-color": e.color } : {}
821
+ "z-index": K.BACKGROUND
211
822
  };
212
- return r !== n.e && j(t, n.e = r), n.t = _e(t, i, n.t), n;
823
+ return r !== n.e && M(t, n.e = r), n.t = z(t, i, n.t), n;
213
824
  }, {
214
825
  e: void 0,
215
826
  t: void 0
@@ -218,55 +829,34 @@ function Mt(e) {
218
829
  }
219
830
  //#endregion
220
831
  //#region src/framework/components/WidgetContent.tsx
221
- var Nt = /*#__PURE__*/ L("<div>");
222
- function Pt(e) {
223
- return (() => {
224
- var t = Nt();
225
- return P(t, () => e.children), N(() => j(t, V("glasshome-widget-content", e.class))), t;
226
- })();
227
- }
228
- //#endregion
229
- //#region src/framework/components/WidgetIcon.tsx
230
- var Ft = /*#__PURE__*/ L("<div class=\"glasshome-widget-icon glasshome-widget-icon-stack glasshome-widget-icon-stack-2\">"), It = /*#__PURE__*/ L("<div class=\"glasshome-widget-icon glasshome-widget-icon-stack glasshome-widget-icon-stack-3\">"), Lt = /*#__PURE__*/ L("<div><div class=\"glasshome-widget-icon-glyph flex items-center justify-center\">");
231
- function Rt(e) {
232
- let t = () => e.entityCount ?? 1;
832
+ var ur = /*#__PURE__*/ B("<div>"), dr = /\bglasshome-widget-(head|hero|controls|backdrop|glyph|layer)\b/;
833
+ function fr(e) {
834
+ let t = rn(A(W));
835
+ E(() => t?.setAccent(e.accent)), k(() => t?.setAccent(void 0));
836
+ let n = T(() => e.children), r = D(() => n.toArray().some((e) => e instanceof Element && dr.test(e.className)));
233
837
  return (() => {
234
- var n = Lt(), r = n.firstChild;
235
- return P(n, M(T, {
236
- get when() {
237
- return t() >= 2;
238
- },
239
- get children() {
240
- return Ft();
241
- }
242
- }), r), P(n, M(T, {
243
- get when() {
244
- return t() >= 3;
245
- },
246
- get children() {
247
- return It();
248
- }
249
- }), r), P(r, () => e.icon), N((t) => {
250
- var r = V("glasshome-widget-icon", "relative flex shrink-0 items-center justify-center pointer-events-none transition-all", e.dimmed && "opacity-50", e.class), i = e.color ? { "--widget-icon-color": e.color } : void 0;
251
- return r !== t.e && j(n, t.e = r), t.t = _e(n, i, t.t), t;
838
+ var t = ur();
839
+ return F(t, n), P((n) => {
840
+ var i = X(r() ? "glasshome-widget-grid" : "glasshome-widget-content", e.class), a = e.accent ? { "--widget-color": e.accent } : void 0;
841
+ return i !== n.e && M(t, n.e = i), n.t = z(t, a, n.t), n;
252
842
  }, {
253
843
  e: void 0,
254
844
  t: void 0
255
- }), n;
845
+ }), t;
256
846
  })();
257
847
  }
258
848
  //#endregion
259
849
  //#region src/framework/components/WidgetStatus.tsx
260
- var zt = /*#__PURE__*/ L("<p>");
261
- function Bt(e) {
850
+ var pr = /*#__PURE__*/ B("<p>");
851
+ function mr(e) {
262
852
  return (() => {
263
- var t = zt();
264
- return P(t, (() => {
265
- var t = F(() => !!e.isUnavailable);
853
+ var t = pr();
854
+ return F(t, (() => {
855
+ var t = I(() => !!e.isUnavailable);
266
856
  return () => t() ? "Unavailable" : e.children;
267
- })()), N((n) => {
268
- var r = V("glasshome-widget-status", "relative", e.dimmed && "opacity-40", e.class), i = B.ACTIONS;
269
- return r !== n.e && j(t, n.e = r), i !== n.t && I(t, "z-index", n.t = i), n;
857
+ })()), P((n) => {
858
+ var r = X("glasshome-widget-status", "relative", e.dimmed && "opacity-40", e.class), i = K.ACTIONS;
859
+ return r !== n.e && M(t, n.e = r), i !== n.t && R(t, "z-index", n.t = i), n;
270
860
  }, {
271
861
  e: void 0,
272
862
  t: void 0
@@ -275,21 +865,21 @@ function Bt(e) {
275
865
  }
276
866
  //#endregion
277
867
  //#region src/framework/components/WidgetTitle.tsx
278
- var Vt = /*#__PURE__*/ L("<span class=\"glasshome-widget-badge shrink-0\">"), Ht = /*#__PURE__*/ L("<div><h3 class=glasshome-widget-title>");
279
- function Ut(e) {
868
+ var hr = /*#__PURE__*/ B("<span class=\"glasshome-widget-badge shrink-0\">"), gr = /*#__PURE__*/ B("<div><h3 class=glasshome-widget-title>");
869
+ function _r(e) {
280
870
  return (() => {
281
- var t = Ht(), n = t.firstChild;
282
- return P(n, () => e.children), P(t, M(T, {
871
+ var t = gr(), n = t.firstChild;
872
+ return F(n, () => e.children), F(t, N(w, {
283
873
  get when() {
284
- return F(() => e.badge !== void 0)() && e.badge > 0;
874
+ return I(() => e.badge !== void 0)() && e.badge > 0;
285
875
  },
286
876
  get children() {
287
- var t = Vt();
288
- return P(t, () => e.badge), t;
877
+ var t = hr();
878
+ return F(t, () => e.badge), t;
289
879
  }
290
- }), null), N((n) => {
291
- var r = V("relative flex items-center gap-2", e.class), i = B.ACTIONS;
292
- return r !== n.e && j(t, n.e = r), i !== n.t && I(t, "z-index", n.t = i), n;
880
+ }), null), P((n) => {
881
+ var r = X("relative flex items-center gap-2", e.class), i = K.ACTIONS;
882
+ return r !== n.e && M(t, n.e = r), i !== n.t && R(t, "z-index", n.t = i), n;
293
883
  }, {
294
884
  e: void 0,
295
885
  t: void 0
@@ -297,8 +887,41 @@ function Ut(e) {
297
887
  })();
298
888
  }
299
889
  //#endregion
890
+ //#region src/framework/utils/clipboard.ts
891
+ async function vr(e) {
892
+ if (navigator.clipboard?.writeText) try {
893
+ return await navigator.clipboard.writeText(e), !0;
894
+ } catch {}
895
+ return yr(e);
896
+ }
897
+ function yr(e) {
898
+ let t = br(), n = document.createElement("textarea");
899
+ n.value = e, n.setAttribute("readonly", ""), n.style.position = "fixed", n.style.top = "0", n.style.left = "0", n.style.opacity = "0", (t?.parentElement ?? document.body).append(n);
900
+ try {
901
+ return n.focus(), n.select(), n.setSelectionRange(0, e.length), n.getRootNode().activeElement === n && document.execCommand("copy");
902
+ } catch {
903
+ return !1;
904
+ } finally {
905
+ n.remove(), t?.focus();
906
+ }
907
+ }
908
+ function br() {
909
+ let e = document.activeElement;
910
+ for (; e?.shadowRoot?.activeElement;) e = e.shadowRoot.activeElement;
911
+ return e instanceof HTMLElement ? e : null;
912
+ }
913
+ function xr(e = 2e3) {
914
+ let [t, n] = O("idle"), r;
915
+ return k(() => clearTimeout(r)), {
916
+ state: t,
917
+ copy: async (t) => {
918
+ n(await vr(t) ? "copied" : "failed"), clearTimeout(r), r = setTimeout(() => n("idle"), e);
919
+ }
920
+ };
921
+ }
922
+ //#endregion
300
923
  //#region src/framework/utils/entity-aggregation.ts
301
- function Wt(e, t = !1) {
924
+ function Sr(e, t = !1) {
302
925
  if (e.length === 0) return {
303
926
  isGroup: !1,
304
927
  state: "unknown",
@@ -321,7 +944,7 @@ function Wt(e, t = !1) {
321
944
  isUnavailable: t.state === "unavailable",
322
945
  brightness: r,
323
946
  brightnessPercent: i,
324
- color: qt(t),
947
+ color: Tr(t),
325
948
  onCount: +!!n,
326
949
  totalCount: 1,
327
950
  description: n ? "On" : "Off"
@@ -333,7 +956,7 @@ function Wt(e, t = !1) {
333
956
  if (r++, t.attributes?.brightness !== void 0 && (s += t.attributes.brightness, c++), t.attributes?.rgb_color) l.push(t.attributes.rgb_color);
334
957
  else if (t.attributes?.hs_color) {
335
958
  let [e, n] = t.attributes.hs_color;
336
- l.push(Kt(e, n));
959
+ l.push(wr(e, n));
337
960
  }
338
961
  break;
339
962
  case "off":
@@ -346,26 +969,26 @@ function Wt(e, t = !1) {
346
969
  }
347
970
  let u = e.length, d = o === u, f = a + o === u, p = r > 0, m = r === u, h = i === u, g, _;
348
971
  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);
349
- let v = c > 0 ? Math.round(s / c) : 0, ee = Math.round(v / 255 * 100), y;
972
+ let v = c > 0 ? Math.round(s / c) : 0, y = Math.round(v / 255 * 100), b;
350
973
  if (l.length > 0) {
351
974
  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;
352
- y = `rgb(${Math.round(e * r)}, ${Math.round(t * r)}, ${Math.round(n * r)})`;
353
- } else y = qt(e[0]);
354
- let b;
355
- return b = m ? "All on" : h ? "All off" : r > 0 ? `${r} of ${u} on` : "Off", {
975
+ b = `rgb(${Math.round(e * r)}, ${Math.round(t * r)}, ${Math.round(n * r)})`;
976
+ } else b = Tr(e[0]);
977
+ let x;
978
+ return x = m ? "All on" : h ? "All off" : r > 0 ? `${r} of ${u} on` : "Off", {
356
979
  isGroup: n,
357
980
  state: g,
358
981
  isOn: _,
359
982
  isUnavailable: g === "unavailable",
360
983
  brightness: v,
361
- brightnessPercent: ee,
362
- color: y,
984
+ brightnessPercent: y,
985
+ color: b,
363
986
  onCount: r,
364
987
  totalCount: u,
365
- description: b
988
+ description: x
366
989
  };
367
990
  }
368
- function Gt(e, t = "mean", n = !0) {
991
+ function Cr(e, t = "mean", n = !0) {
369
992
  if (e.length === 0) return {
370
993
  isGroup: !1,
371
994
  state: "unknown",
@@ -461,7 +1084,7 @@ function Gt(e, t = "mean", n = !0) {
461
1084
  memberValues: a
462
1085
  };
463
1086
  }
464
- function Kt(e, t) {
1087
+ function wr(e, t) {
465
1088
  let n = t / 100, r = n * (1 - Math.abs(e / 60 % 2 - 1)), i = 1 - n, a = 0, o = 0, s = 0;
466
1089
  return e < 60 ? [a, o] = [n, r] : e < 120 ? [a, o] = [r, n] : e < 180 ? [o, s] = [n, r] : e < 240 ? [o, s] = [r, n] : e < 300 ? [a, s] = [r, n] : [a, s] = [n, r], [
467
1090
  (a + i) * 255,
@@ -469,7 +1092,7 @@ function Kt(e, t) {
469
1092
  (s + i) * 255
470
1093
  ];
471
1094
  }
472
- function qt(e) {
1095
+ function Tr(e) {
473
1096
  if (e.state !== "on") return "rgb(100, 100, 100)";
474
1097
  let t = (e.attributes?.brightness ?? 255) / 255;
475
1098
  if (e.attributes?.rgb_color) {
@@ -477,7 +1100,7 @@ function qt(e) {
477
1100
  return `rgb(${Math.round(n * t)}, ${Math.round(r * t)}, ${Math.round(i * t)})`;
478
1101
  }
479
1102
  if (e.attributes?.hs_color) {
480
- let [n, r] = e.attributes.hs_color, [i, a, o] = Kt(n, r);
1103
+ let [n, r] = e.attributes.hs_color, [i, a, o] = wr(n, r);
481
1104
  return `rgb(${Math.round(i * t)}, ${Math.round(a * t)}, ${Math.round(o * t)})`;
482
1105
  }
483
1106
  if (e.attributes?.color_temp) {
@@ -488,7 +1111,7 @@ function qt(e) {
488
1111
  }
489
1112
  //#endregion
490
1113
  //#region src/framework/utils/entity-state.ts
491
- function Jt(e) {
1114
+ function Er(e) {
492
1115
  if (!e) return !1;
493
1116
  if ([
494
1117
  "on",
@@ -504,15 +1127,15 @@ function Jt(e) {
504
1127
  }
505
1128
  return !1;
506
1129
  }
507
- function Yt(e, t, n) {
1130
+ function Dr(e, t, n) {
508
1131
  return e?.attributes ? e.attributes[t] ?? n : n;
509
1132
  }
510
- function Xt(e) {
511
- return e.filter(Jt).length;
1133
+ function Or(e) {
1134
+ return e.filter(Er).length;
512
1135
  }
513
1136
  //#endregion
514
1137
  //#region src/framework/utils/format-value.ts
515
- function Zt(e, t, n) {
1138
+ function kr(e, t, n) {
516
1139
  let { decimals: r, scale: i = !0 } = n || {};
517
1140
  if (typeof e == "string") return t ? `${e}${t}` : e;
518
1141
  if (e == null || Number.isNaN(e)) return t ? `--${t}` : "--";
@@ -523,41 +1146,47 @@ function Zt(e, t, n) {
523
1146
  }
524
1147
  //#endregion
525
1148
  //#region src/framework/utils/interpret-value.ts
526
- function Qt(e, t) {
1149
+ function Ar(e, t) {
527
1150
  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;
528
1151
  }
529
1152
  //#endregion
530
1153
  //#region src/framework/components/WidgetValue.tsx
531
- var $t = /*#__PURE__*/ L("<div class=glasshome-widget-subtitle>"), en = /*#__PURE__*/ L("<div><div class=glasshome-widget-value>");
532
- function tn(e) {
1154
+ var jr = /*#__PURE__*/ B("<div class=glasshome-widget-subtitle>"), Mr = /*#__PURE__*/ B("<div><div class=glasshome-widget-value>");
1155
+ function Nr(e) {
533
1156
  return (() => {
534
- var t = en(), n = t.firstChild;
535
- return P(n, () => Zt(e.value, e.unit)), P(t, M(T, {
1157
+ var t = Mr(), n = t.firstChild;
1158
+ return F(n, () => kr(e.value, e.unit)), F(t, N(w, {
536
1159
  get when() {
537
- return F(() => !!e.interpret)() && typeof e.value == "number";
1160
+ return I(() => !!e.interpret)() && typeof e.value == "number";
538
1161
  },
539
1162
  get children() {
540
- var t = $t();
541
- return P(t, () => Qt(e.value, e.unit)), t;
1163
+ var t = jr();
1164
+ return F(t, () => Ar(e.value, e.unit)), t;
542
1165
  }
543
- }), null), N(() => j(t, V("flex flex-col", e.class))), t;
1166
+ }), null), P(() => M(t, X("flex flex-col", e.class))), t;
544
1167
  })();
545
1168
  }
546
1169
  //#endregion
547
1170
  //#region src/framework/core/Widget.tsx
548
- var nn = /*#__PURE__*/ L("<div><div class=\"relative h-full w-full\">"), rn = /*#__PURE__*/ L("<div class=\"glasshome-widget-loading pointer-events-none absolute inset-0 animate-pulse\">"), an = /*#__PURE__*/ L("<div class=\"flex h-full w-full flex-col items-center justify-center gap-2 text-center\">"), on = /*#__PURE__*/ L("<div class=\"flex items-center justify-center text-white/30\">"), sn = /*#__PURE__*/ L("<h3 class=\"font-semibold text-sm text-white/60\">"), cn = /*#__PURE__*/ L("<p class=\"text-white/50 text-xs\">");
549
- function ln(t) {
550
- let n = k(R), [r, i] = O(), [a, o] = O({
1171
+ var Pr = /*#__PURE__*/ B("<span class=glasshome-widget-hold-flood aria-hidden=true>"), Fr = /*#__PURE__*/ B("<div><div class=\"relative h-full w-full\">"), Ir = /*#__PURE__*/ B("<div class=\"glasshome-widget-loading pointer-events-none absolute inset-0 animate-pulse\">"), Lr = /*#__PURE__*/ B("<div class=\"flex h-full w-full flex-col items-center justify-center gap-2 text-center\">"), Rr = /*#__PURE__*/ B("<div class=\"flex items-center justify-center text-muted-foreground\">"), zr = /*#__PURE__*/ B("<h3 class=\"font-semibold text-sm text-foreground\">"), Br = /*#__PURE__*/ B("<p class=\"text-muted-foreground text-xs\">");
1172
+ function Vr(t) {
1173
+ let n = A(W), r = xn(() => ({ hold: { action: () => (q.get(n ?? {}) ?? q.get(d))?.("edit") } }));
1174
+ k(r.dispose);
1175
+ let i = rn(n), a = xn(() => ({ hold: i?.hasSheet() ? { action: () => (q.get(n ?? {}) ?? q.get(d))?.() } : void 0 }));
1176
+ k(a.dispose);
1177
+ let o = () => t.emptyState && n ? r : t.gestures ?? (i?.hasSheet() ? a : void 0);
1178
+ E(() => i?.setTone(t.color ?? (t.tone ? `var(--tone-${t.tone})` : void 0)));
1179
+ let [s, c] = O(), [l, u] = O({
551
1180
  width: 0,
552
1181
  height: 0
553
1182
  });
554
1183
  E(() => {
555
- let e = r();
1184
+ let e = s();
556
1185
  if (!e) return;
557
1186
  let t = new ResizeObserver(([e]) => {
558
1187
  if (!e) return;
559
1188
  let t = e.borderBoxSize?.[0];
560
- o(t ? {
1189
+ u(t ? {
561
1190
  width: t.inlineSize,
562
1191
  height: t.blockSize
563
1192
  } : {
@@ -565,123 +1194,939 @@ function ln(t) {
565
1194
  height: e.contentRect.height
566
1195
  });
567
1196
  });
568
- t.observe(e), me(() => t.disconnect());
569
- }), he(() => {
570
- let e = r()?.getRootNode();
571
- Ot(typeof ShadowRoot < "u" && e instanceof ShadowRoot || typeof Document < "u" && e instanceof Document ? e : void 0);
1197
+ t.observe(e), k(() => t.disconnect());
1198
+ }), ge(() => {
1199
+ let e = s()?.getRootNode();
1200
+ ir(typeof ShadowRoot < "u" && e instanceof ShadowRoot || typeof Document < "u" && e instanceof Document ? e : void 0);
572
1201
  });
573
- let s = {
1202
+ let d = {
1203
+ ...n,
574
1204
  updateConfig: n?.updateConfig ?? (() => {}),
575
- registerDialogOpener: n?.registerDialogOpener,
576
- callService: n?.callService,
577
- dimensions: e(() => a(), "ctx.dimensions")
578
- }, c = D(() => {
579
- if (t.variant) return typeof t.variant == "string" ? At(t.variant) : t.variant;
580
- }), l = D(() => ({
1205
+ dimensions: e(() => l(), "ctx.dimensions")
1206
+ };
1207
+ n && Object.defineProperty(d, tn, { value: n });
1208
+ let f = D(() => {
1209
+ if (t.variant) return typeof t.variant == "string" ? or(t.variant) : t.variant;
1210
+ }), p = e(() => t.gradient, "widget.gradient"), m = D(() => ({
581
1211
  "container-type": "size",
582
1212
  "container-name": "widget",
583
- "touch-action": t.gestures && !t.isEditMode ? t.gestures.touchAction() : void 0,
584
- ...c()?.styles?.container,
585
- ...c()?.styles?.cssVars || {},
1213
+ "touch-action": o() && !t.isEditMode ? o()?.touchAction() : void 0,
1214
+ ...f()?.styles?.container,
1215
+ ...f()?.styles?.cssVars || {},
586
1216
  ...t.tone ? { "--widget-color": `var(--tone-${t.tone})` } : {},
587
1217
  ...t.color ? { "--widget-color": t.color } : {},
588
- ...t.colorTo ? { "--widget-color-to": t.colorTo } : {},
589
- ...t.gradient ? { "--widget-gradient": t.gradient } : {}
590
- })), u = () => !!t.gestures && !t.isEditMode, d = (e) => {
591
- u() && t.gestures?.onPointerEnter(e);
592
- }, f = (e) => {
593
- u() && t.gestures?.onPointerDown(e);
594
- }, p = (e) => {
595
- u() && t.gestures?.onPointerMove(e);
596
- }, m = (e) => {
597
- u() && t.gestures?.onPointerUp(e);
598
- }, h = (e) => {
599
- u() && t.gestures?.onPointerCancel(e);
600
- };
601
- return M(R.Provider, {
602
- value: s,
1218
+ ...t.tone && t.tone !== "neutral" || t.color ? { "--glass-tone": "var(--widget-color)" } : {},
1219
+ ...t.colorTo ? {
1220
+ "--widget-color-to": t.colorTo,
1221
+ "--glass-tone-2": t.colorTo
1222
+ } : {},
1223
+ ...t.gradient ? { "background-image": p() } : {}
1224
+ })), h = () => !!o() && !t.isEditMode, g = (e) => {
1225
+ h() && o()?.onPointerEnter(e);
1226
+ }, _ = (e) => {
1227
+ h() && o()?.onPointerDown(e);
1228
+ }, v = (e) => {
1229
+ h() && o()?.onPointerMove(e);
1230
+ }, y = (e) => {
1231
+ h() && o()?.onPointerUp(e);
1232
+ }, b = (e) => {
1233
+ h() && o()?.onPointerCancel(e);
1234
+ }, x = () => o()?.hold?.() ?? null, S = {
1235
+ x: 0,
1236
+ y: 0,
1237
+ r: 0
1238
+ }, ee = (e) => (e && Object.assign(S, {
1239
+ x: e.x,
1240
+ y: e.y,
1241
+ r: e.r
1242
+ }), {
1243
+ left: `${S.x}px`,
1244
+ top: `${S.y}px`,
1245
+ width: `${S.r * 2}px`,
1246
+ height: `${S.r * 2}px`,
1247
+ "z-index": K.BACKGROUND
1248
+ });
1249
+ return N(W.Provider, {
1250
+ value: d,
603
1251
  get children() {
604
- return M(xt.Provider, {
605
- value: a,
1252
+ return N(Vn.Provider, {
1253
+ value: () => t.confirmed === !0,
606
1254
  get children() {
607
- var e = nn(), n = e.firstChild;
608
- return A(e, "pointercancel", h), A(e, "pointerup", m), A(e, "pointermove", p), A(e, "pointerdown", f), A(e, "pointerenter", d), ve((e) => {
609
- i(e), t.gestures?.bindElement(e);
610
- }, e), P(n, (() => {
611
- var e = F(() => !!t.emptyState);
612
- return () => e() ? M(un, {
613
- get icon() {
614
- return t.emptyState.icon;
615
- },
616
- get title() {
617
- return t.emptyState.title;
618
- },
619
- get message() {
620
- return t.emptyState.message;
621
- }
622
- }) : t.children;
623
- })()), P(e, (() => {
624
- var e = F(() => !!t.loading);
625
- return () => e() && (() => {
626
- var e = rn();
627
- return N((t) => I(e, "z-index", B.OVERLAY)), e;
628
- })();
629
- })(), null), N((r) => {
630
- var i = V("glasshome-widget", "relative h-full w-full select-none overflow-hidden rounded-xl border border-border/50", c()?.styles?.class, t.class), a = l(), o = B.CONTENT;
631
- return i !== r.e && j(e, r.e = i), r.t = _e(e, a, r.t), o !== r.a && I(n, "z-index", r.a = o), r;
1255
+ return N(Sn.Provider, {
1256
+ value: l,
1257
+ get children() {
1258
+ var e = Fr(), n = e.firstChild;
1259
+ return e.$$keydown = (e) => {
1260
+ h() && o()?.onKeyDown?.(e);
1261
+ }, j(e, "pointercancel", b), j(e, "pointerup", y), j(e, "pointermove", v), j(e, "pointerdown", _), j(e, "pointerenter", g), V((e) => {
1262
+ c(e), t.gestures?.bindElement(e), r.bindElement(e);
1263
+ }, e), F(e, N(w, {
1264
+ get when() {
1265
+ return o()?.hold;
1266
+ },
1267
+ get children() {
1268
+ var e = Pr();
1269
+ return P((t) => {
1270
+ var n = x() && !x()?.fired ? "" : void 0, r = x()?.fired ? "" : void 0, i = ee(x());
1271
+ return n !== t.e && L(e, "data-hold", t.e = n), r !== t.t && L(e, "data-fired", t.t = r), t.a = z(e, i, t.a), t;
1272
+ }, {
1273
+ e: void 0,
1274
+ t: void 0,
1275
+ a: void 0
1276
+ }), e;
1277
+ }
1278
+ }), n), F(n, (() => {
1279
+ var e = I(() => !!t.emptyState);
1280
+ return () => e() ? N(Hr, {
1281
+ get icon() {
1282
+ return t.emptyState.icon;
1283
+ },
1284
+ get title() {
1285
+ return t.emptyState.title;
1286
+ },
1287
+ get message() {
1288
+ return t.emptyState.message;
1289
+ }
1290
+ }) : t.children;
1291
+ })()), F(e, (() => {
1292
+ var e = I(() => !!t.loading);
1293
+ return () => e() && (() => {
1294
+ var e = Ir();
1295
+ return P((t) => R(e, "z-index", K.OVERLAY)), e;
1296
+ })();
1297
+ })(), null), P((r) => {
1298
+ var i = X("glasshome-widget glass", "relative h-full w-full select-none overflow-hidden rounded-xl", f()?.styles?.class, t.class), a = m(), o = t.confirmed || void 0, s = h() ? 0 : void 0, c = K.CONTENT;
1299
+ return i !== r.e && M(e, r.e = i), r.t = z(e, a, r.t), o !== r.a && L(e, "data-confirmed", r.a = o), s !== r.o && L(e, "tabindex", r.o = s), c !== r.i && R(n, "z-index", r.i = c), r;
1300
+ }, {
1301
+ e: void 0,
1302
+ t: void 0,
1303
+ a: void 0,
1304
+ o: void 0,
1305
+ i: void 0
1306
+ }), e;
1307
+ }
1308
+ });
1309
+ }
1310
+ });
1311
+ }
1312
+ });
1313
+ }
1314
+ function Hr(e) {
1315
+ return (() => {
1316
+ var t = Lr();
1317
+ return F(t, (() => {
1318
+ var t = I(() => !!e.icon);
1319
+ return () => t() && (() => {
1320
+ var t = Rr();
1321
+ return F(t, () => e.icon), t;
1322
+ })();
1323
+ })(), null), F(t, (() => {
1324
+ var t = I(() => !!e.title);
1325
+ return () => t() && (() => {
1326
+ var t = zr();
1327
+ return F(t, () => e.title), t;
1328
+ })();
1329
+ })(), null), F(t, (() => {
1330
+ var t = I(() => !!e.message);
1331
+ return () => t() && (() => {
1332
+ var t = Br();
1333
+ return F(t, () => e.message), t;
1334
+ })();
1335
+ })(), null), t;
1336
+ })();
1337
+ }
1338
+ var Z = Vr;
1339
+ Z.Content = fr, Z.Icon = kn, Z.Title = _r, Z.Status = mr, Z.Value = Nr, Z.SliderFill = lr, Z.Head = Un, Z.Hero = Wn, Z.Controls = Gn, Z.Stepper = Kn, Z.Choice = qn, Z.Action = Jn, Z.Chip = Yn, Z.Backdrop = Zn, Z.Layer = Xn, Z.Glyph = Qn, ve(["keydown"]);
1340
+ //#endregion
1341
+ //#region src/framework/panel/panel.tsx
1342
+ var Ur = /*#__PURE__*/ B("<section class=glasshome-panel-section><h3 class=glasshome-panel-label>"), Wr = /*#__PURE__*/ B("<div class=glasshome-panel-rows>"), Gr = /*#__PURE__*/ B("<span class=\"glasshome-widget-slider-fill glasshome-panel-row-fill\">"), Kr = /*#__PURE__*/ B("<span class=\"glasshome-widget-icon glass glasshome-panel-row-icon\">"), qr = /*#__PURE__*/ B("<span class=glasshome-panel-row-state>"), Jr = /*#__PURE__*/ B("<span class=glasshome-panel-row-text><span class=glasshome-panel-row-name>"), Yr = /*#__PURE__*/ B("<span class=glasshome-panel-row-trailing>"), Xr = /*#__PURE__*/ B("<div class=glasshome-panel-row-wrap>"), Zr = /*#__PURE__*/ B("<div>"), Qr = /*#__PURE__*/ B("<div class=\"glasshome-panel-facts glass\">"), $r = /*#__PURE__*/ B("<div class=glasshome-panel-fact><span class=glasshome-panel-row-text><span class=glasshome-panel-fact-label></span><span class=glasshome-panel-fact-value>"), ei = 450, ti = 8, ni = (e, t, n) => Math.min(n, Math.max(t, e)), ri = "button, a, input, select, textarea, [role=\"slider\"], [role=\"radio\"], [role=\"switch\"]";
1343
+ function ii(e) {
1344
+ let t, n = !1, r = !1, i, a = 0, o = (t, n) => {
1345
+ let r = e.slide?.();
1346
+ if (!r) return 0;
1347
+ let i = t.getBoundingClientRect(), a = e.axis === "x" ? (n.clientX - i.left) / i.width : 1 - (n.clientY - i.top) / i.height, o = r.min ?? 0, s = r.max ?? 100;
1348
+ return Math.round(ni(o + a * (s - o), o, s));
1349
+ }, s = () => {
1350
+ clearTimeout(i), t = void 0;
1351
+ };
1352
+ return k(() => clearTimeout(i)), {
1353
+ onPointerDown: (a) => {
1354
+ if (a.button !== 0 || t) return;
1355
+ let o = a.target instanceof Element ? a.target.closest(ri) : null;
1356
+ o && o !== a.currentTarget || (t = {
1357
+ x: a.clientX,
1358
+ y: a.clientY,
1359
+ id: a.pointerId
1360
+ }, a.currentTarget.setPointerCapture?.(a.pointerId), n = !1, r = !1, e.onHold && (i = setTimeout(() => {
1361
+ r = !0, e.onHold?.();
1362
+ }, ei)));
1363
+ },
1364
+ onPointerMove: (s) => {
1365
+ if (!t || s.pointerId !== t.id || r) return;
1366
+ let c = s.currentTarget, l = e.axis === "x" ? Math.abs(s.clientX - t.x) : Math.abs(s.clientY - t.y);
1367
+ !n && e.slide?.() && l > ti && (n = !0, clearTimeout(i)), n ? (a = o(c, s), e.slide?.()?.onChange(a)) : Math.hypot(s.clientX - t.x, s.clientY - t.y) > ti && clearTimeout(i);
1368
+ },
1369
+ onPointerUp: (i) => {
1370
+ t && i.pointerId === t.id && (n ? e.slide?.()?.onCommit?.(a) : r || e.onTap?.(), s());
1371
+ },
1372
+ onPointerCancel: s
1373
+ };
1374
+ }
1375
+ function ai(e) {
1376
+ return (() => {
1377
+ var t = Ur(), n = t.firstChild;
1378
+ return F(n, () => e.label), F(t, () => e.children, null), t;
1379
+ })();
1380
+ }
1381
+ function oi(e) {
1382
+ return (() => {
1383
+ var t = Wr();
1384
+ return F(t, () => e.children), t;
1385
+ })();
1386
+ }
1387
+ function si(e) {
1388
+ let t = () => !!(e.onTap || e.slide || e.onHold), n = ii({
1389
+ axis: "x",
1390
+ slide: () => e.slide,
1391
+ onTap: () => e.onTap?.(),
1392
+ onHold: e.onHold ? () => e.onHold?.() : void 0
1393
+ }), r = () => {
1394
+ if (e.fill !== void 0) return e.fill;
1395
+ let t = e.slide;
1396
+ if (!t || !e.on) return;
1397
+ let n = t.min ?? 0, r = t.max ?? 100;
1398
+ return (t.value - n) / (r - n || 1) * 100;
1399
+ }, i = (t) => {
1400
+ let n = e.slide;
1401
+ if (!n) return;
1402
+ let r = t.key === "ArrowRight" || t.key === "ArrowUp" ? 5 : t.key === "ArrowLeft" || t.key === "ArrowDown" ? -5 : 0;
1403
+ if (!r) return;
1404
+ t.preventDefault();
1405
+ let i = ni(n.value + r, n.min ?? 0, n.max ?? 100);
1406
+ n.onChange(i), n.onCommit?.(i);
1407
+ }, a = () => [
1408
+ N(w, {
1409
+ get when() {
1410
+ return r() !== void 0;
1411
+ },
1412
+ get children() {
1413
+ var e = Gr();
1414
+ return P((t) => z(e, { "--widget-fill-value": r() }, t)), e;
1415
+ }
1416
+ }),
1417
+ (() => {
1418
+ var t = Kr();
1419
+ return F(t, N(U, {
1420
+ get icon() {
1421
+ return e.icon;
1422
+ },
1423
+ class: "glasshome-widget-icon-glyph"
1424
+ })), P((n) => {
1425
+ var r = !!e.on, i = !e.on;
1426
+ return r !== n.e && t.classList.toggle("glass-tint", n.e = r), i !== n.t && t.classList.toggle("glasshome-panel-row-icon-off", n.t = i), n;
1427
+ }, {
1428
+ e: void 0,
1429
+ t: void 0
1430
+ }), t;
1431
+ })(),
1432
+ (() => {
1433
+ var t = Jr(), n = t.firstChild;
1434
+ return F(n, () => e.name), F(t, N(w, {
1435
+ get when() {
1436
+ return e.state !== void 0;
1437
+ },
1438
+ get children() {
1439
+ var t = qr();
1440
+ return F(t, () => e.state), t;
1441
+ }
1442
+ }), null), t;
1443
+ })()
1444
+ ], o = () => ({ "--widget-color": e.tone ?? "var(--tone-neutral)" });
1445
+ return (() => {
1446
+ var r = Xr();
1447
+ return F(r, N(w, {
1448
+ get when() {
1449
+ return t();
1450
+ },
1451
+ get fallback() {
1452
+ return (() => {
1453
+ var e = Zr();
1454
+ return F(e, a), P((t) => {
1455
+ var n = `${Pt({
1456
+ variant: "outline",
1457
+ size: "none"
1458
+ })} glasshome-panel-row glasshome-panel-row-static`, r = o();
1459
+ return n !== t.e && M(e, t.e = n), t.t = z(e, r, t.t), t;
632
1460
  }, {
633
1461
  e: void 0,
634
- t: void 0,
635
- a: void 0
1462
+ t: void 0
636
1463
  }), e;
1464
+ })();
1465
+ },
1466
+ get children() {
1467
+ return N(Ee, {
1468
+ variant: "outline",
1469
+ size: "none",
1470
+ class: "glasshome-panel-row",
1471
+ get style() {
1472
+ return o();
1473
+ },
1474
+ get "aria-label"() {
1475
+ return e["aria-label"];
1476
+ },
1477
+ get "aria-pressed"() {
1478
+ return e.on;
1479
+ },
1480
+ get onPointerDown() {
1481
+ return n.onPointerDown;
1482
+ },
1483
+ get onPointerMove() {
1484
+ return n.onPointerMove;
1485
+ },
1486
+ get onPointerUp() {
1487
+ return n.onPointerUp;
1488
+ },
1489
+ get onPointerCancel() {
1490
+ return n.onPointerCancel;
1491
+ },
1492
+ onKeyDown: i,
1493
+ onClick: (t) => {
1494
+ t.detail === 0 && e.onTap?.();
1495
+ },
1496
+ get children() {
1497
+ return a();
1498
+ }
1499
+ });
1500
+ }
1501
+ }), null), F(r, N(w, {
1502
+ get when() {
1503
+ return e.trailing;
1504
+ },
1505
+ get children() {
1506
+ var t = Yr();
1507
+ return F(t, () => e.trailing), t;
1508
+ }
1509
+ }), null), r;
1510
+ })();
1511
+ }
1512
+ function ci(e) {
1513
+ return (() => {
1514
+ var t = Qr();
1515
+ return F(t, N(C, {
1516
+ get each() {
1517
+ return e.items;
1518
+ },
1519
+ children: (e) => (() => {
1520
+ var t = $r(), n = t.firstChild, r = n.firstChild, i = r.nextSibling;
1521
+ return F(t, N(U, {
1522
+ get icon() {
1523
+ return e.icon;
1524
+ },
1525
+ class: "glasshome-panel-fact-icon"
1526
+ }), n), F(r, () => e.label), F(i, () => e.value), t;
1527
+ })()
1528
+ })), t;
1529
+ })();
1530
+ }
1531
+ //#endregion
1532
+ //#region src/framework/panel/panel-entity.tsx
1533
+ var li = (e) => typeof e == "number" ? Math.round(e) : void 0, ui = (e) => e.charAt(0).toUpperCase() + e.slice(1).replaceAll("_", " "), Q = (e) => ({ entity_id: e.id }), di = {
1534
+ light: {
1535
+ icon: "mdi:lightbulb",
1536
+ tone: (e) => {
1537
+ let t = e.attributes.rgb_color;
1538
+ return Array.isArray(t) && t.length === 3 ? `rgb(${t.join(" ")})` : "var(--tone-warning)";
1539
+ },
1540
+ on: (e) => e.state === "on",
1541
+ state: (e) => {
1542
+ if (e.state !== "on") return "Off";
1543
+ let t = e.attributes.brightness;
1544
+ return typeof t == "number" ? `${Math.round(t / 255 * 100)}%` : "On";
1545
+ },
1546
+ level: (e) => {
1547
+ let t = e.attributes.brightness;
1548
+ return e.state === "on" ? typeof t == "number" ? Math.round(t / 255 * 100) : 100 : 0;
1549
+ },
1550
+ setLevel: (e, t, n) => e("light", n > 0 ? "turn_on" : "turn_off", n > 0 ? { brightness_pct: n } : {}, Q(t)),
1551
+ tap: (e, t) => e("light", "toggle", {}, Q(t))
1552
+ },
1553
+ switch: {
1554
+ icon: "mdi:toggle-switch-variant",
1555
+ tone: "var(--tone-info)",
1556
+ on: (e) => e.state === "on",
1557
+ state: (e) => e.state === "on" ? "On" : "Off",
1558
+ tap: (e, t) => e("switch", "toggle", {}, Q(t))
1559
+ },
1560
+ input_boolean: {
1561
+ icon: "mdi:toggle-switch-variant",
1562
+ tone: "var(--tone-info)",
1563
+ on: (e) => e.state === "on",
1564
+ state: (e) => e.state === "on" ? "On" : "Off",
1565
+ tap: (e, t) => e("input_boolean", "toggle", {}, Q(t))
1566
+ },
1567
+ fan: {
1568
+ icon: "mdi:fan",
1569
+ tone: "var(--tone-success)",
1570
+ on: (e) => e.state === "on",
1571
+ state: (e) => {
1572
+ if (e.state !== "on") return "Off";
1573
+ let t = li(e.attributes.percentage);
1574
+ return t === void 0 ? "On" : `${t}%`;
1575
+ },
1576
+ level: (e) => e.state === "on" ? li(e.attributes.percentage) ?? 100 : 0,
1577
+ setLevel: (e, t, n) => e("fan", "set_percentage", { percentage: n }, Q(t)),
1578
+ tap: (e, t) => e("fan", "toggle", {}, Q(t))
1579
+ },
1580
+ cover: {
1581
+ icon: "mdi:blinds",
1582
+ tone: "var(--tone-info)",
1583
+ on: (e) => e.state !== "closed",
1584
+ state: (e) => {
1585
+ let t = li(e.attributes.current_position), n = ui(e.state);
1586
+ return t !== void 0 && e.state === "open" ? `${n} · ${t}%` : n;
1587
+ },
1588
+ level: (e) => li(e.attributes.current_position),
1589
+ setLevel: (e, t, n) => e("cover", "set_cover_position", { position: n }, Q(t)),
1590
+ tap: (e, t) => e("cover", t.state === "closed" ? "open_cover" : "close_cover", {}, Q(t))
1591
+ },
1592
+ lock: {
1593
+ icon: (e) => e.state === "locked" ? "mdi:lock" : "mdi:lock-open-variant",
1594
+ tone: "var(--tone-success)",
1595
+ on: (e) => e.state === "locked",
1596
+ state: (e) => ui(e.state),
1597
+ tap: (e, t) => e("lock", t.state === "locked" ? "unlock" : "lock", {}, Q(t))
1598
+ },
1599
+ climate: {
1600
+ icon: "mdi:thermostat",
1601
+ tone: "var(--tone-danger)",
1602
+ on: (e) => e.state !== "off",
1603
+ state: (e) => {
1604
+ if (e.state === "off") return "Off";
1605
+ let t = e.attributes.temperature;
1606
+ return typeof t == "number" ? `${ui(e.state)} · ${t}°` : ui(e.state);
1607
+ }
1608
+ },
1609
+ media_player: {
1610
+ icon: "mdi:speaker",
1611
+ tone: "var(--tone-accent)",
1612
+ on: (e) => e.state === "playing",
1613
+ state: (e) => typeof e.attributes.media_title == "string" && e.state !== "off" ? e.attributes.media_title : ui(e.state),
1614
+ level: (e) => typeof e.attributes.volume_level == "number" ? Math.round(e.attributes.volume_level * 100) : void 0,
1615
+ setLevel: (e, t, n) => e("media_player", "volume_set", { volume_level: n / 100 }, Q(t)),
1616
+ tap: (e, t) => e("media_player", "media_play_pause", {}, Q(t))
1617
+ },
1618
+ binary_sensor: {
1619
+ icon: "mdi:eye",
1620
+ tone: "var(--tone-info)",
1621
+ on: (e) => e.state === "on",
1622
+ state: (e) => {
1623
+ let t = pi[e.deviceClass ?? ""] ?? ["On", "Off"];
1624
+ return e.state === "on" ? t[0] : t[1];
1625
+ }
1626
+ },
1627
+ button: {
1628
+ icon: "mdi:gesture-tap-button",
1629
+ tone: "var(--tone-accent)",
1630
+ on: () => !1,
1631
+ state: (e) => mi(e.state),
1632
+ tap: (e, t) => e("button", "press", {}, Q(t))
1633
+ },
1634
+ input_button: {
1635
+ icon: "mdi:gesture-tap-button",
1636
+ tone: "var(--tone-accent)",
1637
+ on: () => !1,
1638
+ state: (e) => mi(e.state),
1639
+ tap: (e, t) => e("input_button", "press", {}, Q(t))
1640
+ },
1641
+ scene: {
1642
+ icon: "mdi:palette",
1643
+ tone: "var(--tone-accent)",
1644
+ on: () => !1,
1645
+ state: () => "Tap to run",
1646
+ tap: (e, t) => e("scene", "turn_on", {}, Q(t))
1647
+ },
1648
+ script: {
1649
+ icon: "mdi:script-text",
1650
+ tone: "var(--tone-accent)",
1651
+ on: (e) => e.state === "on",
1652
+ state: (e) => e.state === "on" ? "Running" : "Tap to run",
1653
+ tap: (e, t) => e("script", "turn_on", {}, Q(t))
1654
+ }
1655
+ }, fi = {
1656
+ garage: "mdi:garage",
1657
+ gate: "mdi:gate",
1658
+ door: "mdi:door",
1659
+ curtain: "mdi:curtains",
1660
+ shutter: "mdi:window-shutter",
1661
+ awning: "mdi:awning"
1662
+ }, pi = {
1663
+ door: ["Open", "Closed"],
1664
+ window: ["Open", "Closed"],
1665
+ garage_door: ["Open", "Closed"],
1666
+ opening: ["Open", "Closed"],
1667
+ motion: ["Detected", "Clear"],
1668
+ occupancy: ["Detected", "Clear"],
1669
+ presence: ["Home", "Away"],
1670
+ moisture: ["Wet", "Dry"],
1671
+ smoke: ["Smoke", "Clear"],
1672
+ lock: ["Unlocked", "Locked"],
1673
+ battery: ["Low", "Normal"],
1674
+ connectivity: ["Connected", "Disconnected"]
1675
+ };
1676
+ function mi(e) {
1677
+ let t = Date.parse(e);
1678
+ return Number.isNaN(t) ? "Never pressed" : new Date(t).toLocaleTimeString([], {
1679
+ hour: "2-digit",
1680
+ minute: "2-digit"
1681
+ });
1682
+ }
1683
+ var hi = {
1684
+ icon: "mdi:circle-medium",
1685
+ tone: "var(--tone-neutral)",
1686
+ on: (e) => e.state === "on",
1687
+ state: (e) => ui(e.state)
1688
+ };
1689
+ function gi(e, t) {
1690
+ if (!t || e.length <= t.length || !e.toLowerCase().startsWith(t.toLowerCase())) return e;
1691
+ let n = e.slice(t.length).trim();
1692
+ return n ? n.charAt(0).toUpperCase() + n.slice(1) : e;
1693
+ }
1694
+ function _i(e) {
1695
+ return !!di[e]?.tap || !!di[e]?.setLevel;
1696
+ }
1697
+ function vi(e) {
1698
+ let t = te(() => e.entityId), { callService: n } = Yt(), [r, i] = O();
1699
+ return E(() => {
1700
+ t(), i(void 0);
1701
+ }), N(w, {
1702
+ get when() {
1703
+ return t();
1704
+ },
1705
+ children: (t) => {
1706
+ let a = () => di[t().domain] ?? hi, o = () => r() ?? a().level?.(t()), s = () => a().setLevel;
1707
+ return N(si, {
1708
+ get icon() {
1709
+ let n = a().icon;
1710
+ return typeof n == "function" ? e.icon ?? n(t()) : e.icon ?? t().icon ?? fi[t().domain === "cover" ? t().deviceClass ?? "" : ""] ?? n;
1711
+ },
1712
+ get name() {
1713
+ return e.name ?? gi(t().friendlyName ?? t().id, e.within);
1714
+ },
1715
+ get state() {
1716
+ return a().state(t());
1717
+ },
1718
+ get tone() {
1719
+ if (e.tone) return e.tone;
1720
+ let n = a().tone;
1721
+ return typeof n == "function" ? n(t()) : n;
1722
+ },
1723
+ get on() {
1724
+ return a().on(t());
1725
+ },
1726
+ get slide() {
1727
+ return I(() => !!(s() && o() !== void 0))() ? {
1728
+ value: o() ?? 0,
1729
+ onChange: i,
1730
+ onCommit: (e) => s()?.(n, t(), e)
1731
+ } : void 0;
1732
+ },
1733
+ get onTap() {
1734
+ return a().tap ? () => a().tap?.(n, t()) : void 0;
1735
+ },
1736
+ get onHold() {
1737
+ return e.onHold;
1738
+ }
1739
+ });
1740
+ }
1741
+ });
1742
+ }
1743
+ //#endregion
1744
+ //#region src/framework/dialogs/debug-view.tsx
1745
+ var yi = /*#__PURE__*/ B("<pre class=\"max-h-64 overflow-auto p-3 font-mono text-muted-foreground text-xs leading-relaxed\">"), bi = /*#__PURE__*/ B("<span class=\"flex items-center gap-2\">"), xi = /*#__PURE__*/ B("<section class=\"flex min-w-0 flex-col gap-2\"><header class=\"flex items-center gap-3\"><div class=\"flex min-w-0 flex-1 flex-col\"></div></header><div class=\"flex flex-col gap-2\">"), Si = /*#__PURE__*/ B("<div class=\"flex flex-col\">"), Ci = /*#__PURE__*/ B("<pre class=\"max-h-96 overflow-auto whitespace-pre-wrap p-3 font-mono text-muted-foreground text-xs leading-relaxed\">");
1746
+ function wi(e, t, n) {
1747
+ return {
1748
+ widgetConfig: e,
1749
+ entities: t.map((e) => ({
1750
+ entity_id: e.id,
1751
+ state: e.state,
1752
+ domain: e.domain,
1753
+ friendly_name: e.friendlyName,
1754
+ device_class: e.deviceClass ?? null,
1755
+ area_id: e.areaId,
1756
+ last_changed: e.lastChanged.toISOString(),
1757
+ last_updated: e.lastUpdated.toISOString(),
1758
+ attributes: e.attributes
1759
+ })),
1760
+ ...n
1761
+ };
1762
+ }
1763
+ var Ti = (e) => JSON.stringify(e, null, 2), Ei = {
1764
+ idle: "lucide:copy",
1765
+ copied: "lucide:check",
1766
+ failed: "lucide:triangle-alert"
1767
+ }, Di = {
1768
+ idle: "text-muted-foreground",
1769
+ copied: "text-success",
1770
+ failed: "text-destructive"
1771
+ };
1772
+ function Oi(e) {
1773
+ let { state: t, copy: n } = xr();
1774
+ return N(Ee, {
1775
+ variant: "ghost",
1776
+ size: "icon",
1777
+ class: "size-8",
1778
+ get "aria-label"() {
1779
+ return e.label;
1780
+ },
1781
+ onClick: () => void n(e.text()),
1782
+ get children() {
1783
+ return N(U, {
1784
+ get icon() {
1785
+ return Ei[t()];
1786
+ },
1787
+ width: 16,
1788
+ height: 16,
1789
+ get class() {
1790
+ return Di[t()];
1791
+ }
1792
+ });
1793
+ }
1794
+ });
1795
+ }
1796
+ function ki(e) {
1797
+ let t = e.replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ");
1798
+ return t.charAt(0).toUpperCase() + t.slice(1).toLowerCase();
1799
+ }
1800
+ var Ai = (e) => typeof e != "object" || !e;
1801
+ function ji(e) {
1802
+ return e == null ? "None" : String(e);
1803
+ }
1804
+ function Mi(e) {
1805
+ return Array.isArray(e) ? e.length : typeof e == "object" && e ? Object.keys(e).length : 0;
1806
+ }
1807
+ function Ni(e) {
1808
+ let t = new Date(e);
1809
+ return Number.isNaN(t.getTime()) ? e : t.toLocaleString();
1810
+ }
1811
+ function Pi(e) {
1812
+ return N(ut, {
1813
+ class: "overflow-hidden p-0",
1814
+ get children() {
1815
+ var t = yi();
1816
+ return F(t, () => Ti(e.value)), t;
1817
+ }
1818
+ });
1819
+ }
1820
+ function Fi(e) {
1821
+ return N(ye, {
1822
+ collapsible: !0,
1823
+ class: "border-border/50 border-t",
1824
+ get children() {
1825
+ return N(xe, {
1826
+ get value() {
1827
+ return e.label;
1828
+ },
1829
+ get children() {
1830
+ return [N(Se, {
1831
+ class: "py-3 text-muted-foreground text-xs",
1832
+ get children() {
1833
+ var t = bi();
1834
+ return F(t, () => e.label, null), F(t, N(w, {
1835
+ get when() {
1836
+ return e.count !== void 0;
1837
+ },
1838
+ get children() {
1839
+ return N(ze, { get children() {
1840
+ return e.count;
1841
+ } });
1842
+ }
1843
+ }), null), t;
1844
+ }
1845
+ }), N(be, { get children() {
1846
+ return N(Pi, { get value() {
1847
+ return e.value;
1848
+ } });
1849
+ } })];
1850
+ }
1851
+ });
1852
+ }
1853
+ });
1854
+ }
1855
+ function Ii(e) {
1856
+ return (() => {
1857
+ var t = xi(), n = t.firstChild, r = n.firstChild, i = n.nextSibling;
1858
+ return F(n, N(ct, {
1859
+ get icon() {
1860
+ return e.icon;
1861
+ },
1862
+ size: "sm"
1863
+ }), r), F(r, N(Ge, {
1864
+ class: "truncate",
1865
+ get children() {
1866
+ return e.title;
1867
+ }
1868
+ }), null), F(r, N(w, {
1869
+ get when() {
1870
+ return e.subtitle;
1871
+ },
1872
+ children: (e) => N(lt, {
1873
+ class: "truncate font-mono",
1874
+ get children() {
1875
+ return e();
1876
+ }
1877
+ })
1878
+ }), null), F(n, () => e.badge, null), F(n, N(Oi, {
1879
+ get label() {
1880
+ return `Copy ${e.title}`;
1881
+ },
1882
+ text: () => Ti(e.source)
1883
+ }), null), F(i, () => e.children), t;
1884
+ })();
1885
+ }
1886
+ function Li(e) {
1887
+ let t = D(() => Object.entries(e.record)), n = D(() => t().filter(([, e]) => Ai(e))), r = D(() => t().filter(([, e]) => !Ai(e)));
1888
+ return N(w, {
1889
+ get when() {
1890
+ return t().length > 0;
1891
+ },
1892
+ get fallback() {
1893
+ return N(lt, { children: "Nothing set" });
1894
+ },
1895
+ get children() {
1896
+ return [N(w, {
1897
+ get when() {
1898
+ return n().length > 0;
1899
+ },
1900
+ get children() {
1901
+ var e = Si();
1902
+ return F(e, N(C, {
1903
+ get each() {
1904
+ return n();
1905
+ },
1906
+ children: ([e, t]) => N(H, {
1907
+ get label() {
1908
+ return ki(e);
1909
+ },
1910
+ get children() {
1911
+ return ji(t);
1912
+ }
1913
+ })
1914
+ })), e;
1915
+ }
1916
+ }), N(C, {
1917
+ get each() {
1918
+ return r();
1919
+ },
1920
+ children: ([e, t]) => N(Fi, {
1921
+ get label() {
1922
+ return ki(e);
1923
+ },
1924
+ get count() {
1925
+ return Mi(t);
1926
+ },
1927
+ value: t
1928
+ })
1929
+ })];
1930
+ }
1931
+ });
1932
+ }
1933
+ function Ri(e) {
1934
+ let t = () => e.entity.attributes ?? {};
1935
+ return N(Ii, {
1936
+ icon: "lucide:activity",
1937
+ get title() {
1938
+ return e.entity.friendly_name ?? e.entity.entity_id;
1939
+ },
1940
+ get subtitle() {
1941
+ return e.entity.entity_id;
1942
+ },
1943
+ get badge() {
1944
+ return N(we, { get children() {
1945
+ return e.entity.state;
1946
+ } });
1947
+ },
1948
+ get source() {
1949
+ return e.entity;
1950
+ },
1951
+ get children() {
1952
+ return [(() => {
1953
+ var t = Si();
1954
+ return F(t, N(H, {
1955
+ label: "Domain",
1956
+ get children() {
1957
+ return e.entity.domain;
1958
+ }
1959
+ }), null), F(t, N(w, {
1960
+ get when() {
1961
+ return e.entity.device_class;
1962
+ },
1963
+ children: (e) => N(H, {
1964
+ label: "Device class",
1965
+ get children() {
1966
+ return e();
1967
+ }
1968
+ })
1969
+ }), null), F(t, N(w, {
1970
+ get when() {
1971
+ return e.entity.area_id;
1972
+ },
1973
+ children: (e) => N(H, {
1974
+ label: "Area",
1975
+ get children() {
1976
+ return e();
1977
+ }
1978
+ })
1979
+ }), null), F(t, N(H, {
1980
+ label: "Changed",
1981
+ get children() {
1982
+ return Ni(e.entity.last_changed);
1983
+ }
1984
+ }), null), F(t, N(H, {
1985
+ label: "Updated",
1986
+ get children() {
1987
+ return Ni(e.entity.last_updated);
1988
+ }
1989
+ }), null), t;
1990
+ })(), N(w, {
1991
+ get when() {
1992
+ return Mi(t()) > 0;
1993
+ },
1994
+ get children() {
1995
+ return N(Fi, {
1996
+ label: "Attributes",
1997
+ get count() {
1998
+ return Mi(t());
1999
+ },
2000
+ get value() {
2001
+ return t();
2002
+ }
2003
+ });
2004
+ }
2005
+ })];
2006
+ }
2007
+ });
2008
+ }
2009
+ function zi(e) {
2010
+ let t = D(() => Object.keys(e.data).filter((e) => e !== "widgetConfig" && e !== "entities"));
2011
+ return N(We, { get children() {
2012
+ return [
2013
+ N(Ii, {
2014
+ icon: "lucide:sliders-horizontal",
2015
+ title: "Configuration",
2016
+ get source() {
2017
+ return e.data.widgetConfig;
2018
+ },
2019
+ get children() {
2020
+ return N(Li, { get record() {
2021
+ return e.data.widgetConfig;
2022
+ } });
637
2023
  }
2024
+ }),
2025
+ N(C, {
2026
+ get each() {
2027
+ return e.data.entities;
2028
+ },
2029
+ children: (e) => N(Ri, { entity: e })
2030
+ }),
2031
+ N(C, {
2032
+ get each() {
2033
+ return t();
2034
+ },
2035
+ children: (t) => N(Ii, {
2036
+ icon: "lucide:braces",
2037
+ get title() {
2038
+ return ki(t);
2039
+ },
2040
+ get source() {
2041
+ return e.data[t];
2042
+ },
2043
+ get children() {
2044
+ return N(Pi, { get value() {
2045
+ return e.data[t];
2046
+ } });
2047
+ }
2048
+ })
2049
+ })
2050
+ ];
2051
+ } });
2052
+ }
2053
+ function Bi(e) {
2054
+ if (typeof e != "object" || !e) return;
2055
+ let t = e;
2056
+ return Array.isArray(t.entities) && typeof t.widgetConfig == "object" ? t : void 0;
2057
+ }
2058
+ function Vi(e) {
2059
+ let t = D(() => Bi(e.data));
2060
+ return N(w, {
2061
+ get when() {
2062
+ return e.data !== void 0;
2063
+ },
2064
+ get fallback() {
2065
+ return N(Be, { get children() {
2066
+ return N(He, { get children() {
2067
+ return [N(Ue, { children: "Nothing to inspect" }), N(Ve, { children: "This widget publishes no debug information." })];
2068
+ } });
2069
+ } });
2070
+ },
2071
+ get children() {
2072
+ return N(w, {
2073
+ get when() {
2074
+ return t();
2075
+ },
2076
+ get fallback() {
2077
+ return N(Ii, {
2078
+ icon: "lucide:braces",
2079
+ title: "Debug data",
2080
+ get source() {
2081
+ return e.data;
2082
+ },
2083
+ get children() {
2084
+ return N(w, {
2085
+ get when() {
2086
+ return typeof e.data == "string";
2087
+ },
2088
+ get fallback() {
2089
+ return N(Pi, { get value() {
2090
+ return e.data;
2091
+ } });
2092
+ },
2093
+ get children() {
2094
+ return N(ut, {
2095
+ class: "overflow-hidden p-0",
2096
+ get children() {
2097
+ var t = Ci();
2098
+ return F(t, () => e.data), t;
2099
+ }
2100
+ });
2101
+ }
2102
+ });
2103
+ }
2104
+ });
2105
+ },
2106
+ children: (e) => N(zi, { get data() {
2107
+ return e();
2108
+ } })
638
2109
  });
639
2110
  }
640
2111
  });
641
2112
  }
642
- function un(e) {
643
- return (() => {
644
- var t = an();
645
- return P(t, (() => {
646
- var t = F(() => !!e.icon);
647
- return () => t() && (() => {
648
- var t = on();
649
- return P(t, () => e.icon), t;
650
- })();
651
- })(), null), P(t, (() => {
652
- var t = F(() => !!e.title);
653
- return () => t() && (() => {
654
- var t = sn();
655
- return P(t, () => e.title), t;
656
- })();
657
- })(), null), P(t, (() => {
658
- var t = F(() => !!e.message);
659
- return () => t() && (() => {
660
- var t = cn();
661
- return P(t, () => e.message), t;
662
- })();
663
- })(), null), t;
664
- })();
665
- }
666
- var H = ln;
667
- H.Content = Pt, H.Icon = Rt, H.Title = Ut, H.Status = Bt, H.Value = tn, H.SliderFill = Mt;
668
2113
  //#endregion
669
2114
  //#region src/framework/dialogs/validate-config.ts
670
- function dn(e) {
2115
+ function Hi(e) {
671
2116
  let t = "";
672
2117
  for (let n of e) t += typeof n == "number" ? `[${n}]` : t ? `.${String(n)}` : String(n);
673
2118
  return t;
674
2119
  }
675
- function fn(e, t) {
2120
+ function Ui(e, t) {
676
2121
  let n = e.safeParse(t);
677
2122
  return n.success ? null : n.error.issues.map((e) => {
678
- let t = dn(e.path);
2123
+ let t = Hi(e.path);
679
2124
  return t ? `${t}: ${e.message}` : e.message;
680
2125
  });
681
2126
  }
682
2127
  //#endregion
683
2128
  //#region src/framework/dialogs/WidgetDialog.tsx
684
- var pn = /*#__PURE__*/ L("<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\">"), mn = /*#__PURE__*/ L("<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"), hn = /*#__PURE__*/ L("<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>"), gn = /*#__PURE__*/ L("<div class=\"rounded-lg bg-muted/30 p-2 text-center md:p-6\"><p class=\"text-muted-foreground text-sm\">No additional controls"), _n = /*#__PURE__*/ L("<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\">"), vn = /*#__PURE__*/ L("<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"), yn = /*#__PURE__*/ L("<span class=\"inline-flex size-3.5 shrink-0 items-center\">"), bn = (e) => ft(e), xn = {
2129
+ var Wi = /*#__PURE__*/ B("<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\">"), Gi = /*#__PURE__*/ B("<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"), Ki = /*#__PURE__*/ B("<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>"), qi = /*#__PURE__*/ B("<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\">"), Ji = /*#__PURE__*/ B("<div class=glasshome-sheet>"), Yi = /*#__PURE__*/ B("<div class=glasshome-sheet-band aria-hidden=true><img alt>"), Xi = /*#__PURE__*/ B("<span class=\"glasshome-widget-icon glass glass-tint glasshome-sheet-icon\">"), Zi = /*#__PURE__*/ B("<span class=\"inline-flex size-3.5 shrink-0 items-center\">"), Qi = (e) => Wt(e), $i = {
685
2130
  sm: "sm",
686
2131
  md: "md",
687
2132
  lg: "lg",
@@ -690,20 +2135,24 @@ var pn = /*#__PURE__*/ L("<svg xmlns=http://www.w3.org/2000/svg class=size-3.5 f
690
2135
  "2xl": "xl",
691
2136
  "3xl": "xl",
692
2137
  "4xl": "full"
2138
+ }, ea = {
2139
+ idle: "Copy all",
2140
+ copied: "Copied",
2141
+ failed: "Copy failed"
693
2142
  };
694
- function Sn(e) {
695
- let [t] = ge(e, /* @__PURE__ */ "open.onOpenChange.title.description.onSave.hasUnsavedChanges.onDelete.editContent.controlsContent.debugContent.debugData.tabs.class.maxWidth.defaultTab.activeTab.onActiveTabChange.headerActions.configSchema.config.onConfigSave.ResponsiveDialog.ResponsiveDialogContent.ResponsiveDialogHeader.ResponsiveDialogTitle.ResponsiveDialogDescription.ResponsiveDialogBody.ResponsiveDialogFooter.Button.SchemaForm.Tabs.TabsList.TabsTrigger.TabsContent".split(".")), n = () => !!t.configSchema && !!t.config && !!t.onConfigSave && !!t.SchemaForm, [r, i] = O({}), [a, o] = O(null), [s, c] = O([]);
696
- E(pe(() => t.config, (e) => {
2143
+ function ta(e) {
2144
+ let [t] = _e(e, /* @__PURE__ */ "open.onOpenChange.title.description.onSave.hasUnsavedChanges.onDelete.editContent.controlsContent.sheet.tile.debugContent.debugData.tabs.class.maxWidth.defaultTab.activeTab.onActiveTabChange.headerActions.configSchema.config.onConfigSave.ResponsiveDialog.ResponsiveDialogContent.ResponsiveDialogHeader.ResponsiveDialogTitle.ResponsiveDialogDescription.ResponsiveDialogBody.ResponsiveDialogFooter.Button.SchemaForm.Tabs.TabsList.TabsTrigger.TabsContent".split(".")), n = () => !!t.configSchema && !!t.config && !!t.onConfigSave && !!t.SchemaForm, [r, i] = O({}), [a, o] = O(null), [s, c] = O([]);
2145
+ E(he(() => t.config, (e) => {
697
2146
  e && i({ ...e });
698
- })), E(pe(() => t.configSchema, (e) => {
699
- e && o(bn(e));
2147
+ })), E(he(() => t.configSchema, (e) => {
2148
+ e && o(Qi(e));
700
2149
  }));
701
2150
  let l = () => n() && JSON.stringify(r()) !== JSON.stringify(t.config), u = (e) => {
702
2151
  !e && t.config && (i({ ...t.config }), c([])), t.onOpenChange(e);
703
2152
  }, d = () => {
704
2153
  let e = t.configSchema;
705
2154
  if (e) {
706
- let t = fn(e, r());
2155
+ let t = Ui(e, r());
707
2156
  if (t) {
708
2157
  c(t);
709
2158
  return;
@@ -712,16 +2161,16 @@ function Sn(e) {
712
2161
  c([]), t.onConfigSave?.(r());
713
2162
  }, [f, p] = O(t.defaultTab ?? "controls"), m = () => t.activeTab ?? f(), h = (e) => {
714
2163
  t.onActiveTabChange ? t.onActiveTabChange(e) : p(e);
715
- }, g = () => xn[t.maxWidth ?? "xl"], _ = () => {
2164
+ }, g = () => $i[t.maxWidth ?? "xl"], _ = () => {
716
2165
  if (t.tabs) return t.tabs;
717
2166
  let e = [];
718
2167
  return e.push({
719
2168
  id: "edit",
720
2169
  label: "Edit",
721
- icon: pn(),
2170
+ icon: Wi(),
722
2171
  content: t.editContent ?? (() => {
723
2172
  let e = t.SchemaForm, o = n() ? a() : void 0;
724
- return !o || !e ? mn() : M(e, {
2173
+ return !o || !e ? Gi() : N(e, {
725
2174
  schema: o,
726
2175
  get data() {
727
2176
  return r();
@@ -735,161 +2184,250 @@ function Sn(e) {
735
2184
  }), e.push({
736
2185
  id: "controls",
737
2186
  label: "Controls",
738
- icon: hn(),
739
- content: t.controlsContent ?? gn()
2187
+ icon: Ki(),
2188
+ content: t.controlsContent ?? N(Be, { get children() {
2189
+ return N(He, { get children() {
2190
+ return [N(Ue, { children: "No controls" }), N(Ve, { children: "This widget is shown as is." })];
2191
+ } });
2192
+ } })
740
2193
  }), e.push({
741
2194
  id: "debug",
742
2195
  label: "Debug",
743
- icon: _n(),
744
- content: t.debugContent ?? vn()
2196
+ icon: qi(),
2197
+ content: t.debugContent ?? N(Vi, { get data() {
2198
+ return t.debugData;
2199
+ } })
745
2200
  }), e;
746
- }, v = async () => {
747
- if (t.debugData !== void 0) try {
748
- let e = typeof t.debugData == "string" ? t.debugData : JSON.stringify(t.debugData, null, 2);
749
- await navigator.clipboard.writeText(e);
750
- } catch {}
751
- }, ee = t.ResponsiveDialog, y = t.ResponsiveDialogContent, b = t.ResponsiveDialogHeader, te = t.ResponsiveDialogTitle, ne = t.ResponsiveDialogDescription, re = t.ResponsiveDialogBody ?? Le, ie = t.ResponsiveDialogFooter ?? He, ae = t.Tabs ?? nt, oe = t.TabsList ?? ot, se = t.TabsTrigger ?? ct, ce = t.TabsContent ?? it, x = t.Button, S = D(pe([
2201
+ }, v = A(W), y = rn(v);
2202
+ E(() => y?.setHasSheet(t.sheet !== void 0)), k(() => y?.setHasSheet(!1));
2203
+ let b = () => ({
2204
+ icon: t.tile?.icon ?? y?.icon(),
2205
+ tone: t.tile?.tone ?? y?.accent() ?? y?.tone(),
2206
+ backdrop: t.tile?.backdrop
2207
+ }), x = () => v?.developer?.() ?? !1, S = () => V() === "controls" && t.sheet !== void 0, ee = na(), te = () => v?.anchor?.(), ne = () => S() && !ee() && te() !== void 0, re = xr(), ie = () => {
2208
+ if (t.debugData === void 0) return;
2209
+ let e = typeof t.debugData == "string" ? t.debugData : JSON.stringify(t.debugData, null, 2);
2210
+ re.copy(e);
2211
+ }, ae = t.ResponsiveDialog, oe = t.ResponsiveDialogContent, se = t.ResponsiveDialogHeader, ce = t.ResponsiveDialogTitle, le = t.ResponsiveDialogDescription, ue = t.ResponsiveDialogBody ?? Qe, de = t.ResponsiveDialogFooter ?? rt, fe = t.Tabs ?? xt, pe = t.TabsList ?? Tt, T = t.TabsTrigger ?? Dt, me = t.TabsContent ?? Ct, ge = t.Button, j = D(he([
752
2212
  () => t.open,
753
2213
  a,
754
2214
  () => t.config,
755
2215
  () => t.tabs
756
- ], () => _())), le = (e) => n() ? u(e) : t.onOpenChange(e), ue = () => n() ? l() : t.hasUnsavedChanges, C = () => n() ? d : t.onSave, w = () => {
757
- let e = S(), t = m();
758
- return e.some((e) => e.id === t) ? t : e[0]?.id ?? t;
759
- }, fe = () => w() === "edit" && (C() || t.onDelete) || w() === "debug" && t.debugData !== void 0;
760
- return M(ee, {
2216
+ ], () => _())), M = (e) => n() ? u(e) : t.onOpenChange(e), ve = () => n() ? l() : t.hasUnsavedChanges, R = () => n() ? d : t.onSave, z = () => j().filter((e) => e.id !== "debug" || x()), B = () => z().filter((e) => e.id !== "controls" || t.sheet === void 0), V = () => {
2217
+ let e = z(), n = m() === "controls" && t.sheet === void 0 && !("controlsContent" in t) && !t.tabs ? "edit" : m();
2218
+ return e.some((e) => e.id === n) ? n : e[0]?.id ?? n;
2219
+ }, ye = () => V() === "edit" && (R() || t.onDelete) || V() === "debug" && t.debugData !== void 0;
2220
+ return N(ae, {
761
2221
  get open() {
762
2222
  return t.open;
763
2223
  },
764
- onOpenChange: (e) => le(e),
2224
+ onOpenChange: (e) => M(e),
765
2225
  get children() {
766
- return M(y, {
767
- get size() {
768
- return g();
769
- },
770
- get class() {
771
- return t.class;
2226
+ return N(w, {
2227
+ get when() {
2228
+ return !S();
772
2229
  },
773
- get children() {
774
- return M(ae, {
775
- get value() {
776
- return w();
2230
+ get fallback() {
2231
+ return N(oe, {
2232
+ size: "sm",
2233
+ get ariaLabel() {
2234
+ return t.title;
2235
+ },
2236
+ get anchor() {
2237
+ return I(() => !!ne())() ? te() : void 0;
2238
+ },
2239
+ class: "glasshome-sheet-surface",
2240
+ get style() {
2241
+ return I(() => !!b().tone)() ? {
2242
+ "--glass-tone": b().tone,
2243
+ "--widget-color": b().tone
2244
+ } : void 0;
777
2245
  },
778
- onChange: h,
779
- layout: "split",
780
2246
  get children() {
781
2247
  return [
782
- M(b, {
783
- class: "flex-wrap",
784
- get action() {
785
- return [M(oe, {
786
- class: "w-auto",
787
- get children() {
788
- return M(de, {
789
- get each() {
790
- return S();
2248
+ N(w, {
2249
+ get when() {
2250
+ return b().backdrop;
2251
+ },
2252
+ children: (e) => (() => {
2253
+ var t = Yi(), n = t.firstChild;
2254
+ return P(() => L(n, "src", e())), t;
2255
+ })()
2256
+ }),
2257
+ N(se, {
2258
+ class: "items-center",
2259
+ get media() {
2260
+ return N(w, {
2261
+ get when() {
2262
+ return b().icon;
2263
+ },
2264
+ children: (e) => (() => {
2265
+ var t = Xi();
2266
+ return F(t, N(U, {
2267
+ get icon() {
2268
+ return e();
791
2269
  },
792
- children: (e) => M(se, {
793
- get value() {
794
- return e.id;
795
- },
796
- get children() {
797
- return [(() => {
798
- var t = yn();
799
- return P(t, () => e.icon), t;
800
- })(), F(() => e.label)];
801
- }
802
- })
803
- });
804
- }
805
- }), F(() => t.headerActions)];
2270
+ class: "glasshome-widget-icon-glyph"
2271
+ })), t;
2272
+ })()
2273
+ });
806
2274
  },
807
2275
  get children() {
808
- return [M(te, {
2276
+ return N(ce, {
809
2277
  class: "truncate",
810
2278
  get children() {
811
2279
  return t.title;
812
2280
  }
813
- }), M(T, {
814
- get when() {
815
- return t.description;
816
- },
817
- get children() {
818
- return M(ne, { get children() {
819
- return t.description;
820
- } });
821
- }
822
- })];
2281
+ });
823
2282
  }
824
2283
  }),
825
- M(re, { get children() {
826
- return M(de, {
827
- get each() {
828
- return S();
829
- },
830
- children: (e) => M(ce, {
831
- get value() {
832
- return e.id;
833
- },
834
- get children() {
835
- return e.content;
836
- }
837
- })
838
- });
839
- } }),
840
- M(T, {
841
- get when() {
842
- return fe();
843
- },
844
- get children() {
845
- return M(ie, { get children() {
846
- return [
847
- M(T, {
2284
+ N(ue, { get children() {
2285
+ var e = Ji();
2286
+ return F(e, () => t.sheet?.()), e;
2287
+ } })
2288
+ ];
2289
+ }
2290
+ });
2291
+ },
2292
+ get children() {
2293
+ return N(oe, {
2294
+ get size() {
2295
+ return g();
2296
+ },
2297
+ get class() {
2298
+ return t.class;
2299
+ },
2300
+ get children() {
2301
+ return N(fe, {
2302
+ get value() {
2303
+ return V();
2304
+ },
2305
+ onChange: h,
2306
+ layout: "split",
2307
+ get children() {
2308
+ return [
2309
+ N(se, {
2310
+ class: "flex-wrap",
2311
+ get action() {
2312
+ return [N(w, {
848
2313
  get when() {
849
- return F(() => w() === "edit")() && t.onDelete;
2314
+ return x() || t.tabs !== void 0;
850
2315
  },
851
2316
  get children() {
852
- return M(x, {
853
- size: "sm",
854
- variant: "destructive",
855
- onClick: () => t.onDelete?.(),
856
- children: "Delete"
2317
+ return N(pe, {
2318
+ class: "w-auto",
2319
+ get children() {
2320
+ return N(C, {
2321
+ get each() {
2322
+ return B();
2323
+ },
2324
+ children: (e) => N(T, {
2325
+ get value() {
2326
+ return e.id;
2327
+ },
2328
+ get children() {
2329
+ return [(() => {
2330
+ var t = Zi();
2331
+ return F(t, () => e.icon), t;
2332
+ })(), I(() => e.label)];
2333
+ }
2334
+ })
2335
+ });
2336
+ }
857
2337
  });
858
2338
  }
859
- }),
860
- M(T, {
2339
+ }), I(() => t.headerActions)];
2340
+ },
2341
+ get children() {
2342
+ return [N(ce, {
2343
+ class: "truncate",
2344
+ get children() {
2345
+ return t.title;
2346
+ }
2347
+ }), N(w, {
861
2348
  get when() {
862
- return F(() => w() === "edit")() && C();
2349
+ return t.description;
863
2350
  },
864
2351
  get children() {
865
- return M(x, {
866
- size: "sm",
867
- get disabled() {
868
- return !ue();
869
- },
870
- onClick: () => C()?.(),
871
- children: "Save"
872
- });
2352
+ return N(le, { get children() {
2353
+ return t.description;
2354
+ } });
873
2355
  }
874
- }),
875
- M(T, {
876
- get when() {
877
- return F(() => w() === "debug")() && t.debugData !== void 0;
2356
+ })];
2357
+ }
2358
+ }),
2359
+ N(ue, { get children() {
2360
+ return N(C, {
2361
+ get each() {
2362
+ return z();
2363
+ },
2364
+ children: (e) => N(me, {
2365
+ get value() {
2366
+ return e.id;
878
2367
  },
879
2368
  get children() {
880
- return M(x, {
881
- size: "sm",
882
- variant: "outline",
883
- onClick: v,
884
- children: "Copy"
885
- });
2369
+ return e.content;
886
2370
  }
887
2371
  })
888
- ];
889
- } });
890
- }
891
- })
892
- ];
2372
+ });
2373
+ } }),
2374
+ N(w, {
2375
+ get when() {
2376
+ return ye();
2377
+ },
2378
+ get children() {
2379
+ return N(de, { get children() {
2380
+ return [
2381
+ N(w, {
2382
+ get when() {
2383
+ return I(() => V() === "edit")() && t.onDelete;
2384
+ },
2385
+ get children() {
2386
+ return N(ge, {
2387
+ size: "sm",
2388
+ variant: "destructive",
2389
+ onClick: () => t.onDelete?.(),
2390
+ children: "Delete"
2391
+ });
2392
+ }
2393
+ }),
2394
+ N(w, {
2395
+ get when() {
2396
+ return I(() => V() === "edit")() && R();
2397
+ },
2398
+ get children() {
2399
+ return N(ge, {
2400
+ size: "sm",
2401
+ get disabled() {
2402
+ return !ve();
2403
+ },
2404
+ onClick: () => R()?.(),
2405
+ children: "Save"
2406
+ });
2407
+ }
2408
+ }),
2409
+ N(w, {
2410
+ get when() {
2411
+ return I(() => V() === "debug")() && t.debugData !== void 0;
2412
+ },
2413
+ get children() {
2414
+ return N(ge, {
2415
+ size: "sm",
2416
+ variant: "outline",
2417
+ onClick: ie,
2418
+ get children() {
2419
+ return ea[re.state()];
2420
+ }
2421
+ });
2422
+ }
2423
+ })
2424
+ ];
2425
+ } });
2426
+ }
2427
+ })
2428
+ ];
2429
+ }
2430
+ });
893
2431
  }
894
2432
  });
895
2433
  }
@@ -897,27 +2435,34 @@ function Sn(e) {
897
2435
  }
898
2436
  });
899
2437
  }
2438
+ function na() {
2439
+ let e = "(max-width: 639px)", [t, n] = O(typeof window < "u" && window.matchMedia(e).matches);
2440
+ return ge(() => {
2441
+ let t = window.matchMedia(e), r = () => n(t.matches);
2442
+ t.addEventListener("change", r), k(() => t.removeEventListener("change", r));
2443
+ }), t;
2444
+ }
900
2445
  //#endregion
901
2446
  //#region src/framework/hooks/use-widget-dashboard.ts
902
- var Cn = {
2447
+ var ra = {
903
2448
  name: "",
904
2449
  icon: "",
905
2450
  areaId: null
906
2451
  };
907
- function wn() {
908
- let e = k(R);
909
- return () => e?.dashboard?.() ?? Cn;
2452
+ function ia() {
2453
+ let e = A(W);
2454
+ return () => e?.dashboard?.() ?? ra;
910
2455
  }
911
2456
  //#endregion
912
2457
  //#region src/framework/hooks/use-widget-viewer.ts
913
- var Tn = { name: null };
914
- function En() {
915
- let e = k(R);
916
- return () => e?.viewer?.() ?? Tn;
2458
+ var aa = { name: null };
2459
+ function oa() {
2460
+ let e = A(W);
2461
+ return () => e?.viewer?.() ?? aa;
917
2462
  }
918
2463
  //#endregion
919
2464
  //#region src/framework/hooks/use-intersection-pause.ts
920
- function Dn(e) {
2465
+ function sa(e) {
921
2466
  if (typeof IntersectionObserver > "u") return () => !1;
922
2467
  let [t, n] = O(!1), r = new IntersectionObserver((e) => {
923
2468
  let t = e[0];
@@ -926,50 +2471,72 @@ function Dn(e) {
926
2471
  return E(() => {
927
2472
  let t = e();
928
2473
  r.disconnect(), t && r.observe(t);
929
- }), me(() => r.disconnect()), t;
2474
+ }), k(() => r.disconnect()), t;
2475
+ }
2476
+ //#endregion
2477
+ //#region src/framework/hooks/use-daylight.ts
2478
+ var ca = -6, la = 864e5;
2479
+ function ua(e, t) {
2480
+ let n = e.next_rising ? Date.parse(e.next_rising) : NaN, r = e.next_setting ? Date.parse(e.next_setting) : NaN;
2481
+ if (!Number.isFinite(n) || !Number.isFinite(r)) return;
2482
+ let [i, a] = e.state === "above_horizon" ? [n - la, r] : [r - la, n], o = a - i;
2483
+ if (!(o <= 0)) return Math.min(1, Math.max(0, (t.getTime() - i) / o));
2484
+ }
2485
+ var da = 20, fa = 7;
2486
+ function pa(e, t) {
2487
+ if (e && (e.state === "above_horizon" || e.state === "below_horizon")) {
2488
+ let n = e.elevation, r = e.state === "above_horizon" ? "day" : n !== void 0 && n > ca ? e.rising ? "dawn" : "dusk" : "night";
2489
+ return {
2490
+ phase: r,
2491
+ isNight: r === "night",
2492
+ elevation: n,
2493
+ progress: ua(e, t)
2494
+ };
2495
+ }
2496
+ let n = t.getHours(), r = n >= da || n < fa ? "night" : "day";
2497
+ return {
2498
+ phase: r,
2499
+ isNight: r === "night"
2500
+ };
2501
+ }
2502
+ var [ma, ha] = O(/* @__PURE__ */ new Date()), ga = 0, _a;
2503
+ function va() {
2504
+ return ga++, _a ||= (ha(/* @__PURE__ */ new Date()), setInterval(() => ha(/* @__PURE__ */ new Date()), 6e4)), () => {
2505
+ ga--, ga === 0 && _a && (clearInterval(_a), _a = void 0);
2506
+ };
2507
+ }
2508
+ function ya() {
2509
+ let e = te("sun.sun");
2510
+ return E(() => {
2511
+ e() || k(va());
2512
+ }), D(() => {
2513
+ let t = e(), n = t ? {
2514
+ state: t.state,
2515
+ elevation: t.attributes?.elevation,
2516
+ rising: t.attributes?.rising,
2517
+ next_rising: t.attributes?.next_rising,
2518
+ next_setting: t.attributes?.next_setting
2519
+ } : void 0;
2520
+ return pa(n, n ? /* @__PURE__ */ new Date() : ma());
2521
+ });
930
2522
  }
931
2523
  //#endregion
932
2524
  //#region src/framework/hooks/use-reduced-motion.ts
933
- function On() {
2525
+ function ba() {
934
2526
  if (typeof window > "u" || typeof window.matchMedia != "function") return () => !1;
935
2527
  let e = window.matchMedia("(prefers-reduced-motion: reduce)"), [t, n] = O(e.matches), r = (e) => n(e.matches);
936
- return e.addEventListener("change", r), me(() => e.removeEventListener("change", r)), t;
937
- }
938
- //#endregion
939
- //#region src/framework/hooks/use-widget-dialog.ts
940
- function kn(e = "controls") {
941
- let [t, n] = O(!1), [r, i] = O(e), a = (t) => {
942
- i(t ?? e), n(!0);
943
- }, o = k(R);
944
- return o?.registerDialogOpener?.(a), me(() => o?.registerDialogOpener?.(null)), {
945
- showDialog: t,
946
- setShowDialog: n,
947
- openDialog: a,
948
- closeDialog: () => n(!1),
949
- activeTab: r,
950
- setActiveTab: i,
951
- dialogProps: {
952
- get open() {
953
- return t();
954
- },
955
- onOpenChange: n,
956
- get activeTab() {
957
- return r();
958
- },
959
- onActiveTabChange: i
960
- }
961
- };
2528
+ return e.addEventListener("change", r), k(() => e.removeEventListener("change", r)), t;
962
2529
  }
963
2530
  //#endregion
964
2531
  //#region src/framework/hooks/use-widget-entity-group.ts
965
- function An(e) {
2532
+ function xa(e) {
966
2533
  let t = e.minEntities ?? 1, n = D(() => e.entities().length), r = D(() => n() >= t), i = D(() => !r() || !e.calculateGroupData ? null : e.calculateGroupData(e.entities())), a = D(() => {
967
2534
  if (!r()) return;
968
2535
  let t = e.aggregationMode?.();
969
2536
  if (!t || t === "none") return;
970
2537
  let n = e.entities();
971
- if (t === "light" || t === "binary-sensor" || t === "switch") return Wt(n, e.allEntitiesMode);
972
- if (t === "sensor") return Gt(n, e.sensorGroupType?.() ?? "mean", !0);
2538
+ if (t === "light" || t === "binary-sensor" || t === "switch") return Sr(n, e.allEntitiesMode);
2539
+ if (t === "sensor") return Cr(n, e.sensorGroupType?.() ?? "mean", !0);
973
2540
  }), o = D(() => r() ? void 0 : e.emptyStateConfig);
974
2541
  return {
975
2542
  entities: e.entities,
@@ -981,264 +2548,8 @@ function An(e) {
981
2548
  };
982
2549
  }
983
2550
  //#endregion
984
- //#region src/framework/gestures/cursors.ts
985
- var U = 32, W = U / 2, G = "white", K = "rgba(0,0,0,0.4)", q = 2, J = 3;
986
- function jn(e) {
987
- return `url("data:image/svg+xml,${encodeURIComponent(e)}")`;
988
- }
989
- function Y(e) {
990
- return `<svg xmlns="http://www.w3.org/2000/svg" width="${U}" height="${U}" viewBox="0 0 ${U} ${U}">${e}</svg>`;
991
- }
992
- var Mn = Y(`
993
- <g transform="translate(6, 2)">
994
- <!-- shadow -->
995
- <g stroke="${K}" stroke-width="${J}" fill="none" stroke-linecap="round" stroke-linejoin="round">
996
- <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"/>
997
- </g>
998
- <!-- main -->
999
- <g stroke="${G}" stroke-width="${q}" fill="none" stroke-linecap="round" stroke-linejoin="round">
1000
- <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"/>
1001
- </g>
1002
- </g>
1003
- `), Nn = Y(`
1004
- <g>
1005
- <circle cx="${W}" cy="${W}" r="8" stroke="${K}" stroke-width="${J}" fill="none"/>
1006
- <circle cx="${W}" cy="${W}" r="8" stroke="${G}" stroke-width="1.5" fill="none"/>
1007
- <circle cx="${W}" cy="${W}" r="1.5" fill="${G}"/>
1008
- </g>
1009
- `), Pn = Y(`
1010
- <g>
1011
- <!-- shadow -->
1012
- <g stroke="${K}" stroke-width="${J}" fill="none" stroke-linecap="round" stroke-linejoin="round">
1013
- <line x1="6" y1="${W}" x2="26" y2="${W}"/>
1014
- <polyline points="10,12 6,${W} 10,20"/>
1015
- <polyline points="22,12 26,${W} 22,20"/>
1016
- </g>
1017
- <!-- main -->
1018
- <g stroke="${G}" stroke-width="${q}" fill="none" stroke-linecap="round" stroke-linejoin="round">
1019
- <line x1="6" y1="${W}" x2="26" y2="${W}"/>
1020
- <polyline points="10,12 6,${W} 10,20"/>
1021
- <polyline points="22,12 26,${W} 22,20"/>
1022
- </g>
1023
- <!-- center grip dots -->
1024
- <circle cx="${W}" cy="${W}" r="1.5" fill="${G}"/>
1025
- <circle cx="11" cy="${W}" r="1" fill="${G}" opacity="0.6"/>
1026
- <circle cx="21" cy="${W}" r="1" fill="${G}" opacity="0.6"/>
1027
- </g>
1028
- `), Fn = Y(`
1029
- <g>
1030
- <!-- shadow -->
1031
- <g stroke="${K}" stroke-width="${J}" fill="none" stroke-linecap="round" stroke-linejoin="round">
1032
- <line x1="${W}" y1="6" x2="${W}" y2="26"/>
1033
- <polyline points="12,10 ${W},6 20,10"/>
1034
- <polyline points="12,22 ${W},26 20,22"/>
1035
- </g>
1036
- <!-- main -->
1037
- <g stroke="${G}" stroke-width="${q}" fill="none" stroke-linecap="round" stroke-linejoin="round">
1038
- <line x1="${W}" y1="6" x2="${W}" y2="26"/>
1039
- <polyline points="12,10 ${W},6 20,10"/>
1040
- <polyline points="12,22 ${W},26 20,22"/>
1041
- </g>
1042
- <!-- center grip dots -->
1043
- <circle cx="${W}" cy="${W}" r="1.5" fill="${G}"/>
1044
- <circle cx="${W}" cy="11" r="1" fill="${G}" opacity="0.6"/>
1045
- <circle cx="${W}" cy="21" r="1" fill="${G}" opacity="0.6"/>
1046
- </g>
1047
- `), In = Y(`
1048
- <g>
1049
- <!-- shadow -->
1050
- <g stroke="${K}" stroke-width="${J}" fill="none" stroke-linecap="round" stroke-linejoin="round">
1051
- <line x1="7" y1="${W}" x2="25" y2="${W}"/>
1052
- <line x1="${W}" y1="7" x2="${W}" y2="25"/>
1053
- <polyline points="11,13 7,${W} 11,19"/>
1054
- <polyline points="21,13 25,${W} 21,19"/>
1055
- <polyline points="13,11 ${W},7 19,11"/>
1056
- <polyline points="13,21 ${W},25 19,21"/>
1057
- </g>
1058
- <!-- main -->
1059
- <g stroke="${G}" stroke-width="${q}" fill="none" stroke-linecap="round" stroke-linejoin="round">
1060
- <line x1="7" y1="${W}" x2="25" y2="${W}"/>
1061
- <line x1="${W}" y1="7" x2="${W}" y2="25"/>
1062
- <polyline points="11,13 7,${W} 11,19"/>
1063
- <polyline points="21,13 25,${W} 21,19"/>
1064
- <polyline points="13,11 ${W},7 19,11"/>
1065
- <polyline points="13,21 ${W},25 19,21"/>
1066
- </g>
1067
- <!-- center dot -->
1068
- <circle cx="${W}" cy="${W}" r="2" fill="${G}"/>
1069
- </g>
1070
- `);
1071
- function X(e, t, n) {
1072
- return {
1073
- css: `${jn(e)} ${t} ${n}, auto`,
1074
- hotspotX: t,
1075
- hotspotY: n
1076
- };
1077
- }
1078
- var Z = {
1079
- tap: X(Mn, 12, 4),
1080
- hold: X(Nn, 16, 16),
1081
- slideHorizontal: X(Pn, W, W),
1082
- slideVertical: X(Fn, W, W),
1083
- slideAuto: X(In, W, W)
1084
- };
1085
- //#endregion
1086
- //#region src/framework/gestures/haptics.ts
1087
- function Ln() {
1088
- if (typeof window > "u") return null;
1089
- let e = window;
1090
- return e.Capacitor?.isNativePlatform?.() ? e.Capacitor.Plugins?.Haptics ?? null : null;
1091
- }
1092
- function Rn(e) {
1093
- if (!(typeof navigator > "u" || typeof navigator.vibrate != "function")) try {
1094
- navigator.vibrate(e);
1095
- } catch {}
1096
- }
1097
- var zn = {
1098
- tick() {
1099
- let e = Ln();
1100
- if (e) {
1101
- e.impact({ style: "Light" }).catch(() => {});
1102
- return;
1103
- }
1104
- Rn(8);
1105
- },
1106
- bump() {
1107
- let e = Ln();
1108
- if (e) {
1109
- e.impact({ style: "Medium" }).catch(() => {});
1110
- return;
1111
- }
1112
- Rn(20);
1113
- },
1114
- pulse() {
1115
- let e = Ln();
1116
- if (e) {
1117
- e.impact({ style: "Heavy" }).catch(() => {});
1118
- return;
1119
- }
1120
- Rn([
1121
- 0,
1122
- 15,
1123
- 40,
1124
- 15
1125
- ]);
1126
- }
1127
- };
1128
- //#endregion
1129
- //#region src/framework/gestures/use-widget-gestures.ts
1130
- function Bn(e, t) {
1131
- let n = {
1132
- isDown: !1,
1133
- isTouch: !1,
1134
- startX: 0,
1135
- startY: 0,
1136
- startTime: 0,
1137
- hasMoved: !1,
1138
- sliding: !1,
1139
- holdTimer: null,
1140
- element: null
1141
- }, r = null, i = null, a = null, [o, s] = O(null);
1142
- function c(e) {
1143
- e !== i && (a && a.disconnect(), a = new ResizeObserver((e) => {
1144
- let t = e[0];
1145
- if (t) {
1146
- let e = t.borderBoxSize?.[0];
1147
- r = e ? {
1148
- width: e.inlineSize,
1149
- height: e.blockSize
1150
- } : {
1151
- width: t.contentRect.width,
1152
- height: t.contentRect.height
1153
- }, s(r.height > r.width);
1154
- }
1155
- }), i = e, a.observe(e), r = {
1156
- width: e.clientWidth,
1157
- height: e.clientHeight
1158
- }, s(r.height > r.width));
1159
- }
1160
- let l = () => {
1161
- n.holdTimer &&= (clearTimeout(n.holdTimer), null);
1162
- }, u = () => {
1163
- n.isDown = !1, n.hasMoved = !1, n.sliding = !1;
1164
- }, d = (n) => {
1165
- let i = e().slide;
1166
- 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";
1167
- }, f = (t) => {
1168
- let r = e();
1169
- if (r.tap || r.hold || r.slide) {
1170
- 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) {
1171
- let e = r.hold.delay ?? 300;
1172
- n.holdTimer = setTimeout(() => {
1173
- n.holdTimer = null, n.isDown && !n.hasMoved && (zn.bump(), r.hold?.action(), n.isDown = !1);
1174
- }, e);
1175
- }
1176
- if (!n.isTouch && r.slide) try {
1177
- t.currentTarget.setPointerCapture(t.pointerId);
1178
- } catch {}
1179
- }
1180
- }, p = (t) => {
1181
- if (!n.isDown) return;
1182
- let i = e(), a = t.clientX - n.startX, o = t.clientY - n.startY;
1183
- if (Math.sqrt(a * a + o * o) > 10 && (l(), n.hasMoved = !0), i.slide && n.hasMoved) {
1184
- let e = t.currentTarget, s = d(e);
1185
- if (n.isTouch && !n.sliding && Math.abs(s === "vertical" ? o : a) < Math.abs(s === "vertical" ? a : o)) return;
1186
- n.sliding = !0;
1187
- let c = i.slide.min ?? 0, l = i.slide.max ?? 100, u = l - c, f = s === "vertical" ? -o : a, p = r ?? {
1188
- width: e.clientWidth,
1189
- height: e.clientHeight
1190
- }, m = f / (s === "vertical" ? p.height : p.width) * u, h = Math.max(c, Math.min(l, i.slide.value + m));
1191
- i.slide.onChange(Math.round(h)), n.startX = t.clientX, n.startY = t.clientY, t.preventDefault();
1192
- }
1193
- }, m = (t) => {
1194
- let r = e(), i = n.isDown, a = Date.now() - n.startTime, o = r.hold?.delay ?? 300;
1195
- l(), i && r.tap && !n.hasMoved && a < o && r.tap();
1196
- try {
1197
- t.currentTarget.releasePointerCapture(t.pointerId);
1198
- } catch {}
1199
- u();
1200
- }, h = (e) => {
1201
- l();
1202
- try {
1203
- e.currentTarget.releasePointerCapture(e.pointerId);
1204
- } catch {}
1205
- u();
1206
- }, g = (t) => {
1207
- let n = e();
1208
- if (n.slide) {
1209
- let e = n.slide.orientation;
1210
- 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);
1211
- }
1212
- return n.tap ? Z.tap.css : n.hold ? Z.hold.css : "";
1213
- };
1214
- return {
1215
- onPointerDown: f,
1216
- onPointerMove: p,
1217
- onPointerUp: m,
1218
- onPointerCancel: h,
1219
- onPointerEnter: (e) => {
1220
- let t = e.currentTarget;
1221
- n.element = t, t.style.cursor = g(t);
1222
- },
1223
- bindElement: (e) => {
1224
- e && (n.element = e, c(e));
1225
- },
1226
- touchAction: () => {
1227
- let n = e();
1228
- if (n.slide) {
1229
- let e = n.slide.orientation;
1230
- return e === "vertical" || e !== "horizontal" && (o() ?? (t?.() ?? "horizontal") !== "horizontal") ? "pan-x" : "pan-y";
1231
- }
1232
- return n.tap || n.hold ? "manipulation" : "auto";
1233
- },
1234
- dispose: () => {
1235
- l(), a &&= (a.disconnect(), null), i = null, r = null;
1236
- }
1237
- };
1238
- }
1239
- //#endregion
1240
2551
  //#region src/framework/theming/svg-colors.ts
1241
- var Vn = {
2552
+ var Sa = {
1242
2553
  solar: "oklch(0.74 0.18 60)",
1243
2554
  grid: "oklch(0.62 0.12 245)",
1244
2555
  battery: "oklch(0.70 0.18 145)",
@@ -1247,21 +2558,21 @@ var Vn = {
1247
2558
  positive: "oklch(0.70 0.14 160)",
1248
2559
  negative: "oklch(0.64 0.22 27)"
1249
2560
  };
1250
- function Hn(e) {
2561
+ function Ca(e) {
1251
2562
  return {
1252
2563
  fill: `color-mix(in oklch, ${e} 20%, transparent)`,
1253
2564
  stroke: e,
1254
2565
  solid: e
1255
2566
  };
1256
2567
  }
1257
- var Un = Object.fromEntries(Object.entries(Vn).map(([e, t]) => [e, Hn(t)])), Wn = o.enum([
2568
+ var wa = Object.fromEntries(Object.entries(Sa).map(([e, t]) => [e, Ca(t)])), Ta = o.enum([
1258
2569
  "success",
1259
2570
  "warning",
1260
2571
  "danger",
1261
2572
  "info",
1262
2573
  "neutral",
1263
2574
  "accent"
1264
- ]), Gn = {
2575
+ ]), Ea = {
1265
2576
  title: e(() => o.string().optional().meta({
1266
2577
  title: "Title",
1267
2578
  description: "Optional display name override"
@@ -1281,62 +2592,63 @@ var Un = Object.fromEntries(Object.entries(Vn).map(([e, t]) => [e, Hn(t)])), Wn
1281
2592
  formType: "area-picker",
1282
2593
  title: "Area"
1283
2594
  }), "widgetFields.areaId")
1284
- }, Kn = 24;
1285
- function Q(e) {
2595
+ }, Da = 24;
2596
+ function $(e) {
1286
2597
  let t = {};
1287
2598
  for (let [n, r] of Object.entries(e)) r !== void 0 && (t[n] = r);
1288
2599
  return t;
1289
2600
  }
1290
- function qn() {
2601
+ function Oa() {
1291
2602
  return o.string().optional().meta({
1292
2603
  title: "Title",
1293
2604
  description: "Optional display name override"
1294
2605
  });
1295
2606
  }
1296
- function Jn(e) {
1297
- return (e.default === void 0 ? o.string().optional() : o.string().default(e.default)).meta(Q({
2607
+ function ka(e) {
2608
+ return (e.default === void 0 ? o.string().optional() : o.string().default(e.default)).meta($({
1298
2609
  title: e.title,
1299
2610
  description: e.description
1300
2611
  }));
1301
2612
  }
1302
- function Yn(e) {
2613
+ function Aa(e) {
1303
2614
  let t = o.number();
1304
- return e.min !== void 0 && (t = t.min(e.min)), e.max !== void 0 && (t = t.max(e.max)), (e.default === void 0 ? t.optional() : t.default(e.default)).meta(Q({
2615
+ return e.min !== void 0 && (t = t.min(e.min)), e.max !== void 0 && (t = t.max(e.max)), (e.default === void 0 ? t.optional() : t.default(e.default)).meta($({
1305
2616
  title: e.title,
1306
2617
  description: e.description
1307
2618
  }));
1308
2619
  }
1309
- function Xn(e) {
1310
- return o.boolean().default(e.default ?? !1).meta(Q({
2620
+ function ja(e) {
2621
+ return o.boolean().default(e.default ?? !1).meta($({
1311
2622
  title: e.title,
1312
2623
  description: e.description
1313
2624
  }));
1314
2625
  }
1315
- function Zn(e, t) {
2626
+ function Ma(e, t) {
1316
2627
  let n = o.enum(e);
1317
- return (t.default === void 0 ? n.optional() : n.default(t.default)).meta(Q({
2628
+ return (t.default === void 0 ? n.optional() : n.default(t.default)).meta($({
1318
2629
  title: t.title,
1319
2630
  description: t.description,
1320
- labels: t.labels
2631
+ labels: t.labels,
2632
+ icons: t.icons
1321
2633
  }));
1322
2634
  }
1323
- function Qn(e, t) {
1324
- return o.array(o.enum(e)).default([...t.default ?? []]).meta(Q({
2635
+ function Na(e, t) {
2636
+ return o.array(o.enum(e)).default([...t.default ?? []]).meta($({
1325
2637
  title: t.title,
1326
2638
  description: t.description,
1327
2639
  labels: t.labels
1328
2640
  }));
1329
2641
  }
1330
- function $n(e, t) {
1331
- return o.array(o.string()).default([]).meta(Q({
2642
+ function Pa(e, t) {
2643
+ return o.array(o.string()).default([]).meta($({
1332
2644
  domain: e,
1333
2645
  title: t?.title ?? "Entities",
1334
2646
  description: t?.description,
1335
2647
  deviceClass: t?.deviceClass
1336
2648
  }));
1337
2649
  }
1338
- function er(e, t) {
1339
- return o.array(o.string()).default([]).meta(Q({
2650
+ function Fa(e, t) {
2651
+ return o.array(o.string()).default([]).meta($({
1340
2652
  domain: e,
1341
2653
  title: t?.title ?? "Entity",
1342
2654
  description: t?.description,
@@ -1344,58 +2656,62 @@ function er(e, t) {
1344
2656
  singleSelect: !0
1345
2657
  }));
1346
2658
  }
1347
- function tr(e) {
2659
+ function Ia(e) {
1348
2660
  return o.string().optional().meta({
1349
2661
  formType: "area-picker",
1350
2662
  title: e?.title ?? "Area"
1351
2663
  });
1352
2664
  }
1353
- function nr(e) {
1354
- let t = o.string().meta(Q({
2665
+ function La(e) {
2666
+ let t = o.string().meta($({
1355
2667
  formType: "icon-picker",
1356
2668
  title: e?.title ?? "Icon",
1357
2669
  description: e?.description
1358
2670
  }));
1359
2671
  return e?.default === void 0 ? t.optional() : t.default(e.default);
1360
2672
  }
1361
- function rr(e) {
1362
- let t = o.string().meta(Q({
2673
+ function Ra(e) {
2674
+ let t = e?.presets && Object.fromEntries(Object.entries(e.presets).map(([e, t]) => [e, {
2675
+ label: t.label,
2676
+ thumb: t.thumb
2677
+ }])), n = o.string().meta($({
1363
2678
  formType: "image-picker",
1364
2679
  title: e?.title ?? "Image",
1365
- description: e?.description
2680
+ description: e?.description,
2681
+ presets: t
1366
2682
  }));
1367
- return e?.default === void 0 ? t.optional() : t.default(e.default);
2683
+ return e?.default === void 0 ? n.optional() : n.default(e.default);
1368
2684
  }
1369
- function ir(e) {
1370
- return o.array(o.string()).default([]).meta(Q({
2685
+ function za(e) {
2686
+ return o.array(o.string()).default([]).meta($({
1371
2687
  title: e.title,
1372
2688
  description: e.description
1373
2689
  }));
1374
2690
  }
1375
- function ar(e, t) {
2691
+ function Ba(e, t) {
1376
2692
  let n = o.object(e);
1377
- return n.default(pt(n)).meta({ title: t.title });
2693
+ return n.default(Gt(n)).meta({ title: t.title });
1378
2694
  }
1379
- function or(e) {
2695
+ function Va(e) {
1380
2696
  return e.def;
1381
2697
  }
1382
- function $(e) {
2698
+ function Ha(e) {
1383
2699
  if (o.globalRegistry.get(e)?.formType === "list") return !0;
1384
- let t = or(e);
1385
- return t.shape ? Object.values(t.shape).some($) : t.options ? t.options.some($) : t.element ? $(t.element) : t.innerType ? $(t.innerType) : !1;
2700
+ let t = Va(e);
2701
+ return t.shape ? Object.values(t.shape).some(Ha) : t.options ? t.options.some(Ha) : t.element ? Ha(t.element) : t.innerType ? Ha(t.innerType) : !1;
1386
2702
  }
1387
- function sr(e) {
1388
- let t = e, n = or(t).innerType;
1389
- for (; n;) t = n, n = or(t).innerType;
2703
+ function Ua(e) {
2704
+ let t = e, n = Va(t).innerType;
2705
+ for (; n;) t = n, n = Va(t).innerType;
1390
2706
  return t;
1391
2707
  }
1392
- function cr(e) {
1393
- let t = or(sr(e));
2708
+ function Wa(e) {
2709
+ let t = Va(Ua(e));
1394
2710
  if (t.shape) return new Set(Object.keys(t.shape));
1395
2711
  if (t.options) {
1396
2712
  let e = [];
1397
2713
  for (let n of t.options) {
1398
- let t = cr(n);
2714
+ let t = Wa(n);
1399
2715
  if (!t) return null;
1400
2716
  e.push(t);
1401
2717
  }
@@ -1407,7 +2723,7 @@ function cr(e) {
1407
2723
  }
1408
2724
  return null;
1409
2725
  }
1410
- function lr(e, t, n) {
2726
+ function Ga(e, t, n) {
1411
2727
  let r = { [t]: n };
1412
2728
  try {
1413
2729
  return e.parse(r);
@@ -1415,14 +2731,14 @@ function lr(e, t, n) {
1415
2731
  return r;
1416
2732
  }
1417
2733
  }
1418
- function ur(e, t) {
2734
+ function Ka(e, t) {
1419
2735
  if (!Number.isInteger(t.max) || t.max < 1) throw Error(`field.list: max must be a positive integer, got ${t.max}`);
1420
- if (t.max > Kn) throw Error(`field.list: max ${t.max} exceeds the ceiling of ${Kn}`);
2736
+ if (t.max > Da) throw Error(`field.list: max ${t.max} exceeds the ceiling of ${Da}`);
1421
2737
  if (t.min !== void 0 && (!Number.isInteger(t.min) || t.min < 0 || t.min > t.max)) throw Error(`field.list: min must be an integer between 0 and max, got ${t.min}`);
1422
- if ($(e)) throw Error("field.list: a list item cannot contain another field.list (depth 1 only)");
1423
- if (t.labelField !== void 0 && !cr(e)?.has(t.labelField)) throw Error(`field.list: labelField "${t.labelField}" must name a field present in every item`);
2738
+ if (Ha(e)) throw Error("field.list: a list item cannot contain another field.list (depth 1 only)");
2739
+ if (t.labelField !== void 0 && !Wa(e)?.has(t.labelField)) throw Error(`field.list: labelField "${t.labelField}" must name a field present in every item`);
1424
2740
  let n = o.array(e);
1425
- return t.min !== void 0 && (n = n.min(t.min)), n = n.max(t.max), n.default([]).meta(Q({
2741
+ return t.min !== void 0 && (n = n.min(t.min)), n = n.max(t.max), n.default([]).meta($({
1426
2742
  formType: "list",
1427
2743
  title: t.title,
1428
2744
  description: t.description,
@@ -1430,7 +2746,7 @@ function ur(e, t) {
1430
2746
  labelField: t.labelField
1431
2747
  }));
1432
2748
  }
1433
- function dr(e, t, n) {
2749
+ function qa(e, t, n) {
1434
2750
  let r = Object.keys(t)[0];
1435
2751
  if (r === void 0) throw Error("field.variants: at least one variant is required");
1436
2752
  if (n.shared && e in n.shared) throw Error(`field.variants: shared fields cannot redefine the discriminator "${e}"`);
@@ -1443,7 +2759,7 @@ function dr(e, t, n) {
1443
2759
  ...r,
1444
2760
  [e]: o.literal(t)
1445
2761
  })), a = o.discriminatedUnion(e, i), s = i[0];
1446
- return a.default(s ? lr(s, e, r) : {}).meta(Q({
2762
+ return a.default(s ? Ga(s, e, r) : {}).meta($({
1447
2763
  formType: "variants",
1448
2764
  discriminator: e,
1449
2765
  title: n.title,
@@ -1451,29 +2767,35 @@ function dr(e, t, n) {
1451
2767
  labels: n.labels
1452
2768
  }));
1453
2769
  }
1454
- var fr = {
1455
- title: qn,
1456
- text: Jn,
1457
- number: Yn,
1458
- toggle: Xn,
1459
- choice: Zn,
1460
- choices: Qn,
1461
- entities: $n,
1462
- entity: er,
1463
- area: tr,
1464
- icon: nr,
1465
- image: rr,
1466
- stringList: ir,
1467
- group: ar,
1468
- list: ur,
1469
- variants: dr
2770
+ var Ja = {
2771
+ title: Oa,
2772
+ text: ka,
2773
+ number: Aa,
2774
+ toggle: ja,
2775
+ choice: Ma,
2776
+ choices: Na,
2777
+ entities: Pa,
2778
+ entity: Fa,
2779
+ area: Ia,
2780
+ icon: La,
2781
+ image: Ra,
2782
+ stringList: za,
2783
+ group: Ba,
2784
+ list: Ka,
2785
+ variants: qa
1470
2786
  };
1471
- function pr(e) {
2787
+ function Ya(e) {
1472
2788
  return o.object(e);
1473
2789
  }
1474
2790
  //#endregion
2791
+ //#region src/framework/image-src.ts
2792
+ function Xa(e, t) {
2793
+ let n = It(e);
2794
+ return n === void 0 ? Rt(e) : t?.[n]?.src;
2795
+ }
2796
+ //#endregion
1475
2797
  //#region src/shared/spline.ts
1476
- function mr(e) {
2798
+ function Za(e) {
1477
2799
  if (e.length < 2) return "";
1478
2800
  let t = e[0], n = e[1];
1479
2801
  if (!t || !n) return "";
@@ -1500,14 +2822,14 @@ function mr(e) {
1500
2822
  }
1501
2823
  //#endregion
1502
2824
  //#region src/theme.ts
1503
- function hr() {
2825
+ function Qa() {
1504
2826
  return document.documentElement.classList.contains("dark");
1505
2827
  }
1506
2828
  //#endregion
1507
2829
  //#region src/version.ts
1508
- var gr = {
2830
+ var $a = {
1509
2831
  name: "@glasshome/widget-sdk",
1510
- version: "1.15.1",
2832
+ version: "1.17.0",
1511
2833
  description: "SDK for building GlassHome dashboard widgets with SolidJS",
1512
2834
  keywords: [
1513
2835
  "glasshome",
@@ -1566,12 +2888,12 @@ var gr = {
1566
2888
  "typecheck:test": "tsc --noEmit -p tsconfig.test.json"
1567
2889
  },
1568
2890
  peerDependencies: {
1569
- "@glasshome/sync-layer": "0.8.1",
1570
- "@glasshome/ui": "1.14.0",
2891
+ "@glasshome/sync-layer": "0.9.0",
2892
+ "@glasshome/ui": "1.20.0",
1571
2893
  "solid-js": "^1.9.11"
1572
2894
  },
1573
2895
  dependencies: {
1574
- "@glasshome/widget-contract": "0.2.1",
2896
+ "@glasshome/widget-contract": "0.3.0",
1575
2897
  "@modular-forms/solid": "^0.25.1",
1576
2898
  "@tailwindcss/vite": "^4.1.13",
1577
2899
  clsx: "^2.1.1",
@@ -1582,7 +2904,7 @@ var gr = {
1582
2904
  zod: "^4.1.13"
1583
2905
  },
1584
2906
  devDependencies: {
1585
- "@glasshome/ui": "1.14.0",
2907
+ "@glasshome/ui": "1.20.0",
1586
2908
  "@solidjs/testing-library": "^0.8.10",
1587
2909
  "@types/bun": "^1.4.0",
1588
2910
  "@types/node": "^25.2.2",
@@ -1603,4 +2925,4 @@ var gr = {
1603
2925
  engines: { node: ">=18" }
1604
2926
  }.version;
1605
2927
  //#endregion
1606
- export { xe as Badge, Se as Button, Ce as Carousel, we as CarouselContent, Te as CarouselDots, Ee as CarouselItem, De as CarouselNext, Oe as CarouselPrevious, ke as ColorSlider, Ae as ColorWheel, je as CountPill, Me as Icon, Ne as Input, Pe as Label, Fe as ResponsiveDialog, Ie as ResponsiveDialogBody, Re as ResponsiveDialogClose, ze as ResponsiveDialogContent, Be as ResponsiveDialogDescription, Ve as ResponsiveDialogFooter, Ue as ResponsiveDialogHeader, We as ResponsiveDialogTitle, gr as SDK_VERSION, Ge as SchemaForm, Ke as SectionIcon, qe as SectionTitle, Je as Select, Ye as SelectContent, Xe as SelectItem, Ze as SelectTrigger, Qe as SelectValue, $e as Slider, et as Switch, tt as Tabs, rt as TabsContent, at as TabsList, st as TabsTrigger, Wn as ToneSchema, H as Widget, Pt as WidgetContent, R as WidgetCtx, Sn as WidgetDialog, Rt as WidgetIcon, r as WidgetManifestSchema, xt as WidgetSizeCtx, Mt as WidgetSliderFill, Bt as WidgetStatus, Ut as WidgetTitle, tn as WidgetValue, g as byDomain, Wt as calculateLightGroup, Gt as calculateSensorGroup, Xt as countActiveEntities, pr as defineConfig, mt as defineWidget, t as deprecations, fr as field, n as formatDeprecation, i as formatSchemaError, Yt as getEntityAttribute, s as getForecasts, c as getStream, l as getWebRtcClientConfig, u as hassMediaUrl, lt as imageUrl, Ot as injectTokens, hr as isDark, Jt as isEntityActive, ut as mediaUrl, mr as monotoneCubicPath, dt as parseColor, d as sendWebRtcCandidate, f as startWebRtcSession, p as state, Un as svgColors, m as trackEntityHistory, h as untrackEntityHistory, _ as useArea, v as useCalendarEvents, ee as useCamera, y as useConnection, b as useCurrency, te as useEntities, ne as useEntity, re as useEntityHistory, ie as useEntityStatistics, ae as useForecast, oe as useHassConfig, Dn as useIntersectionPause, se as useLocale, On as useReducedMotion, _t as useService, x as useStore, S as useTemperatureUnit, bt as useToggle, yt as useTurnOff, vt as useTurnOn, w as useUnitSystem, ht as useWidgetContext, wn as useWidgetDashboard, kn as useWidgetDialog, St as useWidgetDimensions, An as useWidgetEntityGroup, Bn as useWidgetGestures, En as useWidgetViewer, Gn as widgetFields, a as z };
2928
+ export { Ce as Badge, Te as Button, De as ButtonGroup, ke as Carousel, Ae as CarouselContent, je as CarouselDots, Me as CarouselItem, Ne as CarouselNext, Pe as CarouselPrevious, Fe as ColorDisc, Ie as ColorSlider, Le as ColorWheel, Re as CountPill, Ke as Icon, qe as Input, Je as Label, vi as PanelEntityRow, ci as PanelFacts, si as PanelRow, oi as PanelRows, ai as PanelSection, Ye as Progress, Xe as ResponsiveDialog, Ze as ResponsiveDialogBody, $e as ResponsiveDialogClose, et as ResponsiveDialogContent, tt as ResponsiveDialogDescription, nt as ResponsiveDialogFooter, it as ResponsiveDialogHeader, at as ResponsiveDialogTitle, $a as SDK_VERSION, ot as SchemaForm, st as SectionIcon, dt as SectionTitle, ft as Select, pt as SelectContent, mt as SelectItem, ht as SelectTrigger, gt as SelectValue, _t as Slider, vt as SwatchPicker, yt as Switch, bt as Tabs, St as TabsContent, wt as TabsList, Et as TabsTrigger, Ot as TemperatureBar, kt as Toggle, At as ToggleGroup, Mt as ToggleGroupItem, Ta as ToneSchema, Z as Widget, Jn as WidgetAction, Zn as WidgetBackdrop, Yn as WidgetChip, qn as WidgetChoice, fr as WidgetContent, Gn as WidgetControls, W as WidgetCtx, Vi as WidgetDebugTab, zi as WidgetDebugView, ta as WidgetDialog, Qn as WidgetGlyph, Un as WidgetHead, Wn as WidgetHero, kn as WidgetIcon, Xn as WidgetLayer, r as WidgetManifestSchema, Sn as WidgetSizeCtx, lr as WidgetSliderFill, mr as WidgetStatus, Kn as WidgetStepper, _r as WidgetTitle, Nr as WidgetValue, wi as buildDebugData, g as byDomain, Sr as calculateLightGroup, Cr as calculateSensorGroup, vr as copyText, Or as countActiveEntities, Ya as defineConfig, Kt as defineWidget, t as deprecations, Ja as field, n as formatDeprecation, i as formatSchemaError, Dr as getEntityAttribute, s as getForecasts, c as getStream, l as getWebRtcClientConfig, u as hassMediaUrl, Ft as imagePreset, Xa as imageSrc, Lt as imageUrl, ir as injectTokens, Qa as isDark, Er as isEntityActive, _i as isPanelControllable, zt as mediaUrl, Za as monotoneCubicPath, Bt as parseColor, Vt as presetValue, d as sendWebRtcCandidate, f as startWebRtcSession, p as state, wa as svgColors, m as trackEntityHistory, h as untrackEntityHistory, _ as useArea, v as useCalendarEvents, y as useCamera, Tn as useConfirm, b as useConnection, xr as useCopyText, x as useCurrency, ya as useDaylight, S as useEntities, ee as useEntity, ne as useEntityHistory, re as useEntityStatistics, ie as useForecast, ae as useHassConfig, sa as useIntersectionPause, oe as useLocale, ba as useReducedMotion, Yt as useService, ce as useStore, le as useTemperatureUnit, Qt as useToggle, Zt as useTurnOff, Xt as useTurnOn, pe as useUnitSystem, qt as useWidgetContext, ia as useWidgetDashboard, $t as useWidgetDialog, Cn as useWidgetDimensions, xa as useWidgetEntityGroup, xn as useWidgetGestures, oa as useWidgetViewer, Ea as widgetFields, a as z };