@camstack/ui-library 1.1.41 → 1.1.42

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.cjs CHANGED
@@ -8458,6 +8458,68 @@ var Bell = createLucideIcon("bell", [["path", {
8458
8458
  * This source code is licensed under the ISC license.
8459
8459
  * See the LICENSE file in the root directory of this source tree.
8460
8460
  */
8461
+ var Bike = createLucideIcon("bike", [
8462
+ ["circle", {
8463
+ cx: "18.5",
8464
+ cy: "17.5",
8465
+ r: "3.5",
8466
+ key: "15x4ox"
8467
+ }],
8468
+ ["circle", {
8469
+ cx: "5.5",
8470
+ cy: "17.5",
8471
+ r: "3.5",
8472
+ key: "1noe27"
8473
+ }],
8474
+ ["circle", {
8475
+ cx: "15",
8476
+ cy: "5",
8477
+ r: "1",
8478
+ key: "19l28e"
8479
+ }],
8480
+ ["path", {
8481
+ d: "M12 17.5V14l-3-3 4-3 2 3h2",
8482
+ key: "1npguv"
8483
+ }]
8484
+ ]);
8485
+ /**
8486
+ * @license lucide-react v0.576.0 - ISC
8487
+ *
8488
+ * This source code is licensed under the ISC license.
8489
+ * See the LICENSE file in the root directory of this source tree.
8490
+ */
8491
+ var Bird = createLucideIcon("bird", [
8492
+ ["path", {
8493
+ d: "M16 7h.01",
8494
+ key: "1kdx03"
8495
+ }],
8496
+ ["path", {
8497
+ d: "M3.4 18H12a8 8 0 0 0 8-8V7a4 4 0 0 0-7.28-2.3L2 20",
8498
+ key: "oj1oa8"
8499
+ }],
8500
+ ["path", {
8501
+ d: "m20 7 2 .5-2 .5",
8502
+ key: "12nv4d"
8503
+ }],
8504
+ ["path", {
8505
+ d: "M10 18v3",
8506
+ key: "1yea0a"
8507
+ }],
8508
+ ["path", {
8509
+ d: "M14 17.75V21",
8510
+ key: "1pymcb"
8511
+ }],
8512
+ ["path", {
8513
+ d: "M7 18a6 6 0 0 0 3.84-10.61",
8514
+ key: "1npnn0"
8515
+ }]
8516
+ ]);
8517
+ /**
8518
+ * @license lucide-react v0.576.0 - ISC
8519
+ *
8520
+ * This source code is licensed under the ISC license.
8521
+ * See the LICENSE file in the root directory of this source tree.
8522
+ */
8461
8523
  var Blinds = createLucideIcon("blinds", [
8462
8524
  ["path", {
8463
8525
  d: "M3 3h18",
@@ -8614,6 +8676,46 @@ var Bug = createLucideIcon("bug", [
8614
8676
  * This source code is licensed under the ISC license.
8615
8677
  * See the LICENSE file in the root directory of this source tree.
8616
8678
  */
8679
+ var Bus = createLucideIcon("bus", [
8680
+ ["path", {
8681
+ d: "M8 6v6",
8682
+ key: "18i7km"
8683
+ }],
8684
+ ["path", {
8685
+ d: "M15 6v6",
8686
+ key: "1sg6z9"
8687
+ }],
8688
+ ["path", {
8689
+ d: "M2 12h19.6",
8690
+ key: "de5uta"
8691
+ }],
8692
+ ["path", {
8693
+ d: "M18 18h3s.5-1.7.8-2.8c.1-.4.2-.8.2-1.2 0-.4-.1-.8-.2-1.2l-1.4-5C20.1 6.8 19.1 6 18 6H4a2 2 0 0 0-2 2v10h3",
8694
+ key: "1wwztk"
8695
+ }],
8696
+ ["circle", {
8697
+ cx: "7",
8698
+ cy: "18",
8699
+ r: "2",
8700
+ key: "19iecd"
8701
+ }],
8702
+ ["path", {
8703
+ d: "M9 18h5",
8704
+ key: "lrx6i"
8705
+ }],
8706
+ ["circle", {
8707
+ cx: "16",
8708
+ cy: "18",
8709
+ r: "2",
8710
+ key: "1v4tcr"
8711
+ }]
8712
+ ]);
8713
+ /**
8714
+ * @license lucide-react v0.576.0 - ISC
8715
+ *
8716
+ * This source code is licensed under the ISC license.
8717
+ * See the LICENSE file in the root directory of this source tree.
8718
+ */
8617
8719
  var Camera = createLucideIcon("camera", [["path", {
8618
8720
  d: "M13.997 4a2 2 0 0 1 1.76 1.05l.486.9A2 2 0 0 0 18.003 7H20a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h1.997a2 2 0 0 0 1.759-1.048l.489-.904A2 2 0 0 1 10.004 4z",
8619
8721
  key: "18u6gg"
@@ -8629,6 +8731,34 @@ var Camera = createLucideIcon("camera", [["path", {
8629
8731
  * This source code is licensed under the ISC license.
8630
8732
  * See the LICENSE file in the root directory of this source tree.
8631
8733
  */
8734
+ var Car = createLucideIcon("car", [
8735
+ ["path", {
8736
+ d: "M19 17h2c.6 0 1-.4 1-1v-3c0-.9-.7-1.7-1.5-1.9C18.7 10.6 16 10 16 10s-1.3-1.4-2.2-2.3c-.5-.4-1.1-.7-1.8-.7H5c-.6 0-1.1.4-1.4.9l-1.4 2.9A3.7 3.7 0 0 0 2 12v4c0 .6.4 1 1 1h2",
8737
+ key: "5owen"
8738
+ }],
8739
+ ["circle", {
8740
+ cx: "7",
8741
+ cy: "17",
8742
+ r: "2",
8743
+ key: "u2ysq9"
8744
+ }],
8745
+ ["path", {
8746
+ d: "M9 17h6",
8747
+ key: "r8uit2"
8748
+ }],
8749
+ ["circle", {
8750
+ cx: "17",
8751
+ cy: "17",
8752
+ r: "2",
8753
+ key: "axvx0g"
8754
+ }]
8755
+ ]);
8756
+ /**
8757
+ * @license lucide-react v0.576.0 - ISC
8758
+ *
8759
+ * This source code is licensed under the ISC license.
8760
+ * See the LICENSE file in the root directory of this source tree.
8761
+ */
8632
8762
  var Cast = createLucideIcon("cast", [
8633
8763
  ["path", {
8634
8764
  d: "M2 8V6a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2h-6",
@@ -8656,6 +8786,30 @@ var Cast = createLucideIcon("cast", [
8656
8786
  * This source code is licensed under the ISC license.
8657
8787
  * See the LICENSE file in the root directory of this source tree.
8658
8788
  */
8789
+ var Cat = createLucideIcon("cat", [
8790
+ ["path", {
8791
+ d: "M12 5c.67 0 1.35.09 2 .26 1.78-2 5.03-2.84 6.42-2.26 1.4.58-.42 7-.42 7 .57 1.07 1 2.24 1 3.44C21 17.9 16.97 21 12 21s-9-3-9-7.56c0-1.25.5-2.4 1-3.44 0 0-1.89-6.42-.5-7 1.39-.58 4.72.23 6.5 2.23A9.04 9.04 0 0 1 12 5Z",
8792
+ key: "x6xyqk"
8793
+ }],
8794
+ ["path", {
8795
+ d: "M8 14v.5",
8796
+ key: "1nzgdb"
8797
+ }],
8798
+ ["path", {
8799
+ d: "M16 14v.5",
8800
+ key: "1lajdz"
8801
+ }],
8802
+ ["path", {
8803
+ d: "M11.25 16.25h1.5L12 17l-.75-.75Z",
8804
+ key: "12kq1m"
8805
+ }]
8806
+ ]);
8807
+ /**
8808
+ * @license lucide-react v0.576.0 - ISC
8809
+ *
8810
+ * This source code is licensed under the ISC license.
8811
+ * See the LICENSE file in the root directory of this source tree.
8812
+ */
8659
8813
  var Check = createLucideIcon("check", [["path", {
8660
8814
  d: "M20 6 9 17l-5-5",
8661
8815
  key: "1gmf2c"
@@ -9239,6 +9393,34 @@ var Database = createLucideIcon("database", [
9239
9393
  * This source code is licensed under the ISC license.
9240
9394
  * See the LICENSE file in the root directory of this source tree.
9241
9395
  */
9396
+ var Dog = createLucideIcon("dog", [
9397
+ ["path", {
9398
+ d: "M11.25 16.25h1.5L12 17z",
9399
+ key: "w7jh35"
9400
+ }],
9401
+ ["path", {
9402
+ d: "M16 14v.5",
9403
+ key: "1lajdz"
9404
+ }],
9405
+ ["path", {
9406
+ d: "M4.42 11.247A13.152 13.152 0 0 0 4 14.556C4 18.728 7.582 21 12 21s8-2.272 8-6.444a11.702 11.702 0 0 0-.493-3.309",
9407
+ key: "u7s9ue"
9408
+ }],
9409
+ ["path", {
9410
+ d: "M8 14v.5",
9411
+ key: "1nzgdb"
9412
+ }],
9413
+ ["path", {
9414
+ d: "M8.5 8.5c-.384 1.05-1.083 2.028-2.344 2.5-1.931.722-3.576-.297-3.656-1-.113-.994 1.177-6.53 4-7 1.923-.321 3.651.845 3.651 2.235A7.497 7.497 0 0 1 14 5.277c0-1.39 1.844-2.598 3.767-2.277 2.823.47 4.113 6.006 4 7-.08.703-1.725 1.722-3.656 1-1.261-.472-1.855-1.45-2.239-2.5",
9415
+ key: "v8hric"
9416
+ }]
9417
+ ]);
9418
+ /**
9419
+ * @license lucide-react v0.576.0 - ISC
9420
+ *
9421
+ * This source code is licensed under the ISC license.
9422
+ * See the LICENSE file in the root directory of this source tree.
9423
+ */
9242
9424
  var DoorClosed = createLucideIcon("door-closed", [
9243
9425
  ["path", {
9244
9426
  d: "M10 12h.01",
@@ -10452,6 +10634,30 @@ var Network = createLucideIcon("network", [
10452
10634
  * This source code is licensed under the ISC license.
10453
10635
  * See the LICENSE file in the root directory of this source tree.
10454
10636
  */
10637
+ var Package = createLucideIcon("package", [
10638
+ ["path", {
10639
+ d: "M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z",
10640
+ key: "1a0edw"
10641
+ }],
10642
+ ["path", {
10643
+ d: "M12 22V12",
10644
+ key: "d0xqtd"
10645
+ }],
10646
+ ["polyline", {
10647
+ points: "3.29 7 12 12 20.71 7",
10648
+ key: "ousv84"
10649
+ }],
10650
+ ["path", {
10651
+ d: "m7.5 4.27 9 5.15",
10652
+ key: "1c824w"
10653
+ }]
10654
+ ]);
10655
+ /**
10656
+ * @license lucide-react v0.576.0 - ISC
10657
+ *
10658
+ * This source code is licensed under the ISC license.
10659
+ * See the LICENSE file in the root directory of this source tree.
10660
+ */
10455
10661
  var Pause = createLucideIcon("pause", [["rect", {
10456
10662
  x: "14",
10457
10663
  y: "3",
@@ -10536,6 +10742,16 @@ var Pipette = createLucideIcon("pipette", [
10536
10742
  * This source code is licensed under the ISC license.
10537
10743
  * See the LICENSE file in the root directory of this source tree.
10538
10744
  */
10745
+ var Plane = createLucideIcon("plane", [["path", {
10746
+ d: "M17.8 19.2 16 11l3.5-3.5C21 6 21.5 4 21 3c-1-.5-3 0-4.5 1.5L13 8 4.8 6.2c-.5-.1-.9.1-1.1.5l-.3.5c-.2.5-.1 1 .3 1.3L9 12l-2 3H4l-1 1 3 2 2 3 1-1v-3l3-2 3.5 5.3c.3.4.8.5 1.3.3l.5-.2c.4-.3.6-.7.5-1.2z",
10747
+ key: "1v9wt8"
10748
+ }]]);
10749
+ /**
10750
+ * @license lucide-react v0.576.0 - ISC
10751
+ *
10752
+ * This source code is licensed under the ISC license.
10753
+ * See the LICENSE file in the root directory of this source tree.
10754
+ */
10539
10755
  var Play = createLucideIcon("play", [["path", {
10540
10756
  d: "M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z",
10541
10757
  key: "10ikf1"
@@ -10810,6 +11026,26 @@ var RotateCw = createLucideIcon("rotate-cw", [["path", {
10810
11026
  * This source code is licensed under the ISC license.
10811
11027
  * See the LICENSE file in the root directory of this source tree.
10812
11028
  */
11029
+ var Sailboat = createLucideIcon("sailboat", [
11030
+ ["path", {
11031
+ d: "M10 2v15",
11032
+ key: "1qf71f"
11033
+ }],
11034
+ ["path", {
11035
+ d: "M7 22a4 4 0 0 1-4-4 1 1 0 0 1 1-1h16a1 1 0 0 1 1 1 4 4 0 0 1-4 4z",
11036
+ key: "1pxcvx"
11037
+ }],
11038
+ ["path", {
11039
+ d: "M9.159 2.46a1 1 0 0 1 1.521-.193l9.977 8.98A1 1 0 0 1 20 13H4a1 1 0 0 1-.824-1.567z",
11040
+ key: "5oog16"
11041
+ }]
11042
+ ]);
11043
+ /**
11044
+ * @license lucide-react v0.576.0 - ISC
11045
+ *
11046
+ * This source code is licensed under the ISC license.
11047
+ * See the LICENSE file in the root directory of this source tree.
11048
+ */
10813
11049
  var Save = createLucideIcon("save", [
10814
11050
  ["path", {
10815
11051
  d: "M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z",
@@ -11475,6 +11711,22 @@ var Table2 = createLucideIcon("table-2", [["path", {
11475
11711
  * This source code is licensed under the ISC license.
11476
11712
  * See the LICENSE file in the root directory of this source tree.
11477
11713
  */
11714
+ var Tag = createLucideIcon("tag", [["path", {
11715
+ d: "M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z",
11716
+ key: "vktsd0"
11717
+ }], ["circle", {
11718
+ cx: "7.5",
11719
+ cy: "7.5",
11720
+ r: ".5",
11721
+ fill: "currentColor",
11722
+ key: "kqv944"
11723
+ }]]);
11724
+ /**
11725
+ * @license lucide-react v0.576.0 - ISC
11726
+ *
11727
+ * This source code is licensed under the ISC license.
11728
+ * See the LICENSE file in the root directory of this source tree.
11729
+ */
11478
11730
  var Target = createLucideIcon("target", [
11479
11731
  ["circle", {
11480
11732
  cx: "12",
@@ -11530,6 +11782,25 @@ var ToggleLeft = createLucideIcon("toggle-left", [["circle", {
11530
11782
  * This source code is licensed under the ISC license.
11531
11783
  * See the LICENSE file in the root directory of this source tree.
11532
11784
  */
11785
+ var ToggleRight = createLucideIcon("toggle-right", [["circle", {
11786
+ cx: "15",
11787
+ cy: "12",
11788
+ r: "3",
11789
+ key: "1afu0r"
11790
+ }], ["rect", {
11791
+ width: "20",
11792
+ height: "14",
11793
+ x: "2",
11794
+ y: "5",
11795
+ rx: "7",
11796
+ key: "g7kal2"
11797
+ }]]);
11798
+ /**
11799
+ * @license lucide-react v0.576.0 - ISC
11800
+ *
11801
+ * This source code is licensed under the ISC license.
11802
+ * See the LICENSE file in the root directory of this source tree.
11803
+ */
11533
11804
  var Tractor = createLucideIcon("tractor", [
11534
11805
  ["path", {
11535
11806
  d: "m10 11 11 .9a1 1 0 0 1 .8 1.1l-.665 4.158a1 1 0 0 1-.988.842H20",
@@ -11578,6 +11849,38 @@ var Tractor = createLucideIcon("tractor", [
11578
11849
  * This source code is licensed under the ISC license.
11579
11850
  * See the LICENSE file in the root directory of this source tree.
11580
11851
  */
11852
+ var TrainFront = createLucideIcon("train-front", [
11853
+ ["path", {
11854
+ d: "M8 3.1V7a4 4 0 0 0 8 0V3.1",
11855
+ key: "1v71zp"
11856
+ }],
11857
+ ["path", {
11858
+ d: "m9 15-1-1",
11859
+ key: "1yrq24"
11860
+ }],
11861
+ ["path", {
11862
+ d: "m15 15 1-1",
11863
+ key: "1t0d6s"
11864
+ }],
11865
+ ["path", {
11866
+ d: "M9 19c-2.8 0-5-2.2-5-5v-4a8 8 0 0 1 16 0v4c0 2.8-2.2 5-5 5Z",
11867
+ key: "1p0hjs"
11868
+ }],
11869
+ ["path", {
11870
+ d: "m8 19-2 3",
11871
+ key: "13i0xs"
11872
+ }],
11873
+ ["path", {
11874
+ d: "m16 19 2 3",
11875
+ key: "xo31yx"
11876
+ }]
11877
+ ]);
11878
+ /**
11879
+ * @license lucide-react v0.576.0 - ISC
11880
+ *
11881
+ * This source code is licensed under the ISC license.
11882
+ * See the LICENSE file in the root directory of this source tree.
11883
+ */
11581
11884
  var Trash2 = createLucideIcon("trash-2", [
11582
11885
  ["path", {
11583
11886
  d: "M10 11v6",
@@ -11652,6 +11955,38 @@ var TriangleAlert = createLucideIcon("triangle-alert", [
11652
11955
  * This source code is licensed under the ISC license.
11653
11956
  * See the LICENSE file in the root directory of this source tree.
11654
11957
  */
11958
+ var Truck = createLucideIcon("truck", [
11959
+ ["path", {
11960
+ d: "M14 18V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v11a1 1 0 0 0 1 1h2",
11961
+ key: "wrbu53"
11962
+ }],
11963
+ ["path", {
11964
+ d: "M15 18H9",
11965
+ key: "1lyqi6"
11966
+ }],
11967
+ ["path", {
11968
+ d: "M19 18h2a1 1 0 0 0 1-1v-3.65a1 1 0 0 0-.22-.624l-3.48-4.35A1 1 0 0 0 17.52 8H14",
11969
+ key: "lysw3i"
11970
+ }],
11971
+ ["circle", {
11972
+ cx: "17",
11973
+ cy: "18",
11974
+ r: "2",
11975
+ key: "332jqn"
11976
+ }],
11977
+ ["circle", {
11978
+ cx: "7",
11979
+ cy: "18",
11980
+ r: "2",
11981
+ key: "19iecd"
11982
+ }]
11983
+ ]);
11984
+ /**
11985
+ * @license lucide-react v0.576.0 - ISC
11986
+ *
11987
+ * This source code is licensed under the ISC license.
11988
+ * See the LICENSE file in the root directory of this source tree.
11989
+ */
11655
11990
  var Type = createLucideIcon("type", [
11656
11991
  ["path", {
11657
11992
  d: "M12 4v16",
@@ -11702,6 +12037,43 @@ var Upload = createLucideIcon("upload", [
11702
12037
  * This source code is licensed under the ISC license.
11703
12038
  * See the LICENSE file in the root directory of this source tree.
11704
12039
  */
12040
+ var UserCheck = createLucideIcon("user-check", [
12041
+ ["path", {
12042
+ d: "m16 11 2 2 4-4",
12043
+ key: "9rsbq5"
12044
+ }],
12045
+ ["path", {
12046
+ d: "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",
12047
+ key: "1yyitq"
12048
+ }],
12049
+ ["circle", {
12050
+ cx: "9",
12051
+ cy: "7",
12052
+ r: "4",
12053
+ key: "nufk8"
12054
+ }]
12055
+ ]);
12056
+ /**
12057
+ * @license lucide-react v0.576.0 - ISC
12058
+ *
12059
+ * This source code is licensed under the ISC license.
12060
+ * See the LICENSE file in the root directory of this source tree.
12061
+ */
12062
+ var User = createLucideIcon("user", [["path", {
12063
+ d: "M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2",
12064
+ key: "975kel"
12065
+ }], ["circle", {
12066
+ cx: "12",
12067
+ cy: "7",
12068
+ r: "4",
12069
+ key: "17ys0d"
12070
+ }]]);
12071
+ /**
12072
+ * @license lucide-react v0.576.0 - ISC
12073
+ *
12074
+ * This source code is licensed under the ISC license.
12075
+ * See the LICENSE file in the root directory of this source tree.
12076
+ */
11705
12077
  var UtensilsCrossed = createLucideIcon("utensils-crossed", [
11706
12078
  ["path", {
11707
12079
  d: "m16 2-2.3 2.3a3 3 0 0 0 0 4.2l1.8 1.8a3 3 0 0 0 4.2 0L22 8",
@@ -30827,28 +31199,28 @@ function PipelineBuilder({ schema, steps, onChange, templates, selectedTemplateI
30827
31199
  //#endregion
30828
31200
  //#region src/composites/detection-colors.ts
30829
31201
  /**
30830
- * Detection class colors — single source of truth.
31202
+ * Detection class colors — a thin adapter over the SINGLE event-kind
31203
+ * taxonomy dictionary in `@camstack/types` (`EVENT_TAXONOMY`). Colors are no
31204
+ * longer duplicated here; this module only adds the UI-only classes the
31205
+ * taxonomy doesn't model (face / plate) and the deterministic hash fallback.
30831
31206
  *
30832
- * Used by: DetectionCanvas (UI), result-annotator (server-side SVG),
30833
- * admin-ui event viewer, and any other place that visualizes detections.
31207
+ * Used by: DetectionCanvas / DetectionResultTree / DetectionOverlay (UI),
31208
+ * and any other place that visualizes detection classes.
30834
31209
  */
30835
- /** Fixed colors for known detection classes */
30836
- var CLASS_COLORS = {
30837
- person: "#3b82f6",
30838
- vehicle: "#f59e0b",
30839
- animal: "#22c55e",
31210
+ /** UI-only classes not modelled in the event taxonomy (sub-detections). */
31211
+ var UI_ONLY_COLORS = {
30840
31212
  face: "#a855f7",
30841
- plate: "#ec4899",
30842
- bird: "#14b8a6",
30843
- dog: "#84cc16",
30844
- cat: "#f97316",
30845
- car: "#f59e0b",
30846
- truck: "#d97706",
30847
- bus: "#b45309",
30848
- motorcycle: "#eab308",
30849
- bicycle: "#ca8a04",
30850
- motion: "#facc15"
31213
+ plate: "#ec4899"
30851
31214
  };
31215
+ /**
31216
+ * Fixed colors for known detection classes — derived from the taxonomy
31217
+ * (every detection/motion kind) plus the UI-only face/plate classes. Kept as
31218
+ * a named export for back-compat with existing consumers.
31219
+ */
31220
+ var CLASS_COLORS = Object.freeze({
31221
+ ...Object.fromEntries(Object.values(_camstack_types.EVENT_TAXONOMY).filter((e) => e.category === "detection" || e.kind === "motion").map((e) => [e.kind, e.color])),
31222
+ ...UI_ONLY_COLORS
31223
+ });
30852
31224
  /** Fallback color palette for unknown classes (deterministic hash-based) */
30853
31225
  var FALLBACK_PALETTE = [
30854
31226
  "#ef4444",
@@ -30863,19 +31235,113 @@ var FALLBACK_PALETTE = [
30863
31235
  "#059669"
30864
31236
  ];
30865
31237
  /** Primary/default color when nothing else matches */
30866
- var DEFAULT_COLOR = "#f59e42";
31238
+ var DEFAULT_COLOR = _camstack_types.DEFAULT_EVENT_COLOR;
30867
31239
  /**
30868
31240
  * Get the color for a detection class name.
30869
- * Returns a fixed color for known classes, or a deterministic hash-based color for unknown ones.
31241
+ * Resolves: custom override taxonomy/UI-only fixed color deterministic
31242
+ * hash-based color for unknown classes.
30870
31243
  */
30871
31244
  function getClassColor(className, customColors) {
30872
31245
  if (customColors?.[className]) return customColors[className];
30873
31246
  if (customColors?.[className.toLowerCase()]) return customColors[className.toLowerCase()];
31247
+ const fromTaxonomy = _camstack_types.EVENT_TAXONOMY[className] ?? _camstack_types.EVENT_TAXONOMY[className.toLowerCase()];
31248
+ if (fromTaxonomy !== void 0) return fromTaxonomy.color;
30874
31249
  if (CLASS_COLORS[className]) return CLASS_COLORS[className];
30875
31250
  if (CLASS_COLORS[className.toLowerCase()]) return CLASS_COLORS[className.toLowerCase()];
30876
31251
  let hash = 0;
30877
31252
  for (let i = 0; i < className.length; i++) hash = hash * 31 + (className.codePointAt(i) ?? 0) >>> 0;
30878
- return FALLBACK_PALETTE[hash % FALLBACK_PALETTE.length] ?? "#f59e42";
31253
+ return FALLBACK_PALETTE[hash % FALLBACK_PALETTE.length] ?? DEFAULT_COLOR;
31254
+ }
31255
+ //#endregion
31256
+ //#region src/composites/event-kind-visuals.tsx
31257
+ /**
31258
+ * Event-kind VISUALS — the UI-side half of the unified taxonomy dictionary
31259
+ * (`@camstack/types` `EVENT_TAXONOMY` owns the serializable data:
31260
+ * color / iconId / labelKey; this owns `iconId → lucide component` and
31261
+ * `labelKey → t()`).
31262
+ *
31263
+ * Every UI that renders an event kind (timeline, events tree, chips,
31264
+ * detection canvas/tree) resolves its glyph + translated label here — no
31265
+ * per-component hardcoded icon or label.
31266
+ */
31267
+ /**
31268
+ * `iconId` → lucide component. Built ONLY from statically-imported icons
31269
+ * (bundle-safe). Unknown ids resolve to the neutral `Tag` fallback.
31270
+ */
31271
+ var EVENT_KIND_ICONS = {
31272
+ motion: Activity,
31273
+ audio: Volume2,
31274
+ person: User,
31275
+ vehicle: Car,
31276
+ animal: PawPrint,
31277
+ package: Package,
31278
+ sensor: Radio,
31279
+ control: SlidersHorizontal,
31280
+ car: Car,
31281
+ truck: Truck,
31282
+ bus: Bus,
31283
+ motorcycle: Bike,
31284
+ bicycle: Bike,
31285
+ airplane: Plane,
31286
+ boat: Sailboat,
31287
+ train: TrainFront,
31288
+ bird: Bird,
31289
+ cat: Cat,
31290
+ dog: Dog,
31291
+ horse: PawPrint,
31292
+ sheep: PawPrint,
31293
+ cow: PawPrint,
31294
+ elephant: PawPrint,
31295
+ bear: PawPrint,
31296
+ zebra: PawPrint,
31297
+ giraffe: PawPrint,
31298
+ door: DoorOpen,
31299
+ pir: Radar,
31300
+ smoke: Flame,
31301
+ water: Droplet,
31302
+ gas: Wind,
31303
+ vibration: Vibrate,
31304
+ tamper: ShieldAlert,
31305
+ presence: UserCheck,
31306
+ generic: Tag,
31307
+ lock: Lock,
31308
+ siren: Siren,
31309
+ switch: ToggleRight,
31310
+ doorbell: BellRing,
31311
+ button: CircleDot,
31312
+ "audio-speech": MessageSquare,
31313
+ "audio-music": Music,
31314
+ "audio-dog": Dog,
31315
+ "audio-doorbell": BellRing,
31316
+ "audio-siren": Siren,
31317
+ "audio-glass_breaking": TriangleAlert,
31318
+ "audio-alarm": TriangleAlert
31319
+ };
31320
+ /** Resolve an `iconId` to a lucide component (falls back to `Tag`). */
31321
+ function resolveEventKindIcon(iconId) {
31322
+ if (Object.hasOwn(EVENT_KIND_ICONS, iconId)) return EVENT_KIND_ICONS[iconId];
31323
+ if (iconId.startsWith("audio-")) return Volume2;
31324
+ return Tag;
31325
+ }
31326
+ /**
31327
+ * Translated label for an event kind — `t(labelKey)` when a translation
31328
+ * exists, else the English `label` fallback. Robust to a missing key: an
31329
+ * i18n backend that echoes the key unchanged (react-i18next default) is
31330
+ * treated as "no translation" and the fallback label is returned, so the UI
31331
+ * never renders a raw `eventKind.*` key.
31332
+ */
31333
+ function eventKindLabel(descriptor, t) {
31334
+ if (t === void 0) return descriptor.label;
31335
+ const translated = t(descriptor.labelKey);
31336
+ return translated === descriptor.labelKey || translated.length === 0 ? descriptor.label : translated;
31337
+ }
31338
+ /** Small convenience component: renders the lucide glyph for an `iconId`. */
31339
+ function EventKindGlyph({ iconId, size = 16, color, className }) {
31340
+ return (0, react$1.createElement)(resolveEventKindIcon(iconId), {
31341
+ size,
31342
+ color,
31343
+ className
31344
+ });
30879
31345
  }
30880
31346
  //#endregion
30881
31347
  //#region src/composites/detection-canvas.tsx
@@ -32524,6 +32990,294 @@ function mountAddonPage(PageComponent, options = {}) {
32524
32990
  }));
32525
32991
  }
32526
32992
  //#endregion
32993
+ //#region src/composites/device-select-filter.ts
32994
+ /** True when two string lists share at least one member. */
32995
+ function intersects(a, b) {
32996
+ if (a.length === 0 || b.length === 0) return false;
32997
+ const set = new Set(a);
32998
+ return b.some((v) => set.has(v));
32999
+ }
33000
+ /**
33001
+ * Does a device satisfy the filter?
33002
+ *
33003
+ * Union match: with an empty/absent filter every device passes; otherwise the
33004
+ * device passes when ANY provided clause matches — its `features` intersect
33005
+ * `caps`, OR its `type` is in `types`. `excludeDeviceId` is subtracted last
33006
+ * (it always drops the device regardless of the other clauses).
33007
+ */
33008
+ function deviceMatchesFilter(device, filter) {
33009
+ if (filter?.excludeDeviceId !== void 0 && device.id === filter.excludeDeviceId) return false;
33010
+ const hasCaps = filter?.caps !== void 0 && filter.caps.length > 0;
33011
+ const hasTypes = filter?.types !== void 0 && filter.types.length > 0;
33012
+ if (!hasCaps && !hasTypes) return true;
33013
+ if (hasCaps && intersects(device.features ?? [], filter.caps)) return true;
33014
+ if (hasTypes && filter.types.includes(device.type)) return true;
33015
+ return false;
33016
+ }
33017
+ /** Human label for a device option: `Name (Location)` when a location is set. */
33018
+ function deviceOptionLabel(device) {
33019
+ return typeof device.location === "string" && device.location.length > 0 ? `${device.name} (${device.location})` : device.name;
33020
+ }
33021
+ /**
33022
+ * Filter a device list and project it into sorted `{ value, label }` options
33023
+ * (value = the device id as a string). Sorted case-insensitively by label so
33024
+ * the picker order is stable.
33025
+ */
33026
+ function devicesToOptions(devices, filter) {
33027
+ return devices.filter((d) => deviceMatchesFilter(d, filter)).map((d) => ({
33028
+ value: String(d.id),
33029
+ label: deviceOptionLabel(d)
33030
+ })).toSorted((a, b) => a.label.localeCompare(b.label));
33031
+ }
33032
+ /**
33033
+ * Free-text option filter — case-insensitive AND over whitespace tokens, each
33034
+ * matched against the option's `value` + `label` (so a device is found by name,
33035
+ * id, or location). An empty query returns every option in order.
33036
+ */
33037
+ function filterDeviceOptions(options, query) {
33038
+ const tokens = query.trim().toLowerCase().split(/\s+/).filter(Boolean);
33039
+ if (tokens.length === 0) return [...options];
33040
+ return options.filter((opt) => {
33041
+ const hay = `${opt.value} ${opt.label}`.toLowerCase();
33042
+ return tokens.every((t) => hay.includes(t));
33043
+ });
33044
+ }
33045
+ /**
33046
+ * Resolve the currently-selected values into options IN SELECTION ORDER (so
33047
+ * chips stay stable while searching). A selected value with no matching option
33048
+ * becomes a synthetic `{ value, label: value }` — a stale id still shows as a
33049
+ * removable chip rather than silently vanishing.
33050
+ */
33051
+ function selectedDeviceOptions(options, selected) {
33052
+ const byValue = new Map(options.map((o) => [o.value, o]));
33053
+ return selected.map((v) => byValue.get(v) ?? {
33054
+ value: v,
33055
+ label: v
33056
+ });
33057
+ }
33058
+ //#endregion
33059
+ //#region src/composites/device-select-field.tsx
33060
+ /**
33061
+ * `device-select` / `device-multiselect` renderers.
33062
+ *
33063
+ * Both fetch EVERY system device via `deviceManager.listAll` and narrow the
33064
+ * options CLIENT-SIDE with the field's declarative `deviceFilter` (see
33065
+ * `device-select-filter.ts`). No server-computed option list is involved —
33066
+ * the form field carries only the filter. Value(s) are device ids as strings.
33067
+ *
33068
+ * The multi variant mirrors the "Linked devices" searchable combobox UX
33069
+ * (removable chips + typeahead dropdown); the single variant is a native
33070
+ * select. Both are inline in ui-library (like `node-select`) so any host that
33071
+ * renders the shared form field gets them without extra registration.
33072
+ */
33073
+ var INPUT_CLASS$1 = "w-full rounded-md border border-border bg-background px-2.5 py-1.5 text-xs text-foreground focus:border-primary focus:ring-1 focus:ring-primary/30 outline-none disabled:opacity-50 disabled:cursor-not-allowed";
33074
+ var INPUT_SHELL = "flex items-center gap-1.5 rounded-md border border-border bg-background px-2 py-1.5 focus-within:border-primary focus-within:ring-1 focus-within:ring-primary/30";
33075
+ var LABEL_CLASS$1 = "block text-[11px] font-medium text-foreground mb-1 break-words";
33076
+ var DESC_CLASS$1 = "text-[10px] text-foreground-subtle mt-0.5 break-words";
33077
+ /** The compact projection of the listAll rows the device fields consume. */
33078
+ function toCandidates(rows) {
33079
+ if (!Array.isArray(rows)) return [];
33080
+ const out = [];
33081
+ for (const row of rows) {
33082
+ if (typeof row !== "object" || row === null) continue;
33083
+ const r = row;
33084
+ if (typeof r.id !== "number" || typeof r.type !== "string" || typeof r.name !== "string") continue;
33085
+ out.push({
33086
+ id: r.id,
33087
+ type: r.type,
33088
+ name: r.name,
33089
+ location: typeof r.location === "string" ? r.location : null,
33090
+ features: Array.isArray(r.features) ? r.features.filter((f) => typeof f === "string") : []
33091
+ });
33092
+ }
33093
+ return out;
33094
+ }
33095
+ function FieldShell({ label, description, required, translationFn, children }) {
33096
+ const resolvedLabel = resolveLabel(label, translationFn);
33097
+ const resolvedDescription = resolveLabel(description, translationFn);
33098
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
33099
+ className: "min-w-0",
33100
+ children: [
33101
+ resolvedLabel !== void 0 && resolvedLabel !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
33102
+ className: LABEL_CLASS$1,
33103
+ children: [resolvedLabel, required && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
33104
+ className: "text-danger ml-0.5",
33105
+ children: "*"
33106
+ })]
33107
+ }),
33108
+ children,
33109
+ resolvedDescription && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
33110
+ className: DESC_CLASS$1,
33111
+ children: resolvedDescription
33112
+ })
33113
+ ]
33114
+ });
33115
+ }
33116
+ function DeviceSelectField({ field, value, onChange, disabled, translationFn }) {
33117
+ const { data } = useDeviceManagerListAll({});
33118
+ const options = (0, react$1.useMemo)(() => devicesToOptions(toCandidates(data), field.deviceFilter), [data, field.deviceFilter]);
33119
+ const current = value === void 0 || value === null ? "" : String(value);
33120
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FieldShell, {
33121
+ label: field.label,
33122
+ description: field.description,
33123
+ required: field.required,
33124
+ translationFn,
33125
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
33126
+ className: INPUT_CLASS$1,
33127
+ value: current,
33128
+ disabled: disabled || field.disabled,
33129
+ onChange: (e) => onChange(e.target.value),
33130
+ children: [!field.required && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
33131
+ value: "",
33132
+ children: "— Select device —"
33133
+ }), options.map((opt) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
33134
+ value: opt.value,
33135
+ children: opt.label
33136
+ }, opt.value))]
33137
+ })
33138
+ });
33139
+ }
33140
+ function DeviceMultiSelectField({ field, value, onChange, disabled, translationFn }) {
33141
+ const { data } = useDeviceManagerListAll({});
33142
+ const options = (0, react$1.useMemo)(() => devicesToOptions(toCandidates(data), field.deviceFilter), [data, field.deviceFilter]);
33143
+ const selected = Array.isArray(value) ? value.map(String) : [];
33144
+ const isDisabled = disabled === true || field.disabled === true;
33145
+ const atMax = field.maxItems !== void 0 && selected.length >= field.maxItems;
33146
+ const [query, setQuery] = (0, react$1.useState)("");
33147
+ const [open, setOpen] = (0, react$1.useState)(false);
33148
+ const [highlight, setHighlight] = (0, react$1.useState)(0);
33149
+ const inputRef = (0, react$1.useRef)(null);
33150
+ const blurTimer = (0, react$1.useRef)(null);
33151
+ const selectedOptions = (0, react$1.useMemo)(() => selectedDeviceOptions(options, selected), [options, selected]);
33152
+ const filtered = (0, react$1.useMemo)(() => filterDeviceOptions(options, query), [options, query]);
33153
+ const toggle = (optValue) => {
33154
+ if (isDisabled) return;
33155
+ if (selected.includes(optValue)) onChange(selected.filter((v) => v !== optValue));
33156
+ else {
33157
+ if (field.maxItems !== void 0 && selected.length >= field.maxItems) return;
33158
+ onChange([...selected, optValue]);
33159
+ }
33160
+ };
33161
+ const handleKeyDown = (e) => {
33162
+ if (e.key === "ArrowDown") {
33163
+ e.preventDefault();
33164
+ setOpen(true);
33165
+ setHighlight((h) => filtered.length === 0 ? 0 : (h + 1) % filtered.length);
33166
+ } else if (e.key === "ArrowUp") {
33167
+ e.preventDefault();
33168
+ setOpen(true);
33169
+ setHighlight((h) => filtered.length === 0 ? 0 : (h - 1 + filtered.length) % filtered.length);
33170
+ } else if (e.key === "Enter") {
33171
+ e.preventDefault();
33172
+ const opt = filtered[highlight];
33173
+ if (opt) toggle(opt.value);
33174
+ } else if (e.key === "Escape") setOpen(false);
33175
+ else if (e.key === "Backspace" && query === "" && selected.length > 0) onChange(selected.slice(0, -1));
33176
+ };
33177
+ const label = resolveLabel(field.label, translationFn);
33178
+ const description = resolveLabel(field.description, translationFn);
33179
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
33180
+ className: "min-w-0",
33181
+ children: [
33182
+ label !== void 0 && label !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
33183
+ className: LABEL_CLASS$1,
33184
+ children: label
33185
+ }),
33186
+ selectedOptions.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
33187
+ className: "flex flex-wrap gap-1 mb-1.5",
33188
+ children: selectedOptions.map((opt) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
33189
+ className: "inline-flex items-center gap-1 rounded-md bg-primary/10 px-1.5 py-0.5 text-[11px] text-primary max-w-full",
33190
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
33191
+ className: "truncate",
33192
+ children: opt.label
33193
+ }), !isDisabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
33194
+ type: "button",
33195
+ className: "shrink-0 hover:text-danger",
33196
+ "aria-label": `Remove ${opt.label}`,
33197
+ onClick: () => toggle(opt.value),
33198
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(X, { className: "h-2.5 w-2.5" })
33199
+ })]
33200
+ }, opt.value))
33201
+ }),
33202
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
33203
+ className: INPUT_SHELL + (isDisabled ? " opacity-50" : ""),
33204
+ children: [
33205
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Search, { className: "h-3.5 w-3.5 shrink-0 text-foreground-subtle" }),
33206
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
33207
+ ref: inputRef,
33208
+ type: "text",
33209
+ role: "combobox",
33210
+ "aria-expanded": open,
33211
+ "aria-controls": `dsel-${field.key}`,
33212
+ className: "min-w-0 flex-1 bg-transparent text-xs text-foreground outline-none placeholder:text-foreground-disabled",
33213
+ value: query,
33214
+ placeholder: atMax ? `Max ${field.maxItems} selected` : field.placeholder ?? "Search devices…",
33215
+ disabled: isDisabled,
33216
+ onChange: (e) => {
33217
+ setQuery(e.target.value);
33218
+ setOpen(true);
33219
+ setHighlight(0);
33220
+ },
33221
+ onFocus: () => setOpen(true),
33222
+ onBlur: () => {
33223
+ blurTimer.current = setTimeout(() => setOpen(false), 120);
33224
+ },
33225
+ onKeyDown: handleKeyDown
33226
+ }),
33227
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChevronDown, {
33228
+ className: "h-3.5 w-3.5 shrink-0 cursor-pointer text-foreground-subtle",
33229
+ onMouseDown: (e) => {
33230
+ e.preventDefault();
33231
+ if (blurTimer.current) clearTimeout(blurTimer.current);
33232
+ setOpen((o) => !o);
33233
+ inputRef.current?.focus();
33234
+ }
33235
+ })
33236
+ ]
33237
+ }),
33238
+ open && !isDisabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
33239
+ id: `dsel-${field.key}`,
33240
+ role: "listbox",
33241
+ className: "mt-1 max-h-56 overflow-y-auto rounded-md border border-border bg-surface shadow-lg",
33242
+ onMouseDown: (e) => {
33243
+ e.preventDefault();
33244
+ },
33245
+ children: filtered.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
33246
+ className: "px-2.5 py-2 text-[11px] text-foreground-subtle italic",
33247
+ children: options.length === 0 ? "No matching devices" : `No matches for “${query}”`
33248
+ }) : filtered.map((opt, i) => {
33249
+ const checked = selected.includes(opt.value);
33250
+ const blockedByMax = !checked && atMax;
33251
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
33252
+ type: "button",
33253
+ role: "option",
33254
+ "aria-selected": checked,
33255
+ disabled: blockedByMax,
33256
+ className: [
33257
+ "flex w-full items-center gap-2 px-2.5 py-1.5 text-left text-xs transition-colors",
33258
+ i === highlight ? "bg-primary/10" : "hover:bg-surface-hover",
33259
+ blockedByMax ? "opacity-40 cursor-not-allowed" : "cursor-pointer"
33260
+ ].join(" "),
33261
+ onMouseEnter: () => setHighlight(i),
33262
+ onClick: () => toggle(opt.value),
33263
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
33264
+ className: ["flex h-3.5 w-3.5 shrink-0 items-center justify-center rounded border", checked ? "border-primary bg-primary text-white" : "border-border"].join(" "),
33265
+ children: checked && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Check, { className: "h-2.5 w-2.5" })
33266
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
33267
+ className: "truncate text-foreground",
33268
+ children: opt.label
33269
+ })]
33270
+ }, opt.value);
33271
+ })
33272
+ }),
33273
+ description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
33274
+ className: DESC_CLASS$1,
33275
+ children: description
33276
+ })
33277
+ ]
33278
+ });
33279
+ }
33280
+ //#endregion
32527
33281
  //#region src/contexts/custom-field-renderers.tsx
32528
33282
  /**
32529
33283
  * Custom field renderer registry.
@@ -38506,6 +39260,20 @@ function FormField({ field, values, onChange, disabled, translationFn, onTestFie
38506
39260
  disabled,
38507
39261
  translationFn
38508
39262
  });
39263
+ case "device-select": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceSelectField, {
39264
+ field,
39265
+ value,
39266
+ onChange: handleChange,
39267
+ disabled,
39268
+ translationFn
39269
+ });
39270
+ case "device-multiselect": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceMultiSelectField, {
39271
+ field,
39272
+ value,
39273
+ onChange: handleChange,
39274
+ disabled,
39275
+ translationFn
39276
+ });
38509
39277
  case "probe": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProbeField, {
38510
39278
  field,
38511
39279
  value,
@@ -45748,6 +46516,8 @@ exports.DeviceExportPanel = DeviceExportPanel;
45748
46516
  exports.DeviceGrid = DeviceGrid;
45749
46517
  exports.DeviceItem = DeviceItem;
45750
46518
  exports.DeviceList = DeviceList;
46519
+ exports.DeviceMultiSelectField = DeviceMultiSelectField;
46520
+ exports.DeviceSelectField = DeviceSelectField;
45751
46521
  exports.Dialog = Dialog;
45752
46522
  exports.DialogContent = DialogContent;
45753
46523
  exports.DialogDescription = DialogDescription;
@@ -45763,8 +46533,10 @@ exports.DropdownItem = DropdownItem;
45763
46533
  exports.DropdownTrigger = DropdownTrigger;
45764
46534
  exports.DummyHeroCard = DummyHeroCard;
45765
46535
  exports.DummyInline = DummyInline;
46536
+ exports.EVENT_KIND_ICONS = EVENT_KIND_ICONS;
45766
46537
  exports.EmptyState = EmptyState;
45767
46538
  exports.ErrorBox = ErrorBox;
46539
+ exports.EventKindGlyph = EventKindGlyph;
45768
46540
  exports.EventStream = EventStream;
45769
46541
  exports.EyeOff = EyeOff;
45770
46542
  exports.FILL = FILL;
@@ -45930,11 +46702,16 @@ exports.cursorFractionFor = cursorFractionFor;
45930
46702
  exports.darkColors = require_theme_index.darkColors$1;
45931
46703
  exports.defaultTheme = require_theme_index.defaultTheme$1;
45932
46704
  exports.deriveDeviceKind = deriveDeviceKind;
46705
+ exports.deviceMatchesFilter = deviceMatchesFilter;
46706
+ exports.deviceOptionLabel = deviceOptionLabel;
45933
46707
  exports.deviceRoleMeta = deviceRoleMeta;
45934
46708
  exports.deviceRoleMetaOf = deviceRoleMetaOf;
45935
46709
  exports.deviceTypeMeta = deviceTypeMeta;
45936
46710
  exports.deviceTypeMetaOf = deviceTypeMetaOf;
46711
+ exports.devicesToOptions = devicesToOptions;
45937
46712
  exports.ensureMfHostInit = ensureMfHostInit;
46713
+ exports.eventKindLabel = eventKindLabel;
46714
+ exports.filterDeviceOptions = filterDeviceOptions;
45938
46715
  exports.findTimezone = _camstack_types.findTimezone;
45939
46716
  exports.formatControlDateTime = formatControlDateTime;
45940
46717
  exports.formatLastSeen = formatLastSeen;
@@ -45966,9 +46743,11 @@ exports.resolveContainerPrimary = resolveContainerPrimary;
45966
46743
  exports.resolveControlAlign = resolveControlAlign;
45967
46744
  exports.resolveDeviceControl = resolveDeviceControl;
45968
46745
  exports.resolveDisplayIcon = resolveDisplayIcon;
46746
+ exports.resolveEventKindIcon = resolveEventKindIcon;
45969
46747
  exports.resolvePrimaryChild = resolvePrimaryChild;
45970
46748
  exports.resolveSensorDisplay = resolveSensorDisplay;
45971
46749
  exports.scrubReducer = scrubReducer;
46750
+ exports.selectedDeviceOptions = selectedDeviceOptions;
45972
46751
  exports.serializeRecordedCommand = serializeRecordedCommand;
45973
46752
  exports.shouldCommit = shouldCommit;
45974
46753
  exports.shouldEmit = shouldEmit;