@glasshome/widget-sdk 1.16.0 → 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 te, useEntities as ne, useEntity as re, useEntityHistory as ie, useEntityStatistics as ae, useForecast as oe, useHassConfig as se, useLocale as ce, useService as le, useStore as ue, useTemperatureUnit as b, useToggle as x, useTurnOff as de, useTurnOn as fe, useUnitSystem as S } from "@glasshome/sync-layer/solid";
6
- import { For as C, Show as w, createContext as T, createEffect as pe, createMemo as E, createSignal as D, on as me, onCleanup as O, 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 _e, style as ve, template as I, use as ye } from "solid-js/web";
8
- import { clsx as be } from "clsx";
9
- import { twMerge as xe } from "tailwind-merge";
10
- import { Accordion as Se, AccordionContent as Ce, AccordionItem as we, AccordionTrigger as Te, Badge as Ee, Badge as De, Button as Oe, Button as ke, Carousel as Ae, CarouselContent as je, CarouselDots as Me, CarouselItem as Ne, CarouselNext as Pe, CarouselPrevious 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 L, FieldGroup as We, FieldTitle as Ge, Icon as Ke, Icon as qe, Input as Je, Label 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, Switch as vt, Tabs as yt, Tabs as bt, TabsContent as xt, TabsContent as St, TabsList as Ct, TabsList as wt, TabsTrigger as Tt, TabsTrigger as Et, imageUrl as Dt, mediaUrl as Ot, parseColor as kt } 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 At(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 At(e) {
18
18
  } : e.jsonSchema;
19
19
  } });
20
20
  }
21
- function jt(e) {
21
+ function Gt(e) {
22
22
  try {
23
23
  return e.parse({});
24
24
  } catch {
@@ -27,99 +27,714 @@ function jt(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 = At(e.configSchema)), e.manifest.defaultConfig || (e.manifest.defaultConfig = jt(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 = T();
36
- function Nt() {
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 Pt(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(Pt(n), t, r, { entity_id: n });
50
+ await e(Jt(n), t, r, { entity_id: n });
51
51
  };
52
52
  }
53
- function Ft() {
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
- } : le();
57
+ turnOn: G(e, "turn_on"),
58
+ turnOff: G(e, "turn_off"),
59
+ toggle: G(e, "toggle")
60
+ } : se();
61
61
  }
62
- function It() {
63
- let e = k(R)?.callService;
64
- return e ? z(e, "turn_on") : fe();
62
+ function Xt() {
63
+ let e = A(W)?.callService;
64
+ return e ? G(e, "turn_on") : fe();
65
65
  }
66
- function Lt() {
67
- let e = k(R)?.callService;
68
- return e ? z(e, "turn_off") : de();
66
+ function Zt() {
67
+ let e = A(W)?.callService;
68
+ return e ? G(e, "turn_off") : de();
69
69
  }
70
- function Rt() {
71
- let e = k(R)?.callService;
72
- return e ? z(e, "toggle") : x();
70
+ function Qt() {
71
+ let e = A(W)?.callService;
72
+ return e ? G(e, "toggle") : ue();
73
73
  }
74
74
  //#endregion
75
75
  //#region src/framework/design-system/z-index.ts
76
- var B = {
76
+ var K = {
77
77
  BACKGROUND: 0,
78
78
  CONTENT: 10,
79
79
  OVERLAY: 20,
80
80
  ACTIONS: 30
81
- }, zt = T();
82
- function Bt() {
83
- let e = k(zt);
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;
130
+ }
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);
84
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).");
85
424
  return e;
86
425
  }
87
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
+ });
685
+ }
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
+ })();
691
+ }
692
+ function Zn(e) {
693
+ return (() => {
694
+ var t = zn();
695
+ return F(t, () => e.children), t;
696
+ })();
697
+ }
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
+ })();
706
+ }
707
+ //#endregion
88
708
  //#region src/framework/theming/tokens.css?raw
89
- var Vt = "/* 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 * 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: 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 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: 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", Ht = !1, Ut, Wt = /* @__PURE__ */ new WeakSet();
90
- function Gt() {
91
- return Ut || (Ut = new CSSStyleSheet(), Ut.replaceSync(Vt.replace(/:root\b/g, ":host").replace(/^\.dark\b/gm, ":host(.dark)"))), Ut;
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 Kt(e) {
713
+ function ir(e) {
94
714
  if (typeof ShadowRoot < "u" && e instanceof ShadowRoot) {
95
- if (Wt.has(e)) return;
96
- let t = Gt();
97
- e.adoptedStyleSheets.includes(t) || (e.adoptedStyleSheets = [...e.adoptedStyleSheets, t]), Wt.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 (Ht) 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
- Ht = !0;
724
+ er = !0;
105
725
  return;
106
726
  }
107
727
  let n = t.createElement("style");
108
- n.setAttribute("data-glasshome-tokens", ""), n.textContent = Vt, t.head.appendChild(n), Ht = !0;
728
+ n.setAttribute("data-glasshome-tokens", ""), n.textContent = $n, t.head.appendChild(n), er = !0;
109
729
  }
110
- //#endregion
111
- //#region src/framework/utils/cn.ts
112
- function V(...e) {
113
- return xe(be(e));
114
- }
115
- var qt = {
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
736
  "--widget-padding": "1.5rem",
122
- "--widget-backdrop": "blur(var(--glass-blur, 24px)) saturate(1.8)"
737
+ "--widget-backdrop": "blur(var(--glass-blur, var(--material-blur, 24px))) saturate(1.8)"
123
738
  } },
124
739
  layout: {
125
740
  type: "flex",
@@ -191,21 +806,21 @@ var qt = {
191
806
  }
192
807
  }
193
808
  };
194
- function Jt(e) {
195
- return qt[e];
809
+ function or(e) {
810
+ return ar[e];
196
811
  }
197
812
  //#endregion
198
813
  //#region src/framework/backgrounds/WidgetSliderFill.tsx
199
- var Yt = /*#__PURE__*/ I("<div>"), Xt = e(() => void 0, "sliderFill.color");
200
- function Zt(e) {
201
- return e.color !== void 0 && Xt(), (() => {
202
- var t = Yt();
203
- return N((n) => {
204
- 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 = {
205
820
  "--widget-fill-value": e.value,
206
- "z-index": B.BACKGROUND
821
+ "z-index": K.BACKGROUND
207
822
  };
208
- return r !== n.e && j(t, n.e = r), n.t = ve(t, i, n.t), n;
823
+ return r !== n.e && M(t, n.e = r), n.t = z(t, i, n.t), n;
209
824
  }, {
210
825
  e: void 0,
211
826
  t: void 0
@@ -214,55 +829,34 @@ function Zt(e) {
214
829
  }
215
830
  //#endregion
216
831
  //#region src/framework/components/WidgetContent.tsx
217
- var Qt = /*#__PURE__*/ I("<div>");
218
- function $t(e) {
219
- return (() => {
220
- var t = Qt();
221
- return P(t, () => e.children), N(() => j(t, V("glasshome-widget-content", e.class))), t;
222
- })();
223
- }
224
- //#endregion
225
- //#region src/framework/components/WidgetIcon.tsx
226
- var en = /*#__PURE__*/ I("<div class=\"glasshome-widget-icon glasshome-widget-icon-stack glasshome-widget-icon-stack-2 glass glass-tint\">"), tn = /*#__PURE__*/ I("<div class=\"glasshome-widget-icon glasshome-widget-icon-stack glasshome-widget-icon-stack-3 glass glass-tint\">"), nn = /*#__PURE__*/ I("<div><div class=\"glasshome-widget-icon-glyph flex items-center justify-center\">");
227
- function rn(e) {
228
- 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)));
229
837
  return (() => {
230
- var n = nn(), r = n.firstChild;
231
- return P(n, M(w, {
232
- get when() {
233
- return t() >= 2;
234
- },
235
- get children() {
236
- return en();
237
- }
238
- }), r), P(n, M(w, {
239
- get when() {
240
- return t() >= 3;
241
- },
242
- get children() {
243
- return tn();
244
- }
245
- }), r), P(r, () => e.icon), N((t) => {
246
- var r = V("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;
247
- return r !== t.e && j(n, t.e = r), t.t = ve(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;
248
842
  }, {
249
843
  e: void 0,
250
844
  t: void 0
251
- }), n;
845
+ }), t;
252
846
  })();
253
847
  }
254
848
  //#endregion
255
849
  //#region src/framework/components/WidgetStatus.tsx
256
- var an = /*#__PURE__*/ I("<p>");
257
- function on(e) {
850
+ var pr = /*#__PURE__*/ B("<p>");
851
+ function mr(e) {
258
852
  return (() => {
259
- var t = an();
260
- return P(t, (() => {
261
- var t = F(() => !!e.isUnavailable);
853
+ var t = pr();
854
+ return F(t, (() => {
855
+ var t = I(() => !!e.isUnavailable);
262
856
  return () => t() ? "Unavailable" : e.children;
263
- })()), N((n) => {
264
- var r = V("glasshome-widget-status", "relative", e.dimmed && "opacity-40", e.class), i = B.ACTIONS;
265
- return r !== n.e && j(t, n.e = r), i !== n.t && _e(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;
266
860
  }, {
267
861
  e: void 0,
268
862
  t: void 0
@@ -271,21 +865,21 @@ function on(e) {
271
865
  }
272
866
  //#endregion
273
867
  //#region src/framework/components/WidgetTitle.tsx
274
- var sn = /*#__PURE__*/ I("<span class=\"glasshome-widget-badge shrink-0\">"), cn = /*#__PURE__*/ I("<div><h3 class=glasshome-widget-title>");
275
- function ln(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) {
276
870
  return (() => {
277
- var t = cn(), n = t.firstChild;
278
- return P(n, () => e.children), P(t, M(w, {
871
+ var t = gr(), n = t.firstChild;
872
+ return F(n, () => e.children), F(t, N(w, {
279
873
  get when() {
280
- return F(() => e.badge !== void 0)() && e.badge > 0;
874
+ return I(() => e.badge !== void 0)() && e.badge > 0;
281
875
  },
282
876
  get children() {
283
- var t = sn();
284
- return P(t, () => e.badge), t;
877
+ var t = hr();
878
+ return F(t, () => e.badge), t;
285
879
  }
286
- }), null), N((n) => {
287
- var r = V("relative flex items-center gap-2", e.class), i = B.ACTIONS;
288
- return r !== n.e && j(t, n.e = r), i !== n.t && _e(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;
289
883
  }, {
290
884
  e: void 0,
291
885
  t: void 0
@@ -294,14 +888,14 @@ function ln(e) {
294
888
  }
295
889
  //#endregion
296
890
  //#region src/framework/utils/clipboard.ts
297
- async function un(e) {
891
+ async function vr(e) {
298
892
  if (navigator.clipboard?.writeText) try {
299
893
  return await navigator.clipboard.writeText(e), !0;
300
894
  } catch {}
301
- return dn(e);
895
+ return yr(e);
302
896
  }
303
- function dn(e) {
304
- let t = fn(), n = document.createElement("textarea");
897
+ function yr(e) {
898
+ let t = br(), n = document.createElement("textarea");
305
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);
306
900
  try {
307
901
  return n.focus(), n.select(), n.setSelectionRange(0, e.length), n.getRootNode().activeElement === n && document.execCommand("copy");
@@ -311,23 +905,23 @@ function dn(e) {
311
905
  n.remove(), t?.focus();
312
906
  }
313
907
  }
314
- function fn() {
908
+ function br() {
315
909
  let e = document.activeElement;
316
910
  for (; e?.shadowRoot?.activeElement;) e = e.shadowRoot.activeElement;
317
911
  return e instanceof HTMLElement ? e : null;
318
912
  }
319
- function pn(e = 2e3) {
320
- let [t, n] = D("idle"), r;
321
- return O(() => clearTimeout(r)), {
913
+ function xr(e = 2e3) {
914
+ let [t, n] = O("idle"), r;
915
+ return k(() => clearTimeout(r)), {
322
916
  state: t,
323
917
  copy: async (t) => {
324
- n(await un(t) ? "copied" : "failed"), clearTimeout(r), r = setTimeout(() => n("idle"), e);
918
+ n(await vr(t) ? "copied" : "failed"), clearTimeout(r), r = setTimeout(() => n("idle"), e);
325
919
  }
326
920
  };
327
921
  }
328
922
  //#endregion
329
923
  //#region src/framework/utils/entity-aggregation.ts
330
- function mn(e, t = !1) {
924
+ function Sr(e, t = !1) {
331
925
  if (e.length === 0) return {
332
926
  isGroup: !1,
333
927
  state: "unknown",
@@ -350,7 +944,7 @@ function mn(e, t = !1) {
350
944
  isUnavailable: t.state === "unavailable",
351
945
  brightness: r,
352
946
  brightnessPercent: i,
353
- color: _n(t),
947
+ color: Tr(t),
354
948
  onCount: +!!n,
355
949
  totalCount: 1,
356
950
  description: n ? "On" : "Off"
@@ -362,7 +956,7 @@ function mn(e, t = !1) {
362
956
  if (r++, t.attributes?.brightness !== void 0 && (s += t.attributes.brightness, c++), t.attributes?.rgb_color) l.push(t.attributes.rgb_color);
363
957
  else if (t.attributes?.hs_color) {
364
958
  let [e, n] = t.attributes.hs_color;
365
- l.push(gn(e, n));
959
+ l.push(wr(e, n));
366
960
  }
367
961
  break;
368
962
  case "off":
@@ -375,26 +969,26 @@ function mn(e, t = !1) {
375
969
  }
376
970
  let u = e.length, d = o === u, f = a + o === u, p = r > 0, m = r === u, h = i === u, g, _;
377
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);
378
- 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;
379
973
  if (l.length > 0) {
380
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;
381
- y = `rgb(${Math.round(e * r)}, ${Math.round(t * r)}, ${Math.round(n * r)})`;
382
- } else y = _n(e[0]);
383
- let te;
384
- return te = 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", {
385
979
  isGroup: n,
386
980
  state: g,
387
981
  isOn: _,
388
982
  isUnavailable: g === "unavailable",
389
983
  brightness: v,
390
- brightnessPercent: ee,
391
- color: y,
984
+ brightnessPercent: y,
985
+ color: b,
392
986
  onCount: r,
393
987
  totalCount: u,
394
- description: te
988
+ description: x
395
989
  };
396
990
  }
397
- function hn(e, t = "mean", n = !0) {
991
+ function Cr(e, t = "mean", n = !0) {
398
992
  if (e.length === 0) return {
399
993
  isGroup: !1,
400
994
  state: "unknown",
@@ -490,7 +1084,7 @@ function hn(e, t = "mean", n = !0) {
490
1084
  memberValues: a
491
1085
  };
492
1086
  }
493
- function gn(e, t) {
1087
+ function wr(e, t) {
494
1088
  let n = t / 100, r = n * (1 - Math.abs(e / 60 % 2 - 1)), i = 1 - n, a = 0, o = 0, s = 0;
495
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], [
496
1090
  (a + i) * 255,
@@ -498,7 +1092,7 @@ function gn(e, t) {
498
1092
  (s + i) * 255
499
1093
  ];
500
1094
  }
501
- function _n(e) {
1095
+ function Tr(e) {
502
1096
  if (e.state !== "on") return "rgb(100, 100, 100)";
503
1097
  let t = (e.attributes?.brightness ?? 255) / 255;
504
1098
  if (e.attributes?.rgb_color) {
@@ -506,7 +1100,7 @@ function _n(e) {
506
1100
  return `rgb(${Math.round(n * t)}, ${Math.round(r * t)}, ${Math.round(i * t)})`;
507
1101
  }
508
1102
  if (e.attributes?.hs_color) {
509
- let [n, r] = e.attributes.hs_color, [i, a, o] = gn(n, r);
1103
+ let [n, r] = e.attributes.hs_color, [i, a, o] = wr(n, r);
510
1104
  return `rgb(${Math.round(i * t)}, ${Math.round(a * t)}, ${Math.round(o * t)})`;
511
1105
  }
512
1106
  if (e.attributes?.color_temp) {
@@ -517,7 +1111,7 @@ function _n(e) {
517
1111
  }
518
1112
  //#endregion
519
1113
  //#region src/framework/utils/entity-state.ts
520
- function vn(e) {
1114
+ function Er(e) {
521
1115
  if (!e) return !1;
522
1116
  if ([
523
1117
  "on",
@@ -533,15 +1127,15 @@ function vn(e) {
533
1127
  }
534
1128
  return !1;
535
1129
  }
536
- function yn(e, t, n) {
1130
+ function Dr(e, t, n) {
537
1131
  return e?.attributes ? e.attributes[t] ?? n : n;
538
1132
  }
539
- function bn(e) {
540
- return e.filter(vn).length;
1133
+ function Or(e) {
1134
+ return e.filter(Er).length;
541
1135
  }
542
1136
  //#endregion
543
1137
  //#region src/framework/utils/format-value.ts
544
- function xn(e, t, n) {
1138
+ function kr(e, t, n) {
545
1139
  let { decimals: r, scale: i = !0 } = n || {};
546
1140
  if (typeof e == "string") return t ? `${e}${t}` : e;
547
1141
  if (e == null || Number.isNaN(e)) return t ? `--${t}` : "--";
@@ -552,41 +1146,47 @@ function xn(e, t, n) {
552
1146
  }
553
1147
  //#endregion
554
1148
  //#region src/framework/utils/interpret-value.ts
555
- function Sn(e, t) {
1149
+ function Ar(e, t) {
556
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;
557
1151
  }
558
1152
  //#endregion
559
1153
  //#region src/framework/components/WidgetValue.tsx
560
- var Cn = /*#__PURE__*/ I("<div class=glasshome-widget-subtitle>"), wn = /*#__PURE__*/ I("<div><div class=glasshome-widget-value>");
561
- 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) {
562
1156
  return (() => {
563
- var t = wn(), n = t.firstChild;
564
- return P(n, () => xn(e.value, e.unit)), P(t, M(w, {
1157
+ var t = Mr(), n = t.firstChild;
1158
+ return F(n, () => kr(e.value, e.unit)), F(t, N(w, {
565
1159
  get when() {
566
- return F(() => !!e.interpret)() && typeof e.value == "number";
1160
+ return I(() => !!e.interpret)() && typeof e.value == "number";
567
1161
  },
568
1162
  get children() {
569
- var t = Cn();
570
- return P(t, () => Sn(e.value, e.unit)), t;
1163
+ var t = jr();
1164
+ return F(t, () => Ar(e.value, e.unit)), t;
571
1165
  }
572
- }), null), N(() => j(t, V("flex flex-col", e.class))), t;
1166
+ }), null), P(() => M(t, X("flex flex-col", e.class))), t;
573
1167
  })();
574
1168
  }
575
1169
  //#endregion
576
1170
  //#region src/framework/core/Widget.tsx
577
- var En = /*#__PURE__*/ I("<div><div class=\"relative h-full w-full\">"), Dn = /*#__PURE__*/ I("<div class=\"glasshome-widget-loading pointer-events-none absolute inset-0 animate-pulse\">"), On = /*#__PURE__*/ I("<div class=\"flex h-full w-full flex-col items-center justify-center gap-2 text-center\">"), kn = /*#__PURE__*/ I("<div class=\"flex items-center justify-center text-muted-foreground\">"), An = /*#__PURE__*/ I("<h3 class=\"font-semibold text-sm text-foreground\">"), jn = /*#__PURE__*/ I("<p class=\"text-muted-foreground text-xs\">");
578
- function Mn(t) {
579
- let n = k(R), [r, i] = D(), [a, o] = D({
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({
580
1180
  width: 0,
581
1181
  height: 0
582
1182
  });
583
- pe(() => {
584
- let e = r();
1183
+ E(() => {
1184
+ let e = s();
585
1185
  if (!e) return;
586
1186
  let t = new ResizeObserver(([e]) => {
587
1187
  if (!e) return;
588
1188
  let t = e.borderBoxSize?.[0];
589
- o(t ? {
1189
+ u(t ? {
590
1190
  width: t.inlineSize,
591
1191
  height: t.blockSize
592
1192
  } : {
@@ -594,24 +1194,25 @@ function Mn(t) {
594
1194
  height: e.contentRect.height
595
1195
  });
596
1196
  });
597
- t.observe(e), O(() => t.disconnect());
598
- }), he(() => {
599
- let e = r()?.getRootNode();
600
- Kt(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);
601
1201
  });
602
- let s = {
1202
+ let d = {
1203
+ ...n,
603
1204
  updateConfig: n?.updateConfig ?? (() => {}),
604
- registerDialogOpener: n?.registerDialogOpener,
605
- callService: n?.callService,
606
- dimensions: e(() => a(), "ctx.dimensions")
607
- }, c = E(() => {
608
- if (t.variant) return typeof t.variant == "string" ? Jt(t.variant) : t.variant;
609
- }), l = e(() => t.gradient, "widget.gradient"), u = E(() => ({
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(() => ({
610
1211
  "container-type": "size",
611
1212
  "container-name": "widget",
612
- "touch-action": t.gestures && !t.isEditMode ? t.gestures.touchAction() : void 0,
613
- ...c()?.styles?.container,
614
- ...c()?.styles?.cssVars || {},
1213
+ "touch-action": o() && !t.isEditMode ? o()?.touchAction() : void 0,
1214
+ ...f()?.styles?.container,
1215
+ ...f()?.styles?.cssVars || {},
615
1216
  ...t.tone ? { "--widget-color": `var(--tone-${t.tone})` } : {},
616
1217
  ...t.color ? { "--widget-color": t.color } : {},
617
1218
  ...t.tone && t.tone !== "neutral" || t.color ? { "--glass-tone": "var(--widget-color)" } : {},
@@ -619,89 +1220,530 @@ function Mn(t) {
619
1220
  "--widget-color-to": t.colorTo,
620
1221
  "--glass-tone-2": t.colorTo
621
1222
  } : {},
622
- ...t.gradient ? { "background-image": l() } : {}
623
- })), d = () => !!t.gestures && !t.isEditMode, f = (e) => {
624
- d() && t.gestures?.onPointerEnter(e);
625
- }, p = (e) => {
626
- d() && t.gestures?.onPointerDown(e);
627
- }, m = (e) => {
628
- d() && t.gestures?.onPointerMove(e);
629
- }, h = (e) => {
630
- d() && t.gestures?.onPointerUp(e);
631
- }, g = (e) => {
632
- d() && t.gestures?.onPointerCancel(e);
633
- };
634
- return M(R.Provider, {
635
- value: s,
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,
636
1251
  get children() {
637
- return M(zt.Provider, {
638
- value: a,
1252
+ return N(Vn.Provider, {
1253
+ value: () => t.confirmed === !0,
639
1254
  get children() {
640
- var e = En(), n = e.firstChild;
641
- return A(e, "pointercancel", g), A(e, "pointerup", h), A(e, "pointermove", m), A(e, "pointerdown", p), A(e, "pointerenter", f), ye((e) => {
642
- i(e), t.gestures?.bindElement(e);
643
- }, e), P(n, (() => {
644
- var e = F(() => !!t.emptyState);
645
- return () => e() ? M(Nn, {
646
- get icon() {
647
- return t.emptyState.icon;
648
- },
649
- get title() {
650
- return t.emptyState.title;
651
- },
652
- get message() {
653
- return t.emptyState.message;
654
- }
655
- }) : t.children;
656
- })()), P(e, (() => {
657
- var e = F(() => !!t.loading);
658
- return () => e() && (() => {
659
- var e = Dn();
660
- return N((t) => _e(e, "z-index", B.OVERLAY)), e;
661
- })();
662
- })(), null), N((r) => {
663
- var i = V("glasshome-widget glass", "relative h-full w-full select-none overflow-hidden rounded-xl", c()?.styles?.class, t.class), a = u(), o = B.CONTENT;
664
- return i !== r.e && j(e, r.e = i), r.t = ve(e, a, r.t), o !== r.a && _e(n, "z-index", r.a = o), r;
665
- }, {
666
- e: void 0,
667
- t: void 0,
668
- a: void 0
669
- }), e;
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
+ });
670
1309
  }
671
1310
  });
672
1311
  }
673
1312
  });
674
1313
  }
675
- function Nn(e) {
1314
+ function Hr(e) {
676
1315
  return (() => {
677
- var t = On();
678
- return P(t, (() => {
679
- var t = F(() => !!e.icon);
1316
+ var t = Lr();
1317
+ return F(t, (() => {
1318
+ var t = I(() => !!e.icon);
680
1319
  return () => t() && (() => {
681
- var t = kn();
682
- return P(t, () => e.icon), t;
1320
+ var t = Rr();
1321
+ return F(t, () => e.icon), t;
683
1322
  })();
684
- })(), null), P(t, (() => {
685
- var t = F(() => !!e.title);
1323
+ })(), null), F(t, (() => {
1324
+ var t = I(() => !!e.title);
686
1325
  return () => t() && (() => {
687
- var t = An();
688
- return P(t, () => e.title), t;
1326
+ var t = zr();
1327
+ return F(t, () => e.title), t;
689
1328
  })();
690
- })(), null), P(t, (() => {
691
- var t = F(() => !!e.message);
1329
+ })(), null), F(t, (() => {
1330
+ var t = I(() => !!e.message);
692
1331
  return () => t() && (() => {
693
- var t = jn();
694
- return P(t, () => e.message), t;
1332
+ var t = Br();
1333
+ return F(t, () => e.message), t;
695
1334
  })();
696
1335
  })(), null), t;
697
1336
  })();
698
1337
  }
699
- var H = Mn;
700
- H.Content = $t, H.Icon = rn, H.Title = ln, H.Status = on, H.Value = Tn, H.SliderFill = Zt;
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;
1460
+ }, {
1461
+ e: void 0,
1462
+ t: void 0
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
+ }
701
1743
  //#endregion
702
1744
  //#region src/framework/dialogs/debug-view.tsx
703
- var Pn = /*#__PURE__*/ I("<pre class=\"max-h-64 overflow-auto p-3 font-mono text-muted-foreground text-xs leading-relaxed\">"), Fn = /*#__PURE__*/ I("<span class=\"flex items-center gap-2\">"), In = /*#__PURE__*/ I("<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\">"), Ln = /*#__PURE__*/ I("<div class=\"flex flex-col\">"), Rn = /*#__PURE__*/ I("<pre class=\"max-h-96 overflow-auto whitespace-pre-wrap p-3 font-mono text-muted-foreground text-xs leading-relaxed\">");
704
- function zn(e, t, n) {
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) {
705
1747
  return {
706
1748
  widgetConfig: e,
707
1749
  entities: t.map((e) => ({
@@ -718,18 +1760,18 @@ function zn(e, t, n) {
718
1760
  ...n
719
1761
  };
720
1762
  }
721
- var Bn = (e) => JSON.stringify(e, null, 2), Vn = {
1763
+ var Ti = (e) => JSON.stringify(e, null, 2), Ei = {
722
1764
  idle: "lucide:copy",
723
1765
  copied: "lucide:check",
724
1766
  failed: "lucide:triangle-alert"
725
- }, Hn = {
1767
+ }, Di = {
726
1768
  idle: "text-muted-foreground",
727
1769
  copied: "text-success",
728
1770
  failed: "text-destructive"
729
1771
  };
730
- function Un(e) {
731
- let { state: t, copy: n } = pn();
732
- return M(ke, {
1772
+ function Oi(e) {
1773
+ let { state: t, copy: n } = xr();
1774
+ return N(Ee, {
733
1775
  variant: "ghost",
734
1776
  size: "icon",
735
1777
  class: "size-8",
@@ -738,70 +1780,70 @@ function Un(e) {
738
1780
  },
739
1781
  onClick: () => void n(e.text()),
740
1782
  get children() {
741
- return M(qe, {
1783
+ return N(U, {
742
1784
  get icon() {
743
- return Vn[t()];
1785
+ return Ei[t()];
744
1786
  },
745
1787
  width: 16,
746
1788
  height: 16,
747
1789
  get class() {
748
- return Hn[t()];
1790
+ return Di[t()];
749
1791
  }
750
1792
  });
751
1793
  }
752
1794
  });
753
1795
  }
754
- function Wn(e) {
1796
+ function ki(e) {
755
1797
  let t = e.replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ");
756
1798
  return t.charAt(0).toUpperCase() + t.slice(1).toLowerCase();
757
1799
  }
758
- var Gn = (e) => typeof e != "object" || !e;
759
- function Kn(e) {
1800
+ var Ai = (e) => typeof e != "object" || !e;
1801
+ function ji(e) {
760
1802
  return e == null ? "None" : String(e);
761
1803
  }
762
- function qn(e) {
1804
+ function Mi(e) {
763
1805
  return Array.isArray(e) ? e.length : typeof e == "object" && e ? Object.keys(e).length : 0;
764
1806
  }
765
- function Jn(e) {
1807
+ function Ni(e) {
766
1808
  let t = new Date(e);
767
1809
  return Number.isNaN(t.getTime()) ? e : t.toLocaleString();
768
1810
  }
769
- function Yn(e) {
770
- return M(ut, {
1811
+ function Pi(e) {
1812
+ return N(ut, {
771
1813
  class: "overflow-hidden p-0",
772
1814
  get children() {
773
- var t = Pn();
774
- return P(t, () => Bn(e.value)), t;
1815
+ var t = yi();
1816
+ return F(t, () => Ti(e.value)), t;
775
1817
  }
776
1818
  });
777
1819
  }
778
- function Xn(e) {
779
- return M(Se, {
1820
+ function Fi(e) {
1821
+ return N(ye, {
780
1822
  collapsible: !0,
781
1823
  class: "border-border/50 border-t",
782
1824
  get children() {
783
- return M(we, {
1825
+ return N(xe, {
784
1826
  get value() {
785
1827
  return e.label;
786
1828
  },
787
1829
  get children() {
788
- return [M(Te, {
1830
+ return [N(Se, {
789
1831
  class: "py-3 text-muted-foreground text-xs",
790
1832
  get children() {
791
- var t = Fn();
792
- return P(t, () => e.label, null), P(t, M(w, {
1833
+ var t = bi();
1834
+ return F(t, () => e.label, null), F(t, N(w, {
793
1835
  get when() {
794
1836
  return e.count !== void 0;
795
1837
  },
796
1838
  get children() {
797
- return M(ze, { get children() {
1839
+ return N(ze, { get children() {
798
1840
  return e.count;
799
1841
  } });
800
1842
  }
801
1843
  }), null), t;
802
1844
  }
803
- }), M(Ce, { get children() {
804
- return M(Yn, { get value() {
1845
+ }), N(be, { get children() {
1846
+ return N(Pi, { get value() {
805
1847
  return e.value;
806
1848
  } });
807
1849
  } })];
@@ -810,77 +1852,77 @@ function Xn(e) {
810
1852
  }
811
1853
  });
812
1854
  }
813
- function U(e) {
1855
+ function Ii(e) {
814
1856
  return (() => {
815
- var t = In(), n = t.firstChild, r = n.firstChild, i = n.nextSibling;
816
- return P(n, M(ct, {
1857
+ var t = xi(), n = t.firstChild, r = n.firstChild, i = n.nextSibling;
1858
+ return F(n, N(ct, {
817
1859
  get icon() {
818
1860
  return e.icon;
819
1861
  },
820
1862
  size: "sm"
821
- }), r), P(r, M(Ge, {
1863
+ }), r), F(r, N(Ge, {
822
1864
  class: "truncate",
823
1865
  get children() {
824
1866
  return e.title;
825
1867
  }
826
- }), null), P(r, M(w, {
1868
+ }), null), F(r, N(w, {
827
1869
  get when() {
828
1870
  return e.subtitle;
829
1871
  },
830
- children: (e) => M(lt, {
1872
+ children: (e) => N(lt, {
831
1873
  class: "truncate font-mono",
832
1874
  get children() {
833
1875
  return e();
834
1876
  }
835
1877
  })
836
- }), null), P(n, () => e.badge, null), P(n, M(Un, {
1878
+ }), null), F(n, () => e.badge, null), F(n, N(Oi, {
837
1879
  get label() {
838
1880
  return `Copy ${e.title}`;
839
1881
  },
840
- text: () => Bn(e.source)
841
- }), null), P(i, () => e.children), t;
1882
+ text: () => Ti(e.source)
1883
+ }), null), F(i, () => e.children), t;
842
1884
  })();
843
1885
  }
844
- function Zn(e) {
845
- let t = E(() => Object.entries(e.record)), n = E(() => t().filter(([, e]) => Gn(e))), r = E(() => t().filter(([, e]) => !Gn(e)));
846
- return M(w, {
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, {
847
1889
  get when() {
848
1890
  return t().length > 0;
849
1891
  },
850
1892
  get fallback() {
851
- return M(lt, { children: "Nothing set" });
1893
+ return N(lt, { children: "Nothing set" });
852
1894
  },
853
1895
  get children() {
854
- return [M(w, {
1896
+ return [N(w, {
855
1897
  get when() {
856
1898
  return n().length > 0;
857
1899
  },
858
1900
  get children() {
859
- var e = Ln();
860
- return P(e, M(C, {
1901
+ var e = Si();
1902
+ return F(e, N(C, {
861
1903
  get each() {
862
1904
  return n();
863
1905
  },
864
- children: ([e, t]) => M(L, {
1906
+ children: ([e, t]) => N(H, {
865
1907
  get label() {
866
- return Wn(e);
1908
+ return ki(e);
867
1909
  },
868
1910
  get children() {
869
- return Kn(t);
1911
+ return ji(t);
870
1912
  }
871
1913
  })
872
1914
  })), e;
873
1915
  }
874
- }), M(C, {
1916
+ }), N(C, {
875
1917
  get each() {
876
1918
  return r();
877
1919
  },
878
- children: ([e, t]) => M(Xn, {
1920
+ children: ([e, t]) => N(Fi, {
879
1921
  get label() {
880
- return Wn(e);
1922
+ return ki(e);
881
1923
  },
882
1924
  get count() {
883
- return qn(t);
1925
+ return Mi(t);
884
1926
  },
885
1927
  value: t
886
1928
  })
@@ -888,9 +1930,9 @@ function Zn(e) {
888
1930
  }
889
1931
  });
890
1932
  }
891
- function Qn(e) {
1933
+ function Ri(e) {
892
1934
  let t = () => e.entity.attributes ?? {};
893
- return M(U, {
1935
+ return N(Ii, {
894
1936
  icon: "lucide:activity",
895
1937
  get title() {
896
1938
  return e.entity.friendly_name ?? e.entity.entity_id;
@@ -899,7 +1941,7 @@ function Qn(e) {
899
1941
  return e.entity.entity_id;
900
1942
  },
901
1943
  get badge() {
902
- return M(De, { get children() {
1944
+ return N(we, { get children() {
903
1945
  return e.entity.state;
904
1946
  } });
905
1947
  },
@@ -908,52 +1950,52 @@ function Qn(e) {
908
1950
  },
909
1951
  get children() {
910
1952
  return [(() => {
911
- var t = Ln();
912
- return P(t, M(L, {
1953
+ var t = Si();
1954
+ return F(t, N(H, {
913
1955
  label: "Domain",
914
1956
  get children() {
915
1957
  return e.entity.domain;
916
1958
  }
917
- }), null), P(t, M(w, {
1959
+ }), null), F(t, N(w, {
918
1960
  get when() {
919
1961
  return e.entity.device_class;
920
1962
  },
921
- children: (e) => M(L, {
1963
+ children: (e) => N(H, {
922
1964
  label: "Device class",
923
1965
  get children() {
924
1966
  return e();
925
1967
  }
926
1968
  })
927
- }), null), P(t, M(w, {
1969
+ }), null), F(t, N(w, {
928
1970
  get when() {
929
1971
  return e.entity.area_id;
930
1972
  },
931
- children: (e) => M(L, {
1973
+ children: (e) => N(H, {
932
1974
  label: "Area",
933
1975
  get children() {
934
1976
  return e();
935
1977
  }
936
1978
  })
937
- }), null), P(t, M(L, {
1979
+ }), null), F(t, N(H, {
938
1980
  label: "Changed",
939
1981
  get children() {
940
- return Jn(e.entity.last_changed);
1982
+ return Ni(e.entity.last_changed);
941
1983
  }
942
- }), null), P(t, M(L, {
1984
+ }), null), F(t, N(H, {
943
1985
  label: "Updated",
944
1986
  get children() {
945
- return Jn(e.entity.last_updated);
1987
+ return Ni(e.entity.last_updated);
946
1988
  }
947
1989
  }), null), t;
948
- })(), M(w, {
1990
+ })(), N(w, {
949
1991
  get when() {
950
- return qn(t()) > 0;
1992
+ return Mi(t()) > 0;
951
1993
  },
952
1994
  get children() {
953
- return M(Xn, {
1995
+ return N(Fi, {
954
1996
  label: "Attributes",
955
1997
  get count() {
956
- return qn(t());
1998
+ return Mi(t());
957
1999
  },
958
2000
  get value() {
959
2001
  return t();
@@ -964,42 +2006,42 @@ function Qn(e) {
964
2006
  }
965
2007
  });
966
2008
  }
967
- function $n(e) {
968
- let t = E(() => Object.keys(e.data).filter((e) => e !== "widgetConfig" && e !== "entities"));
969
- return M(We, { get children() {
2009
+ function zi(e) {
2010
+ let t = D(() => Object.keys(e.data).filter((e) => e !== "widgetConfig" && e !== "entities"));
2011
+ return N(We, { get children() {
970
2012
  return [
971
- M(U, {
2013
+ N(Ii, {
972
2014
  icon: "lucide:sliders-horizontal",
973
2015
  title: "Configuration",
974
2016
  get source() {
975
2017
  return e.data.widgetConfig;
976
2018
  },
977
2019
  get children() {
978
- return M(Zn, { get record() {
2020
+ return N(Li, { get record() {
979
2021
  return e.data.widgetConfig;
980
2022
  } });
981
2023
  }
982
2024
  }),
983
- M(C, {
2025
+ N(C, {
984
2026
  get each() {
985
2027
  return e.data.entities;
986
2028
  },
987
- children: (e) => M(Qn, { entity: e })
2029
+ children: (e) => N(Ri, { entity: e })
988
2030
  }),
989
- M(C, {
2031
+ N(C, {
990
2032
  get each() {
991
2033
  return t();
992
2034
  },
993
- children: (t) => M(U, {
2035
+ children: (t) => N(Ii, {
994
2036
  icon: "lucide:braces",
995
2037
  get title() {
996
- return Wn(t);
2038
+ return ki(t);
997
2039
  },
998
2040
  get source() {
999
2041
  return e.data[t];
1000
2042
  },
1001
2043
  get children() {
1002
- return M(Yn, { get value() {
2044
+ return N(Pi, { get value() {
1003
2045
  return e.data[t];
1004
2046
  } });
1005
2047
  }
@@ -1008,52 +2050,52 @@ function $n(e) {
1008
2050
  ];
1009
2051
  } });
1010
2052
  }
1011
- function er(e) {
2053
+ function Bi(e) {
1012
2054
  if (typeof e != "object" || !e) return;
1013
2055
  let t = e;
1014
2056
  return Array.isArray(t.entities) && typeof t.widgetConfig == "object" ? t : void 0;
1015
2057
  }
1016
- function tr(e) {
1017
- let t = E(() => er(e.data));
1018
- return M(w, {
2058
+ function Vi(e) {
2059
+ let t = D(() => Bi(e.data));
2060
+ return N(w, {
1019
2061
  get when() {
1020
2062
  return e.data !== void 0;
1021
2063
  },
1022
2064
  get fallback() {
1023
- return M(Be, { get children() {
1024
- return M(He, { get children() {
1025
- return [M(Ue, { children: "Nothing to inspect" }), M(Ve, { children: "This widget publishes no debug information." })];
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." })];
1026
2068
  } });
1027
2069
  } });
1028
2070
  },
1029
2071
  get children() {
1030
- return M(w, {
2072
+ return N(w, {
1031
2073
  get when() {
1032
2074
  return t();
1033
2075
  },
1034
2076
  get fallback() {
1035
- return M(U, {
2077
+ return N(Ii, {
1036
2078
  icon: "lucide:braces",
1037
2079
  title: "Debug data",
1038
2080
  get source() {
1039
2081
  return e.data;
1040
2082
  },
1041
2083
  get children() {
1042
- return M(w, {
2084
+ return N(w, {
1043
2085
  get when() {
1044
2086
  return typeof e.data == "string";
1045
2087
  },
1046
2088
  get fallback() {
1047
- return M(Yn, { get value() {
2089
+ return N(Pi, { get value() {
1048
2090
  return e.data;
1049
2091
  } });
1050
2092
  },
1051
2093
  get children() {
1052
- return M(ut, {
2094
+ return N(ut, {
1053
2095
  class: "overflow-hidden p-0",
1054
2096
  get children() {
1055
- var t = Rn();
1056
- return P(t, () => e.data), t;
2097
+ var t = Ci();
2098
+ return F(t, () => e.data), t;
1057
2099
  }
1058
2100
  });
1059
2101
  }
@@ -1061,7 +2103,7 @@ function tr(e) {
1061
2103
  }
1062
2104
  });
1063
2105
  },
1064
- children: (e) => M($n, { get data() {
2106
+ children: (e) => N(zi, { get data() {
1065
2107
  return e();
1066
2108
  } })
1067
2109
  });
@@ -1070,21 +2112,21 @@ function tr(e) {
1070
2112
  }
1071
2113
  //#endregion
1072
2114
  //#region src/framework/dialogs/validate-config.ts
1073
- function nr(e) {
2115
+ function Hi(e) {
1074
2116
  let t = "";
1075
2117
  for (let n of e) t += typeof n == "number" ? `[${n}]` : t ? `.${String(n)}` : String(n);
1076
2118
  return t;
1077
2119
  }
1078
- function rr(e, t) {
2120
+ function Ui(e, t) {
1079
2121
  let n = e.safeParse(t);
1080
2122
  return n.success ? null : n.error.issues.map((e) => {
1081
- let t = nr(e.path);
2123
+ let t = Hi(e.path);
1082
2124
  return t ? `${t}: ${e.message}` : e.message;
1083
2125
  });
1084
2126
  }
1085
2127
  //#endregion
1086
2128
  //#region src/framework/dialogs/WidgetDialog.tsx
1087
- var ir = /*#__PURE__*/ I("<svg xmlns=http://www.w3.org/2000/svg class=size-3.5 fill=none viewBox=\"0 0 24 24\"stroke=currentColor stroke-width=2><path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\"></path><path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\">"), ar = /*#__PURE__*/ I("<div class=\"rounded-lg bg-muted/30 p-2 text-center md:p-6\"><p class=\"text-muted-foreground text-sm\">No edit options available"), or = /*#__PURE__*/ I("<svg xmlns=http://www.w3.org/2000/svg class=size-3.5 fill=none viewBox=\"0 0 24 24\"stroke=currentColor stroke-width=2><line x1=4 y1=21 x2=4 y2=14></line><line x1=4 y1=10 x2=4 y2=3></line><line x1=12 y1=21 x2=12 y2=12></line><line x1=12 y1=8 x2=12 y2=3></line><line x1=20 y1=21 x2=20 y2=16></line><line x1=20 y1=12 x2=20 y2=3></line><line x1=1 y1=14 x2=7 y2=14></line><line x1=9 y1=8 x2=15 y2=8></line><line x1=17 y1=16 x2=23 y2=16>"), sr = /*#__PURE__*/ I("<svg xmlns=http://www.w3.org/2000/svg class=size-3.5 fill=none viewBox=\"0 0 24 24\"stroke=currentColor stroke-width=2><path d=\"m8 2 1.88 1.88\"></path><path d=\"M14.12 3.88 16 2\"></path><path d=\"M9 7.13v-1a3.003 3.003 0 1 1 6 0v1\"></path><path d=\"M12 20c-3.3 0-6-2.7-6-6v-3a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v3c0 3.3-2.7 6-6 6\"></path><path d=\"M12 20v-9\"></path><path d=\"M6.53 9C4.6 8.8 3 7.1 3 5\"></path><path d=\"M6 13H2\"></path><path d=\"M3 21c0-2.1 1.7-3.9 3.8-4\"></path><path d=\"M20.97 5c0 2.1-1.6 3.8-3.5 4\"></path><path d=\"M22 13h-4\"></path><path d=\"M17.2 17c2.1.1 3.8 1.9 3.8 4\">"), cr = /*#__PURE__*/ I("<span class=\"inline-flex size-3.5 shrink-0 items-center\">"), lr = (e) => At(e), ur = {
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 = {
1088
2130
  sm: "sm",
1089
2131
  md: "md",
1090
2132
  lg: "lg",
@@ -1093,42 +2135,42 @@ var ir = /*#__PURE__*/ I("<svg xmlns=http://www.w3.org/2000/svg class=size-3.5 f
1093
2135
  "2xl": "xl",
1094
2136
  "3xl": "xl",
1095
2137
  "4xl": "full"
1096
- }, dr = {
2138
+ }, ea = {
1097
2139
  idle: "Copy all",
1098
2140
  copied: "Copied",
1099
2141
  failed: "Copy failed"
1100
2142
  };
1101
- function fr(e) {
1102
- 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] = D({}), [a, o] = D(null), [s, c] = D([]);
1103
- pe(me(() => 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) => {
1104
2146
  e && i({ ...e });
1105
- })), pe(me(() => t.configSchema, (e) => {
1106
- e && o(lr(e));
2147
+ })), E(he(() => t.configSchema, (e) => {
2148
+ e && o(Qi(e));
1107
2149
  }));
1108
2150
  let l = () => n() && JSON.stringify(r()) !== JSON.stringify(t.config), u = (e) => {
1109
2151
  !e && t.config && (i({ ...t.config }), c([])), t.onOpenChange(e);
1110
2152
  }, d = () => {
1111
2153
  let e = t.configSchema;
1112
2154
  if (e) {
1113
- let t = rr(e, r());
2155
+ let t = Ui(e, r());
1114
2156
  if (t) {
1115
2157
  c(t);
1116
2158
  return;
1117
2159
  }
1118
2160
  }
1119
2161
  c([]), t.onConfigSave?.(r());
1120
- }, [f, p] = D(t.defaultTab ?? "controls"), m = () => t.activeTab ?? f(), h = (e) => {
2162
+ }, [f, p] = O(t.defaultTab ?? "controls"), m = () => t.activeTab ?? f(), h = (e) => {
1121
2163
  t.onActiveTabChange ? t.onActiveTabChange(e) : p(e);
1122
- }, g = () => ur[t.maxWidth ?? "xl"], _ = () => {
2164
+ }, g = () => $i[t.maxWidth ?? "xl"], _ = () => {
1123
2165
  if (t.tabs) return t.tabs;
1124
2166
  let e = [];
1125
2167
  return e.push({
1126
2168
  id: "edit",
1127
2169
  label: "Edit",
1128
- icon: ir(),
2170
+ icon: Wi(),
1129
2171
  content: t.editContent ?? (() => {
1130
2172
  let e = t.SchemaForm, o = n() ? a() : void 0;
1131
- return !o || !e ? ar() : M(e, {
2173
+ return !o || !e ? Gi() : N(e, {
1132
2174
  schema: o,
1133
2175
  get data() {
1134
2176
  return r();
@@ -1142,168 +2184,250 @@ function fr(e) {
1142
2184
  }), e.push({
1143
2185
  id: "controls",
1144
2186
  label: "Controls",
1145
- icon: or(),
1146
- content: t.controlsContent ?? M(Be, { get children() {
1147
- return M(He, { get children() {
1148
- return [M(Ue, { children: "No controls" }), M(Ve, { children: "This widget is shown as is." })];
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." })];
1149
2191
  } });
1150
2192
  } })
1151
2193
  }), e.push({
1152
2194
  id: "debug",
1153
2195
  label: "Debug",
1154
- icon: sr(),
1155
- content: t.debugContent ?? M(tr, { get data() {
2196
+ icon: qi(),
2197
+ content: t.debugContent ?? N(Vi, { get data() {
1156
2198
  return t.debugData;
1157
2199
  } })
1158
2200
  }), e;
1159
- }, v = pn(), ee = () => {
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 = () => {
1160
2208
  if (t.debugData === void 0) return;
1161
2209
  let e = typeof t.debugData == "string" ? t.debugData : JSON.stringify(t.debugData, null, 2);
1162
- v.copy(e);
1163
- }, y = t.ResponsiveDialog, te = t.ResponsiveDialogContent, ne = t.ResponsiveDialogHeader, re = t.ResponsiveDialogTitle, ie = t.ResponsiveDialogDescription, ae = t.ResponsiveDialogBody ?? Qe, oe = t.ResponsiveDialogFooter ?? rt, se = t.Tabs ?? bt, ce = t.TabsList ?? wt, le = t.TabsTrigger ?? Et, ue = t.TabsContent ?? St, b = t.Button, x = E(me([
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([
1164
2212
  () => t.open,
1165
2213
  a,
1166
2214
  () => t.config,
1167
2215
  () => t.tabs
1168
- ], () => _())), de = (e) => n() ? u(e) : t.onOpenChange(e), fe = () => n() ? l() : t.hasUnsavedChanges, S = () => n() ? d : t.onSave, T = () => {
1169
- let e = x(), t = m();
1170
- return e.some((e) => e.id === t) ? t : e[0]?.id ?? t;
1171
- }, O = () => T() === "edit" && (S() || t.onDelete) || T() === "debug" && t.debugData !== void 0;
1172
- return M(y, {
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, {
1173
2221
  get open() {
1174
2222
  return t.open;
1175
2223
  },
1176
- onOpenChange: (e) => de(e),
2224
+ onOpenChange: (e) => M(e),
1177
2225
  get children() {
1178
- return M(te, {
1179
- get size() {
1180
- return g();
1181
- },
1182
- get class() {
1183
- return t.class;
2226
+ return N(w, {
2227
+ get when() {
2228
+ return !S();
1184
2229
  },
1185
- get children() {
1186
- return M(se, {
1187
- get value() {
1188
- return T();
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;
1189
2245
  },
1190
- onChange: h,
1191
- layout: "split",
1192
2246
  get children() {
1193
2247
  return [
1194
- M(ne, {
1195
- class: "flex-wrap",
1196
- get action() {
1197
- return [M(ce, {
1198
- class: "w-auto",
1199
- get children() {
1200
- return M(C, {
1201
- get each() {
1202
- return x();
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();
1203
2269
  },
1204
- children: (e) => M(le, {
1205
- get value() {
1206
- return e.id;
1207
- },
1208
- get children() {
1209
- return [(() => {
1210
- var t = cr();
1211
- return P(t, () => e.icon), t;
1212
- })(), F(() => e.label)];
1213
- }
1214
- })
1215
- });
1216
- }
1217
- }), F(() => t.headerActions)];
2270
+ class: "glasshome-widget-icon-glyph"
2271
+ })), t;
2272
+ })()
2273
+ });
1218
2274
  },
1219
2275
  get children() {
1220
- return [M(re, {
2276
+ return N(ce, {
1221
2277
  class: "truncate",
1222
2278
  get children() {
1223
2279
  return t.title;
1224
2280
  }
1225
- }), M(w, {
1226
- get when() {
1227
- return t.description;
1228
- },
1229
- get children() {
1230
- return M(ie, { get children() {
1231
- return t.description;
1232
- } });
1233
- }
1234
- })];
2281
+ });
1235
2282
  }
1236
2283
  }),
1237
- M(ae, { get children() {
1238
- return M(C, {
1239
- get each() {
1240
- return x();
1241
- },
1242
- children: (e) => M(ue, {
1243
- get value() {
1244
- return e.id;
1245
- },
1246
- get children() {
1247
- return e.content;
1248
- }
1249
- })
1250
- });
1251
- } }),
1252
- M(w, {
1253
- get when() {
1254
- return O();
1255
- },
1256
- get children() {
1257
- return M(oe, { get children() {
1258
- return [
1259
- M(w, {
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, {
1260
2313
  get when() {
1261
- return F(() => T() === "edit")() && t.onDelete;
2314
+ return x() || t.tabs !== void 0;
1262
2315
  },
1263
2316
  get children() {
1264
- return M(b, {
1265
- size: "sm",
1266
- variant: "destructive",
1267
- onClick: () => t.onDelete?.(),
1268
- 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
+ }
1269
2337
  });
1270
2338
  }
1271
- }),
1272
- M(w, {
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, {
1273
2348
  get when() {
1274
- return F(() => T() === "edit")() && S();
2349
+ return t.description;
1275
2350
  },
1276
2351
  get children() {
1277
- return M(b, {
1278
- size: "sm",
1279
- get disabled() {
1280
- return !fe();
1281
- },
1282
- onClick: () => S()?.(),
1283
- children: "Save"
1284
- });
2352
+ return N(le, { get children() {
2353
+ return t.description;
2354
+ } });
1285
2355
  }
1286
- }),
1287
- M(w, {
1288
- get when() {
1289
- return F(() => T() === "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;
1290
2367
  },
1291
2368
  get children() {
1292
- return M(b, {
1293
- size: "sm",
1294
- variant: "outline",
1295
- onClick: ee,
1296
- get children() {
1297
- return dr[v.state()];
1298
- }
1299
- });
2369
+ return e.content;
1300
2370
  }
1301
2371
  })
1302
- ];
1303
- } });
1304
- }
1305
- })
1306
- ];
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
+ });
1307
2431
  }
1308
2432
  });
1309
2433
  }
@@ -1311,80 +2435,109 @@ function fr(e) {
1311
2435
  }
1312
2436
  });
1313
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
+ }
1314
2445
  //#endregion
1315
2446
  //#region src/framework/hooks/use-widget-dashboard.ts
1316
- var pr = {
2447
+ var ra = {
1317
2448
  name: "",
1318
2449
  icon: "",
1319
2450
  areaId: null
1320
2451
  };
1321
- function mr() {
1322
- let e = k(R);
1323
- return () => e?.dashboard?.() ?? pr;
2452
+ function ia() {
2453
+ let e = A(W);
2454
+ return () => e?.dashboard?.() ?? ra;
1324
2455
  }
1325
2456
  //#endregion
1326
2457
  //#region src/framework/hooks/use-widget-viewer.ts
1327
- var hr = { name: null };
1328
- function gr() {
1329
- let e = k(R);
1330
- return () => e?.viewer?.() ?? hr;
2458
+ var aa = { name: null };
2459
+ function oa() {
2460
+ let e = A(W);
2461
+ return () => e?.viewer?.() ?? aa;
1331
2462
  }
1332
2463
  //#endregion
1333
2464
  //#region src/framework/hooks/use-intersection-pause.ts
1334
- function _r(e) {
2465
+ function sa(e) {
1335
2466
  if (typeof IntersectionObserver > "u") return () => !1;
1336
- let [t, n] = D(!1), r = new IntersectionObserver((e) => {
2467
+ let [t, n] = O(!1), r = new IntersectionObserver((e) => {
1337
2468
  let t = e[0];
1338
2469
  t && n(!t.isIntersecting);
1339
2470
  });
1340
- return pe(() => {
2471
+ return E(() => {
1341
2472
  let t = e();
1342
2473
  r.disconnect(), t && r.observe(t);
1343
- }), O(() => r.disconnect()), t;
2474
+ }), k(() => r.disconnect()), t;
1344
2475
  }
1345
2476
  //#endregion
1346
- //#region src/framework/hooks/use-reduced-motion.ts
1347
- function vr() {
1348
- if (typeof window > "u" || typeof window.matchMedia != "function") return () => !1;
1349
- let e = window.matchMedia("(prefers-reduced-motion: reduce)"), [t, n] = D(e.matches), r = (e) => n(e.matches);
1350
- return e.addEventListener("change", r), O(() => e.removeEventListener("change", r)), t;
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
+ };
1351
2501
  }
1352
- //#endregion
1353
- //#region src/framework/hooks/use-widget-dialog.ts
1354
- function yr(e = "controls") {
1355
- let [t, n] = D(!1), [r, i] = D(e), a = (t) => {
1356
- i(t ?? e), n(!0);
1357
- }, o = k(R);
1358
- return o?.registerDialogOpener?.(a), O(() => o?.registerDialogOpener?.(null)), {
1359
- showDialog: t,
1360
- setShowDialog: n,
1361
- openDialog: a,
1362
- closeDialog: () => n(!1),
1363
- activeTab: r,
1364
- setActiveTab: i,
1365
- dialogProps: {
1366
- get open() {
1367
- return t();
1368
- },
1369
- onOpenChange: n,
1370
- get activeTab() {
1371
- return r();
1372
- },
1373
- onActiveTabChange: i
1374
- }
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);
1375
2506
  };
1376
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
+ });
2522
+ }
2523
+ //#endregion
2524
+ //#region src/framework/hooks/use-reduced-motion.ts
2525
+ function ba() {
2526
+ if (typeof window > "u" || typeof window.matchMedia != "function") return () => !1;
2527
+ let e = window.matchMedia("(prefers-reduced-motion: reduce)"), [t, n] = O(e.matches), r = (e) => n(e.matches);
2528
+ return e.addEventListener("change", r), k(() => e.removeEventListener("change", r)), t;
2529
+ }
1377
2530
  //#endregion
1378
2531
  //#region src/framework/hooks/use-widget-entity-group.ts
1379
- function br(e) {
1380
- let t = e.minEntities ?? 1, n = E(() => e.entities().length), r = E(() => n() >= t), i = E(() => !r() || !e.calculateGroupData ? null : e.calculateGroupData(e.entities())), a = E(() => {
2532
+ function xa(e) {
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(() => {
1381
2534
  if (!r()) return;
1382
2535
  let t = e.aggregationMode?.();
1383
2536
  if (!t || t === "none") return;
1384
2537
  let n = e.entities();
1385
- if (t === "light" || t === "binary-sensor" || t === "switch") return mn(n, e.allEntitiesMode);
1386
- if (t === "sensor") return hn(n, e.sensorGroupType?.() ?? "mean", !0);
1387
- }), o = E(() => r() ? void 0 : e.emptyStateConfig);
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);
2540
+ }), o = D(() => r() ? void 0 : e.emptyStateConfig);
1388
2541
  return {
1389
2542
  entities: e.entities,
1390
2543
  groupData: i,
@@ -1395,264 +2548,8 @@ function br(e) {
1395
2548
  };
1396
2549
  }
1397
2550
  //#endregion
1398
- //#region src/framework/gestures/cursors.ts
1399
- var W = 32, G = W / 2, K = "white", q = "rgba(0,0,0,0.4)", xr = 2, J = 3;
1400
- function Sr(e) {
1401
- return `url("data:image/svg+xml,${encodeURIComponent(e)}")`;
1402
- }
1403
- function Y(e) {
1404
- return `<svg xmlns="http://www.w3.org/2000/svg" width="${W}" height="${W}" viewBox="0 0 ${W} ${W}">${e}</svg>`;
1405
- }
1406
- var Cr = Y(`
1407
- <g transform="translate(6, 2)">
1408
- <!-- shadow -->
1409
- <g stroke="${q}" stroke-width="${J}" fill="none" stroke-linecap="round" stroke-linejoin="round">
1410
- <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"/>
1411
- </g>
1412
- <!-- main -->
1413
- <g stroke="${K}" stroke-width="${xr}" fill="none" stroke-linecap="round" stroke-linejoin="round">
1414
- <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"/>
1415
- </g>
1416
- </g>
1417
- `), wr = Y(`
1418
- <g>
1419
- <circle cx="${G}" cy="${G}" r="8" stroke="${q}" stroke-width="${J}" fill="none"/>
1420
- <circle cx="${G}" cy="${G}" r="8" stroke="${K}" stroke-width="1.5" fill="none"/>
1421
- <circle cx="${G}" cy="${G}" r="1.5" fill="${K}"/>
1422
- </g>
1423
- `), Tr = Y(`
1424
- <g>
1425
- <!-- shadow -->
1426
- <g stroke="${q}" stroke-width="${J}" fill="none" stroke-linecap="round" stroke-linejoin="round">
1427
- <line x1="6" y1="${G}" x2="26" y2="${G}"/>
1428
- <polyline points="10,12 6,${G} 10,20"/>
1429
- <polyline points="22,12 26,${G} 22,20"/>
1430
- </g>
1431
- <!-- main -->
1432
- <g stroke="${K}" stroke-width="${xr}" fill="none" stroke-linecap="round" stroke-linejoin="round">
1433
- <line x1="6" y1="${G}" x2="26" y2="${G}"/>
1434
- <polyline points="10,12 6,${G} 10,20"/>
1435
- <polyline points="22,12 26,${G} 22,20"/>
1436
- </g>
1437
- <!-- center grip dots -->
1438
- <circle cx="${G}" cy="${G}" r="1.5" fill="${K}"/>
1439
- <circle cx="11" cy="${G}" r="1" fill="${K}" opacity="0.6"/>
1440
- <circle cx="21" cy="${G}" r="1" fill="${K}" opacity="0.6"/>
1441
- </g>
1442
- `), Er = Y(`
1443
- <g>
1444
- <!-- shadow -->
1445
- <g stroke="${q}" stroke-width="${J}" fill="none" stroke-linecap="round" stroke-linejoin="round">
1446
- <line x1="${G}" y1="6" x2="${G}" y2="26"/>
1447
- <polyline points="12,10 ${G},6 20,10"/>
1448
- <polyline points="12,22 ${G},26 20,22"/>
1449
- </g>
1450
- <!-- main -->
1451
- <g stroke="${K}" stroke-width="${xr}" fill="none" stroke-linecap="round" stroke-linejoin="round">
1452
- <line x1="${G}" y1="6" x2="${G}" y2="26"/>
1453
- <polyline points="12,10 ${G},6 20,10"/>
1454
- <polyline points="12,22 ${G},26 20,22"/>
1455
- </g>
1456
- <!-- center grip dots -->
1457
- <circle cx="${G}" cy="${G}" r="1.5" fill="${K}"/>
1458
- <circle cx="${G}" cy="11" r="1" fill="${K}" opacity="0.6"/>
1459
- <circle cx="${G}" cy="21" r="1" fill="${K}" opacity="0.6"/>
1460
- </g>
1461
- `), Dr = Y(`
1462
- <g>
1463
- <!-- shadow -->
1464
- <g stroke="${q}" stroke-width="${J}" fill="none" stroke-linecap="round" stroke-linejoin="round">
1465
- <line x1="7" y1="${G}" x2="25" y2="${G}"/>
1466
- <line x1="${G}" y1="7" x2="${G}" y2="25"/>
1467
- <polyline points="11,13 7,${G} 11,19"/>
1468
- <polyline points="21,13 25,${G} 21,19"/>
1469
- <polyline points="13,11 ${G},7 19,11"/>
1470
- <polyline points="13,21 ${G},25 19,21"/>
1471
- </g>
1472
- <!-- main -->
1473
- <g stroke="${K}" stroke-width="${xr}" fill="none" stroke-linecap="round" stroke-linejoin="round">
1474
- <line x1="7" y1="${G}" x2="25" y2="${G}"/>
1475
- <line x1="${G}" y1="7" x2="${G}" y2="25"/>
1476
- <polyline points="11,13 7,${G} 11,19"/>
1477
- <polyline points="21,13 25,${G} 21,19"/>
1478
- <polyline points="13,11 ${G},7 19,11"/>
1479
- <polyline points="13,21 ${G},25 19,21"/>
1480
- </g>
1481
- <!-- center dot -->
1482
- <circle cx="${G}" cy="${G}" r="2" fill="${K}"/>
1483
- </g>
1484
- `);
1485
- function X(e, t, n) {
1486
- return {
1487
- css: `${Sr(e)} ${t} ${n}, auto`,
1488
- hotspotX: t,
1489
- hotspotY: n
1490
- };
1491
- }
1492
- var Z = {
1493
- tap: X(Cr, 12, 4),
1494
- hold: X(wr, 16, 16),
1495
- slideHorizontal: X(Tr, G, G),
1496
- slideVertical: X(Er, G, G),
1497
- slideAuto: X(Dr, G, G)
1498
- };
1499
- //#endregion
1500
- //#region src/framework/gestures/haptics.ts
1501
- function Or() {
1502
- if (typeof window > "u") return null;
1503
- let e = window;
1504
- return e.Capacitor?.isNativePlatform?.() ? e.Capacitor.Plugins?.Haptics ?? null : null;
1505
- }
1506
- function kr(e) {
1507
- if (typeof navigator < "u" && typeof navigator.vibrate == "function") try {
1508
- navigator.vibrate(e);
1509
- } catch {}
1510
- }
1511
- var Ar = {
1512
- tick() {
1513
- let e = Or();
1514
- if (e) {
1515
- e.impact({ style: "Light" }).catch(() => {});
1516
- return;
1517
- }
1518
- kr(8);
1519
- },
1520
- bump() {
1521
- let e = Or();
1522
- if (e) {
1523
- e.impact({ style: "Medium" }).catch(() => {});
1524
- return;
1525
- }
1526
- kr(20);
1527
- },
1528
- pulse() {
1529
- let e = Or();
1530
- if (e) {
1531
- e.impact({ style: "Heavy" }).catch(() => {});
1532
- return;
1533
- }
1534
- kr([
1535
- 0,
1536
- 15,
1537
- 40,
1538
- 15
1539
- ]);
1540
- }
1541
- };
1542
- //#endregion
1543
- //#region src/framework/gestures/use-widget-gestures.ts
1544
- function jr(e, t) {
1545
- let n = {
1546
- isDown: !1,
1547
- isTouch: !1,
1548
- startX: 0,
1549
- startY: 0,
1550
- startTime: 0,
1551
- hasMoved: !1,
1552
- sliding: !1,
1553
- holdTimer: null,
1554
- element: null
1555
- }, r = null, i = null, a = null, [o, s] = D(null);
1556
- function c(e) {
1557
- e !== i && (a && a.disconnect(), a = new ResizeObserver((e) => {
1558
- let t = e[0];
1559
- if (t) {
1560
- let e = t.borderBoxSize?.[0];
1561
- r = e ? {
1562
- width: e.inlineSize,
1563
- height: e.blockSize
1564
- } : {
1565
- width: t.contentRect.width,
1566
- height: t.contentRect.height
1567
- }, s(r.height > r.width);
1568
- }
1569
- }), i = e, a.observe(e), r = {
1570
- width: e.clientWidth,
1571
- height: e.clientHeight
1572
- }, s(r.height > r.width));
1573
- }
1574
- let l = () => {
1575
- n.holdTimer &&= (clearTimeout(n.holdTimer), null);
1576
- }, u = () => {
1577
- n.isDown = !1, n.hasMoved = !1, n.sliding = !1;
1578
- }, d = (n) => {
1579
- let i = e().slide;
1580
- 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";
1581
- }, f = (t) => {
1582
- let r = e();
1583
- if (r.tap || r.hold || r.slide) {
1584
- 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) {
1585
- let e = r.hold.delay ?? 300;
1586
- n.holdTimer = setTimeout(() => {
1587
- n.holdTimer = null, n.isDown && !n.hasMoved && (Ar.bump(), r.hold?.action(), n.isDown = !1);
1588
- }, e);
1589
- }
1590
- if (!n.isTouch && r.slide) try {
1591
- t.currentTarget.setPointerCapture(t.pointerId);
1592
- } catch {}
1593
- }
1594
- }, p = (t) => {
1595
- if (!n.isDown) return;
1596
- let i = e(), a = t.clientX - n.startX, o = t.clientY - n.startY;
1597
- if (Math.sqrt(a * a + o * o) > 10 && (l(), n.hasMoved = !0), i.slide && n.hasMoved) {
1598
- let e = t.currentTarget, s = d(e);
1599
- if (n.isTouch && !n.sliding && Math.abs(s === "vertical" ? o : a) < Math.abs(s === "vertical" ? a : o)) return;
1600
- n.sliding = !0;
1601
- let c = i.slide.min ?? 0, l = i.slide.max ?? 100, u = l - c, f = s === "vertical" ? -o : a, p = r ?? {
1602
- width: e.clientWidth,
1603
- height: e.clientHeight
1604
- }, m = f / (s === "vertical" ? p.height : p.width) * u, h = Math.max(c, Math.min(l, i.slide.value + m));
1605
- i.slide.onChange(Math.round(h)), n.startX = t.clientX, n.startY = t.clientY, t.preventDefault();
1606
- }
1607
- }, m = (t) => {
1608
- let r = e(), i = n.isDown, a = Date.now() - n.startTime, o = r.hold?.delay ?? 300;
1609
- l(), i && r.tap && !n.hasMoved && a < o && r.tap();
1610
- try {
1611
- t.currentTarget.releasePointerCapture(t.pointerId);
1612
- } catch {}
1613
- u();
1614
- }, h = (e) => {
1615
- l();
1616
- try {
1617
- e.currentTarget.releasePointerCapture(e.pointerId);
1618
- } catch {}
1619
- u();
1620
- }, g = (t) => {
1621
- let n = e();
1622
- if (n.slide) {
1623
- let e = n.slide.orientation;
1624
- 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);
1625
- }
1626
- return n.tap ? Z.tap.css : n.hold ? Z.hold.css : "";
1627
- };
1628
- return {
1629
- onPointerDown: f,
1630
- onPointerMove: p,
1631
- onPointerUp: m,
1632
- onPointerCancel: h,
1633
- onPointerEnter: (e) => {
1634
- let t = e.currentTarget;
1635
- n.element = t, t.style.cursor = g(t);
1636
- },
1637
- bindElement: (e) => {
1638
- e && (n.element = e, c(e));
1639
- },
1640
- touchAction: () => {
1641
- let n = e();
1642
- if (n.slide) {
1643
- let e = n.slide.orientation;
1644
- return e === "vertical" || e !== "horizontal" && (o() ?? (t?.() ?? "horizontal") !== "horizontal") ? "pan-x" : "pan-y";
1645
- }
1646
- return n.tap || n.hold ? "manipulation" : "auto";
1647
- },
1648
- dispose: () => {
1649
- l(), a &&= (a.disconnect(), null), i = null, r = null;
1650
- }
1651
- };
1652
- }
1653
- //#endregion
1654
2551
  //#region src/framework/theming/svg-colors.ts
1655
- var Mr = {
2552
+ var Sa = {
1656
2553
  solar: "oklch(0.74 0.18 60)",
1657
2554
  grid: "oklch(0.62 0.12 245)",
1658
2555
  battery: "oklch(0.70 0.18 145)",
@@ -1661,21 +2558,21 @@ var Mr = {
1661
2558
  positive: "oklch(0.70 0.14 160)",
1662
2559
  negative: "oklch(0.64 0.22 27)"
1663
2560
  };
1664
- function Nr(e) {
2561
+ function Ca(e) {
1665
2562
  return {
1666
2563
  fill: `color-mix(in oklch, ${e} 20%, transparent)`,
1667
2564
  stroke: e,
1668
2565
  solid: e
1669
2566
  };
1670
2567
  }
1671
- var Pr = Object.fromEntries(Object.entries(Mr).map(([e, t]) => [e, Nr(t)])), Fr = o.enum([
2568
+ var wa = Object.fromEntries(Object.entries(Sa).map(([e, t]) => [e, Ca(t)])), Ta = o.enum([
1672
2569
  "success",
1673
2570
  "warning",
1674
2571
  "danger",
1675
2572
  "info",
1676
2573
  "neutral",
1677
2574
  "accent"
1678
- ]), Ir = {
2575
+ ]), Ea = {
1679
2576
  title: e(() => o.string().optional().meta({
1680
2577
  title: "Title",
1681
2578
  description: "Optional display name override"
@@ -1695,62 +2592,63 @@ var Pr = Object.fromEntries(Object.entries(Mr).map(([e, t]) => [e, Nr(t)])), Fr
1695
2592
  formType: "area-picker",
1696
2593
  title: "Area"
1697
2594
  }), "widgetFields.areaId")
1698
- }, Lr = 24;
1699
- function Q(e) {
2595
+ }, Da = 24;
2596
+ function $(e) {
1700
2597
  let t = {};
1701
2598
  for (let [n, r] of Object.entries(e)) r !== void 0 && (t[n] = r);
1702
2599
  return t;
1703
2600
  }
1704
- function Rr() {
2601
+ function Oa() {
1705
2602
  return o.string().optional().meta({
1706
2603
  title: "Title",
1707
2604
  description: "Optional display name override"
1708
2605
  });
1709
2606
  }
1710
- function zr(e) {
1711
- 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($({
1712
2609
  title: e.title,
1713
2610
  description: e.description
1714
2611
  }));
1715
2612
  }
1716
- function Br(e) {
2613
+ function Aa(e) {
1717
2614
  let t = o.number();
1718
- 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($({
1719
2616
  title: e.title,
1720
2617
  description: e.description
1721
2618
  }));
1722
2619
  }
1723
- function Vr(e) {
1724
- return o.boolean().default(e.default ?? !1).meta(Q({
2620
+ function ja(e) {
2621
+ return o.boolean().default(e.default ?? !1).meta($({
1725
2622
  title: e.title,
1726
2623
  description: e.description
1727
2624
  }));
1728
2625
  }
1729
- function Hr(e, t) {
2626
+ function Ma(e, t) {
1730
2627
  let n = o.enum(e);
1731
- 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($({
1732
2629
  title: t.title,
1733
2630
  description: t.description,
1734
- labels: t.labels
2631
+ labels: t.labels,
2632
+ icons: t.icons
1735
2633
  }));
1736
2634
  }
1737
- function Ur(e, t) {
1738
- 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($({
1739
2637
  title: t.title,
1740
2638
  description: t.description,
1741
2639
  labels: t.labels
1742
2640
  }));
1743
2641
  }
1744
- function Wr(e, t) {
1745
- return o.array(o.string()).default([]).meta(Q({
2642
+ function Pa(e, t) {
2643
+ return o.array(o.string()).default([]).meta($({
1746
2644
  domain: e,
1747
2645
  title: t?.title ?? "Entities",
1748
2646
  description: t?.description,
1749
2647
  deviceClass: t?.deviceClass
1750
2648
  }));
1751
2649
  }
1752
- function Gr(e, t) {
1753
- return o.array(o.string()).default([]).meta(Q({
2650
+ function Fa(e, t) {
2651
+ return o.array(o.string()).default([]).meta($({
1754
2652
  domain: e,
1755
2653
  title: t?.title ?? "Entity",
1756
2654
  description: t?.description,
@@ -1758,58 +2656,62 @@ function Gr(e, t) {
1758
2656
  singleSelect: !0
1759
2657
  }));
1760
2658
  }
1761
- function Kr(e) {
2659
+ function Ia(e) {
1762
2660
  return o.string().optional().meta({
1763
2661
  formType: "area-picker",
1764
2662
  title: e?.title ?? "Area"
1765
2663
  });
1766
2664
  }
1767
- function qr(e) {
1768
- let t = o.string().meta(Q({
2665
+ function La(e) {
2666
+ let t = o.string().meta($({
1769
2667
  formType: "icon-picker",
1770
2668
  title: e?.title ?? "Icon",
1771
2669
  description: e?.description
1772
2670
  }));
1773
2671
  return e?.default === void 0 ? t.optional() : t.default(e.default);
1774
2672
  }
1775
- function Jr(e) {
1776
- 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($({
1777
2678
  formType: "image-picker",
1778
2679
  title: e?.title ?? "Image",
1779
- description: e?.description
2680
+ description: e?.description,
2681
+ presets: t
1780
2682
  }));
1781
- return e?.default === void 0 ? t.optional() : t.default(e.default);
2683
+ return e?.default === void 0 ? n.optional() : n.default(e.default);
1782
2684
  }
1783
- function Yr(e) {
1784
- return o.array(o.string()).default([]).meta(Q({
2685
+ function za(e) {
2686
+ return o.array(o.string()).default([]).meta($({
1785
2687
  title: e.title,
1786
2688
  description: e.description
1787
2689
  }));
1788
2690
  }
1789
- function Xr(e, t) {
2691
+ function Ba(e, t) {
1790
2692
  let n = o.object(e);
1791
- return n.default(jt(n)).meta({ title: t.title });
2693
+ return n.default(Gt(n)).meta({ title: t.title });
1792
2694
  }
1793
- function Zr(e) {
2695
+ function Va(e) {
1794
2696
  return e.def;
1795
2697
  }
1796
- function $(e) {
2698
+ function Ha(e) {
1797
2699
  if (o.globalRegistry.get(e)?.formType === "list") return !0;
1798
- let t = Zr(e);
1799
- 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;
1800
2702
  }
1801
- function Qr(e) {
1802
- let t = e, n = Zr(t).innerType;
1803
- for (; n;) t = n, n = Zr(t).innerType;
2703
+ function Ua(e) {
2704
+ let t = e, n = Va(t).innerType;
2705
+ for (; n;) t = n, n = Va(t).innerType;
1804
2706
  return t;
1805
2707
  }
1806
- function $r(e) {
1807
- let t = Zr(Qr(e));
2708
+ function Wa(e) {
2709
+ let t = Va(Ua(e));
1808
2710
  if (t.shape) return new Set(Object.keys(t.shape));
1809
2711
  if (t.options) {
1810
2712
  let e = [];
1811
2713
  for (let n of t.options) {
1812
- let t = $r(n);
2714
+ let t = Wa(n);
1813
2715
  if (!t) return null;
1814
2716
  e.push(t);
1815
2717
  }
@@ -1821,7 +2723,7 @@ function $r(e) {
1821
2723
  }
1822
2724
  return null;
1823
2725
  }
1824
- function ei(e, t, n) {
2726
+ function Ga(e, t, n) {
1825
2727
  let r = { [t]: n };
1826
2728
  try {
1827
2729
  return e.parse(r);
@@ -1829,14 +2731,14 @@ function ei(e, t, n) {
1829
2731
  return r;
1830
2732
  }
1831
2733
  }
1832
- function ti(e, t) {
2734
+ function Ka(e, t) {
1833
2735
  if (!Number.isInteger(t.max) || t.max < 1) throw Error(`field.list: max must be a positive integer, got ${t.max}`);
1834
- if (t.max > Lr) throw Error(`field.list: max ${t.max} exceeds the ceiling of ${Lr}`);
2736
+ if (t.max > Da) throw Error(`field.list: max ${t.max} exceeds the ceiling of ${Da}`);
1835
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}`);
1836
- if ($(e)) throw Error("field.list: a list item cannot contain another field.list (depth 1 only)");
1837
- if (t.labelField !== void 0 && !$r(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`);
1838
2740
  let n = o.array(e);
1839
- 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($({
1840
2742
  formType: "list",
1841
2743
  title: t.title,
1842
2744
  description: t.description,
@@ -1844,7 +2746,7 @@ function ti(e, t) {
1844
2746
  labelField: t.labelField
1845
2747
  }));
1846
2748
  }
1847
- function ni(e, t, n) {
2749
+ function qa(e, t, n) {
1848
2750
  let r = Object.keys(t)[0];
1849
2751
  if (r === void 0) throw Error("field.variants: at least one variant is required");
1850
2752
  if (n.shared && e in n.shared) throw Error(`field.variants: shared fields cannot redefine the discriminator "${e}"`);
@@ -1857,7 +2759,7 @@ function ni(e, t, n) {
1857
2759
  ...r,
1858
2760
  [e]: o.literal(t)
1859
2761
  })), a = o.discriminatedUnion(e, i), s = i[0];
1860
- return a.default(s ? ei(s, e, r) : {}).meta(Q({
2762
+ return a.default(s ? Ga(s, e, r) : {}).meta($({
1861
2763
  formType: "variants",
1862
2764
  discriminator: e,
1863
2765
  title: n.title,
@@ -1865,29 +2767,35 @@ function ni(e, t, n) {
1865
2767
  labels: n.labels
1866
2768
  }));
1867
2769
  }
1868
- var ri = {
1869
- title: Rr,
1870
- text: zr,
1871
- number: Br,
1872
- toggle: Vr,
1873
- choice: Hr,
1874
- choices: Ur,
1875
- entities: Wr,
1876
- entity: Gr,
1877
- area: Kr,
1878
- icon: qr,
1879
- image: Jr,
1880
- stringList: Yr,
1881
- group: Xr,
1882
- list: ti,
1883
- variants: ni
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
1884
2786
  };
1885
- function ii(e) {
2787
+ function Ya(e) {
1886
2788
  return o.object(e);
1887
2789
  }
1888
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
1889
2797
  //#region src/shared/spline.ts
1890
- function ai(e) {
2798
+ function Za(e) {
1891
2799
  if (e.length < 2) return "";
1892
2800
  let t = e[0], n = e[1];
1893
2801
  if (!t || !n) return "";
@@ -1914,14 +2822,14 @@ function ai(e) {
1914
2822
  }
1915
2823
  //#endregion
1916
2824
  //#region src/theme.ts
1917
- function oi() {
2825
+ function Qa() {
1918
2826
  return document.documentElement.classList.contains("dark");
1919
2827
  }
1920
2828
  //#endregion
1921
2829
  //#region src/version.ts
1922
- var si = {
2830
+ var $a = {
1923
2831
  name: "@glasshome/widget-sdk",
1924
- version: "1.16.0",
2832
+ version: "1.17.0",
1925
2833
  description: "SDK for building GlassHome dashboard widgets with SolidJS",
1926
2834
  keywords: [
1927
2835
  "glasshome",
@@ -1980,12 +2888,12 @@ var si = {
1980
2888
  "typecheck:test": "tsc --noEmit -p tsconfig.test.json"
1981
2889
  },
1982
2890
  peerDependencies: {
1983
- "@glasshome/sync-layer": "0.8.1",
1984
- "@glasshome/ui": "1.18.0",
2891
+ "@glasshome/sync-layer": "0.9.0",
2892
+ "@glasshome/ui": "1.20.0",
1985
2893
  "solid-js": "^1.9.11"
1986
2894
  },
1987
2895
  dependencies: {
1988
- "@glasshome/widget-contract": "0.2.1",
2896
+ "@glasshome/widget-contract": "0.3.0",
1989
2897
  "@modular-forms/solid": "^0.25.1",
1990
2898
  "@tailwindcss/vite": "^4.1.13",
1991
2899
  clsx: "^2.1.1",
@@ -1996,7 +2904,7 @@ var si = {
1996
2904
  zod: "^4.1.13"
1997
2905
  },
1998
2906
  devDependencies: {
1999
- "@glasshome/ui": "1.18.0",
2907
+ "@glasshome/ui": "1.20.0",
2000
2908
  "@solidjs/testing-library": "^0.8.10",
2001
2909
  "@types/bun": "^1.4.0",
2002
2910
  "@types/node": "^25.2.2",
@@ -2017,4 +2925,4 @@ var si = {
2017
2925
  engines: { node: ">=18" }
2018
2926
  }.version;
2019
2927
  //#endregion
2020
- export { Ee as Badge, Oe as Button, Ae as Carousel, je as CarouselContent, Me as CarouselDots, Ne as CarouselItem, Pe as CarouselNext, Fe as CarouselPrevious, Ie as ColorSlider, Le as ColorWheel, Re as CountPill, Ke as Icon, Je as Input, Ye as Label, Xe as ResponsiveDialog, Ze as ResponsiveDialogBody, $e as ResponsiveDialogClose, et as ResponsiveDialogContent, tt as ResponsiveDialogDescription, nt as ResponsiveDialogFooter, it as ResponsiveDialogHeader, at as ResponsiveDialogTitle, si 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 Switch, yt as Tabs, xt as TabsContent, Ct as TabsList, Tt as TabsTrigger, Fr as ToneSchema, H as Widget, $t as WidgetContent, R as WidgetCtx, tr as WidgetDebugTab, $n as WidgetDebugView, fr as WidgetDialog, rn as WidgetIcon, r as WidgetManifestSchema, zt as WidgetSizeCtx, Zt as WidgetSliderFill, on as WidgetStatus, ln as WidgetTitle, Tn as WidgetValue, zn as buildDebugData, g as byDomain, mn as calculateLightGroup, hn as calculateSensorGroup, un as copyText, bn as countActiveEntities, ii as defineConfig, Mt as defineWidget, t as deprecations, ri as field, n as formatDeprecation, i as formatSchemaError, yn as getEntityAttribute, s as getForecasts, c as getStream, l as getWebRtcClientConfig, u as hassMediaUrl, Dt as imageUrl, Kt as injectTokens, oi as isDark, vn as isEntityActive, Ot as mediaUrl, ai as monotoneCubicPath, kt as parseColor, d as sendWebRtcCandidate, f as startWebRtcSession, p as state, Pr as svgColors, m as trackEntityHistory, h as untrackEntityHistory, _ as useArea, v as useCalendarEvents, ee as useCamera, y as useConnection, pn as useCopyText, te as useCurrency, ne as useEntities, re as useEntity, ie as useEntityHistory, ae as useEntityStatistics, oe as useForecast, se as useHassConfig, _r as useIntersectionPause, ce as useLocale, vr as useReducedMotion, Ft as useService, ue as useStore, b as useTemperatureUnit, Rt as useToggle, Lt as useTurnOff, It as useTurnOn, S as useUnitSystem, Nt as useWidgetContext, mr as useWidgetDashboard, yr as useWidgetDialog, Bt as useWidgetDimensions, br as useWidgetEntityGroup, jr as useWidgetGestures, gr as useWidgetViewer, Ir 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 };