@camstack/types 1.2.241 → 1.2.243

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_sleep = require("./sleep-vrBqRLsb.js");
2
+ const require_sleep = require("./sleep-mVRRyKVq.js");
3
3
  const require_event_category = require("./event-category-BVfsrBYA.js");
4
4
  const require_canonical_hash = require("./canonical-hash-CSE4ioRi.js");
5
5
  const require_enums = require("./enums.js");
@@ -1149,10 +1149,20 @@ var CameraSwitchAuthoritySchema = zod.z.discriminatedUnion("kind", [
1149
1149
  var CameraSwitchUnavailableReasonSchema = zod.z.enum([
1150
1150
  "no-provider",
1151
1151
  "source-unreachable",
1152
- "not-configured",
1153
1152
  "device-disabled"
1154
1153
  ]);
1155
1154
  /**
1155
+ * Something true about a switch that is nonetheless OFFERED.
1156
+ *
1157
+ * The distinction from {@link CameraSwitchUnavailableReasonSchema} is the
1158
+ * whole point: a reason replaces the control, a warning travels WITH it. The
1159
+ * privacy mask taught us the difference — greying the one button that starts
1160
+ * the feature teaches the operator the feature is broken, while a live toggle
1161
+ * that flips nothing teaches them the switch is broken. Neither is true; the
1162
+ * honest surface is a working toggle that says what is missing.
1163
+ */
1164
+ var CameraSwitchWarningSchema = zod.z.enum(["no-privacy-zones"]);
1165
+ /**
1156
1166
  * One switch, resolved for one camera.
1157
1167
  *
1158
1168
  * `label` and `costWhenOff` travel ON THE WIRE rather than being looked up
@@ -1171,6 +1181,11 @@ var CameraSwitchSchema = zod.z.object({
1171
1181
  /** False = do not render a control. `unavailableReason` says why. */
1172
1182
  available: zod.z.boolean(),
1173
1183
  unavailableReason: CameraSwitchUnavailableReasonSchema.optional(),
1184
+ /**
1185
+ * Present on an AVAILABLE switch only. Rendered beside the live control;
1186
+ * never a substitute for one.
1187
+ */
1188
+ warning: CameraSwitchWarningSchema.optional(),
1174
1189
  /** Current state. Meaningless when `available` is false — read it as `true`. */
1175
1190
  enabled: zod.z.boolean(),
1176
1191
  authority: CameraSwitchAuthoritySchema
@@ -1404,9 +1419,9 @@ function resolveState(descriptor, input) {
1404
1419
  unavailableReason: "source-unreachable"
1405
1420
  };
1406
1421
  if (mask.configuredRegions === 0) return {
1407
- available: false,
1408
- enabled: false,
1409
- unavailableReason: "not-configured"
1422
+ available: true,
1423
+ enabled: mask.enabled,
1424
+ warning: "no-privacy-zones"
1410
1425
  };
1411
1426
  return {
1412
1427
  available: true,
@@ -1445,6 +1460,7 @@ function deriveCameraSwitches(input) {
1445
1460
  costWhenOff: descriptor.costWhenOff,
1446
1461
  available: state.available,
1447
1462
  ...state.unavailableReason !== void 0 ? { unavailableReason: state.unavailableReason } : {},
1463
+ ...state.warning !== void 0 ? { warning: state.warning } : {},
1448
1464
  enabled: state.enabled,
1449
1465
  authority: descriptor.authority
1450
1466
  };
@@ -27248,6 +27264,15 @@ var CLIP_STILL_REASON_HEADER = "x-camstack-reason";
27248
27264
  var CLIP_STILL_REASON_CODE_HEADER = "x-camstack-reason-code";
27249
27265
  /** One {@link ClipStillDispositionSchema} token, alone. */
27250
27266
  var CLIP_STILL_DISPOSITION_HEADER = "x-camstack-disposition";
27267
+ /**
27268
+ * The clip STREAM route's own statement of what it is (D597): the value is
27269
+ * `forward-only`. A producer writes it on the 200; a consumer that dials a
27270
+ * URL and does not read it back refuses to play, because a progressive file
27271
+ * through a forward-only feeder looks like it worked until the first seek.
27272
+ * Named here because BOTH the provider and the broker spell it, and two
27273
+ * copies of a header name is how one of them stops being checked.
27274
+ */
27275
+ var CLIP_STREAM_TRANSPORT_HEADER = "x-camstack-clip-transport";
27251
27276
  var ClipSchema = zod.z.object({
27252
27277
  /** Opaque, provider-namespaced id. The default provider encodes the time
27253
27278
  * window so `getClipPlayback` is self-contained (no event re-query). */
@@ -27533,6 +27558,82 @@ var ClipBytesSchema = zod.z.object({
27533
27558
  */
27534
27559
  durationMs: zod.z.number().positive().optional()
27535
27560
  });
27561
+ /**
27562
+ * Where a clip's STREAM can be dialled (D597) — the answer to
27563
+ * {@link videoclipsCapability.methods.dialClipStream}.
27564
+ *
27565
+ * `url` is plain `http://` on the provider's own token-gated listener, one
27566
+ * shot, short-lived. It is NOT the hub-proxied `/addon/<id>/clip-stream/…`
27567
+ * path: that plane takes only a user credential, which an addon does not
27568
+ * hold, and the framework offers no addon→addon byte transport — the one
27569
+ * precedent is the broker's own restream URLs (`getStreamWithCodec`), which
27570
+ * a consumer dials directly, and this is that precedent one addon over.
27571
+ */
27572
+ /**
27573
+ * The audio a clip stream can be asked for, and the audio it carries.
27574
+ *
27575
+ * The camera stores AAC and no WebRTC session speaks it, so a stream that
27576
+ * carries sound carries it TRANSCODED, muxed as a second track beside the
27577
+ * video by the one ffmpeg the provider already runs (D600). `opus` is
27578
+ * 48 kHz mono, `pcmu` is 8 kHz µ-law — the two codecs a broker session
27579
+ * negotiates — and `none` is a stream asked for, or served, without sound.
27580
+ */
27581
+ var ClipStreamAudioSchema = zod.z.enum([
27582
+ "opus",
27583
+ "pcmu",
27584
+ "none"
27585
+ ]);
27586
+ /**
27587
+ * Why a stream that was ASKED for sound is not carrying it (D600).
27588
+ *
27589
+ * Only ever set beside `servedAudio: 'none'` after a non-`none` ask. Absent
27590
+ * means the ask was honoured, or there was no ask.
27591
+ *
27592
+ * - `not-requested` — the caller asked for `none`.
27593
+ * - `unsupported-ask` — the provider cannot produce that codec.
27594
+ *
27595
+ * Whether the RECORDING has sound at all is not knowable here: the camera
27596
+ * declares no audio track before its first frame arrives. That answer is in
27597
+ * the stream itself — an fMP4 with no audio track — and the broker reads it
27598
+ * there. A dial that says `opus` promises the codec, never the content.
27599
+ */
27600
+ var ClipStreamAudioReasonSchema = zod.z.enum(["not-requested", "unsupported-ask"]);
27601
+ var ClipStreamDialSchema = zod.z.object({
27602
+ url: zod.z.string().min(1),
27603
+ /** After this the token is gone and the URL answers 404 `dial-expired`. */
27604
+ expiresAtMs: zod.z.number(),
27605
+ /** What the stream IS — a consumer that cannot honour it must not dial. */
27606
+ transport: zod.z.literal("forward-only"),
27607
+ /**
27608
+ * Which twin the stream ACTUALLY carries — not what was asked for.
27609
+ *
27610
+ * The stream serves every profile (D599), and a recording whose main twin
27611
+ * does not exist is streamed as its sub copy, which this field reports as
27612
+ * `low`. That is the whole reason the dial no longer refuses `high`:
27613
+ * stating what was served is what makes accepting honest, where a silent
27614
+ * substitution would be the 33x lie D576 forbids. Stated rather than
27615
+ * assumed, the way {@link ClipPlaybackSchema.served} is (D549 15).
27616
+ */
27617
+ served: require_sleep.CamProfileSchema,
27618
+ /**
27619
+ * Which audio the stream will ACTUALLY carry — `served`'s companion for
27620
+ * sound, and the same reasoning (D599, D600).
27621
+ *
27622
+ * The broker asks for the codec its WebRTC session negotiated, and the
27623
+ * provider either muxes that codec or carries none. Stating it is what
27624
+ * lets the broker wire the matching sink before the first byte, and what
27625
+ * keeps a session from being handed a codec it cannot send — the audio
27626
+ * shape of the substitution `served` exists to prevent.
27627
+ *
27628
+ * It is a promise about the CODEC, not about the content: a recording with
27629
+ * no microphone track answers `opus` here and then arrives with no audio
27630
+ * track at all. That second answer is in the stream, and the broker reads
27631
+ * it from the `moov`.
27632
+ */
27633
+ servedAudio: ClipStreamAudioSchema,
27634
+ /** Why `servedAudio` is `none` although sound was asked for. */
27635
+ audioReason: ClipStreamAudioReasonSchema.optional()
27636
+ });
27536
27637
  var ClipSourceAvailabilitySchema = zod.z.object({
27537
27638
  state: zod.z.enum([
27538
27639
  "ok",
@@ -27783,6 +27884,44 @@ var videoclipsCapability = {
27783
27884
  }), ClipBytesSchema, {
27784
27885
  kind: "query",
27785
27886
  auth: "protected"
27887
+ }),
27888
+ /**
27889
+ * Where this clip's STREAM can be dialled (D597) — the forward-only
27890
+ * fMP4 the provider writes from the first muxed byte, for the broker to
27891
+ * play through the same WebRTC session as recorded footage, with the
27892
+ * first frame at the first fragment instead of after the last byte.
27893
+ *
27894
+ * Nothing is fetched here: the answer is a one-shot URL on the
27895
+ * provider's own listener, and the camera is touched when it is dialled.
27896
+ * The gates the file path runs (`readClipBytes`) run on the dial too —
27897
+ * the id, the row, a clip still being written — and refuse in the same
27898
+ * vocabulary, THROWN with `clipExportFailure(<token>, <prose>)`. Every
27899
+ * profile is served (D599) and the answer states which twin it carries;
27900
+ * `high` is not refused. Optional on the provider for the same reason
27901
+ * `readClipBytes` is: a source with no camera socket behind it (the
27902
+ * recorder's analytics window, a HomeKit tee) has no stream.
27903
+ */
27904
+ dialClipStream: require_sleep.optionalMethod(zod.z.object({
27905
+ deviceId: zod.z.number(),
27906
+ clipId: zod.z.string().min(1),
27907
+ /** WHICH provider holds the camera — see `readClipBytes.provider`. */
27908
+ provider: zod.z.string().min(1),
27909
+ /** Which twin — `high` → the main file, everything else the sub (D599). */
27910
+ profile: require_sleep.CamProfileSchema.optional(),
27911
+ /**
27912
+ * Which audio codec the caller's session negotiated, so the provider
27913
+ * can mux it (D600). The ask travels on the DIAL because the mux is
27914
+ * spawned once, before the first byte, and cannot gain a track later.
27915
+ *
27916
+ * ABSENT IS `none`, never a guess: a caller that does not state an
27917
+ * ask is served the video-only stream that shipped first, so a broker
27918
+ * older than this field keeps working unchanged (D382 — an unstated
27919
+ * ask is zero).
27920
+ */
27921
+ audio: ClipStreamAudioSchema.optional()
27922
+ }), ClipStreamDialSchema, {
27923
+ kind: "query",
27924
+ auth: "protected"
27786
27925
  })
27787
27926
  }
27788
27927
  };
@@ -42717,12 +42856,39 @@ function rank(type) {
42717
42856
  * must decide what an empty container means for it, rather than being handed a
42718
42857
  * child that is not there.
42719
42858
  */
42859
+ /**
42860
+ * Two names for the same thing, compared the way an integration writes them.
42861
+ *
42862
+ * An exact case-insensitive match was not enough, and the failure was total
42863
+ * rather than marginal. An ESPHome shutter arrives as a container named
42864
+ * `Tapparella-Cucina` whose children include the COVER, named `Tapparella
42865
+ * cucina`, and a device-presence entity carrying the slug verbatim,
42866
+ * `tapparella-cucina`. The slug matched the container exactly and the cover
42867
+ * did not, so the namesake tie-break handed the container to a connectivity
42868
+ * indicator — and the viewer's accessory panel, which correctly shows only
42869
+ * children with an actuating control, then rendered NOTHING. The operator saw
42870
+ * no shutters at all on cucina, studio and both veranda cameras (2026-09-22).
42871
+ *
42872
+ * `Markise` was the control case that proved the mechanism: there the cover
42873
+ * really is called exactly like its container, so it won and appeared.
42874
+ *
42875
+ * Separators are therefore normalised — `-`, `_` and whitespace are the same
42876
+ * character for this comparison, and runs of them collapse. The two candidates
42877
+ * then tie on the namesake and the decision falls through to `rank(type)`,
42878
+ * where `cover` is eighth and a `presence` entity is not listed at all. The
42879
+ * criterion keeps doing its job for a container whose child IS the namesake;
42880
+ * it stops being decided by which integration used a hyphen.
42881
+ */
42882
+ function sameName(childName, containerName) {
42883
+ const flatten = (v) => v.toLowerCase().replace(/[-_\s]+/g, " ").trim();
42884
+ return flatten(childName) === flatten(containerName);
42885
+ }
42720
42886
  function resolveContainerPrimaryChild(children, overrideEntityId, containerName) {
42721
42887
  if (overrideEntityId !== void 0 && overrideEntityId !== null) {
42722
42888
  const picked = children.find((c) => c.stableId === overrideEntityId) ?? children.find((c) => c.entityId !== void 0 && c.entityId === overrideEntityId);
42723
42889
  if (picked !== void 0) return picked;
42724
42890
  }
42725
- const namesake = (c) => containerName !== void 0 && containerName.length > 0 && c.name !== void 0 && c.name.toLowerCase() === containerName.toLowerCase() ? 0 : 1;
42891
+ const namesake = (c) => containerName !== void 0 && containerName.length > 0 && c.name !== void 0 && sameName(c.name, containerName) ? 0 : 1;
42726
42892
  return [...children].toSorted((a, b) => roleRank(a.role) - roleRank(b.role) || namesake(a) - namesake(b) || rank(a.type) - rank(b.type))[0] ?? null;
42727
42893
  }
42728
42894
  //#endregion
@@ -43192,6 +43358,1429 @@ function resolveDeviceProfile(features) {
43192
43358
  return null;
43193
43359
  }
43194
43360
  //#endregion
43361
+ //#region src/device/display-icon-vocabulary.ts
43362
+ /** The order the groups are offered in, and the only members there are. */
43363
+ var DISPLAY_ICON_GROUPS = [
43364
+ "device",
43365
+ "lighting",
43366
+ "sensing",
43367
+ "place",
43368
+ "life"
43369
+ ];
43370
+ /**
43371
+ * The vocabulary, in the order a picker offers it.
43372
+ *
43373
+ * Adding a key here is not enough to make it pickable: both glyph tables must
43374
+ * gain it too, and their tests fail until they do. That is the intended
43375
+ * friction — it is the only thing that keeps the two surfaces honest.
43376
+ */
43377
+ var DISPLAY_ICON_VOCABULARY = [
43378
+ {
43379
+ key: "camera",
43380
+ group: "device",
43381
+ synonyms: [
43382
+ "telecamera",
43383
+ "videocamera",
43384
+ "camera",
43385
+ "cam"
43386
+ ]
43387
+ },
43388
+ {
43389
+ key: "network",
43390
+ group: "device",
43391
+ synonyms: [
43392
+ "rete",
43393
+ "network",
43394
+ "lan"
43395
+ ]
43396
+ },
43397
+ {
43398
+ key: "toggle-left",
43399
+ group: "device",
43400
+ synonyms: [
43401
+ "interruttore",
43402
+ "switch",
43403
+ "toggle"
43404
+ ]
43405
+ },
43406
+ {
43407
+ key: "toggle-right",
43408
+ group: "device",
43409
+ synonyms: [
43410
+ "interruttore",
43411
+ "switch",
43412
+ "toggle",
43413
+ "acceso"
43414
+ ]
43415
+ },
43416
+ {
43417
+ key: "circle-dot",
43418
+ group: "device",
43419
+ synonyms: [
43420
+ "pulsante",
43421
+ "bottone",
43422
+ "button",
43423
+ "dot"
43424
+ ]
43425
+ },
43426
+ {
43427
+ key: "refresh-cw",
43428
+ group: "device",
43429
+ synonyms: [
43430
+ "aggiorna",
43431
+ "ricarica",
43432
+ "refresh",
43433
+ "reload",
43434
+ "ciclo"
43435
+ ]
43436
+ },
43437
+ {
43438
+ key: "box",
43439
+ group: "device",
43440
+ synonyms: [
43441
+ "scatola",
43442
+ "box",
43443
+ "contenitore"
43444
+ ]
43445
+ },
43446
+ {
43447
+ key: "scroll-text",
43448
+ group: "device",
43449
+ synonyms: [
43450
+ "registro",
43451
+ "log",
43452
+ "testo"
43453
+ ]
43454
+ },
43455
+ {
43456
+ key: "workflow",
43457
+ group: "device",
43458
+ synonyms: [
43459
+ "automazione",
43460
+ "flusso",
43461
+ "workflow",
43462
+ "scenario"
43463
+ ]
43464
+ },
43465
+ {
43466
+ key: "lock",
43467
+ group: "device",
43468
+ synonyms: [
43469
+ "serratura",
43470
+ "chiave",
43471
+ "lucchetto",
43472
+ "chiuso",
43473
+ "locked"
43474
+ ]
43475
+ },
43476
+ {
43477
+ key: "lock-open",
43478
+ group: "device",
43479
+ synonyms: [
43480
+ "serratura",
43481
+ "aperta",
43482
+ "sbloccato",
43483
+ "unlocked"
43484
+ ]
43485
+ },
43486
+ {
43487
+ key: "blinds",
43488
+ group: "device",
43489
+ synonyms: [
43490
+ "tapparella",
43491
+ "persiana",
43492
+ "serranda",
43493
+ "avvolgibile",
43494
+ "shutter",
43495
+ "blind",
43496
+ "veneziana"
43497
+ ]
43498
+ },
43499
+ {
43500
+ key: "air-vent",
43501
+ group: "device",
43502
+ synonyms: [
43503
+ "bocchetta",
43504
+ "aria",
43505
+ "ventilazione",
43506
+ "condizionatore",
43507
+ "vent"
43508
+ ]
43509
+ },
43510
+ {
43511
+ key: "monitor-play",
43512
+ group: "device",
43513
+ synonyms: [
43514
+ "schermo",
43515
+ "riproduzione",
43516
+ "player",
43517
+ "display"
43518
+ ]
43519
+ },
43520
+ {
43521
+ key: "sliders-horizontal",
43522
+ group: "device",
43523
+ synonyms: [
43524
+ "regolazione",
43525
+ "cursori",
43526
+ "impostazioni",
43527
+ "slider"
43528
+ ]
43529
+ },
43530
+ {
43531
+ key: "map-pin",
43532
+ group: "device",
43533
+ synonyms: [
43534
+ "posizione",
43535
+ "luogo",
43536
+ "mappa",
43537
+ "pin"
43538
+ ]
43539
+ },
43540
+ {
43541
+ key: "bot",
43542
+ group: "device",
43543
+ synonyms: [
43544
+ "robot",
43545
+ "aspirapolvere",
43546
+ "bot"
43547
+ ]
43548
+ },
43549
+ {
43550
+ key: "tractor",
43551
+ group: "device",
43552
+ synonyms: [
43553
+ "trattore",
43554
+ "tosaerba",
43555
+ "giardino"
43556
+ ]
43557
+ },
43558
+ {
43559
+ key: "image",
43560
+ group: "device",
43561
+ synonyms: [
43562
+ "immagine",
43563
+ "foto",
43564
+ "snapshot"
43565
+ ]
43566
+ },
43567
+ {
43568
+ key: "bone",
43569
+ group: "device",
43570
+ synonyms: ["osso", "cane"]
43571
+ },
43572
+ {
43573
+ key: "door-closed",
43574
+ group: "device",
43575
+ synonyms: [
43576
+ "porta",
43577
+ "chiusa",
43578
+ "contatto"
43579
+ ]
43580
+ },
43581
+ {
43582
+ key: "door-open",
43583
+ group: "device",
43584
+ synonyms: [
43585
+ "porta",
43586
+ "aperta",
43587
+ "contatto",
43588
+ "ingresso",
43589
+ "uscita"
43590
+ ]
43591
+ },
43592
+ {
43593
+ key: "crosshair",
43594
+ group: "device",
43595
+ synonyms: [
43596
+ "mirino",
43597
+ "puntamento",
43598
+ "centro"
43599
+ ]
43600
+ },
43601
+ {
43602
+ key: "eye",
43603
+ group: "device",
43604
+ synonyms: [
43605
+ "occhio",
43606
+ "visibile",
43607
+ "visto"
43608
+ ]
43609
+ },
43610
+ {
43611
+ key: "eye-off",
43612
+ group: "device",
43613
+ synonyms: [
43614
+ "privacy",
43615
+ "nascosto",
43616
+ "oscurato",
43617
+ "mascherato",
43618
+ "invisibile"
43619
+ ]
43620
+ },
43621
+ {
43622
+ key: "smartphone",
43623
+ group: "device",
43624
+ synonyms: [
43625
+ "telefono",
43626
+ "cellulare",
43627
+ "smartphone"
43628
+ ]
43629
+ },
43630
+ {
43631
+ key: "phone",
43632
+ group: "device",
43633
+ synonyms: ["telefono", "chiamata"]
43634
+ },
43635
+ {
43636
+ key: "tablet",
43637
+ group: "device",
43638
+ synonyms: ["tablet", "ipad"]
43639
+ },
43640
+ {
43641
+ key: "laptop",
43642
+ group: "device",
43643
+ synonyms: [
43644
+ "portatile",
43645
+ "laptop",
43646
+ "notebook"
43647
+ ]
43648
+ },
43649
+ {
43650
+ key: "monitor",
43651
+ group: "device",
43652
+ synonyms: ["monitor", "schermo"]
43653
+ },
43654
+ {
43655
+ key: "tv",
43656
+ group: "device",
43657
+ synonyms: ["televisore", "tv"]
43658
+ },
43659
+ {
43660
+ key: "speaker",
43661
+ group: "device",
43662
+ synonyms: [
43663
+ "altoparlante",
43664
+ "cassa",
43665
+ "speaker"
43666
+ ]
43667
+ },
43668
+ {
43669
+ key: "printer",
43670
+ group: "device",
43671
+ synonyms: ["stampante"]
43672
+ },
43673
+ {
43674
+ key: "projector",
43675
+ group: "device",
43676
+ synonyms: ["proiettore"]
43677
+ },
43678
+ {
43679
+ key: "gamepad-2",
43680
+ group: "device",
43681
+ synonyms: [
43682
+ "console",
43683
+ "gioco",
43684
+ "joystick"
43685
+ ]
43686
+ },
43687
+ {
43688
+ key: "radio",
43689
+ group: "device",
43690
+ synonyms: ["radio"]
43691
+ },
43692
+ {
43693
+ key: "router",
43694
+ group: "device",
43695
+ synonyms: ["router", "modem"]
43696
+ },
43697
+ {
43698
+ key: "bluetooth",
43699
+ group: "device",
43700
+ synonyms: ["bluetooth"]
43701
+ },
43702
+ {
43703
+ key: "cpu",
43704
+ group: "device",
43705
+ synonyms: [
43706
+ "processore",
43707
+ "cpu",
43708
+ "chip",
43709
+ "dispositivo"
43710
+ ]
43711
+ },
43712
+ {
43713
+ key: "hard-drive",
43714
+ group: "device",
43715
+ synonyms: [
43716
+ "disco",
43717
+ "hdd",
43718
+ "archiviazione",
43719
+ "storage"
43720
+ ]
43721
+ },
43722
+ {
43723
+ key: "server",
43724
+ group: "device",
43725
+ synonyms: ["server", "nas"]
43726
+ },
43727
+ {
43728
+ key: "mic",
43729
+ group: "device",
43730
+ synonyms: ["microfono", "audio"]
43731
+ },
43732
+ {
43733
+ key: "mic-off",
43734
+ group: "device",
43735
+ synonyms: [
43736
+ "microfono",
43737
+ "spento",
43738
+ "muto"
43739
+ ]
43740
+ },
43741
+ {
43742
+ key: "video",
43743
+ group: "device",
43744
+ synonyms: ["video"]
43745
+ },
43746
+ {
43747
+ key: "video-off",
43748
+ group: "device",
43749
+ synonyms: ["video", "spento"]
43750
+ },
43751
+ {
43752
+ key: "music",
43753
+ group: "device",
43754
+ synonyms: ["musica"]
43755
+ },
43756
+ {
43757
+ key: "plug",
43758
+ group: "device",
43759
+ synonyms: [
43760
+ "presa",
43761
+ "spina",
43762
+ "plug"
43763
+ ]
43764
+ },
43765
+ {
43766
+ key: "plug-zap",
43767
+ group: "device",
43768
+ synonyms: ["presa", "alimentata"]
43769
+ },
43770
+ {
43771
+ key: "power",
43772
+ group: "device",
43773
+ synonyms: [
43774
+ "accensione",
43775
+ "alimentazione",
43776
+ "power"
43777
+ ]
43778
+ },
43779
+ {
43780
+ key: "power-off",
43781
+ group: "device",
43782
+ synonyms: ["spegnimento", "spento"]
43783
+ },
43784
+ {
43785
+ key: "cable",
43786
+ group: "device",
43787
+ synonyms: ["cavo"]
43788
+ },
43789
+ {
43790
+ key: "battery",
43791
+ group: "device",
43792
+ synonyms: ["batteria"]
43793
+ },
43794
+ {
43795
+ key: "battery-charging",
43796
+ group: "device",
43797
+ synonyms: [
43798
+ "batteria",
43799
+ "carica",
43800
+ "ricarica"
43801
+ ]
43802
+ },
43803
+ {
43804
+ key: "battery-full",
43805
+ group: "device",
43806
+ synonyms: [
43807
+ "batteria",
43808
+ "carica",
43809
+ "piena"
43810
+ ]
43811
+ },
43812
+ {
43813
+ key: "battery-low",
43814
+ group: "device",
43815
+ synonyms: ["batteria", "scarica"]
43816
+ },
43817
+ {
43818
+ key: "key",
43819
+ group: "device",
43820
+ synonyms: ["chiave"]
43821
+ },
43822
+ {
43823
+ key: "key-round",
43824
+ group: "device",
43825
+ synonyms: ["chiave", "tonda"]
43826
+ },
43827
+ {
43828
+ key: "mailbox",
43829
+ group: "device",
43830
+ synonyms: [
43831
+ "cassetta",
43832
+ "postale",
43833
+ "posta"
43834
+ ]
43835
+ },
43836
+ {
43837
+ key: "package",
43838
+ group: "device",
43839
+ synonyms: ["pacco", "consegna"]
43840
+ },
43841
+ {
43842
+ key: "shield",
43843
+ group: "device",
43844
+ synonyms: [
43845
+ "scudo",
43846
+ "protezione",
43847
+ "sicurezza",
43848
+ "allarme"
43849
+ ]
43850
+ },
43851
+ {
43852
+ key: "shield-check",
43853
+ group: "device",
43854
+ synonyms: [
43855
+ "protetto",
43856
+ "sicuro",
43857
+ "armato"
43858
+ ]
43859
+ },
43860
+ {
43861
+ key: "shield-off",
43862
+ group: "device",
43863
+ synonyms: [
43864
+ "protezione",
43865
+ "disattivata",
43866
+ "disarmato"
43867
+ ]
43868
+ },
43869
+ {
43870
+ key: "briefcase",
43871
+ group: "device",
43872
+ synonyms: [
43873
+ "ufficio",
43874
+ "lavoro",
43875
+ "valigetta",
43876
+ "studio"
43877
+ ]
43878
+ },
43879
+ {
43880
+ key: "lightbulb",
43881
+ group: "lighting",
43882
+ synonyms: [
43883
+ "luce",
43884
+ "lampadina",
43885
+ "lampada",
43886
+ "light"
43887
+ ]
43888
+ },
43889
+ {
43890
+ key: "lamp",
43891
+ group: "lighting",
43892
+ synonyms: ["lampada", "abatjour"]
43893
+ },
43894
+ {
43895
+ key: "lamp-ceiling",
43896
+ group: "lighting",
43897
+ synonyms: [
43898
+ "plafoniera",
43899
+ "lampadario",
43900
+ "luce",
43901
+ "soffitto"
43902
+ ]
43903
+ },
43904
+ {
43905
+ key: "lamp-desk",
43906
+ group: "lighting",
43907
+ synonyms: [
43908
+ "lampada",
43909
+ "scrivania",
43910
+ "abatjour"
43911
+ ]
43912
+ },
43913
+ {
43914
+ key: "lamp-floor",
43915
+ group: "lighting",
43916
+ synonyms: [
43917
+ "piantana",
43918
+ "lampada",
43919
+ "terra"
43920
+ ]
43921
+ },
43922
+ {
43923
+ key: "flashlight",
43924
+ group: "lighting",
43925
+ synonyms: [
43926
+ "faretto",
43927
+ "torcia",
43928
+ "spot",
43929
+ "faro"
43930
+ ]
43931
+ },
43932
+ {
43933
+ key: "heater",
43934
+ group: "lighting",
43935
+ synonyms: [
43936
+ "riscaldamento",
43937
+ "termosifone",
43938
+ "stufa",
43939
+ "calore"
43940
+ ]
43941
+ },
43942
+ {
43943
+ key: "snowflake",
43944
+ group: "lighting",
43945
+ synonyms: [
43946
+ "freddo",
43947
+ "raffrescamento",
43948
+ "aria",
43949
+ "condizionata",
43950
+ "neve"
43951
+ ]
43952
+ },
43953
+ {
43954
+ key: "thermometer-sun",
43955
+ group: "lighting",
43956
+ synonyms: [
43957
+ "caldo",
43958
+ "temperatura",
43959
+ "alta"
43960
+ ]
43961
+ },
43962
+ {
43963
+ key: "thermometer-snowflake",
43964
+ group: "lighting",
43965
+ synonyms: [
43966
+ "freddo",
43967
+ "temperatura",
43968
+ "bassa"
43969
+ ]
43970
+ },
43971
+ {
43972
+ key: "refrigerator",
43973
+ group: "lighting",
43974
+ synonyms: ["frigorifero", "frigo"]
43975
+ },
43976
+ {
43977
+ key: "microwave",
43978
+ group: "lighting",
43979
+ synonyms: ["microonde", "forno"]
43980
+ },
43981
+ {
43982
+ key: "washing-machine",
43983
+ group: "lighting",
43984
+ synonyms: [
43985
+ "lavatrice",
43986
+ "lavastoviglie",
43987
+ "asciugatrice"
43988
+ ]
43989
+ },
43990
+ {
43991
+ key: "cooking-pot",
43992
+ group: "lighting",
43993
+ synonyms: [
43994
+ "pentola",
43995
+ "cucina",
43996
+ "fornello"
43997
+ ]
43998
+ },
43999
+ {
44000
+ key: "utensils",
44001
+ group: "lighting",
44002
+ synonyms: [
44003
+ "cucina",
44004
+ "posate",
44005
+ "sala",
44006
+ "pranzo"
44007
+ ]
44008
+ },
44009
+ {
44010
+ key: "thermometer",
44011
+ group: "sensing",
44012
+ synonyms: [
44013
+ "temperatura",
44014
+ "termometro",
44015
+ "termostato"
44016
+ ]
44017
+ },
44018
+ {
44019
+ key: "droplets",
44020
+ group: "sensing",
44021
+ synonyms: [
44022
+ "umidita",
44023
+ "acqua",
44024
+ "allagamento",
44025
+ "perdita"
44026
+ ]
44027
+ },
44028
+ {
44029
+ key: "droplet",
44030
+ group: "sensing",
44031
+ synonyms: [
44032
+ "goccia",
44033
+ "acqua",
44034
+ "perdita",
44035
+ "allagamento"
44036
+ ]
44037
+ },
44038
+ {
44039
+ key: "gauge",
44040
+ group: "sensing",
44041
+ synonyms: [
44042
+ "misura",
44043
+ "livello",
44044
+ "pressione",
44045
+ "indicatore"
44046
+ ]
44047
+ },
44048
+ {
44049
+ key: "gauge2",
44050
+ group: "sensing",
44051
+ synonyms: [
44052
+ "misura",
44053
+ "livello",
44054
+ "pressione",
44055
+ "indicatore"
44056
+ ],
44057
+ aliasOf: "gauge"
44058
+ },
44059
+ {
44060
+ key: "sun",
44061
+ group: "sensing",
44062
+ synonyms: [
44063
+ "sole",
44064
+ "luminosita",
44065
+ "giorno",
44066
+ "esterno"
44067
+ ]
44068
+ },
44069
+ {
44070
+ key: "sun-medium",
44071
+ group: "sensing",
44072
+ synonyms: ["sole", "luminosita"]
44073
+ },
44074
+ {
44075
+ key: "sunrise",
44076
+ group: "sensing",
44077
+ synonyms: ["alba"]
44078
+ },
44079
+ {
44080
+ key: "moon",
44081
+ group: "sensing",
44082
+ synonyms: [
44083
+ "notte",
44084
+ "luna",
44085
+ "notturna",
44086
+ "nightvision"
44087
+ ]
44088
+ },
44089
+ {
44090
+ key: "wind",
44091
+ group: "sensing",
44092
+ synonyms: [
44093
+ "vento",
44094
+ "aria",
44095
+ "gas",
44096
+ "monossido",
44097
+ "co"
44098
+ ]
44099
+ },
44100
+ {
44101
+ key: "cloud",
44102
+ group: "sensing",
44103
+ synonyms: ["nuvola", "nuvoloso"]
44104
+ },
44105
+ {
44106
+ key: "cloud-rain",
44107
+ group: "sensing",
44108
+ synonyms: ["pioggia"]
44109
+ },
44110
+ {
44111
+ key: "cloud-sun",
44112
+ group: "sensing",
44113
+ synonyms: [
44114
+ "variabile",
44115
+ "sole",
44116
+ "nuvole"
44117
+ ]
44118
+ },
44119
+ {
44120
+ key: "waves",
44121
+ group: "sensing",
44122
+ synonyms: [
44123
+ "onde",
44124
+ "acqua",
44125
+ "vibrazione"
44126
+ ]
44127
+ },
44128
+ {
44129
+ key: "sprout",
44130
+ group: "sensing",
44131
+ synonyms: [
44132
+ "irrigazione",
44133
+ "pianta",
44134
+ "germoglio",
44135
+ "orto"
44136
+ ]
44137
+ },
44138
+ {
44139
+ key: "leaf",
44140
+ group: "sensing",
44141
+ synonyms: [
44142
+ "foglia",
44143
+ "pianta",
44144
+ "verde"
44145
+ ]
44146
+ },
44147
+ {
44148
+ key: "flower",
44149
+ group: "sensing",
44150
+ synonyms: ["fiore", "pianta"]
44151
+ },
44152
+ {
44153
+ key: "zap",
44154
+ group: "sensing",
44155
+ synonyms: [
44156
+ "energia",
44157
+ "corrente",
44158
+ "consumo",
44159
+ "watt",
44160
+ "elettricita"
44161
+ ]
44162
+ },
44163
+ {
44164
+ key: "flame",
44165
+ group: "sensing",
44166
+ synonyms: [
44167
+ "fiamma",
44168
+ "gas",
44169
+ "fuoco",
44170
+ "incendio"
44171
+ ]
44172
+ },
44173
+ {
44174
+ key: "bell",
44175
+ group: "sensing",
44176
+ synonyms: [
44177
+ "campanello",
44178
+ "suoneria",
44179
+ "notifica",
44180
+ "bell",
44181
+ "chime"
44182
+ ]
44183
+ },
44184
+ {
44185
+ key: "bell-ring",
44186
+ group: "sensing",
44187
+ synonyms: [
44188
+ "campanello",
44189
+ "suona",
44190
+ "doorbell",
44191
+ "notifica"
44192
+ ]
44193
+ },
44194
+ {
44195
+ key: "bell-off",
44196
+ group: "sensing",
44197
+ synonyms: [
44198
+ "silenzioso",
44199
+ "notifiche",
44200
+ "disattivate",
44201
+ "muto"
44202
+ ]
44203
+ },
44204
+ {
44205
+ key: "siren",
44206
+ group: "sensing",
44207
+ synonyms: ["sirena", "allarme"]
44208
+ },
44209
+ {
44210
+ key: "radar",
44211
+ group: "sensing",
44212
+ synonyms: [
44213
+ "movimento",
44214
+ "presenza",
44215
+ "pir",
44216
+ "rilevamento",
44217
+ "radar"
44218
+ ]
44219
+ },
44220
+ {
44221
+ key: "activity",
44222
+ group: "sensing",
44223
+ synonyms: [
44224
+ "attivita",
44225
+ "sensore",
44226
+ "generico"
44227
+ ]
44228
+ },
44229
+ {
44230
+ key: "hash",
44231
+ group: "sensing",
44232
+ synonyms: [
44233
+ "numero",
44234
+ "contatore",
44235
+ "valore"
44236
+ ]
44237
+ },
44238
+ {
44239
+ key: "clock",
44240
+ group: "sensing",
44241
+ synonyms: [
44242
+ "orologio",
44243
+ "ora",
44244
+ "tempo"
44245
+ ]
44246
+ },
44247
+ {
44248
+ key: "timer",
44249
+ group: "sensing",
44250
+ synonyms: [
44251
+ "timer",
44252
+ "conto",
44253
+ "rovescia"
44254
+ ]
44255
+ },
44256
+ {
44257
+ key: "calendar",
44258
+ group: "sensing",
44259
+ synonyms: [
44260
+ "calendario",
44261
+ "data",
44262
+ "pianificazione"
44263
+ ]
44264
+ },
44265
+ {
44266
+ key: "pipette",
44267
+ group: "sensing",
44268
+ synonyms: [
44269
+ "qualita",
44270
+ "aria",
44271
+ "misura",
44272
+ "campione"
44273
+ ]
44274
+ },
44275
+ {
44276
+ key: "fan",
44277
+ group: "sensing",
44278
+ synonyms: [
44279
+ "ventilatore",
44280
+ "ventola",
44281
+ "aria"
44282
+ ]
44283
+ },
44284
+ {
44285
+ key: "bath",
44286
+ group: "sensing",
44287
+ synonyms: [
44288
+ "bagno",
44289
+ "vasca",
44290
+ "doccia"
44291
+ ]
44292
+ },
44293
+ {
44294
+ key: "footprints",
44295
+ group: "sensing",
44296
+ synonyms: [
44297
+ "movimento",
44298
+ "passi",
44299
+ "presenza",
44300
+ "motion"
44301
+ ]
44302
+ },
44303
+ {
44304
+ key: "alarm-smoke",
44305
+ group: "sensing",
44306
+ synonyms: [
44307
+ "fumo",
44308
+ "antincendio",
44309
+ "rilevatore"
44310
+ ]
44311
+ },
44312
+ {
44313
+ key: "shield-alert",
44314
+ group: "sensing",
44315
+ synonyms: [
44316
+ "manomissione",
44317
+ "allarme",
44318
+ "tamper",
44319
+ "avviso"
44320
+ ]
44321
+ },
44322
+ {
44323
+ key: "vibrate",
44324
+ group: "sensing",
44325
+ synonyms: [
44326
+ "vibrazione",
44327
+ "urto",
44328
+ "tamper"
44329
+ ]
44330
+ },
44331
+ {
44332
+ key: "wifi",
44333
+ group: "sensing",
44334
+ synonyms: [
44335
+ "wifi",
44336
+ "rete",
44337
+ "segnale"
44338
+ ]
44339
+ },
44340
+ {
44341
+ key: "wifi-off",
44342
+ group: "sensing",
44343
+ synonyms: [
44344
+ "wifi",
44345
+ "assente",
44346
+ "offline",
44347
+ "disconnesso"
44348
+ ]
44349
+ },
44350
+ {
44351
+ key: "volume-2",
44352
+ group: "sensing",
44353
+ synonyms: [
44354
+ "volume",
44355
+ "audio",
44356
+ "altoparlante",
44357
+ "suono"
44358
+ ]
44359
+ },
44360
+ {
44361
+ key: "volume-x",
44362
+ group: "sensing",
44363
+ synonyms: [
44364
+ "muto",
44365
+ "silenziato",
44366
+ "volume",
44367
+ "spento"
44368
+ ]
44369
+ },
44370
+ {
44371
+ key: "heart",
44372
+ group: "sensing",
44373
+ synonyms: [
44374
+ "cuore",
44375
+ "preferito",
44376
+ "salute"
44377
+ ]
44378
+ },
44379
+ {
44380
+ key: "heart-pulse",
44381
+ group: "sensing",
44382
+ synonyms: [
44383
+ "battito",
44384
+ "salute",
44385
+ "monitoraggio"
44386
+ ]
44387
+ },
44388
+ {
44389
+ key: "star",
44390
+ group: "sensing",
44391
+ synonyms: [
44392
+ "preferito",
44393
+ "stella",
44394
+ "importante"
44395
+ ]
44396
+ },
44397
+ {
44398
+ key: "sparkles",
44399
+ group: "sensing",
44400
+ synonyms: [
44401
+ "automatico",
44402
+ "intelligente",
44403
+ "ai",
44404
+ "scena"
44405
+ ]
44406
+ },
44407
+ {
44408
+ key: "house",
44409
+ group: "place",
44410
+ synonyms: [
44411
+ "casa",
44412
+ "abitazione",
44413
+ "home"
44414
+ ]
44415
+ },
44416
+ {
44417
+ key: "sofa",
44418
+ group: "place",
44419
+ synonyms: [
44420
+ "salone",
44421
+ "soggiorno",
44422
+ "divano",
44423
+ "living"
44424
+ ]
44425
+ },
44426
+ {
44427
+ key: "bed-double",
44428
+ group: "place",
44429
+ synonyms: [
44430
+ "camera",
44431
+ "letto",
44432
+ "matrimoniale"
44433
+ ]
44434
+ },
44435
+ {
44436
+ key: "bed",
44437
+ group: "place",
44438
+ synonyms: [
44439
+ "cameretta",
44440
+ "letto",
44441
+ "singolo"
44442
+ ]
44443
+ },
44444
+ {
44445
+ key: "warehouse",
44446
+ group: "place",
44447
+ synonyms: [
44448
+ "magazzino",
44449
+ "capanno",
44450
+ "deposito",
44451
+ "cantina"
44452
+ ]
44453
+ },
44454
+ {
44455
+ key: "trees",
44456
+ group: "place",
44457
+ synonyms: [
44458
+ "giardino",
44459
+ "alberi",
44460
+ "esterno",
44461
+ "parco"
44462
+ ]
44463
+ },
44464
+ {
44465
+ key: "tree-pine",
44466
+ group: "place",
44467
+ synonyms: [
44468
+ "albero",
44469
+ "pino",
44470
+ "giardino"
44471
+ ]
44472
+ },
44473
+ {
44474
+ key: "fence",
44475
+ group: "place",
44476
+ synonyms: [
44477
+ "recinto",
44478
+ "cancello",
44479
+ "staccionata",
44480
+ "perimetro"
44481
+ ]
44482
+ },
44483
+ {
44484
+ key: "store",
44485
+ group: "place",
44486
+ synonyms: [
44487
+ "negozio",
44488
+ "ingresso",
44489
+ "vetrina"
44490
+ ]
44491
+ },
44492
+ {
44493
+ key: "building",
44494
+ group: "place",
44495
+ synonyms: ["edificio", "palazzo"]
44496
+ },
44497
+ {
44498
+ key: "building-2",
44499
+ group: "place",
44500
+ synonyms: [
44501
+ "edificio",
44502
+ "uffici",
44503
+ "condominio"
44504
+ ]
44505
+ },
44506
+ {
44507
+ key: "mountain",
44508
+ group: "place",
44509
+ synonyms: [
44510
+ "montagna",
44511
+ "esterno",
44512
+ "panorama"
44513
+ ]
44514
+ },
44515
+ {
44516
+ key: "umbrella",
44517
+ group: "place",
44518
+ synonyms: [
44519
+ "tenda",
44520
+ "markise",
44521
+ "ombrellone",
44522
+ "pergola",
44523
+ "veranda"
44524
+ ]
44525
+ },
44526
+ {
44527
+ key: "dumbbell",
44528
+ group: "place",
44529
+ synonyms: ["palestra", "attrezzi"]
44530
+ },
44531
+ {
44532
+ key: "wrench",
44533
+ group: "place",
44534
+ synonyms: [
44535
+ "officina",
44536
+ "manutenzione",
44537
+ "attrezzi",
44538
+ "utenze"
44539
+ ]
44540
+ },
44541
+ {
44542
+ key: "hammer",
44543
+ group: "place",
44544
+ synonyms: [
44545
+ "officina",
44546
+ "martello",
44547
+ "lavori"
44548
+ ]
44549
+ },
44550
+ {
44551
+ key: "drill",
44552
+ group: "place",
44553
+ synonyms: [
44554
+ "officina",
44555
+ "trapano",
44556
+ "lavori"
44557
+ ]
44558
+ },
44559
+ {
44560
+ key: "waves-ladder",
44561
+ group: "place",
44562
+ synonyms: ["piscina", "vasca"]
44563
+ },
44564
+ {
44565
+ key: "circle-parking",
44566
+ group: "place",
44567
+ synonyms: [
44568
+ "parcheggio",
44569
+ "posto",
44570
+ "auto",
44571
+ "garage"
44572
+ ]
44573
+ },
44574
+ {
44575
+ key: "route",
44576
+ group: "place",
44577
+ synonyms: [
44578
+ "percorso",
44579
+ "strada",
44580
+ "vialetto",
44581
+ "tragitto"
44582
+ ]
44583
+ },
44584
+ {
44585
+ key: "car",
44586
+ group: "life",
44587
+ synonyms: [
44588
+ "auto",
44589
+ "macchina",
44590
+ "veicolo",
44591
+ "parcheggio"
44592
+ ]
44593
+ },
44594
+ {
44595
+ key: "bike",
44596
+ group: "life",
44597
+ synonyms: [
44598
+ "bicicletta",
44599
+ "bici",
44600
+ "moto"
44601
+ ]
44602
+ },
44603
+ {
44604
+ key: "bus",
44605
+ group: "life",
44606
+ synonyms: ["autobus", "pullman"]
44607
+ },
44608
+ {
44609
+ key: "truck",
44610
+ group: "life",
44611
+ synonyms: [
44612
+ "camion",
44613
+ "furgone",
44614
+ "consegna"
44615
+ ]
44616
+ },
44617
+ {
44618
+ key: "plane",
44619
+ group: "life",
44620
+ synonyms: ["aereo"]
44621
+ },
44622
+ {
44623
+ key: "train-front",
44624
+ group: "life",
44625
+ synonyms: ["treno"]
44626
+ },
44627
+ {
44628
+ key: "sailboat",
44629
+ group: "life",
44630
+ synonyms: ["barca", "imbarcazione"]
44631
+ },
44632
+ {
44633
+ key: "dog",
44634
+ group: "life",
44635
+ synonyms: ["cane", "animale"]
44636
+ },
44637
+ {
44638
+ key: "cat",
44639
+ group: "life",
44640
+ synonyms: ["gatto", "animale"]
44641
+ },
44642
+ {
44643
+ key: "bird",
44644
+ group: "life",
44645
+ synonyms: ["uccello", "animale"]
44646
+ },
44647
+ {
44648
+ key: "paw-print",
44649
+ group: "life",
44650
+ synonyms: [
44651
+ "animale",
44652
+ "zampa",
44653
+ "pet"
44654
+ ]
44655
+ },
44656
+ {
44657
+ key: "baby",
44658
+ group: "life",
44659
+ synonyms: [
44660
+ "neonato",
44661
+ "bimbo",
44662
+ "cameretta",
44663
+ "babymonitor"
44664
+ ]
44665
+ },
44666
+ {
44667
+ key: "user",
44668
+ group: "life",
44669
+ synonyms: ["persona", "utente"]
44670
+ },
44671
+ {
44672
+ key: "users",
44673
+ group: "life",
44674
+ synonyms: [
44675
+ "persone",
44676
+ "gruppo",
44677
+ "famiglia"
44678
+ ]
44679
+ },
44680
+ {
44681
+ key: "person-standing",
44682
+ group: "life",
44683
+ synonyms: [
44684
+ "persona",
44685
+ "piedi",
44686
+ "presenza"
44687
+ ]
44688
+ }
44689
+ ];
44690
+ /** Every key, in vocabulary order — aliases included, because they resolve. */
44691
+ var DISPLAY_ICON_KEYS = DISPLAY_ICON_VOCABULARY.map((e) => e.key);
44692
+ /** The keys a picker OFFERS: everything that is not a deprecated spelling. */
44693
+ var DISPLAY_ICON_OFFERED_KEYS = DISPLAY_ICON_VOCABULARY.filter((e) => e.aliasOf === void 0).map((e) => e.key);
44694
+ var ENTRY_BY_KEY = new Map(DISPLAY_ICON_VOCABULARY.map((e) => [e.key, e]));
44695
+ /** Is this a key of the shared vocabulary? */
44696
+ function isDisplayIconKey(value) {
44697
+ return typeof value === "string" && ENTRY_BY_KEY.has(value);
44698
+ }
44699
+ /** The entry for a key, or `undefined` — never a guessed one. */
44700
+ function displayIconEntry(key) {
44701
+ return ENTRY_BY_KEY.get(key);
44702
+ }
44703
+ /** The entries of one group, in vocabulary order. */
44704
+ function displayIconsInGroup(group) {
44705
+ return DISPLAY_ICON_VOCABULARY.filter((e) => e.group === group);
44706
+ }
44707
+ /**
44708
+ * Lower-case, strip accents, collapse separators.
44709
+ *
44710
+ * The accent strip is not cosmetic: an operator typing "umidità" must reach
44711
+ * `droplets`, whose synonym is spelled without one, and an Italian keyboard
44712
+ * produces the composed form.
44713
+ */
44714
+ function normalise(text) {
44715
+ return text.normalize("NFD").replace(/\p{Diacritic}/gu, "").toLowerCase().replace(/[_-]+/g, " ").trim();
44716
+ }
44717
+ /** Does `needle` appear in `haystack` in order, though not adjacently? */
44718
+ function isSubsequence(needle, haystack) {
44719
+ let i = 0;
44720
+ for (const ch of haystack) {
44721
+ if (ch === needle[i]) i += 1;
44722
+ if (i === needle.length) return true;
44723
+ }
44724
+ return needle.length === 0;
44725
+ }
44726
+ /**
44727
+ * How well one word answers the query. 0 = not at all.
44728
+ *
44729
+ * The tiers are ordered by how confident the operator can be that they meant
44730
+ * this: an exact word beats a prefix, a prefix beats a word STARTING inside
44731
+ * the phrase, and a loose subsequence comes last because it is the tier that
44732
+ * matches almost anything ("cr" reaches `circle-parking`).
44733
+ */
44734
+ function scoreWord(query, word) {
44735
+ if (word === query) return 100;
44736
+ if (word.startsWith(query)) return 80;
44737
+ if (word.split(" ").some((w) => w.startsWith(query))) return 60;
44738
+ if (word.includes(query)) return 40;
44739
+ if (isSubsequence(query, word)) return 15;
44740
+ return 0;
44741
+ }
44742
+ /**
44743
+ * Rank the vocabulary against a free-text query.
44744
+ *
44745
+ * An empty query returns the WHOLE vocabulary in its declared order, because
44746
+ * a picker's resting state is the full list, not an empty one.
44747
+ *
44748
+ * `extraWords` lets a caller add the words IT can translate — a localised
44749
+ * device-role label, say — without this module knowing what a locale is.
44750
+ * They score exactly like a synonym.
44751
+ *
44752
+ * Ties keep vocabulary order: a search that reshuffles equally-good results
44753
+ * between two keystrokes makes the list unusable.
44754
+ */
44755
+ function searchDisplayIcons(query, extraWords) {
44756
+ const q = normalise(query);
44757
+ if (q.length === 0) return DISPLAY_ICON_VOCABULARY.filter((e) => e.aliasOf === void 0).map((entry) => ({
44758
+ entry,
44759
+ score: 0
44760
+ }));
44761
+ const hits = [];
44762
+ for (const entry of DISPLAY_ICON_VOCABULARY) {
44763
+ if (entry.aliasOf !== void 0) continue;
44764
+ const words = [
44765
+ normalise(entry.key),
44766
+ ...entry.synonyms.map(normalise),
44767
+ ...(extraWords?.get(entry.key) ?? []).map(normalise)
44768
+ ];
44769
+ let best = 0;
44770
+ for (const [index, word] of words.entries()) {
44771
+ const score = scoreWord(q, word);
44772
+ if (score === 0) continue;
44773
+ const weighted = index === 0 ? score + 1 : score;
44774
+ if (weighted > best) best = weighted;
44775
+ }
44776
+ if (best > 0) hits.push({
44777
+ entry,
44778
+ score: best
44779
+ });
44780
+ }
44781
+ return hits.sort((a, b) => b.score - a.score);
44782
+ }
44783
+ //#endregion
43195
44784
  //#region src/device/path-util.ts
43196
44785
  /** Returns true when `x` is a non-null, non-array plain object. */
43197
44786
  function isRecord(x) {
@@ -52164,6 +53753,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
52164
53753
  addonId: null,
52165
53754
  access: "view"
52166
53755
  },
53756
+ "videoclips.dialClipStream": {
53757
+ capName: "videoclips",
53758
+ capScope: "device",
53759
+ addonId: null,
53760
+ access: "view"
53761
+ },
52167
53762
  "videoclips.getClipPlayback": {
52168
53763
  capName: "videoclips",
52169
53764
  capScope: "device",
@@ -54530,6 +56125,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
54530
56125
  form: "single",
54531
56126
  optional: false
54532
56127
  }],
56128
+ "videoclips.dialClipStream": [{
56129
+ name: "deviceId",
56130
+ form: "single",
56131
+ optional: false
56132
+ }],
54533
56133
  "videoclips.getClipPlayback": [{
54534
56134
  name: "deviceId",
54535
56135
  form: "single",
@@ -60164,6 +61764,7 @@ exports.CLASS_MAP_MACRO_TARGETS = CLASS_MAP_MACRO_TARGETS;
60164
61764
  exports.CLIP_STILL_DISPOSITION_HEADER = CLIP_STILL_DISPOSITION_HEADER;
60165
61765
  exports.CLIP_STILL_REASON_CODE_HEADER = CLIP_STILL_REASON_CODE_HEADER;
60166
61766
  exports.CLIP_STILL_REASON_HEADER = CLIP_STILL_REASON_HEADER;
61767
+ exports.CLIP_STREAM_TRANSPORT_HEADER = CLIP_STREAM_TRANSPORT_HEADER;
60167
61768
  exports.CLUSTER_MODEL_SCOPED_STEPS = CLUSTER_MODEL_SCOPED_STEPS;
60168
61769
  exports.CLUSTER_MODEL_SECTION_ID = CLUSTER_MODEL_SECTION_ID;
60169
61770
  exports.CLUSTER_STEP_SETTING_FIELDS = CLUSTER_STEP_SETTING_FIELDS;
@@ -60207,6 +61808,7 @@ exports.CameraSwitchGroupSchema = CameraSwitchGroupSchema;
60207
61808
  exports.CameraSwitchIdSchema = CameraSwitchIdSchema;
60208
61809
  exports.CameraSwitchSchema = CameraSwitchSchema;
60209
61810
  exports.CameraSwitchUnavailableReasonSchema = CameraSwitchUnavailableReasonSchema;
61811
+ exports.CameraSwitchWarningSchema = CameraSwitchWarningSchema;
60210
61812
  exports.CandidateQueryFilterSchema = CandidateQueryFilterSchema;
60211
61813
  exports.CapScopeSchema = CapScopeSchema;
60212
61814
  exports.CapabilityBindingsSchema = CapabilityBindingsSchema;
@@ -60222,6 +61824,9 @@ exports.ClipSourceAvailabilitySchema = ClipSourceAvailabilitySchema;
60222
61824
  exports.ClipSourceSchema = ClipSourceSchema;
60223
61825
  exports.ClipStillDispositionSchema = ClipStillDispositionSchema;
60224
61826
  exports.ClipStillRefusalCodeSchema = ClipStillRefusalCodeSchema;
61827
+ exports.ClipStreamAudioReasonSchema = ClipStreamAudioReasonSchema;
61828
+ exports.ClipStreamAudioSchema = ClipStreamAudioSchema;
61829
+ exports.ClipStreamDialSchema = ClipStreamDialSchema;
60225
61830
  exports.ClipWakeSchema = ClipWakeSchema;
60226
61831
  exports.ClusterAddonNodeDeploymentSchema = ClusterAddonNodeDeploymentSchema;
60227
61832
  exports.ClusterAddonStatusEntrySchema = ClusterAddonStatusEntrySchema;
@@ -60299,6 +61904,10 @@ exports.DEVICE_STATE_READERS = DEVICE_STATE_READERS;
60299
61904
  exports.DEVICE_STATUS_METHOD = require_sleep.DEVICE_STATUS_METHOD;
60300
61905
  exports.DEVICE_TYPE_CONTROL_KIND = DEVICE_TYPE_CONTROL_KIND;
60301
61906
  exports.DEVICE_TYPE_INFO = DEVICE_TYPE_INFO;
61907
+ exports.DISPLAY_ICON_GROUPS = DISPLAY_ICON_GROUPS;
61908
+ exports.DISPLAY_ICON_KEYS = DISPLAY_ICON_KEYS;
61909
+ exports.DISPLAY_ICON_OFFERED_KEYS = DISPLAY_ICON_OFFERED_KEYS;
61910
+ exports.DISPLAY_ICON_VOCABULARY = DISPLAY_ICON_VOCABULARY;
60302
61911
  exports.DataStoreEngineInfoSchema = EngineInfoSchema;
60303
61912
  exports.DayNightModeSchema = DayNightModeSchema;
60304
61913
  exports.DayNightOptionsSchema = DayNightOptionsSchema;
@@ -61316,6 +62925,8 @@ exports.deviceProviderCapability = deviceProviderCapability;
61316
62925
  exports.deviceSelectorMatches = deviceSelectorMatches;
61317
62926
  exports.deviceStateCapability = deviceStateCapability;
61318
62927
  exports.deviceStatusCapability = deviceStatusCapability;
62928
+ exports.displayIconEntry = displayIconEntry;
62929
+ exports.displayIconsInGroup = displayIconsInGroup;
61319
62930
  exports.doorbellCapability = doorbellCapability;
61320
62931
  exports.droppedConditionsForKind = droppedConditionsForKind;
61321
62932
  exports.egressTranscodeSharingKey = egressTranscodeSharingKey;
@@ -61393,6 +63004,7 @@ exports.isDeployableToAgent = isDeployableToAgent;
61393
63004
  exports.isDetectionMacroClass = isDetectionMacroClass;
61394
63005
  exports.isDeviceConfigCap = require_sleep.isDeviceConfigCap;
61395
63006
  exports.isDeviceScopedCap = require_sleep.isDeviceScopedCap;
63007
+ exports.isDisplayIconKey = isDisplayIconKey;
61396
63008
  exports.isEvent = require_sleep.isEvent;
61397
63009
  exports.isEventOwnerType = isEventOwnerType;
61398
63010
  exports.isFirstLevelMacroClass = isFirstLevelMacroClass;
@@ -61584,6 +63196,7 @@ exports.scopesAllowAddon = scopesAllowAddon;
61584
63196
  exports.scopesAllowDeviceCap = scopesAllowDeviceCap;
61585
63197
  exports.scoreRuntimes = scoreRuntimes;
61586
63198
  exports.scriptRunnerCapability = scriptRunnerCapability;
63199
+ exports.searchDisplayIcons = searchDisplayIcons;
61587
63200
  exports.selectAssignedProfileSlots = require_sleep.selectAssignedProfileSlots;
61588
63201
  exports.serverManagementCapability = serverManagementCapability;
61589
63202
  exports.setByPath = setByPath;