@camstack/ui-library 1.2.368 → 1.2.369

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
@@ -5,7 +5,7 @@ import * as __mfHostReact from "react";
5
5
  import React, { Fragment, Suspense, cloneElement, createContext, createElement, forwardRef, lazy, useCallback, useContext, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useReducer, useRef, useState, useSyncExternalStore } from "react";
6
6
  import * as __mfHostReactJsxRuntime from "react/jsx-runtime";
7
7
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
8
- import { ALL_CAPABILITY_DEFINITIONS, CAM_PROFILE_ORDER, CLIP_STILL_DISPOSITION_HEADER, CLIP_STILL_REASON_CODE_HEADER, CLIP_STILL_REASON_HEADER, COMPOSER_ADDON_ID, CONTAINER_CHILD_PRIORITY, ConsumableLevelSchema, DEFAULT_DISPLAY_PREFERENCE, DEFAULT_EVENTS_BAND_BUFFER_SEC, DEVICE_HISTORY_ENERGY_KEY, DEVICE_HISTORY_QUERY_MANY_MAX_ITEMS, DEVICE_TYPE_CONTROL_KIND, DISPLAY_PREFERENCES, DeviceExportStatusSchema, DeviceFeature, DeviceRole, DeviceType, EXTENSION_SLOTS, EXTENSION_SLOT_IDS, EventCategory, ExportEntityKindSchema, ExposedDeviceSchema, ExposedEntitySchema, FIRST_LEVEL_MACRO_CLASSES, HISTORY_CATALOG, ICON_CATEGORIES, KNOWN_CAP_NAMES, MAX_SENSOR_TRIGGER_DEVICES, MODEL_PROVIDER_IDS, NAVIGATION_LIGHT_LEVEL_MAX, NAVIGATION_LIGHT_LEVEL_MIN, NODE_COLOR_IDS, NodeColorIdSchema, PALETTE_ENTRY_IDS, PET_FEEDER_MANUAL_FEED_MAX, PET_FEEDER_MANUAL_FEED_MIN, QUANTITY_BASE, RECORDING_AUDIO_TRIGGER_OFFERED_DBFS, RECORDING_SOURCE_CAMSTACK_ADDON, REDACTED_SECRET, RecordingConfigSchema, RecordingStatusSchema, SECRET_CLEAR, SOURCE_CAP_ACTIVE_FIELD, STATIONARY_OVERLAY_STYLE, SUBJECT_PATH_DWELL_EPS, SUBJECT_PATH_FULL_FRAME_COVERAGE, SUBJECT_PATH_MAX_POINTS, TIMEZONES, USE_ROOT_MODEL_SETTING_KEY, assignNodeColorId, assignNodeColorId as assignNodeColorId$1, baseUnitForQuantity, baseUnitOf, buildModelVariantGroups, buildSubjectPath, bundledCamstack, canConvertUnit, canonicalIconKey, clearModelBoundOverrides, clearModelBoundSetting, clusterStepSettingFieldsFor, collectModelBoundKeys, consumableFormOf, consumableKindOf, convertQuantityInput, coreBlockComposition, createDeviceProxy, createLazyTrpcSource, createSliceHandle, dehydrateSchema, deriveRecordingMode, describeModelVariant, displayUnitFor, effectiveStepSettings, findTimezone, formatParkedFor, formatReading, hasModelBoundOverrides, iconCategoryLabel, iconsInCategory, isDrawableSubjectPath, isKeychainStoredField, isModelScopedStepSettingKey, isReadingQuantity, isRootSuppliableStepId, isSecretClear, isSecretFieldView, isSecretMarker, lockDoorLinkOfComposition, modelBindingKey, normalizeUnit, paintHex, parseOccupancyScope, projectSubjectPath, publicEventCategories, resolveContainerPrimaryChild, resolveDeviceControlKind, resolveIconKey, resolveModelBoundSetting, resolveRecordingProfiles, resolveRootSupply, resolveVariantModelId, resolveViewableDeviceIds, searchIcons, selectAssignedProfileSlots, stepSettingSource, subjectPathSampleFromBox, subjectPathSvgPoints, tryConvertUnit, unitDimension, unitsForDimension, unitsForQuantity, withFieldFrom, withoutField, writeModelBoundSetting } from "@camstack/types";
8
+ import { ALL_CAPABILITY_DEFINITIONS, CAM_PROFILE_ORDER, CLIP_STILL_DISPOSITION_HEADER, CLIP_STILL_REASON_CODE_HEADER, CLIP_STILL_REASON_HEADER, COMPOSER_ADDON_ID, CONTAINER_CHILD_PRIORITY, ConsumableLevelSchema, DEFAULT_DISPLAY_PREFERENCE, DEFAULT_EVENTS_BAND_BUFFER_SEC, DEVICE_HISTORY_ENERGY_KEY, DEVICE_HISTORY_QUERY_MANY_MAX_ITEMS, DEVICE_TYPE_CONTROL_KIND, DISPLAY_PREFERENCES, DeviceExportStatusSchema, DeviceFeature, DeviceRole, DeviceType, EXTENSION_SLOTS, EXTENSION_SLOT_IDS, EventCategory, ExportEntityKindSchema, ExposedDeviceSchema, ExposedEntitySchema, FIRST_LEVEL_MACRO_CLASSES, HISTORY_CATALOG, ICON_CATEGORIES, KNOWN_CAP_NAMES, MAX_SENSOR_TRIGGER_DEVICES, MODEL_PROVIDER_IDS, NAVIGATION_LIGHT_LEVEL_MAX, NAVIGATION_LIGHT_LEVEL_MIN, NODE_COLOR_IDS, NodeColorIdSchema, PALETTE_ENTRY_IDS, PET_FEEDER_MANUAL_FEED_MAX, PET_FEEDER_MANUAL_FEED_MIN, QUANTITY_BASE, RECORDING_AUDIO_TRIGGER_OFFERED_DBFS, RECORDING_SOURCE_CAMSTACK_ADDON, REDACTED_SECRET, RecordingConfigSchema, RecordingStatusSchema, SECRET_CLEAR, SOURCE_CAP_ACTIVE_FIELD, STATIONARY_OVERLAY_STYLE, SUBJECT_PATH_DWELL_EPS, SUBJECT_PATH_FULL_FRAME_COVERAGE, SUBJECT_PATH_MAX_POINTS, TIMED_RUN_LIMITS, TIMEZONES, USE_ROOT_MODEL_SETTING_KEY, assignNodeColorId, assignNodeColorId as assignNodeColorId$1, baseUnitForQuantity, baseUnitOf, buildModelVariantGroups, buildSubjectPath, bundledCamstack, canConvertUnit, canonicalIconKey, clearModelBoundOverrides, clearModelBoundSetting, clusterStepSettingFieldsFor, collectModelBoundKeys, consumableFormOf, consumableKindOf, convertQuantityInput, coreBlockComposition, createDeviceProxy, createLazyTrpcSource, createSliceHandle, dehydrateSchema, deriveRecordingMode, describeModelVariant, displayUnitFor, effectiveStepSettings, findTimezone, formatParkedFor, formatReading, hasModelBoundOverrides, iconCategoryLabel, iconsInCategory, isDrawableSubjectPath, isKeychainStoredField, isModelScopedStepSettingKey, isReadingQuantity, isRootSuppliableStepId, isSecretClear, isSecretFieldView, isSecretMarker, lockDoorLinkOfComposition, modelBindingKey, normalizeUnit, paintHex, parseOccupancyScope, projectSubjectPath, publicEventCategories, resolveContainerPrimaryChild, resolveDeviceControlKind, resolveIconKey, resolveModelBoundSetting, resolveRecordingProfiles, resolveRootSupply, resolveVariantModelId, resolveViewableDeviceIds, searchIcons, selectAssignedProfileSlots, stepSettingSource, subjectPathSampleFromBox, subjectPathSvgPoints, tryConvertUnit, unitDimension, unitsForDimension, unitsForQuantity, withFieldFrom, withoutField, writeModelBoundSetting } from "@camstack/types";
9
9
  import * as __mfHostTrpcReactQuery from "@trpc/react-query";
10
10
  import { createTRPCReact } from "@trpc/react-query";
11
11
  import * as __mfHostReactDOM from "react-dom";
@@ -4260,6 +4260,34 @@ var Thermometer = createLucideIcon("thermometer", [["path", {
4260
4260
  * This source code is licensed under the ISC license.
4261
4261
  * See the LICENSE file in the root directory of this source tree.
4262
4262
  */
4263
+ var TimerOff = createLucideIcon("timer-off", [
4264
+ ["path", {
4265
+ d: "M10 2h4",
4266
+ key: "n1abiw"
4267
+ }],
4268
+ ["path", {
4269
+ d: "M4.6 11a8 8 0 0 0 1.7 8.7 8 8 0 0 0 8.7 1.7",
4270
+ key: "10he05"
4271
+ }],
4272
+ ["path", {
4273
+ d: "M7.4 7.4a8 8 0 0 1 10.3 1 8 8 0 0 1 .9 10.2",
4274
+ key: "15f7sh"
4275
+ }],
4276
+ ["path", {
4277
+ d: "m2 2 20 20",
4278
+ key: "1ooewy"
4279
+ }],
4280
+ ["path", {
4281
+ d: "M12 12v-2",
4282
+ key: "fwoke6"
4283
+ }]
4284
+ ]);
4285
+ /**
4286
+ * @license lucide-react v0.576.0 - ISC
4287
+ *
4288
+ * This source code is licensed under the ISC license.
4289
+ * See the LICENSE file in the root directory of this source tree.
4290
+ */
4263
4291
  var Timer = createLucideIcon("timer", [
4264
4292
  ["line", {
4265
4293
  x1: "10",
@@ -5432,6 +5460,11 @@ var DEVICE_TYPE_META = {
5432
5460
  labelKey: "uiLibrary.deviceMeta.type.petFountain",
5433
5461
  labelFallback: "Pet fountain"
5434
5462
  },
5463
+ [DeviceType.Heater]: {
5464
+ icon: Flame,
5465
+ labelKey: "uiLibrary.deviceMeta.type.heater",
5466
+ labelFallback: "Heater"
5467
+ },
5435
5468
  [DeviceType.Dishwasher]: {
5436
5469
  icon: Waves,
5437
5470
  labelKey: "uiLibrary.deviceMeta.type.dishwasher",
@@ -5937,7 +5970,7 @@ function lucideExportName(key) {
5937
5970
  function loadIconGlyphs() {
5938
5971
  if (fullTable !== void 0) return Promise.resolve();
5939
5972
  if (failure$1 !== void 0) return Promise.reject(failure$1);
5940
- pending ??= import("./icons-CZwJd50b.js").then((module) => {
5973
+ pending ??= import("./icons-e-xohmFb.js").then((module) => {
5941
5974
  fullTable = module;
5942
5975
  publish();
5943
5976
  }, (error) => {
@@ -11502,6 +11535,14 @@ var useFanControlSetDirection = /*#__PURE__*/ alias(() => trpc.fanControl.setDir
11502
11535
  var useFanControlSetOscillating = /*#__PURE__*/ alias(() => trpc.fanControl.setOscillating.useMutation);
11503
11536
  /** Generated alias around `trpc.fanControl.getStatus.useQuery`. */
11504
11537
  var useFanControlGetStatus = /*#__PURE__*/ alias(() => trpc.fanControl.getStatus.useQuery);
11538
+ /** Generated alias around `trpc.fanPresets.getPresets.useQuery`. */
11539
+ var useFanPresetsGetPresets = /*#__PURE__*/ alias(() => trpc.fanPresets.getPresets.useQuery);
11540
+ /** Generated alias around `trpc.fanPresets.setPresets.useMutation`. */
11541
+ var useFanPresetsSetPresets = /*#__PURE__*/ alias(() => trpc.fanPresets.setPresets.useMutation);
11542
+ /** Generated alias around `trpc.fanPresets.applyPreset.useMutation`. */
11543
+ var useFanPresetsApplyPreset = /*#__PURE__*/ alias(() => trpc.fanPresets.applyPreset.useMutation);
11544
+ /** Generated alias around `trpc.fanPresets.capturePreset.useQuery`. */
11545
+ var useFanPresetsCapturePreset = /*#__PURE__*/ alias(() => trpc.fanPresets.capturePreset.useQuery);
11505
11546
  /** Generated alias around `trpc.featureProbe.getStatus.useQuery`. */
11506
11547
  var useFeatureProbeGetStatus = /*#__PURE__*/ alias(() => trpc.featureProbe.getStatus.useQuery);
11507
11548
  /** Generated alias around `trpc.flood.getStatus.useQuery`. */
@@ -13032,6 +13073,12 @@ var useTerminalSessionPullOutput = /*#__PURE__*/ alias(() => trpc.terminalSessio
13032
13073
  var useTerminalSessionWriteInput = /*#__PURE__*/ alias(() => trpc.terminalSession.writeInput.useMutation);
13033
13074
  /** Generated alias around `trpc.terminalSession.close.useMutation`. */
13034
13075
  var useTerminalSessionClose = /*#__PURE__*/ alias(() => trpc.terminalSession.close.useMutation);
13076
+ /** Generated alias around `trpc.timedRun.runFor.useMutation`. */
13077
+ var useTimedRunRunFor = /*#__PURE__*/ alias(() => trpc.timedRun.runFor.useMutation);
13078
+ /** Generated alias around `trpc.timedRun.cancel.useMutation`. */
13079
+ var useTimedRunCancel = /*#__PURE__*/ alias(() => trpc.timedRun.cancel.useMutation);
13080
+ /** Generated alias around `trpc.timedRun.getStatus.useQuery`. */
13081
+ var useTimedRunGetStatus = /*#__PURE__*/ alias(() => trpc.timedRun.getStatus.useQuery);
13035
13082
  /** Generated alias around `trpc.toast.onToast.useSubscription`. */
13036
13083
  var useToastOnToast = /*#__PURE__*/ alias(() => trpc.toast.onToast.useSubscription);
13037
13084
  /** Generated alias around `trpc.training.listBaseModels.useQuery`. */
@@ -30560,8 +30607,8 @@ function RecordingPanel({ deviceId }) {
30560
30607
  * `type:'widget'` ConfigField. `WidgetSlot` resolves these BEFORE the
30561
30608
  * Module-Federation `WidgetRegistry`. ids are namespaced `host/<name>`. */
30562
30609
  var HOST_WIDGETS = {
30563
- "host/motion-zones-grid": lazy(() => import("./MotionZonesSettings-dx3wObgK.js").then((m) => ({ default: m.MotionZonesSettings }))),
30564
- "host/privacy-mask-grid": lazy(() => import("./PrivacyMaskSettings-BM2C_xWz.js").then((m) => ({ default: m.PrivacyMaskSettings }))),
30610
+ "host/motion-zones-grid": lazy(() => import("./MotionZonesSettings-Zcfa5c9l.js").then((m) => ({ default: m.MotionZonesSettings }))),
30611
+ "host/privacy-mask-grid": lazy(() => import("./PrivacyMaskSettings-B_X42yzN.js").then((m) => ({ default: m.PrivacyMaskSettings }))),
30565
30612
  "host/ptz-panel": PtzPanel,
30566
30613
  "host/navigation-panel": NavigationPanel,
30567
30614
  "host/consumables-panel": ConsumablesPanel,
@@ -54120,6 +54167,137 @@ function PetFeederHeroCard({ trpc, deviceId, features, optimistic }) {
54120
54167
  });
54121
54168
  }
54122
54169
  //#endregion
54170
+ //#region src/composites/device-controls/timed-run-control.tsx
54171
+ /**
54172
+ * "Run for N" - the inline control of the `timed-run` cap (D993).
54173
+ *
54174
+ * A number, the unit it is in, and a Run button: the hub turns the device on and
54175
+ * switches it off again after that long. While a run is armed the control shows
54176
+ * the time left (counted down from the slice's `activeUntil`) and a Cancel. The
54177
+ * maximum is the device type's own bound (`TIMED_RUN_LIMITS`); a value above it
54178
+ * is refused by the hub with a typed reason, which this control says in words.
54179
+ *
54180
+ * Rendered only when the device binds `timed-run`. An unknown slice is "nothing
54181
+ * armed", never a running timer.
54182
+ */
54183
+ var TICK_MS = 1e3;
54184
+ var SECONDS_PER_MINUTE$1 = 60;
54185
+ var MS_PER_SECOND = 1e3;
54186
+ var DEFAULT_MINUTES = 30;
54187
+ var DEFAULT_SECONDS = 60;
54188
+ /** `m:ss` for a countdown; a started run never shows a negative time. */
54189
+ function formatCountdown(remainingMs) {
54190
+ const total = Math.max(0, Math.ceil(remainingMs / MS_PER_SECOND));
54191
+ const minutes = Math.floor(total / SECONDS_PER_MINUTE$1);
54192
+ const seconds = total % SECONDS_PER_MINUTE$1;
54193
+ return `${minutes}:${String(seconds).padStart(2, "0")}`;
54194
+ }
54195
+ /** The largest value the field accepts, in the limit's unit. */
54196
+ function maxInUnit(limit) {
54197
+ return limit.unit === "min" ? limit.maxSeconds / SECONDS_PER_MINUTE$1 : limit.maxSeconds;
54198
+ }
54199
+ function useNow(active) {
54200
+ const [now, setNow] = useState(() => Date.now());
54201
+ useEffect(() => {
54202
+ if (!active) return void 0;
54203
+ setNow(Date.now());
54204
+ const handle = setInterval(() => setNow(Date.now()), TICK_MS);
54205
+ return () => clearInterval(handle);
54206
+ }, [active]);
54207
+ return now;
54208
+ }
54209
+ function TimedRunControl({ trpc, deviceId, limit }) {
54210
+ const t = useUiText();
54211
+ const { cap, slice, online } = useDeviceCapability({
54212
+ trpc,
54213
+ deviceId,
54214
+ cap: (d) => d.timedRun,
54215
+ slice: (d) => d.state.timedRun
54216
+ });
54217
+ const max = maxInUnit(limit);
54218
+ const [draft, setDraft] = useState(Math.min(max, limit.unit === "min" ? DEFAULT_MINUTES : DEFAULT_SECONDS));
54219
+ const [refusal, setRefusal] = useState(null);
54220
+ const activeUntil = slice?.activeUntil ?? null;
54221
+ const now = useNow(activeUntil !== null);
54222
+ if (cap === void 0) return null;
54223
+ const unitLabel = limit.unit === "min" ? t("uiLibrary.timedRun.minutes", "min") : t("uiLibrary.timedRun.seconds", "s");
54224
+ const valid = Number.isFinite(draft) && draft > 0 && draft <= max;
54225
+ const armed = activeUntil !== null && activeUntil > now;
54226
+ const run = () => {
54227
+ if (!valid) return;
54228
+ setRefusal(null);
54229
+ cap.runFor({
54230
+ duration: draft,
54231
+ unit: limit.unit
54232
+ }).then((result) => {
54233
+ if (!result.ok) setRefusal(result.reason);
54234
+ });
54235
+ };
54236
+ return /* @__PURE__ */ jsxs("div", {
54237
+ className: "flex flex-col gap-1.5",
54238
+ "data-testid": "timed-run-control",
54239
+ children: [
54240
+ /* @__PURE__ */ jsxs("div", {
54241
+ className: "flex items-center gap-2",
54242
+ children: [
54243
+ /* @__PURE__ */ jsx(Input, {
54244
+ type: "number",
54245
+ inputMode: "numeric",
54246
+ min: 1,
54247
+ max,
54248
+ step: 1,
54249
+ value: Number.isFinite(draft) ? draft : "",
54250
+ disabled: !online,
54251
+ "aria-label": t("uiLibrary.timedRun.duration", "Run for"),
54252
+ className: "w-20 tabular-nums",
54253
+ onChange: (event) => setDraft(event.target.valueAsNumber)
54254
+ }),
54255
+ /* @__PURE__ */ jsx("span", {
54256
+ className: "text-xs text-foreground-muted",
54257
+ children: unitLabel
54258
+ }),
54259
+ /* @__PURE__ */ jsxs(Button, {
54260
+ size: "sm",
54261
+ disabled: !online || !valid,
54262
+ onClick: run,
54263
+ children: [/* @__PURE__ */ jsx(Timer, {
54264
+ className: "h-4 w-4",
54265
+ "aria-hidden": true
54266
+ }), t("uiLibrary.timedRun.run", "Run")]
54267
+ }),
54268
+ armed && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
54269
+ className: "text-xs font-medium tabular-nums text-foreground",
54270
+ "data-testid": "timed-run-countdown",
54271
+ children: t("uiLibrary.timedRun.remaining", "{{time}} left", { time: formatCountdown(activeUntil - now) })
54272
+ }), /* @__PURE__ */ jsx(Button, {
54273
+ size: "sm",
54274
+ variant: "outline",
54275
+ disabled: !online,
54276
+ "aria-label": t("uiLibrary.timedRun.cancel", "Cancel the timer"),
54277
+ onClick: () => void cap.cancel({}),
54278
+ children: /* @__PURE__ */ jsx(TimerOff, {
54279
+ className: "h-4 w-4",
54280
+ "aria-hidden": true
54281
+ })
54282
+ })] })
54283
+ ]
54284
+ }),
54285
+ !valid && /* @__PURE__ */ jsx("span", {
54286
+ className: "text-xs text-danger",
54287
+ children: t("uiLibrary.timedRun.range", "Enter 1 to {{max}} {{unit}}", {
54288
+ max,
54289
+ unit: unitLabel
54290
+ })
54291
+ }),
54292
+ refusal !== null && /* @__PURE__ */ jsx("span", {
54293
+ className: "text-xs text-danger",
54294
+ role: "alert",
54295
+ children: refusal === "over-max" ? t("uiLibrary.timedRun.overMax", "That is longer than this device may run.") : refusal === "command-failed" ? t("uiLibrary.timedRun.commandFailed", "The device did not turn on.") : t("uiLibrary.timedRun.unsupported", "This device cannot run on a timer.")
54296
+ })
54297
+ ]
54298
+ });
54299
+ }
54300
+ //#endregion
54123
54301
  //#region src/composites/device-controls/pet-fountain-panel.tsx
54124
54302
  /**
54125
54303
  * Pet-fountain controls for a `DeviceType.PetFountain` device.
@@ -54148,6 +54326,7 @@ var KEYFRAMES$2 = `
54148
54326
  .pfn-ripple, .pfn-bubble { animation: none !important; opacity: 0; }
54149
54327
  }
54150
54328
  `;
54329
+ var PUMP_LIMIT = TIMED_RUN_LIMITS[DeviceType.PetFountain];
54151
54330
  var LITRES_TO_ML = 1e3;
54152
54331
  var SECONDS_PER_MINUTE = 60;
54153
54332
  var MAX_PUMP_MINUTES = 240;
@@ -54312,6 +54491,11 @@ function PetFountainPanel({ trpc, deviceId, layout, optimistic }) {
54312
54491
  ]
54313
54492
  })
54314
54493
  }),
54494
+ PUMP_LIMIT !== void 0 && /* @__PURE__ */ jsx(TimedRunControl, {
54495
+ trpc,
54496
+ deviceId,
54497
+ limit: PUMP_LIMIT
54498
+ }),
54315
54499
  /* @__PURE__ */ jsxs(Button, {
54316
54500
  variant: "outline",
54317
54501
  size: "sm",
@@ -54536,795 +54720,215 @@ function PetFountainHeroCard({ trpc, deviceId, features, optimistic }) {
54536
54720
  });
54537
54721
  }
54538
54722
  //#endregion
54539
- //#region src/composites/device-controls/dishwasher-control.tsx
54540
- /**
54541
- * Dishwasher controls for a `DeviceType.Dishwasher` device.
54542
- *
54543
- * Reads the `dishwasher` cap status slice and renders inline + hero surfaces
54544
- * mirroring vacuum-control / pet-feeder patterns.
54545
- *
54546
- * Salt and rinse aid are not here: they are items of the device's `consumables`
54547
- * cap, shown by the page's Consumables section like every device's (D915).
54548
- *
54549
- * UNKNOWN IS NOT OFF. The slice carries `null` for everything the appliance has not
54550
- * reported, and this view renders that as "—" / a disabled control, never as an unchecked
54551
- * box or a zero. It also does not echo a command before the appliance confirms it: the
54552
- * slice moves when the appliance says so.
54553
- */
54554
- /** What the operation state is called to a person, and how it is toned. */
54555
- function dishwasherOperationMeta(operationState, t = defaultUiText) {
54556
- switch (operationState) {
54557
- case "Run": return {
54558
- label: t("uiLibrary.dishwasher.op.run", "Running"),
54559
- tone: "text-primary"
54560
- };
54561
- case "Pause": return {
54562
- label: t("uiLibrary.dishwasher.op.pause", "Paused"),
54563
- tone: "text-warning"
54564
- };
54565
- case "Finished": return {
54566
- label: t("uiLibrary.dishwasher.op.finished", "Finished"),
54567
- tone: "text-success"
54568
- };
54569
- case "Error": return {
54570
- label: t("uiLibrary.dishwasher.op.error", "Error"),
54571
- tone: "text-danger"
54572
- };
54573
- case "Aborting": return {
54574
- label: t("uiLibrary.dishwasher.op.aborting", "Stopping"),
54575
- tone: "text-warning"
54576
- };
54577
- case "ActionRequired": return {
54578
- label: t("uiLibrary.dishwasher.op.actionRequired", "Action required"),
54579
- tone: "text-warning"
54580
- };
54581
- case "DelayedStart": return {
54582
- label: t("uiLibrary.dishwasher.op.delayedStart", "Delayed start"),
54583
- tone: "text-primary"
54584
- };
54585
- case "Ready": return {
54586
- label: t("uiLibrary.dishwasher.op.ready", "Ready"),
54587
- tone: "text-foreground"
54588
- };
54589
- case "Inactive": return {
54590
- label: t("uiLibrary.dishwasher.op.inactive", "Inactive"),
54591
- tone: "text-foreground-subtle"
54592
- };
54593
- case null: return {
54594
- label: t("uiLibrary.dishwasher.unknown", "Unknown"),
54595
- tone: "text-foreground-subtle"
54596
- };
54597
- }
54723
+ //#region src/composites/device-controls/ac-panel.tsx
54724
+ /** Modes that mean the device can cool, dry, or move air — an air conditioner. */
54725
+ var COOLING_MODES = new Set([
54726
+ "cool",
54727
+ "heat_cool",
54728
+ "dry",
54729
+ "fan_only"
54730
+ ]);
54731
+ /** A heater offers heat (and maybe auto/off) and none of the cooling modes. */
54732
+ function climateOffersCooling(modes) {
54733
+ return modes.some((mode) => COOLING_MODES.has(mode));
54598
54734
  }
54599
- /** The headline for the whole slice: the appliance's state, or why there is none. */
54600
- function dishwasherHeadline(status, t = defaultUiText) {
54601
- switch (status.availability) {
54602
- case "offline": return {
54603
- label: t("uiLibrary.dishwasher.offline", "Offline"),
54604
- tone: "text-foreground-subtle"
54605
- };
54606
- case "description-missing": return {
54607
- label: t("uiLibrary.dishwasher.descriptionMissing", "Waiting for the appliance profile"),
54608
- tone: "text-warning"
54609
- };
54610
- case "available": return dishwasherOperationMeta(status.operationState, t);
54735
+ /** Setpoint track bounds. Absent when the integration did not report both ends. */
54736
+ function climateSetpointBounds(status) {
54737
+ const min = status.minTemp;
54738
+ const max = status.maxTemp;
54739
+ if (typeof min !== "number" || typeof max !== "number") return null;
54740
+ if (!Number.isFinite(min) || !Number.isFinite(max) || max <= min) return null;
54741
+ return {
54742
+ min,
54743
+ max
54744
+ };
54745
+ }
54746
+ /** Map a 0–1 drag fraction onto the setpoint, snapped to `tempStep`. */
54747
+ function climateTargetFromFraction(fraction, bounds, tempStep) {
54748
+ const step = resolveClimateTempStep(tempStep);
54749
+ const clamped = Math.min(1, Math.max(0, fraction));
54750
+ const raw = bounds.min + clamped * (bounds.max - bounds.min);
54751
+ const steps = Math.round((raw - bounds.min) / step);
54752
+ const snapped = bounds.min + steps * step;
54753
+ const rounded = Math.round(snapped * 1e3) / 1e3;
54754
+ return Math.min(bounds.max, Math.max(bounds.min, rounded));
54755
+ }
54756
+ /** AC-appropriate short mode labels. Exhaustive over HvacMode. */
54757
+ function modeLabel(t, mode) {
54758
+ switch (mode) {
54759
+ case "cool": return t("uiLibrary.acPanel.modeCool", "Cool");
54760
+ case "heat": return t("uiLibrary.acPanel.modeHeat", "Heat");
54761
+ case "auto": return t("uiLibrary.acPanel.modeAuto", "Auto");
54762
+ case "heat_cool": return t("uiLibrary.acPanel.modeHeatCool", "Heat·Cool");
54763
+ case "fan_only": return t("uiLibrary.acPanel.modeFan", "Fan");
54764
+ case "dry": return t("uiLibrary.acPanel.modeDry", "Dry");
54765
+ case "off": return t("uiLibrary.acPanel.modeOff", "Off");
54611
54766
  }
54612
54767
  }
54613
- /** Last segment of a feature key, spaced out: `Dishcare.Dishwasher.Program.Eco50` -> `Eco50`. */
54614
- function featureLabel(key) {
54615
- return (key.split(".").pop() ?? key).replace(/([a-z0-9])([A-Z])/g, "$1 $2");
54768
+ /** Per-mode icon (lucide). Exhaustive over HvacMode. */
54769
+ var MODE_ICON = {
54770
+ cool: Snowflake,
54771
+ heat: Flame,
54772
+ auto: Sparkles,
54773
+ heat_cool: Thermometer,
54774
+ fan_only: Fan,
54775
+ dry: Droplets,
54776
+ off: Power
54777
+ };
54778
+ /** Mode accent hex — drives the airflow particles, the glow, and the target
54779
+ * value colour. Mirrors the thermostat gauge palette. Exhaustive. */
54780
+ var MODE_ACCENT = {
54781
+ heat: "#f59e0b",
54782
+ cool: "#60a5fa",
54783
+ auto: "#c084fc",
54784
+ heat_cool: "#e879f9",
54785
+ fan_only: "#94a3b8",
54786
+ dry: "#22d3ee",
54787
+ off: "#a1a1aa"
54788
+ };
54789
+ /** Title-case a snake/lower token for a selector option ('medium_low' → 'Medium
54790
+ * low', 'turbo' → 'Turbo'). Shared by the fan + preset selectors. */
54791
+ function fanLabel(token) {
54792
+ const spaced = token.replace(/_/g, " ");
54793
+ return spaced.charAt(0).toUpperCase() + spaced.slice(1);
54794
+ }
54795
+ /** Preset → icon. Unknown presets fall back to a neutral sparkle. */
54796
+ function presetIcon(preset) {
54797
+ switch (preset) {
54798
+ case "turbo": return Zap;
54799
+ case "quiet": return Feather;
54800
+ case "sleep": return Moon;
54801
+ case "eco": return Leaf;
54802
+ case "8c_heat": return Snowflake;
54803
+ case "none": return Ban;
54804
+ default: return Sparkles;
54805
+ }
54616
54806
  }
54617
54807
  /**
54618
- * Salt and rinse aid are consumable items (D915). Their events must not
54619
- * reappear on the hero — the Consumables section is the only surface.
54808
+ * Fan level → airflow animation period. Higher speed ⇒ shorter period. Unknown
54809
+ * strings fall back to a medium pace. Turbo (a preset) shortens it further.
54620
54810
  */
54621
- function isConsumableDishwasherEvent(event) {
54622
- const short = (event.split(".").pop() ?? event).toLowerCase();
54623
- return short.includes("salt") || short.includes("rinse");
54624
- }
54625
- /** Raised events the hero may name. Consumable events are dropped. */
54626
- function visibleDishwasherEvents(events) {
54627
- return events.filter((event) => !isConsumableDishwasherEvent(event));
54811
+ function airflowPeriodSec(fanMode) {
54812
+ switch (fanMode) {
54813
+ case "high": return 1;
54814
+ case "medium_high": return 1.3;
54815
+ case "medium": return 1.6;
54816
+ case "medium_low": return 1.9;
54817
+ case "low": return 2.2;
54818
+ default: return 1.8;
54819
+ }
54628
54820
  }
54629
- /** Whole seconds as a short duration: `1 h 24 min`, `42 min`, `30 s`. */
54630
- function formatDuration(seconds, t = defaultUiText) {
54631
- if (seconds < 60) return t("uiLibrary.dishwasher.durationSeconds", "{{n}} s", { n: seconds });
54632
- const minutes = Math.round(seconds / 60);
54633
- if (minutes < 60) return t("uiLibrary.dishwasher.durationMinutes", "{{n}} min", { n: minutes });
54634
- const hours = Math.floor(minutes / 60);
54635
- const rest = minutes % 60;
54636
- return rest === 0 ? t("uiLibrary.dishwasher.durationHours", "{{n}} h", { n: hours }) : t("uiLibrary.dishwasher.durationHoursMinutes", "{{h}} h {{m}} min", {
54637
- h: hours,
54638
- m: rest
54639
- });
54821
+ var KEYFRAMES$1 = `
54822
+ @keyframes acv-fall { 0%{transform:translateY(-1.75rem);opacity:0} 18%{opacity:.7} 82%{opacity:.7} 100%{transform:translateY(7.5rem);opacity:0} }
54823
+ @keyframes acv-rise { 0%{transform:translateY(7.5rem);opacity:0} 18%{opacity:.7} 82%{opacity:.7} 100%{transform:translateY(-1.75rem);opacity:0} }
54824
+ @keyframes acv-sway { 0%,100%{transform:translateX(-9%)} 50%{transform:translateX(9%)} }
54825
+ @keyframes acv-swing-h { 0%,100%{transform:translateX(-22%)} 50%{transform:translateX(22%)} }
54826
+ @keyframes acv-swing-v { 0%,100%{transform:translateY(-22%)} 50%{transform:translateY(22%)} }
54827
+ @keyframes acv-spin { to { transform:rotate(360deg) } }
54828
+ @keyframes acv-glow { 0%,100%{opacity:.35;transform:scale(1)} 50%{opacity:.6;transform:scale(1.06)} }
54829
+ @media (prefers-reduced-motion: reduce) {
54830
+ .acv-streak, .acv-fan, .acv-sway-wrap, .acv-glow, .acv-swing { animation: none !important; }
54640
54831
  }
54641
- function useDishwasher(trpc, deviceId) {
54642
- return useDeviceCapability({
54832
+ `;
54833
+ function AcPanel({ trpc, deviceId, layout, optimistic }) {
54834
+ const t = useUiText();
54835
+ const { cap, slice, available } = useDeviceCapability({
54643
54836
  trpc,
54644
54837
  deviceId,
54645
- cap: (d) => d.dishwasher,
54646
- slice: (d) => d.state.dishwasher
54647
- });
54648
- }
54649
- function DishwasherIconButton({ label, busy, active, onClick, children }) {
54650
- return /* @__PURE__ */ jsx("button", {
54651
- type: "button",
54652
- "aria-label": label,
54653
- title: label,
54654
- disabled: busy,
54655
- onClick: (e) => {
54656
- e.stopPropagation();
54657
- onClick();
54658
- },
54659
- className: cn("inline-flex h-5 w-5 items-center justify-center rounded text-foreground-subtle hover:text-foreground hover:bg-surface-hover transition-colors", active && "bg-primary text-primary-foreground", busy && "opacity-40 cursor-not-allowed"),
54660
- children
54661
- });
54662
- }
54663
- function DishwasherGraphic({ running, progressPercent }) {
54664
- const pct = progressPercent != null ? Math.max(0, Math.min(100, progressPercent)) : running ? 40 : 0;
54665
- return /* @__PURE__ */ jsxs("div", {
54666
- "aria-hidden": "true",
54667
- className: "relative w-28 h-36 rounded border-2 border-border bg-gradient-to-b from-surface-hover to-surface overflow-hidden flex-shrink-0",
54668
- children: [/* @__PURE__ */ jsx("div", {
54669
- className: cn("absolute inset-x-0 bottom-0 bg-primary/25 transition-[height] duration-500", running && "animate-pulse"),
54670
- style: { height: `${pct}%` }
54671
- }), /* @__PURE__ */ jsx("div", {
54672
- className: "absolute inset-0 flex items-center justify-center text-foreground-subtle",
54673
- children: /* @__PURE__ */ jsx(Waves, { className: "h-10 w-10 opacity-70" })
54674
- })]
54838
+ cap: (d) => d.climateControl,
54839
+ slice: (d) => d.state.climateControl
54675
54840
  });
54676
- }
54677
- function DishwasherPanel({ trpc, deviceId, layout }) {
54678
- const t = useUiText();
54679
- const { cap, slice, available } = useDishwasher(trpc, deviceId);
54841
+ const { display, applyOptimistic } = useOptimisticSlice(slice, { enabled: optimistic ?? true });
54680
54842
  if (cap === void 0) return null;
54681
- if (slice === void 0) return null;
54682
- const display = slice;
54683
- const link = display.availability === "available";
54684
- const busy = !available || !link;
54685
- const optionTogglesLocked = display.childLock === true;
54686
- const meta = dishwasherHeadline(display, t);
54687
- const running = display.operationState === "Run";
54688
- const paused = display.operationState === "Pause";
54689
- const startable = display.remoteStartAllowed === true && display.selectedProgram !== null;
54690
- const press = (fn) => {
54691
- if (busy) return;
54692
- fn();
54693
- };
54843
+ if (display === void 0) return null;
54844
+ const busy = !available;
54694
54845
  if (layout === "compact") return /* @__PURE__ */ jsxs("div", {
54695
- className: "inline-flex items-center gap-1.5 max-w-full",
54846
+ "data-mode": display.mode,
54847
+ className: "inline-flex items-center gap-1",
54696
54848
  children: [
54697
- display.doorOpen === true && /* @__PURE__ */ jsx("span", {
54698
- className: "inline-flex text-warning shrink-0",
54699
- title: t("uiLibrary.dishwasher.doorOpen", "Door open"),
54700
- "aria-label": t("uiLibrary.dishwasher.doorOpen", "Door open"),
54701
- children: /* @__PURE__ */ jsx(DoorOpen, { className: "h-3.5 w-3.5" })
54702
- }),
54703
54849
  /* @__PURE__ */ jsx("span", {
54704
- className: cn("text-xs font-medium tabular-nums shrink-0", meta.tone),
54705
- children: meta.label
54706
- }),
54707
- display.program != null && /* @__PURE__ */ jsx("span", {
54708
- className: "text-xs text-foreground-subtle truncate max-w-[7rem]",
54709
- title: display.program,
54710
- children: featureLabel(display.program)
54711
- }),
54712
- display.remaining != null && /* @__PURE__ */ jsxs("span", {
54713
- className: "inline-flex items-center gap-0.5 text-xs text-foreground-subtle tabular-nums shrink-0",
54714
- children: [/* @__PURE__ */ jsx(Timer, { className: "h-3 w-3" }), formatDuration(display.remaining, t)]
54715
- }),
54716
- /* @__PURE__ */ jsx(DishwasherIconButton, {
54717
- label: t("uiLibrary.dishwasher.start", "Start"),
54718
- busy: busy || !startable,
54719
- active: running,
54720
- onClick: () => press(() => cap.start({})),
54721
- children: /* @__PURE__ */ jsx(Play, { className: "h-3 w-3" })
54850
+ className: cn("text-xs tabular-nums font-medium", MODE_TEXT_COLOR[display.mode]),
54851
+ children: display.target !== null ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
54852
+ display.target,
54853
+ "°",
54854
+ display.currentTemp !== null && /* @__PURE__ */ jsxs("span", {
54855
+ className: "text-foreground-subtle font-normal",
54856
+ children: [
54857
+ " ",
54858
+ "(",
54859
+ display.currentTemp,
54860
+ "°)"
54861
+ ]
54862
+ })
54863
+ ] }) : display.currentTemp !== null ? /* @__PURE__ */ jsxs("span", {
54864
+ className: "text-foreground-subtle",
54865
+ children: [display.currentTemp, "°"]
54866
+ }) : null
54722
54867
  }),
54723
- /* @__PURE__ */ jsx(DishwasherIconButton, {
54724
- label: paused ? t("uiLibrary.dishwasher.resume", "Resume") : t("uiLibrary.dishwasher.pause", "Pause"),
54725
- busy: busy || !(running || paused),
54726
- active: paused,
54727
- onClick: () => press(() => paused ? cap.resume({}) : cap.pause({})),
54728
- children: /* @__PURE__ */ jsx(Pause, { className: "h-3 w-3" })
54868
+ display.target !== null && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("button", {
54869
+ type: "button",
54870
+ "aria-label": t("uiLibrary.acPanel.decrease", "Decrease target"),
54871
+ disabled: busy,
54872
+ onClick: (e) => {
54873
+ e.stopPropagation();
54874
+ if (!busy && display.target !== null) {
54875
+ const next = nextClimateTarget(display.target, -1, display);
54876
+ applyOptimistic({ target: next });
54877
+ cap.setTarget({ target: next });
54878
+ }
54879
+ },
54880
+ className: cn("inline-flex h-5 w-5 items-center justify-center rounded text-foreground-subtle hover:text-foreground hover:bg-surface-hover transition-colors text-xs", busy && "opacity-40 cursor-not-allowed"),
54881
+ children: "−"
54882
+ }), /* @__PURE__ */ jsx("button", {
54883
+ type: "button",
54884
+ "aria-label": t("uiLibrary.acPanel.increase", "Increase target"),
54885
+ disabled: busy,
54886
+ onClick: (e) => {
54887
+ e.stopPropagation();
54888
+ if (!busy && display.target !== null) {
54889
+ const next = nextClimateTarget(display.target, 1, display);
54890
+ applyOptimistic({ target: next });
54891
+ cap.setTarget({ target: next });
54892
+ }
54893
+ },
54894
+ className: cn("inline-flex h-5 w-5 items-center justify-center rounded text-foreground-subtle hover:text-foreground hover:bg-surface-hover transition-colors text-xs", busy && "opacity-40 cursor-not-allowed"),
54895
+ children: "+"
54896
+ })] }),
54897
+ /* @__PURE__ */ jsx("select", {
54898
+ "aria-label": t("uiLibrary.acPanel.mode", "Mode"),
54899
+ value: display.mode,
54900
+ disabled: busy,
54901
+ onChange: (e) => {
54902
+ e.stopPropagation();
54903
+ const mode = display.availableModes.find((m) => m === e.target.value);
54904
+ if (!busy && mode) {
54905
+ applyOptimistic({ mode });
54906
+ cap.setMode({ mode });
54907
+ }
54908
+ },
54909
+ className: cn("bg-transparent px-0.5 text-xs text-foreground-subtle hover:text-foreground cursor-pointer", busy && "opacity-40 cursor-not-allowed"),
54910
+ children: display.availableModes.map((m) => /* @__PURE__ */ jsx("option", {
54911
+ value: m,
54912
+ children: modeLabel(t, m)
54913
+ }, m))
54729
54914
  })
54730
54915
  ]
54731
54916
  });
54732
- const programs = display.availablePrograms;
54917
+ const accent = MODE_ACCENT[display.mode];
54918
+ const on = display.mode !== "off";
54919
+ const heatingOnly = !climateOffersCooling(display.availableModes);
54920
+ const setpointBounds = climateSetpointBounds(display);
54921
+ const CurrentPresetIcon = presetIcon(display.preset);
54922
+ const boost = display.preset === "turbo";
54923
+ const period = Math.max(.55, airflowPeriodSec(display.fanMode) * (boost ? .6 : 1));
54924
+ const showVSwing = display.swingVertical !== null;
54925
+ const showHSwing = display.swingHorizontal !== null;
54926
+ const swaying = on && (display.swingVertical === true || display.swingHorizontal === true);
54733
54927
  return /* @__PURE__ */ jsxs("div", {
54734
- className: "flex flex-col gap-3 rounded-lg border border-border bg-surface p-4",
54928
+ "data-mode": display.mode,
54929
+ className: cn("relative flex flex-col items-stretch gap-2.5 overflow-hidden rounded-lg border p-3 transition-colors", MODE_COLOR[display.mode]),
54735
54930
  children: [
54736
- /* @__PURE__ */ jsxs("div", {
54737
- className: "flex items-start gap-4",
54738
- children: [/* @__PURE__ */ jsx(DishwasherGraphic, {
54739
- running,
54740
- progressPercent: display.progress
54741
- }), /* @__PURE__ */ jsxs("div", {
54742
- className: "flex min-w-0 flex-1 flex-col gap-2",
54743
- children: [
54744
- /* @__PURE__ */ jsxs("div", {
54745
- className: "flex flex-wrap items-center gap-2",
54746
- children: [/* @__PURE__ */ jsx("span", {
54747
- className: cn("text-3xl font-semibold", meta.tone),
54748
- children: meta.label
54749
- }), display.powerOn === false && /* @__PURE__ */ jsx("span", {
54750
- className: "text-xs font-medium text-foreground-subtle",
54751
- children: t("uiLibrary.dishwasher.powerOff", "Power off")
54752
- })]
54753
- }),
54754
- display.program != null && /* @__PURE__ */ jsx("span", {
54755
- className: "text-sm text-foreground-subtle",
54756
- title: display.program,
54757
- children: featureLabel(display.program)
54758
- }),
54759
- display.remaining != null && /* @__PURE__ */ jsxs("span", {
54760
- className: "inline-flex items-center gap-1 text-sm text-foreground-subtle tabular-nums",
54761
- children: [/* @__PURE__ */ jsx(Timer, { className: "h-3.5 w-3.5" }), t("uiLibrary.dishwasher.remaining", "{{time}} left", { time: formatDuration(display.remaining, t) })]
54762
- }),
54763
- display.delayedStart != null && display.delayedStart > 0 && /* @__PURE__ */ jsx("span", {
54764
- className: "text-xs text-foreground-subtle tabular-nums",
54765
- children: t("uiLibrary.dishwasher.startsIn", "Starts in {{time}}", { time: formatDuration(display.delayedStart, t) })
54766
- }),
54767
- display.progress != null && /* @__PURE__ */ jsxs("div", {
54768
- className: "flex items-center gap-2",
54769
- children: [/* @__PURE__ */ jsx("div", {
54770
- className: "h-1.5 flex-1 rounded bg-surface-hover overflow-hidden",
54771
- children: /* @__PURE__ */ jsx("div", {
54772
- className: "h-full bg-primary transition-[width] duration-500",
54773
- style: { width: `${Math.max(0, Math.min(100, display.progress))}%` }
54774
- })
54775
- }), /* @__PURE__ */ jsxs("span", {
54776
- className: "tabular-nums text-xs text-foreground-subtle",
54777
- children: [Math.round(display.progress), "%"]
54778
- })]
54779
- }),
54780
- /* @__PURE__ */ jsxs("div", {
54781
- className: "flex flex-wrap items-center gap-x-3 gap-y-1.5",
54782
- children: [display.doorOpen === true && /* @__PURE__ */ jsxs("span", {
54783
- className: "inline-flex items-center gap-1 text-xs text-warning",
54784
- children: [/* @__PURE__ */ jsx(DoorOpen, { className: "h-3.5 w-3.5" }), t("uiLibrary.dishwasher.doorOpen", "Door open")]
54785
- }), visibleDishwasherEvents(display.activeEvents).map((event) => /* @__PURE__ */ jsx("span", {
54786
- className: "text-xs text-warning",
54787
- title: event,
54788
- children: featureLabel(event)
54789
- }, event))]
54790
- }),
54791
- display.operationState === "Error" && /* @__PURE__ */ jsxs("div", {
54792
- className: "inline-flex items-center gap-1 text-xs text-danger",
54793
- children: [/* @__PURE__ */ jsx(TriangleAlert, { className: "h-3.5 w-3.5" }), /* @__PURE__ */ jsx("span", { children: display.errorLabel != null ? featureLabel(display.errorLabel) : display.errorCode != null ? t("uiLibrary.dishwasher.errorCode", "Error {{code}}", { code: display.errorCode }) : t("uiLibrary.dishwasher.op.error", "Error") })]
54794
- }),
54795
- /* @__PURE__ */ jsxs("div", {
54796
- className: "flex flex-wrap items-center gap-2",
54797
- children: [
54798
- /* @__PURE__ */ jsx(DishwasherIconButton, {
54799
- label: t("uiLibrary.dishwasher.start", "Start"),
54800
- busy: busy || !startable,
54801
- active: running,
54802
- onClick: () => press(() => cap.start({})),
54803
- children: /* @__PURE__ */ jsx(Play, { className: "h-4 w-4" })
54804
- }),
54805
- /* @__PURE__ */ jsx(DishwasherIconButton, {
54806
- label: paused ? t("uiLibrary.dishwasher.resume", "Resume") : t("uiLibrary.dishwasher.pause", "Pause"),
54807
- busy: busy || !(running || paused),
54808
- active: paused,
54809
- onClick: () => press(() => paused ? cap.resume({}) : cap.pause({})),
54810
- children: /* @__PURE__ */ jsx(Pause, { className: "h-4 w-4" })
54811
- }),
54812
- /* @__PURE__ */ jsx(DishwasherIconButton, {
54813
- label: t("uiLibrary.dishwasher.stop", "Stop"),
54814
- busy: busy || !(running || paused),
54815
- active: false,
54816
- onClick: () => press(() => cap.stop({})),
54817
- children: /* @__PURE__ */ jsx(Square, { className: "h-3.5 w-3.5" })
54818
- }),
54819
- /* @__PURE__ */ jsx(DishwasherIconButton, {
54820
- label: t("uiLibrary.dishwasher.power", "Power"),
54821
- busy: busy || display.powerOn === null,
54822
- active: display.powerOn === true,
54823
- onClick: () => {
54824
- const next = display.powerOn !== true;
54825
- press(() => cap.setPower({ on: next }));
54826
- },
54827
- children: /* @__PURE__ */ jsx(Power, { className: "h-4 w-4" })
54828
- })
54829
- ]
54830
- })
54831
- ]
54832
- })]
54833
- }),
54834
- programs.length > 0 && /* @__PURE__ */ jsxs("label", {
54835
- className: "flex items-center gap-2 text-xs text-foreground-subtle",
54836
- children: [/* @__PURE__ */ jsx("span", {
54837
- className: "w-16 shrink-0",
54838
- children: t("uiLibrary.dishwasher.program", "Program")
54839
- }), /* @__PURE__ */ jsxs("select", {
54840
- "aria-label": t("uiLibrary.dishwasher.program", "Program"),
54841
- value: display.selectedProgram ?? "",
54842
- disabled: busy,
54843
- onChange: (e) => {
54844
- const program = e.target.value;
54845
- if (!program) return;
54846
- cap.setProgram({ program });
54847
- },
54848
- onClick: (e) => {
54849
- e.stopPropagation();
54850
- },
54851
- className: "flex-1 rounded border border-border bg-surface px-2 py-1 text-foreground disabled:opacity-50",
54852
- children: [display.selectedProgram == null && /* @__PURE__ */ jsx("option", {
54853
- value: "",
54854
- children: "—"
54855
- }), programs.map((p) => /* @__PURE__ */ jsx("option", {
54856
- value: p,
54857
- children: featureLabel(p)
54858
- }, p))]
54859
- })]
54860
- }),
54861
- /* @__PURE__ */ jsxs("div", {
54862
- className: "flex flex-wrap gap-4 text-xs",
54863
- children: [
54864
- /* @__PURE__ */ jsx(ToggleRow, {
54865
- label: t("uiLibrary.dishwasher.halfLoad", "Half load"),
54866
- checked: display.halfLoad,
54867
- shown: link,
54868
- busy: busy || optionTogglesLocked,
54869
- onChange: (on) => void cap.setHalfLoad({ on })
54870
- }),
54871
- /* @__PURE__ */ jsx(ToggleRow, {
54872
- label: t("uiLibrary.dishwasher.hygienePlus", "Hygiene plus"),
54873
- checked: display.hygienePlus,
54874
- shown: link,
54875
- busy: busy || optionTogglesLocked,
54876
- onChange: (on) => void cap.setHygienePlus({ on })
54877
- }),
54878
- /* @__PURE__ */ jsx(ToggleRow, {
54879
- label: t("uiLibrary.dishwasher.extraDry", "Extra dry"),
54880
- checked: display.extraDry,
54881
- shown: link,
54882
- busy: busy || optionTogglesLocked,
54883
- onChange: (on) => void cap.setExtraDry({ on })
54884
- }),
54885
- /* @__PURE__ */ jsx(ToggleRow, {
54886
- label: t("uiLibrary.dishwasher.intensiveZone", "Intensive zone"),
54887
- checked: display.intensiveZone,
54888
- shown: link,
54889
- busy: busy || optionTogglesLocked,
54890
- onChange: (on) => void cap.setIntensiveZone({ on })
54891
- }),
54892
- /* @__PURE__ */ jsx(ToggleRow, {
54893
- label: t("uiLibrary.dishwasher.varioSpeedPlus", "VarioSpeed+"),
54894
- checked: display.varioSpeedPlus,
54895
- shown: link,
54896
- busy: busy || optionTogglesLocked,
54897
- onChange: (on) => void cap.setVarioSpeedPlus({ on })
54898
- }),
54899
- /* @__PURE__ */ jsx(ToggleRow, {
54900
- label: t("uiLibrary.dishwasher.childLock", "Child lock"),
54901
- checked: display.childLock,
54902
- shown: link,
54903
- busy,
54904
- onChange: (on) => void cap.setChildLock({ on })
54905
- })
54906
- ]
54907
- })
54908
- ]
54909
- });
54910
- }
54911
- /**
54912
- * One boolean setting. `checked === null` is "the appliance has not said": on a reachable
54913
- * appliance that means it does not offer the setting (hidden); on an unreachable one the
54914
- * setting is shown but disabled and marked unknown — never as an unchecked box.
54915
- */
54916
- function ToggleRow({ label, checked, shown, busy, onChange }) {
54917
- const t = useUiText();
54918
- if (checked === null && shown) return null;
54919
- return /* @__PURE__ */ jsxs("label", {
54920
- className: "inline-flex items-center gap-2 cursor-pointer",
54921
- children: [
54922
- /* @__PURE__ */ jsx("input", {
54923
- type: "checkbox",
54924
- checked: checked === true,
54925
- "aria-checked": checked === null ? "mixed" : checked,
54926
- disabled: busy || checked === null,
54927
- onChange: (e) => {
54928
- onChange(e.target.checked);
54929
- },
54930
- onClick: (e) => {
54931
- e.stopPropagation();
54932
- },
54933
- className: "rounded border-border"
54934
- }),
54935
- /* @__PURE__ */ jsx("span", { children: label }),
54936
- checked === null && /* @__PURE__ */ jsx("span", {
54937
- className: "text-foreground-subtle",
54938
- children: t("uiLibrary.dishwasher.unknownValue", "—")
54939
- })
54940
- ]
54941
- });
54942
- }
54943
- function DishwasherInlineControl(props) {
54944
- return /* @__PURE__ */ jsx(DishwasherPanel, {
54945
- ...props,
54946
- layout: "compact"
54947
- });
54948
- }
54949
- function DishwasherHeroCard(props) {
54950
- return /* @__PURE__ */ jsx(DishwasherPanel, {
54951
- ...props,
54952
- layout: "full"
54953
- });
54954
- }
54955
- //#endregion
54956
- //#region src/composites/device-controls/appliance-control.tsx
54957
- /**
54958
- * Appliance card for a `DeviceType.Washer` / `DeviceType.Dryer` device.
54959
- *
54960
- * These appliances have no program surface: what is worth showing is whether
54961
- * the cycle is running (the `running-state` cap), for how long, and what the
54962
- * appliance draws right now (the `power-meter` cap). Both slices are read
54963
- * straight from the device; neither is required.
54964
- * - ApplianceInlineControl (device-list row): the running badge round the
54965
- * drum icon, plus the live watts when there are any.
54966
- * - ApplianceHeroCard (device-detail hero): the drum (turning only while a
54967
- * cycle runs), the state, the phase, the dwell and the power.
54968
- *
54969
- * UNKNOWN IS NOT OFF (D393). `running: null` is drawn as "Unknown" and the
54970
- * drum stays still and unbadged; a missing watt reading is a dash, never
54971
- * "0 W". A slice that has not landed hides its row instead of faking a value.
54972
- */
54973
- var KEYFRAMES$1 = `
54974
- @keyframes apl-tumble { to { transform: rotate(360deg) } }
54975
- .apl-drum-run { animation: apl-tumble 3s linear infinite; }
54976
- @media (prefers-reduced-motion: reduce) {
54977
- .apl-drum-run { animation: none !important; }
54978
- }
54979
- `;
54980
- /** Whole watts, or a dash when the appliance has not reported a reading. */
54981
- function formatWatts(power) {
54982
- return power === void 0 || !Number.isFinite(power) ? "—" : `${Math.round(power)} W`;
54983
- }
54984
- /** The state to a person: running / idle, or why there is none (unknown). */
54985
- function applianceStateLabel(running, t) {
54986
- if (running === true) return {
54987
- label: t("uiLibrary.appliance.running", "Running"),
54988
- tone: "text-primary"
54989
- };
54990
- if (running === false) return {
54991
- label: t("uiLibrary.appliance.idle", "Idle"),
54992
- tone: "text-foreground"
54993
- };
54994
- return {
54995
- label: t("uiLibrary.appliance.unknown", "Unknown"),
54996
- tone: "text-foreground-subtle"
54997
- };
54998
- }
54999
- function dwellText(running, since, now, t) {
55000
- if (running !== true) return null;
55001
- const { duration } = runningStatusParts(running, since, null, now);
55002
- if (duration === void 0) return null;
55003
- return "minutes" in duration ? t("uiLibrary.appliance.forMinutes", "for {{count}} min", { count: duration.minutes }) : t("uiLibrary.appliance.forHours", "for {{count}} h", { count: duration.hours });
55004
- }
55005
- function useApplianceState(props) {
55006
- return {
55007
- running: useDeviceState(props.trpc, props.deviceId, (s) => s.runningState),
55008
- power: useDeviceState(props.trpc, props.deviceId, (s) => s.powerMeter)
55009
- };
55010
- }
55011
- /** The drum: a ring with a few items in it, turning only while a cycle runs. */
55012
- function Drum({ running }) {
55013
- return /* @__PURE__ */ jsx("div", {
55014
- "aria-hidden": "true",
55015
- "data-testid": "appliance-drum",
55016
- "data-running": running === true ? "running" : running === false ? "idle" : "unknown",
55017
- className: "relative flex h-28 w-28 shrink-0 items-center justify-center rounded-full border-2 border-border bg-surface-hover",
55018
- children: /* @__PURE__ */ jsxs("div", {
55019
- className: cn("relative h-20 w-20 rounded-full border-2", running === true ? "apl-drum-run border-primary" : "border-border"),
55020
- "data-testid": "appliance-drum-ring",
55021
- children: [
55022
- /* @__PURE__ */ jsx("span", { className: "absolute left-2 top-4 h-3 w-3 rounded-full bg-primary/40" }),
55023
- /* @__PURE__ */ jsx("span", { className: "absolute bottom-3 right-3 h-4 w-4 rounded-full bg-info/40" }),
55024
- /* @__PURE__ */ jsx("span", { className: "absolute bottom-4 left-4 h-2.5 w-2.5 rounded-full bg-foreground-subtle/40" })
55025
- ]
55026
- })
55027
- });
55028
- }
55029
- function ApplianceHeroCard(props) {
55030
- const t = useUiText();
55031
- const { running, power } = useApplianceState(props);
55032
- const state = running?.running ?? null;
55033
- const meta = applianceStateLabel(state, t);
55034
- const phase = running?.phase?.trim() ?? "";
55035
- const dwell = running === void 0 ? null : dwellText(state, running.since, Date.now(), t);
55036
- return /* @__PURE__ */ jsxs("div", {
55037
- className: "flex items-center gap-4 rounded-lg border border-border bg-surface p-4",
55038
- children: [
55039
- /* @__PURE__ */ jsx("style", { children: KEYFRAMES$1 }),
55040
- /* @__PURE__ */ jsx(Drum, { running: state }),
55041
- /* @__PURE__ */ jsxs("div", {
55042
- className: "flex min-w-0 flex-1 flex-col gap-2",
55043
- children: [
55044
- /* @__PURE__ */ jsxs("div", {
55045
- className: "flex flex-wrap items-baseline gap-x-2",
55046
- children: [/* @__PURE__ */ jsx("span", {
55047
- "data-testid": "appliance-state",
55048
- className: cn("text-3xl font-semibold", meta.tone),
55049
- children: meta.label
55050
- }), dwell !== null && /* @__PURE__ */ jsx("span", {
55051
- className: "text-sm tabular-nums text-foreground-subtle",
55052
- children: dwell
55053
- })]
55054
- }),
55055
- phase !== "" && state !== null && /* @__PURE__ */ jsx("span", {
55056
- className: "text-sm text-foreground-subtle",
55057
- children: phase
55058
- }),
55059
- power !== void 0 && /* @__PURE__ */ jsxs("span", {
55060
- "data-testid": "appliance-power",
55061
- className: "inline-flex items-center gap-1 text-sm tabular-nums text-foreground-muted",
55062
- title: power.power === void 0 ? t("uiLibrary.appliance.powerUnknown", "Power unknown") : void 0,
55063
- children: [/* @__PURE__ */ jsx(Zap, {
55064
- className: "h-3.5 w-3.5",
55065
- "aria-hidden": true
55066
- }), formatWatts(power.power)]
55067
- })
55068
- ]
55069
- })
55070
- ]
55071
- });
55072
- }
55073
- function ApplianceInlineControl(props) {
55074
- const { running, power } = useApplianceState(props);
55075
- return /* @__PURE__ */ jsxs("div", {
55076
- className: "inline-flex items-center gap-1.5 max-w-full",
55077
- children: [/* @__PURE__ */ jsx(RunningBadge, {
55078
- running: running?.running ?? null,
55079
- children: /* @__PURE__ */ jsx(WashingMachine, {
55080
- className: "h-4 w-4 text-foreground-muted",
55081
- "aria-hidden": true
55082
- })
55083
- }), power !== void 0 && /* @__PURE__ */ jsx("span", {
55084
- className: "text-xs tabular-nums text-foreground-subtle",
55085
- children: formatWatts(power.power)
55086
- })]
55087
- });
55088
- }
55089
- //#endregion
55090
- //#region src/composites/device-controls/heating-valve-readout.tsx
55091
- function formatHeatingValvePosition(position) {
55092
- return position !== null ? `${position}%` : "—";
55093
- }
55094
- function HeatingValveReadout({ trpc, deviceId, layout }) {
55095
- const t = useUiText();
55096
- const { cap, slice } = useDeviceCapability({
55097
- trpc,
55098
- deviceId,
55099
- cap: (d) => d.heatingValve,
55100
- slice: (d) => d.state.heatingValve
55101
- });
55102
- if (cap === void 0 || slice === void 0) return null;
55103
- const label = t("uiLibrary.heatingValveReadout.valve", "Valve");
55104
- const value = formatHeatingValvePosition(slice.position);
55105
- if (layout === "compact") return /* @__PURE__ */ jsx("span", {
55106
- className: "inline-flex items-center text-xs tabular-nums text-foreground-subtle",
55107
- "aria-label": `${label} ${value}`,
55108
- children: value
55109
- });
55110
- return /* @__PURE__ */ jsxs("div", {
55111
- className: "flex items-center gap-2 text-xs tabular-nums text-foreground-subtle",
55112
- children: [/* @__PURE__ */ jsx("span", { children: label }), /* @__PURE__ */ jsx("span", {
55113
- className: "font-medium text-foreground",
55114
- children: value
55115
- })]
55116
- });
55117
- }
55118
- //#endregion
55119
- //#region src/composites/device-controls/ac-panel.tsx
55120
- /** Modes that mean the device can cool, dry, or move air — an air conditioner. */
55121
- var COOLING_MODES = new Set([
55122
- "cool",
55123
- "heat_cool",
55124
- "dry",
55125
- "fan_only"
55126
- ]);
55127
- /** A heater offers heat (and maybe auto/off) and none of the cooling modes. */
55128
- function climateOffersCooling(modes) {
55129
- return modes.some((mode) => COOLING_MODES.has(mode));
55130
- }
55131
- /** Setpoint track bounds. Absent when the integration did not report both ends. */
55132
- function climateSetpointBounds(status) {
55133
- const min = status.minTemp;
55134
- const max = status.maxTemp;
55135
- if (typeof min !== "number" || typeof max !== "number") return null;
55136
- if (!Number.isFinite(min) || !Number.isFinite(max) || max <= min) return null;
55137
- return {
55138
- min,
55139
- max
55140
- };
55141
- }
55142
- /** Map a 0–1 drag fraction onto the setpoint, snapped to `tempStep`. */
55143
- function climateTargetFromFraction(fraction, bounds, tempStep) {
55144
- const step = resolveClimateTempStep(tempStep);
55145
- const clamped = Math.min(1, Math.max(0, fraction));
55146
- const raw = bounds.min + clamped * (bounds.max - bounds.min);
55147
- const steps = Math.round((raw - bounds.min) / step);
55148
- const snapped = bounds.min + steps * step;
55149
- const rounded = Math.round(snapped * 1e3) / 1e3;
55150
- return Math.min(bounds.max, Math.max(bounds.min, rounded));
55151
- }
55152
- /** AC-appropriate short mode labels. Exhaustive over HvacMode. */
55153
- function modeLabel(t, mode) {
55154
- switch (mode) {
55155
- case "cool": return t("uiLibrary.acPanel.modeCool", "Cool");
55156
- case "heat": return t("uiLibrary.acPanel.modeHeat", "Heat");
55157
- case "auto": return t("uiLibrary.acPanel.modeAuto", "Auto");
55158
- case "heat_cool": return t("uiLibrary.acPanel.modeHeatCool", "Heat·Cool");
55159
- case "fan_only": return t("uiLibrary.acPanel.modeFan", "Fan");
55160
- case "dry": return t("uiLibrary.acPanel.modeDry", "Dry");
55161
- case "off": return t("uiLibrary.acPanel.modeOff", "Off");
55162
- }
55163
- }
55164
- /** Per-mode icon (lucide). Exhaustive over HvacMode. */
55165
- var MODE_ICON = {
55166
- cool: Snowflake,
55167
- heat: Flame,
55168
- auto: Sparkles,
55169
- heat_cool: Thermometer,
55170
- fan_only: Fan,
55171
- dry: Droplets,
55172
- off: Power
55173
- };
55174
- /** Mode accent hex — drives the airflow particles, the glow, and the target
55175
- * value colour. Mirrors the thermostat gauge palette. Exhaustive. */
55176
- var MODE_ACCENT = {
55177
- heat: "#f59e0b",
55178
- cool: "#60a5fa",
55179
- auto: "#c084fc",
55180
- heat_cool: "#e879f9",
55181
- fan_only: "#94a3b8",
55182
- dry: "#22d3ee",
55183
- off: "#a1a1aa"
55184
- };
55185
- /** Title-case a snake/lower token for a selector option ('medium_low' → 'Medium
55186
- * low', 'turbo' → 'Turbo'). Shared by the fan + preset selectors. */
55187
- function fanLabel(token) {
55188
- const spaced = token.replace(/_/g, " ");
55189
- return spaced.charAt(0).toUpperCase() + spaced.slice(1);
55190
- }
55191
- /** Preset → icon. Unknown presets fall back to a neutral sparkle. */
55192
- function presetIcon(preset) {
55193
- switch (preset) {
55194
- case "turbo": return Zap;
55195
- case "quiet": return Feather;
55196
- case "sleep": return Moon;
55197
- case "eco": return Leaf;
55198
- case "8c_heat": return Snowflake;
55199
- case "none": return Ban;
55200
- default: return Sparkles;
55201
- }
55202
- }
55203
- /**
55204
- * Fan level → airflow animation period. Higher speed ⇒ shorter period. Unknown
55205
- * strings fall back to a medium pace. Turbo (a preset) shortens it further.
55206
- */
55207
- function airflowPeriodSec(fanMode) {
55208
- switch (fanMode) {
55209
- case "high": return 1;
55210
- case "medium_high": return 1.3;
55211
- case "medium": return 1.6;
55212
- case "medium_low": return 1.9;
55213
- case "low": return 2.2;
55214
- default: return 1.8;
55215
- }
55216
- }
55217
- var KEYFRAMES = `
55218
- @keyframes acv-fall { 0%{transform:translateY(-1.75rem);opacity:0} 18%{opacity:.7} 82%{opacity:.7} 100%{transform:translateY(7.5rem);opacity:0} }
55219
- @keyframes acv-rise { 0%{transform:translateY(7.5rem);opacity:0} 18%{opacity:.7} 82%{opacity:.7} 100%{transform:translateY(-1.75rem);opacity:0} }
55220
- @keyframes acv-sway { 0%,100%{transform:translateX(-9%)} 50%{transform:translateX(9%)} }
55221
- @keyframes acv-swing-h { 0%,100%{transform:translateX(-22%)} 50%{transform:translateX(22%)} }
55222
- @keyframes acv-swing-v { 0%,100%{transform:translateY(-22%)} 50%{transform:translateY(22%)} }
55223
- @keyframes acv-spin { to { transform:rotate(360deg) } }
55224
- @keyframes acv-glow { 0%,100%{opacity:.35;transform:scale(1)} 50%{opacity:.6;transform:scale(1.06)} }
55225
- @media (prefers-reduced-motion: reduce) {
55226
- .acv-streak, .acv-fan, .acv-sway-wrap, .acv-glow, .acv-swing { animation: none !important; }
55227
- }
55228
- `;
55229
- function AcPanel({ trpc, deviceId, layout, optimistic }) {
55230
- const t = useUiText();
55231
- const { cap, slice, available } = useDeviceCapability({
55232
- trpc,
55233
- deviceId,
55234
- cap: (d) => d.climateControl,
55235
- slice: (d) => d.state.climateControl
55236
- });
55237
- const { display, applyOptimistic } = useOptimisticSlice(slice, { enabled: optimistic ?? true });
55238
- if (cap === void 0) return null;
55239
- if (display === void 0) return null;
55240
- const busy = !available;
55241
- if (layout === "compact") return /* @__PURE__ */ jsxs("div", {
55242
- "data-mode": display.mode,
55243
- className: "inline-flex items-center gap-1",
55244
- children: [
55245
- /* @__PURE__ */ jsx("span", {
55246
- className: cn("text-xs tabular-nums font-medium", MODE_TEXT_COLOR[display.mode]),
55247
- children: display.target !== null ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
55248
- display.target,
55249
- "°",
55250
- display.currentTemp !== null && /* @__PURE__ */ jsxs("span", {
55251
- className: "text-foreground-subtle font-normal",
55252
- children: [
55253
- " ",
55254
- "(",
55255
- display.currentTemp,
55256
- "°)"
55257
- ]
55258
- })
55259
- ] }) : display.currentTemp !== null ? /* @__PURE__ */ jsxs("span", {
55260
- className: "text-foreground-subtle",
55261
- children: [display.currentTemp, "°"]
55262
- }) : null
55263
- }),
55264
- display.target !== null && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("button", {
55265
- type: "button",
55266
- "aria-label": t("uiLibrary.acPanel.decrease", "Decrease target"),
55267
- disabled: busy,
55268
- onClick: (e) => {
55269
- e.stopPropagation();
55270
- if (!busy && display.target !== null) {
55271
- const next = nextClimateTarget(display.target, -1, display);
55272
- applyOptimistic({ target: next });
55273
- cap.setTarget({ target: next });
55274
- }
55275
- },
55276
- className: cn("inline-flex h-5 w-5 items-center justify-center rounded text-foreground-subtle hover:text-foreground hover:bg-surface-hover transition-colors text-xs", busy && "opacity-40 cursor-not-allowed"),
55277
- children: "−"
55278
- }), /* @__PURE__ */ jsx("button", {
55279
- type: "button",
55280
- "aria-label": t("uiLibrary.acPanel.increase", "Increase target"),
55281
- disabled: busy,
55282
- onClick: (e) => {
55283
- e.stopPropagation();
55284
- if (!busy && display.target !== null) {
55285
- const next = nextClimateTarget(display.target, 1, display);
55286
- applyOptimistic({ target: next });
55287
- cap.setTarget({ target: next });
55288
- }
55289
- },
55290
- className: cn("inline-flex h-5 w-5 items-center justify-center rounded text-foreground-subtle hover:text-foreground hover:bg-surface-hover transition-colors text-xs", busy && "opacity-40 cursor-not-allowed"),
55291
- children: "+"
55292
- })] }),
55293
- /* @__PURE__ */ jsx("select", {
55294
- "aria-label": t("uiLibrary.acPanel.mode", "Mode"),
55295
- value: display.mode,
55296
- disabled: busy,
55297
- onChange: (e) => {
55298
- e.stopPropagation();
55299
- const mode = display.availableModes.find((m) => m === e.target.value);
55300
- if (!busy && mode) {
55301
- applyOptimistic({ mode });
55302
- cap.setMode({ mode });
55303
- }
55304
- },
55305
- className: cn("bg-transparent px-0.5 text-xs text-foreground-subtle hover:text-foreground cursor-pointer", busy && "opacity-40 cursor-not-allowed"),
55306
- children: display.availableModes.map((m) => /* @__PURE__ */ jsx("option", {
55307
- value: m,
55308
- children: modeLabel(t, m)
55309
- }, m))
55310
- })
55311
- ]
55312
- });
55313
- const accent = MODE_ACCENT[display.mode];
55314
- const on = display.mode !== "off";
55315
- const heatingOnly = !climateOffersCooling(display.availableModes);
55316
- const setpointBounds = climateSetpointBounds(display);
55317
- const CurrentPresetIcon = presetIcon(display.preset);
55318
- const boost = display.preset === "turbo";
55319
- const period = Math.max(.55, airflowPeriodSec(display.fanMode) * (boost ? .6 : 1));
55320
- const showVSwing = display.swingVertical !== null;
55321
- const showHSwing = display.swingHorizontal !== null;
55322
- const swaying = on && (display.swingVertical === true || display.swingHorizontal === true);
55323
- return /* @__PURE__ */ jsxs("div", {
55324
- "data-mode": display.mode,
55325
- className: cn("relative flex flex-col items-stretch gap-2.5 overflow-hidden rounded-lg border p-3 transition-colors", MODE_COLOR[display.mode]),
55326
- children: [
55327
- /* @__PURE__ */ jsx("style", { children: KEYFRAMES }),
54931
+ /* @__PURE__ */ jsx("style", { children: KEYFRAMES$1 }),
55328
54932
  /* @__PURE__ */ jsxs("div", {
55329
54933
  className: "relative z-10 flex flex-col items-center justify-center gap-1 overflow-hidden rounded-lg border border-border/50 bg-surface/30 px-3 py-3",
55330
54934
  children: [
@@ -55466,347 +55070,1080 @@ function AcPanel({ trpc, deviceId, layout, optimistic }) {
55466
55070
  }
55467
55071
  }
55468
55072
  }),
55469
- display.availableFanModes.length > 0 && /* @__PURE__ */ jsx(CompactSelect, {
55470
- label: t("uiLibrary.acPanel.fan", "Fan"),
55471
- icon: /* @__PURE__ */ jsx(Wind, { className: "h-4 w-4 text-sky-500" }),
55472
- value: display.fanMode,
55473
- options: display.availableFanModes.map((f) => ({
55474
- value: f,
55475
- label: fanLabel(f)
55476
- })),
55477
- disabled: busy,
55478
- onChange: (v) => {
55479
- applyOptimistic({ fanMode: v });
55480
- cap.setFanMode({ fanMode: v });
55481
- }
55073
+ display.availableFanModes.length > 0 && /* @__PURE__ */ jsx(CompactSelect, {
55074
+ label: t("uiLibrary.acPanel.fan", "Fan"),
55075
+ icon: /* @__PURE__ */ jsx(Wind, { className: "h-4 w-4 text-sky-500" }),
55076
+ value: display.fanMode,
55077
+ options: display.availableFanModes.map((f) => ({
55078
+ value: f,
55079
+ label: fanLabel(f)
55080
+ })),
55081
+ disabled: busy,
55082
+ onChange: (v) => {
55083
+ applyOptimistic({ fanMode: v });
55084
+ cap.setFanMode({ fanMode: v });
55085
+ }
55086
+ }),
55087
+ display.availablePresets.length > 0 && /* @__PURE__ */ jsx(CompactSelect, {
55088
+ label: t("uiLibrary.acPanel.preset", "Preset"),
55089
+ icon: /* @__PURE__ */ jsx(CurrentPresetIcon, { className: "h-4 w-4 text-emerald-500" }),
55090
+ value: display.preset,
55091
+ options: display.availablePresets.map((p) => ({
55092
+ value: p,
55093
+ label: fanLabel(p)
55094
+ })),
55095
+ disabled: busy,
55096
+ onChange: (v) => {
55097
+ applyOptimistic({ preset: v });
55098
+ cap.setPreset({ preset: v });
55099
+ }
55100
+ })
55101
+ ]
55102
+ }),
55103
+ (showVSwing || showHSwing) && /* @__PURE__ */ jsx(Field, {
55104
+ label: t("uiLibrary.acPanel.swing", "Swing"),
55105
+ children: /* @__PURE__ */ jsxs("div", {
55106
+ className: "grid grid-cols-2 gap-1",
55107
+ children: [showVSwing && /* @__PURE__ */ jsx(SwingToggle, {
55108
+ axis: "vertical",
55109
+ on: display.swingVertical ?? false,
55110
+ busy,
55111
+ onToggle: (next) => {
55112
+ applyOptimistic({ swingVertical: next });
55113
+ cap.setSwingVertical({ on: next });
55114
+ }
55115
+ }), showHSwing && /* @__PURE__ */ jsx(SwingToggle, {
55116
+ axis: "horizontal",
55117
+ on: display.swingHorizontal ?? false,
55118
+ busy,
55119
+ onToggle: (next) => {
55120
+ applyOptimistic({ swingHorizontal: next });
55121
+ cap.setSwingHorizontal({ on: next });
55122
+ }
55123
+ })]
55124
+ })
55125
+ })
55126
+ ]
55127
+ });
55128
+ }
55129
+ /** Labelled control group — a small uppercase header above its control. */
55130
+ function Field({ label, children }) {
55131
+ return /* @__PURE__ */ jsxs("div", {
55132
+ className: "relative z-10 flex flex-col gap-1",
55133
+ children: [/* @__PURE__ */ jsx("span", {
55134
+ className: "text-[10px] font-semibold uppercase tracking-wider text-foreground-subtle",
55135
+ children: label
55136
+ }), children]
55137
+ });
55138
+ }
55139
+ function ModeIcon({ mode, heatingOnly = false, className }) {
55140
+ return /* @__PURE__ */ jsx(heatingOnly && mode === "heat" ? Heater : MODE_ICON[mode], {
55141
+ className,
55142
+ "aria-hidden": true
55143
+ });
55144
+ }
55145
+ /** Compact labelled dropdown — a leading icon + native `<select>` + chevron,
55146
+ * used for the Mode / Fan / Preset selectors so all three fit in one row. */
55147
+ function CompactSelect({ label, icon, value, options, disabled, onChange }) {
55148
+ return /* @__PURE__ */ jsxs("div", {
55149
+ className: "flex min-w-0 flex-col gap-1",
55150
+ children: [/* @__PURE__ */ jsx("span", {
55151
+ className: "text-[10px] font-semibold uppercase tracking-wider text-foreground-subtle",
55152
+ children: label
55153
+ }), /* @__PURE__ */ jsxs("div", {
55154
+ className: cn("flex items-center gap-1 overflow-hidden rounded-lg border border-border/60 bg-surface-subtle px-1.5 py-1.5 has-[:focus-visible]:border-primary", disabled && "opacity-40"),
55155
+ children: [
55156
+ /* @__PURE__ */ jsx("span", {
55157
+ className: "flex shrink-0",
55158
+ children: icon
55159
+ }),
55160
+ /* @__PURE__ */ jsx("select", {
55161
+ "aria-label": label,
55162
+ value,
55163
+ disabled,
55164
+ onChange: (e) => {
55165
+ e.stopPropagation();
55166
+ if (!disabled) onChange(e.target.value);
55167
+ },
55168
+ className: "min-w-0 flex-1 cursor-pointer appearance-none truncate bg-transparent text-xs font-medium text-foreground outline-none",
55169
+ children: options.map((o) => /* @__PURE__ */ jsx("option", {
55170
+ value: o.value,
55171
+ children: o.label
55172
+ }, o.value))
55173
+ }),
55174
+ /* @__PURE__ */ jsx(ChevronDown, { className: "h-3 w-3 shrink-0 text-foreground-subtle" })
55175
+ ]
55176
+ })]
55177
+ });
55178
+ }
55179
+ /** Circular ± button for the target. */
55180
+ function RoundStep({ label, symbol, disabled, onClick }) {
55181
+ return /* @__PURE__ */ jsx("button", {
55182
+ type: "button",
55183
+ "aria-label": label,
55184
+ disabled,
55185
+ onClick,
55186
+ className: cn("flex h-8 w-8 shrink-0 items-center justify-center rounded-full border border-border bg-surface text-lg leading-none text-foreground-subtle transition-colors hover:bg-surface-hover hover:text-foreground active:scale-95", disabled && "opacity-40 cursor-not-allowed"),
55187
+ children: symbol
55188
+ });
55189
+ }
55190
+ /** Setpoint track. Drag previews; the command is sent when the pointer is released. */
55191
+ function RangeTrack({ value, min, max, step, accent, disabled, label, onPreview, onCommit }) {
55192
+ const trackRef = useRef(null);
55193
+ const draggingRef = useRef(false);
55194
+ const [draft, setDraft] = useState(null);
55195
+ const shown = draft ?? value;
55196
+ const pct = `${Math.min(1, Math.max(0, (shown - min) / (max - min))) * 100}%`;
55197
+ const tempAt = (clientX) => {
55198
+ const el = trackRef.current;
55199
+ if (el === null) return value;
55200
+ const rect = el.getBoundingClientRect();
55201
+ if (rect.width <= 0) return value;
55202
+ return climateTargetFromFraction((clientX - rect.left) / rect.width, {
55203
+ min,
55204
+ max
55205
+ }, step);
55206
+ };
55207
+ const onPointerDown = (event) => {
55208
+ if (disabled) return;
55209
+ event.stopPropagation();
55210
+ event.preventDefault();
55211
+ draggingRef.current = true;
55212
+ if (typeof event.currentTarget.setPointerCapture === "function") event.currentTarget.setPointerCapture(event.pointerId);
55213
+ const next = tempAt(event.clientX);
55214
+ setDraft(next);
55215
+ onPreview(next);
55216
+ };
55217
+ const onPointerMove = (event) => {
55218
+ if (disabled || !draggingRef.current) return;
55219
+ event.stopPropagation();
55220
+ const next = tempAt(event.clientX);
55221
+ setDraft(next);
55222
+ onPreview(next);
55223
+ };
55224
+ const endDrag = (event) => {
55225
+ if (!draggingRef.current) return;
55226
+ event.stopPropagation();
55227
+ draggingRef.current = false;
55228
+ const next = tempAt(event.clientX);
55229
+ setDraft(null);
55230
+ if (event.currentTarget.hasPointerCapture?.(event.pointerId) === true) event.currentTarget.releasePointerCapture(event.pointerId);
55231
+ onCommit(next);
55232
+ };
55233
+ const onKeyDown = (event) => {
55234
+ if (disabled) return;
55235
+ const current = draft ?? value;
55236
+ if (event.key === "ArrowRight" || event.key === "ArrowUp") {
55237
+ event.preventDefault();
55238
+ onCommit(nextClimateTarget(current, 1, {
55239
+ tempStep: step,
55240
+ minTemp: min,
55241
+ maxTemp: max
55242
+ }));
55243
+ } else if (event.key === "ArrowLeft" || event.key === "ArrowDown") {
55244
+ event.preventDefault();
55245
+ onCommit(nextClimateTarget(current, -1, {
55246
+ tempStep: step,
55247
+ minTemp: min,
55248
+ maxTemp: max
55249
+ }));
55250
+ } else if (event.key === "Home") {
55251
+ event.preventDefault();
55252
+ onCommit(min);
55253
+ } else if (event.key === "End") {
55254
+ event.preventDefault();
55255
+ onCommit(max);
55256
+ }
55257
+ };
55258
+ return /* @__PURE__ */ jsxs("div", {
55259
+ ref: trackRef,
55260
+ role: "slider",
55261
+ "aria-label": label,
55262
+ "aria-valuemin": min,
55263
+ "aria-valuemax": max,
55264
+ "aria-valuenow": shown,
55265
+ "aria-disabled": disabled,
55266
+ tabIndex: disabled ? -1 : 0,
55267
+ onPointerDown,
55268
+ onPointerMove,
55269
+ onPointerUp: endDrag,
55270
+ onPointerCancel: endDrag,
55271
+ onKeyDown,
55272
+ className: cn("mt-1 w-full touch-none select-none py-2", disabled ? "cursor-not-allowed opacity-40" : "cursor-ew-resize"),
55273
+ children: [/* @__PURE__ */ jsxs("div", {
55274
+ className: "relative h-1.5 w-full rounded-full bg-surface-subtle",
55275
+ children: [/* @__PURE__ */ jsx("div", {
55276
+ className: "absolute inset-y-0 left-0 rounded-full",
55277
+ style: {
55278
+ width: pct,
55279
+ background: accent
55280
+ }
55281
+ }), /* @__PURE__ */ jsx("div", {
55282
+ className: "absolute top-1/2 h-3.5 w-3.5 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-surface shadow",
55283
+ style: {
55284
+ left: pct,
55285
+ background: accent
55286
+ }
55287
+ })]
55288
+ }), /* @__PURE__ */ jsxs("div", {
55289
+ className: "mt-0.5 flex justify-between text-[9px] tabular-nums text-foreground-subtle",
55290
+ children: [/* @__PURE__ */ jsxs("span", { children: [min, "°"] }), /* @__PURE__ */ jsxs("span", { children: [max, "°"] })]
55291
+ })]
55292
+ });
55293
+ }
55294
+ /**
55295
+ * Animated centerpiece. `fan_only` renders a spinning fan; `off` a dim static
55296
+ * vent; every active mode renders drifting particles that FALL (cool/dry/auto)
55297
+ * or RISE (heat), with a horizontal sweep overlaid when a swing axis is active.
55298
+ */
55299
+ function AirflowViz({ mode, accent, periodSec, swaying, forceRising = false }) {
55300
+ const columns = [
55301
+ 0,
55302
+ 1,
55303
+ 2,
55304
+ 3,
55305
+ 4,
55306
+ 5
55307
+ ];
55308
+ const rising = forceRising || mode === "heat";
55309
+ const isDroplet = mode === "dry";
55310
+ return /* @__PURE__ */ jsx("div", {
55311
+ "aria-hidden": true,
55312
+ className: "absolute inset-0 overflow-hidden",
55313
+ children: mode === "off" ? /* @__PURE__ */ jsx("div", {
55314
+ className: "flex h-full items-center justify-center gap-2 opacity-30",
55315
+ children: columns.map((i) => /* @__PURE__ */ jsx("span", { className: "h-8 w-1 rounded-full bg-foreground-subtle opacity-40" }, i))
55316
+ }) : mode === "fan_only" ? /* @__PURE__ */ jsx("div", {
55317
+ className: "flex h-full items-center justify-center",
55318
+ children: /* @__PURE__ */ jsx(FanBlades, {
55319
+ color: accent,
55320
+ periodSec: Math.max(.5, periodSec * .7),
55321
+ size: 56
55322
+ })
55323
+ }) : /* @__PURE__ */ jsx("div", {
55324
+ "data-testid": forceRising ? "climate-heat-rise" : void 0,
55325
+ className: cn("acv-sway-wrap absolute inset-0", swaying && "acv-sway"),
55326
+ style: swaying ? { animation: "acv-sway 2.6s ease-in-out infinite" } : void 0,
55327
+ children: columns.map((i) => {
55328
+ return /* @__PURE__ */ jsx("span", {
55329
+ className: "acv-streak absolute rounded-full",
55330
+ style: {
55331
+ left: `${8 + i * 15}%`,
55332
+ width: isDroplet ? "0.4rem" : "0.3rem",
55333
+ height: isDroplet ? "0.4rem" : "1.9rem",
55334
+ background: accent,
55335
+ boxShadow: `0 0 6px ${accent}`,
55336
+ animationName: rising ? "acv-rise" : "acv-fall",
55337
+ animationTimingFunction: "linear",
55338
+ animationIterationCount: "infinite",
55339
+ animationDuration: `${periodSec}s`,
55340
+ animationDelay: `${i % 3 * (periodSec / 3) + i * .05}s`
55341
+ }
55342
+ }, i);
55343
+ })
55344
+ })
55345
+ });
55346
+ }
55347
+ /** Still radiator fins — the off state of a heating-only climate. */
55348
+ function RadiatorFins() {
55349
+ return /* @__PURE__ */ jsx("div", {
55350
+ "data-testid": "climate-radiator",
55351
+ "aria-hidden": true,
55352
+ className: "flex h-full items-end justify-center gap-1.5 px-8 pb-3 opacity-40",
55353
+ children: [
55354
+ 0,
55355
+ 1,
55356
+ 2,
55357
+ 3,
55358
+ 4,
55359
+ 5,
55360
+ 6
55361
+ ].map((i) => /* @__PURE__ */ jsx("span", { className: "h-10 w-1.5 rounded-t-full bg-foreground-subtle" }, i))
55362
+ });
55363
+ }
55364
+ /** Big spinning fan for `fan_only` mode. */
55365
+ function FanBlades({ color, periodSec, size }) {
55366
+ return /* @__PURE__ */ jsxs("svg", {
55367
+ width: size,
55368
+ height: size,
55369
+ viewBox: "0 0 100 100",
55370
+ className: "acv-fan",
55371
+ style: {
55372
+ animation: `acv-spin ${periodSec}s linear infinite`,
55373
+ transformOrigin: "50% 50%"
55374
+ },
55375
+ "aria-hidden": true,
55376
+ children: [[
55377
+ 0,
55378
+ 120,
55379
+ 240
55380
+ ].map((deg) => /* @__PURE__ */ jsx("path", {
55381
+ d: "M50 50 C 58 30, 78 26, 84 12 C 66 20, 54 34, 50 50 Z",
55382
+ fill: color,
55383
+ opacity: .85,
55384
+ transform: `rotate(${deg} 50 50)`
55385
+ }, deg)), /* @__PURE__ */ jsx("circle", {
55386
+ cx: "50",
55387
+ cy: "50",
55388
+ r: "7",
55389
+ fill: color
55390
+ })]
55391
+ });
55392
+ }
55393
+ /** Swing axis toggle — a card with a MoveVertical/Horizontal glyph that
55394
+ * oscillates along its axis when on. On/off is non-destructive → plain tap. */
55395
+ function SwingToggle({ axis, on, busy, onToggle }) {
55396
+ const t = useUiText();
55397
+ const label = axis === "vertical" ? t("uiLibrary.acPanel.vertical", "Vertical") : t("uiLibrary.acPanel.horizontal", "Horizontal");
55398
+ const Icon = axis === "vertical" ? MoveVertical : MoveHorizontal;
55399
+ const anim = axis === "vertical" ? "acv-swing-v" : "acv-swing-h";
55400
+ return /* @__PURE__ */ jsxs("button", {
55401
+ type: "button",
55402
+ "aria-label": t("uiLibrary.acPanel.swingAxis", "{{axis}} swing", { axis: label }),
55403
+ "aria-pressed": on,
55404
+ disabled: busy,
55405
+ onClick: () => {
55406
+ if (!busy) onToggle(!on);
55407
+ },
55408
+ className: cn("flex items-center justify-center gap-2 rounded-lg border px-2 py-1.5 text-xs font-medium transition-colors", on ? "border-transparent bg-indigo-400 text-indigo-950 shadow-sm" : "border-border/60 bg-surface-subtle text-foreground-subtle hover:bg-surface-hover hover:text-foreground", busy && "opacity-40 cursor-not-allowed"),
55409
+ children: [/* @__PURE__ */ jsx(Icon, {
55410
+ className: "acv-swing h-4 w-4",
55411
+ "aria-hidden": true,
55412
+ style: on ? { animation: `${anim} 1.4s ease-in-out infinite` } : void 0
55413
+ }), label]
55414
+ });
55415
+ }
55416
+ //#endregion
55417
+ //#region src/composites/device-controls/heater-control.tsx
55418
+ /**
55419
+ * Heater controls for a `DeviceType.Heater` device (a dumb plug-in stove).
55420
+ *
55421
+ * A heater is a switch that heats while it is on, and the hub can switch it off
55422
+ * again after a chosen time (`timed-run`, D993):
55423
+ * - HeaterInlineControl (device-list row): the on/off switch and a one-tap
55424
+ * "Run N min".
55425
+ * - HeaterHeroCard (device-detail hero): the glowing heat backdrop (the same
55426
+ * rising streaks a heating air conditioner draws) while it is on, the
55427
+ * on/off switch, the power draw when the plug measures one, and the timed
55428
+ * run (number, unit, Run, countdown, Cancel).
55429
+ *
55430
+ * Every reading may be unknown (`null`) and is drawn as a dash, never as zero.
55431
+ */
55432
+ var HEATER_LIMIT = TIMED_RUN_LIMITS[DeviceType.Heater];
55433
+ var QUICK_RUN_MINUTES = 30;
55434
+ var HEAT_ACCENT = "var(--color-warning)";
55435
+ var HEAT_PERIOD_SEC = 1.8;
55436
+ function useHeater({ trpc, deviceId, optimistic }) {
55437
+ const { cap, slice, available } = useDeviceCapability({
55438
+ trpc,
55439
+ deviceId,
55440
+ cap: (d) => d.switch,
55441
+ slice: (d) => d.state.switch
55442
+ });
55443
+ const running = useDeviceCapability({
55444
+ trpc,
55445
+ deviceId,
55446
+ cap: (d) => d.runningState,
55447
+ slice: (d) => d.state.runningState
55448
+ });
55449
+ const power = useDeviceCapability({
55450
+ trpc,
55451
+ deviceId,
55452
+ cap: (d) => d.powerMeter,
55453
+ slice: (d) => d.state.powerMeter
55454
+ });
55455
+ const timer = useDeviceCapability({
55456
+ trpc,
55457
+ deviceId,
55458
+ cap: (d) => d.timedRun,
55459
+ slice: (d) => d.state.timedRun
55460
+ });
55461
+ const { display, applyOptimistic } = useOptimisticSlice(slice, { enabled: optimistic ?? true });
55462
+ return {
55463
+ cap,
55464
+ display,
55465
+ available,
55466
+ applyOptimistic,
55467
+ running: running.slice,
55468
+ power: power.slice,
55469
+ timer
55470
+ };
55471
+ }
55472
+ function HeaterInlineControl(props) {
55473
+ const t = useUiText();
55474
+ const { cap, display, available, applyOptimistic, timer } = useHeater(props);
55475
+ if (cap === void 0 || display === void 0) return null;
55476
+ const on = display.on === true;
55477
+ const quickMinutes = HEATER_LIMIT === void 0 ? QUICK_RUN_MINUTES : Math.min(QUICK_RUN_MINUTES, maxInUnit(HEATER_LIMIT));
55478
+ return /* @__PURE__ */ jsxs("div", {
55479
+ className: "inline-flex items-center gap-2",
55480
+ children: [/* @__PURE__ */ jsx("span", {
55481
+ onClick: (e) => e.stopPropagation(),
55482
+ children: /* @__PURE__ */ jsx(Switch, {
55483
+ checked: on,
55484
+ disabled: !available,
55485
+ "aria-label": t("uiLibrary.heater.power", "Heater"),
55486
+ onCheckedChange: (next) => {
55487
+ applyOptimistic({ on: next });
55488
+ cap.setState({ on: next });
55489
+ }
55490
+ })
55491
+ }), timer.cap !== void 0 && /* @__PURE__ */ jsx("span", {
55492
+ onClick: (e) => e.stopPropagation(),
55493
+ children: /* @__PURE__ */ jsxs(Button, {
55494
+ size: "sm",
55495
+ variant: "outline",
55496
+ disabled: !timer.online,
55497
+ onClick: () => void timer.cap?.runFor({
55498
+ duration: quickMinutes,
55499
+ unit: "min"
55500
+ }),
55501
+ children: [/* @__PURE__ */ jsx(Timer, {
55502
+ className: "h-3.5 w-3.5",
55503
+ "aria-hidden": true
55504
+ }), t("uiLibrary.heater.quickRun", "Run {{minutes}} min", { minutes: quickMinutes })]
55505
+ })
55506
+ })]
55507
+ });
55508
+ }
55509
+ function HeaterHeroCard(props) {
55510
+ const t = useUiText();
55511
+ const { cap, display, available, applyOptimistic, running, power, timer } = useHeater(props);
55512
+ if (cap === void 0 || display === void 0) return null;
55513
+ const on = display.on === true;
55514
+ const heating = running?.running ?? on;
55515
+ const watts = power?.power ?? null;
55516
+ return /* @__PURE__ */ jsxs("div", {
55517
+ className: "relative flex flex-col items-stretch gap-3 overflow-hidden rounded-lg border border-border bg-surface p-4",
55518
+ children: [
55519
+ /* @__PURE__ */ jsx("style", { children: KEYFRAMES$1 }),
55520
+ /* @__PURE__ */ jsxs("div", {
55521
+ className: "relative flex h-32 items-center justify-center overflow-hidden rounded-lg border border-border-subtle bg-background-elevated",
55522
+ children: [/* @__PURE__ */ jsx("div", {
55523
+ className: cn("pointer-events-none absolute inset-0", heating ? "opacity-60" : "opacity-20"),
55524
+ children: /* @__PURE__ */ jsx(AirflowViz, {
55525
+ mode: heating ? "heat" : "off",
55526
+ accent: HEAT_ACCENT,
55527
+ periodSec: HEAT_PERIOD_SEC,
55528
+ swaying: false,
55529
+ forceRising: true
55530
+ })
55531
+ }), /* @__PURE__ */ jsxs("div", {
55532
+ className: "relative z-10 flex flex-col items-center gap-1",
55533
+ children: [
55534
+ /* @__PURE__ */ jsx(Flame, {
55535
+ className: cn("h-8 w-8", heating ? "text-warning" : "text-foreground-subtle"),
55536
+ "aria-hidden": true
55537
+ }),
55538
+ /* @__PURE__ */ jsx("span", {
55539
+ className: "text-sm font-medium text-foreground",
55540
+ children: heating ? t("uiLibrary.heater.heating", "Heating") : t("uiLibrary.heater.off", "Off")
55541
+ }),
55542
+ /* @__PURE__ */ jsx("span", {
55543
+ className: "text-xs tabular-nums text-foreground-muted",
55544
+ "data-testid": "heater-watts",
55545
+ children: watts === null ? "—" : `${Math.round(watts)} W`
55546
+ })
55547
+ ]
55548
+ })]
55549
+ }),
55550
+ /* @__PURE__ */ jsxs("label", {
55551
+ className: "flex items-center justify-between gap-3 text-sm text-foreground",
55552
+ children: [t("uiLibrary.heater.power", "Heater"), /* @__PURE__ */ jsx(Switch, {
55553
+ checked: on,
55554
+ disabled: !available,
55555
+ onCheckedChange: (next) => {
55556
+ applyOptimistic({ on: next });
55557
+ cap.setState({ on: next });
55558
+ }
55559
+ })]
55560
+ }),
55561
+ timer.cap !== void 0 && HEATER_LIMIT !== void 0 && /* @__PURE__ */ jsx(TimedRunControl, {
55562
+ trpc: props.trpc,
55563
+ deviceId: props.deviceId,
55564
+ limit: HEATER_LIMIT
55565
+ })
55566
+ ]
55567
+ });
55568
+ }
55569
+ //#endregion
55570
+ //#region src/composites/device-controls/dishwasher-control.tsx
55571
+ /**
55572
+ * Dishwasher controls for a `DeviceType.Dishwasher` device.
55573
+ *
55574
+ * Reads the `dishwasher` cap status slice and renders inline + hero surfaces
55575
+ * mirroring vacuum-control / pet-feeder patterns.
55576
+ *
55577
+ * Salt and rinse aid are not here: they are items of the device's `consumables`
55578
+ * cap, shown by the page's Consumables section like every device's (D915).
55579
+ *
55580
+ * UNKNOWN IS NOT OFF. The slice carries `null` for everything the appliance has not
55581
+ * reported, and this view renders that as "—" / a disabled control, never as an unchecked
55582
+ * box or a zero. It also does not echo a command before the appliance confirms it: the
55583
+ * slice moves when the appliance says so.
55584
+ */
55585
+ /** What the operation state is called to a person, and how it is toned. */
55586
+ function dishwasherOperationMeta(operationState, t = defaultUiText) {
55587
+ switch (operationState) {
55588
+ case "Run": return {
55589
+ label: t("uiLibrary.dishwasher.op.run", "Running"),
55590
+ tone: "text-primary"
55591
+ };
55592
+ case "Pause": return {
55593
+ label: t("uiLibrary.dishwasher.op.pause", "Paused"),
55594
+ tone: "text-warning"
55595
+ };
55596
+ case "Finished": return {
55597
+ label: t("uiLibrary.dishwasher.op.finished", "Finished"),
55598
+ tone: "text-success"
55599
+ };
55600
+ case "Error": return {
55601
+ label: t("uiLibrary.dishwasher.op.error", "Error"),
55602
+ tone: "text-danger"
55603
+ };
55604
+ case "Aborting": return {
55605
+ label: t("uiLibrary.dishwasher.op.aborting", "Stopping"),
55606
+ tone: "text-warning"
55607
+ };
55608
+ case "ActionRequired": return {
55609
+ label: t("uiLibrary.dishwasher.op.actionRequired", "Action required"),
55610
+ tone: "text-warning"
55611
+ };
55612
+ case "DelayedStart": return {
55613
+ label: t("uiLibrary.dishwasher.op.delayedStart", "Delayed start"),
55614
+ tone: "text-primary"
55615
+ };
55616
+ case "Ready": return {
55617
+ label: t("uiLibrary.dishwasher.op.ready", "Ready"),
55618
+ tone: "text-foreground"
55619
+ };
55620
+ case "Inactive": return {
55621
+ label: t("uiLibrary.dishwasher.op.inactive", "Inactive"),
55622
+ tone: "text-foreground-subtle"
55623
+ };
55624
+ case null: return {
55625
+ label: t("uiLibrary.dishwasher.unknown", "Unknown"),
55626
+ tone: "text-foreground-subtle"
55627
+ };
55628
+ }
55629
+ }
55630
+ /** The headline for the whole slice: the appliance's state, or why there is none. */
55631
+ function dishwasherHeadline(status, t = defaultUiText) {
55632
+ switch (status.availability) {
55633
+ case "offline": return {
55634
+ label: t("uiLibrary.dishwasher.offline", "Offline"),
55635
+ tone: "text-foreground-subtle"
55636
+ };
55637
+ case "description-missing": return {
55638
+ label: t("uiLibrary.dishwasher.descriptionMissing", "Waiting for the appliance profile"),
55639
+ tone: "text-warning"
55640
+ };
55641
+ case "available": return dishwasherOperationMeta(status.operationState, t);
55642
+ }
55643
+ }
55644
+ /** Last segment of a feature key, spaced out: `Dishcare.Dishwasher.Program.Eco50` -> `Eco50`. */
55645
+ function featureLabel(key) {
55646
+ return (key.split(".").pop() ?? key).replace(/([a-z0-9])([A-Z])/g, "$1 $2");
55647
+ }
55648
+ /**
55649
+ * Salt and rinse aid are consumable items (D915). Their events must not
55650
+ * reappear on the hero — the Consumables section is the only surface.
55651
+ */
55652
+ function isConsumableDishwasherEvent(event) {
55653
+ const short = (event.split(".").pop() ?? event).toLowerCase();
55654
+ return short.includes("salt") || short.includes("rinse");
55655
+ }
55656
+ /** Raised events the hero may name. Consumable events are dropped. */
55657
+ function visibleDishwasherEvents(events) {
55658
+ return events.filter((event) => !isConsumableDishwasherEvent(event));
55659
+ }
55660
+ /** Whole seconds as a short duration: `1 h 24 min`, `42 min`, `30 s`. */
55661
+ function formatDuration(seconds, t = defaultUiText) {
55662
+ if (seconds < 60) return t("uiLibrary.dishwasher.durationSeconds", "{{n}} s", { n: seconds });
55663
+ const minutes = Math.round(seconds / 60);
55664
+ if (minutes < 60) return t("uiLibrary.dishwasher.durationMinutes", "{{n}} min", { n: minutes });
55665
+ const hours = Math.floor(minutes / 60);
55666
+ const rest = minutes % 60;
55667
+ return rest === 0 ? t("uiLibrary.dishwasher.durationHours", "{{n}} h", { n: hours }) : t("uiLibrary.dishwasher.durationHoursMinutes", "{{h}} h {{m}} min", {
55668
+ h: hours,
55669
+ m: rest
55670
+ });
55671
+ }
55672
+ function useDishwasher(trpc, deviceId) {
55673
+ return useDeviceCapability({
55674
+ trpc,
55675
+ deviceId,
55676
+ cap: (d) => d.dishwasher,
55677
+ slice: (d) => d.state.dishwasher
55678
+ });
55679
+ }
55680
+ function DishwasherIconButton({ label, busy, active, onClick, children }) {
55681
+ return /* @__PURE__ */ jsx("button", {
55682
+ type: "button",
55683
+ "aria-label": label,
55684
+ title: label,
55685
+ disabled: busy,
55686
+ onClick: (e) => {
55687
+ e.stopPropagation();
55688
+ onClick();
55689
+ },
55690
+ className: cn("inline-flex h-5 w-5 items-center justify-center rounded text-foreground-subtle hover:text-foreground hover:bg-surface-hover transition-colors", active && "bg-primary text-primary-foreground", busy && "opacity-40 cursor-not-allowed"),
55691
+ children
55692
+ });
55693
+ }
55694
+ function DishwasherGraphic({ running, progressPercent }) {
55695
+ const pct = progressPercent != null ? Math.max(0, Math.min(100, progressPercent)) : running ? 40 : 0;
55696
+ return /* @__PURE__ */ jsxs("div", {
55697
+ "aria-hidden": "true",
55698
+ className: "relative w-28 h-36 rounded border-2 border-border bg-gradient-to-b from-surface-hover to-surface overflow-hidden flex-shrink-0",
55699
+ children: [/* @__PURE__ */ jsx("div", {
55700
+ className: cn("absolute inset-x-0 bottom-0 bg-primary/25 transition-[height] duration-500", running && "animate-pulse"),
55701
+ style: { height: `${pct}%` }
55702
+ }), /* @__PURE__ */ jsx("div", {
55703
+ className: "absolute inset-0 flex items-center justify-center text-foreground-subtle",
55704
+ children: /* @__PURE__ */ jsx(Waves, { className: "h-10 w-10 opacity-70" })
55705
+ })]
55706
+ });
55707
+ }
55708
+ function DishwasherPanel({ trpc, deviceId, layout }) {
55709
+ const t = useUiText();
55710
+ const { cap, slice, available } = useDishwasher(trpc, deviceId);
55711
+ if (cap === void 0) return null;
55712
+ if (slice === void 0) return null;
55713
+ const display = slice;
55714
+ const link = display.availability === "available";
55715
+ const busy = !available || !link;
55716
+ const optionTogglesLocked = display.childLock === true;
55717
+ const meta = dishwasherHeadline(display, t);
55718
+ const running = display.operationState === "Run";
55719
+ const paused = display.operationState === "Pause";
55720
+ const startable = display.remoteStartAllowed === true && display.selectedProgram !== null;
55721
+ const press = (fn) => {
55722
+ if (busy) return;
55723
+ fn();
55724
+ };
55725
+ if (layout === "compact") return /* @__PURE__ */ jsxs("div", {
55726
+ className: "inline-flex items-center gap-1.5 max-w-full",
55727
+ children: [
55728
+ display.doorOpen === true && /* @__PURE__ */ jsx("span", {
55729
+ className: "inline-flex text-warning shrink-0",
55730
+ title: t("uiLibrary.dishwasher.doorOpen", "Door open"),
55731
+ "aria-label": t("uiLibrary.dishwasher.doorOpen", "Door open"),
55732
+ children: /* @__PURE__ */ jsx(DoorOpen, { className: "h-3.5 w-3.5" })
55733
+ }),
55734
+ /* @__PURE__ */ jsx("span", {
55735
+ className: cn("text-xs font-medium tabular-nums shrink-0", meta.tone),
55736
+ children: meta.label
55737
+ }),
55738
+ display.program != null && /* @__PURE__ */ jsx("span", {
55739
+ className: "text-xs text-foreground-subtle truncate max-w-[7rem]",
55740
+ title: display.program,
55741
+ children: featureLabel(display.program)
55742
+ }),
55743
+ display.remaining != null && /* @__PURE__ */ jsxs("span", {
55744
+ className: "inline-flex items-center gap-0.5 text-xs text-foreground-subtle tabular-nums shrink-0",
55745
+ children: [/* @__PURE__ */ jsx(Timer, { className: "h-3 w-3" }), formatDuration(display.remaining, t)]
55746
+ }),
55747
+ /* @__PURE__ */ jsx(DishwasherIconButton, {
55748
+ label: t("uiLibrary.dishwasher.start", "Start"),
55749
+ busy: busy || !startable,
55750
+ active: running,
55751
+ onClick: () => press(() => cap.start({})),
55752
+ children: /* @__PURE__ */ jsx(Play, { className: "h-3 w-3" })
55753
+ }),
55754
+ /* @__PURE__ */ jsx(DishwasherIconButton, {
55755
+ label: paused ? t("uiLibrary.dishwasher.resume", "Resume") : t("uiLibrary.dishwasher.pause", "Pause"),
55756
+ busy: busy || !(running || paused),
55757
+ active: paused,
55758
+ onClick: () => press(() => paused ? cap.resume({}) : cap.pause({})),
55759
+ children: /* @__PURE__ */ jsx(Pause, { className: "h-3 w-3" })
55760
+ })
55761
+ ]
55762
+ });
55763
+ const programs = display.availablePrograms;
55764
+ return /* @__PURE__ */ jsxs("div", {
55765
+ className: "flex flex-col gap-3 rounded-lg border border-border bg-surface p-4",
55766
+ children: [
55767
+ /* @__PURE__ */ jsxs("div", {
55768
+ className: "flex items-start gap-4",
55769
+ children: [/* @__PURE__ */ jsx(DishwasherGraphic, {
55770
+ running,
55771
+ progressPercent: display.progress
55772
+ }), /* @__PURE__ */ jsxs("div", {
55773
+ className: "flex min-w-0 flex-1 flex-col gap-2",
55774
+ children: [
55775
+ /* @__PURE__ */ jsxs("div", {
55776
+ className: "flex flex-wrap items-center gap-2",
55777
+ children: [/* @__PURE__ */ jsx("span", {
55778
+ className: cn("text-3xl font-semibold", meta.tone),
55779
+ children: meta.label
55780
+ }), display.powerOn === false && /* @__PURE__ */ jsx("span", {
55781
+ className: "text-xs font-medium text-foreground-subtle",
55782
+ children: t("uiLibrary.dishwasher.powerOff", "Power off")
55783
+ })]
55784
+ }),
55785
+ display.program != null && /* @__PURE__ */ jsx("span", {
55786
+ className: "text-sm text-foreground-subtle",
55787
+ title: display.program,
55788
+ children: featureLabel(display.program)
55789
+ }),
55790
+ display.remaining != null && /* @__PURE__ */ jsxs("span", {
55791
+ className: "inline-flex items-center gap-1 text-sm text-foreground-subtle tabular-nums",
55792
+ children: [/* @__PURE__ */ jsx(Timer, { className: "h-3.5 w-3.5" }), t("uiLibrary.dishwasher.remaining", "{{time}} left", { time: formatDuration(display.remaining, t) })]
55793
+ }),
55794
+ display.delayedStart != null && display.delayedStart > 0 && /* @__PURE__ */ jsx("span", {
55795
+ className: "text-xs text-foreground-subtle tabular-nums",
55796
+ children: t("uiLibrary.dishwasher.startsIn", "Starts in {{time}}", { time: formatDuration(display.delayedStart, t) })
55797
+ }),
55798
+ display.progress != null && /* @__PURE__ */ jsxs("div", {
55799
+ className: "flex items-center gap-2",
55800
+ children: [/* @__PURE__ */ jsx("div", {
55801
+ className: "h-1.5 flex-1 rounded bg-surface-hover overflow-hidden",
55802
+ children: /* @__PURE__ */ jsx("div", {
55803
+ className: "h-full bg-primary transition-[width] duration-500",
55804
+ style: { width: `${Math.max(0, Math.min(100, display.progress))}%` }
55805
+ })
55806
+ }), /* @__PURE__ */ jsxs("span", {
55807
+ className: "tabular-nums text-xs text-foreground-subtle",
55808
+ children: [Math.round(display.progress), "%"]
55809
+ })]
55810
+ }),
55811
+ /* @__PURE__ */ jsxs("div", {
55812
+ className: "flex flex-wrap items-center gap-x-3 gap-y-1.5",
55813
+ children: [display.doorOpen === true && /* @__PURE__ */ jsxs("span", {
55814
+ className: "inline-flex items-center gap-1 text-xs text-warning",
55815
+ children: [/* @__PURE__ */ jsx(DoorOpen, { className: "h-3.5 w-3.5" }), t("uiLibrary.dishwasher.doorOpen", "Door open")]
55816
+ }), visibleDishwasherEvents(display.activeEvents).map((event) => /* @__PURE__ */ jsx("span", {
55817
+ className: "text-xs text-warning",
55818
+ title: event,
55819
+ children: featureLabel(event)
55820
+ }, event))]
55821
+ }),
55822
+ display.operationState === "Error" && /* @__PURE__ */ jsxs("div", {
55823
+ className: "inline-flex items-center gap-1 text-xs text-danger",
55824
+ children: [/* @__PURE__ */ jsx(TriangleAlert, { className: "h-3.5 w-3.5" }), /* @__PURE__ */ jsx("span", { children: display.errorLabel != null ? featureLabel(display.errorLabel) : display.errorCode != null ? t("uiLibrary.dishwasher.errorCode", "Error {{code}}", { code: display.errorCode }) : t("uiLibrary.dishwasher.op.error", "Error") })]
55825
+ }),
55826
+ /* @__PURE__ */ jsxs("div", {
55827
+ className: "flex flex-wrap items-center gap-2",
55828
+ children: [
55829
+ /* @__PURE__ */ jsx(DishwasherIconButton, {
55830
+ label: t("uiLibrary.dishwasher.start", "Start"),
55831
+ busy: busy || !startable,
55832
+ active: running,
55833
+ onClick: () => press(() => cap.start({})),
55834
+ children: /* @__PURE__ */ jsx(Play, { className: "h-4 w-4" })
55835
+ }),
55836
+ /* @__PURE__ */ jsx(DishwasherIconButton, {
55837
+ label: paused ? t("uiLibrary.dishwasher.resume", "Resume") : t("uiLibrary.dishwasher.pause", "Pause"),
55838
+ busy: busy || !(running || paused),
55839
+ active: paused,
55840
+ onClick: () => press(() => paused ? cap.resume({}) : cap.pause({})),
55841
+ children: /* @__PURE__ */ jsx(Pause, { className: "h-4 w-4" })
55842
+ }),
55843
+ /* @__PURE__ */ jsx(DishwasherIconButton, {
55844
+ label: t("uiLibrary.dishwasher.stop", "Stop"),
55845
+ busy: busy || !(running || paused),
55846
+ active: false,
55847
+ onClick: () => press(() => cap.stop({})),
55848
+ children: /* @__PURE__ */ jsx(Square, { className: "h-3.5 w-3.5" })
55849
+ }),
55850
+ /* @__PURE__ */ jsx(DishwasherIconButton, {
55851
+ label: t("uiLibrary.dishwasher.power", "Power"),
55852
+ busy: busy || display.powerOn === null,
55853
+ active: display.powerOn === true,
55854
+ onClick: () => {
55855
+ const next = display.powerOn !== true;
55856
+ press(() => cap.setPower({ on: next }));
55857
+ },
55858
+ children: /* @__PURE__ */ jsx(Power, { className: "h-4 w-4" })
55859
+ })
55860
+ ]
55861
+ })
55862
+ ]
55863
+ })]
55864
+ }),
55865
+ programs.length > 0 && /* @__PURE__ */ jsxs("label", {
55866
+ className: "flex items-center gap-2 text-xs text-foreground-subtle",
55867
+ children: [/* @__PURE__ */ jsx("span", {
55868
+ className: "w-16 shrink-0",
55869
+ children: t("uiLibrary.dishwasher.program", "Program")
55870
+ }), /* @__PURE__ */ jsxs("select", {
55871
+ "aria-label": t("uiLibrary.dishwasher.program", "Program"),
55872
+ value: display.selectedProgram ?? "",
55873
+ disabled: busy,
55874
+ onChange: (e) => {
55875
+ const program = e.target.value;
55876
+ if (!program) return;
55877
+ cap.setProgram({ program });
55878
+ },
55879
+ onClick: (e) => {
55880
+ e.stopPropagation();
55881
+ },
55882
+ className: "flex-1 rounded border border-border bg-surface px-2 py-1 text-foreground disabled:opacity-50",
55883
+ children: [display.selectedProgram == null && /* @__PURE__ */ jsx("option", {
55884
+ value: "",
55885
+ children: "—"
55886
+ }), programs.map((p) => /* @__PURE__ */ jsx("option", {
55887
+ value: p,
55888
+ children: featureLabel(p)
55889
+ }, p))]
55890
+ })]
55891
+ }),
55892
+ /* @__PURE__ */ jsxs("div", {
55893
+ className: "flex flex-wrap gap-4 text-xs",
55894
+ children: [
55895
+ /* @__PURE__ */ jsx(ToggleRow, {
55896
+ label: t("uiLibrary.dishwasher.halfLoad", "Half load"),
55897
+ checked: display.halfLoad,
55898
+ shown: link,
55899
+ busy: busy || optionTogglesLocked,
55900
+ onChange: (on) => void cap.setHalfLoad({ on })
55901
+ }),
55902
+ /* @__PURE__ */ jsx(ToggleRow, {
55903
+ label: t("uiLibrary.dishwasher.hygienePlus", "Hygiene plus"),
55904
+ checked: display.hygienePlus,
55905
+ shown: link,
55906
+ busy: busy || optionTogglesLocked,
55907
+ onChange: (on) => void cap.setHygienePlus({ on })
55908
+ }),
55909
+ /* @__PURE__ */ jsx(ToggleRow, {
55910
+ label: t("uiLibrary.dishwasher.extraDry", "Extra dry"),
55911
+ checked: display.extraDry,
55912
+ shown: link,
55913
+ busy: busy || optionTogglesLocked,
55914
+ onChange: (on) => void cap.setExtraDry({ on })
55915
+ }),
55916
+ /* @__PURE__ */ jsx(ToggleRow, {
55917
+ label: t("uiLibrary.dishwasher.intensiveZone", "Intensive zone"),
55918
+ checked: display.intensiveZone,
55919
+ shown: link,
55920
+ busy: busy || optionTogglesLocked,
55921
+ onChange: (on) => void cap.setIntensiveZone({ on })
55922
+ }),
55923
+ /* @__PURE__ */ jsx(ToggleRow, {
55924
+ label: t("uiLibrary.dishwasher.varioSpeedPlus", "VarioSpeed+"),
55925
+ checked: display.varioSpeedPlus,
55926
+ shown: link,
55927
+ busy: busy || optionTogglesLocked,
55928
+ onChange: (on) => void cap.setVarioSpeedPlus({ on })
55482
55929
  }),
55483
- display.availablePresets.length > 0 && /* @__PURE__ */ jsx(CompactSelect, {
55484
- label: t("uiLibrary.acPanel.preset", "Preset"),
55485
- icon: /* @__PURE__ */ jsx(CurrentPresetIcon, { className: "h-4 w-4 text-emerald-500" }),
55486
- value: display.preset,
55487
- options: display.availablePresets.map((p) => ({
55488
- value: p,
55489
- label: fanLabel(p)
55490
- })),
55491
- disabled: busy,
55492
- onChange: (v) => {
55493
- applyOptimistic({ preset: v });
55494
- cap.setPreset({ preset: v });
55495
- }
55930
+ /* @__PURE__ */ jsx(ToggleRow, {
55931
+ label: t("uiLibrary.dishwasher.childLock", "Child lock"),
55932
+ checked: display.childLock,
55933
+ shown: link,
55934
+ busy,
55935
+ onChange: (on) => void cap.setChildLock({ on })
55496
55936
  })
55497
55937
  ]
55498
- }),
55499
- (showVSwing || showHSwing) && /* @__PURE__ */ jsx(Field, {
55500
- label: t("uiLibrary.acPanel.swing", "Swing"),
55501
- children: /* @__PURE__ */ jsxs("div", {
55502
- className: "grid grid-cols-2 gap-1",
55503
- children: [showVSwing && /* @__PURE__ */ jsx(SwingToggle, {
55504
- axis: "vertical",
55505
- on: display.swingVertical ?? false,
55506
- busy,
55507
- onToggle: (next) => {
55508
- applyOptimistic({ swingVertical: next });
55509
- cap.setSwingVertical({ on: next });
55510
- }
55511
- }), showHSwing && /* @__PURE__ */ jsx(SwingToggle, {
55512
- axis: "horizontal",
55513
- on: display.swingHorizontal ?? false,
55514
- busy,
55515
- onToggle: (next) => {
55516
- applyOptimistic({ swingHorizontal: next });
55517
- cap.setSwingHorizontal({ on: next });
55518
- }
55519
- })]
55520
- })
55521
55938
  })
55522
55939
  ]
55523
55940
  });
55524
55941
  }
55525
- /** Labelled control group — a small uppercase header above its control. */
55526
- function Field({ label, children }) {
55527
- return /* @__PURE__ */ jsxs("div", {
55528
- className: "relative z-10 flex flex-col gap-1",
55529
- children: [/* @__PURE__ */ jsx("span", {
55530
- className: "text-[10px] font-semibold uppercase tracking-wider text-foreground-subtle",
55531
- children: label
55532
- }), children]
55942
+ /**
55943
+ * One boolean setting. `checked === null` is "the appliance has not said": on a reachable
55944
+ * appliance that means it does not offer the setting (hidden); on an unreachable one the
55945
+ * setting is shown but disabled and marked unknown — never as an unchecked box.
55946
+ */
55947
+ function ToggleRow({ label, checked, shown, busy, onChange }) {
55948
+ const t = useUiText();
55949
+ if (checked === null && shown) return null;
55950
+ return /* @__PURE__ */ jsxs("label", {
55951
+ className: "inline-flex items-center gap-2 cursor-pointer",
55952
+ children: [
55953
+ /* @__PURE__ */ jsx("input", {
55954
+ type: "checkbox",
55955
+ checked: checked === true,
55956
+ "aria-checked": checked === null ? "mixed" : checked,
55957
+ disabled: busy || checked === null,
55958
+ onChange: (e) => {
55959
+ onChange(e.target.checked);
55960
+ },
55961
+ onClick: (e) => {
55962
+ e.stopPropagation();
55963
+ },
55964
+ className: "rounded border-border"
55965
+ }),
55966
+ /* @__PURE__ */ jsx("span", { children: label }),
55967
+ checked === null && /* @__PURE__ */ jsx("span", {
55968
+ className: "text-foreground-subtle",
55969
+ children: t("uiLibrary.dishwasher.unknownValue", "—")
55970
+ })
55971
+ ]
55533
55972
  });
55534
55973
  }
55535
- function ModeIcon({ mode, heatingOnly = false, className }) {
55536
- return /* @__PURE__ */ jsx(heatingOnly && mode === "heat" ? Heater : MODE_ICON[mode], {
55537
- className,
55538
- "aria-hidden": true
55974
+ function DishwasherInlineControl(props) {
55975
+ return /* @__PURE__ */ jsx(DishwasherPanel, {
55976
+ ...props,
55977
+ layout: "compact"
55539
55978
  });
55540
55979
  }
55541
- /** Compact labelled dropdown — a leading icon + native `<select>` + chevron,
55542
- * used for the Mode / Fan / Preset selectors so all three fit in one row. */
55543
- function CompactSelect({ label, icon, value, options, disabled, onChange }) {
55544
- return /* @__PURE__ */ jsxs("div", {
55545
- className: "flex min-w-0 flex-col gap-1",
55546
- children: [/* @__PURE__ */ jsx("span", {
55547
- className: "text-[10px] font-semibold uppercase tracking-wider text-foreground-subtle",
55548
- children: label
55549
- }), /* @__PURE__ */ jsxs("div", {
55550
- className: cn("flex items-center gap-1 overflow-hidden rounded-lg border border-border/60 bg-surface-subtle px-1.5 py-1.5 has-[:focus-visible]:border-primary", disabled && "opacity-40"),
55551
- children: [
55552
- /* @__PURE__ */ jsx("span", {
55553
- className: "flex shrink-0",
55554
- children: icon
55555
- }),
55556
- /* @__PURE__ */ jsx("select", {
55557
- "aria-label": label,
55558
- value,
55559
- disabled,
55560
- onChange: (e) => {
55561
- e.stopPropagation();
55562
- if (!disabled) onChange(e.target.value);
55563
- },
55564
- className: "min-w-0 flex-1 cursor-pointer appearance-none truncate bg-transparent text-xs font-medium text-foreground outline-none",
55565
- children: options.map((o) => /* @__PURE__ */ jsx("option", {
55566
- value: o.value,
55567
- children: o.label
55568
- }, o.value))
55569
- }),
55570
- /* @__PURE__ */ jsx(ChevronDown, { className: "h-3 w-3 shrink-0 text-foreground-subtle" })
55571
- ]
55572
- })]
55980
+ function DishwasherHeroCard(props) {
55981
+ return /* @__PURE__ */ jsx(DishwasherPanel, {
55982
+ ...props,
55983
+ layout: "full"
55573
55984
  });
55574
55985
  }
55575
- /** Circular ± button for the target. */
55576
- function RoundStep({ label, symbol, disabled, onClick }) {
55577
- return /* @__PURE__ */ jsx("button", {
55578
- type: "button",
55579
- "aria-label": label,
55580
- disabled,
55581
- onClick,
55582
- className: cn("flex h-8 w-8 shrink-0 items-center justify-center rounded-full border border-border bg-surface text-lg leading-none text-foreground-subtle transition-colors hover:bg-surface-hover hover:text-foreground active:scale-95", disabled && "opacity-40 cursor-not-allowed"),
55583
- children: symbol
55584
- });
55986
+ //#endregion
55987
+ //#region src/composites/device-controls/appliance-control.tsx
55988
+ /**
55989
+ * Appliance card for a `DeviceType.Washer` / `DeviceType.Dryer` device.
55990
+ *
55991
+ * These appliances have no program surface: what is worth showing is whether
55992
+ * the cycle is running (the `running-state` cap), for how long, and what the
55993
+ * appliance draws right now (the `power-meter` cap). Both slices are read
55994
+ * straight from the device; neither is required.
55995
+ * - ApplianceInlineControl (device-list row): the running badge round the
55996
+ * drum icon, plus the live watts when there are any.
55997
+ * - ApplianceHeroCard (device-detail hero): the drum (turning only while a
55998
+ * cycle runs), the state, the phase, the dwell and the power.
55999
+ *
56000
+ * UNKNOWN IS NOT OFF (D393). `running: null` is drawn as "Unknown" and the
56001
+ * drum stays still and unbadged; a missing watt reading is a dash, never
56002
+ * "0 W". A slice that has not landed hides its row instead of faking a value.
56003
+ */
56004
+ var KEYFRAMES = `
56005
+ @keyframes apl-tumble { to { transform: rotate(360deg) } }
56006
+ .apl-drum-run { animation: apl-tumble 3s linear infinite; }
56007
+ @media (prefers-reduced-motion: reduce) {
56008
+ .apl-drum-run { animation: none !important; }
55585
56009
  }
55586
- /** Setpoint track. Drag previews; the command is sent when the pointer is released. */
55587
- function RangeTrack({ value, min, max, step, accent, disabled, label, onPreview, onCommit }) {
55588
- const trackRef = useRef(null);
55589
- const draggingRef = useRef(false);
55590
- const [draft, setDraft] = useState(null);
55591
- const shown = draft ?? value;
55592
- const pct = `${Math.min(1, Math.max(0, (shown - min) / (max - min))) * 100}%`;
55593
- const tempAt = (clientX) => {
55594
- const el = trackRef.current;
55595
- if (el === null) return value;
55596
- const rect = el.getBoundingClientRect();
55597
- if (rect.width <= 0) return value;
55598
- return climateTargetFromFraction((clientX - rect.left) / rect.width, {
55599
- min,
55600
- max
55601
- }, step);
55602
- };
55603
- const onPointerDown = (event) => {
55604
- if (disabled) return;
55605
- event.stopPropagation();
55606
- event.preventDefault();
55607
- draggingRef.current = true;
55608
- if (typeof event.currentTarget.setPointerCapture === "function") event.currentTarget.setPointerCapture(event.pointerId);
55609
- const next = tempAt(event.clientX);
55610
- setDraft(next);
55611
- onPreview(next);
56010
+ `;
56011
+ /** Whole watts, or a dash when the appliance has not reported a reading. */
56012
+ function formatWatts(power) {
56013
+ return power === void 0 || !Number.isFinite(power) ? "—" : `${Math.round(power)} W`;
56014
+ }
56015
+ /** The state to a person: running / idle, or why there is none (unknown). */
56016
+ function applianceStateLabel(running, t) {
56017
+ if (running === true) return {
56018
+ label: t("uiLibrary.appliance.running", "Running"),
56019
+ tone: "text-primary"
55612
56020
  };
55613
- const onPointerMove = (event) => {
55614
- if (disabled || !draggingRef.current) return;
55615
- event.stopPropagation();
55616
- const next = tempAt(event.clientX);
55617
- setDraft(next);
55618
- onPreview(next);
56021
+ if (running === false) return {
56022
+ label: t("uiLibrary.appliance.idle", "Idle"),
56023
+ tone: "text-foreground"
55619
56024
  };
55620
- const endDrag = (event) => {
55621
- if (!draggingRef.current) return;
55622
- event.stopPropagation();
55623
- draggingRef.current = false;
55624
- const next = tempAt(event.clientX);
55625
- setDraft(null);
55626
- if (event.currentTarget.hasPointerCapture?.(event.pointerId) === true) event.currentTarget.releasePointerCapture(event.pointerId);
55627
- onCommit(next);
56025
+ return {
56026
+ label: t("uiLibrary.appliance.unknown", "Unknown"),
56027
+ tone: "text-foreground-subtle"
55628
56028
  };
55629
- const onKeyDown = (event) => {
55630
- if (disabled) return;
55631
- const current = draft ?? value;
55632
- if (event.key === "ArrowRight" || event.key === "ArrowUp") {
55633
- event.preventDefault();
55634
- onCommit(nextClimateTarget(current, 1, {
55635
- tempStep: step,
55636
- minTemp: min,
55637
- maxTemp: max
55638
- }));
55639
- } else if (event.key === "ArrowLeft" || event.key === "ArrowDown") {
55640
- event.preventDefault();
55641
- onCommit(nextClimateTarget(current, -1, {
55642
- tempStep: step,
55643
- minTemp: min,
55644
- maxTemp: max
55645
- }));
55646
- } else if (event.key === "Home") {
55647
- event.preventDefault();
55648
- onCommit(min);
55649
- } else if (event.key === "End") {
55650
- event.preventDefault();
55651
- onCommit(max);
55652
- }
56029
+ }
56030
+ function dwellText(running, since, now, t) {
56031
+ if (running !== true) return null;
56032
+ const { duration } = runningStatusParts(running, since, null, now);
56033
+ if (duration === void 0) return null;
56034
+ return "minutes" in duration ? t("uiLibrary.appliance.forMinutes", "for {{count}} min", { count: duration.minutes }) : t("uiLibrary.appliance.forHours", "for {{count}} h", { count: duration.hours });
56035
+ }
56036
+ function useApplianceState(props) {
56037
+ return {
56038
+ running: useDeviceState(props.trpc, props.deviceId, (s) => s.runningState),
56039
+ power: useDeviceState(props.trpc, props.deviceId, (s) => s.powerMeter)
55653
56040
  };
55654
- return /* @__PURE__ */ jsxs("div", {
55655
- ref: trackRef,
55656
- role: "slider",
55657
- "aria-label": label,
55658
- "aria-valuemin": min,
55659
- "aria-valuemax": max,
55660
- "aria-valuenow": shown,
55661
- "aria-disabled": disabled,
55662
- tabIndex: disabled ? -1 : 0,
55663
- onPointerDown,
55664
- onPointerMove,
55665
- onPointerUp: endDrag,
55666
- onPointerCancel: endDrag,
55667
- onKeyDown,
55668
- className: cn("mt-1 w-full touch-none select-none py-2", disabled ? "cursor-not-allowed opacity-40" : "cursor-ew-resize"),
55669
- children: [/* @__PURE__ */ jsxs("div", {
55670
- className: "relative h-1.5 w-full rounded-full bg-surface-subtle",
55671
- children: [/* @__PURE__ */ jsx("div", {
55672
- className: "absolute inset-y-0 left-0 rounded-full",
55673
- style: {
55674
- width: pct,
55675
- background: accent
55676
- }
55677
- }), /* @__PURE__ */ jsx("div", {
55678
- className: "absolute top-1/2 h-3.5 w-3.5 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-surface shadow",
55679
- style: {
55680
- left: pct,
55681
- background: accent
55682
- }
55683
- })]
55684
- }), /* @__PURE__ */ jsxs("div", {
55685
- className: "mt-0.5 flex justify-between text-[9px] tabular-nums text-foreground-subtle",
55686
- children: [/* @__PURE__ */ jsxs("span", { children: [min, "°"] }), /* @__PURE__ */ jsxs("span", { children: [max, "°"] })]
55687
- })]
55688
- });
55689
56041
  }
55690
- /**
55691
- * Animated centerpiece. `fan_only` renders a spinning fan; `off` a dim static
55692
- * vent; every active mode renders drifting particles that FALL (cool/dry/auto)
55693
- * or RISE (heat), with a horizontal sweep overlaid when a swing axis is active.
55694
- */
55695
- function AirflowViz({ mode, accent, periodSec, swaying, forceRising = false }) {
55696
- const columns = [
55697
- 0,
55698
- 1,
55699
- 2,
55700
- 3,
55701
- 4,
55702
- 5
55703
- ];
55704
- const rising = forceRising || mode === "heat";
55705
- const isDroplet = mode === "dry";
56042
+ /** The drum: a ring with a few items in it, turning only while a cycle runs. */
56043
+ function Drum({ running }) {
55706
56044
  return /* @__PURE__ */ jsx("div", {
55707
- "aria-hidden": true,
55708
- className: "absolute inset-0 overflow-hidden",
55709
- children: mode === "off" ? /* @__PURE__ */ jsx("div", {
55710
- className: "flex h-full items-center justify-center gap-2 opacity-30",
55711
- children: columns.map((i) => /* @__PURE__ */ jsx("span", { className: "h-8 w-1 rounded-full bg-foreground-subtle opacity-40" }, i))
55712
- }) : mode === "fan_only" ? /* @__PURE__ */ jsx("div", {
55713
- className: "flex h-full items-center justify-center",
55714
- children: /* @__PURE__ */ jsx(FanBlades, {
55715
- color: accent,
55716
- periodSec: Math.max(.5, periodSec * .7),
55717
- size: 56
55718
- })
55719
- }) : /* @__PURE__ */ jsx("div", {
55720
- "data-testid": forceRising ? "climate-heat-rise" : void 0,
55721
- className: cn("acv-sway-wrap absolute inset-0", swaying && "acv-sway"),
55722
- style: swaying ? { animation: "acv-sway 2.6s ease-in-out infinite" } : void 0,
55723
- children: columns.map((i) => {
55724
- return /* @__PURE__ */ jsx("span", {
55725
- className: "acv-streak absolute rounded-full",
55726
- style: {
55727
- left: `${8 + i * 15}%`,
55728
- width: isDroplet ? "0.4rem" : "0.3rem",
55729
- height: isDroplet ? "0.4rem" : "1.9rem",
55730
- background: accent,
55731
- boxShadow: `0 0 6px ${accent}`,
55732
- animationName: rising ? "acv-rise" : "acv-fall",
55733
- animationTimingFunction: "linear",
55734
- animationIterationCount: "infinite",
55735
- animationDuration: `${periodSec}s`,
55736
- animationDelay: `${i % 3 * (periodSec / 3) + i * .05}s`
55737
- }
55738
- }, i);
55739
- })
56045
+ "aria-hidden": "true",
56046
+ "data-testid": "appliance-drum",
56047
+ "data-running": running === true ? "running" : running === false ? "idle" : "unknown",
56048
+ className: "relative flex h-28 w-28 shrink-0 items-center justify-center rounded-full border-2 border-border bg-surface-hover",
56049
+ children: /* @__PURE__ */ jsxs("div", {
56050
+ className: cn("relative h-20 w-20 rounded-full border-2", running === true ? "apl-drum-run border-primary" : "border-border"),
56051
+ "data-testid": "appliance-drum-ring",
56052
+ children: [
56053
+ /* @__PURE__ */ jsx("span", { className: "absolute left-2 top-4 h-3 w-3 rounded-full bg-primary/40" }),
56054
+ /* @__PURE__ */ jsx("span", { className: "absolute bottom-3 right-3 h-4 w-4 rounded-full bg-info/40" }),
56055
+ /* @__PURE__ */ jsx("span", { className: "absolute bottom-4 left-4 h-2.5 w-2.5 rounded-full bg-foreground-subtle/40" })
56056
+ ]
55740
56057
  })
55741
56058
  });
55742
56059
  }
55743
- /** Still radiator fins — the off state of a heating-only climate. */
55744
- function RadiatorFins() {
55745
- return /* @__PURE__ */ jsx("div", {
55746
- "data-testid": "climate-radiator",
55747
- "aria-hidden": true,
55748
- className: "flex h-full items-end justify-center gap-1.5 px-8 pb-3 opacity-40",
56060
+ function ApplianceHeroCard(props) {
56061
+ const t = useUiText();
56062
+ const { running, power } = useApplianceState(props);
56063
+ const state = running?.running ?? null;
56064
+ const meta = applianceStateLabel(state, t);
56065
+ const phase = running?.phase?.trim() ?? "";
56066
+ const dwell = running === void 0 ? null : dwellText(state, running.since, Date.now(), t);
56067
+ return /* @__PURE__ */ jsxs("div", {
56068
+ className: "flex items-center gap-4 rounded-lg border border-border bg-surface p-4",
55749
56069
  children: [
55750
- 0,
55751
- 1,
55752
- 2,
55753
- 3,
55754
- 4,
55755
- 5,
55756
- 6
55757
- ].map((i) => /* @__PURE__ */ jsx("span", { className: "h-10 w-1.5 rounded-t-full bg-foreground-subtle" }, i))
56070
+ /* @__PURE__ */ jsx("style", { children: KEYFRAMES }),
56071
+ /* @__PURE__ */ jsx(Drum, { running: state }),
56072
+ /* @__PURE__ */ jsxs("div", {
56073
+ className: "flex min-w-0 flex-1 flex-col gap-2",
56074
+ children: [
56075
+ /* @__PURE__ */ jsxs("div", {
56076
+ className: "flex flex-wrap items-baseline gap-x-2",
56077
+ children: [/* @__PURE__ */ jsx("span", {
56078
+ "data-testid": "appliance-state",
56079
+ className: cn("text-3xl font-semibold", meta.tone),
56080
+ children: meta.label
56081
+ }), dwell !== null && /* @__PURE__ */ jsx("span", {
56082
+ className: "text-sm tabular-nums text-foreground-subtle",
56083
+ children: dwell
56084
+ })]
56085
+ }),
56086
+ phase !== "" && state !== null && /* @__PURE__ */ jsx("span", {
56087
+ className: "text-sm text-foreground-subtle",
56088
+ children: phase
56089
+ }),
56090
+ power !== void 0 && /* @__PURE__ */ jsxs("span", {
56091
+ "data-testid": "appliance-power",
56092
+ className: "inline-flex items-center gap-1 text-sm tabular-nums text-foreground-muted",
56093
+ title: power.power === void 0 ? t("uiLibrary.appliance.powerUnknown", "Power unknown") : void 0,
56094
+ children: [/* @__PURE__ */ jsx(Zap, {
56095
+ className: "h-3.5 w-3.5",
56096
+ "aria-hidden": true
56097
+ }), formatWatts(power.power)]
56098
+ })
56099
+ ]
56100
+ })
56101
+ ]
55758
56102
  });
55759
56103
  }
55760
- /** Big spinning fan for `fan_only` mode. */
55761
- function FanBlades({ color, periodSec, size }) {
55762
- return /* @__PURE__ */ jsxs("svg", {
55763
- width: size,
55764
- height: size,
55765
- viewBox: "0 0 100 100",
55766
- className: "acv-fan",
55767
- style: {
55768
- animation: `acv-spin ${periodSec}s linear infinite`,
55769
- transformOrigin: "50% 50%"
55770
- },
55771
- "aria-hidden": true,
55772
- children: [[
55773
- 0,
55774
- 120,
55775
- 240
55776
- ].map((deg) => /* @__PURE__ */ jsx("path", {
55777
- d: "M50 50 C 58 30, 78 26, 84 12 C 66 20, 54 34, 50 50 Z",
55778
- fill: color,
55779
- opacity: .85,
55780
- transform: `rotate(${deg} 50 50)`
55781
- }, deg)), /* @__PURE__ */ jsx("circle", {
55782
- cx: "50",
55783
- cy: "50",
55784
- r: "7",
55785
- fill: color
56104
+ function ApplianceInlineControl(props) {
56105
+ const { running, power } = useApplianceState(props);
56106
+ return /* @__PURE__ */ jsxs("div", {
56107
+ className: "inline-flex items-center gap-1.5 max-w-full",
56108
+ children: [/* @__PURE__ */ jsx(RunningBadge, {
56109
+ running: running?.running ?? null,
56110
+ children: /* @__PURE__ */ jsx(WashingMachine, {
56111
+ className: "h-4 w-4 text-foreground-muted",
56112
+ "aria-hidden": true
56113
+ })
56114
+ }), power !== void 0 && /* @__PURE__ */ jsx("span", {
56115
+ className: "text-xs tabular-nums text-foreground-subtle",
56116
+ children: formatWatts(power.power)
55786
56117
  })]
55787
56118
  });
55788
56119
  }
55789
- /** Swing axis toggle — a card with a MoveVertical/Horizontal glyph that
55790
- * oscillates along its axis when on. On/off is non-destructive → plain tap. */
55791
- function SwingToggle({ axis, on, busy, onToggle }) {
56120
+ //#endregion
56121
+ //#region src/composites/device-controls/heating-valve-readout.tsx
56122
+ function formatHeatingValvePosition(position) {
56123
+ return position !== null ? `${position}%` : "—";
56124
+ }
56125
+ function HeatingValveReadout({ trpc, deviceId, layout }) {
55792
56126
  const t = useUiText();
55793
- const label = axis === "vertical" ? t("uiLibrary.acPanel.vertical", "Vertical") : t("uiLibrary.acPanel.horizontal", "Horizontal");
55794
- const Icon = axis === "vertical" ? MoveVertical : MoveHorizontal;
55795
- const anim = axis === "vertical" ? "acv-swing-v" : "acv-swing-h";
55796
- return /* @__PURE__ */ jsxs("button", {
55797
- type: "button",
55798
- "aria-label": t("uiLibrary.acPanel.swingAxis", "{{axis}} swing", { axis: label }),
55799
- "aria-pressed": on,
55800
- disabled: busy,
55801
- onClick: () => {
55802
- if (!busy) onToggle(!on);
55803
- },
55804
- className: cn("flex items-center justify-center gap-2 rounded-lg border px-2 py-1.5 text-xs font-medium transition-colors", on ? "border-transparent bg-indigo-400 text-indigo-950 shadow-sm" : "border-border/60 bg-surface-subtle text-foreground-subtle hover:bg-surface-hover hover:text-foreground", busy && "opacity-40 cursor-not-allowed"),
55805
- children: [/* @__PURE__ */ jsx(Icon, {
55806
- className: "acv-swing h-4 w-4",
55807
- "aria-hidden": true,
55808
- style: on ? { animation: `${anim} 1.4s ease-in-out infinite` } : void 0
55809
- }), label]
56127
+ const { cap, slice } = useDeviceCapability({
56128
+ trpc,
56129
+ deviceId,
56130
+ cap: (d) => d.heatingValve,
56131
+ slice: (d) => d.state.heatingValve
56132
+ });
56133
+ if (cap === void 0 || slice === void 0) return null;
56134
+ const label = t("uiLibrary.heatingValveReadout.valve", "Valve");
56135
+ const value = formatHeatingValvePosition(slice.position);
56136
+ if (layout === "compact") return /* @__PURE__ */ jsx("span", {
56137
+ className: "inline-flex items-center text-xs tabular-nums text-foreground-subtle",
56138
+ "aria-label": `${label} ${value}`,
56139
+ children: value
56140
+ });
56141
+ return /* @__PURE__ */ jsxs("div", {
56142
+ className: "flex items-center gap-2 text-xs tabular-nums text-foreground-subtle",
56143
+ children: [/* @__PURE__ */ jsx("span", { children: label }), /* @__PURE__ */ jsx("span", {
56144
+ className: "font-medium text-foreground",
56145
+ children: value
56146
+ })]
55810
56147
  });
55811
56148
  }
55812
56149
  //#endregion
@@ -57898,6 +58235,10 @@ var CONTROL_KIND_COMPONENTS = {
57898
58235
  InlineControl: PetFountainInlineControl,
57899
58236
  HeroCard: PetFountainHeroCard
57900
58237
  },
58238
+ heater: {
58239
+ InlineControl: HeaterInlineControl,
58240
+ HeroCard: HeaterHeroCard
58241
+ },
57901
58242
  dishwasher: {
57902
58243
  InlineControl: DishwasherInlineControl,
57903
58244
  HeroCard: DishwasherHeroCard
@@ -57985,6 +58326,7 @@ var CONTROL_FILLS = {
57985
58326
  [DeviceType.Image]: false,
57986
58327
  [DeviceType.PetFeeder]: false,
57987
58328
  [DeviceType.PetFountain]: false,
58329
+ [DeviceType.Heater]: false,
57988
58330
  [DeviceType.Dishwasher]: false,
57989
58331
  [DeviceType.Washer]: false,
57990
58332
  [DeviceType.Dryer]: false
@@ -73399,12 +73741,12 @@ var statusIcons = {
73399
73741
  * Render inside `<Suspense>` at all call sites. */
73400
73742
  var MaskShapeCanvas = lazy(() => import("./MaskShapeCanvas-C9cJlxvG.js").then((m) => ({ default: m.MaskShapeCanvas })));
73401
73743
  /** Lazy-wrapped `MotionZonesSettings` — code-split off the main bundle. */
73402
- var MotionZonesSettings = lazy(() => import("./MotionZonesSettings-dx3wObgK.js").then((m) => ({ default: m.MotionZonesSettings })));
73744
+ var MotionZonesSettings = lazy(() => import("./MotionZonesSettings-Zcfa5c9l.js").then((m) => ({ default: m.MotionZonesSettings })));
73403
73745
  /** Lazy-wrapped `SceneMonitorEditor` — code-split off the main bundle for the
73404
73746
  * same reason: it mounts `MaskShapeCanvas`, which chains react-konva. Render
73405
73747
  * inside `<Suspense>`; the admin-ui `/scenes` dialog is its only caller. */
73406
- var SceneMonitorEditor = lazy(() => import("./SceneMonitorEditor-CI72S4eN.js").then((m) => ({ default: m.SceneMonitorEditor })));
73748
+ var SceneMonitorEditor = lazy(() => import("./SceneMonitorEditor-C8YXVzYI.js").then((m) => ({ default: m.SceneMonitorEditor })));
73407
73749
  /** Lazy-wrapped `PrivacyMaskSettings` — code-split off the main bundle. */
73408
- var PrivacyMaskSettings = lazy(() => import("./PrivacyMaskSettings-BM2C_xWz.js").then((m) => ({ default: m.PrivacyMaskSettings })));
73750
+ var PrivacyMaskSettings = lazy(() => import("./PrivacyMaskSettings-B_X42yzN.js").then((m) => ({ default: m.PrivacyMaskSettings })));
73409
73751
  //#endregion
73410
- export { Shield as $, CloudRain as $n, LockOpen as $t, Trash2 as A, AddProviderEntryDialog, AddonGlobalSettingsForm, AdminLinkQuickAction, AgentStepEditor, AlarmHeroCard, AlarmInlineControl as AlarmPanelInlineControl, Flame as An, AppShell, Bone as Ar, ArcKnob, Pencil as At, AudioClassificationList, AudioLevelWaveform, AudioWaveform, AutomationHeroCard, AutomationInlineControl, AutotrackSection, Sun as B, BATTERY_BADGE_LOW_KEY, BATTERY_BADGE_NORMAL_KEY, BINARY_BATTERY_LOW_BELOW, BOOLEAN_STATES, BTN_COMPACT, BTN_COMPACT_DANGER, BTN_COMPACT_PRIMARY, BTN_COMPACT_WARNING, BackToStepsButton, Badge, BarSeries, BatteryBadge, Droplet as Bn, BottomSheet, BatteryFull as Br, Breadcrumb, BrightnessPanel, BrokerPickerSlotProvider, MousePointerClick as Bt, Button, ButtonControl, ButtonHeroCard, Unlink2 as C, CENTER, CHART_SERIES_TOKENS, CHIP_ACTIVE, CHIP_BASE, CHIP_INACTIVE, CLASS_COLORS, COLUMN_BREAKPOINT_CLASS, COLUMN_PRIORITY, COMMIT_DEDUPE_TOLERANCE_MS, COMMIT_DEDUPE_WINDOW_MS, CONSUMABLE_LOW_PERCENT, CONTROL_CAP_NAMES, CONTROL_FILLS, CameraStreamPlayer, Card, ChartFrame, ChartPlaceholder, ChartSwatch, ChartWindowToggle, Checkbox, ChildSectionAccordion, ClimatePanel, GraduationCap as Cn, CodeBlock, CollapsibleCard, ConfigFormBuilder, FormField as ConfigFormField, ConfigNotificationTargetMultiSelectFieldView, ConfigNotificationTargetSelectFieldView, ConfigSchemaField, ConfirmActionButton, ConfirmDialogProvider, ConsumableLevelBadge, ConsumablesPanel, ContainerChildrenProvider, ContainerPrimaryHero, ControlColumn, ControlHeroCard, ControlInlineControl, ControlPanel, CopyButton, CoverHeroCard, CoverInlineControl, CoverPanel, Car as Cr, Plug as Ct, CustomFieldRenderersProvider, TriangleAlert as D, DATA_RECORDS_KIND_PARAM, DATA_RECORDS_OWNER_PARAM, DATA_RECORD_FACET_GROUPS, DEFAULT_COLOR, DEFAULT_PAGINATION_LABELS, DEFAULT_UNIT_PREFERENCES, DEVICE_COLUMNS, DEVICE_EXPORT_PAGE_SIZE_KEY, DEVICE_LIST_PAGE_SIZE_KEY, DEVICE_LIST_PAGE_SIZE_OPTIONS, DEVICE_NAME_FORMS, DEVICE_NAME_JOIN, DEVICE_PICKER_GROUP_STORAGE_KEY, DEVICE_ROLE_META, DEVICE_ROLE_NOUNS, DEVICE_TYPE_CONTROL, DEVICE_TYPE_META, DEVICE_TYPE_NOUNS, DataRecordsHub, DataTable, DataTableFilterBar, DataTablePager, DetectionCanvas, DetectionOverlay, DetectionResultTree, DevShell, DeviceActivityPanel, DeviceBatchToolbar, DeviceCard, DeviceContextProvider, DeviceExportPanel, DeviceExportSetup, DeviceFilterBar, DeviceFleetFromServer, DeviceFleetProvider, DeviceGrid, DeviceHistoryView, DeviceItem, DeviceList, DeviceMultiSelectField, DeviceName, DevicePicker, DeviceQuickDetailProvider, DeviceSelectField, DeviceSelectorPicker, DeviceStepMatrix, DevicesFailedLine, DevicesLoadingLine, DevicesWidenWarning, Dialog, DialogBody, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, DisclosureChevron, DiscoveryPanel, DisplayPaletteProvider, Footprints as Dn, DoorbellRecentPanel, Bug as Dr, Dropdown, DropdownContent, DropdownItem, DropdownTrigger, Pipette as Dt, DummyHeroCard, DummyInline, Truck as E, EMPTY_DATA_TABLE_FILTER, EMPTY_HISTORY_PANELS, EVENT_KIND_ICONS, EmptyState, Funnel as En, EndpointResultsCard, EndpointTestCard, EntryJsonSchemaForm, Bus as Er, ErrorBox, Plane as Et, EventKindGlyph, EventStream, ExtensionsPanel, Timer as F, FALLBACK_SCOPE, FAST_ICON_GLYPHS, FILL, FLEET_LIST_GC_TIME_MS, FLEET_LIST_QUERY_KEY, FLEET_LIST_STALE_TIME_MS, FanHeroCard, FanInlineControl, FanPanel, FileInput, FilterBar, FloatingEventStream, FloatingLogStream, FloatingPanel, EyeOff as Fn, FormField$1 as FormField, BellRing as Fr, Navigation as Ft, Sparkles as G, GAP_INTERVAL_FACTOR, GRID_GAP, GRID_PAIRED, GRID_QUICK_STATS, GateBadge, GateControl, Database as Gn, ArrowUpToLine as Gr, GripTrack, GroupedModelSelector, GroupedTilePicker, Mic as Gt, Star as H, HISTORY_PAGE_PATH, HISTORY_PANELS_NAMESPACE, HISTORY_SELECTION_MAX, HISTORY_WINDOW_IDS, HISTORY_WINDOW_MS, HOST_WIDGETS, HUB_SESSION_RUN_MS, HistoryChart, HistoryWindowBar, HlsVideo, DoorOpen as Hn, HotkeyProvider, HotkeyScope, HoverZoomImage, Ban as Hr, MonitorPlay as Ht, HubSessionTestCard, HumidifierHeroCard, HumidifierInlineControl, Thermometer as I, INPUT_COMPACT, INPUT_SHELL, IconAction, IconButton, IconPicker, ImageHeroCard, ImageInlineControl, ImageSelector, ExternalLink as In, InferenceConfigSelector, Input, Battery as Ir, Music as It, ItemFormDialog, SlidersHorizontal as J, Copy as Jn, ArrowDown as Jr, Megaphone as Jt, Snowflake as K, KebabMenu, KeyValueList, Crosshair as Kn, ArrowRight as Kr, MessageSquare as Kt, Target as L, LIST_ROW, Label, LawnMowerHeroCard, LawnMowerInlineControl, LayeredSettingsForm, LightHeroCard, LightInlineControl, Eraser as Ln, LockHeroCard, LockInlineControl, LockPanel, LogStream, LoginForm, BatteryWarning as Lr, Move as Lt, Tractor as M, MEDIA_GRID, MINUTES_PER_DAY, MODE_COLOR, MaskShapeCanvas, MediaCard, MediaGrid, MediaPlayerHeroCard, MediaPlayerInlineControl, MediaPlayerPanel, Feather as Mn, MobileDrawer, ModelPicker, MotionZonesSettings, Bird as Mr, Pause as Mt, ToggleRight as N, NAVIGATION_DRIVE_INTERVAL_MS, NODE_COLOR_IDS, NatResultCard, NavigationPanel, NetworkLinkBadge, Fan as Nn, NodeMultiSelectField, NodePicker, NodeSelectField, NotificationTargetSelectField, NotificationTargetsField, Bike as Nr, Package as Nt, TrendingDown as O, OCCUPANCY_KEY, OPTION_SELECT_SEARCH_MIN_OPTIONS, OfflineBadge, Flashlight as On, OptionSelect, Box as Or, Pin as Ot, ToggleLeft as P, PAGE_SIZE_ALL, PHASE_CONFIG, PICKER_CHIP_LIMIT, PICKER_DEFAULT_GROUP_BY, PICKER_GROUP_BY_MODES, PICKER_GROUP_COLLAPSE_AT, PICKER_NONE_KEY, PICKER_NOUN_PLURAL, PICKER_NO_FILTERS, PICKER_PAGE_SIZE, PICKER_SEARCH_DEBOUNCE_MS, PICKER_WINDOW, PRIORITY, PTZOverlay, PageHeader, PageShell, PageSizeSelect, Pagination, PasswordInput, PhaseIcon, PipelineBuilder, PipelineRuntimeSelector, PipelineStep, PlaceholderChipField, PlayerOverlaysProvider, Eye as Pn, Popover, PopoverContent, PopoverRowAction, PopoverTrigger, Bell as Pr, PrimaryChildPicker, PrivacyMaskSettings, ProviderBadge, ProviderEntryPills, Network as Pt, PtzPanel, Ship as Q, CloudSnow as Qn, Activity as Qr, QrCode, Lock as Qt, QuantityValueInput, Tag as R, RECONNECT_POLICY, RECORDED_PLAYBACK_MODES, RESOLUTION_BUCKET_MS, RIGHT, ROI_AREA_WARN_FRACTION, ROLE_DESCRIPTOR, ROOT_DETECTOR_STEP_ID, RadialGauge, Radio, RecordEntriesPanel, RecordedPlaybackProvider, RecordingPanel, ResponseLog, RetrainReviewBadge, EllipsisVertical as Rn, RoleDisplayDefaultsFromServer, RoleDisplayDefaultsProvider, RoleNodePill, RootModelSourceControl, RootSuppliedModelNote, BatteryMedium as Rr, MoveVertical as Rt, RunReport, RunningBadge, RunningStatusLine, Upload as S, SCENE_CAPTURE_VARIANTS, SECRET_MASK_PLACEHOLDER, SECRET_REVEAL_MS, SECTION_BODY, SECTION_CARD, SECTION_HEADER, SETTING_ROW, SETTING_ROW_LABEL, SETTING_ROW_STACK_BREAKPOINT, SETTING_ROW_VALUE, SETTING_ROW_VALUE_TEXT, SNAPSHOT_MEDIA_PATH, SPLIT_PANEL_OUTER, SPLIT_PANEL_SIDE, STACK_GAP, STATE_COLOR, STEP_DOCK_WIDTH_PX, SUBJECT_PATH_DWELL_EPS, SUBJECT_PATH_FULL_FRAME_COVERAGE, SUBJECT_PATH_MAX_POINTS, SceneMonitorEditor, ScopePicker, ScriptHeroCard, ScriptInlineControl, ScrollArea, SecretFieldControl, SecretRevealProvider, SectionCard, SectionToolbar, SectionedPage, SegmentedChoice, Select, SelectedChip, SemanticBadge, SendFrameToTrainingButton, SensorHeroCard, SensorInlineControl, SensorValueAtom, Separator, SettingRow, Sidebar, SidebarItem, Skeleton, SlideToggle, Slider, Grid2x2 as Sn, SnapshotButton, SortHeaderButton, Sparkline, Cast as Sr, PowerOff as St, StableTabPanel, StatCard, StateTimeline, StateValuesStream, StatusBadge, StepDetailDock, StepInspectorPanel, StepModelRow, StepTimings, Stepper, StorageRecordsPanel, StreamBrokerSelector, StreamDebugOverlay, StreamPanel, Switch, SwitchHeroCard, SwitchInlineControl, SwitchPanel, SystemProvider, Type as T, TABLE_SCROLL_MAX_H, TEMPERATURE_SCALES, TEXT_FIELD_LABEL, TEXT_HINT, TEXT_METRIC, TEXT_SECTION_LABEL, TEXT_VALUE, TIMEZONES, Tabs, TabsContent, TabsList, TabsTrigger, TapToggle, Textarea, ThemeProvider, ThermostatHeroCard, ThermostatInlineControl, TimeSeriesChart, TimelineSlider, TimezoneSelector, Gamepad2 as Tn, Tooltip, TooltipContent, TooltipTrigger, Cable as Tr, TrainingBaseModelPicker, TrainingCollectionPicker, Play as Tt, Square as U, UNIT_PREFERENCES_NAMESPACE, UiTextProvider, UiTrans, DoorClosed as Un, UnitPicker, UnitPreferencesFromServer, UnitPreferencesProvider, Baby as Ur, Minus as Ut, SunMedium as V, VacuumHeroCard, VacuumInlineControl, ValueReadout, ValveHeroCard, ValveInlineControl, VersionBadge, ViewSwitch, Download as Vn, VodPlaybackProvider, Bath as Vr, Moon as Vt, Sprout as W, WaterHeaterHeroCard, WaterHeaterInlineControl, WeatherHeroCard, WeatherInlineControl, WidgetMetricCard, WidgetPanel, WidgetRegistryProvider, WidgetSlot, Dog as Wn, ArrowUp as Wr, Minimize2 as Wt, SkipBack as X, Cloud as Xn, AlarmSmoke as Xr, MapPin as Xt, SkipForward as Y, Cog as Yn, ArrowDownToLine as Yr, Maximize2 as Yt, Siren as Z, CloudSun as Zn, ZoneEditingProvider, AirVent as Zr, Mail as Zt, Vibrate as _, Hash as _n, ChevronLeft as _r, RadioTower as _t, Wrench as a, acceleratorLabel, acceleratorShortLabel, agentColumnKey, alignSeries, allDeviceTypeFilterOptions, Lightbulb as an, anchorNow, applyFleetQueryDefaults, applyPickerFilters, CircleStop as ar, ariaSortForColumn, assignNodeColorId, Server as at, axisTicks, User as b, badgeFor, binaryBatteryIsLow, bindsToModel, Hammer as bn, booleanLabels, boundsInPicked, ChartLine as br, Puzzle as bt, bucketTotals, buildColorByNodeId, buildDataRecordRows, buildPeerConnectionConfig, buildStepTreeFromSchema, buildSubjectPath, buildTimeSeriesModel, Wifi as c, catalogHasDraft, chartKeys, chartSeriesStyle, childEntityId, childListName, chipOverflow, chunk, clampMinute, classifyAddressScope, classifyCapability, classifySessionVerdict, clearPickerGroup, clusterRootModelIds, cn, colorIdForNode, columnsForContext, compareSrflxMappings, computePageButtons, consumableItemLevel, consumableLevelBarClass, consumableLevelLabel, consumableLevelVariant, containerChildToRef, countableDevices, coverHighlight, coverageLine, CirclePause as cr, createAddonI18n, createSharedContext, createTheme, Scan as ct, currentAddonLanguage, cursorFractionFor, WifiLow as d, darkColors, dataRecordContents, dataRecordKey, dataRecordSearchText, dataRecordType, dataTableFacetGroups, dataTableFacets, decodeCustomWindow, decodeSeriesRef, defaultAxisSpec, defaultOfField, defaultSelectClusterRoots, defaultSingleClusterRoot, defaultTheme, defaultUiText, deriveDeviceKind, deriveWebrtcDebugStats, describeDeviceSelector, detectPlatform, deviceIntegrationResolver, deviceListStateOf, deviceMatchesFilter, deviceNameNouns, deviceOptionLabel, deviceRoleMeta, deviceRoleMetaOf, deviceTypeLabel, deviceTypeMeta, deviceTypeMetaOf, devicesToOptions, Inbox as dn, dockBox, CircleCheckBig as dr, draftFromQuery, Router as dt, effectivePageSize, emptyDevicesWidens, emptySessionRun, LocateFixed as en, encodeCustomWindow, encodeSeriesRef, energyBuckets, ensureMfHostInit, CloudLightning as er, ShieldOff as et, eventKindLabel, WifiHigh as f, filterDataTableRows, filterDeviceOptions, filterOccupancyLines, filterOptions as filterOptionSelectOptions, filterPickerDevices, finalizeSessionRun, findTimezone, flattenPickerGrouping, flattenPickerRows, fleetViewOf, Image as fn, foldDeviceName, formatChartBytes, formatChartNumber, formatChartValue, formatControlDateTime, formatDeviceName, formatLastSeen, formatNumeric, formatSettingValue, formatSpan, formatTimeLabel, CircleAlert as fr, freezeVerdict, Route as ft, fuzzyMatch, Volume2 as g, gapThresholdMs, getClassColor, getPhaseVisual, Heater as gn, ChevronRight as gr, groupAgentColumns, groupChildrenByLayout, groupDeviceSeries, groupPickerDevices, groupPickerDevicesBy, Radio$1 as gt, VolumeX as h, hardwareLabel, historyPageHref, History as hn, ChevronUp as hr, RefreshCw as ht, hubOrigin, hubPath, hubUrl, hubWsUrl, humanDuration, humanizeName, humidifierTint, X as i, iconGlyphsFailed, iconGlyphsLoaded, Link2 as in, indexDeviceNames, initialScrubState, insertAtSelection, CircleX as ir, isAbsentProvider, isByteUnit, isConsumableLevelField, isDataTableFilterActive, isDeviceNameStock, isDrawableSubjectPath, isFieldVisible, isGroupExpanded, isHistoryWindowId, isKeychainFieldValue, isModelScopedField, isPickableUnit, isRedactedSecret, isRefusal, isSecretField, isValueField, Settings as it, TrainFront as j, Film as jn, Blinds as jr, PawPrint as jt, TrendingUp as k, FlashlightOff as kn, Bot as kr, Phone as kt, WifiZero as l, lawnMowerActivityMeta, lightColors, linePoints, Laugh as ln, loadIconGlyphs, loadRemoteBundle, CircleDot as lr, Save as lt, lucideExportName, WashingMachine as m, makeScrubBridge, mapRootDetectorPlacements, matchesCombo, mergeSecretForSubmit, metadataEntries, metadataString, minuteFromPointer, House as mn, mountAddonPage, mountPath, ChevronsDownUp as mr, RotateCcw as mt, ZoomIn as n, nextGridPosition, nextReconnectAction, nextSort, nextSortDirection, nextTableSort, niceMax, niceRange, List as nn, nodeColorClass, nodeSoftBgClass, nodeTextColorClass, normalizeForSearch, normalizeLanguage, normalizeSelection, nounSpecFor, Clock as nr, ShieldAlert as nt, Workflow as o, occupancyFacets, occupancyLines, offListSelections, Leaf as on, openTopLayer, optionSearchText as optionSelectSearchText, CircleQuestionMark as or, orphanDeviceLabel, Search as ot, outsideBounds, overrideEntityIdFromLink, Waves as p, pageRows, pageSizeLabel, paginateRows, parentDetailOf, parseCapKey, parseCombo, parseConsumableLevel, parseIceCandidate, parsePickerGroupBy, parseProducerKey, parseRecordedServerMessage, partitionSelected as partitionOptionSelectSelected, partitionSuggested, pickerFacetFilterShown, pickerFacetKey, pickerFacetOptions, pickerFiltersActive, pickerGroupKey, pickerHiddenSelectedCount, pickerLocationKey, pickerQueryTokens, pickerRowFacts, pickerSearchText, pickerZoneFilterSuspended, pinnedStreamChoices, placePopover, ImageOff as pn, ChevronsUpDown as pr, preferenceForQuantity, previousWindow, projectSubjectPath, providerIcons, RotateCw as pt, Smartphone as q, Cpu as qn, ArrowLeft as qr, Menu as qt, quantityStoredUnit, quantityUnitChoices, Zap as r, readHistory, readHistoryPanels, readItemId, readStoredGroupBy, readUnitPreferences, reduceSessionRun, registerAddonBundle, renderMarkup, renderTagged, resetHubMountForTests, resetPickerFilters, resolveContainerPrimary, resolveControlAlign, resolveDeviceControl, resolveDeviceIntegration, resolveDeviceLabel, resolveDisplayIcon, resolveEffectiveDefaultModel, resolveEffectiveStepModel, resolveEventKindIcon, resolveHistoryWindow, resolveSearchable as resolveOptionSelectSearchable, resolveParentNames, resolvePrimaryChild, resolveSelectedDevices, resolveSensorDisplay, resolveStepDefaultModel, retrainReviewBadgeLook, ListChecks as rn, roiTooLarge, rootSourceState, routerBasename, Clapperboard as rr, Share2 as rt, runningDurationSince, runningStatusParts, Wind as s, sameDeviceName, sameLocationSuggestions, scrubReducer, searchSteps, secretDisplayValue, secretSubmitValue, segmentsFromChanges, selectPickerGroup, selectedDeviceOptions, serializeRecordedCommand, seriesRefId, settingsModelIdFor, sharedGapSpans, shiftPoints, shouldCommit, shouldEmit, shouldShowAddNewFooter, shouldShowUseQueryRow, shouldUseSingleNode, showsNoCamerasHint, LayoutGrid as sn, snapMinute, sortRows, sortRowsByColumn, CirclePlus as sr, ScrollText as st, stackBuckets, stackSeries, stateAt, stateRow, stateStyle, statusIcons, statusLine, stepFieldDomId, stepHasModelForFormat, stepLocalFields, stepModelOptions, storedToPicked, stripDeviceParentPrefix, stripParentNamePrefix, subjectPathSampleFromBox, subjectPathSvgPoints, summarizeHubCandidates, swatchFillClass, swatchLineClass, ZoomOut as t, tabForSelector, themeToCss, themeToRootCss, timeInState, LoaderCircle as tn, toStationaryOverlayBox, toggleDataTableFacet, toggleDataTableGroupFacet, togglePickerDevice, togglePickerKey, CloudFog as tr, trainingRefusalText, translateAddonKey, trpc, ShieldCheck as tt, typeLabel, typedToStored, WifiOff as u, Info as un, unitAxes, CircleCheck as ur, useAccessoriesGetStatus, useAccessoriesSetChildHidden, useAccountUnitPreferences, useActionSourceListActions, useActionSourceRunAction, useActionSourceStopAction, useActionsCreate, useActionsDelete, useActionsGet, useActionsGetLinks, useActionsGetTraces, useActionsList, useActionsListForCamera, useActionsRun, useActionsSetLinks, useActionsStop, useActionsUpdate, useAddonPagesListPages, useAddonSettingsGetDeclaredSettingsKeys, useAddonSettingsGetDeviceSettings, useAddonSettingsGetGlobalSettings, useAddonSettingsGetIntegrationFormSchema, useAddonSettingsGetIntegrationSettings, useAddonSettingsUnsetStoredSettingsKeys, useAddonSettingsUpdateDeviceSettings, useAddonSettingsUpdateGlobalSettings, useAddonT, useAddonWidgetsListWidgets, useAddonsApplyAutoUpdateToAll, useAddonsCancelJob, useAddonsCustom, useAddonsForceRefresh, useAddonsGetAddonAutoUpdate, useAddonsGetAutoUpdateSettings, useAddonsGetJob, useAddonsGetLastRestart, useAddonsGetLogs, useAddonsGetPackageDocs, useAddonsGetVersions, useAddonsInstallPackage, useAddonsList, useAddonsListCapabilityProviders, useAddonsListFrameworkPackages, useAddonsListInstallations, useAddonsListJobs, useAddonsListPackages, useAddonsListUpdates, useAddonsOnAddonLogs, useAddonsReloadPackages, useAddonsRestartAddon, useAddonsRestartServer, useAddonsRetryLoad, useAddonsRollbackPackage, useAddonsSearchAvailable, useAddonsSetAddonAutoUpdate, useAddonsSetAutoUpdateSettings, useAddonsSetCapabilityProviderEnabled, useAddonsStartJob, useAddonsUninstallPackage, useAddonsUpdatePackage, useAirQualitySensorGetStatus, useAlarmPanelArm, useAlarmPanelDisarm, useAlarmPanelGetStatus, useAlarmPanelTrigger, useAlert, useAlertsDismiss, useAlertsEmit, useAlertsGetUnreadCount, useAlertsList, useAlertsMarkAllRead, useAlertsMarkRead, useAlertsUpdate, useAllWidgets, useAmbientLightSensorGetStatus, useAudioAnalysisApplyDeviceSettingsPatch, useAudioAnalysisGetDeviceLiveContribution, useAudioAnalysisGetDeviceSettingsContribution, useAudioAnalysisResolveDeviceSettings, useAudioAnalyzerAnalyseChunk, useAudioAnalyzerAttachDevice, useAudioAnalyzerClassify, useAudioAnalyzerDetachDevice, useAudioAnalyzerDispose, useAudioAnalyzerIsReady, useAudioAnalyzerReprobeAudioEngine, useAudioCodecCanHandle, useAudioCodecCloseSession, useAudioCodecCreateDecodeSession, useAudioCodecCreateEncodeSession, useAudioCodecFlushEncode, useAudioCodecListActiveSessions, useAudioCodecListSupportedCodecs, useAudioCodecPullEncoded, useAudioCodecPullPcm, useAudioCodecPushEncodedFrame, useAudioCodecPushPcm, useAudioMetricsGetCurrentSnapshot, useAudioMetricsGetHistory, useAutomationControlDisable, useAutomationControlEnable, useAutomationControlGetStatus, useAutomationControlTrigger, useBackupCancel, useBackupCheckBackupKey, useBackupDelete, useBackupDeleteSchedule, useBackupDisableEncryption, useBackupGetEncryption, useBackupGetEntries, useBackupList, useBackupListArchives, useBackupListAvailableDatabases, useBackupListDestinations, useBackupListLocations, useBackupListRuns, useBackupListSchedules, useBackupPreviewSchedule, useBackupRestore, useBackupSetupEncryption, useBackupTrigger, useBackupUpsertDestinationPolicy, useBackupUpsertSchedule, useBatteryGetStatus, useBatteryWakeForStream, useBinaryGetStatus, useBrightnessGetStatus, useBrightnessSetBrightness, useBrokerAdd, useBrokerGet, useBrokerGetBrokerConfig, useBrokerGetSettings, useBrokerGetSettingsSchema, useBrokerGetState, useBrokerGetStatus, useBrokerList, useBrokerListProviders, useBrokerPickerSlot, useBrokerPublish, useBrokerRemove, useBrokerSetSettings, useBrokerSubscribe, useBrokerTestConnection, useBrokerTestSettings, useBrokerUnsubscribe, useButtonPress, useCalendarsGetPreferences, useCalendarsListCalendars, useCalendarsListEvents, useCalendarsSetCalendarPreference, useCameraCredentialsGetCredentials, useCameraCredentialsGetStatus, useCameraGridLayoutApplyDeviceSettingsPatch, useCameraGridLayoutGetDeviceLiveContribution, useCameraGridLayoutGetDeviceSettingsContribution, useCameraGridLayoutGetLayout, useCameraGridLayoutSaveLayout, useCameraPipelineConfigApplyDeviceSettingsPatch, useCameraPipelineConfigGetDeviceLiveContribution, useCameraPipelineConfigGetDeviceSettingsContribution, useCameraStreamsGetBrokerStreams, useCameraStreamsGetCameraStreams, useCameraStreamsGetProfileRtspEntries, useCameraStreamsGetRtspEntries, useCameraStreamsPickStream, useCapabilityPresence, useCarbonMonoxideGetStatus, useClassPainter, useClimateControlGetStatus, useClimateControlSetFanMode, useClimateControlSetMode, useClimateControlSetPreset, useClimateControlSetSwingHorizontal, useClimateControlSetSwingVertical, useClimateControlSetTarget, useClimateControlSetTargetHumidity, useClimateControlSetTargetRange, useClusterNodes, useClusterTopology, useColorGetStatus, useColorSetColor, useConfirm, useConnectionTestDescribeTest, useConnectionTestTestSettings, useConnectivityGetStatus, useConsumablesGetStatus, useConsumablesReset, useContactGetStatus, useContainerChildren, useControlGetStatus, useControlSetValue, useCoreBlocksCompile, useCoreBlocksCreate, useCoreBlocksCreateComposition, useCoreBlocksDelete, useCoreBlocksGet, useCoreBlocksGetAutomationRunState, useCoreBlocksGetBlockSettings, useCoreBlocksGetComposition, useCoreBlocksGetCustomization, useCoreBlocksGetTraces, useCoreBlocksGetTypeDefs, useCoreBlocksList, useCoreBlocksListComposableCaps, useCoreBlocksListCompositions, useCoreBlocksMigrateRawSecrets, useCoreBlocksReportAutomationRun, useCoreBlocksRestart, useCoreBlocksSetEnabled, useCoreBlocksUpdate, useCoreBlocksUpdateBlockSettings, useCoreBlocksUpdateComposition, useCoreBlocksValidateComposition, useCoverClose, useCoverGetStatus, useCoverOpen, useCoverSetPosition, useCoverSetTiltPosition, useCoverStop, useCustomFieldRenderer, useDataTableFilter, useDayNightGetOptions, useDayNightGetStatus, useDayNightSetSettings, useDebouncedString, useDecoderGetInfo, useDecoderReprobeHwaccel, useDetectionPipelineApplyDeviceSettingsPatch, useDetectionPipelineGetDeviceLiveContribution, useDetectionPipelineGetDeviceSettingsContribution, useDevShell, useDevice, useDeviceAdminLink, useDeviceAdminLinkGetAdminLink, useDeviceAdoptionAdopt, useDeviceAdoptionGetCandidate, useDeviceAdoptionGetStatus, useDeviceAdoptionListCandidateFilters, useDeviceAdoptionListCandidates, useDeviceAdoptionRefresh, useDeviceAdoptionRelease, useDeviceAdoptionResync, useDeviceAutotrack, useDeviceBattery, useDeviceCapSlice, useDeviceCapability, useDeviceCredentialsDeleteDeviceCredential, useDeviceCredentialsGetDeviceCaStatus, useDeviceCredentialsGetDeviceCertificateSettings, useDeviceCredentialsListDeviceCredentials, useDeviceCredentialsRenameDeviceCredential, useDeviceCredentialsRevokeDeviceCredential, useDeviceCredentialsSetDeviceCertificateSettings, useDeviceCredentialsStartEnrollment, useDeviceDetections, useDeviceDiscoveryAdoptDevice, useDeviceDiscoveryGetStatus, useDeviceDiscoveryListDiscovered, useDeviceDiscoveryRefreshDiscovery, useDeviceDiscoveryReleaseDevice, useDeviceExportApplyDeviceSettingsPatch, useDeviceExportExposeDevice, useDeviceExportExposeEntity, useDeviceExportGetDeviceLiveContribution, useDeviceExportGetDeviceSettingsContribution, useDeviceExportGetStatus, useDeviceExportListExposedDevices, useDeviceExportListExposedEntities, useDeviceExportListSupportedDeviceKinds, useDeviceExportListSupportedEntityKinds, useDeviceExportUnexposeDevice, useDeviceExportUnexposeEntity, useDeviceExtensionListCandidates, useDeviceExtensionListSlots, useDeviceExtensionListSources, useDeviceExtensionSetSlot, useDeviceHistoryDeclareSeries, useDeviceHistoryDeleteOrphanSeries, useDeviceHistoryGetDeviceEnabled, useDeviceHistoryGetStatus, useDeviceHistoryListNodeSeries, useDeviceHistoryListOrphanSeries, useDeviceHistoryListSeries, useDeviceHistoryQuery, useDeviceHistoryQueryMany, useDeviceHistoryQueryNode, useDeviceHistoryRecord, useDeviceHistoryRecordBuckets, useDeviceHistorySetDeviceEnabled, useDeviceId, useDeviceLabel, useDeviceLabelById, useDeviceListPageSize, useDeviceManagerAddLocation, useDeviceManagerAdoptDevice, useDeviceManagerAdoptionAdopt, useDeviceManagerAdoptionCancelJob, useDeviceManagerAdoptionListCandidateFilters, useDeviceManagerAdoptionListCandidates, useDeviceManagerAdoptionListJobs, useDeviceManagerAdoptionRefresh, useDeviceManagerAdoptionRelease, useDeviceManagerAdoptionResync, useDeviceManagerAdoptionStartJob, useDeviceManagerAllocateDeviceId, useDeviceManagerApplyInitialMeta, useDeviceManagerCleanupDeletedDevicesData, useDeviceManagerCreateDevice, useDeviceManagerDisable, useDeviceManagerDiscoverAllProviders, useDeviceManagerDiscoverDevices, useDeviceManagerDiscoverProvider, useDeviceManagerDiscoveryProviders, useDeviceManagerEnable, useDeviceManagerGetAllBindings, useDeviceManagerGetBindings, useDeviceManagerGetBindingsBatch, useDeviceManagerGetChildren, useDeviceManagerGetChildrenBatch, useDeviceManagerGetConfigSchema, useDeviceManagerGetCreationSchema, useDeviceManagerGetDevice, useDeviceManagerGetDeviceAggregate, useDeviceManagerGetDeviceLiveInfoAggregate, useDeviceManagerGetDeviceSettingsAggregate, useDeviceManagerGetDeviceStatusAggregate, useDeviceManagerGetDeviceStatusAggregateBatch, useDeviceManagerGetLinkedDevices, useDeviceManagerGetLinkedDevicesBatch, useDeviceManagerGetRoleDisplayDefaults, useDeviceManagerGetSettingsSchema, useDeviceManagerGetStreamProfileMap, useDeviceManagerGetStreamSources, useDeviceManagerGetWireableFields, useDeviceManagerGetWrapperActivation, useDeviceManagerListAll, useDeviceManagerListBindableCapsForDeviceType, useDeviceManagerListDeletedSince, useDeviceManagerListDeviceIdsByCaps, useDeviceManagerListLocationDescriptions, useDeviceManagerListLocationIcons, useDeviceManagerListLocations, useDeviceManagerListPersistedByAddon, useDeviceManagerListSiteZones, useDeviceManagerListWrappersForCap, useDeviceManagerLoadConfig, useDeviceManagerLoadMeta, useDeviceManagerLoadRuntimeState, useDeviceManagerMigrateDevice, useDeviceManagerPersistConfig, useDeviceManagerProbeStreams, useDeviceManagerProviderCreationType, useDeviceManagerProviderDiscoveryParamsSchema, useDeviceManagerRegisterDevice, useDeviceManagerRemove, useDeviceManagerRemoveByIntegration, useDeviceManagerRemoveDevice, useDeviceManagerRemoveLocation, useDeviceManagerRemoveSiteZone, useDeviceManagerRenameLocation, useDeviceManagerRenameSiteZone, useDeviceManagerRunDeviceAction, useDeviceManagerSetChildLayout, useDeviceManagerSetDisabled, useDeviceManagerSetDisplay, useDeviceManagerSetIntegrationId, useDeviceManagerSetLinkDeviceId, useDeviceManagerSetLocation, useDeviceManagerSetLocationDescription, useDeviceManagerSetLocationIcon, useDeviceManagerSetLocationZone, useDeviceManagerSetMetadata, useDeviceManagerSetName, useDeviceManagerSetPrimaryChildEntityId, useDeviceManagerSetRole, useDeviceManagerSetRoleDisplayDefaults, useDeviceManagerSetSiteZone, useDeviceManagerSetStreamProfileMap, useDeviceManagerSetType, useDeviceManagerSetWrapperActive, useDeviceManagerTestCreationField, useDeviceManagerTestField, useDeviceManagerUpdateConfig, useDeviceManagerUpdateDeviceField, useDeviceManagerUpdateDeviceFieldsBatch, useDeviceNameIndex, useDeviceNameNouns, useDeviceNetworkLink, useDeviceOpsGetConfigEntries, useDeviceOpsGetRawState, useDeviceOpsGetSettingsSchema, useDeviceOpsGetStreamSources, useDeviceOpsRemoveDevice, useDeviceOpsRunAction, useDeviceOpsSetConfig, useDeviceProviderAdoptDiscoveredDevice, useDeviceProviderClassifyDiscoveryHits, useDeviceProviderCreateDevice, useDeviceProviderDiscoverDevices, useDeviceProviderGetChildCreationSchema, useDeviceProviderGetDevices, useDeviceProviderGetDiscoveryModes, useDeviceProviderGetDiscoveryParamsSchema, useDeviceProviderGetManualCreationType, useDeviceProviderGetStatus, useDeviceProviderReloadDevice, useDeviceProviderStart, useDeviceProviderStop, useDeviceProviderSupportsDiscovery, useDeviceProviderSupportsManualCreation, useDeviceProviderTestCreationField, useDeviceProxy, useDeviceQuickDetailOpen, useDeviceRunsGetCurrentRun, useDeviceRunsGetRun, useDeviceRunsListRuns, useDeviceSeriesList, useDeviceSnapshot, useDeviceSnapshotImage, useDeviceState, useDeviceStateClaimFields, useDeviceStateGetAllSnapshots, useDeviceStateGetCapSlice, useDeviceStateGetNativeCapSlice, useDeviceStateGetSnapshot, useDeviceStateListClaims, useDeviceStatePatchOwnedFields, useDeviceStateReleaseClaim, useDeviceStateSetCapSlice, useDeviceStateSlice, useDeviceStatusGetStatus, useDeviceWebrtc, useDevices, useDiscoveredOptions, useDishwasherGetOptions, useDishwasherGetStatus, useDishwasherPause, useDishwasherResume, useDishwasherSetChildLock, useDishwasherSetExtraDry, useDishwasherSetHalfLoad, useDishwasherSetHygienePlus, useDishwasherSetIntensiveZone, useDishwasherSetOption, useDishwasherSetPower, useDishwasherSetProgram, useDishwasherSetVarioSpeedPlus, useDishwasherStart, useDishwasherStop, useDisplayIconResolver, useDisplayPaletteGetPalette, useDisplayPaletteListPresets, useDisplayPaletteSetPalette, useDisplayPaletteView, useDoorbellEvents, useDoorbellGetStatus, useEnumSensorGetStatus, useEventEmitterGetStatus, useEventInvalidation, useEventStreamLatest, useEventStreamMap, useFaceGalleryAssignFace, useFaceGalleryAssignFaces, useFaceGalleryAuditIdentitySamples, useFaceGalleryCreateIdentity, useFaceGalleryDeleteFace, useFaceGalleryDeleteIdentity, useFaceGalleryGetFaceByTrack, useFaceGalleryGetFaceMedia, useFaceGalleryListIdentities, useFaceGalleryListIdentitySamples, useFaceGalleryListRecentFaces, useFaceGalleryRemoveSample, useFaceGalleryRenameIdentity, useFaceGallerySuggestFaceClusters, useFaceGalleryUnassignFace, useFaceGalleryUnassignFaces, useFanControlGetStatus, useFanControlSetDirection, useFanControlSetOscillating, useFanControlSetPercentage, useFanControlSetPreset, useFeatureProbeGetStatus, useFloodGetStatus, useGasGetStatus, useGroupActiveGetStatus, useGroupCommandsGetStatus, useGroupStatusGetStatus, useHeatingValveGetStatus, useHistoryPanels, useHistoryReader, useHistoryReads, useHotkey, useHumidifierGetStatus, useHumidifierSetMode, useHumidifierSetOn, useHumidifierSetTargetHumidity, useHumiditySensorGetStatus, useIconGlyphsVersion, useImageGetStatus, useImageSettingsGetOptions, useImageSettingsGetStatus, useImageSettingsSetSettings, useIntegrationsCreate, useIntegrationsDelete, useIntegrationsGet, useIntegrationsGetAvailableTypes, useIntegrationsGetByAddonId, useIntegrationsGetSettings, useIntegrationsList, useIntegrationsSetSettings, useIntegrationsTestConnection, useIntegrationsUpdate, useIntercomEndTalkSession, useIntercomGetStatus, useIntercomHandleAnswer, useIntercomPushTalkAudio, useIntercomStartSession, useIntercomStartTalkSession, useIntercomStopSession, useIrTransmitterGetInfo, useIrTransmitterSend, useIsMidWidth, useIsMobile, useItemFormUrl, useKeychainAdminAcknowledgeReset, useKeychainAdminDeleteOrphans, useKeychainAdminDownloadRecoveryKey, useKeychainAdminImportSecret, useKeychainAdminListAudit, useKeychainAdminListSecrets, useKeychainAdminPurgeRetiredKeys, useKeychainAdminResetKeychain, useKeychainAdminResetReport, useKeychainAdminReveal, useKeychainAdminRotateMasterKey, useKeychainAdminSetSystemSecret, useKeychainAdminStatus, useLawnMowerControlDock, useLawnMowerControlGetStatus, useLawnMowerControlPause, useLawnMowerControlStartMowing, useLiveBuffer, useLiveEvent, useLlmCancel, useLlmDeleteModel, useLlmDeleteProfile, useLlmGenerate, useLlmGenerateVision, useLlmGetDefaults, useLlmGetRuntimeStatus, useLlmGetUsage, useLlmInstallModel, useLlmListModelCatalog, useLlmListModels, useLlmListNodeModels, useLlmListProfileKinds, useLlmListProfiles, useLlmListRuntimeNodes, useLlmMigrateRawSecrets, useLlmResolveModelRef, useLlmSetDefault, useLlmStartRuntime, useLlmStopRuntime, useLlmTestProfile, useLlmUpsertProfile, useLocalNetworkAddCustomAddress, useLocalNetworkDownloadCa, useLocalNetworkGetAddresses, useLocalNetworkGetAllowedAddresses, useLocalNetworkGetConnectionEndpoints, useLocalNetworkGetHubAddresses, useLocalNetworkGetNotificationEndpoint, useLocalNetworkGetPreferred, useLocalNetworkGetScanSubnets, useLocalNetworkGetTlsStatus, useLocalNetworkGetViewerEndpoints, useLocalNetworkList, useLocalNetworkRegenerateCertificate, useLocalNetworkRemoveCustomAddress, useLocalNetworkResetAllowlistToBestMatch, useLocalNetworkRevertToGeneratedCertificate, useLocalNetworkScanNetwork, useLocalNetworkSetAddressRole, useLocalNetworkSetAllowedAddresses, useLocalNetworkSetNotificationEndpoint, useLocalNetworkSetScanSubnets, useLocalNetworkSetViewerEndpoints, useLocalNetworkUploadCertificate, useLocalNetworkUseStoredUploadedCertificate, useLockControlGetStatus, useLockControlLock, useLockControlOpen, useLockControlUnlock, useLockDoorSensor, useMediaPlayerGetStatus, useMediaPlayerNext, useMediaPlayerPause, useMediaPlayerPlay, useMediaPlayerPlayMedia, useMediaPlayerPrevious, useMediaPlayerSeek, useMediaPlayerSelectSource, useMediaPlayerSetMute, useMediaPlayerSetRepeat, useMediaPlayerSetShuffle, useMediaPlayerSetVolume, useMediaPlayerStop, useMeshNetworkGetStatus, useMeshNetworkJoin, useMeshNetworkLeave, useMeshNetworkListPeers, useMeshNetworkLogout, useMeshNetworkStartLogin, useMeshNetworkTestConnection, useMeterGetStatus, useMetricsProviderCollectSnapshot, useMetricsProviderGetAddonStats, useMetricsProviderGetCached, useMetricsProviderGetCpuTemperature, useMetricsProviderGetCurrent, useMetricsProviderGetDiskSpace, useMetricsProviderGetGpuInfo, useMetricsProviderGetLoadSeries, useMetricsProviderGetProcessStats, useMetricsProviderListAddonInstances, useMetricsProviderListNodeProcesses, useMotionDetectionAnalyze, useMotionDetectionApplyDeviceSettingsPatch, useMotionDetectionGetDeviceLiveContribution, useMotionDetectionGetDeviceSettingsContribution, useMotionDetectionRemoveCamera, useMotionDetectionReset, useMotionGetStatus, useMotionIsDetected, useMotionTriggerGetStatus, useMotionTriggerSetMotionTrigger, useMotionZonesGetOptions, useMotionZonesGetStatus, useMotionZonesSetZone, useMqttBrokerAddBroker, useMqttBrokerGetBrokerConfig, useMqttBrokerGetStatus, useMqttBrokerListBrokers, useMqttBrokerRemoveBroker, useMqttBrokerStartEmbeddedBroker, useMqttBrokerStopEmbeddedBroker, useMqttBrokerTestConnection, useNativeObjectDetectionGetOptions, useNativeObjectDetectionGetStatus, useNativeObjectDetectionSetEnabled, useNativeObjectDetectionSetSettings, useNavigation, useNavigationGetFeatures, useNavigationGetStatus, useNavigationGoToPoint, useNavigationListActions, useNavigationMove, useNavigationPlaySound, useNavigationRunAction, useNavigationSetLightLevel, useNavigationSetLightMode, useNavigationSetLightOn, useNavigationStop, useNetworkAccessGetEndpoint, useNetworkAccessGetStatus, useNetworkAccessListEndpoints, useNetworkAccessStart, useNetworkAccessStop, useNetworkLinkGetStatus, useNetworkQualityGetAllStats, useNetworkQualityGetDeviceStats, useNetworkQualityReportClientStats, useNodesClusterAddonStatus, useNodesDeployAddon, useNodesDirectory, useNodesExecuteQuery, useNodesGetCapUsageGraph, useNodesGetNodeAddons, useNodesRenameNode, useNodesRestartAddon, useNodesRestartNode, useNodesRestartProcess, useNodesSetProcessLogLevel, useNodesShutdownNode, useNodesTopology, useNodesUndeployAddon, useNotificationOutputDeleteTarget, useNotificationOutputDiscoverTargets, useNotificationOutputGetTarget, useNotificationOutputListTargetKinds, useNotificationOutputListTargets, useNotificationOutputProbeTargetConfig, useNotificationOutputSend, useNotificationOutputSetTargetEnabled, useNotificationOutputTestTarget, useNotificationOutputUpsertTarget, useNotificationRulesActivateAlarmProfile, useNotificationRulesCancelSnooze, useNotificationRulesCreateAlarmProfile, useNotificationRulesCreateRule, useNotificationRulesCreateSequence, useNotificationRulesCreateSnooze, useNotificationRulesDeleteAlarmProfile, useNotificationRulesDeleteRule, useNotificationRulesDeleteSequence, useNotificationRulesGetAlarmConfig, useNotificationRulesGetAlarmSensors, useNotificationRulesGetClipRetentionAsks, useNotificationRulesGetConditionCatalog, useNotificationRulesGetHistory, useNotificationRulesGetRule, useNotificationRulesGetRuleLastRuns, useNotificationRulesGetSequence, useNotificationRulesGetTemplateCatalog, useNotificationRulesListDeviceMutes, useNotificationRulesListRules, useNotificationRulesListSequences, useNotificationRulesListSnoozes, useNotificationRulesPreviewStateSummary, useNotificationRulesPreviewTemplate, useNotificationRulesRenameAlarmProfile, useNotificationRulesResolveArtifactUrl, useNotificationRulesSetAlarmConfig, useNotificationRulesSetDeviceMuted, useNotificationRulesSetRuleEnabled, useNotificationRulesTestRule, useNotificationRulesUpdateRule, useNotificationRulesUpdateSequence, useNotifierCancel, useNotifierGetStatus, useNotifierSend, useNumericSensorGetStatus, useOidcConnectionsConnectionFormSchema, useOidcConnectionsCreateConnection, useOidcConnectionsDeleteConnection, useOidcConnectionsListConnections, useOidcConnectionsUpdateConnection, useOptimisticSlice, useOptionalSystem, useOptionalWidgetRegistry, useOsdGetStatus, useOsdManagerClearSlotBinding, useOsdManagerCopyDeviceConfiguration, useOsdManagerDeleteTemplate, useOsdManagerGetConditionSupport, useOsdManagerGetDeviceOsd, useOsdManagerGetSourceCatalog, useOsdManagerListTemplates, useOsdManagerPreviewSlot, useOsdManagerRenderDevice, useOsdManagerSetSlotBinding, useOsdManagerSetSlotCameraEnabled, useOsdManagerUpsertTemplate, useOsdSetOverlay, usePTZ, usePersistedDisclosure, usePersistedPageSize, usePetFeederCallPet, usePetFeederCancelFeed, usePetFeederFeed, usePetFeederGetStatus, usePetFeederMarkFoodReplenished, usePetFeederPlaySound, usePetFeederResetDesiccant, usePetFeederSetChildLock, usePetFeederSetFeedSound, usePetFeederSetIndicatorLight, usePetFeederSetVolume, usePetFountainGetStatus, usePetFountainResetDailyConsumption, usePetFountainSetPump, usePetFountainSetPumpInterval, usePetFountainSetPumpOffMinutes, usePetFountainSetPumpOnMinutes, usePickerSiteZones, usePipelineAnalyticsAddRetrainFrameFromRecording, usePipelineAnalyticsAddRetrainFramesToCollection, usePipelineAnalyticsApplyDeviceSettingsPatch, usePipelineAnalyticsBackfillRetrainOrigins, usePipelineAnalyticsCancelRelocateMedia, usePipelineAnalyticsCancelStorageMigrationMove, usePipelineAnalyticsClearTrackRelation, usePipelineAnalyticsClearTracks, usePipelineAnalyticsCompleteRetrainTrack, usePipelineAnalyticsCountRelocatableMedia, usePipelineAnalyticsCountUnstampedEventMedia, usePipelineAnalyticsCreateRetrainCollection, usePipelineAnalyticsDeleteDeviceEvents, usePipelineAnalyticsDeleteRetrainCollection, usePipelineAnalyticsDeleteTracks, usePipelineAnalyticsDeselectRetrainFrame, usePipelineAnalyticsGetActiveTracks, usePipelineAnalyticsGetAudioEvents, usePipelineAnalyticsGetDeviceLiveContribution, usePipelineAnalyticsGetDeviceSettingsContribution, usePipelineAnalyticsGetEventDensity, usePipelineAnalyticsGetEventDensityBatch, usePipelineAnalyticsGetEventMedia, usePipelineAnalyticsGetEventMediaFootprintByKind, usePipelineAnalyticsGetEventStoreFootprint, usePipelineAnalyticsGetKeyEvents, usePipelineAnalyticsGetKeyEventsBatch, usePipelineAnalyticsGetMediaReclaimStatus, usePipelineAnalyticsGetMotionEvents, usePipelineAnalyticsGetObjectEmbeddingRebuildStatus, usePipelineAnalyticsGetObjectEvents, usePipelineAnalyticsGetRetrainCorpusKpi, usePipelineAnalyticsGetRetrainExportUrl, usePipelineAnalyticsGetRetrainFrameImage, usePipelineAnalyticsGetSensorEvents, usePipelineAnalyticsGetStorageMigrationMoveStatus, usePipelineAnalyticsGetTrack, usePipelineAnalyticsGetTrackMedia, usePipelineAnalyticsGetTrainingExportSummary, usePipelineAnalyticsGetTrainingExportUrl, usePipelineAnalyticsListArchivedDebugNotes, usePipelineAnalyticsListBirthDecisions, usePipelineAnalyticsListEventKinds, usePipelineAnalyticsListEventKindsBatch, usePipelineAnalyticsListEventMedia, usePipelineAnalyticsListOpsLog, usePipelineAnalyticsListRecentTracks, usePipelineAnalyticsListRelocateMediaJobs, usePipelineAnalyticsListRetrainAnnotations, usePipelineAnalyticsListRetrainAssistProfiles, usePipelineAnalyticsListRetrainCollectionFrames, usePipelineAnalyticsListRetrainCollections, usePipelineAnalyticsListRetrainCorpusPage, usePipelineAnalyticsListRetrainFrames, usePipelineAnalyticsListRetrainStaging, usePipelineAnalyticsListTrackMedia, usePipelineAnalyticsListTrackRelations, usePipelineAnalyticsListTracks, usePipelineAnalyticsOfferRetrainArchive, usePipelineAnalyticsOwnersWithMedia, usePipelineAnalyticsPauseForStorageMigration, usePipelineAnalyticsProposeRetrainAnnotations, usePipelineAnalyticsProposeRetrainAnnotationsWithLlm, usePipelineAnalyticsPruneEvents, usePipelineAnalyticsPruneEventsBefore, usePipelineAnalyticsPruneTracksBefore, usePipelineAnalyticsReadLongTermSeries, usePipelineAnalyticsRebuildObjectEmbeddings, usePipelineAnalyticsReclaimDebugMedia, usePipelineAnalyticsReconcileFromDisk, usePipelineAnalyticsRefreshStorageLocationsForMigration, usePipelineAnalyticsRelocateMedia, usePipelineAnalyticsRemoveRetrainFrameFromCollection, usePipelineAnalyticsRenameRetrainCollection, usePipelineAnalyticsResolveRetrainTrainingCorpus, usePipelineAnalyticsRestageRetrainTrack, usePipelineAnalyticsResumeForStorageMigration, usePipelineAnalyticsSaveRetrainAnnotations, usePipelineAnalyticsSearchObjectEvents, usePipelineAnalyticsSelectRetrainFrames, usePipelineAnalyticsSetRetrainFrameComplete, usePipelineAnalyticsSetTrackFlags, usePipelineAnalyticsSetTrackPurity, usePipelineAnalyticsSetTrackRelation, usePipelineAnalyticsStartStorageMigrationMove, usePipelineAnalyticsWipeAllAnalytics, usePipelineAnalyticsWipeObjectEmbeddings, usePipelineAnalyticsWriteRetrainArchive, usePipelineExecutorCacheFrameInPool, usePipelineExecutorDeleteModel, usePipelineExecutorDownloadModel, usePipelineExecutorGetAddonModels, usePipelineExecutorGetAudioCapabilities, usePipelineExecutorGetAvailableEngines, usePipelineExecutorGetCapabilities, usePipelineExecutorGetDetectionConfigSchema, usePipelineExecutorGetEffectiveTuning, usePipelineExecutorGetEngineProvisioning, usePipelineExecutorGetInferenceDeviceHealth, usePipelineExecutorGetOrchestratorConfigSchema, usePipelineExecutorGetReferenceAudio, usePipelineExecutorGetReferenceAudioFiles, usePipelineExecutorGetReferenceImage, usePipelineExecutorGetSchema, usePipelineExecutorGetSelectedEngine, usePipelineExecutorGetVideoPipelineSteps, usePipelineExecutorInferCached, usePipelineExecutorKillEngine, usePipelineExecutorListLoadedEngines, usePipelineExecutorListReferenceImages, usePipelineExecutorRearmInferenceDevice, usePipelineExecutorRunAudioTest, usePipelineExecutorRunPipeline, usePipelineExecutorRunPipelineBatch, usePipelineExecutorSetVideoPipelineSteps, usePipelineExecutorSpinEngine, usePipelineExecutorUncacheFrame, usePipelineExecutorValidatePipeline, usePipelineOrchestratorAbortNodeBenchmark, usePipelineOrchestratorApplyAutoTune, usePipelineOrchestratorApplyDeviceSettingsPatch, usePipelineOrchestratorAssignAudio, usePipelineOrchestratorAssignPipeline, usePipelineOrchestratorDeleteNodeBenchmarkResult, usePipelineOrchestratorForgetInferenceDevice, usePipelineOrchestratorGetAgentLoad, usePipelineOrchestratorGetAgentSettings, usePipelineOrchestratorGetAudioAssignment, usePipelineOrchestratorGetAudioAssignments, usePipelineOrchestratorGetAudioNodeLoad, usePipelineOrchestratorGetCameraDetectionSource, usePipelineOrchestratorGetCameraMetrics, usePipelineOrchestratorGetCameraSettings, usePipelineOrchestratorGetCameraStatus, usePipelineOrchestratorGetCameraStatuses, usePipelineOrchestratorGetCameraSwitches, usePipelineOrchestratorGetCapabilityBindings, usePipelineOrchestratorGetClusterModelChoice, usePipelineOrchestratorGetDeviceLiveContribution, usePipelineOrchestratorGetDeviceSettingsContribution, usePipelineOrchestratorGetEffectiveShares, usePipelineOrchestratorGetGlobalMetrics, usePipelineOrchestratorGetIngestOwner, usePipelineOrchestratorGetNodeBenchmarkCandidates, usePipelineOrchestratorGetNodeBenchmarkPreflight, usePipelineOrchestratorGetNodeBenchmarkStatus, usePipelineOrchestratorGetNodeInferenceDevices, usePipelineOrchestratorGetPipelineAssignment, usePipelineOrchestratorGetPipelineAssignments, usePipelineOrchestratorGetPipelineDevicePin, usePipelineOrchestratorGetPlacementStats, usePipelineOrchestratorGetReconcileFromDiskStatus, usePipelineOrchestratorListAgentSettings, usePipelineOrchestratorListNodeBenchmarkResults, usePipelineOrchestratorPauseForStorageMigration, usePipelineOrchestratorPlanAutoTune, usePipelineOrchestratorRebalance, usePipelineOrchestratorReconcileFromDisk, usePipelineOrchestratorRemoveAgentSettings, usePipelineOrchestratorRequestOccupancyLook, usePipelineOrchestratorResetNodePipelineDefaults, usePipelineOrchestratorResolvePipeline, usePipelineOrchestratorResumeForStorageMigration, usePipelineOrchestratorSetAgentCapabilities, usePipelineOrchestratorSetAgentDecodeLimits, usePipelineOrchestratorSetAgentInferenceDevices, usePipelineOrchestratorSetAgentMaxCameras, usePipelineOrchestratorSetAgentReachableHost, usePipelineOrchestratorSetCameraDetectionSource, usePipelineOrchestratorSetCameraSensors, usePipelineOrchestratorSetCameraStepSettings, usePipelineOrchestratorSetCameraStepToggle, usePipelineOrchestratorSetCameraSwitch, usePipelineOrchestratorSetCapabilityBinding, usePipelineOrchestratorSetLoadBalancingShares, usePipelineOrchestratorSetNodeStepSettings, usePipelineOrchestratorSetPipelineDevicePin, usePipelineOrchestratorSetShareSource, usePipelineOrchestratorStartNodeBenchmark, usePipelineOrchestratorSuggestShares, usePipelineOrchestratorUnassignAudio, usePipelineOrchestratorUnassignPipeline, usePipelineRunnerAbortNodeBench, usePipelineRunnerAttachCamera, usePipelineRunnerDetachCamera, usePipelineRunnerGetAllCameraMetrics, usePipelineRunnerGetCameraMetrics, usePipelineRunnerGetLocalCameras, usePipelineRunnerGetLocalLoad, usePipelineRunnerGetLocalMetrics, usePipelineRunnerGetNativeCrop, usePipelineRunnerGetNodeBenchStatus, usePipelineRunnerGetParkedTrackFrame, usePipelineRunnerParkTrackFrame, usePipelineRunnerReleaseParkedTrackFrames, usePipelineRunnerReportMotion, usePipelineRunnerRequestOccupancyBurst, usePipelineRunnerRunDetailSubtree, usePipelineRunnerRunStatelessStep, usePipelineRunnerStartNodeBench, usePlateGalleryAssignPlate, usePlateGalleryAssignPlates, usePlateGalleryCorrectPlateText, usePlateGalleryCreateVehicle, usePlateGalleryDeletePlate, usePlateGalleryDeleteVehicle, usePlateGalleryGetPlateByTrack, usePlateGalleryGetPlateMedia, usePlateGalleryListPlates, usePlateGalleryListVehicleSamples, usePlateGalleryListVehicles, usePlateGalleryRemoveVehicleSample, usePlateGalleryRenameVehicle, usePlateGallerySearchPlates, usePlateGallerySuggestPlateClusters, usePlateGalleryUnassignPlate, usePlateGalleryUnassignPlates, usePlatformProbeGetCapabilities, usePlatformProbeGetHardware, usePlatformProbeRescanAccelerators, usePlatformProbeResolveHwAccel, usePlatformProbeResolveInferenceConfig, usePlayerOverlayLayer, usePlayerOverlayLayers, usePlayerToolbarButton, usePlayerToolbarButtons, usePowerMeterGetStatus, usePowerSourceForceRestart, usePowerSourceGetStatus, usePowerSourcePowerOff, usePowerSourcePowerOn, usePresenceGetStatus, usePressureSensorGetStatus, usePrivacyMaskGetOptions, usePrivacyMaskGetStatus, usePrivacyMaskSetAudioEnabled, usePrivacyMaskSetMask, usePrompt, usePtzAutotrackGetSettings, usePtzAutotrackGetStatus, usePtzAutotrackSetEnabled, usePtzAutotrackSetSettings, usePtzCaptureHomeHere, usePtzContinuousMove, usePtzDeletePreset, usePtzGetHomePreset, usePtzGetHomeReturn, usePtzGetOptions, usePtzGetPosition, usePtzGetPresets, usePtzGetStatus, usePtzGoHome, usePtzGoToPreset, usePtzMove, usePtzSavePreset, usePtzSetAutofocus, usePtzSetHomePreset, usePtzSetHomeReturn, usePtzStop, useRebootReboot, useRecordEntriesDeleteEntry, useRecordEntriesListEntries, useRecordEntriesListEntryKinds, useRecordEntriesPutEntry, useRecordedPlayback, useRecordingArchiveApplyDeviceSettingsPatch, useRecordingArchiveCancelRelocateJob, useRecordingArchiveCancelStorageMigrationMove, useRecordingArchiveDeleteFootprint, useRecordingArchiveGetAvailabilityBatch, useRecordingArchiveGetDaysWithRecordingsBatch, useRecordingArchiveGetDeviceConfig, useRecordingArchiveGetDeviceLiveContribution, useRecordingArchiveGetDeviceSettingsContribution, useRecordingArchiveGetPlacement, useRecordingArchiveGetRelocateResidue, useRecordingArchiveGetStatus, useRecordingArchiveGetStorageMigrationMoveStatus, useRecordingArchiveGetStorageUsage, useRecordingArchiveListOpsLog, useRecordingArchiveListRelocateJobs, useRecordingArchiveLocateSegment, useRecordingArchivePauseForStorageMigration, useRecordingArchivePlanStorageRebalance, useRecordingArchivePruneFootage, useRecordingArchiveReadGopBytes, useRecordingArchiveReadSegmentBytes, useRecordingArchiveReadWindowBytes, useRecordingArchiveReconcileLedgerAgainstDisk, useRecordingArchiveRefreshStorageLocationsForMigration, useRecordingArchiveRelocateFootage, useRecordingArchiveRenderClip, useRecordingArchiveRenderGif, useRecordingArchiveRescanStorage, useRecordingArchiveResumeForStorageMigration, useRecordingArchiveSetDeviceConfig, useRecordingArchiveSetDevicePlacement, useRecordingArchiveStartStorageMigrationMove, useRecordingArchiveStartStorageRebalance, useRecordingExportCancelExport, useRecordingExportCreateExport, useRecordingExportDeleteExport, useRecordingExportGetDownloadUrl, useRecordingExportGetExport, useRecordingExportListExports, useRecordingExportReadExportBytes, useRecordingGetAvailability, useRecordingGetDaysWithRecordings, useRecordingGetPlayback, useRecordingGetPlaybackOptions, useRecordingListSources, useRecordingOnboardGetOptions, useRecordingOnboardGetStatus, useRecordingOnboardSetSettings, useRecordingSignalGetStatus, useRemoteComponent, useRemoteGetConfig, useRemoteLayoutComponentsListComponents, useRemoteListCommands, useRemoteSendCommand, useRemoteSendMediaCommand, useRemoteSetConfig, useRoleDisplayDefaults, useRunningStateGetStatus, useSceneMonitorCaptureReference, useSceneMonitorCreateScene, useSceneMonitorDeleteReference, useSceneMonitorDeleteScene, useSceneMonitorGetStatus, useSceneMonitorListScenes, useSceneMonitorListScenesBatch, useSceneMonitorRecheckNow, useSceneMonitorResetScene, useSceneMonitorUpdateScene, useSchedulersConflicts, useSchedulersCreate, useSchedulersDelete, useSchedulersGet, useSchedulersGetStatus, useSchedulersGetTraces, useSchedulersList, useSchedulersPreview, useSchedulersSetEnabled, useSchedulersUpdate, useScriptRunnerGetStatus, useScriptRunnerRun, useScriptRunnerStop, useScrubController, useSearchFieldHotkey, useServerManagementApplyServerUpdate, useServerManagementCheckServerUpdate, useServerManagementGetLaunchOverrides, useServerManagementGetServerPackageStatus, useServerManagementInstallDesktopUpdate, useServerManagementRestartServer, useServerManagementRollbackServerUpdate, useServerManagementSetLaunchOverrides, useSettingsStoreAggregate, useSettingsStoreCount, useSettingsStoreDeclareCollection, useSettingsStoreDelete, useSettingsStoreDeleteWhere, useSettingsStoreGet, useSettingsStoreHistogram, useSettingsStoreInsert, useSettingsStoreInsertMany, useSettingsStoreIsEmpty, useSettingsStoreQuery, useSettingsStoreSet, useSettingsStoreTransact, useSettingsStoreUpdate, useSettingsStoreUpdateWhere, useSettingsStoreUpsert, useSettingsStoreUpsertMany, useSmokeGetStatus, useSnapshotApplyDeviceSettingsPatch, useSnapshotGetDebugState, useSnapshotGetDeviceLiveContribution, useSnapshotGetDeviceSettingsContribution, useSnapshotGetSnapshot, useSnapshotGetSnapshotLinks, useSnapshotGetSnapshotOverview, useSnapshotGetStatus, useSnapshotInvalidateCache, useStationaryOverlay, useStorageAbortUpload, useStorageBeginDownload, useStorageBeginUpload, useStorageDelete, useStorageDeleteLocation, useStorageEndDownload, useStorageExists, useStorageFinalizeUpload, useStorageGetAvailableSpace, useStorageList, useStorageListDrainProgress, useStorageListLocationDeclarations, useStorageListLocations, useStorageListProviders, useStorageMigrationCancel, useStorageMigrationCleanupCancel, useStorageMigrationCleanupStart, useStorageMigrationCleanupStatus, useStorageMigrationDrain, useStorageMigrationHistory, useStorageMigrationMoverClearance, useStorageMigrationMovers, useStorageMigrationPlan, useStorageMigrationResidue, useStorageMigrationStart, useStorageMigrationStatus, useStorageRead, useStorageReadChunk, useStorageResolve, useStorageTestConfig, useStorageTestLocation, useStorageUpsertLocation, useStorageWrite, useStorageWriteChunk, useStoredGroupBy, useStreamBrokerAcquireEgressTranscode, useStreamBrokerApplyDeviceSettingsPatch, useStreamBrokerAssignProfile, useStreamBrokerFetchEventMedia, useStreamBrokerForgetDeviceHardware, useStreamBrokerGetAllRtspEntries, useStreamBrokerGetBrokerStats, useStreamBrokerGetDeviceAudioMute, useStreamBrokerGetDeviceLiveContribution, useStreamBrokerGetDeviceSettingsContribution, useStreamBrokerGetLiveViewerCounts, useStreamBrokerGetPreBufferInfo, useStreamBrokerGetRtspEntry, useStreamBrokerGetRtspPort, useStreamBrokerGetStreamUrl, useStreamBrokerGetStreamWithCodec, useStreamBrokerIsRtspEnabled, useStreamBrokerKillClient, useStreamBrokerListAllCameraStreams, useStreamBrokerListAllProfileSlots, useStreamBrokerListClients, useStreamBrokerProbeStream, useStreamBrokerProduceEventMedia, useStreamBrokerPublishCameraStream, useStreamBrokerPullAudioChunks, useStreamBrokerRegenerateRtspToken, useStreamBrokerReleaseEgressTranscode, useStreamBrokerReleaseStreamWithCodec, useStreamBrokerRenderPreBufferClip, useStreamBrokerReportStreamSignal, useStreamBrokerRestartProfile, useStreamBrokerRetractCameraStream, useStreamBrokerSetDeviceAudioMute, useStreamBrokerSetPreBufferDuration, useStreamBrokerSetRtspEnabled, useStreamBrokerSubscribeAudioChunks, useStreamBrokerUnassignProfile, useStreamBrokerUnsubscribeAudioChunks, useStreamCatalogGetCatalog, useStreamParamsGetConfigSchema, useStreamParamsGetOptions, useStreamParamsGetStatus, useStreamParamsSetProfile, useStreamSignalsListSignals, useSwitchGetStatus, useSwitchSetState, useSystem, useSystemDetectSiteLocation, useSystemFeatureFlags, useSystemForceRetentionCleanup, useSystemGetFailureContributions, useSystemGetLoadContributions, useSystemGetLoggingSettings, useSystemGetRequestCensus, useSystemGetRetentionConfig, useSystemGetSiteLocation, useSystemHealth, useSystemInfo, useSystemMutation, useSystemNetworkAddresses, useSystemQuery, useSystemSetLoggingSettings, useSystemSetRetentionConfig, useSystemSetSiteLocation, useTamperGetStatus, useTemperatureSensorGetStatus, useTemplateCreate, useTemplateDelete, useTemplateGet, useTemplateList, useTemplateUpdate, useTerminalSessionAdoptLegacyMonitor, useTerminalSessionClose, useTerminalSessionCreateInstance, useTerminalSessionDeleteInstance, useTerminalSessionListInstances, useTerminalSessionListLegacyCameras, useTerminalSessionListProfiles, useTerminalSessionListSessions, useTerminalSessionOpenSession, useTerminalSessionPullOutput, useTerminalSessionResize, useTerminalSessionSetInstanceEnabled, useTerminalSessionUpdateInstance, useTerminalSessionWriteInput, useThemeMode, useToastOnToast, useTrainingCanaryResult, useTrainingCancelJob, useTrainingDiscardResult, useTrainingGetJob, useTrainingGetJobResult, useTrainingListBaseModels, useTrainingListCanaryTargets, useTrainingListJobs, useTrainingPlanJob, useTrainingRegisterResult, useTrainingRollbackCanary, useTrainingStartJob, useTrainingStartJobBatch, useTurnProviderGetTurnServers, useUiText, useUnitPreferences, useUpdateGetStatus, useUpdateInstallUpdate, useUrlQueryParam, useUserManagementConfirmTotp, useUserManagementCreateUser, useUserManagementDeleteUser, useUserManagementDisableTotp, useUserManagementFindUserByExternalIdentity, useUserManagementGetAdminBootstrapStatus, useUserManagementGetTotpStatus, useUserManagementListExternalIdentities, useUserManagementListOauthSessions, useUserManagementListUsers, useUserManagementMigrateRawSecrets, useUserManagementOauthExchangeCode, useUserManagementOauthIssueCode, useUserManagementOauthRefresh, useUserManagementOauthVerifyAccessToken, useUserManagementResetPassword, useUserManagementRevokeOauthSession, useUserManagementSetUserScopes, useUserManagementSetupTotp, useUserManagementUnlinkExternalIdentity, useUserManagementUpdateUser, useUserManagementValidateCredentials, useUserManagementVerifyTotp, useVacuumControlGetStatus, useVacuumControlLocate, useVacuumControlPause, useVacuumControlReturnToBase, useVacuumControlSetFanSpeed, useVacuumControlStart, useVacuumControlStop, useValveClose, useValveGetStatus, useValveOpen, useValveSetPosition, useValveStop, useVibrationGetStatus, useVideoclipsDialClipStream, useVideoclipsGetClipPlayback, useVideoclipsGetPlaybackOptions, useVideoclipsListClips, useVideoclipsListSources, useVideoclipsOfferClipBytes, useVideoclipsReadClipBytes, useVodPlayback, useWaterHeaterGetStatus, useWaterHeaterSetAway, useWaterHeaterSetOperationMode, useWaterHeaterSetTargetTemp, useWeatherGetStatus, useWebrtcSessionAddIceCandidate, useWebrtcSessionApplyDownlinkProbe, useWebrtcSessionCloseSession, useWebrtcSessionCreateSession, useWebrtcSessionGetIceCandidates, useWebrtcSessionGetSessionDebug, useWebrtcSessionGetSessionState, useWebrtcSessionHandleAnswer, useWebrtcSessionHandleOffer, useWebrtcSessionHasAdaptiveBitrate, useWebrtcSessionListStreams, useWidget, useWidgetMetadata, useWidgetRegistry, useZoneAnalyticsGetCameraHistory, useZoneAnalyticsGetCurrentSnapshot, useZoneAnalyticsGetCurrentSnapshotBatch, useZoneAnalyticsGetUnzonedHistory, useZoneAnalyticsGetZoneHistory, useZoneEditing, useZoneRulesListRules, useZoneRulesSetRules, useZonesAddZone, useZonesListZones, useZonesRemoveZone, useZonesUpdateZone, Sailboat as ut, UtensilsCrossed as v, vacuumStateMeta, validateScopes, valveStateMeta, variantLabel, HardDrive as vn, ChevronDown as vr, Radar as vt, Undo2 as w, waterHeaterPhase, waterHeaterTint, weatherConditionMeta, weatherTint, withHiddenChart, withPanel, withResolvedParentDetail, withUseRootModel, withoutModelScopedFields, withoutPanel, Gauge as wn, Camera as wr, writeStoredGroupBy, Plus as wt, UserCheck as x, GripHorizontal as xn, Cat as xr, Power as xt, Users as y, Hand as yn, Check as yr, QrCode$1 as yt, Sunrise as z, Droplets as zn, BatteryLow as zr, MoveHorizontal as zt };
73752
+ export { Ship as $, CloudSnow as $n, Activity as $r, Lock as $t, Trash2 as A, AddProviderEntryDialog, AddonGlobalSettingsForm, AdminLinkQuickAction, AgentStepEditor, AlarmHeroCard, AlarmInlineControl as AlarmPanelInlineControl, FlashlightOff as An, AppShell, Bot as Ar, ArcKnob, Phone as At, AudioClassificationList, AudioLevelWaveform, AudioWaveform, AutomationHeroCard, AutomationInlineControl, AutotrackSection, Sunrise as B, BATTERY_BADGE_LOW_KEY, BATTERY_BADGE_NORMAL_KEY, BINARY_BATTERY_LOW_BELOW, BOOLEAN_STATES, BTN_COMPACT, BTN_COMPACT_DANGER, BTN_COMPACT_PRIMARY, BTN_COMPACT_WARNING, BackToStepsButton, Badge, BarSeries, BatteryBadge, Droplets as Bn, BottomSheet, BatteryLow as Br, Breadcrumb, BrightnessPanel, BrokerPickerSlotProvider, MoveHorizontal as Bt, Button, ButtonControl, ButtonHeroCard, Unlink2 as C, CENTER, CHART_SERIES_TOKENS, CHIP_ACTIVE, CHIP_BASE, CHIP_INACTIVE, CLASS_COLORS, COLUMN_BREAKPOINT_CLASS, COLUMN_PRIORITY, COMMIT_DEDUPE_TOLERANCE_MS, COMMIT_DEDUPE_WINDOW_MS, CONSUMABLE_LOW_PERCENT, CONTROL_CAP_NAMES, CONTROL_FILLS, CameraStreamPlayer, Card, ChartFrame, ChartPlaceholder, ChartSwatch, ChartWindowToggle, Checkbox, ChildSectionAccordion, ClimatePanel, Grid2x2 as Cn, CodeBlock, CollapsibleCard, ConfigFormBuilder, FormField as ConfigFormField, ConfigNotificationTargetMultiSelectFieldView, ConfigNotificationTargetSelectFieldView, ConfigSchemaField, ConfirmActionButton, ConfirmDialogProvider, ConsumableLevelBadge, ConsumablesPanel, ContainerChildrenProvider, ContainerPrimaryHero, ControlColumn, ControlHeroCard, ControlInlineControl, ControlPanel, CopyButton, CoverHeroCard, CoverInlineControl, CoverPanel, Cast as Cr, PowerOff as Ct, CustomFieldRenderersProvider, TriangleAlert as D, DATA_RECORDS_KIND_PARAM, DATA_RECORDS_OWNER_PARAM, DATA_RECORD_FACET_GROUPS, DEFAULT_COLOR, DEFAULT_PAGINATION_LABELS, DEFAULT_UNIT_PREFERENCES, DEVICE_COLUMNS, DEVICE_EXPORT_PAGE_SIZE_KEY, DEVICE_LIST_PAGE_SIZE_KEY, DEVICE_LIST_PAGE_SIZE_OPTIONS, DEVICE_NAME_FORMS, DEVICE_NAME_JOIN, DEVICE_PICKER_GROUP_STORAGE_KEY, DEVICE_ROLE_META, DEVICE_ROLE_NOUNS, DEVICE_TYPE_CONTROL, DEVICE_TYPE_META, DEVICE_TYPE_NOUNS, DataRecordsHub, DataTable, DataTableFilterBar, DataTablePager, DetectionCanvas, DetectionOverlay, DetectionResultTree, DevShell, DeviceActivityPanel, DeviceBatchToolbar, DeviceCard, DeviceContextProvider, DeviceExportPanel, DeviceExportSetup, DeviceFilterBar, DeviceFleetFromServer, DeviceFleetProvider, DeviceGrid, DeviceHistoryView, DeviceItem, DeviceList, DeviceMultiSelectField, DeviceName, DevicePicker, DeviceQuickDetailProvider, DeviceSelectField, DeviceSelectorPicker, DeviceStepMatrix, DevicesFailedLine, DevicesLoadingLine, DevicesWidenWarning, Dialog, DialogBody, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, DisclosureChevron, DiscoveryPanel, DisplayPaletteProvider, Funnel as Dn, DoorbellRecentPanel, Bus as Dr, Dropdown, DropdownContent, DropdownItem, DropdownTrigger, Plane as Dt, DummyHeroCard, DummyInline, Truck as E, EMPTY_DATA_TABLE_FILTER, EMPTY_HISTORY_PANELS, EVENT_KIND_ICONS, EmptyState, Gamepad2 as En, EndpointResultsCard, EndpointTestCard, EntryJsonSchemaForm, Cable as Er, ErrorBox, Play as Et, EventKindGlyph, EventStream, ExtensionsPanel, Timer as F, FALLBACK_SCOPE, FAST_ICON_GLYPHS, FILL, FLEET_LIST_GC_TIME_MS, FLEET_LIST_QUERY_KEY, FLEET_LIST_STALE_TIME_MS, FanHeroCard, FanInlineControl, FanPanel, FileInput, FilterBar, FloatingEventStream, FloatingLogStream, FloatingPanel, Eye as Fn, FormField$1 as FormField, Bell as Fr, Network as Ft, Sprout as G, GAP_INTERVAL_FACTOR, GRID_GAP, GRID_PAIRED, GRID_QUICK_STATS, GateBadge, GateControl, Dog as Gn, ArrowUp as Gr, GripTrack, GroupedModelSelector, GroupedTilePicker, Minimize2 as Gt, SunMedium as H, HISTORY_PAGE_PATH, HISTORY_PANELS_NAMESPACE, HISTORY_SELECTION_MAX, HISTORY_WINDOW_IDS, HISTORY_WINDOW_MS, HOST_WIDGETS, HUB_SESSION_RUN_MS, HistoryChart, HistoryWindowBar, HlsVideo, Download as Hn, HotkeyProvider, HotkeyScope, HoverZoomImage, Bath as Hr, Moon as Ht, HubSessionTestCard, HumidifierHeroCard, HumidifierInlineControl, TimerOff as I, INPUT_COMPACT, INPUT_SHELL, IconAction, IconButton, IconPicker, ImageHeroCard, ImageInlineControl, ImageSelector, EyeOff as In, InferenceConfigSelector, Input, BellRing as Ir, Navigation as It, ItemFormDialog, Smartphone as J, Cpu as Jn, ArrowLeft as Jr, Menu as Jt, Sparkles as K, KebabMenu, KeyValueList, Database as Kn, ArrowUpToLine as Kr, Mic as Kt, Thermometer as L, LIST_ROW, Label, LawnMowerHeroCard, LawnMowerInlineControl, LayeredSettingsForm, LightHeroCard, LightInlineControl, ExternalLink as Ln, LockHeroCard, LockInlineControl, LockPanel, LogStream, LoginForm, Battery as Lr, Music as Lt, Tractor as M, MEDIA_GRID, MINUTES_PER_DAY, MODE_COLOR, MaskShapeCanvas, MediaCard, MediaGrid, MediaPlayerHeroCard, MediaPlayerInlineControl, MediaPlayerPanel, Film as Mn, MobileDrawer, ModelPicker, MotionZonesSettings, Blinds as Mr, PawPrint as Mt, ToggleRight as N, NAVIGATION_DRIVE_INTERVAL_MS, NODE_COLOR_IDS, NatResultCard, NavigationPanel, NetworkLinkBadge, Feather as Nn, NodeMultiSelectField, NodePicker, NodeSelectField, NotificationTargetSelectField, NotificationTargetsField, Bird as Nr, Pause as Nt, TrendingDown as O, OCCUPANCY_KEY, OPTION_SELECT_SEARCH_MIN_OPTIONS, OfflineBadge, Footprints as On, OptionSelect, Bug as Or, Pipette as Ot, ToggleLeft as P, PAGE_SIZE_ALL, PHASE_CONFIG, PICKER_CHIP_LIMIT, PICKER_DEFAULT_GROUP_BY, PICKER_GROUP_BY_MODES, PICKER_GROUP_COLLAPSE_AT, PICKER_NONE_KEY, PICKER_NOUN_PLURAL, PICKER_NO_FILTERS, PICKER_PAGE_SIZE, PICKER_SEARCH_DEBOUNCE_MS, PICKER_WINDOW, PRIORITY, PTZOverlay, PageHeader, PageShell, PageSizeSelect, Pagination, PasswordInput, PhaseIcon, PipelineBuilder, PipelineRuntimeSelector, PipelineStep, PlaceholderChipField, PlayerOverlaysProvider, Fan as Pn, Popover, PopoverContent, PopoverRowAction, PopoverTrigger, Bike as Pr, PrimaryChildPicker, PrivacyMaskSettings, ProviderBadge, ProviderEntryPills, Package as Pt, PtzPanel, Siren as Q, CloudSun as Qn, AirVent as Qr, QrCode, Mail as Qt, QuantityValueInput, Target as R, RECONNECT_POLICY, RECORDED_PLAYBACK_MODES, RESOLUTION_BUCKET_MS, RIGHT, ROI_AREA_WARN_FRACTION, ROLE_DESCRIPTOR, ROOT_DETECTOR_STEP_ID, RadialGauge, Radio, RecordEntriesPanel, RecordedPlaybackProvider, RecordingPanel, ResponseLog, RetrainReviewBadge, Eraser as Rn, RoleDisplayDefaultsFromServer, RoleDisplayDefaultsProvider, RoleNodePill, RootModelSourceControl, RootSuppliedModelNote, BatteryWarning as Rr, Move as Rt, RunReport, RunningBadge, RunningStatusLine, Upload as S, SCENE_CAPTURE_VARIANTS, SECRET_MASK_PLACEHOLDER, SECRET_REVEAL_MS, SECTION_BODY, SECTION_CARD, SECTION_HEADER, SETTING_ROW, SETTING_ROW_LABEL, SETTING_ROW_STACK_BREAKPOINT, SETTING_ROW_VALUE, SETTING_ROW_VALUE_TEXT, SNAPSHOT_MEDIA_PATH, SPLIT_PANEL_OUTER, SPLIT_PANEL_SIDE, STACK_GAP, STATE_COLOR, STEP_DOCK_WIDTH_PX, SUBJECT_PATH_DWELL_EPS, SUBJECT_PATH_FULL_FRAME_COVERAGE, SUBJECT_PATH_MAX_POINTS, SceneMonitorEditor, ScopePicker, ScriptHeroCard, ScriptInlineControl, ScrollArea, SecretFieldControl, SecretRevealProvider, SectionCard, SectionToolbar, SectionedPage, SegmentedChoice, Select, SelectedChip, SemanticBadge, SendFrameToTrainingButton, SensorHeroCard, SensorInlineControl, SensorValueAtom, Separator, SettingRow, Sidebar, SidebarItem, Skeleton, SlideToggle, Slider, GripHorizontal as Sn, SnapshotButton, SortHeaderButton, Sparkline, Cat as Sr, Power as St, StableTabPanel, StatCard, StateTimeline, StateValuesStream, StatusBadge, StepDetailDock, StepInspectorPanel, StepModelRow, StepTimings, Stepper, StorageRecordsPanel, StreamBrokerSelector, StreamDebugOverlay, StreamPanel, Switch, SwitchHeroCard, SwitchInlineControl, SwitchPanel, SystemProvider, Type as T, TABLE_SCROLL_MAX_H, TEMPERATURE_SCALES, TEXT_FIELD_LABEL, TEXT_HINT, TEXT_METRIC, TEXT_SECTION_LABEL, TEXT_VALUE, TIMEZONES, Tabs, TabsContent, TabsList, TabsTrigger, TapToggle, Textarea, ThemeProvider, ThermostatHeroCard, ThermostatInlineControl, TimeSeriesChart, TimelineSlider, TimezoneSelector, Gauge as Tn, Tooltip, TooltipContent, TooltipTrigger, Camera as Tr, TrainingBaseModelPicker, TrainingCollectionPicker, Plus as Tt, Star as U, UNIT_PREFERENCES_NAMESPACE, UiTextProvider, UiTrans, DoorOpen as Un, UnitPicker, UnitPreferencesFromServer, UnitPreferencesProvider, Ban as Ur, MonitorPlay as Ut, Sun as V, VacuumHeroCard, VacuumInlineControl, ValueReadout, ValveHeroCard, ValveInlineControl, VersionBadge, ViewSwitch, Droplet as Vn, VodPlaybackProvider, BatteryFull as Vr, MousePointerClick as Vt, Square as W, WaterHeaterHeroCard, WaterHeaterInlineControl, WeatherHeroCard, WeatherInlineControl, WidgetMetricCard, WidgetPanel, WidgetRegistryProvider, WidgetSlot, DoorClosed as Wn, Baby as Wr, Minus as Wt, SkipForward as X, Cog as Xn, ArrowDownToLine as Xr, Maximize2 as Xt, SlidersHorizontal as Y, Copy as Yn, ArrowDown as Yr, Megaphone as Yt, SkipBack as Z, Cloud as Zn, ZoneEditingProvider, AlarmSmoke as Zr, MapPin as Zt, Vibrate as _, Heater as _n, ChevronRight as _r, Radio$1 as _t, Wrench as a, acceleratorLabel, acceleratorShortLabel, agentColumnKey, alignSeries, allDeviceTypeFilterOptions, Link2 as an, anchorNow, applyFleetQueryDefaults, applyPickerFilters, CircleX as ar, ariaSortForColumn, assignNodeColorId, Settings as at, axisTicks, User as b, badgeFor, binaryBatteryIsLow, bindsToModel, Hand as bn, booleanLabels, boundsInPicked, Check as br, QrCode$1 as bt, bucketTotals, buildColorByNodeId, buildDataRecordRows, buildPeerConnectionConfig, buildStepTreeFromSchema, buildSubjectPath, buildTimeSeriesModel, Wifi as c, catalogHasDraft, chartKeys, chartSeriesStyle, childEntityId, childListName, chipOverflow, chunk, clampMinute, classifyAddressScope, classifyCapability, classifySessionVerdict, clearPickerGroup, clusterRootModelIds, cn, colorIdForNode, columnsForContext, compareSrflxMappings, computePageButtons, consumableItemLevel, consumableLevelBarClass, consumableLevelLabel, consumableLevelVariant, containerChildToRef, countableDevices, coverHighlight, coverageLine, CirclePlus as cr, createAddonI18n, createSharedContext, createTheme, ScrollText as ct, currentAddonLanguage, cursorFractionFor, WifiLow as d, darkColors, dataRecordContents, dataRecordKey, dataRecordSearchText, dataRecordType, dataTableFacetGroups, dataTableFacets, decodeCustomWindow, decodeSeriesRef, defaultAxisSpec, defaultOfField, defaultSelectClusterRoots, defaultSingleClusterRoot, defaultTheme, defaultUiText, deriveDeviceKind, deriveWebrtcDebugStats, describeDeviceSelector, detectPlatform, deviceIntegrationResolver, deviceListStateOf, deviceMatchesFilter, deviceNameNouns, deviceOptionLabel, deviceRoleMeta, deviceRoleMetaOf, deviceTypeLabel, deviceTypeMeta, deviceTypeMetaOf, devicesToOptions, Info as dn, dockBox, CircleCheck as dr, draftFromQuery, Sailboat as dt, effectivePageSize, emptyDevicesWidens, emptySessionRun, LockOpen as en, encodeCustomWindow, encodeSeriesRef, energyBuckets, ensureMfHostInit, CloudRain as er, Shield as et, eventKindLabel, WifiHigh as f, filterDataTableRows, filterDeviceOptions, filterOccupancyLines, filterOptions as filterOptionSelectOptions, filterPickerDevices, finalizeSessionRun, findTimezone, flattenPickerGrouping, flattenPickerRows, fleetViewOf, Inbox as fn, foldDeviceName, formatChartBytes, formatChartNumber, formatChartValue, formatControlDateTime, formatDeviceName, formatLastSeen, formatNumeric, formatSettingValue, formatSpan, formatTimeLabel, CircleCheckBig as fr, freezeVerdict, Router as ft, fuzzyMatch, Volume2 as g, gapThresholdMs, getClassColor, getPhaseVisual, History as gn, ChevronUp as gr, groupAgentColumns, groupChildrenByLayout, groupDeviceSeries, groupPickerDevices, groupPickerDevicesBy, RefreshCw as gt, VolumeX as h, hardwareLabel, historyPageHref, House as hn, ChevronsDownUp as hr, RotateCcw as ht, hubOrigin, hubPath, hubUrl, hubWsUrl, humanDuration, humanizeName, humidifierTint, X as i, iconGlyphsFailed, iconGlyphsLoaded, ListChecks as in, indexDeviceNames, initialScrubState, insertAtSelection, Clapperboard as ir, isAbsentProvider, isByteUnit, isConsumableLevelField, isDataTableFilterActive, isDeviceNameStock, isDrawableSubjectPath, isFieldVisible, isGroupExpanded, isHistoryWindowId, isKeychainFieldValue, isModelScopedField, isPickableUnit, isRedactedSecret, isRefusal, isSecretField, isValueField, Share2 as it, TrainFront as j, Flame as jn, Bone as jr, Pencil as jt, TrendingUp as k, Flashlight as kn, Box as kr, Pin as kt, WifiZero as l, lawnMowerActivityMeta, lightColors, linePoints, LayoutGrid as ln, loadIconGlyphs, loadRemoteBundle, CirclePause as lr, Scan as lt, lucideExportName, WashingMachine as m, makeScrubBridge, mapRootDetectorPlacements, matchesCombo, mergeSecretForSubmit, metadataEntries, metadataString, minuteFromPointer, ImageOff as mn, mountAddonPage, mountPath, ChevronsUpDown as mr, RotateCw as mt, ZoomIn as n, nextGridPosition, nextReconnectAction, nextSort, nextSortDirection, nextTableSort, niceMax, niceRange, LoaderCircle as nn, nodeColorClass, nodeSoftBgClass, nodeTextColorClass, normalizeForSearch, normalizeLanguage, normalizeSelection, nounSpecFor, CloudFog as nr, ShieldCheck as nt, Workflow as o, occupancyFacets, occupancyLines, offListSelections, Lightbulb as on, openTopLayer, optionSearchText as optionSelectSearchText, CircleStop as or, orphanDeviceLabel, Server as ot, outsideBounds, overrideEntityIdFromLink, Waves as p, pageRows, pageSizeLabel, paginateRows, parentDetailOf, parseCapKey, parseCombo, parseConsumableLevel, parseIceCandidate, parsePickerGroupBy, parseProducerKey, parseRecordedServerMessage, partitionSelected as partitionOptionSelectSelected, partitionSuggested, pickerFacetFilterShown, pickerFacetKey, pickerFacetOptions, pickerFiltersActive, pickerGroupKey, pickerHiddenSelectedCount, pickerLocationKey, pickerQueryTokens, pickerRowFacts, pickerSearchText, pickerZoneFilterSuspended, pinnedStreamChoices, placePopover, Image as pn, CircleAlert as pr, preferenceForQuantity, previousWindow, projectSubjectPath, providerIcons, Route as pt, Snowflake as q, Crosshair as qn, ArrowRight as qr, MessageSquare as qt, quantityStoredUnit, quantityUnitChoices, Zap as r, readHistory, readHistoryPanels, readItemId, readStoredGroupBy, readUnitPreferences, reduceSessionRun, registerAddonBundle, renderMarkup, renderTagged, resetHubMountForTests, resetPickerFilters, resolveContainerPrimary, resolveControlAlign, resolveDeviceControl, resolveDeviceIntegration, resolveDeviceLabel, resolveDisplayIcon, resolveEffectiveDefaultModel, resolveEffectiveStepModel, resolveEventKindIcon, resolveHistoryWindow, resolveSearchable as resolveOptionSelectSearchable, resolveParentNames, resolvePrimaryChild, resolveSelectedDevices, resolveSensorDisplay, resolveStepDefaultModel, retrainReviewBadgeLook, List as rn, roiTooLarge, rootSourceState, routerBasename, Clock as rr, ShieldAlert as rt, runningDurationSince, runningStatusParts, Wind as s, sameDeviceName, sameLocationSuggestions, scrubReducer, searchSteps, secretDisplayValue, secretSubmitValue, segmentsFromChanges, selectPickerGroup, selectedDeviceOptions, serializeRecordedCommand, seriesRefId, settingsModelIdFor, sharedGapSpans, shiftPoints, shouldCommit, shouldEmit, shouldShowAddNewFooter, shouldShowUseQueryRow, shouldUseSingleNode, showsNoCamerasHint, Leaf as sn, snapMinute, sortRows, sortRowsByColumn, CircleQuestionMark as sr, Search as st, stackBuckets, stackSeries, stateAt, stateRow, stateStyle, statusIcons, statusLine, stepFieldDomId, stepHasModelForFormat, stepLocalFields, stepModelOptions, storedToPicked, stripDeviceParentPrefix, stripParentNamePrefix, subjectPathSampleFromBox, subjectPathSvgPoints, summarizeHubCandidates, swatchFillClass, swatchLineClass, ZoomOut as t, tabForSelector, themeToCss, themeToRootCss, timeInState, LocateFixed as tn, toStationaryOverlayBox, toggleDataTableFacet, toggleDataTableGroupFacet, togglePickerDevice, togglePickerKey, CloudLightning as tr, trainingRefusalText, translateAddonKey, trpc, ShieldOff as tt, typeLabel, typedToStored, WifiOff as u, Laugh as un, unitAxes, CircleDot as ur, useAccessoriesGetStatus, useAccessoriesSetChildHidden, useAccountUnitPreferences, useActionSourceListActions, useActionSourceRunAction, useActionSourceStopAction, useActionsCreate, useActionsDelete, useActionsGet, useActionsGetLinks, useActionsGetTraces, useActionsList, useActionsListForCamera, useActionsRun, useActionsSetLinks, useActionsStop, useActionsUpdate, useAddonPagesListPages, useAddonSettingsGetDeclaredSettingsKeys, useAddonSettingsGetDeviceSettings, useAddonSettingsGetGlobalSettings, useAddonSettingsGetIntegrationFormSchema, useAddonSettingsGetIntegrationSettings, useAddonSettingsUnsetStoredSettingsKeys, useAddonSettingsUpdateDeviceSettings, useAddonSettingsUpdateGlobalSettings, useAddonT, useAddonWidgetsListWidgets, useAddonsApplyAutoUpdateToAll, useAddonsCancelJob, useAddonsCustom, useAddonsForceRefresh, useAddonsGetAddonAutoUpdate, useAddonsGetAutoUpdateSettings, useAddonsGetJob, useAddonsGetLastRestart, useAddonsGetLogs, useAddonsGetPackageDocs, useAddonsGetVersions, useAddonsInstallPackage, useAddonsList, useAddonsListCapabilityProviders, useAddonsListFrameworkPackages, useAddonsListInstallations, useAddonsListJobs, useAddonsListPackages, useAddonsListUpdates, useAddonsOnAddonLogs, useAddonsReloadPackages, useAddonsRestartAddon, useAddonsRestartServer, useAddonsRetryLoad, useAddonsRollbackPackage, useAddonsSearchAvailable, useAddonsSetAddonAutoUpdate, useAddonsSetAutoUpdateSettings, useAddonsSetCapabilityProviderEnabled, useAddonsStartJob, useAddonsUninstallPackage, useAddonsUpdatePackage, useAirQualitySensorGetStatus, useAlarmPanelArm, useAlarmPanelDisarm, useAlarmPanelGetStatus, useAlarmPanelTrigger, useAlert, useAlertsDismiss, useAlertsEmit, useAlertsGetUnreadCount, useAlertsList, useAlertsMarkAllRead, useAlertsMarkRead, useAlertsUpdate, useAllWidgets, useAmbientLightSensorGetStatus, useAudioAnalysisApplyDeviceSettingsPatch, useAudioAnalysisGetDeviceLiveContribution, useAudioAnalysisGetDeviceSettingsContribution, useAudioAnalysisResolveDeviceSettings, useAudioAnalyzerAnalyseChunk, useAudioAnalyzerAttachDevice, useAudioAnalyzerClassify, useAudioAnalyzerDetachDevice, useAudioAnalyzerDispose, useAudioAnalyzerIsReady, useAudioAnalyzerReprobeAudioEngine, useAudioCodecCanHandle, useAudioCodecCloseSession, useAudioCodecCreateDecodeSession, useAudioCodecCreateEncodeSession, useAudioCodecFlushEncode, useAudioCodecListActiveSessions, useAudioCodecListSupportedCodecs, useAudioCodecPullEncoded, useAudioCodecPullPcm, useAudioCodecPushEncodedFrame, useAudioCodecPushPcm, useAudioMetricsGetCurrentSnapshot, useAudioMetricsGetHistory, useAutomationControlDisable, useAutomationControlEnable, useAutomationControlGetStatus, useAutomationControlTrigger, useBackupCancel, useBackupCheckBackupKey, useBackupDelete, useBackupDeleteSchedule, useBackupDisableEncryption, useBackupGetEncryption, useBackupGetEntries, useBackupList, useBackupListArchives, useBackupListAvailableDatabases, useBackupListDestinations, useBackupListLocations, useBackupListRuns, useBackupListSchedules, useBackupPreviewSchedule, useBackupRestore, useBackupSetupEncryption, useBackupTrigger, useBackupUpsertDestinationPolicy, useBackupUpsertSchedule, useBatteryGetStatus, useBatteryWakeForStream, useBinaryGetStatus, useBrightnessGetStatus, useBrightnessSetBrightness, useBrokerAdd, useBrokerGet, useBrokerGetBrokerConfig, useBrokerGetSettings, useBrokerGetSettingsSchema, useBrokerGetState, useBrokerGetStatus, useBrokerList, useBrokerListProviders, useBrokerPickerSlot, useBrokerPublish, useBrokerRemove, useBrokerSetSettings, useBrokerSubscribe, useBrokerTestConnection, useBrokerTestSettings, useBrokerUnsubscribe, useButtonPress, useCalendarsGetPreferences, useCalendarsListCalendars, useCalendarsListEvents, useCalendarsSetCalendarPreference, useCameraCredentialsGetCredentials, useCameraCredentialsGetStatus, useCameraGridLayoutApplyDeviceSettingsPatch, useCameraGridLayoutGetDeviceLiveContribution, useCameraGridLayoutGetDeviceSettingsContribution, useCameraGridLayoutGetLayout, useCameraGridLayoutSaveLayout, useCameraPipelineConfigApplyDeviceSettingsPatch, useCameraPipelineConfigGetDeviceLiveContribution, useCameraPipelineConfigGetDeviceSettingsContribution, useCameraStreamsGetBrokerStreams, useCameraStreamsGetCameraStreams, useCameraStreamsGetProfileRtspEntries, useCameraStreamsGetRtspEntries, useCameraStreamsPickStream, useCapabilityPresence, useCarbonMonoxideGetStatus, useClassPainter, useClimateControlGetStatus, useClimateControlSetFanMode, useClimateControlSetMode, useClimateControlSetPreset, useClimateControlSetSwingHorizontal, useClimateControlSetSwingVertical, useClimateControlSetTarget, useClimateControlSetTargetHumidity, useClimateControlSetTargetRange, useClusterNodes, useClusterTopology, useColorGetStatus, useColorSetColor, useConfirm, useConnectionTestDescribeTest, useConnectionTestTestSettings, useConnectivityGetStatus, useConsumablesGetStatus, useConsumablesReset, useContactGetStatus, useContainerChildren, useControlGetStatus, useControlSetValue, useCoreBlocksCompile, useCoreBlocksCreate, useCoreBlocksCreateComposition, useCoreBlocksDelete, useCoreBlocksGet, useCoreBlocksGetAutomationRunState, useCoreBlocksGetBlockSettings, useCoreBlocksGetComposition, useCoreBlocksGetCustomization, useCoreBlocksGetTraces, useCoreBlocksGetTypeDefs, useCoreBlocksList, useCoreBlocksListComposableCaps, useCoreBlocksListCompositions, useCoreBlocksMigrateRawSecrets, useCoreBlocksReportAutomationRun, useCoreBlocksRestart, useCoreBlocksSetEnabled, useCoreBlocksUpdate, useCoreBlocksUpdateBlockSettings, useCoreBlocksUpdateComposition, useCoreBlocksValidateComposition, useCoverClose, useCoverGetStatus, useCoverOpen, useCoverSetPosition, useCoverSetTiltPosition, useCoverStop, useCustomFieldRenderer, useDataTableFilter, useDayNightGetOptions, useDayNightGetStatus, useDayNightSetSettings, useDebouncedString, useDecoderGetInfo, useDecoderReprobeHwaccel, useDetectionPipelineApplyDeviceSettingsPatch, useDetectionPipelineGetDeviceLiveContribution, useDetectionPipelineGetDeviceSettingsContribution, useDevShell, useDevice, useDeviceAdminLink, useDeviceAdminLinkGetAdminLink, useDeviceAdoptionAdopt, useDeviceAdoptionGetCandidate, useDeviceAdoptionGetStatus, useDeviceAdoptionListCandidateFilters, useDeviceAdoptionListCandidates, useDeviceAdoptionRefresh, useDeviceAdoptionRelease, useDeviceAdoptionResync, useDeviceAutotrack, useDeviceBattery, useDeviceCapSlice, useDeviceCapability, useDeviceCredentialsDeleteDeviceCredential, useDeviceCredentialsGetDeviceCaStatus, useDeviceCredentialsGetDeviceCertificateSettings, useDeviceCredentialsListDeviceCredentials, useDeviceCredentialsRenameDeviceCredential, useDeviceCredentialsRevokeDeviceCredential, useDeviceCredentialsSetDeviceCertificateSettings, useDeviceCredentialsStartEnrollment, useDeviceDetections, useDeviceDiscoveryAdoptDevice, useDeviceDiscoveryGetStatus, useDeviceDiscoveryListDiscovered, useDeviceDiscoveryRefreshDiscovery, useDeviceDiscoveryReleaseDevice, useDeviceExportApplyDeviceSettingsPatch, useDeviceExportExposeDevice, useDeviceExportExposeEntity, useDeviceExportGetDeviceLiveContribution, useDeviceExportGetDeviceSettingsContribution, useDeviceExportGetStatus, useDeviceExportListExposedDevices, useDeviceExportListExposedEntities, useDeviceExportListSupportedDeviceKinds, useDeviceExportListSupportedEntityKinds, useDeviceExportUnexposeDevice, useDeviceExportUnexposeEntity, useDeviceExtensionListCandidates, useDeviceExtensionListSlots, useDeviceExtensionListSources, useDeviceExtensionSetSlot, useDeviceHistoryDeclareSeries, useDeviceHistoryDeleteOrphanSeries, useDeviceHistoryGetDeviceEnabled, useDeviceHistoryGetStatus, useDeviceHistoryListNodeSeries, useDeviceHistoryListOrphanSeries, useDeviceHistoryListSeries, useDeviceHistoryQuery, useDeviceHistoryQueryMany, useDeviceHistoryQueryNode, useDeviceHistoryRecord, useDeviceHistoryRecordBuckets, useDeviceHistorySetDeviceEnabled, useDeviceId, useDeviceLabel, useDeviceLabelById, useDeviceListPageSize, useDeviceManagerAddLocation, useDeviceManagerAdoptDevice, useDeviceManagerAdoptionAdopt, useDeviceManagerAdoptionCancelJob, useDeviceManagerAdoptionListCandidateFilters, useDeviceManagerAdoptionListCandidates, useDeviceManagerAdoptionListJobs, useDeviceManagerAdoptionRefresh, useDeviceManagerAdoptionRelease, useDeviceManagerAdoptionResync, useDeviceManagerAdoptionStartJob, useDeviceManagerAllocateDeviceId, useDeviceManagerApplyInitialMeta, useDeviceManagerCleanupDeletedDevicesData, useDeviceManagerCreateDevice, useDeviceManagerDisable, useDeviceManagerDiscoverAllProviders, useDeviceManagerDiscoverDevices, useDeviceManagerDiscoverProvider, useDeviceManagerDiscoveryProviders, useDeviceManagerEnable, useDeviceManagerGetAllBindings, useDeviceManagerGetBindings, useDeviceManagerGetBindingsBatch, useDeviceManagerGetChildren, useDeviceManagerGetChildrenBatch, useDeviceManagerGetConfigSchema, useDeviceManagerGetCreationSchema, useDeviceManagerGetDevice, useDeviceManagerGetDeviceAggregate, useDeviceManagerGetDeviceLiveInfoAggregate, useDeviceManagerGetDeviceSettingsAggregate, useDeviceManagerGetDeviceStatusAggregate, useDeviceManagerGetDeviceStatusAggregateBatch, useDeviceManagerGetLinkedDevices, useDeviceManagerGetLinkedDevicesBatch, useDeviceManagerGetRoleDisplayDefaults, useDeviceManagerGetSettingsSchema, useDeviceManagerGetStreamProfileMap, useDeviceManagerGetStreamSources, useDeviceManagerGetWireableFields, useDeviceManagerGetWrapperActivation, useDeviceManagerListAll, useDeviceManagerListBindableCapsForDeviceType, useDeviceManagerListDeletedSince, useDeviceManagerListDeviceIdsByCaps, useDeviceManagerListLocationDescriptions, useDeviceManagerListLocationIcons, useDeviceManagerListLocations, useDeviceManagerListPersistedByAddon, useDeviceManagerListSiteZones, useDeviceManagerListWrappersForCap, useDeviceManagerLoadConfig, useDeviceManagerLoadMeta, useDeviceManagerLoadRuntimeState, useDeviceManagerMigrateDevice, useDeviceManagerPersistConfig, useDeviceManagerProbeStreams, useDeviceManagerProviderCreationType, useDeviceManagerProviderDiscoveryParamsSchema, useDeviceManagerRegisterDevice, useDeviceManagerRemove, useDeviceManagerRemoveByIntegration, useDeviceManagerRemoveDevice, useDeviceManagerRemoveLocation, useDeviceManagerRemoveSiteZone, useDeviceManagerRenameLocation, useDeviceManagerRenameSiteZone, useDeviceManagerRunDeviceAction, useDeviceManagerSetChildLayout, useDeviceManagerSetDisabled, useDeviceManagerSetDisplay, useDeviceManagerSetIntegrationId, useDeviceManagerSetLinkDeviceId, useDeviceManagerSetLocation, useDeviceManagerSetLocationDescription, useDeviceManagerSetLocationIcon, useDeviceManagerSetLocationZone, useDeviceManagerSetMetadata, useDeviceManagerSetName, useDeviceManagerSetPrimaryChildEntityId, useDeviceManagerSetRole, useDeviceManagerSetRoleDisplayDefaults, useDeviceManagerSetSiteZone, useDeviceManagerSetStreamProfileMap, useDeviceManagerSetType, useDeviceManagerSetWrapperActive, useDeviceManagerTestCreationField, useDeviceManagerTestField, useDeviceManagerUpdateConfig, useDeviceManagerUpdateDeviceField, useDeviceManagerUpdateDeviceFieldsBatch, useDeviceNameIndex, useDeviceNameNouns, useDeviceNetworkLink, useDeviceOpsGetConfigEntries, useDeviceOpsGetRawState, useDeviceOpsGetSettingsSchema, useDeviceOpsGetStreamSources, useDeviceOpsRemoveDevice, useDeviceOpsRunAction, useDeviceOpsSetConfig, useDeviceProviderAdoptDiscoveredDevice, useDeviceProviderClassifyDiscoveryHits, useDeviceProviderCreateDevice, useDeviceProviderDiscoverDevices, useDeviceProviderGetChildCreationSchema, useDeviceProviderGetDevices, useDeviceProviderGetDiscoveryModes, useDeviceProviderGetDiscoveryParamsSchema, useDeviceProviderGetManualCreationType, useDeviceProviderGetStatus, useDeviceProviderReloadDevice, useDeviceProviderStart, useDeviceProviderStop, useDeviceProviderSupportsDiscovery, useDeviceProviderSupportsManualCreation, useDeviceProviderTestCreationField, useDeviceProxy, useDeviceQuickDetailOpen, useDeviceRunsGetCurrentRun, useDeviceRunsGetRun, useDeviceRunsListRuns, useDeviceSeriesList, useDeviceSnapshot, useDeviceSnapshotImage, useDeviceState, useDeviceStateClaimFields, useDeviceStateGetAllSnapshots, useDeviceStateGetCapSlice, useDeviceStateGetNativeCapSlice, useDeviceStateGetSnapshot, useDeviceStateListClaims, useDeviceStatePatchOwnedFields, useDeviceStateReleaseClaim, useDeviceStateSetCapSlice, useDeviceStateSlice, useDeviceStatusGetStatus, useDeviceWebrtc, useDevices, useDiscoveredOptions, useDishwasherGetOptions, useDishwasherGetStatus, useDishwasherPause, useDishwasherResume, useDishwasherSetChildLock, useDishwasherSetExtraDry, useDishwasherSetHalfLoad, useDishwasherSetHygienePlus, useDishwasherSetIntensiveZone, useDishwasherSetOption, useDishwasherSetPower, useDishwasherSetProgram, useDishwasherSetVarioSpeedPlus, useDishwasherStart, useDishwasherStop, useDisplayIconResolver, useDisplayPaletteGetPalette, useDisplayPaletteListPresets, useDisplayPaletteSetPalette, useDisplayPaletteView, useDoorbellEvents, useDoorbellGetStatus, useEnumSensorGetStatus, useEventEmitterGetStatus, useEventInvalidation, useEventStreamLatest, useEventStreamMap, useFaceGalleryAssignFace, useFaceGalleryAssignFaces, useFaceGalleryAuditIdentitySamples, useFaceGalleryCreateIdentity, useFaceGalleryDeleteFace, useFaceGalleryDeleteIdentity, useFaceGalleryGetFaceByTrack, useFaceGalleryGetFaceMedia, useFaceGalleryListIdentities, useFaceGalleryListIdentitySamples, useFaceGalleryListRecentFaces, useFaceGalleryRemoveSample, useFaceGalleryRenameIdentity, useFaceGallerySuggestFaceClusters, useFaceGalleryUnassignFace, useFaceGalleryUnassignFaces, useFanControlGetStatus, useFanControlSetDirection, useFanControlSetOscillating, useFanControlSetPercentage, useFanControlSetPreset, useFanPresetsApplyPreset, useFanPresetsCapturePreset, useFanPresetsGetPresets, useFanPresetsSetPresets, useFeatureProbeGetStatus, useFloodGetStatus, useGasGetStatus, useGroupActiveGetStatus, useGroupCommandsGetStatus, useGroupStatusGetStatus, useHeatingValveGetStatus, useHistoryPanels, useHistoryReader, useHistoryReads, useHotkey, useHumidifierGetStatus, useHumidifierSetMode, useHumidifierSetOn, useHumidifierSetTargetHumidity, useHumiditySensorGetStatus, useIconGlyphsVersion, useImageGetStatus, useImageSettingsGetOptions, useImageSettingsGetStatus, useImageSettingsSetSettings, useIntegrationsCreate, useIntegrationsDelete, useIntegrationsGet, useIntegrationsGetAvailableTypes, useIntegrationsGetByAddonId, useIntegrationsGetSettings, useIntegrationsList, useIntegrationsSetSettings, useIntegrationsTestConnection, useIntegrationsUpdate, useIntercomEndTalkSession, useIntercomGetStatus, useIntercomHandleAnswer, useIntercomPushTalkAudio, useIntercomStartSession, useIntercomStartTalkSession, useIntercomStopSession, useIrTransmitterGetInfo, useIrTransmitterSend, useIsMidWidth, useIsMobile, useItemFormUrl, useKeychainAdminAcknowledgeReset, useKeychainAdminDeleteOrphans, useKeychainAdminDownloadRecoveryKey, useKeychainAdminImportSecret, useKeychainAdminListAudit, useKeychainAdminListSecrets, useKeychainAdminPurgeRetiredKeys, useKeychainAdminResetKeychain, useKeychainAdminResetReport, useKeychainAdminReveal, useKeychainAdminRotateMasterKey, useKeychainAdminSetSystemSecret, useKeychainAdminStatus, useLawnMowerControlDock, useLawnMowerControlGetStatus, useLawnMowerControlPause, useLawnMowerControlStartMowing, useLiveBuffer, useLiveEvent, useLlmCancel, useLlmDeleteModel, useLlmDeleteProfile, useLlmGenerate, useLlmGenerateVision, useLlmGetDefaults, useLlmGetRuntimeStatus, useLlmGetUsage, useLlmInstallModel, useLlmListModelCatalog, useLlmListModels, useLlmListNodeModels, useLlmListProfileKinds, useLlmListProfiles, useLlmListRuntimeNodes, useLlmMigrateRawSecrets, useLlmResolveModelRef, useLlmSetDefault, useLlmStartRuntime, useLlmStopRuntime, useLlmTestProfile, useLlmUpsertProfile, useLocalNetworkAddCustomAddress, useLocalNetworkDownloadCa, useLocalNetworkGetAddresses, useLocalNetworkGetAllowedAddresses, useLocalNetworkGetConnectionEndpoints, useLocalNetworkGetHubAddresses, useLocalNetworkGetNotificationEndpoint, useLocalNetworkGetPreferred, useLocalNetworkGetScanSubnets, useLocalNetworkGetTlsStatus, useLocalNetworkGetViewerEndpoints, useLocalNetworkList, useLocalNetworkRegenerateCertificate, useLocalNetworkRemoveCustomAddress, useLocalNetworkResetAllowlistToBestMatch, useLocalNetworkRevertToGeneratedCertificate, useLocalNetworkScanNetwork, useLocalNetworkSetAddressRole, useLocalNetworkSetAllowedAddresses, useLocalNetworkSetNotificationEndpoint, useLocalNetworkSetScanSubnets, useLocalNetworkSetViewerEndpoints, useLocalNetworkUploadCertificate, useLocalNetworkUseStoredUploadedCertificate, useLockControlGetStatus, useLockControlLock, useLockControlOpen, useLockControlUnlock, useLockDoorSensor, useMediaPlayerGetStatus, useMediaPlayerNext, useMediaPlayerPause, useMediaPlayerPlay, useMediaPlayerPlayMedia, useMediaPlayerPrevious, useMediaPlayerSeek, useMediaPlayerSelectSource, useMediaPlayerSetMute, useMediaPlayerSetRepeat, useMediaPlayerSetShuffle, useMediaPlayerSetVolume, useMediaPlayerStop, useMeshNetworkGetStatus, useMeshNetworkJoin, useMeshNetworkLeave, useMeshNetworkListPeers, useMeshNetworkLogout, useMeshNetworkStartLogin, useMeshNetworkTestConnection, useMeterGetStatus, useMetricsProviderCollectSnapshot, useMetricsProviderGetAddonStats, useMetricsProviderGetCached, useMetricsProviderGetCpuTemperature, useMetricsProviderGetCurrent, useMetricsProviderGetDiskSpace, useMetricsProviderGetGpuInfo, useMetricsProviderGetLoadSeries, useMetricsProviderGetProcessStats, useMetricsProviderListAddonInstances, useMetricsProviderListNodeProcesses, useMotionDetectionAnalyze, useMotionDetectionApplyDeviceSettingsPatch, useMotionDetectionGetDeviceLiveContribution, useMotionDetectionGetDeviceSettingsContribution, useMotionDetectionRemoveCamera, useMotionDetectionReset, useMotionGetStatus, useMotionIsDetected, useMotionTriggerGetStatus, useMotionTriggerSetMotionTrigger, useMotionZonesGetOptions, useMotionZonesGetStatus, useMotionZonesSetZone, useMqttBrokerAddBroker, useMqttBrokerGetBrokerConfig, useMqttBrokerGetStatus, useMqttBrokerListBrokers, useMqttBrokerRemoveBroker, useMqttBrokerStartEmbeddedBroker, useMqttBrokerStopEmbeddedBroker, useMqttBrokerTestConnection, useNativeObjectDetectionGetOptions, useNativeObjectDetectionGetStatus, useNativeObjectDetectionSetEnabled, useNativeObjectDetectionSetSettings, useNavigation, useNavigationGetFeatures, useNavigationGetStatus, useNavigationGoToPoint, useNavigationListActions, useNavigationMove, useNavigationPlaySound, useNavigationRunAction, useNavigationSetLightLevel, useNavigationSetLightMode, useNavigationSetLightOn, useNavigationStop, useNetworkAccessGetEndpoint, useNetworkAccessGetStatus, useNetworkAccessListEndpoints, useNetworkAccessStart, useNetworkAccessStop, useNetworkLinkGetStatus, useNetworkQualityGetAllStats, useNetworkQualityGetDeviceStats, useNetworkQualityReportClientStats, useNodesClusterAddonStatus, useNodesDeployAddon, useNodesDirectory, useNodesExecuteQuery, useNodesGetCapUsageGraph, useNodesGetNodeAddons, useNodesRenameNode, useNodesRestartAddon, useNodesRestartNode, useNodesRestartProcess, useNodesSetProcessLogLevel, useNodesShutdownNode, useNodesTopology, useNodesUndeployAddon, useNotificationOutputDeleteTarget, useNotificationOutputDiscoverTargets, useNotificationOutputGetTarget, useNotificationOutputListTargetKinds, useNotificationOutputListTargets, useNotificationOutputProbeTargetConfig, useNotificationOutputSend, useNotificationOutputSetTargetEnabled, useNotificationOutputTestTarget, useNotificationOutputUpsertTarget, useNotificationRulesActivateAlarmProfile, useNotificationRulesCancelSnooze, useNotificationRulesCreateAlarmProfile, useNotificationRulesCreateRule, useNotificationRulesCreateSequence, useNotificationRulesCreateSnooze, useNotificationRulesDeleteAlarmProfile, useNotificationRulesDeleteRule, useNotificationRulesDeleteSequence, useNotificationRulesGetAlarmConfig, useNotificationRulesGetAlarmSensors, useNotificationRulesGetClipRetentionAsks, useNotificationRulesGetConditionCatalog, useNotificationRulesGetHistory, useNotificationRulesGetRule, useNotificationRulesGetRuleLastRuns, useNotificationRulesGetSequence, useNotificationRulesGetTemplateCatalog, useNotificationRulesListDeviceMutes, useNotificationRulesListRules, useNotificationRulesListSequences, useNotificationRulesListSnoozes, useNotificationRulesPreviewStateSummary, useNotificationRulesPreviewTemplate, useNotificationRulesRenameAlarmProfile, useNotificationRulesResolveArtifactUrl, useNotificationRulesSetAlarmConfig, useNotificationRulesSetDeviceMuted, useNotificationRulesSetRuleEnabled, useNotificationRulesTestRule, useNotificationRulesUpdateRule, useNotificationRulesUpdateSequence, useNotifierCancel, useNotifierGetStatus, useNotifierSend, useNumericSensorGetStatus, useOidcConnectionsConnectionFormSchema, useOidcConnectionsCreateConnection, useOidcConnectionsDeleteConnection, useOidcConnectionsListConnections, useOidcConnectionsUpdateConnection, useOptimisticSlice, useOptionalSystem, useOptionalWidgetRegistry, useOsdGetStatus, useOsdManagerClearSlotBinding, useOsdManagerCopyDeviceConfiguration, useOsdManagerDeleteTemplate, useOsdManagerGetConditionSupport, useOsdManagerGetDeviceOsd, useOsdManagerGetSourceCatalog, useOsdManagerListTemplates, useOsdManagerPreviewSlot, useOsdManagerRenderDevice, useOsdManagerSetSlotBinding, useOsdManagerSetSlotCameraEnabled, useOsdManagerUpsertTemplate, useOsdSetOverlay, usePTZ, usePersistedDisclosure, usePersistedPageSize, usePetFeederCallPet, usePetFeederCancelFeed, usePetFeederFeed, usePetFeederGetStatus, usePetFeederMarkFoodReplenished, usePetFeederPlaySound, usePetFeederResetDesiccant, usePetFeederSetChildLock, usePetFeederSetFeedSound, usePetFeederSetIndicatorLight, usePetFeederSetVolume, usePetFountainGetStatus, usePetFountainResetDailyConsumption, usePetFountainSetPump, usePetFountainSetPumpInterval, usePetFountainSetPumpOffMinutes, usePetFountainSetPumpOnMinutes, usePickerSiteZones, usePipelineAnalyticsAddRetrainFrameFromRecording, usePipelineAnalyticsAddRetrainFramesToCollection, usePipelineAnalyticsApplyDeviceSettingsPatch, usePipelineAnalyticsBackfillRetrainOrigins, usePipelineAnalyticsCancelRelocateMedia, usePipelineAnalyticsCancelStorageMigrationMove, usePipelineAnalyticsClearTrackRelation, usePipelineAnalyticsClearTracks, usePipelineAnalyticsCompleteRetrainTrack, usePipelineAnalyticsCountRelocatableMedia, usePipelineAnalyticsCountUnstampedEventMedia, usePipelineAnalyticsCreateRetrainCollection, usePipelineAnalyticsDeleteDeviceEvents, usePipelineAnalyticsDeleteRetrainCollection, usePipelineAnalyticsDeleteTracks, usePipelineAnalyticsDeselectRetrainFrame, usePipelineAnalyticsGetActiveTracks, usePipelineAnalyticsGetAudioEvents, usePipelineAnalyticsGetDeviceLiveContribution, usePipelineAnalyticsGetDeviceSettingsContribution, usePipelineAnalyticsGetEventDensity, usePipelineAnalyticsGetEventDensityBatch, usePipelineAnalyticsGetEventMedia, usePipelineAnalyticsGetEventMediaFootprintByKind, usePipelineAnalyticsGetEventStoreFootprint, usePipelineAnalyticsGetKeyEvents, usePipelineAnalyticsGetKeyEventsBatch, usePipelineAnalyticsGetMediaReclaimStatus, usePipelineAnalyticsGetMotionEvents, usePipelineAnalyticsGetObjectEmbeddingRebuildStatus, usePipelineAnalyticsGetObjectEvents, usePipelineAnalyticsGetRetrainCorpusKpi, usePipelineAnalyticsGetRetrainExportUrl, usePipelineAnalyticsGetRetrainFrameImage, usePipelineAnalyticsGetSensorEvents, usePipelineAnalyticsGetStorageMigrationMoveStatus, usePipelineAnalyticsGetTrack, usePipelineAnalyticsGetTrackMedia, usePipelineAnalyticsGetTrainingExportSummary, usePipelineAnalyticsGetTrainingExportUrl, usePipelineAnalyticsListArchivedDebugNotes, usePipelineAnalyticsListBirthDecisions, usePipelineAnalyticsListEventKinds, usePipelineAnalyticsListEventKindsBatch, usePipelineAnalyticsListEventMedia, usePipelineAnalyticsListOpsLog, usePipelineAnalyticsListRecentTracks, usePipelineAnalyticsListRelocateMediaJobs, usePipelineAnalyticsListRetrainAnnotations, usePipelineAnalyticsListRetrainAssistProfiles, usePipelineAnalyticsListRetrainCollectionFrames, usePipelineAnalyticsListRetrainCollections, usePipelineAnalyticsListRetrainCorpusPage, usePipelineAnalyticsListRetrainFrames, usePipelineAnalyticsListRetrainStaging, usePipelineAnalyticsListTrackMedia, usePipelineAnalyticsListTrackRelations, usePipelineAnalyticsListTracks, usePipelineAnalyticsOfferRetrainArchive, usePipelineAnalyticsOwnersWithMedia, usePipelineAnalyticsPauseForStorageMigration, usePipelineAnalyticsProposeRetrainAnnotations, usePipelineAnalyticsProposeRetrainAnnotationsWithLlm, usePipelineAnalyticsPruneEvents, usePipelineAnalyticsPruneEventsBefore, usePipelineAnalyticsPruneTracksBefore, usePipelineAnalyticsReadLongTermSeries, usePipelineAnalyticsRebuildObjectEmbeddings, usePipelineAnalyticsReclaimDebugMedia, usePipelineAnalyticsReconcileFromDisk, usePipelineAnalyticsRefreshStorageLocationsForMigration, usePipelineAnalyticsRelocateMedia, usePipelineAnalyticsRemoveRetrainFrameFromCollection, usePipelineAnalyticsRenameRetrainCollection, usePipelineAnalyticsResolveRetrainTrainingCorpus, usePipelineAnalyticsRestageRetrainTrack, usePipelineAnalyticsResumeForStorageMigration, usePipelineAnalyticsSaveRetrainAnnotations, usePipelineAnalyticsSearchObjectEvents, usePipelineAnalyticsSelectRetrainFrames, usePipelineAnalyticsSetRetrainFrameComplete, usePipelineAnalyticsSetTrackFlags, usePipelineAnalyticsSetTrackPurity, usePipelineAnalyticsSetTrackRelation, usePipelineAnalyticsStartStorageMigrationMove, usePipelineAnalyticsWipeAllAnalytics, usePipelineAnalyticsWipeObjectEmbeddings, usePipelineAnalyticsWriteRetrainArchive, usePipelineExecutorCacheFrameInPool, usePipelineExecutorDeleteModel, usePipelineExecutorDownloadModel, usePipelineExecutorGetAddonModels, usePipelineExecutorGetAudioCapabilities, usePipelineExecutorGetAvailableEngines, usePipelineExecutorGetCapabilities, usePipelineExecutorGetDetectionConfigSchema, usePipelineExecutorGetEffectiveTuning, usePipelineExecutorGetEngineProvisioning, usePipelineExecutorGetInferenceDeviceHealth, usePipelineExecutorGetOrchestratorConfigSchema, usePipelineExecutorGetReferenceAudio, usePipelineExecutorGetReferenceAudioFiles, usePipelineExecutorGetReferenceImage, usePipelineExecutorGetSchema, usePipelineExecutorGetSelectedEngine, usePipelineExecutorGetVideoPipelineSteps, usePipelineExecutorInferCached, usePipelineExecutorKillEngine, usePipelineExecutorListLoadedEngines, usePipelineExecutorListReferenceImages, usePipelineExecutorRearmInferenceDevice, usePipelineExecutorRunAudioTest, usePipelineExecutorRunPipeline, usePipelineExecutorRunPipelineBatch, usePipelineExecutorSetVideoPipelineSteps, usePipelineExecutorSpinEngine, usePipelineExecutorUncacheFrame, usePipelineExecutorValidatePipeline, usePipelineOrchestratorAbortNodeBenchmark, usePipelineOrchestratorApplyAutoTune, usePipelineOrchestratorApplyDeviceSettingsPatch, usePipelineOrchestratorAssignAudio, usePipelineOrchestratorAssignPipeline, usePipelineOrchestratorDeleteNodeBenchmarkResult, usePipelineOrchestratorForgetInferenceDevice, usePipelineOrchestratorGetAgentLoad, usePipelineOrchestratorGetAgentSettings, usePipelineOrchestratorGetAudioAssignment, usePipelineOrchestratorGetAudioAssignments, usePipelineOrchestratorGetAudioNodeLoad, usePipelineOrchestratorGetCameraDetectionSource, usePipelineOrchestratorGetCameraMetrics, usePipelineOrchestratorGetCameraSettings, usePipelineOrchestratorGetCameraStatus, usePipelineOrchestratorGetCameraStatuses, usePipelineOrchestratorGetCameraSwitches, usePipelineOrchestratorGetCapabilityBindings, usePipelineOrchestratorGetClusterModelChoice, usePipelineOrchestratorGetDeviceLiveContribution, usePipelineOrchestratorGetDeviceSettingsContribution, usePipelineOrchestratorGetEffectiveShares, usePipelineOrchestratorGetGlobalMetrics, usePipelineOrchestratorGetIngestOwner, usePipelineOrchestratorGetNodeBenchmarkCandidates, usePipelineOrchestratorGetNodeBenchmarkPreflight, usePipelineOrchestratorGetNodeBenchmarkStatus, usePipelineOrchestratorGetNodeInferenceDevices, usePipelineOrchestratorGetPipelineAssignment, usePipelineOrchestratorGetPipelineAssignments, usePipelineOrchestratorGetPipelineDevicePin, usePipelineOrchestratorGetPlacementStats, usePipelineOrchestratorGetReconcileFromDiskStatus, usePipelineOrchestratorListAgentSettings, usePipelineOrchestratorListNodeBenchmarkResults, usePipelineOrchestratorPauseForStorageMigration, usePipelineOrchestratorPlanAutoTune, usePipelineOrchestratorRebalance, usePipelineOrchestratorReconcileFromDisk, usePipelineOrchestratorRemoveAgentSettings, usePipelineOrchestratorRequestOccupancyLook, usePipelineOrchestratorResetNodePipelineDefaults, usePipelineOrchestratorResolvePipeline, usePipelineOrchestratorResumeForStorageMigration, usePipelineOrchestratorSetAgentCapabilities, usePipelineOrchestratorSetAgentDecodeLimits, usePipelineOrchestratorSetAgentInferenceDevices, usePipelineOrchestratorSetAgentMaxCameras, usePipelineOrchestratorSetAgentReachableHost, usePipelineOrchestratorSetCameraDetectionSource, usePipelineOrchestratorSetCameraSensors, usePipelineOrchestratorSetCameraStepSettings, usePipelineOrchestratorSetCameraStepToggle, usePipelineOrchestratorSetCameraSwitch, usePipelineOrchestratorSetCapabilityBinding, usePipelineOrchestratorSetLoadBalancingShares, usePipelineOrchestratorSetNodeStepSettings, usePipelineOrchestratorSetPipelineDevicePin, usePipelineOrchestratorSetShareSource, usePipelineOrchestratorStartNodeBenchmark, usePipelineOrchestratorSuggestShares, usePipelineOrchestratorUnassignAudio, usePipelineOrchestratorUnassignPipeline, usePipelineRunnerAbortNodeBench, usePipelineRunnerAttachCamera, usePipelineRunnerDetachCamera, usePipelineRunnerGetAllCameraMetrics, usePipelineRunnerGetCameraMetrics, usePipelineRunnerGetLocalCameras, usePipelineRunnerGetLocalLoad, usePipelineRunnerGetLocalMetrics, usePipelineRunnerGetNativeCrop, usePipelineRunnerGetNodeBenchStatus, usePipelineRunnerGetParkedTrackFrame, usePipelineRunnerParkTrackFrame, usePipelineRunnerReleaseParkedTrackFrames, usePipelineRunnerReportMotion, usePipelineRunnerRequestOccupancyBurst, usePipelineRunnerRunDetailSubtree, usePipelineRunnerRunStatelessStep, usePipelineRunnerStartNodeBench, usePlateGalleryAssignPlate, usePlateGalleryAssignPlates, usePlateGalleryCorrectPlateText, usePlateGalleryCreateVehicle, usePlateGalleryDeletePlate, usePlateGalleryDeleteVehicle, usePlateGalleryGetPlateByTrack, usePlateGalleryGetPlateMedia, usePlateGalleryListPlates, usePlateGalleryListVehicleSamples, usePlateGalleryListVehicles, usePlateGalleryRemoveVehicleSample, usePlateGalleryRenameVehicle, usePlateGallerySearchPlates, usePlateGallerySuggestPlateClusters, usePlateGalleryUnassignPlate, usePlateGalleryUnassignPlates, usePlatformProbeGetCapabilities, usePlatformProbeGetHardware, usePlatformProbeRescanAccelerators, usePlatformProbeResolveHwAccel, usePlatformProbeResolveInferenceConfig, usePlayerOverlayLayer, usePlayerOverlayLayers, usePlayerToolbarButton, usePlayerToolbarButtons, usePowerMeterGetStatus, usePowerSourceForceRestart, usePowerSourceGetStatus, usePowerSourcePowerOff, usePowerSourcePowerOn, usePresenceGetStatus, usePressureSensorGetStatus, usePrivacyMaskGetOptions, usePrivacyMaskGetStatus, usePrivacyMaskSetAudioEnabled, usePrivacyMaskSetMask, usePrompt, usePtzAutotrackGetSettings, usePtzAutotrackGetStatus, usePtzAutotrackSetEnabled, usePtzAutotrackSetSettings, usePtzCaptureHomeHere, usePtzContinuousMove, usePtzDeletePreset, usePtzGetHomePreset, usePtzGetHomeReturn, usePtzGetOptions, usePtzGetPosition, usePtzGetPresets, usePtzGetStatus, usePtzGoHome, usePtzGoToPreset, usePtzMove, usePtzSavePreset, usePtzSetAutofocus, usePtzSetHomePreset, usePtzSetHomeReturn, usePtzStop, useRebootReboot, useRecordEntriesDeleteEntry, useRecordEntriesListEntries, useRecordEntriesListEntryKinds, useRecordEntriesPutEntry, useRecordedPlayback, useRecordingArchiveApplyDeviceSettingsPatch, useRecordingArchiveCancelRelocateJob, useRecordingArchiveCancelStorageMigrationMove, useRecordingArchiveDeleteFootprint, useRecordingArchiveGetAvailabilityBatch, useRecordingArchiveGetDaysWithRecordingsBatch, useRecordingArchiveGetDeviceConfig, useRecordingArchiveGetDeviceLiveContribution, useRecordingArchiveGetDeviceSettingsContribution, useRecordingArchiveGetPlacement, useRecordingArchiveGetRelocateResidue, useRecordingArchiveGetStatus, useRecordingArchiveGetStorageMigrationMoveStatus, useRecordingArchiveGetStorageUsage, useRecordingArchiveListOpsLog, useRecordingArchiveListRelocateJobs, useRecordingArchiveLocateSegment, useRecordingArchivePauseForStorageMigration, useRecordingArchivePlanStorageRebalance, useRecordingArchivePruneFootage, useRecordingArchiveReadGopBytes, useRecordingArchiveReadSegmentBytes, useRecordingArchiveReadWindowBytes, useRecordingArchiveReconcileLedgerAgainstDisk, useRecordingArchiveRefreshStorageLocationsForMigration, useRecordingArchiveRelocateFootage, useRecordingArchiveRenderClip, useRecordingArchiveRenderGif, useRecordingArchiveRescanStorage, useRecordingArchiveResumeForStorageMigration, useRecordingArchiveSetDeviceConfig, useRecordingArchiveSetDevicePlacement, useRecordingArchiveStartStorageMigrationMove, useRecordingArchiveStartStorageRebalance, useRecordingExportCancelExport, useRecordingExportCreateExport, useRecordingExportDeleteExport, useRecordingExportGetDownloadUrl, useRecordingExportGetExport, useRecordingExportListExports, useRecordingExportReadExportBytes, useRecordingGetAvailability, useRecordingGetDaysWithRecordings, useRecordingGetPlayback, useRecordingGetPlaybackOptions, useRecordingListSources, useRecordingOnboardGetOptions, useRecordingOnboardGetStatus, useRecordingOnboardSetSettings, useRecordingSignalGetStatus, useRemoteComponent, useRemoteGetConfig, useRemoteLayoutComponentsListComponents, useRemoteListCommands, useRemoteSendCommand, useRemoteSendMediaCommand, useRemoteSetConfig, useRoleDisplayDefaults, useRunningStateGetStatus, useSceneMonitorCaptureReference, useSceneMonitorCreateScene, useSceneMonitorDeleteReference, useSceneMonitorDeleteScene, useSceneMonitorGetStatus, useSceneMonitorListScenes, useSceneMonitorListScenesBatch, useSceneMonitorRecheckNow, useSceneMonitorResetScene, useSceneMonitorUpdateScene, useSchedulersConflicts, useSchedulersCreate, useSchedulersDelete, useSchedulersGet, useSchedulersGetStatus, useSchedulersGetTraces, useSchedulersList, useSchedulersPreview, useSchedulersSetEnabled, useSchedulersUpdate, useScriptRunnerGetStatus, useScriptRunnerRun, useScriptRunnerStop, useScrubController, useSearchFieldHotkey, useServerManagementApplyServerUpdate, useServerManagementCheckServerUpdate, useServerManagementGetLaunchOverrides, useServerManagementGetServerPackageStatus, useServerManagementInstallDesktopUpdate, useServerManagementRestartServer, useServerManagementRollbackServerUpdate, useServerManagementSetLaunchOverrides, useSettingsStoreAggregate, useSettingsStoreCount, useSettingsStoreDeclareCollection, useSettingsStoreDelete, useSettingsStoreDeleteWhere, useSettingsStoreGet, useSettingsStoreHistogram, useSettingsStoreInsert, useSettingsStoreInsertMany, useSettingsStoreIsEmpty, useSettingsStoreQuery, useSettingsStoreSet, useSettingsStoreTransact, useSettingsStoreUpdate, useSettingsStoreUpdateWhere, useSettingsStoreUpsert, useSettingsStoreUpsertMany, useSmokeGetStatus, useSnapshotApplyDeviceSettingsPatch, useSnapshotGetDebugState, useSnapshotGetDeviceLiveContribution, useSnapshotGetDeviceSettingsContribution, useSnapshotGetSnapshot, useSnapshotGetSnapshotLinks, useSnapshotGetSnapshotOverview, useSnapshotGetStatus, useSnapshotInvalidateCache, useStationaryOverlay, useStorageAbortUpload, useStorageBeginDownload, useStorageBeginUpload, useStorageDelete, useStorageDeleteLocation, useStorageEndDownload, useStorageExists, useStorageFinalizeUpload, useStorageGetAvailableSpace, useStorageList, useStorageListDrainProgress, useStorageListLocationDeclarations, useStorageListLocations, useStorageListProviders, useStorageMigrationCancel, useStorageMigrationCleanupCancel, useStorageMigrationCleanupStart, useStorageMigrationCleanupStatus, useStorageMigrationDrain, useStorageMigrationHistory, useStorageMigrationMoverClearance, useStorageMigrationMovers, useStorageMigrationPlan, useStorageMigrationResidue, useStorageMigrationStart, useStorageMigrationStatus, useStorageRead, useStorageReadChunk, useStorageResolve, useStorageTestConfig, useStorageTestLocation, useStorageUpsertLocation, useStorageWrite, useStorageWriteChunk, useStoredGroupBy, useStreamBrokerAcquireEgressTranscode, useStreamBrokerApplyDeviceSettingsPatch, useStreamBrokerAssignProfile, useStreamBrokerFetchEventMedia, useStreamBrokerForgetDeviceHardware, useStreamBrokerGetAllRtspEntries, useStreamBrokerGetBrokerStats, useStreamBrokerGetDeviceAudioMute, useStreamBrokerGetDeviceLiveContribution, useStreamBrokerGetDeviceSettingsContribution, useStreamBrokerGetLiveViewerCounts, useStreamBrokerGetPreBufferInfo, useStreamBrokerGetRtspEntry, useStreamBrokerGetRtspPort, useStreamBrokerGetStreamUrl, useStreamBrokerGetStreamWithCodec, useStreamBrokerIsRtspEnabled, useStreamBrokerKillClient, useStreamBrokerListAllCameraStreams, useStreamBrokerListAllProfileSlots, useStreamBrokerListClients, useStreamBrokerProbeStream, useStreamBrokerProduceEventMedia, useStreamBrokerPublishCameraStream, useStreamBrokerPullAudioChunks, useStreamBrokerRegenerateRtspToken, useStreamBrokerReleaseEgressTranscode, useStreamBrokerReleaseStreamWithCodec, useStreamBrokerRenderPreBufferClip, useStreamBrokerReportStreamSignal, useStreamBrokerRestartProfile, useStreamBrokerRetractCameraStream, useStreamBrokerSetDeviceAudioMute, useStreamBrokerSetPreBufferDuration, useStreamBrokerSetRtspEnabled, useStreamBrokerSubscribeAudioChunks, useStreamBrokerUnassignProfile, useStreamBrokerUnsubscribeAudioChunks, useStreamCatalogGetCatalog, useStreamParamsGetConfigSchema, useStreamParamsGetOptions, useStreamParamsGetStatus, useStreamParamsSetProfile, useStreamSignalsListSignals, useSwitchGetStatus, useSwitchSetState, useSystem, useSystemDetectSiteLocation, useSystemFeatureFlags, useSystemForceRetentionCleanup, useSystemGetFailureContributions, useSystemGetLoadContributions, useSystemGetLoggingSettings, useSystemGetRequestCensus, useSystemGetRetentionConfig, useSystemGetSiteLocation, useSystemHealth, useSystemInfo, useSystemMutation, useSystemNetworkAddresses, useSystemQuery, useSystemSetLoggingSettings, useSystemSetRetentionConfig, useSystemSetSiteLocation, useTamperGetStatus, useTemperatureSensorGetStatus, useTemplateCreate, useTemplateDelete, useTemplateGet, useTemplateList, useTemplateUpdate, useTerminalSessionAdoptLegacyMonitor, useTerminalSessionClose, useTerminalSessionCreateInstance, useTerminalSessionDeleteInstance, useTerminalSessionListInstances, useTerminalSessionListLegacyCameras, useTerminalSessionListProfiles, useTerminalSessionListSessions, useTerminalSessionOpenSession, useTerminalSessionPullOutput, useTerminalSessionResize, useTerminalSessionSetInstanceEnabled, useTerminalSessionUpdateInstance, useTerminalSessionWriteInput, useThemeMode, useTimedRunCancel, useTimedRunGetStatus, useTimedRunRunFor, useToastOnToast, useTrainingCanaryResult, useTrainingCancelJob, useTrainingDiscardResult, useTrainingGetJob, useTrainingGetJobResult, useTrainingListBaseModels, useTrainingListCanaryTargets, useTrainingListJobs, useTrainingPlanJob, useTrainingRegisterResult, useTrainingRollbackCanary, useTrainingStartJob, useTrainingStartJobBatch, useTurnProviderGetTurnServers, useUiText, useUnitPreferences, useUpdateGetStatus, useUpdateInstallUpdate, useUrlQueryParam, useUserManagementConfirmTotp, useUserManagementCreateUser, useUserManagementDeleteUser, useUserManagementDisableTotp, useUserManagementFindUserByExternalIdentity, useUserManagementGetAdminBootstrapStatus, useUserManagementGetTotpStatus, useUserManagementListExternalIdentities, useUserManagementListOauthSessions, useUserManagementListUsers, useUserManagementMigrateRawSecrets, useUserManagementOauthExchangeCode, useUserManagementOauthIssueCode, useUserManagementOauthRefresh, useUserManagementOauthVerifyAccessToken, useUserManagementResetPassword, useUserManagementRevokeOauthSession, useUserManagementSetUserScopes, useUserManagementSetupTotp, useUserManagementUnlinkExternalIdentity, useUserManagementUpdateUser, useUserManagementValidateCredentials, useUserManagementVerifyTotp, useVacuumControlGetStatus, useVacuumControlLocate, useVacuumControlPause, useVacuumControlReturnToBase, useVacuumControlSetFanSpeed, useVacuumControlStart, useVacuumControlStop, useValveClose, useValveGetStatus, useValveOpen, useValveSetPosition, useValveStop, useVibrationGetStatus, useVideoclipsDialClipStream, useVideoclipsGetClipPlayback, useVideoclipsGetPlaybackOptions, useVideoclipsListClips, useVideoclipsListSources, useVideoclipsOfferClipBytes, useVideoclipsReadClipBytes, useVodPlayback, useWaterHeaterGetStatus, useWaterHeaterSetAway, useWaterHeaterSetOperationMode, useWaterHeaterSetTargetTemp, useWeatherGetStatus, useWebrtcSessionAddIceCandidate, useWebrtcSessionApplyDownlinkProbe, useWebrtcSessionCloseSession, useWebrtcSessionCreateSession, useWebrtcSessionGetIceCandidates, useWebrtcSessionGetSessionDebug, useWebrtcSessionGetSessionState, useWebrtcSessionHandleAnswer, useWebrtcSessionHandleOffer, useWebrtcSessionHasAdaptiveBitrate, useWebrtcSessionListStreams, useWidget, useWidgetMetadata, useWidgetRegistry, useZoneAnalyticsGetCameraHistory, useZoneAnalyticsGetCurrentSnapshot, useZoneAnalyticsGetCurrentSnapshotBatch, useZoneAnalyticsGetUnzonedHistory, useZoneAnalyticsGetZoneHistory, useZoneEditing, useZoneRulesListRules, useZoneRulesSetRules, useZonesAddZone, useZonesListZones, useZonesRemoveZone, useZonesUpdateZone, Save as ut, UtensilsCrossed as v, vacuumStateMeta, validateScopes, valveStateMeta, variantLabel, Hash as vn, ChevronLeft as vr, RadioTower as vt, Undo2 as w, waterHeaterPhase, waterHeaterTint, weatherConditionMeta, weatherTint, withHiddenChart, withPanel, withResolvedParentDetail, withUseRootModel, withoutModelScopedFields, withoutPanel, GraduationCap as wn, Car as wr, writeStoredGroupBy, Plug as wt, UserCheck as x, Hammer as xn, ChartLine as xr, Puzzle as xt, Users as y, HardDrive as yn, ChevronDown as yr, Radar as yt, Tag as z, EllipsisVertical as zn, BatteryMedium as zr, MoveVertical as zt };