@camstack/ui-library 0.1.50 → 0.1.52

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
@@ -1,29 +1,30 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  //#region \0rolldown/runtime.js
3
3
  var __create = Object.create;
4
- var __defProp = Object.defineProperty;
4
+ var __defProp$1 = Object.defineProperty;
5
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __getProtoOf = Object.getPrototypeOf;
8
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
9
9
  var __copyProps = (to, from, except, desc) => {
10
10
  if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
11
  key = keys[i];
12
- if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ if (!__hasOwnProp$1.call(to, key) && key !== except) __defProp$1(to, key, {
13
13
  get: ((k) => from[k]).bind(null, key),
14
14
  enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
15
  });
16
16
  }
17
17
  return to;
18
18
  };
19
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp$1(target, "default", {
20
20
  value: mod,
21
21
  enumerable: true
22
22
  }) : target, mod));
23
23
  //#endregion
24
24
  const require_theme_index = require("./theme/index.cjs");
25
25
  let react = require("react");
26
- react = __toESM(react, 1);
26
+ let react$1 = __toESM(react, 1);
27
+ react = __toESM(react);
27
28
  let react_jsx_runtime = require("react/jsx-runtime");
28
29
  react_jsx_runtime = __toESM(react_jsx_runtime, 1);
29
30
  let react_dom = require("react-dom");
@@ -38,6 +39,7 @@ let _trpc_react_query = require("@trpc/react-query");
38
39
  _trpc_react_query = __toESM(_trpc_react_query, 1);
39
40
  let _camstack_types = require("@camstack/types");
40
41
  let _camstack_sdk = require("@camstack/sdk");
42
+ let zod = require("zod");
41
43
  //#region ../../node_modules/clsx/dist/clsx.mjs
42
44
  function r(e) {
43
45
  var t, f, n = "";
@@ -3590,13 +3592,13 @@ function getPhaseVisual(phase) {
3590
3592
  * the Map is typed as `Context<unknown>`).
3591
3593
  */
3592
3594
  function createSharedContext(name, defaultValue) {
3593
- if (typeof globalThis === "undefined") return (0, react.createContext)(defaultValue);
3595
+ if (typeof globalThis === "undefined") return (0, react$1.createContext)(defaultValue);
3594
3596
  const existingMap = globalThis.__camstackSharedContexts;
3595
3597
  const map = existingMap ?? /* @__PURE__ */ new Map();
3596
3598
  if (!existingMap) globalThis.__camstackSharedContexts = map;
3597
3599
  const existing = map.get(name);
3598
3600
  if (existing) return existing;
3599
- const ctx = (0, react.createContext)(defaultValue);
3601
+ const ctx = (0, react$1.createContext)(defaultValue);
3600
3602
  map.set(name, ctx);
3601
3603
  return ctx;
3602
3604
  }
@@ -6866,7 +6868,7 @@ function getModuleCache() {
6866
6868
  }
6867
6869
  function populateShareCache() {
6868
6870
  const cache = getModuleCache();
6869
- cache.share["react"] ??= react;
6871
+ cache.share["react"] ??= react$1;
6870
6872
  cache.share["react-dom"] ??= react_dom;
6871
6873
  cache.share["react-dom/client"] ??= react_dom_client;
6872
6874
  cache.share["react/jsx-runtime"] ??= react_jsx_runtime;
@@ -6884,7 +6886,7 @@ function ensureMfHostInit() {
6884
6886
  name: "admin_ui_host",
6885
6887
  remotes: [],
6886
6888
  shared: {
6887
- "react": npmShared(() => react),
6889
+ "react": npmShared(() => react$1),
6888
6890
  "react-dom": npmShared(() => react_dom),
6889
6891
  "react-dom/client": npmShared(() => react_dom_client),
6890
6892
  "react/jsx-runtime": npmShared(() => react_jsx_runtime),
@@ -7991,6 +7993,68 @@ var PowerOff = createLucideIcon("power-off", [
7991
7993
  key: "1ooewy"
7992
7994
  }]
7993
7995
  ]);
7996
+ var QrCode$1 = createLucideIcon("qr-code", [
7997
+ ["rect", {
7998
+ width: "5",
7999
+ height: "5",
8000
+ x: "3",
8001
+ y: "3",
8002
+ rx: "1",
8003
+ key: "1tu5fj"
8004
+ }],
8005
+ ["rect", {
8006
+ width: "5",
8007
+ height: "5",
8008
+ x: "16",
8009
+ y: "3",
8010
+ rx: "1",
8011
+ key: "1v8r4q"
8012
+ }],
8013
+ ["rect", {
8014
+ width: "5",
8015
+ height: "5",
8016
+ x: "3",
8017
+ y: "16",
8018
+ rx: "1",
8019
+ key: "1x03jg"
8020
+ }],
8021
+ ["path", {
8022
+ d: "M21 16h-3a2 2 0 0 0-2 2v3",
8023
+ key: "177gqh"
8024
+ }],
8025
+ ["path", {
8026
+ d: "M21 21v.01",
8027
+ key: "ents32"
8028
+ }],
8029
+ ["path", {
8030
+ d: "M12 7v3a2 2 0 0 1-2 2H7",
8031
+ key: "8crl2c"
8032
+ }],
8033
+ ["path", {
8034
+ d: "M3 12h.01",
8035
+ key: "nlz23k"
8036
+ }],
8037
+ ["path", {
8038
+ d: "M12 3h.01",
8039
+ key: "n36tog"
8040
+ }],
8041
+ ["path", {
8042
+ d: "M12 16v.01",
8043
+ key: "133mhm"
8044
+ }],
8045
+ ["path", {
8046
+ d: "M16 12h1",
8047
+ key: "1slzba"
8048
+ }],
8049
+ ["path", {
8050
+ d: "M21 12v.01",
8051
+ key: "1lwtk9"
8052
+ }],
8053
+ ["path", {
8054
+ d: "M12 21v-1",
8055
+ key: "1880an"
8056
+ }]
8057
+ ]);
7994
8058
  var Radar = createLucideIcon("radar", [
7995
8059
  ["path", {
7996
8060
  d: "M19.07 4.93A10 10 0 0 0 6.99 3.34",
@@ -8176,6 +8240,40 @@ var Server = createLucideIcon("server", [
8176
8240
  key: "nzw8ys"
8177
8241
  }]
8178
8242
  ]);
8243
+ var Share2 = createLucideIcon("share-2", [
8244
+ ["circle", {
8245
+ cx: "18",
8246
+ cy: "5",
8247
+ r: "3",
8248
+ key: "gq8acd"
8249
+ }],
8250
+ ["circle", {
8251
+ cx: "6",
8252
+ cy: "12",
8253
+ r: "3",
8254
+ key: "w7nqdw"
8255
+ }],
8256
+ ["circle", {
8257
+ cx: "18",
8258
+ cy: "19",
8259
+ r: "3",
8260
+ key: "1xt0gg"
8261
+ }],
8262
+ ["line", {
8263
+ x1: "8.59",
8264
+ x2: "15.42",
8265
+ y1: "13.51",
8266
+ y2: "17.49",
8267
+ key: "47mynk"
8268
+ }],
8269
+ ["line", {
8270
+ x1: "15.41",
8271
+ x2: "8.59",
8272
+ y1: "6.51",
8273
+ y2: "10.49",
8274
+ key: "1n3mei"
8275
+ }]
8276
+ ]);
8179
8277
  var Shield = createLucideIcon("shield", [["path", {
8180
8278
  d: "M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",
8181
8279
  key: "oel41y"
@@ -8383,6 +8481,10 @@ var TriangleAlert = createLucideIcon("triangle-alert", [
8383
8481
  key: "p32p05"
8384
8482
  }]
8385
8483
  ]);
8484
+ var Unlink2 = createLucideIcon("unlink-2", [["path", {
8485
+ d: "M15 7h2a5 5 0 0 1 0 10h-2m-6 0H7A5 5 0 0 1 7 7h2",
8486
+ key: "1re2ne"
8487
+ }]]);
8386
8488
  var Upload = createLucideIcon("upload", [
8387
8489
  ["path", {
8388
8490
  d: "M12 3v12",
@@ -8603,7 +8705,7 @@ var buttonVariants = cva("inline-flex items-center justify-center rounded-md fon
8603
8705
  size: "sm"
8604
8706
  }
8605
8707
  });
8606
- var Button = (0, react.forwardRef)(({ className, variant, size, ...props }, ref) => {
8708
+ var Button = (0, react$1.forwardRef)(({ className, variant, size, ...props }, ref) => {
8607
8709
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
8608
8710
  ref,
8609
8711
  className: cn(buttonVariants({
@@ -8636,7 +8738,7 @@ var iconButtonVariants = cva("inline-flex items-center justify-center rounded-md
8636
8738
  size: "sm"
8637
8739
  }
8638
8740
  });
8639
- var IconButton = (0, react.forwardRef)(({ className, variant, size, icon: Icon, ...props }, ref) => {
8741
+ var IconButton = (0, react$1.forwardRef)(({ className, variant, size, icon: Icon, ...props }, ref) => {
8640
8742
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
8641
8743
  ref,
8642
8744
  className: cn(iconButtonVariants({
@@ -8669,7 +8771,7 @@ var badgeVariants = cva("inline-flex items-center rounded-full text-xs font-medi
8669
8771
  styleVariant: "solid"
8670
8772
  }
8671
8773
  });
8672
- var Badge = (0, react.forwardRef)(({ className, variant, style, ...props }, ref) => {
8774
+ var Badge = (0, react$1.forwardRef)(({ className, variant, style, ...props }, ref) => {
8673
8775
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8674
8776
  ref,
8675
8777
  className: cn(badgeVariants({
@@ -8689,7 +8791,7 @@ var cardVariants = cva("rounded-lg p-3", {
8689
8791
  } },
8690
8792
  defaultVariants: { variant: "bordered" }
8691
8793
  });
8692
- var Card = (0, react.forwardRef)(({ className, variant, ...props }, ref) => {
8794
+ var Card = (0, react$1.forwardRef)(({ className, variant, ...props }, ref) => {
8693
8795
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8694
8796
  ref,
8695
8797
  className: cn(cardVariants({ variant }), className),
@@ -8725,7 +8827,7 @@ function CollapsibleCard({ expanded, onExpandedChange, header, children, dimmed
8725
8827
  }
8726
8828
  //#endregion
8727
8829
  //#region src/primitives/label.tsx
8728
- var Label = (0, react.forwardRef)(({ className, ...props }, ref) => {
8830
+ var Label = (0, react$1.forwardRef)(({ className, ...props }, ref) => {
8729
8831
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
8730
8832
  ref,
8731
8833
  className: cn("text-[10px] uppercase tracking-wider text-foreground-muted font-medium", className),
@@ -8742,7 +8844,7 @@ var separatorVariants = cva("", {
8742
8844
  } },
8743
8845
  defaultVariants: { orientation: "horizontal" }
8744
8846
  });
8745
- var Separator = (0, react.forwardRef)(({ className, orientation, ...props }, ref) => {
8847
+ var Separator = (0, react$1.forwardRef)(({ className, orientation, ...props }, ref) => {
8746
8848
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8747
8849
  ref,
8748
8850
  role: "separator",
@@ -8753,7 +8855,7 @@ var Separator = (0, react.forwardRef)(({ className, orientation, ...props }, ref
8753
8855
  Separator.displayName = "Separator";
8754
8856
  //#endregion
8755
8857
  //#region src/primitives/skeleton.tsx
8756
- var Skeleton = (0, react.forwardRef)(({ className, ...props }, ref) => {
8858
+ var Skeleton = (0, react$1.forwardRef)(({ className, ...props }, ref) => {
8757
8859
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8758
8860
  ref,
8759
8861
  className: cn("animate-pulse bg-surface-hover rounded-md h-4 w-full", className),
@@ -8770,7 +8872,7 @@ var inputVariants = cva("h-7 w-full px-2.5 text-xs bg-surface border rounded-md
8770
8872
  } },
8771
8873
  defaultVariants: { state: "default" }
8772
8874
  });
8773
- var Input = (0, react.forwardRef)(({ className, state, leftSlot, rightSlot, ...props }, ref) => {
8875
+ var Input = (0, react$1.forwardRef)(({ className, state, leftSlot, rightSlot, ...props }, ref) => {
8774
8876
  if (leftSlot || rightSlot) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8775
8877
  className: "relative flex items-center w-full",
8776
8878
  children: [
@@ -8798,7 +8900,7 @@ var Input = (0, react.forwardRef)(({ className, state, leftSlot, rightSlot, ...p
8798
8900
  Input.displayName = "Input";
8799
8901
  //#endregion
8800
8902
  //#region src/primitives/select.tsx
8801
- var Select = (0, react.forwardRef)(({ className, options, ...props }, ref) => {
8903
+ var Select = (0, react$1.forwardRef)(({ className, options, ...props }, ref) => {
8802
8904
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8803
8905
  className: "relative w-full",
8804
8906
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
@@ -8818,7 +8920,7 @@ var Select = (0, react.forwardRef)(({ className, options, ...props }, ref) => {
8818
8920
  Select.displayName = "Select";
8819
8921
  //#endregion
8820
8922
  //#region src/primitives/checkbox.tsx
8821
- var Checkbox = (0, react.forwardRef)(({ className, ...props }, ref) => {
8923
+ var Checkbox = (0, react$1.forwardRef)(({ className, ...props }, ref) => {
8822
8924
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
8823
8925
  ref,
8824
8926
  type: "checkbox",
@@ -8829,7 +8931,7 @@ var Checkbox = (0, react.forwardRef)(({ className, ...props }, ref) => {
8829
8931
  Checkbox.displayName = "Checkbox";
8830
8932
  //#endregion
8831
8933
  //#region src/primitives/switch.tsx
8832
- var Switch = (0, react.forwardRef)(({ className, checked, onCheckedChange, label, ...props }, ref) => {
8934
+ var Switch = (0, react$1.forwardRef)(({ className, checked, onCheckedChange, label, ...props }, ref) => {
8833
8935
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
8834
8936
  ref,
8835
8937
  role: "switch",
@@ -8850,17 +8952,17 @@ var Switch = (0, react.forwardRef)(({ className, checked, onCheckedChange, label
8850
8952
  Switch.displayName = "Switch";
8851
8953
  //#endregion
8852
8954
  //#region src/primitives/dialog.tsx
8853
- var DialogContext = (0, react.createContext)(null);
8955
+ var DialogContext = (0, react$1.createContext)(null);
8854
8956
  function useDialogContext() {
8855
- const ctx = (0, react.useContext)(DialogContext);
8957
+ const ctx = (0, react$1.useContext)(DialogContext);
8856
8958
  if (!ctx) throw new Error("Dialog compound components must be used within <Dialog>");
8857
8959
  return ctx;
8858
8960
  }
8859
8961
  function Dialog({ children, open: controlledOpen, onOpenChange }) {
8860
- const [uncontrolledOpen, setUncontrolledOpen] = (0, react.useState)(false);
8962
+ const [uncontrolledOpen, setUncontrolledOpen] = (0, react$1.useState)(false);
8861
8963
  const open = controlledOpen ?? uncontrolledOpen;
8862
- const contentId = (0, react.useId)();
8863
- const setOpen = (0, react.useCallback)((next) => {
8964
+ const contentId = (0, react$1.useId)();
8965
+ const setOpen = (0, react$1.useCallback)((next) => {
8864
8966
  onOpenChange?.(next);
8865
8967
  if (controlledOpen === void 0) setUncontrolledOpen(next);
8866
8968
  }, [controlledOpen, onOpenChange]);
@@ -8890,11 +8992,11 @@ var contentVariants = cva("bg-background-elevated border border-border rounded-l
8890
8992
  } },
8891
8993
  defaultVariants: { width: "md" }
8892
8994
  });
8893
- var DialogContent = (0, react.forwardRef)(({ className, width, children, ...props }, ref) => {
8995
+ var DialogContent = (0, react$1.forwardRef)(({ className, width, children, ...props }, ref) => {
8894
8996
  const { open, setOpen, contentId } = useDialogContext();
8895
- const innerRef = (0, react.useRef)(null);
8997
+ const innerRef = (0, react$1.useRef)(null);
8896
8998
  const dialogRef = ref ?? innerRef;
8897
- (0, react.useEffect)(() => {
8999
+ (0, react$1.useEffect)(() => {
8898
9000
  const el = dialogRef.current;
8899
9001
  if (!el) return;
8900
9002
  if (open && !el.open) el.showModal();
@@ -8940,17 +9042,17 @@ function DialogDescription({ className, ...props }) {
8940
9042
  }
8941
9043
  //#endregion
8942
9044
  //#region src/primitives/dropdown.tsx
8943
- var DropdownContext = (0, react.createContext)(null);
9045
+ var DropdownContext = (0, react$1.createContext)(null);
8944
9046
  function useDropdownContext() {
8945
- const ctx = (0, react.useContext)(DropdownContext);
9047
+ const ctx = (0, react$1.useContext)(DropdownContext);
8946
9048
  if (!ctx) throw new Error("Dropdown compound components must be used within <Dropdown>");
8947
9049
  return ctx;
8948
9050
  }
8949
9051
  function Dropdown({ children }) {
8950
- const [open, setOpen] = (0, react.useState)(false);
8951
- const triggerId = (0, react.useId)();
8952
- const contentId = (0, react.useId)();
8953
- const triggerRef = (0, react.useRef)(null);
9052
+ const [open, setOpen] = (0, react$1.useState)(false);
9053
+ const triggerId = (0, react$1.useId)();
9054
+ const contentId = (0, react$1.useId)();
9055
+ const triggerRef = (0, react$1.useRef)(null);
8954
9056
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DropdownContext.Provider, {
8955
9057
  value: {
8956
9058
  open,
@@ -8981,9 +9083,9 @@ function DropdownTrigger({ children, ...props }) {
8981
9083
  }
8982
9084
  function DropdownContent({ className, children, align = "start", offset = 4, ...props }) {
8983
9085
  const { open, setOpen, contentId, triggerId, triggerRef } = useDropdownContext();
8984
- const ref = (0, react.useRef)(null);
8985
- const [coords, setCoords] = (0, react.useState)(null);
8986
- (0, react.useLayoutEffect)(() => {
9086
+ const ref = (0, react$1.useRef)(null);
9087
+ const [coords, setCoords] = (0, react$1.useState)(null);
9088
+ (0, react$1.useLayoutEffect)(() => {
8987
9089
  if (!open) {
8988
9090
  setCoords(null);
8989
9091
  return;
@@ -9012,7 +9114,7 @@ function DropdownContent({ className, children, align = "start", offset = 4, ...
9012
9114
  offset,
9013
9115
  triggerRef
9014
9116
  ]);
9015
- (0, react.useEffect)(() => {
9117
+ (0, react$1.useEffect)(() => {
9016
9118
  if (!open) return;
9017
9119
  const handler = (e) => {
9018
9120
  const el = ref.current;
@@ -9052,7 +9154,7 @@ function DropdownContent({ className, children, align = "start", offset = 4, ...
9052
9154
  }
9053
9155
  function DropdownItem({ className, icon: Icon, variant = "default", children, onClick, ...props }) {
9054
9156
  const { setOpen } = useDropdownContext();
9055
- const handleClick = (0, react.useCallback)((e) => {
9157
+ const handleClick = (0, react$1.useCallback)((e) => {
9056
9158
  onClick?.(e);
9057
9159
  setOpen(false);
9058
9160
  }, [onClick, setOpen]);
@@ -9067,16 +9169,16 @@ function DropdownItem({ className, icon: Icon, variant = "default", children, on
9067
9169
  }
9068
9170
  //#endregion
9069
9171
  //#region src/primitives/tooltip.tsx
9070
- var TooltipContext = (0, react.createContext)(null);
9172
+ var TooltipContext = (0, react$1.createContext)(null);
9071
9173
  function useTooltipContext() {
9072
- const ctx = (0, react.useContext)(TooltipContext);
9174
+ const ctx = (0, react$1.useContext)(TooltipContext);
9073
9175
  if (!ctx) throw new Error("Tooltip compound components must be used within <Tooltip>");
9074
9176
  return ctx;
9075
9177
  }
9076
9178
  function Tooltip({ children }) {
9077
- const [open, setOpen] = (0, react.useState)(false);
9078
- const timerRef = (0, react.useRef)(null);
9079
- const tooltipId = (0, react.useId)();
9179
+ const [open, setOpen] = (0, react$1.useState)(false);
9180
+ const timerRef = (0, react$1.useRef)(null);
9181
+ const tooltipId = (0, react$1.useId)();
9080
9182
  const show = () => {
9081
9183
  timerRef.current = setTimeout(() => setOpen(true), 300);
9082
9184
  };
@@ -9143,7 +9245,7 @@ function getServerSnapshot() {
9143
9245
  return false;
9144
9246
  }
9145
9247
  function useIsMobile() {
9146
- return (0, react.useSyncExternalStore)(subscribeQuery(MOBILE_QUERY), getSnapshot(MOBILE_QUERY), getServerSnapshot);
9248
+ return (0, react$1.useSyncExternalStore)(subscribeQuery(MOBILE_QUERY), getSnapshot(MOBILE_QUERY), getServerSnapshot);
9147
9249
  }
9148
9250
  /**
9149
9251
  * True when the viewport is in the medium (`md`) Tailwind range —
@@ -9152,12 +9254,12 @@ function useIsMobile() {
9152
9254
  * sidebar rail, narrower stat tiles).
9153
9255
  */
9154
9256
  function useIsMidWidth() {
9155
- return (0, react.useSyncExternalStore)(subscribeQuery(MID_QUERY), getSnapshot(MID_QUERY), getServerSnapshot);
9257
+ return (0, react$1.useSyncExternalStore)(subscribeQuery(MID_QUERY), getSnapshot(MID_QUERY), getServerSnapshot);
9156
9258
  }
9157
9259
  //#endregion
9158
9260
  //#region src/primitives/bottom-sheet.tsx
9159
9261
  function BottomSheet({ open, onClose, title, children, className }) {
9160
- (0, react.useEffect)(() => {
9262
+ (0, react$1.useEffect)(() => {
9161
9263
  if (!open) return;
9162
9264
  const handleKeyDown = (e) => {
9163
9265
  if (e.key === "Escape") onClose();
@@ -9202,18 +9304,18 @@ function BottomSheet({ open, onClose, title, children, className }) {
9202
9304
  }
9203
9305
  //#endregion
9204
9306
  //#region src/primitives/popover.tsx
9205
- var PopoverContext = (0, react.createContext)(null);
9307
+ var PopoverContext = (0, react$1.createContext)(null);
9206
9308
  function usePopoverContext() {
9207
- const ctx = (0, react.useContext)(PopoverContext);
9309
+ const ctx = (0, react$1.useContext)(PopoverContext);
9208
9310
  if (!ctx) throw new Error("Popover compound components must be used within <Popover>");
9209
9311
  return ctx;
9210
9312
  }
9211
9313
  function Popover({ children, open: controlledOpen, onOpenChange }) {
9212
- const [uncontrolledOpen, setUncontrolledOpen] = (0, react.useState)(false);
9314
+ const [uncontrolledOpen, setUncontrolledOpen] = (0, react$1.useState)(false);
9213
9315
  const open = controlledOpen ?? uncontrolledOpen;
9214
- const triggerId = (0, react.useId)();
9215
- const contentId = (0, react.useId)();
9216
- const setOpen = (0, react.useCallback)((next) => {
9316
+ const triggerId = (0, react$1.useId)();
9317
+ const contentId = (0, react$1.useId)();
9318
+ const setOpen = (0, react$1.useCallback)((next) => {
9217
9319
  onOpenChange?.(next);
9218
9320
  if (controlledOpen === void 0) setUncontrolledOpen(next);
9219
9321
  }, [controlledOpen, onOpenChange]);
@@ -9246,8 +9348,8 @@ function PopoverTrigger({ children, ...props }) {
9246
9348
  function PopoverContent({ className, children, ...props }) {
9247
9349
  const { open, setOpen, contentId, triggerId } = usePopoverContext();
9248
9350
  const isMobile = useIsMobile();
9249
- const ref = (0, react.useRef)(null);
9250
- (0, react.useEffect)(() => {
9351
+ const ref = (0, react$1.useRef)(null);
9352
+ (0, react$1.useEffect)(() => {
9251
9353
  if (!open || isMobile) return;
9252
9354
  const handler = (e) => {
9253
9355
  const el = ref.current;
@@ -9287,16 +9389,16 @@ function PopoverContent({ className, children, ...props }) {
9287
9389
  }
9288
9390
  //#endregion
9289
9391
  //#region src/primitives/tabs.tsx
9290
- var TabsContext = (0, react.createContext)(null);
9392
+ var TabsContext = (0, react$1.createContext)(null);
9291
9393
  function useTabsContext() {
9292
- const ctx = (0, react.useContext)(TabsContext);
9394
+ const ctx = (0, react$1.useContext)(TabsContext);
9293
9395
  if (!ctx) throw new Error("Tabs compound components must be used within <Tabs>");
9294
9396
  return ctx;
9295
9397
  }
9296
9398
  function Tabs({ value: controlledValue, onValueChange, defaultValue = "", className, ...props }) {
9297
- const [uncontrolledValue, setUncontrolledValue] = (0, react.useState)(defaultValue);
9399
+ const [uncontrolledValue, setUncontrolledValue] = (0, react$1.useState)(defaultValue);
9298
9400
  const value = controlledValue ?? uncontrolledValue;
9299
- const setValue = (0, react.useCallback)((next) => {
9401
+ const setValue = (0, react$1.useCallback)((next) => {
9300
9402
  onValueChange?.(next);
9301
9403
  if (controlledValue === void 0) setUncontrolledValue(next);
9302
9404
  }, [controlledValue, onValueChange]);
@@ -9344,7 +9446,7 @@ function TabsContent({ value, className, ...props }) {
9344
9446
  }
9345
9447
  //#endregion
9346
9448
  //#region src/primitives/scroll-area.tsx
9347
- var ScrollArea = (0, react.forwardRef)(({ className, ...props }, ref) => {
9449
+ var ScrollArea = (0, react$1.forwardRef)(({ className, ...props }, ref) => {
9348
9450
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
9349
9451
  ref,
9350
9452
  className: cn("overflow-auto [&::-webkit-scrollbar]:w-1 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:bg-surface-hover [&::-webkit-scrollbar-thumb]:rounded-full", className),
@@ -9355,23 +9457,23 @@ ScrollArea.displayName = "ScrollArea";
9355
9457
  //#endregion
9356
9458
  //#region src/primitives/floating-panel.tsx
9357
9459
  function FloatingPanel({ title, onClose, children, defaultWidth = 360, defaultHeight = 280, minWidth = 280, minHeight = 160, offsetIndex = 0, className }) {
9358
- const [pos, setPos] = (0, react.useState)({
9460
+ const [pos, setPos] = (0, react$1.useState)({
9359
9461
  x: 80 + offsetIndex * 30,
9360
9462
  y: 80 + offsetIndex * 30
9361
9463
  });
9362
- const [size, setSize] = (0, react.useState)({
9464
+ const [size, setSize] = (0, react$1.useState)({
9363
9465
  w: defaultWidth,
9364
9466
  h: defaultHeight
9365
9467
  });
9366
- const [minimized, setMinimized] = (0, react.useState)(false);
9367
- const dragging = (0, react.useRef)(false);
9368
- const resizing = (0, react.useRef)(false);
9369
- const offset = (0, react.useRef)({
9468
+ const [minimized, setMinimized] = (0, react$1.useState)(false);
9469
+ const dragging = (0, react$1.useRef)(false);
9470
+ const resizing = (0, react$1.useRef)(false);
9471
+ const offset = (0, react$1.useRef)({
9370
9472
  x: 0,
9371
9473
  y: 0
9372
9474
  });
9373
9475
  const isMobile = useIsMobile();
9374
- const onDragStart = (0, react.useCallback)((e) => {
9476
+ const onDragStart = (0, react$1.useCallback)((e) => {
9375
9477
  e.preventDefault();
9376
9478
  dragging.current = true;
9377
9479
  offset.current = {
@@ -9379,7 +9481,7 @@ function FloatingPanel({ title, onClose, children, defaultWidth = 360, defaultHe
9379
9481
  y: e.clientY - pos.y
9380
9482
  };
9381
9483
  }, [pos]);
9382
- const onResizeStart = (0, react.useCallback)((e) => {
9484
+ const onResizeStart = (0, react$1.useCallback)((e) => {
9383
9485
  e.preventDefault();
9384
9486
  e.stopPropagation();
9385
9487
  resizing.current = true;
@@ -9388,7 +9490,7 @@ function FloatingPanel({ title, onClose, children, defaultWidth = 360, defaultHe
9388
9490
  y: e.clientY
9389
9491
  };
9390
9492
  }, []);
9391
- (0, react.useEffect)(() => {
9493
+ (0, react$1.useEffect)(() => {
9392
9494
  const onMouseMove = (e) => {
9393
9495
  if (dragging.current) setPos({
9394
9496
  x: e.clientX - offset.current.x,
@@ -9493,8 +9595,8 @@ function FloatingPanel({ title, onClose, children, defaultWidth = 360, defaultHe
9493
9595
  //#endregion
9494
9596
  //#region src/primitives/mobile-drawer.tsx
9495
9597
  function MobileDrawer({ open, onClose, children, className, width = "w-64" }) {
9496
- const drawerRef = (0, react.useRef)(null);
9497
- (0, react.useEffect)(() => {
9598
+ const drawerRef = (0, react$1.useRef)(null);
9599
+ (0, react$1.useEffect)(() => {
9498
9600
  if (!open) return;
9499
9601
  const handleKeyDown = (e) => {
9500
9602
  if (e.key === "Escape") onClose();
@@ -9538,7 +9640,7 @@ function Breadcrumb({ items, className }) {
9538
9640
  children: items.map((item, i) => {
9539
9641
  const isLast = i === items.length - 1;
9540
9642
  const isClickable = !isLast && (item.onClick || item.href);
9541
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.default.Fragment, { children: [i > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChevronRight, { className: "h-3 w-3 flex-shrink-0" }), isClickable ? item.onClick ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
9643
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react$1.default.Fragment, { children: [i > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChevronRight, { className: "h-3 w-3 flex-shrink-0" }), isClickable ? item.onClick ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
9542
9644
  type: "button",
9543
9645
  onClick: item.onClick,
9544
9646
  className: "hover:text-foreground transition-colors",
@@ -9614,7 +9716,7 @@ function DataTable({ columns, rows, rowKey, onRowClick, minWidthPx = 480, emptyM
9614
9716
  //#endregion
9615
9717
  //#region src/composites/slide-over-panel.tsx
9616
9718
  function SlideOverPanel({ open, onClose, title, subtitle, footer, children, widthClass = "w-[360px]" }) {
9617
- (0, react.useEffect)(() => {
9719
+ (0, react$1.useEffect)(() => {
9618
9720
  if (!open) return;
9619
9721
  const onEsc = (e) => {
9620
9722
  if (e.key === "Escape") onClose();
@@ -9757,7 +9859,7 @@ function modelsForStep(schema) {
9757
9859
  }));
9758
9860
  }
9759
9861
  function PipelineStep({ step, schema, allSchemas: _allSchemas, depth: _depth = 0, onChange, onDelete: _onDelete, readOnly = false, toggleMode = "simple", overrideState = null, onOverrideChange, inheritedEnabled, hideModelAndSettings = false }) {
9760
- const [expanded, setExpanded] = (0, react.useState)(false);
9862
+ const [expanded, setExpanded] = (0, react$1.useState)(false);
9761
9863
  const models = modelsForStep(schema);
9762
9864
  if (models.length > 0 && !models.some((m) => m.id === step.modelId) && !readOnly) {
9763
9865
  const fallback = (schema?.defaultModelId ? models.find((m) => m.id === schema.defaultModelId) : null) ?? models[0];
@@ -10308,7 +10410,7 @@ function DeviceModeEditor({ addon, agentDefault, agentNodeId, currentPatch, mode
10308
10410
  }
10309
10411
  function AgentStepEditor(props) {
10310
10412
  const { mode, addon, agentDefault, agentNodeId, currentPatch, onChangeAgentConfig, onChangePatch, engineFormat } = props;
10311
- const modelsForFormat = (0, react.useMemo)(() => addon.models.filter((m) => Boolean(m.formats[engineFormat])), [addon.models, engineFormat]);
10413
+ const modelsForFormat = (0, react$1.useMemo)(() => addon.models.filter((m) => Boolean(m.formats[engineFormat])), [addon.models, engineFormat]);
10312
10414
  if (mode === "agent") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AgentModeEditor, {
10313
10415
  addon,
10314
10416
  agentDefault,
@@ -10458,7 +10560,7 @@ function Row({ node, depth, agents, getCellState, onCellClick, selectedCell, tog
10458
10560
  })] });
10459
10561
  }
10460
10562
  function PipelineTreeMatrix({ tree, agents, getCellState, onCellClick, selectedCell, onToggleEnabled }) {
10461
- const rows = (0, react.useMemo)(() => flattenTree(tree), [tree]);
10563
+ const rows = (0, react$1.useMemo)(() => flattenTree(tree), [tree]);
10462
10564
  const gridTemplate = `minmax(320px, 1fr) repeat(${agents.length}, minmax(160px, 220px))`;
10463
10565
  const showToggle = onToggleEnabled !== void 0 && agents.length === 1;
10464
10566
  const onlyAgent = agents[0]?.agentNodeId;
@@ -10564,7 +10666,7 @@ function SystemProvider({ system, children }) {
10564
10666
  * relies on the system, so a clear error beats a silent null.
10565
10667
  */
10566
10668
  function useSystem() {
10567
- const sys = (0, react.useContext)(SystemContext);
10669
+ const sys = (0, react$1.useContext)(SystemContext);
10568
10670
  if (!sys) throw new Error("useSystem(): no <SystemProvider> in tree");
10569
10671
  return sys;
10570
10672
  }
@@ -10574,7 +10676,7 @@ function useSystem() {
10574
10676
  * (boot-time splash screens etc.).
10575
10677
  */
10576
10678
  function useOptionalSystem() {
10577
- return (0, react.useContext)(SystemContext);
10679
+ return (0, react$1.useContext)(SystemContext);
10578
10680
  }
10579
10681
  //#endregion
10580
10682
  //#region src/hooks/use-live-event.ts
@@ -10590,15 +10692,15 @@ function useOptionalSystem() {
10590
10692
  */
10591
10693
  function useLiveEvent(category, cb) {
10592
10694
  const system = useSystem();
10593
- const cbRef = (0, react.useRef)(cb);
10695
+ const cbRef = (0, react$1.useRef)(cb);
10594
10696
  cbRef.current = cb;
10595
- const [tick, setTick] = (0, react.useState)(system.connectionVersion);
10596
- (0, react.useEffect)(() => {
10697
+ const [tick, setTick] = (0, react$1.useState)(system.connectionVersion);
10698
+ (0, react$1.useEffect)(() => {
10597
10699
  return system.subscribeConnectionEvents((state, version) => {
10598
10700
  if (state === "connected") setTick(version);
10599
10701
  });
10600
10702
  }, [system]);
10601
- (0, react.useEffect)(() => {
10703
+ (0, react$1.useEffect)(() => {
10602
10704
  return system.subscribeEvent(category, (evt) => {
10603
10705
  cbRef.current(evt);
10604
10706
  });
@@ -10617,12 +10719,12 @@ function useLiveEvent(category, cb) {
10617
10719
  * useEventStreamMap — same but accumulates per-key payloads into a map.
10618
10720
  */
10619
10721
  function useFreshRef(value) {
10620
- const ref = (0, react.useRef)(value);
10722
+ const ref = (0, react$1.useRef)(value);
10621
10723
  ref.current = value;
10622
10724
  return ref;
10623
10725
  }
10624
10726
  function useEventStreamLatest(category, filter) {
10625
- const [data, setData] = (0, react.useState)(null);
10727
+ const [data, setData] = (0, react$1.useState)(null);
10626
10728
  const filterRef = useFreshRef(filter);
10627
10729
  useLiveEvent(category, (evt) => {
10628
10730
  const payload = evt.data;
@@ -10633,7 +10735,7 @@ function useEventStreamLatest(category, filter) {
10633
10735
  return data;
10634
10736
  }
10635
10737
  function useEventStreamMap(category, keyOf, filter) {
10636
- const [map, setMap] = (0, react.useState)(() => /* @__PURE__ */ new Map());
10738
+ const [map, setMap] = (0, react$1.useState)(() => /* @__PURE__ */ new Map());
10637
10739
  const keyOfRef = useFreshRef(keyOf);
10638
10740
  const filterRef = useFreshRef(filter);
10639
10741
  useLiveEvent(category, (evt) => {
@@ -10649,7 +10751,7 @@ function useEventStreamMap(category, keyOf, filter) {
10649
10751
  });
10650
10752
  return {
10651
10753
  map,
10652
- values: (0, react.useMemo)(() => Array.from(map.values()), [map])
10754
+ values: (0, react$1.useMemo)(() => Array.from(map.values()), [map])
10653
10755
  };
10654
10756
  }
10655
10757
  //#endregion
@@ -10669,7 +10771,7 @@ function useClusterNodes() {
10669
10771
  const { data: bootstrapTopology, isLoading } = trpc.nodes.topology.useQuery(void 0, { staleTime: 6e4 });
10670
10772
  const sourceNodes = useEventStreamLatest("cluster.topology-snapshot")?.nodes ?? bootstrapTopology;
10671
10773
  return {
10672
- nodes: (0, react.useMemo)(() => {
10774
+ nodes: (0, react$1.useMemo)(() => {
10673
10775
  const list = [];
10674
10776
  for (const n of sourceNodes ?? []) list.push({
10675
10777
  id: String(n.id ?? ""),
@@ -10803,7 +10905,7 @@ function ProviderBadge({ provider, showLabel = true, className }) {
10803
10905
  }
10804
10906
  //#endregion
10805
10907
  //#region src/composites/version-badge.tsx
10806
- var VARIANT_STYLES = {
10908
+ var VARIANT_STYLES$1 = {
10807
10909
  success: "bg-emerald-400 text-emerald-950",
10808
10910
  warning: "bg-amber-400 text-amber-950",
10809
10911
  danger: "bg-red-400 text-red-950",
@@ -10816,7 +10918,7 @@ var VARIANT_STYLES = {
10816
10918
  */
10817
10919
  function SemanticBadge({ children, variant = "neutral", mono, className }) {
10818
10920
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
10819
- className: cn("inline-flex items-center rounded-md px-2 py-0.5 text-[11px] font-bold leading-tight", mono && "font-mono", VARIANT_STYLES[variant], className),
10921
+ className: cn("inline-flex items-center rounded-md px-2 py-0.5 text-[11px] font-bold leading-tight", mono && "font-mono", VARIANT_STYLES$1[variant], className),
10820
10922
  children
10821
10923
  });
10822
10924
  }
@@ -10905,16 +11007,65 @@ function EmptyState({ icon: Icon, title, description, action, className }) {
10905
11007
  });
10906
11008
  }
10907
11009
  //#endregion
11010
+ //#region src/composites/error-box.tsx
11011
+ var VARIANT_STYLES = {
11012
+ danger: {
11013
+ box: "border-danger/40 bg-danger/10",
11014
+ icon: "text-danger",
11015
+ title: "text-danger",
11016
+ message: "text-danger"
11017
+ },
11018
+ warning: {
11019
+ box: "border-amber-500/40 bg-amber-500/10",
11020
+ icon: "text-amber-600 dark:text-amber-400",
11021
+ title: "text-amber-700 dark:text-amber-300",
11022
+ message: "text-amber-700 dark:text-amber-300"
11023
+ }
11024
+ };
11025
+ function ErrorBox({ message, title, onRetry, action, variant = "danger", className }) {
11026
+ const styles = VARIANT_STYLES[variant];
11027
+ const Icon = variant === "warning" ? TriangleAlert : CircleAlert;
11028
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
11029
+ role: "alert",
11030
+ className: cn("flex items-start gap-2.5 rounded border px-3 py-2.5", styles.box, className),
11031
+ children: [
11032
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
11033
+ className: cn("h-4 w-4 mt-0.5 shrink-0", styles.icon),
11034
+ "aria-hidden": "true"
11035
+ }),
11036
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
11037
+ className: "flex-1 min-w-0",
11038
+ children: [title && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
11039
+ className: cn("text-xs font-semibold", styles.title),
11040
+ children: title
11041
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
11042
+ className: cn("text-xs break-words", styles.message, title ? "mt-0.5" : ""),
11043
+ children: message
11044
+ })]
11045
+ }),
11046
+ action ?? (onRetry && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
11047
+ type: "button",
11048
+ onClick: onRetry,
11049
+ className: cn("shrink-0 inline-flex items-center gap-1 rounded px-2 py-1 text-[11px] font-medium", "border border-current/30 hover:bg-current/10 transition-colors", styles.message),
11050
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(RefreshCw, {
11051
+ className: "h-3 w-3",
11052
+ "aria-hidden": "true"
11053
+ }), "Retry"]
11054
+ }))
11055
+ ]
11056
+ });
11057
+ }
11058
+ //#endregion
10908
11059
  //#region src/composites/confirm-dialog.tsx
10909
11060
  var ConfirmContext = createSharedContext("camstack:confirm-dialog", null);
10910
11061
  function useConfirm() {
10911
- const ctx = (0, react.useContext)(ConfirmContext);
11062
+ const ctx = (0, react$1.useContext)(ConfirmContext);
10912
11063
  if (!ctx) throw new Error("useConfirm must be used within ConfirmDialogProvider");
10913
11064
  return ctx.confirm;
10914
11065
  }
10915
11066
  function ConfirmDialogProvider({ children }) {
10916
- const [dialog, setDialog] = (0, react.useState)(null);
10917
- const confirm = (0, react.useCallback)((options) => {
11067
+ const [dialog, setDialog] = (0, react$1.useState)(null);
11068
+ const confirm = (0, react$1.useCallback)((options) => {
10918
11069
  return new Promise((resolve) => {
10919
11070
  setDialog({
10920
11071
  ...options,
@@ -11026,8 +11177,8 @@ function KeyValueList({ items, className }) {
11026
11177
  //#endregion
11027
11178
  //#region src/composites/code-block.tsx
11028
11179
  function CodeBlock({ children, maxHeight = 300, className }) {
11029
- const [copied, setCopied] = (0, react.useState)(false);
11030
- const handleCopy = (0, react.useCallback)(() => {
11180
+ const [copied, setCopied] = (0, react$1.useState)(false);
11181
+ const handleCopy = (0, react$1.useCallback)(() => {
11031
11182
  navigator.clipboard.writeText(children).then(() => {
11032
11183
  setCopied(true);
11033
11184
  setTimeout(() => setCopied(false), 2e3);
@@ -11057,7 +11208,7 @@ function CodeBlock({ children, maxHeight = 300, className }) {
11057
11208
  //#region src/composites/filter-bar.tsx
11058
11209
  function FilterBar({ filters, values, onChange, className }) {
11059
11210
  const isMobile = useIsMobile();
11060
- const [sheetOpen, setSheetOpen] = (0, react.useState)(false);
11211
+ const [sheetOpen, setSheetOpen] = (0, react$1.useState)(false);
11061
11212
  const handleChange = (key, value) => {
11062
11213
  onChange({
11063
11214
  ...values,
@@ -11222,7 +11373,7 @@ function Sidebar({ logo, sections, footer, onNavigate, className }) {
11222
11373
  //#region src/composites/app-shell/app-shell.tsx
11223
11374
  function AppShell({ sidebar, header, mobileLogo, mobileActions, children, className }) {
11224
11375
  const isMobile = useIsMobile();
11225
- const [drawerOpen, setDrawerOpen] = (0, react.useState)(false);
11376
+ const [drawerOpen, setDrawerOpen] = (0, react$1.useState)(false);
11226
11377
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
11227
11378
  className: cn("flex h-screen", className),
11228
11379
  children: [
@@ -11408,8 +11559,8 @@ var BINDING_CHANGED_CATEGORY = "capability.binding-changed";
11408
11559
  * when `deviceId` is null. Re-rendered when bindings change.
11409
11560
  */
11410
11561
  function useDeviceProxy(trpc, deviceId) {
11411
- const [binding, setBinding] = (0, react.useState)(null);
11412
- (0, react.useEffect)(() => {
11562
+ const [binding, setBinding] = (0, react$1.useState)(null);
11563
+ (0, react$1.useEffect)(() => {
11413
11564
  if (deviceId === null) {
11414
11565
  setBinding(null);
11415
11566
  return;
@@ -11437,7 +11588,7 @@ function useDeviceProxy(trpc, deviceId) {
11437
11588
  sub?.unsubscribe();
11438
11589
  };
11439
11590
  }, [trpc, deviceId]);
11440
- return (0, react.useMemo)(() => {
11591
+ return (0, react$1.useMemo)(() => {
11441
11592
  if (!binding) return null;
11442
11593
  return (0, _camstack_types.createDeviceProxy)(trpc, binding);
11443
11594
  }, [trpc, binding]);
@@ -11461,12 +11612,12 @@ function useDeviceProxy(trpc, deviceId) {
11461
11612
  * de-dups identical pushes).
11462
11613
  */
11463
11614
  function useDeviceStateSlice(handle) {
11464
- const subscribe = (0, react.useCallback)((notify) => {
11615
+ const subscribe = (0, react$1.useCallback)((notify) => {
11465
11616
  if (!handle) return () => void 0;
11466
11617
  return handle.subscribe(() => notify());
11467
11618
  }, [handle]);
11468
- const getSnapshot = (0, react.useCallback)(() => handle?.value, [handle]);
11469
- return (0, react.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
11619
+ const getSnapshot = (0, react$1.useCallback)(() => handle?.value, [handle]);
11620
+ return (0, react$1.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
11470
11621
  }
11471
11622
  /**
11472
11623
  * One-line combinator — collapse the common
@@ -11751,7 +11902,7 @@ function ChildSwitchToggle({ trpc, deviceId }) {
11751
11902
  cap: (d) => d.switch,
11752
11903
  slice: (d) => d.state.switch
11753
11904
  });
11754
- const [pending, setPending] = (0, react.useState)(false);
11905
+ const [pending, setPending] = (0, react$1.useState)(false);
11755
11906
  if (dev !== null && !cap) return null;
11756
11907
  const on = slice?.on === true;
11757
11908
  const knobStyle = { transform: on ? "translateX(14px)" : "translateX(2px)" };
@@ -11789,7 +11940,7 @@ function ChildMotionTriggerToggle({ trpc, deviceId, features }) {
11789
11940
  requireFeature: "motion-trigger",
11790
11941
  deviceFeatures: features
11791
11942
  });
11792
- const [pending, setPending] = (0, react.useState)(false);
11943
+ const [pending, setPending] = (0, react$1.useState)(false);
11793
11944
  if (dev !== null && !cap) return null;
11794
11945
  const on = slice?.enabled === true;
11795
11946
  const handleClick = async (e) => {
@@ -11867,7 +12018,7 @@ function SwitchToggle({ trpc, deviceId }) {
11867
12018
  cap: (d) => d.switch,
11868
12019
  slice: (d) => d.state.switch
11869
12020
  });
11870
- const [pending, setPending] = (0, react.useState)(false);
12021
+ const [pending, setPending] = (0, react$1.useState)(false);
11871
12022
  if (dev !== null && !cap) return null;
11872
12023
  const on = slice?.on === true;
11873
12024
  const knobStyle = { transform: on ? "translateX(14px)" : "translateX(2px)" };
@@ -11905,7 +12056,7 @@ function OnMotionToggle({ trpc, deviceId, features }) {
11905
12056
  requireFeature: "motion-trigger",
11906
12057
  deviceFeatures: features
11907
12058
  });
11908
- const [pending, setPending] = (0, react.useState)(false);
12059
+ const [pending, setPending] = (0, react$1.useState)(false);
11909
12060
  if (dev !== null && !cap) return null;
11910
12061
  const on = slice?.enabled === true;
11911
12062
  const handleClick = async (e) => {
@@ -11939,10 +12090,10 @@ function MoreActionsMenu({ trpc, deviceId }) {
11939
12090
  cap: (d) => d.reboot,
11940
12091
  slice: () => void 0
11941
12092
  });
11942
- const triggerRef = (0, react.useRef)(null);
11943
- const menuRef = (0, react.useRef)(null);
11944
- const [position, setPosition] = (0, react.useState)(null);
11945
- const [pending, setPending] = (0, react.useState)(false);
12093
+ const triggerRef = (0, react$1.useRef)(null);
12094
+ const menuRef = (0, react$1.useRef)(null);
12095
+ const [position, setPosition] = (0, react$1.useState)(null);
12096
+ const [pending, setPending] = (0, react$1.useState)(false);
11946
12097
  const ready = dev !== null && cap !== void 0 && cap !== null;
11947
12098
  const isOpen = position !== null;
11948
12099
  const close = () => setPosition(null);
@@ -11957,7 +12108,7 @@ function MoreActionsMenu({ trpc, deviceId }) {
11957
12108
  left
11958
12109
  });
11959
12110
  };
11960
- (0, react.useEffect)(() => {
12111
+ (0, react$1.useEffect)(() => {
11961
12112
  if (!isOpen) return;
11962
12113
  const onMouseDown = (e) => {
11963
12114
  const trg = triggerRef.current;
@@ -12095,10 +12246,10 @@ function buildResolved(rawFeatures, binding) {
12095
12246
  return out;
12096
12247
  }
12097
12248
  function useDeviceFeatures(trpc, deviceId, rawFeatures) {
12098
- const [binding, setBinding] = (0, react.useState)(null);
12099
- const [errored, setErrored] = (0, react.useState)(false);
12100
- const [loading, setLoading] = (0, react.useState)(true);
12101
- (0, react.useEffect)(() => {
12249
+ const [binding, setBinding] = (0, react$1.useState)(null);
12250
+ const [errored, setErrored] = (0, react$1.useState)(false);
12251
+ const [loading, setLoading] = (0, react$1.useState)(true);
12252
+ (0, react$1.useEffect)(() => {
12102
12253
  if (deviceId === null) {
12103
12254
  setBinding(null);
12104
12255
  setErrored(false);
@@ -12196,8 +12347,8 @@ function ChildrenCountBadge({ accessoryCount, adoptedCount }) {
12196
12347
  var POPOVER_WIDTH$1 = 240;
12197
12348
  var POPOVER_MIN_HEIGHT = 200;
12198
12349
  function FeatureRow({ resolved }) {
12199
- const triggerRef = (0, react.useRef)(null);
12200
- const [position, setPosition] = (0, react.useState)(null);
12350
+ const triggerRef = (0, react$1.useRef)(null);
12351
+ const [position, setPosition] = (0, react$1.useState)(null);
12201
12352
  const open = () => {
12202
12353
  const el = triggerRef.current;
12203
12354
  if (!el) return;
@@ -12390,7 +12541,7 @@ function useDeviceBattery(trpc, deviceId) {
12390
12541
  */
12391
12542
  function useDeviceSnapshotImage(trpc, deviceId) {
12392
12543
  const dev = useDeviceProxy(trpc, deviceId);
12393
- const forceRef = (0, react.useRef)(false);
12544
+ const forceRef = (0, react$1.useRef)(false);
12394
12545
  const { data, isLoading, isFetching, refetch } = (0, _tanstack_react_query.useQuery)({
12395
12546
  queryKey: [
12396
12547
  "device",
@@ -12507,8 +12658,8 @@ var POPOVER_WIDTH = 288;
12507
12658
  var POPOVER_HEIGHT = 196;
12508
12659
  var TRIGGER_GAP = 8;
12509
12660
  function SnapshotPopoverInline({ deviceName, snapshotUrl, status }) {
12510
- const triggerRef = (0, react.useRef)(null);
12511
- const [position, setPosition] = (0, react.useState)(null);
12661
+ const triggerRef = (0, react$1.useRef)(null);
12662
+ const [position, setPosition] = (0, react$1.useState)(null);
12512
12663
  const offline = status === "offline" || status === "disabled";
12513
12664
  const open = () => {
12514
12665
  const el = triggerRef.current;
@@ -12598,7 +12749,7 @@ function DeviceItem(props) {
12598
12749
  const accessoryChildren = childrenList.filter(isAccessoryChild);
12599
12750
  const adoptedChildren = childrenList.filter((c) => !isAccessoryChild(c));
12600
12751
  const hasChildren = childrenList.length > 0;
12601
- const [localExpanded, setLocalExpanded] = (0, react.useState)(false);
12752
+ const [localExpanded, setLocalExpanded] = (0, react$1.useState)(false);
12602
12753
  const expanded = props.expanded ?? localExpanded;
12603
12754
  const onToggleExpand = props.onToggleExpand ?? (() => setLocalExpanded((v) => !v));
12604
12755
  const navigate = (id) => {
@@ -12748,8 +12899,8 @@ function DeviceItemTableRow(props) {
12748
12899
  * (caller's `useState`); this hook produces a debounced derivation.
12749
12900
  */
12750
12901
  function useDebouncedString(value, delayMs) {
12751
- const [debounced, setDebounced] = (0, react.useState)(value);
12752
- (0, react.useEffect)(() => {
12902
+ const [debounced, setDebounced] = (0, react$1.useState)(value);
12903
+ (0, react$1.useEffect)(() => {
12753
12904
  const t = setTimeout(() => setDebounced(value), delayMs);
12754
12905
  return () => clearTimeout(t);
12755
12906
  }, [value, delayMs]);
@@ -13050,12 +13201,12 @@ function writeUrlState(scope, next, defaultView) {
13050
13201
  }
13051
13202
  function useDeviceListUrlState(options) {
13052
13203
  const { scope, defaultView, lsKey } = options;
13053
- const [state, setState] = (0, react.useState)(() => {
13204
+ const [state, setState] = (0, react$1.useState)(() => {
13054
13205
  return readUrlState(scope, defaultView, readFromLS(lsKey));
13055
13206
  });
13056
- const stateRef = (0, react.useRef)(state);
13207
+ const stateRef = (0, react$1.useRef)(state);
13057
13208
  stateRef.current = state;
13058
- (0, react.useEffect)(() => {
13209
+ (0, react$1.useEffect)(() => {
13059
13210
  const handler = () => {
13060
13211
  const next = readUrlState(scope, defaultView, readFromLS(lsKey));
13061
13212
  stateRef.current = next;
@@ -13068,7 +13219,7 @@ function useDeviceListUrlState(options) {
13068
13219
  defaultView,
13069
13220
  lsKey
13070
13221
  ]);
13071
- const apply = (0, react.useCallback)((mutate) => {
13222
+ const apply = (0, react$1.useCallback)((mutate) => {
13072
13223
  const next = mutate(stateRef.current);
13073
13224
  stateRef.current = next;
13074
13225
  setState(next);
@@ -13086,30 +13237,30 @@ function useDeviceListUrlState(options) {
13086
13237
  ]);
13087
13238
  return {
13088
13239
  state,
13089
- setView: (0, react.useCallback)((view) => apply((s) => ({
13240
+ setView: (0, react$1.useCallback)((view) => apply((s) => ({
13090
13241
  ...s,
13091
13242
  view
13092
13243
  })), [apply]),
13093
- setPage: (0, react.useCallback)((page) => apply((s) => ({
13244
+ setPage: (0, react$1.useCallback)((page) => apply((s) => ({
13094
13245
  ...s,
13095
13246
  page
13096
13247
  })), [apply]),
13097
- setAddon: (0, react.useCallback)((addon) => apply((s) => ({
13248
+ setAddon: (0, react$1.useCallback)((addon) => apply((s) => ({
13098
13249
  ...s,
13099
13250
  addon,
13100
13251
  page: 1
13101
13252
  })), [apply]),
13102
- setType: (0, react.useCallback)((type) => apply((s) => ({
13253
+ setType: (0, react$1.useCallback)((type) => apply((s) => ({
13103
13254
  ...s,
13104
13255
  type,
13105
13256
  page: 1
13106
13257
  })), [apply]),
13107
- setQ: (0, react.useCallback)((q) => apply((s) => ({
13258
+ setQ: (0, react$1.useCallback)((q) => apply((s) => ({
13108
13259
  ...s,
13109
13260
  q,
13110
13261
  page: 1
13111
13262
  })), [apply]),
13112
- clearFilters: (0, react.useCallback)(() => apply((s) => ({
13263
+ clearFilters: (0, react$1.useCallback)(() => apply((s) => ({
13113
13264
  ...s,
13114
13265
  addon: null,
13115
13266
  type: null,
@@ -13149,13 +13300,13 @@ function DeviceList(props) {
13149
13300
  });
13150
13301
  const view = url.state.view;
13151
13302
  const currentPageSize = view === "cards" ? pageSize.cards : pageSize.table;
13152
- const [searchInput, setSearchInput] = (0, react.useState)(url.state.q);
13303
+ const [searchInput, setSearchInput] = (0, react$1.useState)(url.state.q);
13153
13304
  const debouncedSearch = useDebouncedString(searchInput, 300);
13154
- (0, react.useEffect)(() => {
13305
+ (0, react$1.useEffect)(() => {
13155
13306
  if (debouncedSearch !== url.state.q) url.setQ(debouncedSearch);
13156
13307
  }, [debouncedSearch]);
13157
13308
  const effectiveAddon = forceAddon ?? url.state.addon;
13158
- const filtered = (0, react.useMemo)(() => {
13309
+ const filtered = (0, react$1.useMemo)(() => {
13159
13310
  const q = url.state.q.toLowerCase().trim();
13160
13311
  return devices.filter((d) => {
13161
13312
  if (effectiveAddon && d.addonId !== effectiveAddon) return false;
@@ -13169,8 +13320,8 @@ function DeviceList(props) {
13169
13320
  url.state.type,
13170
13321
  url.state.q
13171
13322
  ]);
13172
- const grouped = (0, react.useMemo)(() => groupTopLevelAndAccessories(filtered), [filtered]);
13173
- const autoExpandedParents = (0, react.useMemo)(() => {
13323
+ const grouped = (0, react$1.useMemo)(() => groupTopLevelAndAccessories(filtered), [filtered]);
13324
+ const autoExpandedParents = (0, react$1.useMemo)(() => {
13174
13325
  if (url.state.q.trim() === "") return /* @__PURE__ */ new Set();
13175
13326
  const q = url.state.q.toLowerCase().trim();
13176
13327
  const matching = /* @__PURE__ */ new Set();
@@ -13182,7 +13333,7 @@ function DeviceList(props) {
13182
13333
  const safePage = Math.min(url.state.page, totalPages);
13183
13334
  const startIdx = (safePage - 1) * currentPageSize;
13184
13335
  const pageRows = grouped.topLevel.slice(startIdx, startIdx + currentPageSize);
13185
- (0, react.useEffect)(() => {
13336
+ (0, react$1.useEffect)(() => {
13186
13337
  if (safePage !== url.state.page) url.setPage(safePage);
13187
13338
  }, [safePage]);
13188
13339
  useDeviceListRealtimeSync();
@@ -13287,7 +13438,7 @@ function topLevelIndentLevel(device, parentType) {
13287
13438
  return 0;
13288
13439
  }
13289
13440
  function TableLayout({ rows, accessoriesByParent, autoExpandedParents, devices, trpc, resolveIntegrationIcon, resolveParent, onNavigate }) {
13290
- const parentTypeById = (0, react.useMemo)(() => {
13441
+ const parentTypeById = (0, react$1.useMemo)(() => {
13291
13442
  const m = /* @__PURE__ */ new Map();
13292
13443
  for (const d of devices) m.set(d.id, d.type);
13293
13444
  return m;
@@ -13342,9 +13493,9 @@ function TableLayout({ rows, accessoriesByParent, autoExpandedParents, devices,
13342
13493
  });
13343
13494
  }
13344
13495
  function TableRowGroup({ parent, accessories, hasAccessories, forceExpanded, trpc, integrationIcon, parentRowParent, indentLevel, onNavigate }) {
13345
- const [expanded, setExpanded] = (0, react.useState)(forceExpanded);
13346
- const prevForce = (0, react.useRef)(forceExpanded);
13347
- (0, react.useEffect)(() => {
13496
+ const [expanded, setExpanded] = (0, react$1.useState)(forceExpanded);
13497
+ const prevForce = (0, react$1.useRef)(forceExpanded);
13498
+ (0, react$1.useEffect)(() => {
13348
13499
  if (prevForce.current !== forceExpanded) {
13349
13500
  setExpanded(forceExpanded);
13350
13501
  prevForce.current = forceExpanded;
@@ -13508,9 +13659,9 @@ function PipelineBuilder({ schema, steps, onChange, templates, selectedTemplateI
13508
13659
  inheritedEnabled: inheritedEnabledByAddon[addonId]
13509
13660
  } : {}
13510
13661
  });
13511
- const excluded = (0, react.useMemo)(() => new Set(excludeAddons), [excludeAddons]);
13512
- const schemaMap = (0, react.useMemo)(() => buildSchemaMap(schema), [schema]);
13513
- const [warnings, setWarnings] = (0, react.useState)([]);
13662
+ const excluded = (0, react$1.useMemo)(() => new Set(excludeAddons), [excludeAddons]);
13663
+ const schemaMap = (0, react$1.useMemo)(() => buildSchemaMap(schema), [schema]);
13664
+ const [warnings, setWarnings] = (0, react$1.useState)([]);
13514
13665
  const dirty = selectedTemplateId ? JSON.stringify(steps) !== JSON.stringify(templates.find((t) => t.id === selectedTemplateId)?.steps) : false;
13515
13666
  function handleSelectTemplate(e) {
13516
13667
  const id = e.target.value || null;
@@ -13965,8 +14116,8 @@ function BoundingBox({ detection, imageWidth, imageHeight, color, showConfidence
13965
14116
  }
13966
14117
  /** Renders a segmentation mask as a semi-transparent colored canvas overlay */
13967
14118
  function MaskOverlay({ mask, maskWidth, maskHeight, bbox, imageWidth, imageHeight, color }) {
13968
- const canvasRef = (0, react.useRef)(null);
13969
- (0, react.useEffect)(() => {
14119
+ const canvasRef = (0, react$1.useRef)(null);
14120
+ (0, react$1.useEffect)(() => {
13970
14121
  const canvas = canvasRef.current;
13971
14122
  if (!canvas) return;
13972
14123
  const ctx = canvas.getContext("2d");
@@ -14278,7 +14429,7 @@ function ChildrenTree({ items, colors, hiddenKeys, onToggleVisibility }) {
14278
14429
  });
14279
14430
  }
14280
14431
  function AlternateLabelsSection({ alternateLabels, colors }) {
14281
- const [expanded, setExpanded] = (0, react.useState)(false);
14432
+ const [expanded, setExpanded] = (0, react$1.useState)(false);
14282
14433
  const sources = Object.keys(alternateLabels);
14283
14434
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
14284
14435
  className: "mt-1",
@@ -15184,11 +15335,11 @@ function SpinnerIcon({ className }) {
15184
15335
  });
15185
15336
  }
15186
15337
  function LoginForm({ onLogin, serverUrl, logoSrc, error: externalError, className }) {
15187
- const [username, setUsername] = (0, react.useState)("");
15188
- const [password, setPassword] = (0, react.useState)("");
15189
- const [showPassword, setShowPassword] = (0, react.useState)(false);
15190
- const [submitting, setSubmitting] = (0, react.useState)(false);
15191
- const [internalError, setInternalError] = (0, react.useState)(null);
15338
+ const [username, setUsername] = (0, react$1.useState)("");
15339
+ const [password, setPassword] = (0, react$1.useState)("");
15340
+ const [showPassword, setShowPassword] = (0, react$1.useState)(false);
15341
+ const [submitting, setSubmitting] = (0, react$1.useState)(false);
15342
+ const [internalError, setInternalError] = (0, react$1.useState)(null);
15192
15343
  const error = externalError ?? internalError;
15193
15344
  const handleSubmit = async (e) => {
15194
15345
  e.preventDefault();
@@ -15280,9 +15431,9 @@ function LoginForm({ onLogin, serverUrl, logoSrc, error: externalError, classNam
15280
15431
  //#endregion
15281
15432
  //#region src/composites/dev-shell.tsx
15282
15433
  var STORAGE_KEY = "camstack_dev_token";
15283
- var DevShellContext = (0, react.createContext)(null);
15434
+ var DevShellContext = (0, react$1.createContext)(null);
15284
15435
  function useDevShell() {
15285
- const ctx = (0, react.useContext)(DevShellContext);
15436
+ const ctx = (0, react$1.useContext)(DevShellContext);
15286
15437
  if (!ctx) throw new Error("useDevShell must be used within a DevShell");
15287
15438
  return ctx;
15288
15439
  }
@@ -15332,7 +15483,7 @@ function MoonIcon({ className }) {
15332
15483
  }
15333
15484
  function DevShellInner({ children, serverUrl, title, token, onLogout }) {
15334
15485
  const theme = require_theme_index.useThemeMode$1();
15335
- const links = (0, react.useMemo)(() => {
15486
+ const links = (0, react$1.useMemo)(() => {
15336
15487
  return [(0, _trpc_client.splitLink)({
15337
15488
  condition: (op) => op.type === "subscription",
15338
15489
  true: (0, _trpc_client.wsLink)({
@@ -15349,20 +15500,20 @@ function DevShellInner({ children, serverUrl, title, token, onLogout }) {
15349
15500
  })
15350
15501
  })];
15351
15502
  }, [serverUrl, token]);
15352
- const trpc$1 = (0, react.useMemo)(() => (0, _trpc_client.createTRPCClient)({ links }), [links]);
15353
- const trpcReactClient = (0, react.useMemo)(() => trpc.createClient({ links }), [links]);
15354
- const system = (0, react.useMemo)(() => (0, _camstack_sdk.createSystem)({
15503
+ const trpc$1 = (0, react$1.useMemo)(() => (0, _trpc_client.createTRPCClient)({ links }), [links]);
15504
+ const trpcReactClient = (0, react$1.useMemo)(() => trpc.createClient({ links }), [links]);
15505
+ const system = (0, react$1.useMemo)(() => (0, _camstack_sdk.createSystem)({
15355
15506
  serverUrl,
15356
15507
  token
15357
15508
  }), [serverUrl, token]);
15358
- (0, react.useEffect)(() => {
15509
+ (0, react$1.useEffect)(() => {
15359
15510
  system.init().catch(() => void 0);
15360
15511
  return () => {
15361
15512
  system.close();
15362
15513
  };
15363
15514
  }, [system]);
15364
- const queryClient = (0, react.useMemo)(() => new _tanstack_react_query.QueryClient(), []);
15365
- const contextValue = (0, react.useMemo)(() => ({
15515
+ const queryClient = (0, react$1.useMemo)(() => new _tanstack_react_query.QueryClient(), []);
15516
+ const contextValue = (0, react$1.useMemo)(() => ({
15366
15517
  trpc: trpc$1,
15367
15518
  token,
15368
15519
  logout: onLogout
@@ -15429,8 +15580,8 @@ function DevShellInner({ children, serverUrl, title, token, onLogout }) {
15429
15580
  });
15430
15581
  }
15431
15582
  function DevShell({ children, serverUrl = "https://localhost:4443", title }) {
15432
- const [token, setToken] = (0, react.useState)(getStoredToken);
15433
- const handleLogin = (0, react.useCallback)(async (username, password) => {
15583
+ const [token, setToken] = (0, react$1.useState)(getStoredToken);
15584
+ const handleLogin = (0, react$1.useCallback)(async (username, password) => {
15434
15585
  const loginResult = await (0, _trpc_client.createTRPCClient)({ links: [(0, _trpc_client.httpLink)({
15435
15586
  url: `${serverUrl}/trpc`,
15436
15587
  transformer: SuperJSON
@@ -15442,7 +15593,7 @@ function DevShell({ children, serverUrl = "https://localhost:4443", title }) {
15442
15593
  localStorage.setItem(STORAGE_KEY, loginResult.token);
15443
15594
  setToken(loginResult.token);
15444
15595
  }, [serverUrl]);
15445
- const handleLogout = (0, react.useCallback)(() => {
15596
+ const handleLogout = (0, react$1.useCallback)(() => {
15446
15597
  localStorage.removeItem(STORAGE_KEY);
15447
15598
  setToken(null);
15448
15599
  }, []);
@@ -15491,10 +15642,10 @@ function mountAddonPage(PageComponent, options = {}) {
15491
15642
  console.error(`[mountAddonPage] Element #${rootId} not found`);
15492
15643
  return;
15493
15644
  }
15494
- (0, react_dom_client.createRoot)(root).render((0, react.createElement)(DevShell, {
15645
+ (0, react_dom_client.createRoot)(root).render((0, react$1.createElement)(DevShell, {
15495
15646
  serverUrl,
15496
15647
  title,
15497
- children: ({ trpc, theme }) => (0, react.createElement)(PageComponent, {
15648
+ children: ({ trpc, theme }) => (0, react$1.createElement)(PageComponent, {
15498
15649
  trpc,
15499
15650
  theme: { isDark: theme.resolvedMode === "dark" },
15500
15651
  navigate: (path) => {
@@ -15554,7 +15705,7 @@ function CustomFieldRenderersProvider({ renderers, children }) {
15554
15705
  * (or renders nothing).
15555
15706
  */
15556
15707
  function useCustomFieldRenderer(type) {
15557
- return (0, react.useContext)(CustomFieldRenderersContext)[type] ?? null;
15708
+ return (0, react$1.useContext)(CustomFieldRenderersContext)[type] ?? null;
15558
15709
  }
15559
15710
  //#endregion
15560
15711
  //#region src/contexts/device-context.tsx
@@ -15591,11 +15742,11 @@ function DeviceContextProvider({ deviceId, device, children }) {
15591
15742
  }
15592
15743
  /** @returns the device id of the current page subtree, or null if outside any provider. */
15593
15744
  function useDeviceId() {
15594
- return (0, react.useContext)(DeviceContext)?.deviceId ?? null;
15745
+ return (0, react$1.useContext)(DeviceContext)?.deviceId ?? null;
15595
15746
  }
15596
15747
  /** @returns the cached device snapshot, or null when no snapshot is provided. */
15597
15748
  function useDeviceSnapshot() {
15598
- return (0, react.useContext)(DeviceContext)?.device ?? null;
15749
+ return (0, react$1.useContext)(DeviceContext)?.device ?? null;
15599
15750
  }
15600
15751
  //#endregion
15601
15752
  //#region src/generated/system-hooks.ts
@@ -15649,6 +15800,16 @@ var useAddonsRollbackPackage = trpc.addons.rollbackPackage.useMutation;
15649
15800
  var useAddonsForceRefresh = trpc.addons.forceRefresh.useMutation;
15650
15801
  /** Generated alias around `trpc.addons.restartServer.useMutation`. */
15651
15802
  var useAddonsRestartServer = trpc.addons.restartServer.useMutation;
15803
+ /** Generated alias around `trpc.addons.getLastRestart.useQuery`. */
15804
+ var useAddonsGetLastRestart = trpc.addons.getLastRestart.useQuery;
15805
+ /** Generated alias around `trpc.addons.listFrameworkPackages.useQuery`. */
15806
+ var useAddonsListFrameworkPackages = trpc.addons.listFrameworkPackages.useQuery;
15807
+ /** Generated alias around `trpc.addons.listCapabilityProviders.useQuery`. */
15808
+ var useAddonsListCapabilityProviders = trpc.addons.listCapabilityProviders.useQuery;
15809
+ /** Generated alias around `trpc.addons.setCapabilityProviderEnabled.useMutation`. */
15810
+ var useAddonsSetCapabilityProviderEnabled = trpc.addons.setCapabilityProviderEnabled.useMutation;
15811
+ /** Generated alias around `trpc.addons.updateFrameworkPackage.useMutation`. */
15812
+ var useAddonsUpdateFrameworkPackage = trpc.addons.updateFrameworkPackage.useMutation;
15652
15813
  /** Generated alias around `trpc.addons.getVersions.useQuery`. */
15653
15814
  var useAddonsGetVersions = trpc.addons.getVersions.useQuery;
15654
15815
  /** Generated alias around `trpc.addons.restartAddon.useMutation`. */
@@ -15737,10 +15898,6 @@ var useAudioCodecListActiveSessions = trpc.audioCodec.listActiveSessions.useQuer
15737
15898
  var useAudioMetricsGetCurrentSnapshot = trpc.audioMetrics.getCurrentSnapshot.useQuery;
15738
15899
  /** Generated alias around `trpc.audioMetrics.getHistory.useQuery`. */
15739
15900
  var useAudioMetricsGetHistory = trpc.audioMetrics.getHistory.useQuery;
15740
- /** Generated alias around `trpc.authentication.listProviders.useQuery`. */
15741
- var useAuthenticationListProviders = trpc.authentication.listProviders.useQuery;
15742
- /** Generated alias around `trpc.authentication.setProviderEnabled.useMutation`. */
15743
- var useAuthenticationSetProviderEnabled = trpc.authentication.setProviderEnabled.useMutation;
15744
15901
  /** Generated alias around `trpc.backup.listDestinations.useQuery`. */
15745
15902
  var useBackupListDestinations = trpc.backup.listDestinations.useQuery;
15746
15903
  /** Generated alias around `trpc.backup.trigger.useMutation`. */
@@ -16033,18 +16190,6 @@ var useMeshNetworkLogout = trpc.meshNetwork.logout.useMutation;
16033
16190
  var useMeshNetworkListPeers = trpc.meshNetwork.listPeers.useQuery;
16034
16191
  /** Generated alias around `trpc.meshNetwork.testConnection.useMutation`. */
16035
16192
  var useMeshNetworkTestConnection = trpc.meshNetwork.testConnection.useMutation;
16036
- /** Generated alias around `trpc.meshOrchestrator.listProviders.useQuery`. */
16037
- var useMeshOrchestratorListProviders = trpc.meshOrchestrator.listProviders.useQuery;
16038
- /** Generated alias around `trpc.meshOrchestrator.joinProvider.useMutation`. */
16039
- var useMeshOrchestratorJoinProvider = trpc.meshOrchestrator.joinProvider.useMutation;
16040
- /** Generated alias around `trpc.meshOrchestrator.leaveProvider.useMutation`. */
16041
- var useMeshOrchestratorLeaveProvider = trpc.meshOrchestrator.leaveProvider.useMutation;
16042
- /** Generated alias around `trpc.meshOrchestrator.startLoginProvider.useMutation`. */
16043
- var useMeshOrchestratorStartLoginProvider = trpc.meshOrchestrator.startLoginProvider.useMutation;
16044
- /** Generated alias around `trpc.meshOrchestrator.logoutProvider.useMutation`. */
16045
- var useMeshOrchestratorLogoutProvider = trpc.meshOrchestrator.logoutProvider.useMutation;
16046
- /** Generated alias around `trpc.meshOrchestrator.listProviderPeers.useQuery`. */
16047
- var useMeshOrchestratorListProviderPeers = trpc.meshOrchestrator.listProviderPeers.useQuery;
16048
16193
  /** Generated alias around `trpc.metricsProvider.collectSnapshot.useQuery`. */
16049
16194
  var useMetricsProviderCollectSnapshot = trpc.metricsProvider.collectSnapshot.useQuery;
16050
16195
  /** Generated alias around `trpc.metricsProvider.getCached.useQuery`. */
@@ -16105,6 +16250,16 @@ var useMqttBrokerStopEmbeddedBroker = trpc.mqttBroker.stopEmbeddedBroker.useMuta
16105
16250
  var useMqttBrokerGetStatus = trpc.mqttBroker.getStatus.useQuery;
16106
16251
  /** Generated alias around `trpc.nativeObjectDetection.getStatus.useQuery`. */
16107
16252
  var useNativeObjectDetectionGetStatus = trpc.nativeObjectDetection.getStatus.useQuery;
16253
+ /** Generated alias around `trpc.networkAccess.start.useMutation`. */
16254
+ var useNetworkAccessStart = trpc.networkAccess.start.useMutation;
16255
+ /** Generated alias around `trpc.networkAccess.stop.useMutation`. */
16256
+ var useNetworkAccessStop = trpc.networkAccess.stop.useMutation;
16257
+ /** Generated alias around `trpc.networkAccess.getEndpoint.useQuery`. */
16258
+ var useNetworkAccessGetEndpoint = trpc.networkAccess.getEndpoint.useQuery;
16259
+ /** Generated alias around `trpc.networkAccess.getStatus.useQuery`. */
16260
+ var useNetworkAccessGetStatus = trpc.networkAccess.getStatus.useQuery;
16261
+ /** Generated alias around `trpc.networkAccess.listEndpoints.useQuery`. */
16262
+ var useNetworkAccessListEndpoints = trpc.networkAccess.listEndpoints.useQuery;
16108
16263
  /** Generated alias around `trpc.networkQuality.getDeviceStats.useQuery`. */
16109
16264
  var useNetworkQualityGetDeviceStats = trpc.networkQuality.getDeviceStats.useQuery;
16110
16265
  /** Generated alias around `trpc.networkQuality.getAllStats.useQuery`. */
@@ -16405,12 +16560,6 @@ var useRecordingEngineGetRetentionConfig = trpc.recordingEngine.getRetentionConf
16405
16560
  var useRecordingEngineUpdateRetentionConfig = trpc.recordingEngine.updateRetentionConfig.useMutation;
16406
16561
  /** Generated alias around `trpc.recordingEngine.getMotionStats.useQuery`. */
16407
16562
  var useRecordingEngineGetMotionStats = trpc.recordingEngine.getMotionStats.useQuery;
16408
- /** Generated alias around `trpc.remoteAccess.listProviders.useQuery`. */
16409
- var useRemoteAccessListProviders = trpc.remoteAccess.listProviders.useQuery;
16410
- /** Generated alias around `trpc.remoteAccess.startProvider.useMutation`. */
16411
- var useRemoteAccessStartProvider = trpc.remoteAccess.startProvider.useMutation;
16412
- /** Generated alias around `trpc.remoteAccess.stopProvider.useMutation`. */
16413
- var useRemoteAccessStopProvider = trpc.remoteAccess.stopProvider.useMutation;
16414
16563
  /** Generated alias around `trpc.settingsStore.get.useQuery`. */
16415
16564
  var useSettingsStoreGet = trpc.settingsStore.get.useQuery;
16416
16565
  /** Generated alias around `trpc.settingsStore.set.useMutation`. */
@@ -16557,12 +16706,6 @@ var useSystemSetRetentionConfig = trpc.system.setRetentionConfig.useMutation;
16557
16706
  var useSystemForceRetentionCleanup = trpc.system.forceRetentionCleanup.useMutation;
16558
16707
  /** Generated alias around `trpc.toast.onToast.useSubscription`. */
16559
16708
  var useToastOnToast = trpc.toast.onToast.useSubscription;
16560
- /** Generated alias around `trpc.turnOrchestrator.listProviders.useQuery`. */
16561
- var useTurnOrchestratorListProviders = trpc.turnOrchestrator.listProviders.useQuery;
16562
- /** Generated alias around `trpc.turnOrchestrator.getAllServers.useQuery`. */
16563
- var useTurnOrchestratorGetAllServers = trpc.turnOrchestrator.getAllServers.useQuery;
16564
- /** Generated alias around `trpc.turnOrchestrator.setProviderEnabled.useMutation`. */
16565
- var useTurnOrchestratorSetProviderEnabled = trpc.turnOrchestrator.setProviderEnabled.useMutation;
16566
16709
  /** Generated alias around `trpc.turnProvider.getTurnServers.useQuery`. */
16567
16710
  var useTurnProviderGetTurnServers = trpc.turnProvider.getTurnServers.useQuery;
16568
16711
  /** Generated alias around `trpc.userManagement.listUsers.useQuery`. */
@@ -16748,7 +16891,7 @@ var BOOT_WINDOW_MS = 3e4;
16748
16891
  var POLL_INTERVAL_MS = 2e3;
16749
16892
  function WidgetRegistryProvider({ children }) {
16750
16893
  const queryClient = (0, _tanstack_react_query.useQueryClient)();
16751
- const mountedAtRef = (0, react.useRef)(Date.now());
16894
+ const mountedAtRef = (0, react$1.useRef)(Date.now());
16752
16895
  const { data: rawWidgets } = useAddonWidgetsListWidgets(void 0, {
16753
16896
  staleTime: 0,
16754
16897
  refetchOnMount: "always",
@@ -16762,8 +16905,8 @@ function WidgetRegistryProvider({ children }) {
16762
16905
  useLiveEvent("addon.widget-ready", () => {
16763
16906
  queryClient.invalidateQueries({ queryKey: [["addonWidgets", "listWidgets"]] });
16764
16907
  });
16765
- const [resolvedTick, setResolvedTick] = (0, react.useState)(0);
16766
- (0, react.useEffect)(() => {
16908
+ const [resolvedTick, setResolvedTick] = (0, react$1.useState)(0);
16909
+ (0, react$1.useEffect)(() => {
16767
16910
  if (!rawWidgets) return;
16768
16911
  let cancelled = false;
16769
16912
  const seenRemotes = /* @__PURE__ */ new Set();
@@ -16787,7 +16930,7 @@ function WidgetRegistryProvider({ children }) {
16787
16930
  cancelled = true;
16788
16931
  };
16789
16932
  }, [rawWidgets]);
16790
- const registry = (0, react.useMemo)(() => {
16933
+ const registry = (0, react$1.useMemo)(() => {
16791
16934
  const widgets = rawWidgets ?? [];
16792
16935
  const byId = /* @__PURE__ */ new Map();
16793
16936
  for (const w of widgets) byId.set(`${w.addonId}/${w.stableId}`, w);
@@ -16859,7 +17002,7 @@ function useOptionalWidgetRegistry() {
16859
17002
  return useContextSafe(WidgetRegistryContext);
16860
17003
  }
16861
17004
  function useContextSafe(ctx) {
16862
- return (0, react.useContext)(ctx);
17005
+ return (0, react$1.useContext)(ctx);
16863
17006
  }
16864
17007
  //#endregion
16865
17008
  //#region src/composites/widget-slot.tsx
@@ -16883,7 +17026,7 @@ function WidgetSlot(props) {
16883
17026
  const { widgetId, host = "device-tab", config, deviceId, integrationId, instanceId, size, columns, rows } = props;
16884
17027
  const Component = useWidget(widgetId);
16885
17028
  const metadata = useWidgetMetadata(widgetId);
16886
- const resolvedInstanceId = (0, react.useMemo)(() => instanceId ?? widgetId, [instanceId, widgetId]);
17029
+ const resolvedInstanceId = (0, react$1.useMemo)(() => instanceId ?? widgetId, [instanceId, widgetId]);
16887
17030
  if (Component === void 0 && metadata === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WidgetMissingError, {
16888
17031
  widgetId,
16889
17032
  reason: "unknown"
@@ -16977,9 +17120,9 @@ function TextField({ field, value, onChange, disabled, translationFn }) {
16977
17120
  });
16978
17121
  }
16979
17122
  function NumberField({ field, value, onChange, disabled, translationFn }) {
16980
- const [local, setLocal] = (0, react.useState)(value === void 0 || value === null ? "" : String(value));
16981
- const focusedRef = (0, react.useRef)(false);
16982
- (0, react.useEffect)(() => {
17123
+ const [local, setLocal] = (0, react$1.useState)(value === void 0 || value === null ? "" : String(value));
17124
+ const focusedRef = (0, react$1.useRef)(false);
17125
+ (0, react$1.useEffect)(() => {
16983
17126
  if (focusedRef.current) return;
16984
17127
  setLocal(value === void 0 || value === null ? "" : String(value));
16985
17128
  }, [value]);
@@ -17145,7 +17288,7 @@ function MultiSelectField({ field, value, onChange, disabled, translationFn }) {
17145
17288
  });
17146
17289
  }
17147
17290
  function PasswordField({ field, value, onChange, disabled, translationFn }) {
17148
- const [show, setShow] = (0, react.useState)(false);
17291
+ const [show, setShow] = (0, react$1.useState)(false);
17149
17292
  const showToggle = field.showToggle !== false;
17150
17293
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FieldWrapper, {
17151
17294
  label: field.label,
@@ -17312,9 +17455,9 @@ function SliderField({ field, value, onChange, disabled, translationFn }) {
17312
17455
  }
17313
17456
  function TagsField({ field, value, onChange, disabled, translationFn }) {
17314
17457
  const tags = Array.isArray(value) ? value : [];
17315
- const [input, setInput] = (0, react.useState)("");
17316
- const inputRef = (0, react.useRef)(null);
17317
- const addTag = (0, react.useCallback)((tag) => {
17458
+ const [input, setInput] = (0, react$1.useState)("");
17459
+ const inputRef = (0, react$1.useRef)(null);
17460
+ const addTag = (0, react$1.useCallback)((tag) => {
17318
17461
  const trimmed = tag.trim();
17319
17462
  if (!trimmed || tags.includes(trimmed)) return;
17320
17463
  if (field.maxTags !== void 0 && tags.length >= field.maxTags) return;
@@ -17473,12 +17616,12 @@ function ColorField({ field, value, onChange, disabled, translationFn }) {
17473
17616
  });
17474
17617
  }
17475
17618
  function ProbeField({ field, value, onChange, disabled, translationFn, onTestField, onAction, externalProbe }) {
17476
- const [localStatus, setLocalStatus] = (0, react.useState)("idle");
17477
- const [localResult, setLocalResult] = (0, react.useState)(null);
17619
+ const [localStatus, setLocalStatus] = (0, react$1.useState)("idle");
17620
+ const [localResult, setLocalResult] = (0, react$1.useState)(null);
17478
17621
  const probeStatus = externalProbe?.status ?? localStatus;
17479
17622
  const probeResult = externalProbe?.result ?? localResult;
17480
17623
  const hasTestHandler = !!onTestField || !!onAction;
17481
- const handleTest = (0, react.useCallback)(async () => {
17624
+ const handleTest = (0, react$1.useCallback)(async () => {
17482
17625
  if (!hasTestHandler) return;
17483
17626
  setLocalStatus("probing");
17484
17627
  setLocalResult(null);
@@ -17557,7 +17700,7 @@ function ProbeField({ field, value, onChange, disabled, translationFn, onTestFie
17557
17700
  });
17558
17701
  }
17559
17702
  function GroupField({ field, values, onChange, disabled, translationFn, onTestField }) {
17560
- const [collapsed, setCollapsed] = (0, react.useState)(field.defaultCollapsed ?? false);
17703
+ const [collapsed, setCollapsed] = (0, react$1.useState)(field.defaultCollapsed ?? false);
17561
17704
  const isAccordion = field.style === "accordion";
17562
17705
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
17563
17706
  className: field.span === 2 ? "col-span-2" : field.span === 3 ? "col-span-3" : field.span === 4 ? "col-span-4" : "col-span-1",
@@ -17588,7 +17731,7 @@ function GroupField({ field, values, onChange, disabled, translationFn, onTestFi
17588
17731
  });
17589
17732
  }
17590
17733
  function SubTabsField({ field, values, onChange, disabled, translationFn, onTestField, onAction }) {
17591
- const [active, setActive] = (0, react.useState)(field.tabs[0]?.id ?? "");
17734
+ const [active, setActive] = (0, react$1.useState)(field.tabs[0]?.id ?? "");
17592
17735
  const colSpanClass = field.span === 2 ? "col-span-2" : field.span === 3 ? "col-span-3" : field.span === 4 ? "col-span-4" : "col-span-1";
17593
17736
  if (field.tabs.length === 0) return null;
17594
17737
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -17929,7 +18072,7 @@ function EditableArrayField({ field, value, onChange, disabled, translationFn, o
17929
18072
  });
17930
18073
  }
17931
18074
  function ButtonField({ field, disabled, onAction }) {
17932
- const [loading, setLoading] = (0, react.useState)(false);
18075
+ const [loading, setLoading] = (0, react$1.useState)(false);
17933
18076
  const confirm = useConfirm();
17934
18077
  const handleClick = async () => {
17935
18078
  if (field.confirmMessage) {
@@ -17975,12 +18118,12 @@ function resolveActionParams(field, values) {
17975
18118
  return params;
17976
18119
  }
17977
18120
  function AddonActionSelectField({ field, value, values, onChange, disabled, onAction }) {
17978
- const [loading, setLoading] = (0, react.useState)(false);
17979
- const [error, setError] = (0, react.useState)(null);
17980
- const [options, setOptions] = (0, react.useState)(null);
18121
+ const [loading, setLoading] = (0, react$1.useState)(false);
18122
+ const [error, setError] = (0, react$1.useState)(null);
18123
+ const [options, setOptions] = (0, react$1.useState)(null);
17981
18124
  const params = resolveActionParams(field, values);
17982
18125
  const missingParam = Object.keys(field.paramsFromForm ?? {}).some((k) => params[k] === void 0);
17983
- (0, react.useEffect)(() => {
18126
+ (0, react$1.useEffect)(() => {
17984
18127
  if (!onAction || missingParam) {
17985
18128
  setOptions(null);
17986
18129
  setError(null);
@@ -18066,8 +18209,8 @@ function AddonActionSelectField({ field, value, values, onChange, disabled, onAc
18066
18209
  });
18067
18210
  }
18068
18211
  function AddonActionButtonField({ field, values, disabled, onAction }) {
18069
- const [loading, setLoading] = (0, react.useState)(false);
18070
- const [status, setStatus] = (0, react.useState)(null);
18212
+ const [loading, setLoading] = (0, react$1.useState)(false);
18213
+ const [status, setStatus] = (0, react$1.useState)(null);
18071
18214
  const confirm = useConfirm();
18072
18215
  const handleClick = async () => {
18073
18216
  if (field.confirmMessage) {
@@ -18212,7 +18355,7 @@ function InlineIconGlyph({ name }) {
18212
18355
  */
18213
18356
  function InlineActionIcon({ action, fieldKey, value, onAction }) {
18214
18357
  const confirm = useConfirm();
18215
- const [loading, setLoading] = (0, react.useState)(false);
18358
+ const [loading, setLoading] = (0, react$1.useState)(false);
18216
18359
  const variantClass = action.variant === "danger" ? "text-danger hover:bg-danger/10 border-danger/30" : action.variant === "primary" ? "text-primary hover:bg-primary/10 border-primary/30" : "text-foreground-subtle hover:text-foreground hover:bg-surface-hover border-border";
18217
18360
  const handleClick = async () => {
18218
18361
  if (action.confirmMessage) {
@@ -18560,7 +18703,7 @@ function resolveLabel(value, t) {
18560
18703
  return value;
18561
18704
  }
18562
18705
  function SectionCard({ section, values, onChange, disabled, translationFn, onTestField, probeResults }) {
18563
- const [collapsed, setCollapsed] = (0, react.useState)(section.defaultCollapsed ?? false);
18706
+ const [collapsed, setCollapsed] = (0, react$1.useState)(section.defaultCollapsed ?? false);
18564
18707
  const isAccordion = section.style === "accordion";
18565
18708
  const columns = section.columns ?? 2;
18566
18709
  const gridClass = columns === 1 ? "grid-cols-1" : columns === 3 ? "grid-cols-1 @[480px]:grid-cols-2 @[880px]:grid-cols-3" : columns === 4 ? "grid-cols-1 @[480px]:grid-cols-2 @[1140px]:grid-cols-4" : "grid-cols-1 @[640px]:grid-cols-2";
@@ -18665,14 +18808,14 @@ function stripValues(schema) {
18665
18808
  }
18666
18809
  function AddonGlobalSettingsForm({ trpc, addonId, nodeId, title, disabled, onAfterChange, refreshToken, collapsible, defaultOpen, mode, onOverrideChange }) {
18667
18810
  const effectiveMode = mode ?? "persist";
18668
- const [hydrated, setHydrated] = (0, react.useState)(null);
18669
- const [loading, setLoading] = (0, react.useState)(true);
18670
- const [error, setError] = (0, react.useState)(null);
18671
- const [saving, setSaving] = (0, react.useState)(false);
18672
- const [open, setOpen] = (0, react.useState)(defaultOpen ?? false);
18673
- const [overrideValues, setOverrideValues] = (0, react.useState)({});
18674
- const [baseValues, setBaseValues] = (0, react.useState)(null);
18675
- (0, react.useEffect)(() => {
18811
+ const [hydrated, setHydrated] = (0, react$1.useState)(null);
18812
+ const [loading, setLoading] = (0, react$1.useState)(true);
18813
+ const [error, setError] = (0, react$1.useState)(null);
18814
+ const [saving, setSaving] = (0, react$1.useState)(false);
18815
+ const [open, setOpen] = (0, react$1.useState)(defaultOpen ?? false);
18816
+ const [overrideValues, setOverrideValues] = (0, react$1.useState)({});
18817
+ const [baseValues, setBaseValues] = (0, react$1.useState)(null);
18818
+ (0, react$1.useEffect)(() => {
18676
18819
  setBaseValues(null);
18677
18820
  setOverrideValues({});
18678
18821
  }, [
@@ -18682,7 +18825,7 @@ function AddonGlobalSettingsForm({ trpc, addonId, nodeId, title, disabled, onAft
18682
18825
  refreshToken,
18683
18826
  effectiveMode
18684
18827
  ]);
18685
- (0, react.useEffect)(() => {
18828
+ (0, react$1.useEffect)(() => {
18686
18829
  let cancelled = false;
18687
18830
  setLoading(true);
18688
18831
  setError(null);
@@ -18712,8 +18855,8 @@ function AddonGlobalSettingsForm({ trpc, addonId, nodeId, title, disabled, onAft
18712
18855
  effectiveMode,
18713
18856
  JSON.stringify(overrideValues)
18714
18857
  ]);
18715
- const values = (0, react.useMemo)(() => extractValues(hydrated), [hydrated]);
18716
- const schemaNoValues = (0, react.useMemo)(() => hydrated ? stripValues(hydrated) : null, [hydrated]);
18858
+ const values = (0, react$1.useMemo)(() => extractValues(hydrated), [hydrated]);
18859
+ const schemaNoValues = (0, react$1.useMemo)(() => hydrated ? stripValues(hydrated) : null, [hydrated]);
18717
18860
  const handleChange = async (nextValues) => {
18718
18861
  if (effectiveMode === "override") {
18719
18862
  const ref = baseValues ?? values;
@@ -18960,30 +19103,30 @@ function computeClientHints(container) {
18960
19103
  var RECONNECT_DELAY_MS = 3e3;
18961
19104
  var MAX_RECONNECT_ATTEMPTS = 5;
18962
19105
  function CameraStreamPlayer({ serverUrl, streamKey, label, autoPlay = true, muted: initialMuted = true, showControls = true, className = "", onStateChange, onError, overlay, createSession, sendAnswer, closeSession, hintsOverride }) {
18963
- const videoRef = (0, react.useRef)(null);
18964
- const containerRef = (0, react.useRef)(null);
18965
- const pcRef = (0, react.useRef)(null);
19106
+ const videoRef = (0, react$1.useRef)(null);
19107
+ const containerRef = (0, react$1.useRef)(null);
19108
+ const pcRef = (0, react$1.useRef)(null);
18966
19109
  /** All session IDs created during this player's lifetime — closed on cleanup */
18967
- const sessionIdsRef = (0, react.useRef)(/* @__PURE__ */ new Set());
19110
+ const sessionIdsRef = (0, react$1.useRef)(/* @__PURE__ */ new Set());
18968
19111
  /** Abort controller to cancel in-flight connection attempts on cleanup */
18969
- const connectAbortRef = (0, react.useRef)(null);
18970
- const reconnectTimerRef = (0, react.useRef)(null);
18971
- const reconnectAttemptsRef = (0, react.useRef)(0);
18972
- const mountedRef = (0, react.useRef)(true);
18973
- const [state, setState] = (0, react.useState)("idle");
18974
- const [errorMessage, setErrorMessage] = (0, react.useState)("");
18975
- const [isMuted, setIsMuted] = (0, react.useState)(initialMuted);
18976
- const [isFullscreen, setIsFullscreen] = (0, react.useState)(false);
18977
- const [showToolbar, setShowToolbar] = (0, react.useState)(false);
18978
- const hideTimerRef = (0, react.useRef)(null);
18979
- const serverOfferModeRef = (0, react.useRef)(false);
19112
+ const connectAbortRef = (0, react$1.useRef)(null);
19113
+ const reconnectTimerRef = (0, react$1.useRef)(null);
19114
+ const reconnectAttemptsRef = (0, react$1.useRef)(0);
19115
+ const mountedRef = (0, react$1.useRef)(true);
19116
+ const [state, setState] = (0, react$1.useState)("idle");
19117
+ const [errorMessage, setErrorMessage] = (0, react$1.useState)("");
19118
+ const [isMuted, setIsMuted] = (0, react$1.useState)(initialMuted);
19119
+ const [isFullscreen, setIsFullscreen] = (0, react$1.useState)(false);
19120
+ const [showToolbar, setShowToolbar] = (0, react$1.useState)(false);
19121
+ const hideTimerRef = (0, react$1.useRef)(null);
19122
+ const serverOfferModeRef = (0, react$1.useRef)(false);
18980
19123
  if (sendAnswer || createSession) serverOfferModeRef.current = true;
18981
19124
  const useServerOffer = serverOfferModeRef.current;
18982
- const updateState = (0, react.useCallback)((s) => {
19125
+ const updateState = (0, react$1.useCallback)((s) => {
18983
19126
  setState(s);
18984
19127
  onStateChange?.(s);
18985
19128
  }, [onStateChange]);
18986
- const cleanup = (0, react.useCallback)(() => {
19129
+ const cleanup = (0, react$1.useCallback)(() => {
18987
19130
  connectAbortRef.current?.abort();
18988
19131
  connectAbortRef.current = null;
18989
19132
  if (reconnectTimerRef.current) {
@@ -19000,7 +19143,7 @@ function CameraStreamPlayer({ serverUrl, streamKey, label, autoPlay = true, mute
19000
19143
  }
19001
19144
  if (videoRef.current) videoRef.current.srcObject = null;
19002
19145
  }, [closeSession]);
19003
- const connectServerOffer = (0, react.useCallback)(async () => {
19146
+ const connectServerOffer = (0, react$1.useCallback)(async () => {
19004
19147
  if (!mountedRef.current || !createSession || !sendAnswer) return;
19005
19148
  cleanup();
19006
19149
  updateState("connecting");
@@ -19091,7 +19234,7 @@ function CameraStreamPlayer({ serverUrl, streamKey, label, autoPlay = true, mute
19091
19234
  onError,
19092
19235
  hintsOverride
19093
19236
  ]);
19094
- const connectWhep = (0, react.useCallback)(async () => {
19237
+ const connectWhep = (0, react$1.useCallback)(async () => {
19095
19238
  if (!mountedRef.current) return;
19096
19239
  cleanup();
19097
19240
  updateState("connecting");
@@ -19152,9 +19295,9 @@ function CameraStreamPlayer({ serverUrl, streamKey, label, autoPlay = true, mute
19152
19295
  onError
19153
19296
  ]);
19154
19297
  const connect = useServerOffer ? connectServerOffer : connectWhep;
19155
- const connectRef = (0, react.useRef)(() => {});
19298
+ const connectRef = (0, react$1.useRef)(() => {});
19156
19299
  connectRef.current = connect;
19157
- const scheduleReconnect = (0, react.useCallback)(() => {
19300
+ const scheduleReconnect = (0, react$1.useCallback)(() => {
19158
19301
  if (!mountedRef.current) return;
19159
19302
  if (reconnectAttemptsRef.current >= MAX_RECONNECT_ATTEMPTS) return;
19160
19303
  reconnectAttemptsRef.current += 1;
@@ -19162,7 +19305,7 @@ function CameraStreamPlayer({ serverUrl, streamKey, label, autoPlay = true, mute
19162
19305
  if (mountedRef.current) connectRef.current();
19163
19306
  }, RECONNECT_DELAY_MS);
19164
19307
  }, []);
19165
- (0, react.useEffect)(() => {
19308
+ (0, react$1.useEffect)(() => {
19166
19309
  mountedRef.current = true;
19167
19310
  reconnectAttemptsRef.current = 0;
19168
19311
  if (autoPlay) connect();
@@ -19171,8 +19314,8 @@ function CameraStreamPlayer({ serverUrl, streamKey, label, autoPlay = true, mute
19171
19314
  cleanup();
19172
19315
  };
19173
19316
  }, [serverUrl, streamKey]);
19174
- const hasSignaledRef = (0, react.useRef)(false);
19175
- (0, react.useEffect)(() => {
19317
+ const hasSignaledRef = (0, react$1.useRef)(false);
19318
+ (0, react$1.useEffect)(() => {
19176
19319
  if (!autoPlay || !useServerOffer) return;
19177
19320
  if (!createSession || !sendAnswer) return;
19178
19321
  if (hasSignaledRef.current) return;
@@ -19218,7 +19361,7 @@ function CameraStreamPlayer({ serverUrl, streamKey, label, autoPlay = true, mute
19218
19361
  link.href = canvas.toDataURL("image/jpeg", .92);
19219
19362
  link.click();
19220
19363
  };
19221
- (0, react.useEffect)(() => {
19364
+ (0, react$1.useEffect)(() => {
19222
19365
  const handler = () => setIsFullscreen(!!document.fullscreenElement);
19223
19366
  document.addEventListener("fullscreenchange", handler);
19224
19367
  return () => document.removeEventListener("fullscreenchange", handler);
@@ -19442,16 +19585,16 @@ async function waitForIceGathering(pc) {
19442
19585
  var PlayerOverlaysStateContext = createSharedContext("camstack:player-overlays-state", null);
19443
19586
  var PlayerOverlaysActionsContext = createSharedContext("camstack:player-overlays-actions", null);
19444
19587
  function PlayerOverlaysProvider({ children }) {
19445
- const [layers, setLayers] = (0, react.useState)(() => /* @__PURE__ */ new Map());
19446
- const [buttons, setButtons] = (0, react.useState)(() => /* @__PURE__ */ new Map());
19447
- const setLayer = (0, react.useCallback)((layer) => {
19588
+ const [layers, setLayers] = (0, react$1.useState)(() => /* @__PURE__ */ new Map());
19589
+ const [buttons, setButtons] = (0, react$1.useState)(() => /* @__PURE__ */ new Map());
19590
+ const setLayer = (0, react$1.useCallback)((layer) => {
19448
19591
  setLayers((prev) => {
19449
19592
  const next = new Map(prev);
19450
19593
  next.set(layer.id, layer);
19451
19594
  return next;
19452
19595
  });
19453
19596
  }, []);
19454
- const removeLayer = (0, react.useCallback)((id) => {
19597
+ const removeLayer = (0, react$1.useCallback)((id) => {
19455
19598
  setLayers((prev) => {
19456
19599
  if (!prev.has(id)) return prev;
19457
19600
  const next = new Map(prev);
@@ -19459,14 +19602,14 @@ function PlayerOverlaysProvider({ children }) {
19459
19602
  return next;
19460
19603
  });
19461
19604
  }, []);
19462
- const setButton = (0, react.useCallback)((button) => {
19605
+ const setButton = (0, react$1.useCallback)((button) => {
19463
19606
  setButtons((prev) => {
19464
19607
  const next = new Map(prev);
19465
19608
  next.set(button.id, button);
19466
19609
  return next;
19467
19610
  });
19468
19611
  }, []);
19469
- const removeButton = (0, react.useCallback)((id) => {
19612
+ const removeButton = (0, react$1.useCallback)((id) => {
19470
19613
  setButtons((prev) => {
19471
19614
  if (!prev.has(id)) return prev;
19472
19615
  const next = new Map(prev);
@@ -19474,11 +19617,11 @@ function PlayerOverlaysProvider({ children }) {
19474
19617
  return next;
19475
19618
  });
19476
19619
  }, []);
19477
- const stateValue = (0, react.useMemo)(() => ({
19620
+ const stateValue = (0, react$1.useMemo)(() => ({
19478
19621
  layers,
19479
19622
  buttons
19480
19623
  }), [layers, buttons]);
19481
- const actionsValue = (0, react.useMemo)(() => ({
19624
+ const actionsValue = (0, react$1.useMemo)(() => ({
19482
19625
  setLayer,
19483
19626
  removeLayer,
19484
19627
  setButton,
@@ -19501,16 +19644,16 @@ function PlayerOverlaysProvider({ children }) {
19501
19644
  * by insertion order of the underlying Map). Returns `[]` outside a
19502
19645
  * provider. */
19503
19646
  function usePlayerOverlayLayers() {
19504
- const state = (0, react.useContext)(PlayerOverlaysStateContext);
19505
- return (0, react.useMemo)(() => {
19647
+ const state = (0, react$1.useContext)(PlayerOverlaysStateContext);
19648
+ return (0, react$1.useMemo)(() => {
19506
19649
  if (!state) return [];
19507
19650
  return [...state.layers.values()].sort((a, b) => a.order - b.order);
19508
19651
  }, [state]);
19509
19652
  }
19510
19653
  /** Snapshot of registered toolbar buttons, ordered by `order` (asc). */
19511
19654
  function usePlayerToolbarButtons() {
19512
- const state = (0, react.useContext)(PlayerOverlaysStateContext);
19513
- return (0, react.useMemo)(() => {
19655
+ const state = (0, react$1.useContext)(PlayerOverlaysStateContext);
19656
+ return (0, react$1.useMemo)(() => {
19514
19657
  if (!state) return [];
19515
19658
  return [...state.buttons.values()].sort((a, b) => a.order - b.order);
19516
19659
  }, [state]);
@@ -19527,8 +19670,8 @@ function usePlayerToolbarButtons() {
19527
19670
  * effects depend on referential equality of the spec object.
19528
19671
  */
19529
19672
  function usePlayerOverlayLayer(spec) {
19530
- const actions = (0, react.useContext)(PlayerOverlaysActionsContext);
19531
- (0, react.useEffect)(() => {
19673
+ const actions = (0, react$1.useContext)(PlayerOverlaysActionsContext);
19674
+ (0, react$1.useEffect)(() => {
19532
19675
  if (!actions || !spec) return void 0;
19533
19676
  actions.setLayer(spec);
19534
19677
  return () => actions.removeLayer(spec.id);
@@ -19536,8 +19679,8 @@ function usePlayerOverlayLayer(spec) {
19536
19679
  }
19537
19680
  /** Same shape as `usePlayerOverlayLayer`, scoped to toolbar buttons. */
19538
19681
  function usePlayerToolbarButton(spec) {
19539
- const actions = (0, react.useContext)(PlayerOverlaysActionsContext);
19540
- (0, react.useEffect)(() => {
19682
+ const actions = (0, react$1.useContext)(PlayerOverlaysActionsContext);
19683
+ (0, react$1.useEffect)(() => {
19541
19684
  if (!actions || !spec) return void 0;
19542
19685
  actions.setButton(spec);
19543
19686
  return () => actions.removeButton(spec.id);
@@ -19706,13 +19849,13 @@ function ImageOffIcon({ className }) {
19706
19849
  }
19707
19850
  function StreamPanel({ serverUrl, createSession, sendAnswer, closeSession, streams, activeStreamId: controlledStreamId, onStreamChange, deviceName, phase, pipelineMetrics, detections, defaultShowDetections = true, defaultShowMotion = false, streamStats, autoPlay = false, showPlayStop = false, snapshotSrc, snapshotLoading = false, onRefreshSnapshot, showStreamStats = false, children, extraOverlay, ptzAvailable = false, ptzShown = false, ptzOverlay, onPtzToggle, intercomAvailable = false, intercomShown = false, onIntercomToggle, chromeless = false, className }) {
19708
19851
  const registeredButtons = usePlayerToolbarButtons();
19709
- const [isPlaying, setIsPlaying] = (0, react.useState)(autoPlay);
19710
- const [showDetections, setShowDetections] = (0, react.useState)(defaultShowDetections);
19711
- const [showMotion, setShowMotion] = (0, react.useState)(defaultShowMotion);
19712
- const [internalStreamId, setInternalStreamId] = (0, react.useState)(null);
19713
- const [menuOpen, setMenuOpen] = (0, react.useState)(false);
19714
- const menuRef = (0, react.useRef)(null);
19715
- (0, react.useEffect)(() => {
19852
+ const [isPlaying, setIsPlaying] = (0, react$1.useState)(autoPlay);
19853
+ const [showDetections, setShowDetections] = (0, react$1.useState)(defaultShowDetections);
19854
+ const [showMotion, setShowMotion] = (0, react$1.useState)(defaultShowMotion);
19855
+ const [internalStreamId, setInternalStreamId] = (0, react$1.useState)(null);
19856
+ const [menuOpen, setMenuOpen] = (0, react$1.useState)(false);
19857
+ const menuRef = (0, react$1.useRef)(null);
19858
+ (0, react$1.useEffect)(() => {
19716
19859
  if (!menuOpen) return;
19717
19860
  function onClick(e) {
19718
19861
  if (menuRef.current && !menuRef.current.contains(e.target)) setMenuOpen(false);
@@ -19735,7 +19878,7 @@ function StreamPanel({ serverUrl, createSession, sendAnswer, closeSession, strea
19735
19878
  setTimeout(() => setIsPlaying(true), 50);
19736
19879
  }
19737
19880
  };
19738
- const playerCreateSession = (0, react.useMemo)(() => {
19881
+ const playerCreateSession = (0, react$1.useMemo)(() => {
19739
19882
  const target = selectedChoice?.target;
19740
19883
  if (!target) return void 0;
19741
19884
  return (hints) => createSession(target, hints);
@@ -20058,10 +20201,10 @@ function profileLabel(streamId) {
20058
20201
  return streamId.charAt(0).toUpperCase() + streamId.slice(1);
20059
20202
  }
20060
20203
  function StreamBrokerSelector({ deviceId, value, onChange, disabled, label, className }) {
20061
- const labelId = (0, react.useId)();
20204
+ const labelId = (0, react$1.useId)();
20062
20205
  const query = useCameraStreamsGetRtspEntries({ deviceId }, { refetchOnWindowFocus: false });
20063
- const [options, setOptions] = (0, react.useState)([AUTO_OPTION]);
20064
- (0, react.useEffect)(() => {
20206
+ const [options, setOptions] = (0, react$1.useState)([AUTO_OPTION]);
20207
+ (0, react$1.useEffect)(() => {
20065
20208
  if (!query.data) return;
20066
20209
  const prefix = `${deviceId}/`;
20067
20210
  const next = [AUTO_OPTION];
@@ -20100,6 +20243,1489 @@ function StreamBrokerSelector({ deviceId, value, onChange, disabled, label, clas
20100
20243
  });
20101
20244
  }
20102
20245
  //#endregion
20246
+ //#region ../../node_modules/qrcode.react/lib/esm/index.js
20247
+ var __defProp = Object.defineProperty;
20248
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
20249
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
20250
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
20251
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {
20252
+ enumerable: true,
20253
+ configurable: true,
20254
+ writable: true,
20255
+ value
20256
+ }) : obj[key] = value;
20257
+ var __spreadValues = (a, b) => {
20258
+ for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]);
20259
+ if (__getOwnPropSymbols) {
20260
+ for (var prop of __getOwnPropSymbols(b)) if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]);
20261
+ }
20262
+ return a;
20263
+ };
20264
+ var __objRest = (source, exclude) => {
20265
+ var target = {};
20266
+ for (var prop in source) if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0) target[prop] = source[prop];
20267
+ if (source != null && __getOwnPropSymbols) {
20268
+ for (var prop of __getOwnPropSymbols(source)) if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop)) target[prop] = source[prop];
20269
+ }
20270
+ return target;
20271
+ };
20272
+ /**
20273
+ * @license QR Code generator library (TypeScript)
20274
+ * Copyright (c) Project Nayuki.
20275
+ * SPDX-License-Identifier: MIT
20276
+ */
20277
+ var qrcodegen;
20278
+ ((qrcodegen2) => {
20279
+ const _QrCode = class _QrCode {
20280
+ constructor(version, errorCorrectionLevel, dataCodewords, msk) {
20281
+ this.version = version;
20282
+ this.errorCorrectionLevel = errorCorrectionLevel;
20283
+ this.modules = [];
20284
+ this.isFunction = [];
20285
+ if (version < _QrCode.MIN_VERSION || version > _QrCode.MAX_VERSION) throw new RangeError("Version value out of range");
20286
+ if (msk < -1 || msk > 7) throw new RangeError("Mask value out of range");
20287
+ this.size = version * 4 + 17;
20288
+ let row = [];
20289
+ for (let i = 0; i < this.size; i++) row.push(false);
20290
+ for (let i = 0; i < this.size; i++) {
20291
+ this.modules.push(row.slice());
20292
+ this.isFunction.push(row.slice());
20293
+ }
20294
+ this.drawFunctionPatterns();
20295
+ const allCodewords = this.addEccAndInterleave(dataCodewords);
20296
+ this.drawCodewords(allCodewords);
20297
+ if (msk == -1) {
20298
+ let minPenalty = 1e9;
20299
+ for (let i = 0; i < 8; i++) {
20300
+ this.applyMask(i);
20301
+ this.drawFormatBits(i);
20302
+ const penalty = this.getPenaltyScore();
20303
+ if (penalty < minPenalty) {
20304
+ msk = i;
20305
+ minPenalty = penalty;
20306
+ }
20307
+ this.applyMask(i);
20308
+ }
20309
+ }
20310
+ assert(0 <= msk && msk <= 7);
20311
+ this.mask = msk;
20312
+ this.applyMask(msk);
20313
+ this.drawFormatBits(msk);
20314
+ this.isFunction = [];
20315
+ }
20316
+ static encodeText(text, ecl) {
20317
+ const segs = qrcodegen2.QrSegment.makeSegments(text);
20318
+ return _QrCode.encodeSegments(segs, ecl);
20319
+ }
20320
+ static encodeBinary(data, ecl) {
20321
+ const seg = qrcodegen2.QrSegment.makeBytes(data);
20322
+ return _QrCode.encodeSegments([seg], ecl);
20323
+ }
20324
+ static encodeSegments(segs, ecl, minVersion = 1, maxVersion = 40, mask = -1, boostEcl = true) {
20325
+ if (!(_QrCode.MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= _QrCode.MAX_VERSION) || mask < -1 || mask > 7) throw new RangeError("Invalid value");
20326
+ let version;
20327
+ let dataUsedBits;
20328
+ for (version = minVersion;; version++) {
20329
+ const dataCapacityBits2 = _QrCode.getNumDataCodewords(version, ecl) * 8;
20330
+ const usedBits = QrSegment.getTotalBits(segs, version);
20331
+ if (usedBits <= dataCapacityBits2) {
20332
+ dataUsedBits = usedBits;
20333
+ break;
20334
+ }
20335
+ if (version >= maxVersion) throw new RangeError("Data too long");
20336
+ }
20337
+ for (const newEcl of [
20338
+ _QrCode.Ecc.MEDIUM,
20339
+ _QrCode.Ecc.QUARTILE,
20340
+ _QrCode.Ecc.HIGH
20341
+ ]) if (boostEcl && dataUsedBits <= _QrCode.getNumDataCodewords(version, newEcl) * 8) ecl = newEcl;
20342
+ let bb = [];
20343
+ for (const seg of segs) {
20344
+ appendBits(seg.mode.modeBits, 4, bb);
20345
+ appendBits(seg.numChars, seg.mode.numCharCountBits(version), bb);
20346
+ for (const b of seg.getData()) bb.push(b);
20347
+ }
20348
+ assert(bb.length == dataUsedBits);
20349
+ const dataCapacityBits = _QrCode.getNumDataCodewords(version, ecl) * 8;
20350
+ assert(bb.length <= dataCapacityBits);
20351
+ appendBits(0, Math.min(4, dataCapacityBits - bb.length), bb);
20352
+ appendBits(0, (8 - bb.length % 8) % 8, bb);
20353
+ assert(bb.length % 8 == 0);
20354
+ for (let padByte = 236; bb.length < dataCapacityBits; padByte ^= 253) appendBits(padByte, 8, bb);
20355
+ let dataCodewords = [];
20356
+ while (dataCodewords.length * 8 < bb.length) dataCodewords.push(0);
20357
+ bb.forEach((b, i) => dataCodewords[i >>> 3] |= b << 7 - (i & 7));
20358
+ return new _QrCode(version, ecl, dataCodewords, mask);
20359
+ }
20360
+ getModule(x, y) {
20361
+ return 0 <= x && x < this.size && 0 <= y && y < this.size && this.modules[y][x];
20362
+ }
20363
+ getModules() {
20364
+ return this.modules;
20365
+ }
20366
+ drawFunctionPatterns() {
20367
+ for (let i = 0; i < this.size; i++) {
20368
+ this.setFunctionModule(6, i, i % 2 == 0);
20369
+ this.setFunctionModule(i, 6, i % 2 == 0);
20370
+ }
20371
+ this.drawFinderPattern(3, 3);
20372
+ this.drawFinderPattern(this.size - 4, 3);
20373
+ this.drawFinderPattern(3, this.size - 4);
20374
+ const alignPatPos = this.getAlignmentPatternPositions();
20375
+ const numAlign = alignPatPos.length;
20376
+ for (let i = 0; i < numAlign; i++) for (let j = 0; j < numAlign; j++) if (!(i == 0 && j == 0 || i == 0 && j == numAlign - 1 || i == numAlign - 1 && j == 0)) this.drawAlignmentPattern(alignPatPos[i], alignPatPos[j]);
20377
+ this.drawFormatBits(0);
20378
+ this.drawVersion();
20379
+ }
20380
+ drawFormatBits(mask) {
20381
+ const data = this.errorCorrectionLevel.formatBits << 3 | mask;
20382
+ let rem = data;
20383
+ for (let i = 0; i < 10; i++) rem = rem << 1 ^ (rem >>> 9) * 1335;
20384
+ const bits = (data << 10 | rem) ^ 21522;
20385
+ assert(bits >>> 15 == 0);
20386
+ for (let i = 0; i <= 5; i++) this.setFunctionModule(8, i, getBit(bits, i));
20387
+ this.setFunctionModule(8, 7, getBit(bits, 6));
20388
+ this.setFunctionModule(8, 8, getBit(bits, 7));
20389
+ this.setFunctionModule(7, 8, getBit(bits, 8));
20390
+ for (let i = 9; i < 15; i++) this.setFunctionModule(14 - i, 8, getBit(bits, i));
20391
+ for (let i = 0; i < 8; i++) this.setFunctionModule(this.size - 1 - i, 8, getBit(bits, i));
20392
+ for (let i = 8; i < 15; i++) this.setFunctionModule(8, this.size - 15 + i, getBit(bits, i));
20393
+ this.setFunctionModule(8, this.size - 8, true);
20394
+ }
20395
+ drawVersion() {
20396
+ if (this.version < 7) return;
20397
+ let rem = this.version;
20398
+ for (let i = 0; i < 12; i++) rem = rem << 1 ^ (rem >>> 11) * 7973;
20399
+ const bits = this.version << 12 | rem;
20400
+ assert(bits >>> 18 == 0);
20401
+ for (let i = 0; i < 18; i++) {
20402
+ const color = getBit(bits, i);
20403
+ const a = this.size - 11 + i % 3;
20404
+ const b = Math.floor(i / 3);
20405
+ this.setFunctionModule(a, b, color);
20406
+ this.setFunctionModule(b, a, color);
20407
+ }
20408
+ }
20409
+ drawFinderPattern(x, y) {
20410
+ for (let dy = -4; dy <= 4; dy++) for (let dx = -4; dx <= 4; dx++) {
20411
+ const dist = Math.max(Math.abs(dx), Math.abs(dy));
20412
+ const xx = x + dx;
20413
+ const yy = y + dy;
20414
+ if (0 <= xx && xx < this.size && 0 <= yy && yy < this.size) this.setFunctionModule(xx, yy, dist != 2 && dist != 4);
20415
+ }
20416
+ }
20417
+ drawAlignmentPattern(x, y) {
20418
+ for (let dy = -2; dy <= 2; dy++) for (let dx = -2; dx <= 2; dx++) this.setFunctionModule(x + dx, y + dy, Math.max(Math.abs(dx), Math.abs(dy)) != 1);
20419
+ }
20420
+ setFunctionModule(x, y, isDark) {
20421
+ this.modules[y][x] = isDark;
20422
+ this.isFunction[y][x] = true;
20423
+ }
20424
+ addEccAndInterleave(data) {
20425
+ const ver = this.version;
20426
+ const ecl = this.errorCorrectionLevel;
20427
+ if (data.length != _QrCode.getNumDataCodewords(ver, ecl)) throw new RangeError("Invalid argument");
20428
+ const numBlocks = _QrCode.NUM_ERROR_CORRECTION_BLOCKS[ecl.ordinal][ver];
20429
+ const blockEccLen = _QrCode.ECC_CODEWORDS_PER_BLOCK[ecl.ordinal][ver];
20430
+ const rawCodewords = Math.floor(_QrCode.getNumRawDataModules(ver) / 8);
20431
+ const numShortBlocks = numBlocks - rawCodewords % numBlocks;
20432
+ const shortBlockLen = Math.floor(rawCodewords / numBlocks);
20433
+ let blocks = [];
20434
+ const rsDiv = _QrCode.reedSolomonComputeDivisor(blockEccLen);
20435
+ for (let i = 0, k = 0; i < numBlocks; i++) {
20436
+ let dat = data.slice(k, k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1));
20437
+ k += dat.length;
20438
+ const ecc = _QrCode.reedSolomonComputeRemainder(dat, rsDiv);
20439
+ if (i < numShortBlocks) dat.push(0);
20440
+ blocks.push(dat.concat(ecc));
20441
+ }
20442
+ let result = [];
20443
+ for (let i = 0; i < blocks[0].length; i++) blocks.forEach((block, j) => {
20444
+ if (i != shortBlockLen - blockEccLen || j >= numShortBlocks) result.push(block[i]);
20445
+ });
20446
+ assert(result.length == rawCodewords);
20447
+ return result;
20448
+ }
20449
+ drawCodewords(data) {
20450
+ if (data.length != Math.floor(_QrCode.getNumRawDataModules(this.version) / 8)) throw new RangeError("Invalid argument");
20451
+ let i = 0;
20452
+ for (let right = this.size - 1; right >= 1; right -= 2) {
20453
+ if (right == 6) right = 5;
20454
+ for (let vert = 0; vert < this.size; vert++) for (let j = 0; j < 2; j++) {
20455
+ const x = right - j;
20456
+ const y = (right + 1 & 2) == 0 ? this.size - 1 - vert : vert;
20457
+ if (!this.isFunction[y][x] && i < data.length * 8) {
20458
+ this.modules[y][x] = getBit(data[i >>> 3], 7 - (i & 7));
20459
+ i++;
20460
+ }
20461
+ }
20462
+ }
20463
+ assert(i == data.length * 8);
20464
+ }
20465
+ applyMask(mask) {
20466
+ if (mask < 0 || mask > 7) throw new RangeError("Mask value out of range");
20467
+ for (let y = 0; y < this.size; y++) for (let x = 0; x < this.size; x++) {
20468
+ let invert;
20469
+ switch (mask) {
20470
+ case 0:
20471
+ invert = (x + y) % 2 == 0;
20472
+ break;
20473
+ case 1:
20474
+ invert = y % 2 == 0;
20475
+ break;
20476
+ case 2:
20477
+ invert = x % 3 == 0;
20478
+ break;
20479
+ case 3:
20480
+ invert = (x + y) % 3 == 0;
20481
+ break;
20482
+ case 4:
20483
+ invert = (Math.floor(x / 3) + Math.floor(y / 2)) % 2 == 0;
20484
+ break;
20485
+ case 5:
20486
+ invert = x * y % 2 + x * y % 3 == 0;
20487
+ break;
20488
+ case 6:
20489
+ invert = (x * y % 2 + x * y % 3) % 2 == 0;
20490
+ break;
20491
+ case 7:
20492
+ invert = ((x + y) % 2 + x * y % 3) % 2 == 0;
20493
+ break;
20494
+ default: throw new Error("Unreachable");
20495
+ }
20496
+ if (!this.isFunction[y][x] && invert) this.modules[y][x] = !this.modules[y][x];
20497
+ }
20498
+ }
20499
+ getPenaltyScore() {
20500
+ let result = 0;
20501
+ for (let y = 0; y < this.size; y++) {
20502
+ let runColor = false;
20503
+ let runX = 0;
20504
+ let runHistory = [
20505
+ 0,
20506
+ 0,
20507
+ 0,
20508
+ 0,
20509
+ 0,
20510
+ 0,
20511
+ 0
20512
+ ];
20513
+ for (let x = 0; x < this.size; x++) if (this.modules[y][x] == runColor) {
20514
+ runX++;
20515
+ if (runX == 5) result += _QrCode.PENALTY_N1;
20516
+ else if (runX > 5) result++;
20517
+ } else {
20518
+ this.finderPenaltyAddHistory(runX, runHistory);
20519
+ if (!runColor) result += this.finderPenaltyCountPatterns(runHistory) * _QrCode.PENALTY_N3;
20520
+ runColor = this.modules[y][x];
20521
+ runX = 1;
20522
+ }
20523
+ result += this.finderPenaltyTerminateAndCount(runColor, runX, runHistory) * _QrCode.PENALTY_N3;
20524
+ }
20525
+ for (let x = 0; x < this.size; x++) {
20526
+ let runColor = false;
20527
+ let runY = 0;
20528
+ let runHistory = [
20529
+ 0,
20530
+ 0,
20531
+ 0,
20532
+ 0,
20533
+ 0,
20534
+ 0,
20535
+ 0
20536
+ ];
20537
+ for (let y = 0; y < this.size; y++) if (this.modules[y][x] == runColor) {
20538
+ runY++;
20539
+ if (runY == 5) result += _QrCode.PENALTY_N1;
20540
+ else if (runY > 5) result++;
20541
+ } else {
20542
+ this.finderPenaltyAddHistory(runY, runHistory);
20543
+ if (!runColor) result += this.finderPenaltyCountPatterns(runHistory) * _QrCode.PENALTY_N3;
20544
+ runColor = this.modules[y][x];
20545
+ runY = 1;
20546
+ }
20547
+ result += this.finderPenaltyTerminateAndCount(runColor, runY, runHistory) * _QrCode.PENALTY_N3;
20548
+ }
20549
+ for (let y = 0; y < this.size - 1; y++) for (let x = 0; x < this.size - 1; x++) {
20550
+ const color = this.modules[y][x];
20551
+ if (color == this.modules[y][x + 1] && color == this.modules[y + 1][x] && color == this.modules[y + 1][x + 1]) result += _QrCode.PENALTY_N2;
20552
+ }
20553
+ let dark = 0;
20554
+ for (const row of this.modules) dark = row.reduce((sum, color) => sum + (color ? 1 : 0), dark);
20555
+ const total = this.size * this.size;
20556
+ const k = Math.ceil(Math.abs(dark * 20 - total * 10) / total) - 1;
20557
+ assert(0 <= k && k <= 9);
20558
+ result += k * _QrCode.PENALTY_N4;
20559
+ assert(0 <= result && result <= 2568888);
20560
+ return result;
20561
+ }
20562
+ getAlignmentPatternPositions() {
20563
+ if (this.version == 1) return [];
20564
+ else {
20565
+ const numAlign = Math.floor(this.version / 7) + 2;
20566
+ const step = this.version == 32 ? 26 : Math.ceil((this.version * 4 + 4) / (numAlign * 2 - 2)) * 2;
20567
+ let result = [6];
20568
+ for (let pos = this.size - 7; result.length < numAlign; pos -= step) result.splice(1, 0, pos);
20569
+ return result;
20570
+ }
20571
+ }
20572
+ static getNumRawDataModules(ver) {
20573
+ if (ver < _QrCode.MIN_VERSION || ver > _QrCode.MAX_VERSION) throw new RangeError("Version number out of range");
20574
+ let result = (16 * ver + 128) * ver + 64;
20575
+ if (ver >= 2) {
20576
+ const numAlign = Math.floor(ver / 7) + 2;
20577
+ result -= (25 * numAlign - 10) * numAlign - 55;
20578
+ if (ver >= 7) result -= 36;
20579
+ }
20580
+ assert(208 <= result && result <= 29648);
20581
+ return result;
20582
+ }
20583
+ static getNumDataCodewords(ver, ecl) {
20584
+ return Math.floor(_QrCode.getNumRawDataModules(ver) / 8) - _QrCode.ECC_CODEWORDS_PER_BLOCK[ecl.ordinal][ver] * _QrCode.NUM_ERROR_CORRECTION_BLOCKS[ecl.ordinal][ver];
20585
+ }
20586
+ static reedSolomonComputeDivisor(degree) {
20587
+ if (degree < 1 || degree > 255) throw new RangeError("Degree out of range");
20588
+ let result = [];
20589
+ for (let i = 0; i < degree - 1; i++) result.push(0);
20590
+ result.push(1);
20591
+ let root = 1;
20592
+ for (let i = 0; i < degree; i++) {
20593
+ for (let j = 0; j < result.length; j++) {
20594
+ result[j] = _QrCode.reedSolomonMultiply(result[j], root);
20595
+ if (j + 1 < result.length) result[j] ^= result[j + 1];
20596
+ }
20597
+ root = _QrCode.reedSolomonMultiply(root, 2);
20598
+ }
20599
+ return result;
20600
+ }
20601
+ static reedSolomonComputeRemainder(data, divisor) {
20602
+ let result = divisor.map((_) => 0);
20603
+ for (const b of data) {
20604
+ const factor = b ^ result.shift();
20605
+ result.push(0);
20606
+ divisor.forEach((coef, i) => result[i] ^= _QrCode.reedSolomonMultiply(coef, factor));
20607
+ }
20608
+ return result;
20609
+ }
20610
+ static reedSolomonMultiply(x, y) {
20611
+ if (x >>> 8 != 0 || y >>> 8 != 0) throw new RangeError("Byte out of range");
20612
+ let z = 0;
20613
+ for (let i = 7; i >= 0; i--) {
20614
+ z = z << 1 ^ (z >>> 7) * 285;
20615
+ z ^= (y >>> i & 1) * x;
20616
+ }
20617
+ assert(z >>> 8 == 0);
20618
+ return z;
20619
+ }
20620
+ finderPenaltyCountPatterns(runHistory) {
20621
+ const n = runHistory[1];
20622
+ assert(n <= this.size * 3);
20623
+ const core = n > 0 && runHistory[2] == n && runHistory[3] == n * 3 && runHistory[4] == n && runHistory[5] == n;
20624
+ return (core && runHistory[0] >= n * 4 && runHistory[6] >= n ? 1 : 0) + (core && runHistory[6] >= n * 4 && runHistory[0] >= n ? 1 : 0);
20625
+ }
20626
+ finderPenaltyTerminateAndCount(currentRunColor, currentRunLength, runHistory) {
20627
+ if (currentRunColor) {
20628
+ this.finderPenaltyAddHistory(currentRunLength, runHistory);
20629
+ currentRunLength = 0;
20630
+ }
20631
+ currentRunLength += this.size;
20632
+ this.finderPenaltyAddHistory(currentRunLength, runHistory);
20633
+ return this.finderPenaltyCountPatterns(runHistory);
20634
+ }
20635
+ finderPenaltyAddHistory(currentRunLength, runHistory) {
20636
+ if (runHistory[0] == 0) currentRunLength += this.size;
20637
+ runHistory.pop();
20638
+ runHistory.unshift(currentRunLength);
20639
+ }
20640
+ };
20641
+ _QrCode.MIN_VERSION = 1;
20642
+ _QrCode.MAX_VERSION = 40;
20643
+ _QrCode.PENALTY_N1 = 3;
20644
+ _QrCode.PENALTY_N2 = 3;
20645
+ _QrCode.PENALTY_N3 = 40;
20646
+ _QrCode.PENALTY_N4 = 10;
20647
+ _QrCode.ECC_CODEWORDS_PER_BLOCK = [
20648
+ [
20649
+ -1,
20650
+ 7,
20651
+ 10,
20652
+ 15,
20653
+ 20,
20654
+ 26,
20655
+ 18,
20656
+ 20,
20657
+ 24,
20658
+ 30,
20659
+ 18,
20660
+ 20,
20661
+ 24,
20662
+ 26,
20663
+ 30,
20664
+ 22,
20665
+ 24,
20666
+ 28,
20667
+ 30,
20668
+ 28,
20669
+ 28,
20670
+ 28,
20671
+ 28,
20672
+ 30,
20673
+ 30,
20674
+ 26,
20675
+ 28,
20676
+ 30,
20677
+ 30,
20678
+ 30,
20679
+ 30,
20680
+ 30,
20681
+ 30,
20682
+ 30,
20683
+ 30,
20684
+ 30,
20685
+ 30,
20686
+ 30,
20687
+ 30,
20688
+ 30,
20689
+ 30
20690
+ ],
20691
+ [
20692
+ -1,
20693
+ 10,
20694
+ 16,
20695
+ 26,
20696
+ 18,
20697
+ 24,
20698
+ 16,
20699
+ 18,
20700
+ 22,
20701
+ 22,
20702
+ 26,
20703
+ 30,
20704
+ 22,
20705
+ 22,
20706
+ 24,
20707
+ 24,
20708
+ 28,
20709
+ 28,
20710
+ 26,
20711
+ 26,
20712
+ 26,
20713
+ 26,
20714
+ 28,
20715
+ 28,
20716
+ 28,
20717
+ 28,
20718
+ 28,
20719
+ 28,
20720
+ 28,
20721
+ 28,
20722
+ 28,
20723
+ 28,
20724
+ 28,
20725
+ 28,
20726
+ 28,
20727
+ 28,
20728
+ 28,
20729
+ 28,
20730
+ 28,
20731
+ 28,
20732
+ 28
20733
+ ],
20734
+ [
20735
+ -1,
20736
+ 13,
20737
+ 22,
20738
+ 18,
20739
+ 26,
20740
+ 18,
20741
+ 24,
20742
+ 18,
20743
+ 22,
20744
+ 20,
20745
+ 24,
20746
+ 28,
20747
+ 26,
20748
+ 24,
20749
+ 20,
20750
+ 30,
20751
+ 24,
20752
+ 28,
20753
+ 28,
20754
+ 26,
20755
+ 30,
20756
+ 28,
20757
+ 30,
20758
+ 30,
20759
+ 30,
20760
+ 30,
20761
+ 28,
20762
+ 30,
20763
+ 30,
20764
+ 30,
20765
+ 30,
20766
+ 30,
20767
+ 30,
20768
+ 30,
20769
+ 30,
20770
+ 30,
20771
+ 30,
20772
+ 30,
20773
+ 30,
20774
+ 30,
20775
+ 30
20776
+ ],
20777
+ [
20778
+ -1,
20779
+ 17,
20780
+ 28,
20781
+ 22,
20782
+ 16,
20783
+ 22,
20784
+ 28,
20785
+ 26,
20786
+ 26,
20787
+ 24,
20788
+ 28,
20789
+ 24,
20790
+ 28,
20791
+ 22,
20792
+ 24,
20793
+ 24,
20794
+ 30,
20795
+ 28,
20796
+ 28,
20797
+ 26,
20798
+ 28,
20799
+ 30,
20800
+ 24,
20801
+ 30,
20802
+ 30,
20803
+ 30,
20804
+ 30,
20805
+ 30,
20806
+ 30,
20807
+ 30,
20808
+ 30,
20809
+ 30,
20810
+ 30,
20811
+ 30,
20812
+ 30,
20813
+ 30,
20814
+ 30,
20815
+ 30,
20816
+ 30,
20817
+ 30,
20818
+ 30
20819
+ ]
20820
+ ];
20821
+ _QrCode.NUM_ERROR_CORRECTION_BLOCKS = [
20822
+ [
20823
+ -1,
20824
+ 1,
20825
+ 1,
20826
+ 1,
20827
+ 1,
20828
+ 1,
20829
+ 2,
20830
+ 2,
20831
+ 2,
20832
+ 2,
20833
+ 4,
20834
+ 4,
20835
+ 4,
20836
+ 4,
20837
+ 4,
20838
+ 6,
20839
+ 6,
20840
+ 6,
20841
+ 6,
20842
+ 7,
20843
+ 8,
20844
+ 8,
20845
+ 9,
20846
+ 9,
20847
+ 10,
20848
+ 12,
20849
+ 12,
20850
+ 12,
20851
+ 13,
20852
+ 14,
20853
+ 15,
20854
+ 16,
20855
+ 17,
20856
+ 18,
20857
+ 19,
20858
+ 19,
20859
+ 20,
20860
+ 21,
20861
+ 22,
20862
+ 24,
20863
+ 25
20864
+ ],
20865
+ [
20866
+ -1,
20867
+ 1,
20868
+ 1,
20869
+ 1,
20870
+ 2,
20871
+ 2,
20872
+ 4,
20873
+ 4,
20874
+ 4,
20875
+ 5,
20876
+ 5,
20877
+ 5,
20878
+ 8,
20879
+ 9,
20880
+ 9,
20881
+ 10,
20882
+ 10,
20883
+ 11,
20884
+ 13,
20885
+ 14,
20886
+ 16,
20887
+ 17,
20888
+ 17,
20889
+ 18,
20890
+ 20,
20891
+ 21,
20892
+ 23,
20893
+ 25,
20894
+ 26,
20895
+ 28,
20896
+ 29,
20897
+ 31,
20898
+ 33,
20899
+ 35,
20900
+ 37,
20901
+ 38,
20902
+ 40,
20903
+ 43,
20904
+ 45,
20905
+ 47,
20906
+ 49
20907
+ ],
20908
+ [
20909
+ -1,
20910
+ 1,
20911
+ 1,
20912
+ 2,
20913
+ 2,
20914
+ 4,
20915
+ 4,
20916
+ 6,
20917
+ 6,
20918
+ 8,
20919
+ 8,
20920
+ 8,
20921
+ 10,
20922
+ 12,
20923
+ 16,
20924
+ 12,
20925
+ 17,
20926
+ 16,
20927
+ 18,
20928
+ 21,
20929
+ 20,
20930
+ 23,
20931
+ 23,
20932
+ 25,
20933
+ 27,
20934
+ 29,
20935
+ 34,
20936
+ 34,
20937
+ 35,
20938
+ 38,
20939
+ 40,
20940
+ 43,
20941
+ 45,
20942
+ 48,
20943
+ 51,
20944
+ 53,
20945
+ 56,
20946
+ 59,
20947
+ 62,
20948
+ 65,
20949
+ 68
20950
+ ],
20951
+ [
20952
+ -1,
20953
+ 1,
20954
+ 1,
20955
+ 2,
20956
+ 4,
20957
+ 4,
20958
+ 4,
20959
+ 5,
20960
+ 6,
20961
+ 8,
20962
+ 8,
20963
+ 11,
20964
+ 11,
20965
+ 16,
20966
+ 16,
20967
+ 18,
20968
+ 16,
20969
+ 19,
20970
+ 21,
20971
+ 25,
20972
+ 25,
20973
+ 25,
20974
+ 34,
20975
+ 30,
20976
+ 32,
20977
+ 35,
20978
+ 37,
20979
+ 40,
20980
+ 42,
20981
+ 45,
20982
+ 48,
20983
+ 51,
20984
+ 54,
20985
+ 57,
20986
+ 60,
20987
+ 63,
20988
+ 66,
20989
+ 70,
20990
+ 74,
20991
+ 77,
20992
+ 81
20993
+ ]
20994
+ ];
20995
+ qrcodegen2.QrCode = _QrCode;
20996
+ function appendBits(val, len, bb) {
20997
+ if (len < 0 || len > 31 || val >>> len != 0) throw new RangeError("Value out of range");
20998
+ for (let i = len - 1; i >= 0; i--) bb.push(val >>> i & 1);
20999
+ }
21000
+ function getBit(x, i) {
21001
+ return (x >>> i & 1) != 0;
21002
+ }
21003
+ function assert(cond) {
21004
+ if (!cond) throw new Error("Assertion error");
21005
+ }
21006
+ const _QrSegment = class _QrSegment {
21007
+ constructor(mode, numChars, bitData) {
21008
+ this.mode = mode;
21009
+ this.numChars = numChars;
21010
+ this.bitData = bitData;
21011
+ if (numChars < 0) throw new RangeError("Invalid argument");
21012
+ this.bitData = bitData.slice();
21013
+ }
21014
+ static makeBytes(data) {
21015
+ let bb = [];
21016
+ for (const b of data) appendBits(b, 8, bb);
21017
+ return new _QrSegment(_QrSegment.Mode.BYTE, data.length, bb);
21018
+ }
21019
+ static makeNumeric(digits) {
21020
+ if (!_QrSegment.isNumeric(digits)) throw new RangeError("String contains non-numeric characters");
21021
+ let bb = [];
21022
+ for (let i = 0; i < digits.length;) {
21023
+ const n = Math.min(digits.length - i, 3);
21024
+ appendBits(parseInt(digits.substring(i, i + n), 10), n * 3 + 1, bb);
21025
+ i += n;
21026
+ }
21027
+ return new _QrSegment(_QrSegment.Mode.NUMERIC, digits.length, bb);
21028
+ }
21029
+ static makeAlphanumeric(text) {
21030
+ if (!_QrSegment.isAlphanumeric(text)) throw new RangeError("String contains unencodable characters in alphanumeric mode");
21031
+ let bb = [];
21032
+ let i;
21033
+ for (i = 0; i + 2 <= text.length; i += 2) {
21034
+ let temp = _QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45;
21035
+ temp += _QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1));
21036
+ appendBits(temp, 11, bb);
21037
+ }
21038
+ if (i < text.length) appendBits(_QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6, bb);
21039
+ return new _QrSegment(_QrSegment.Mode.ALPHANUMERIC, text.length, bb);
21040
+ }
21041
+ static makeSegments(text) {
21042
+ if (text == "") return [];
21043
+ else if (_QrSegment.isNumeric(text)) return [_QrSegment.makeNumeric(text)];
21044
+ else if (_QrSegment.isAlphanumeric(text)) return [_QrSegment.makeAlphanumeric(text)];
21045
+ else return [_QrSegment.makeBytes(_QrSegment.toUtf8ByteArray(text))];
21046
+ }
21047
+ static makeEci(assignVal) {
21048
+ let bb = [];
21049
+ if (assignVal < 0) throw new RangeError("ECI assignment value out of range");
21050
+ else if (assignVal < 128) appendBits(assignVal, 8, bb);
21051
+ else if (assignVal < 16384) {
21052
+ appendBits(2, 2, bb);
21053
+ appendBits(assignVal, 14, bb);
21054
+ } else if (assignVal < 1e6) {
21055
+ appendBits(6, 3, bb);
21056
+ appendBits(assignVal, 21, bb);
21057
+ } else throw new RangeError("ECI assignment value out of range");
21058
+ return new _QrSegment(_QrSegment.Mode.ECI, 0, bb);
21059
+ }
21060
+ static isNumeric(text) {
21061
+ return _QrSegment.NUMERIC_REGEX.test(text);
21062
+ }
21063
+ static isAlphanumeric(text) {
21064
+ return _QrSegment.ALPHANUMERIC_REGEX.test(text);
21065
+ }
21066
+ getData() {
21067
+ return this.bitData.slice();
21068
+ }
21069
+ static getTotalBits(segs, version) {
21070
+ let result = 0;
21071
+ for (const seg of segs) {
21072
+ const ccbits = seg.mode.numCharCountBits(version);
21073
+ if (seg.numChars >= 1 << ccbits) return Infinity;
21074
+ result += 4 + ccbits + seg.bitData.length;
21075
+ }
21076
+ return result;
21077
+ }
21078
+ static toUtf8ByteArray(str) {
21079
+ str = encodeURI(str);
21080
+ let result = [];
21081
+ for (let i = 0; i < str.length; i++) if (str.charAt(i) != "%") result.push(str.charCodeAt(i));
21082
+ else {
21083
+ result.push(parseInt(str.substring(i + 1, i + 3), 16));
21084
+ i += 2;
21085
+ }
21086
+ return result;
21087
+ }
21088
+ };
21089
+ _QrSegment.NUMERIC_REGEX = /^[0-9]*$/;
21090
+ _QrSegment.ALPHANUMERIC_REGEX = /^[A-Z0-9 $%*+.\/:-]*$/;
21091
+ _QrSegment.ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
21092
+ let QrSegment = _QrSegment;
21093
+ qrcodegen2.QrSegment = _QrSegment;
21094
+ })(qrcodegen || (qrcodegen = {}));
21095
+ ((qrcodegen2) => {
21096
+ ((QrCode2) => {
21097
+ const _Ecc = class _Ecc {
21098
+ constructor(ordinal, formatBits) {
21099
+ this.ordinal = ordinal;
21100
+ this.formatBits = formatBits;
21101
+ }
21102
+ };
21103
+ _Ecc.LOW = new _Ecc(0, 1);
21104
+ _Ecc.MEDIUM = new _Ecc(1, 0);
21105
+ _Ecc.QUARTILE = new _Ecc(2, 3);
21106
+ _Ecc.HIGH = new _Ecc(3, 2);
21107
+ QrCode2.Ecc = _Ecc;
21108
+ })(qrcodegen2.QrCode || (qrcodegen2.QrCode = {}));
21109
+ })(qrcodegen || (qrcodegen = {}));
21110
+ ((qrcodegen2) => {
21111
+ ((QrSegment2) => {
21112
+ const _Mode = class _Mode {
21113
+ constructor(modeBits, numBitsCharCount) {
21114
+ this.modeBits = modeBits;
21115
+ this.numBitsCharCount = numBitsCharCount;
21116
+ }
21117
+ numCharCountBits(ver) {
21118
+ return this.numBitsCharCount[Math.floor((ver + 7) / 17)];
21119
+ }
21120
+ };
21121
+ _Mode.NUMERIC = new _Mode(1, [
21122
+ 10,
21123
+ 12,
21124
+ 14
21125
+ ]);
21126
+ _Mode.ALPHANUMERIC = new _Mode(2, [
21127
+ 9,
21128
+ 11,
21129
+ 13
21130
+ ]);
21131
+ _Mode.BYTE = new _Mode(4, [
21132
+ 8,
21133
+ 16,
21134
+ 16
21135
+ ]);
21136
+ _Mode.KANJI = new _Mode(8, [
21137
+ 8,
21138
+ 10,
21139
+ 12
21140
+ ]);
21141
+ _Mode.ECI = new _Mode(7, [
21142
+ 0,
21143
+ 0,
21144
+ 0
21145
+ ]);
21146
+ QrSegment2.Mode = _Mode;
21147
+ })(qrcodegen2.QrSegment || (qrcodegen2.QrSegment = {}));
21148
+ })(qrcodegen || (qrcodegen = {}));
21149
+ var qrcodegen_default = qrcodegen;
21150
+ /**
21151
+ * @license qrcode.react
21152
+ * Copyright (c) Paul O'Shannessy
21153
+ * SPDX-License-Identifier: ISC
21154
+ */
21155
+ var ERROR_LEVEL_MAP = {
21156
+ L: qrcodegen_default.QrCode.Ecc.LOW,
21157
+ M: qrcodegen_default.QrCode.Ecc.MEDIUM,
21158
+ Q: qrcodegen_default.QrCode.Ecc.QUARTILE,
21159
+ H: qrcodegen_default.QrCode.Ecc.HIGH
21160
+ };
21161
+ var DEFAULT_SIZE$1 = 128;
21162
+ var DEFAULT_LEVEL = "L";
21163
+ var DEFAULT_BGCOLOR = "#FFFFFF";
21164
+ var DEFAULT_FGCOLOR = "#000000";
21165
+ var DEFAULT_INCLUDEMARGIN = false;
21166
+ var DEFAULT_MINVERSION = 1;
21167
+ var SPEC_MARGIN_SIZE = 4;
21168
+ var DEFAULT_MARGIN_SIZE = 0;
21169
+ var DEFAULT_IMG_SCALE = .1;
21170
+ function generatePath(modules, margin = 0) {
21171
+ const ops = [];
21172
+ modules.forEach(function(row, y) {
21173
+ let start = null;
21174
+ row.forEach(function(cell, x) {
21175
+ if (!cell && start !== null) {
21176
+ ops.push(`M${start + margin} ${y + margin}h${x - start}v1H${start + margin}z`);
21177
+ start = null;
21178
+ return;
21179
+ }
21180
+ if (x === row.length - 1) {
21181
+ if (!cell) return;
21182
+ if (start === null) ops.push(`M${x + margin},${y + margin} h1v1H${x + margin}z`);
21183
+ else ops.push(`M${start + margin},${y + margin} h${x + 1 - start}v1H${start + margin}z`);
21184
+ return;
21185
+ }
21186
+ if (cell && start === null) start = x;
21187
+ });
21188
+ });
21189
+ return ops.join("");
21190
+ }
21191
+ function excavateModules(modules, excavation) {
21192
+ return modules.slice().map((row, y) => {
21193
+ if (y < excavation.y || y >= excavation.y + excavation.h) return row;
21194
+ return row.map((cell, x) => {
21195
+ if (x < excavation.x || x >= excavation.x + excavation.w) return cell;
21196
+ return false;
21197
+ });
21198
+ });
21199
+ }
21200
+ function getImageSettings(cells, size, margin, imageSettings) {
21201
+ if (imageSettings == null) return null;
21202
+ const numCells = cells.length + margin * 2;
21203
+ const defaultSize = Math.floor(size * DEFAULT_IMG_SCALE);
21204
+ const scale = numCells / size;
21205
+ const w = (imageSettings.width || defaultSize) * scale;
21206
+ const h = (imageSettings.height || defaultSize) * scale;
21207
+ const x = imageSettings.x == null ? cells.length / 2 - w / 2 : imageSettings.x * scale;
21208
+ const y = imageSettings.y == null ? cells.length / 2 - h / 2 : imageSettings.y * scale;
21209
+ const opacity = imageSettings.opacity == null ? 1 : imageSettings.opacity;
21210
+ let excavation = null;
21211
+ if (imageSettings.excavate) {
21212
+ let floorX = Math.floor(x);
21213
+ let floorY = Math.floor(y);
21214
+ excavation = {
21215
+ x: floorX,
21216
+ y: floorY,
21217
+ w: Math.ceil(w + x - floorX),
21218
+ h: Math.ceil(h + y - floorY)
21219
+ };
21220
+ }
21221
+ const crossOrigin = imageSettings.crossOrigin;
21222
+ return {
21223
+ x,
21224
+ y,
21225
+ h,
21226
+ w,
21227
+ excavation,
21228
+ opacity,
21229
+ crossOrigin
21230
+ };
21231
+ }
21232
+ function getMarginSize(includeMargin, marginSize) {
21233
+ if (marginSize != null) return Math.max(Math.floor(marginSize), 0);
21234
+ return includeMargin ? SPEC_MARGIN_SIZE : DEFAULT_MARGIN_SIZE;
21235
+ }
21236
+ function useQRCode({ value, level, minVersion, includeMargin, marginSize, imageSettings, size, boostLevel }) {
21237
+ let qrcode = react.default.useMemo(() => {
21238
+ const segments = (Array.isArray(value) ? value : [value]).reduce((accum, v) => {
21239
+ accum.push(...qrcodegen_default.QrSegment.makeSegments(v));
21240
+ return accum;
21241
+ }, []);
21242
+ return qrcodegen_default.QrCode.encodeSegments(segments, ERROR_LEVEL_MAP[level], minVersion, void 0, void 0, boostLevel);
21243
+ }, [
21244
+ value,
21245
+ level,
21246
+ minVersion,
21247
+ boostLevel
21248
+ ]);
21249
+ const { cells, margin, numCells, calculatedImageSettings } = react.default.useMemo(() => {
21250
+ let cells2 = qrcode.getModules();
21251
+ const margin2 = getMarginSize(includeMargin, marginSize);
21252
+ return {
21253
+ cells: cells2,
21254
+ margin: margin2,
21255
+ numCells: cells2.length + margin2 * 2,
21256
+ calculatedImageSettings: getImageSettings(cells2, size, margin2, imageSettings)
21257
+ };
21258
+ }, [
21259
+ qrcode,
21260
+ size,
21261
+ imageSettings,
21262
+ includeMargin,
21263
+ marginSize
21264
+ ]);
21265
+ return {
21266
+ qrcode,
21267
+ margin,
21268
+ cells,
21269
+ numCells,
21270
+ calculatedImageSettings
21271
+ };
21272
+ }
21273
+ var SUPPORTS_PATH2D = function() {
21274
+ try {
21275
+ new Path2D().addPath(new Path2D());
21276
+ } catch (e) {
21277
+ return false;
21278
+ }
21279
+ return true;
21280
+ }();
21281
+ var QRCodeCanvas = react.default.forwardRef(function QRCodeCanvas2(props, forwardedRef) {
21282
+ const _a = props, { value, size = DEFAULT_SIZE$1, level = DEFAULT_LEVEL, bgColor = DEFAULT_BGCOLOR, fgColor = DEFAULT_FGCOLOR, includeMargin = DEFAULT_INCLUDEMARGIN, minVersion = DEFAULT_MINVERSION, boostLevel, marginSize, imageSettings } = _a;
21283
+ const _b = __objRest(_a, [
21284
+ "value",
21285
+ "size",
21286
+ "level",
21287
+ "bgColor",
21288
+ "fgColor",
21289
+ "includeMargin",
21290
+ "minVersion",
21291
+ "boostLevel",
21292
+ "marginSize",
21293
+ "imageSettings"
21294
+ ]), { style } = _b, otherProps = __objRest(_b, ["style"]);
21295
+ const imgSrc = imageSettings == null ? void 0 : imageSettings.src;
21296
+ const _canvas = react.default.useRef(null);
21297
+ const _image = react.default.useRef(null);
21298
+ const setCanvasRef = react.default.useCallback((node) => {
21299
+ _canvas.current = node;
21300
+ if (typeof forwardedRef === "function") forwardedRef(node);
21301
+ else if (forwardedRef) forwardedRef.current = node;
21302
+ }, [forwardedRef]);
21303
+ const [isImgLoaded, setIsImageLoaded] = react.default.useState(false);
21304
+ const { margin, cells, numCells, calculatedImageSettings } = useQRCode({
21305
+ value,
21306
+ level,
21307
+ minVersion,
21308
+ boostLevel,
21309
+ includeMargin,
21310
+ marginSize,
21311
+ imageSettings,
21312
+ size
21313
+ });
21314
+ react.default.useEffect(() => {
21315
+ if (_canvas.current != null) {
21316
+ const canvas = _canvas.current;
21317
+ const ctx = canvas.getContext("2d");
21318
+ if (!ctx) return;
21319
+ let cellsToDraw = cells;
21320
+ const image = _image.current;
21321
+ const haveImageToRender = calculatedImageSettings != null && image !== null && image.complete && image.naturalHeight !== 0 && image.naturalWidth !== 0;
21322
+ if (haveImageToRender) {
21323
+ if (calculatedImageSettings.excavation != null) cellsToDraw = excavateModules(cells, calculatedImageSettings.excavation);
21324
+ }
21325
+ const pixelRatio = window.devicePixelRatio || 1;
21326
+ canvas.height = canvas.width = size * pixelRatio;
21327
+ const scale = size / numCells * pixelRatio;
21328
+ ctx.scale(scale, scale);
21329
+ ctx.fillStyle = bgColor;
21330
+ ctx.fillRect(0, 0, numCells, numCells);
21331
+ ctx.fillStyle = fgColor;
21332
+ if (SUPPORTS_PATH2D) ctx.fill(new Path2D(generatePath(cellsToDraw, margin)));
21333
+ else cells.forEach(function(row, rdx) {
21334
+ row.forEach(function(cell, cdx) {
21335
+ if (cell) ctx.fillRect(cdx + margin, rdx + margin, 1, 1);
21336
+ });
21337
+ });
21338
+ if (calculatedImageSettings) ctx.globalAlpha = calculatedImageSettings.opacity;
21339
+ if (haveImageToRender) ctx.drawImage(image, calculatedImageSettings.x + margin, calculatedImageSettings.y + margin, calculatedImageSettings.w, calculatedImageSettings.h);
21340
+ }
21341
+ });
21342
+ react.default.useEffect(() => {
21343
+ setIsImageLoaded(false);
21344
+ }, [imgSrc]);
21345
+ const canvasStyle = __spreadValues({
21346
+ height: size,
21347
+ width: size
21348
+ }, style);
21349
+ let img = null;
21350
+ if (imgSrc != null) img = /* @__PURE__ */ react.default.createElement("img", {
21351
+ src: imgSrc,
21352
+ key: imgSrc,
21353
+ style: { display: "none" },
21354
+ onLoad: () => {
21355
+ setIsImageLoaded(true);
21356
+ },
21357
+ ref: _image,
21358
+ crossOrigin: calculatedImageSettings == null ? void 0 : calculatedImageSettings.crossOrigin
21359
+ });
21360
+ return /* @__PURE__ */ react.default.createElement(react.default.Fragment, null, /* @__PURE__ */ react.default.createElement("canvas", __spreadValues({
21361
+ style: canvasStyle,
21362
+ height: size,
21363
+ width: size,
21364
+ ref: setCanvasRef,
21365
+ role: "img"
21366
+ }, otherProps)), img);
21367
+ });
21368
+ QRCodeCanvas.displayName = "QRCodeCanvas";
21369
+ var QRCodeSVG = react.default.forwardRef(function QRCodeSVG2(props, forwardedRef) {
21370
+ const _a = props, { value, size = DEFAULT_SIZE$1, level = DEFAULT_LEVEL, bgColor = DEFAULT_BGCOLOR, fgColor = DEFAULT_FGCOLOR, includeMargin = DEFAULT_INCLUDEMARGIN, minVersion = DEFAULT_MINVERSION, boostLevel, title, marginSize, imageSettings } = _a, otherProps = __objRest(_a, [
21371
+ "value",
21372
+ "size",
21373
+ "level",
21374
+ "bgColor",
21375
+ "fgColor",
21376
+ "includeMargin",
21377
+ "minVersion",
21378
+ "boostLevel",
21379
+ "title",
21380
+ "marginSize",
21381
+ "imageSettings"
21382
+ ]);
21383
+ const { margin, cells, numCells, calculatedImageSettings } = useQRCode({
21384
+ value,
21385
+ level,
21386
+ minVersion,
21387
+ boostLevel,
21388
+ includeMargin,
21389
+ marginSize,
21390
+ imageSettings,
21391
+ size
21392
+ });
21393
+ let cellsToDraw = cells;
21394
+ let image = null;
21395
+ if (imageSettings != null && calculatedImageSettings != null) {
21396
+ if (calculatedImageSettings.excavation != null) cellsToDraw = excavateModules(cells, calculatedImageSettings.excavation);
21397
+ image = /* @__PURE__ */ react.default.createElement("image", {
21398
+ href: imageSettings.src,
21399
+ height: calculatedImageSettings.h,
21400
+ width: calculatedImageSettings.w,
21401
+ x: calculatedImageSettings.x + margin,
21402
+ y: calculatedImageSettings.y + margin,
21403
+ preserveAspectRatio: "none",
21404
+ opacity: calculatedImageSettings.opacity,
21405
+ crossOrigin: calculatedImageSettings.crossOrigin
21406
+ });
21407
+ }
21408
+ const fgPath = generatePath(cellsToDraw, margin);
21409
+ return /* @__PURE__ */ react.default.createElement("svg", __spreadValues({
21410
+ height: size,
21411
+ width: size,
21412
+ viewBox: `0 0 ${numCells} ${numCells}`,
21413
+ ref: forwardedRef,
21414
+ role: "img"
21415
+ }, otherProps), !!title && /* @__PURE__ */ react.default.createElement("title", null, title), /* @__PURE__ */ react.default.createElement("path", {
21416
+ fill: bgColor,
21417
+ d: `M0,0 h${numCells}v${numCells}H0z`,
21418
+ shapeRendering: "crispEdges"
21419
+ }), /* @__PURE__ */ react.default.createElement("path", {
21420
+ fill: fgColor,
21421
+ d: fgPath,
21422
+ shapeRendering: "crispEdges"
21423
+ }), image);
21424
+ });
21425
+ QRCodeSVG.displayName = "QRCodeSVG";
21426
+ //#endregion
21427
+ //#region src/composites/qr-code.tsx
21428
+ var DEFAULT_SIZE = 192;
21429
+ function QrCode({ value, size = DEFAULT_SIZE, className, alt }) {
21430
+ const trimmed = value.trim();
21431
+ if (trimmed.length === 0) return null;
21432
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
21433
+ className: cn("inline-flex rounded-md bg-white p-2", className),
21434
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QRCodeSVG, {
21435
+ value: trimmed,
21436
+ size,
21437
+ marginSize: 1,
21438
+ title: alt ?? "QR code"
21439
+ })
21440
+ });
21441
+ }
21442
+ //#endregion
21443
+ //#region src/composites/copy-button.tsx
21444
+ /**
21445
+ * `CopyButton` — a compact button that copies a string `value` to the
21446
+ * clipboard via `navigator.clipboard.writeText`, showing a brief
21447
+ * "copied" check state. Addon-agnostic; used wherever a secret / URL
21448
+ * needs a one-click copy affordance (export setup panels, etc.).
21449
+ */
21450
+ var COPIED_RESET_MS = 2e3;
21451
+ function CopyButton({ value, label, className, disabled }) {
21452
+ const [copied, setCopied] = (0, react$1.useState)(false);
21453
+ const handleCopy = (0, react$1.useCallback)(() => {
21454
+ if (!value) return;
21455
+ navigator.clipboard.writeText(value).then(() => {
21456
+ setCopied(true);
21457
+ setTimeout(() => setCopied(false), COPIED_RESET_MS);
21458
+ });
21459
+ }, [value]);
21460
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Button, {
21461
+ size: "sm",
21462
+ variant: "ghost",
21463
+ type: "button",
21464
+ disabled: disabled || value.length === 0,
21465
+ onClick: handleCopy,
21466
+ className: cn(className),
21467
+ "aria-label": copied ? "Copied" : `Copy ${label ?? "value"}`,
21468
+ children: [copied ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Check, { className: "h-3.5 w-3.5 text-success" }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Copy, { className: "h-3.5 w-3.5" }), label ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
21469
+ className: "ml-1",
21470
+ children: copied ? "Copied" : label
21471
+ }) : null]
21472
+ });
21473
+ }
21474
+ //#endregion
21475
+ //#region src/composites/device-export-panel.tsx
21476
+ /**
21477
+ * DeviceExportPanel — generic, addon-agnostic surface for the
21478
+ * `device-export` capability.
21479
+ *
21480
+ * Renders the COMMON device-export surface for a single export addon
21481
+ * (HomeAssistant via MQTT, HomeKit/HAP, Alexa Smart Home, …):
21482
+ *
21483
+ * - a link-state status badge + exposed-device count from `getStatus`,
21484
+ * - the exposed-devices table from `listExposedDevices` (device name,
21485
+ * status, stream preference) with a per-row unexpose action
21486
+ * (`unexposeDevice`),
21487
+ * - an empty state directing the operator to the device-details page.
21488
+ *
21489
+ * This composite is the reusable replacement for the per-addon
21490
+ * Module-Federation overview tables that each export addon used to
21491
+ * ship. It is driven entirely by the `device-export` cap — there are no
21492
+ * Alexa / HAP / MQTT specifics here. Mount it next to an export addon's
21493
+ * standard settings form (e.g. in the addon-settings modal).
21494
+ *
21495
+ * Routing note: `device-export` is a collection cap. Export addons are
21496
+ * all `hub-only`, so the panel queries `nodeId: 'hub'`. It also passes
21497
+ * `addonId` so the codegen'd cap-router resolves THIS addon's provider
21498
+ * within the local collection — when multiple device-export addons are
21499
+ * co-installed each panel shows its own provider, not provider[0].
21500
+ */
21501
+ var ExposedDeviceArraySchema = zod.z.array(_camstack_types.ExposedDeviceSchema);
21502
+ var STATUS_POLL_INTERVAL_MS = 1e4;
21503
+ function statusVariant(state) {
21504
+ if (state === "linked") return "success";
21505
+ if (state === "error") return "danger";
21506
+ return "warning";
21507
+ }
21508
+ function capitaliseLinkState(state) {
21509
+ if (state === "linked") return "Linked";
21510
+ if (state === "unlinked") return "Unlinked";
21511
+ if (state === "error") return "Error";
21512
+ return state;
21513
+ }
21514
+ /**
21515
+ * A single label/value row in the Setup section. `secret` rows mask the
21516
+ * value behind a reveal toggle; every row gets a copy button.
21517
+ */
21518
+ function SetupFieldRow({ field }) {
21519
+ const [revealed, setRevealed] = (0, react$1.useState)(false);
21520
+ const isSecret = field.secret === true;
21521
+ const displayValue = isSecret && !revealed ? "•".repeat(Math.min(field.value.length, 24)) : field.value;
21522
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
21523
+ className: "flex items-center gap-2 py-1.5",
21524
+ children: [
21525
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
21526
+ className: "text-[11px] text-foreground-subtle w-32 shrink-0",
21527
+ children: field.label
21528
+ }),
21529
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
21530
+ className: "flex-1 min-w-0 truncate font-mono text-xs text-foreground",
21531
+ children: displayValue || "—"
21532
+ }),
21533
+ isSecret && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
21534
+ size: "sm",
21535
+ variant: "ghost",
21536
+ type: "button",
21537
+ "aria-label": revealed ? "Hide value" : "Reveal value",
21538
+ onClick: () => setRevealed((v) => !v),
21539
+ children: revealed ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EyeOff, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Eye, { className: "h-3.5 w-3.5" })
21540
+ }),
21541
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopyButton, {
21542
+ value: field.value,
21543
+ label: field.label
21544
+ })
21545
+ ]
21546
+ });
21547
+ }
21548
+ /**
21549
+ * Generic "Setup" section — pairing QR + copyable label/value rows +
21550
+ * operator note. Driven entirely by the cap's `setup` block; renders
21551
+ * nothing addon-specific.
21552
+ */
21553
+ function SetupSection({ setup }) {
21554
+ const fields = setup.fields ?? [];
21555
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
21556
+ className: "border-b border-border bg-surface-hover/10",
21557
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
21558
+ className: "flex items-center gap-2 px-4 py-2 border-b border-border",
21559
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(QrCode$1, { className: "h-3.5 w-3.5 text-foreground-subtle shrink-0" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
21560
+ className: "text-[11px] font-semibold text-foreground-subtle uppercase tracking-wide",
21561
+ children: "Setup"
21562
+ })]
21563
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
21564
+ className: "flex flex-col gap-3 p-4 sm:flex-row sm:items-start",
21565
+ children: [setup.qr && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
21566
+ className: "shrink-0",
21567
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QrCode, {
21568
+ value: setup.qr,
21569
+ alt: "Pairing QR code"
21570
+ })
21571
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
21572
+ className: "flex-1 min-w-0",
21573
+ children: [setup.note && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
21574
+ className: "text-xs text-foreground-muted whitespace-pre-line mb-2",
21575
+ children: setup.note
21576
+ }), fields.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
21577
+ className: "divide-y divide-border-subtle",
21578
+ children: fields.map((field) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SetupFieldRow, { field }, field.label))
21579
+ })]
21580
+ })]
21581
+ })]
21582
+ });
21583
+ }
21584
+ /**
21585
+ * Generic device-export panel. Addon-agnostic — only the `device-export`
21586
+ * cap drives it.
21587
+ */
21588
+ function DeviceExportPanel({ addonId, onOpenDevice }) {
21589
+ const queryClient = (0, _tanstack_react_query.useQueryClient)();
21590
+ const statusQuery = useDeviceExportGetStatus({
21591
+ nodeId: "hub",
21592
+ addonId
21593
+ }, {
21594
+ refetchInterval: STATUS_POLL_INTERVAL_MS,
21595
+ retry: false
21596
+ });
21597
+ const exposedQuery = useDeviceExportListExposedDevices({
21598
+ nodeId: "hub",
21599
+ addonId
21600
+ }, {
21601
+ refetchInterval: STATUS_POLL_INTERVAL_MS,
21602
+ retry: false
21603
+ });
21604
+ const unexposeMutation = useDeviceExportUnexposeDevice({ onSuccess: () => {
21605
+ queryClient.invalidateQueries({ queryKey: [["deviceExport"]] });
21606
+ } });
21607
+ const status = (0, react$1.useMemo)(() => {
21608
+ const parsed = _camstack_types.DeviceExportStatusSchema.safeParse(statusQuery.data);
21609
+ return parsed.success ? parsed.data : null;
21610
+ }, [statusQuery.data]);
21611
+ const exposed = (0, react$1.useMemo)(() => {
21612
+ const parsed = ExposedDeviceArraySchema.safeParse(exposedQuery.data);
21613
+ return parsed.success ? parsed.data : [];
21614
+ }, [exposedQuery.data]);
21615
+ const linkState = status?.linkState ?? "unlinked";
21616
+ const rows = (0, react$1.useMemo)(() => exposed.map((entry) => ({
21617
+ deviceId: entry.deviceId,
21618
+ displayName: entry.exposedAs ?? `Device ${entry.deviceId}`,
21619
+ streamPreference: "auto",
21620
+ linkState
21621
+ })), [exposed, linkState]);
21622
+ const loading = statusQuery.isLoading || exposedQuery.isLoading;
21623
+ const exposedCount = status?.exposedDeviceCount ?? rows.length;
21624
+ const columns = (0, react$1.useMemo)(() => [
21625
+ {
21626
+ key: "device",
21627
+ header: "Device",
21628
+ render: (row) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
21629
+ className: "flex flex-col",
21630
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
21631
+ className: "text-foreground font-medium",
21632
+ children: row.displayName
21633
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
21634
+ className: "text-foreground-subtle text-xs font-mono",
21635
+ children: ["#", row.deviceId]
21636
+ })]
21637
+ })
21638
+ },
21639
+ {
21640
+ key: "status",
21641
+ header: "Status",
21642
+ render: (row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Badge, {
21643
+ variant: statusVariant(row.linkState),
21644
+ children: capitaliseLinkState(row.linkState)
21645
+ })
21646
+ },
21647
+ {
21648
+ key: "stream",
21649
+ header: "Stream",
21650
+ render: (row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
21651
+ className: "text-xs text-foreground-subtle font-mono",
21652
+ children: row.streamPreference === "auto" ? "Auto" : row.streamPreference
21653
+ })
21654
+ },
21655
+ {
21656
+ key: "actions",
21657
+ header: "",
21658
+ align: "right",
21659
+ render: (row) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
21660
+ className: "flex items-center justify-end gap-2",
21661
+ children: [onOpenDevice && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Button, {
21662
+ size: "sm",
21663
+ variant: "ghost",
21664
+ onClick: () => onOpenDevice(row.deviceId),
21665
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExternalLink, { className: "h-3.5 w-3.5 mr-1" }), "Open"]
21666
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Button, {
21667
+ size: "sm",
21668
+ variant: "ghost",
21669
+ disabled: unexposeMutation.isPending,
21670
+ onClick: () => unexposeMutation.mutate({
21671
+ deviceId: row.deviceId,
21672
+ nodeId: "hub",
21673
+ addonId
21674
+ }),
21675
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Unlink2, { className: "h-3.5 w-3.5 mr-1" }), "Unexpose"]
21676
+ })]
21677
+ })
21678
+ }
21679
+ ], [
21680
+ onOpenDevice,
21681
+ unexposeMutation,
21682
+ addonId
21683
+ ]);
21684
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
21685
+ className: "rounded-lg border border-border bg-surface overflow-hidden",
21686
+ children: [
21687
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
21688
+ className: "flex items-center justify-between gap-3 px-4 py-2.5 border-b border-border bg-surface-hover/20",
21689
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
21690
+ className: "flex items-center gap-2 min-w-0",
21691
+ children: [
21692
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Share2, { className: "h-3.5 w-3.5 text-foreground-subtle shrink-0" }),
21693
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
21694
+ className: "text-[11px] font-semibold text-foreground-subtle uppercase tracking-wide",
21695
+ children: "Exported devices"
21696
+ }),
21697
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Badge, {
21698
+ variant: statusVariant(linkState),
21699
+ children: capitaliseLinkState(linkState)
21700
+ }),
21701
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
21702
+ className: "text-[11px] text-foreground-subtle",
21703
+ children: [exposedCount, " exposed"]
21704
+ })
21705
+ ]
21706
+ }), loading && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LoaderCircle, { className: "h-3.5 w-3.5 animate-spin text-foreground-subtle" })]
21707
+ }),
21708
+ status?.error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
21709
+ className: "px-4 py-3 border-b border-border",
21710
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorBox, { message: status.error })
21711
+ }),
21712
+ status?.setup && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SetupSection, { setup: status.setup }),
21713
+ rows.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmptyState, {
21714
+ icon: Share2,
21715
+ title: "No devices exposed",
21716
+ description: `Expose a camera to "${addonId}" from its device-details page to surface it in the connected ecosystem.`
21717
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
21718
+ className: "p-3",
21719
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DataTable, {
21720
+ columns,
21721
+ rows,
21722
+ rowKey: (row) => row.deviceId
21723
+ })
21724
+ })
21725
+ ]
21726
+ });
21727
+ }
21728
+ //#endregion
20103
21729
  //#region src/composites/audio-waveform.tsx
20104
21730
  /**
20105
21731
  * Canvas-based audio waveform visualization.
@@ -20107,9 +21733,9 @@ function StreamBrokerSelector({ deviceId, value, onChange, disabled, label, clas
20107
21733
  * Downsamples to pixel resolution for performance.
20108
21734
  */
20109
21735
  function AudioWaveform({ samples, sampleRate = 16e3, height = 96, className = "", color = "#3b82f6", bgColor = "transparent" }) {
20110
- const canvasRef = (0, react.useRef)(null);
20111
- const containerRef = (0, react.useRef)(null);
20112
- const draw = (0, react.useCallback)(() => {
21736
+ const canvasRef = (0, react$1.useRef)(null);
21737
+ const containerRef = (0, react$1.useRef)(null);
21738
+ const draw = (0, react$1.useCallback)(() => {
20113
21739
  const canvas = canvasRef.current;
20114
21740
  const container = containerRef.current;
20115
21741
  if (!canvas || !container || !samples || samples.length === 0) return;
@@ -20161,10 +21787,10 @@ function AudioWaveform({ samples, sampleRate = 16e3, height = 96, className = ""
20161
21787
  color,
20162
21788
  bgColor
20163
21789
  ]);
20164
- (0, react.useEffect)(() => {
21790
+ (0, react$1.useEffect)(() => {
20165
21791
  draw();
20166
21792
  }, [draw]);
20167
- (0, react.useEffect)(() => {
21793
+ (0, react$1.useEffect)(() => {
20168
21794
  const observer = new ResizeObserver(() => draw());
20169
21795
  const el = containerRef.current;
20170
21796
  if (el) observer.observe(el);
@@ -20203,10 +21829,10 @@ function AudioWaveform({ samples, sampleRate = 16e3, height = 96, className = ""
20203
21829
  * (each chunk, ~0.5s, produces one sample via `frame.level.dbfs`).
20204
21830
  */
20205
21831
  function AudioLevelWaveform({ currentDbfs, durationSec = 30, maxSamples = 120, height = 64, className = "", color = "#10b981", clipColor = "#ef4444", clipThreshold = -6, minDbfs = -96 }) {
20206
- const canvasRef = (0, react.useRef)(null);
20207
- const containerRef = (0, react.useRef)(null);
20208
- const [samples, setSamples] = (0, react.useState)([]);
20209
- (0, react.useEffect)(() => {
21832
+ const canvasRef = (0, react$1.useRef)(null);
21833
+ const containerRef = (0, react$1.useRef)(null);
21834
+ const [samples, setSamples] = (0, react$1.useState)([]);
21835
+ (0, react$1.useEffect)(() => {
20210
21836
  if (currentDbfs === null) return;
20211
21837
  setSamples((prev) => {
20212
21838
  const next = [...prev, {
@@ -20216,7 +21842,7 @@ function AudioLevelWaveform({ currentDbfs, durationSec = 30, maxSamples = 120, h
20216
21842
  return next.length > maxSamples ? next.slice(-maxSamples) : next;
20217
21843
  });
20218
21844
  }, [currentDbfs, maxSamples]);
20219
- const draw = (0, react.useCallback)(() => {
21845
+ const draw = (0, react$1.useCallback)(() => {
20220
21846
  const canvas = canvasRef.current;
20221
21847
  const container = containerRef.current;
20222
21848
  if (!canvas || !container) return;
@@ -20269,10 +21895,10 @@ function AudioLevelWaveform({ currentDbfs, durationSec = 30, maxSamples = 120, h
20269
21895
  clipThreshold,
20270
21896
  minDbfs
20271
21897
  ]);
20272
- (0, react.useEffect)(() => {
21898
+ (0, react$1.useEffect)(() => {
20273
21899
  draw();
20274
21900
  }, [draw]);
20275
- (0, react.useEffect)(() => {
21901
+ (0, react$1.useEffect)(() => {
20276
21902
  const observer = new ResizeObserver(() => draw());
20277
21903
  const el = containerRef.current;
20278
21904
  if (el) observer.observe(el);
@@ -20394,7 +22020,7 @@ function AudioClassificationList({ classifications, processing = false, inferenc
20394
22020
  * Expandable log box showing the raw JSON response from a pipeline run.
20395
22021
  */
20396
22022
  function ResponseLog({ data, label = "Response", className = "" }) {
20397
- const [expanded, setExpanded] = (0, react.useState)(false);
22023
+ const [expanded, setExpanded] = (0, react$1.useState)(false);
20398
22024
  if (!data) return null;
20399
22025
  const json = JSON.stringify(data, null, 2);
20400
22026
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -20466,17 +22092,17 @@ function PhaseIcon({ phase, ...props }) {
20466
22092
  * keeping idle subscriptions alive.
20467
22093
  */
20468
22094
  function useLiveBuffer(max) {
20469
- const [entries, setEntries] = (0, react.useState)([]);
20470
- const append = (0, react.useCallback)((entry) => {
22095
+ const [entries, setEntries] = (0, react$1.useState)([]);
22096
+ const append = (0, react$1.useCallback)((entry) => {
20471
22097
  setEntries((prev) => {
20472
22098
  const next = [...prev, entry];
20473
22099
  return next.length > max ? next.slice(-max) : next;
20474
22100
  });
20475
22101
  }, [max]);
20476
- const reset = (0, react.useCallback)(() => {
22102
+ const reset = (0, react$1.useCallback)(() => {
20477
22103
  setEntries([]);
20478
22104
  }, []);
20479
- return (0, react.useMemo)(() => ({
22105
+ return (0, react$1.useMemo)(() => ({
20480
22106
  entries,
20481
22107
  append,
20482
22108
  reset
@@ -20550,15 +22176,15 @@ function passesLevel(logLevel, filterLevel) {
20550
22176
  return (LEVEL_SEVERITY[logLevel] ?? 0) >= (LEVEL_SEVERITY[filterLevel] ?? 0);
20551
22177
  }
20552
22178
  function LogStream({ agentId: propsAgentId, addonId: propsAddonId, deviceId: propsDeviceId, integrationId: propsIntegrationId, requestId: propsRequestId, level: initialLevel, maxHeight = "max-h-96", showScope = false, showFilters = true, limit = 100, liveBuffer: externalBuffer, onClose, className }) {
20553
- const [localAddonId, setLocalAddonId] = (0, react.useState)("");
20554
- const [localDeviceId, setLocalDeviceId] = (0, react.useState)("");
20555
- const [levelFilter, setLevelFilter] = (0, react.useState)(initialLevel);
22179
+ const [localAddonId, setLocalAddonId] = (0, react$1.useState)("");
22180
+ const [localDeviceId, setLocalDeviceId] = (0, react$1.useState)("");
22181
+ const [levelFilter, setLevelFilter] = (0, react$1.useState)(initialLevel);
20556
22182
  const agentId = propsAgentId;
20557
22183
  const addonId = propsAddonId ?? (localAddonId || void 0);
20558
22184
  const deviceId = propsDeviceId ?? (localDeviceId ? Number(localDeviceId) : void 0);
20559
22185
  const integrationId = propsIntegrationId;
20560
22186
  const requestId = propsRequestId;
20561
- const tags = (0, react.useMemo)(() => {
22187
+ const tags = (0, react$1.useMemo)(() => {
20562
22188
  const t = {};
20563
22189
  if (agentId) t.agentId = agentId;
20564
22190
  if (addonId) t.addonId = addonId;
@@ -20576,15 +22202,15 @@ function LogStream({ agentId: propsAgentId, addonId: propsAddonId, deviceId: pro
20576
22202
  const fallbackBuffer = useLiveBuffer(MAX_LIVE_ENTRIES$2);
20577
22203
  const buffer = externalBuffer ?? fallbackBuffer;
20578
22204
  const liveLogs = buffer.entries;
20579
- const [clearedAt, setClearedAt] = (0, react.useState)(0);
20580
- const [autoScroll, setAutoScroll] = (0, react.useState)(false);
20581
- const [copied, setCopied] = (0, react.useState)(false);
20582
- const [expandedRows, setExpandedRows] = (0, react.useState)(/* @__PURE__ */ new Set());
20583
- const [searchText, setSearchText] = (0, react.useState)("");
20584
- const scrollRef = (0, react.useRef)(null);
22205
+ const [clearedAt, setClearedAt] = (0, react$1.useState)(0);
22206
+ const [autoScroll, setAutoScroll] = (0, react$1.useState)(false);
22207
+ const [copied, setCopied] = (0, react$1.useState)(false);
22208
+ const [expandedRows, setExpandedRows] = (0, react$1.useState)(/* @__PURE__ */ new Set());
22209
+ const [searchText, setSearchText] = (0, react$1.useState)("");
22210
+ const scrollRef = (0, react$1.useRef)(null);
20585
22211
  const scopeKey = `${agentId ?? ""}:${addonId ?? ""}:${String(deviceId ?? "")}:${integrationId ?? ""}:${requestId ?? ""}`;
20586
- const prevScopeRef = (0, react.useRef)(scopeKey);
20587
- (0, react.useEffect)(() => {
22212
+ const prevScopeRef = (0, react$1.useRef)(scopeKey);
22213
+ (0, react$1.useEffect)(() => {
20588
22214
  if (prevScopeRef.current !== scopeKey) {
20589
22215
  prevScopeRef.current = scopeKey;
20590
22216
  buffer.reset();
@@ -20599,8 +22225,8 @@ function LogStream({ agentId: propsAgentId, addonId: propsAddonId, deviceId: pro
20599
22225
  trpc.logs.subscribe.useSubscription({ ...tags ? { tags } : {} }, { onData: (entry) => {
20600
22226
  buffer.append(entry);
20601
22227
  } });
20602
- const prevLiveCountRef = (0, react.useRef)(liveLogs.length);
20603
- (0, react.useEffect)(() => {
22228
+ const prevLiveCountRef = (0, react$1.useRef)(liveLogs.length);
22229
+ (0, react$1.useEffect)(() => {
20604
22230
  const el = scrollRef.current;
20605
22231
  if (!el) {
20606
22232
  prevLiveCountRef.current = liveLogs.length;
@@ -20616,7 +22242,7 @@ function LogStream({ agentId: propsAgentId, addonId: propsAddonId, deviceId: pro
20616
22242
  el.scrollTop += rowHeight * (liveLogs.length - prevCount);
20617
22243
  }
20618
22244
  }, [liveLogs.length, autoScroll]);
20619
- const allLogs = (0, react.useMemo)(() => {
22245
+ const allLogs = (0, react$1.useMemo)(() => {
20620
22246
  const initial = (initialLogs ?? []).map((log) => ({
20621
22247
  timestamp: log.timestamp,
20622
22248
  level: log.level,
@@ -20661,7 +22287,7 @@ function LogStream({ agentId: propsAgentId, addonId: propsAddonId, deviceId: pro
20661
22287
  clearedAt,
20662
22288
  searchText
20663
22289
  ]);
20664
- const handleCopyAll = (0, react.useCallback)(() => {
22290
+ const handleCopyAll = (0, react$1.useCallback)(() => {
20665
22291
  const lines = allLogs.map((log) => {
20666
22292
  const time = new Date(log.timestamp).toLocaleTimeString();
20667
22293
  const tagsStr = log.tags ? " " + Object.entries(log.tags).filter(([, v]) => v).map(([k, v]) => `${k}=${v}`).join(" ") : "";
@@ -20673,7 +22299,7 @@ function LogStream({ agentId: propsAgentId, addonId: propsAddonId, deviceId: pro
20673
22299
  });
20674
22300
  }, [allLogs]);
20675
22301
  const clearMutation = trpc.logs.clear.useMutation();
20676
- const handleClear = (0, react.useCallback)(() => {
22302
+ const handleClear = (0, react$1.useCallback)(() => {
20677
22303
  setClearedAt(Date.now());
20678
22304
  buffer.reset();
20679
22305
  clearMutation.mutate({ ...tags ? { tags } : {} });
@@ -20682,7 +22308,7 @@ function LogStream({ agentId: propsAgentId, addonId: propsAddonId, deviceId: pro
20682
22308
  clearMutation,
20683
22309
  tags
20684
22310
  ]);
20685
- const toggleRow = (0, react.useCallback)((rowKey) => {
22311
+ const toggleRow = (0, react$1.useCallback)((rowKey) => {
20686
22312
  setExpandedRows((prev) => {
20687
22313
  const next = new Set(prev);
20688
22314
  if (next.has(rowKey)) next.delete(rowKey);
@@ -20690,8 +22316,8 @@ function LogStream({ agentId: propsAgentId, addonId: propsAddonId, deviceId: pro
20690
22316
  return next;
20691
22317
  });
20692
22318
  }, []);
20693
- const [copiedRowKey, setCopiedRowKey] = (0, react.useState)(null);
20694
- const copyOne = (0, react.useCallback)((log, key) => {
22319
+ const [copiedRowKey, setCopiedRowKey] = (0, react$1.useState)(null);
22320
+ const copyOne = (0, react$1.useCallback)((log, key) => {
20695
22321
  const time = new Date(log.timestamp).toISOString();
20696
22322
  const tagsStr = log.tags ? " " + Object.entries(log.tags).filter(([, v]) => v).map(([k, v]) => `${k}=${v}`).join(" ") : "";
20697
22323
  const metaStr = log.meta && Object.keys(log.meta).length > 0 ? ` meta=${JSON.stringify(log.meta)}` : "";
@@ -20701,7 +22327,7 @@ function LogStream({ agentId: propsAgentId, addonId: propsAddonId, deviceId: pro
20701
22327
  setTimeout(() => setCopiedRowKey((prev) => prev === key ? null : prev), 1200);
20702
22328
  });
20703
22329
  }, []);
20704
- const rowKey = (0, react.useCallback)((log) => `${log.timestamp}|${log.level}|${log.scope ?? ""}|${log.message}`, []);
22330
+ const rowKey = (0, react$1.useCallback)((log) => `${log.timestamp}|${log.level}|${log.scope ?? ""}|${log.message}`, []);
20705
22331
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
20706
22332
  className: cn("h-full min-h-0 flex flex-col", className),
20707
22333
  onClick: (e) => e.stopPropagation(),
@@ -21266,11 +22892,11 @@ function hasContent(entry) {
21266
22892
  }
21267
22893
  var MAX_LIVE_ENTRIES$1 = 300;
21268
22894
  function EventStream({ agentId, addonId, deviceId, defaultCategories, categories: legacyCategories, category: propsCategory, maxHeight = "max-h-96", limit = 50, showCategoryFilter = true, showFilters: _showFilters = false, liveBuffer: externalBuffer, onClose, className }) {
21269
- const defaultsArray = (0, react.useMemo)(() => defaultCategories ?? legacyCategories ?? DEFAULT_EVENT_CATEGORIES, [defaultCategories, legacyCategories]);
21270
- const defaultsKey = (0, react.useMemo)(() => [...defaultsArray].sort().join(","), [defaultsArray]);
21271
- const [activeCategories, setActiveCategories] = (0, react.useState)(() => new Set(defaultsArray));
21272
- const prevDefaultsKey = (0, react.useRef)(defaultsKey);
21273
- (0, react.useEffect)(() => {
22895
+ const defaultsArray = (0, react$1.useMemo)(() => defaultCategories ?? legacyCategories ?? DEFAULT_EVENT_CATEGORIES, [defaultCategories, legacyCategories]);
22896
+ const defaultsKey = (0, react$1.useMemo)(() => [...defaultsArray].sort().join(","), [defaultsArray]);
22897
+ const [activeCategories, setActiveCategories] = (0, react$1.useState)(() => new Set(defaultsArray));
22898
+ const prevDefaultsKey = (0, react$1.useRef)(defaultsKey);
22899
+ (0, react$1.useEffect)(() => {
21274
22900
  if (prevDefaultsKey.current !== defaultsKey) {
21275
22901
  prevDefaultsKey.current = defaultsKey;
21276
22902
  setActiveCategories(new Set(defaultsArray));
@@ -21279,17 +22905,17 @@ function EventStream({ agentId, addonId, deviceId, defaultCategories, categories
21279
22905
  const fallbackBuffer = useLiveBuffer(MAX_LIVE_ENTRIES$1);
21280
22906
  const buffer = externalBuffer ?? fallbackBuffer;
21281
22907
  const liveEvents = buffer.entries;
21282
- const [autoScroll, setAutoScroll] = (0, react.useState)(true);
21283
- const [expandedRows, setExpandedRows] = (0, react.useState)(/* @__PURE__ */ new Set());
21284
- const [searchText, setSearchText] = (0, react.useState)("");
21285
- const [filterOpen, setFilterOpen] = (0, react.useState)(false);
21286
- const [categorySearch, setCategorySearch] = (0, react.useState)("");
21287
- const [clearedAt, setClearedAt] = (0, react.useState)(0);
21288
- const scrollRef = (0, react.useRef)(null);
21289
- const filterRootRef = (0, react.useRef)(null);
22908
+ const [autoScroll, setAutoScroll] = (0, react$1.useState)(true);
22909
+ const [expandedRows, setExpandedRows] = (0, react$1.useState)(/* @__PURE__ */ new Set());
22910
+ const [searchText, setSearchText] = (0, react$1.useState)("");
22911
+ const [filterOpen, setFilterOpen] = (0, react$1.useState)(false);
22912
+ const [categorySearch, setCategorySearch] = (0, react$1.useState)("");
22913
+ const [clearedAt, setClearedAt] = (0, react$1.useState)(0);
22914
+ const scrollRef = (0, react$1.useRef)(null);
22915
+ const filterRootRef = (0, react$1.useRef)(null);
21290
22916
  const scopeKey = `${agentId ?? ""}:${addonId ?? ""}:${String(deviceId ?? "")}:${propsCategory ?? ""}`;
21291
- const prevScopeRef = (0, react.useRef)(scopeKey);
21292
- (0, react.useEffect)(() => {
22917
+ const prevScopeRef = (0, react$1.useRef)(scopeKey);
22918
+ (0, react$1.useEffect)(() => {
21293
22919
  if (prevScopeRef.current !== scopeKey) {
21294
22920
  prevScopeRef.current = scopeKey;
21295
22921
  buffer.reset();
@@ -21297,7 +22923,7 @@ function EventStream({ agentId, addonId, deviceId, defaultCategories, categories
21297
22923
  setClearedAt(0);
21298
22924
  }
21299
22925
  }, [scopeKey, buffer]);
21300
- (0, react.useEffect)(() => {
22926
+ (0, react$1.useEffect)(() => {
21301
22927
  if (!filterOpen) return;
21302
22928
  const onDocClick = (e) => {
21303
22929
  const root = filterRootRef.current;
@@ -21308,7 +22934,7 @@ function EventStream({ agentId, addonId, deviceId, defaultCategories, categories
21308
22934
  document.removeEventListener("mousedown", onDocClick);
21309
22935
  };
21310
22936
  }, [filterOpen]);
21311
- const scopeInput = (0, react.useMemo)(() => {
22937
+ const scopeInput = (0, react$1.useMemo)(() => {
21312
22938
  const s = {};
21313
22939
  if (agentId) s.agentId = agentId;
21314
22940
  if (addonId) s.addonId = addonId;
@@ -21321,8 +22947,8 @@ function EventStream({ agentId, addonId, deviceId, defaultCategories, categories
21321
22947
  deviceId,
21322
22948
  propsCategory
21323
22949
  ]);
21324
- const activeArray = (0, react.useMemo)(() => [...activeCategories].sort(), [activeCategories]);
21325
- const getRecentInput = (0, react.useMemo)(() => {
22950
+ const activeArray = (0, react$1.useMemo)(() => [...activeCategories].sort(), [activeCategories]);
22951
+ const getRecentInput = (0, react$1.useMemo)(() => {
21326
22952
  const s = {
21327
22953
  ...scopeInput,
21328
22954
  limit
@@ -21332,12 +22958,12 @@ function EventStream({ agentId, addonId, deviceId, defaultCategories, categories
21332
22958
  }, [
21333
22959
  scopeInput,
21334
22960
  limit,
21335
- (0, react.useMemo)(() => activeArray.join(","), [activeArray]),
22961
+ (0, react$1.useMemo)(() => activeArray.join(","), [activeArray]),
21336
22962
  activeArray
21337
22963
  ]);
21338
22964
  const { data: initialEvents, isLoading } = trpc.systemEvents.getRecent.useQuery(getRecentInput, { staleTime: 3e4 });
21339
- const activeCategoriesRef = (0, react.useRef)(activeCategories);
21340
- (0, react.useEffect)(() => {
22965
+ const activeCategoriesRef = (0, react$1.useRef)(activeCategories);
22966
+ (0, react$1.useEffect)(() => {
21341
22967
  activeCategoriesRef.current = activeCategories;
21342
22968
  }, [activeCategories]);
21343
22969
  const subInput = scopeInput;
@@ -21348,8 +22974,8 @@ function EventStream({ agentId, addonId, deviceId, defaultCategories, categories
21348
22974
  if (!activeCategoriesRef.current.has(entry.category)) return;
21349
22975
  buffer.append(entry);
21350
22976
  } });
21351
- const prevLiveCountRef = (0, react.useRef)(liveEvents.length);
21352
- (0, react.useEffect)(() => {
22977
+ const prevLiveCountRef = (0, react$1.useRef)(liveEvents.length);
22978
+ (0, react$1.useEffect)(() => {
21353
22979
  const el = scrollRef.current;
21354
22980
  if (!el) {
21355
22981
  prevLiveCountRef.current = liveEvents.length;
@@ -21365,7 +22991,7 @@ function EventStream({ agentId, addonId, deviceId, defaultCategories, categories
21365
22991
  el.scrollTop += rowHeight * (liveEvents.length - prevCount);
21366
22992
  }
21367
22993
  }, [liveEvents.length, autoScroll]);
21368
- const allEvents = (0, react.useMemo)(() => {
22994
+ const allEvents = (0, react$1.useMemo)(() => {
21369
22995
  const byId = /* @__PURE__ */ new Map();
21370
22996
  for (const e of initialEvents ?? []) byId.set(e.id, e);
21371
22997
  for (const e of liveEvents) byId.set(e.id, e);
@@ -21394,7 +23020,7 @@ function EventStream({ agentId, addonId, deviceId, defaultCategories, categories
21394
23020
  searchText,
21395
23021
  clearedAt
21396
23022
  ]);
21397
- const toggleRow = (0, react.useCallback)((id) => {
23023
+ const toggleRow = (0, react$1.useCallback)((id) => {
21398
23024
  setExpandedRows((prev) => {
21399
23025
  const next = new Set(prev);
21400
23026
  if (next.has(id)) next.delete(id);
@@ -21402,7 +23028,7 @@ function EventStream({ agentId, addonId, deviceId, defaultCategories, categories
21402
23028
  return next;
21403
23029
  });
21404
23030
  }, []);
21405
- const toggleCategory = (0, react.useCallback)((cat) => {
23031
+ const toggleCategory = (0, react$1.useCallback)((cat) => {
21406
23032
  setActiveCategories((prev) => {
21407
23033
  const next = new Set(prev);
21408
23034
  if (next.has(cat)) next.delete(cat);
@@ -21410,43 +23036,43 @@ function EventStream({ agentId, addonId, deviceId, defaultCategories, categories
21410
23036
  return next;
21411
23037
  });
21412
23038
  }, []);
21413
- const handleReset = (0, react.useCallback)(() => {
23039
+ const handleReset = (0, react$1.useCallback)(() => {
21414
23040
  setActiveCategories(new Set(defaultsArray));
21415
23041
  setSearchText("");
21416
23042
  setClearedAt(0);
21417
23043
  }, [defaultsArray]);
21418
- const handleClear = (0, react.useCallback)(() => {
23044
+ const handleClear = (0, react$1.useCallback)(() => {
21419
23045
  setClearedAt(Date.now());
21420
23046
  buffer.reset();
21421
23047
  }, [buffer]);
21422
- const [copiedAll, setCopiedAll] = (0, react.useState)(false);
21423
- const [copiedRowId, setCopiedRowId] = (0, react.useState)(null);
21424
- const formatEventForCopy = (0, react.useCallback)((event) => {
23048
+ const [copiedAll, setCopiedAll] = (0, react$1.useState)(false);
23049
+ const [copiedRowId, setCopiedRowId] = (0, react$1.useState)(null);
23050
+ const formatEventForCopy = (0, react$1.useCallback)((event) => {
21425
23051
  const time = new Date(event.timestamp).toISOString();
21426
23052
  const summary = summarizeEvent(event.category, event.data) ?? "";
21427
23053
  const summaryStr = summary ? ` ${summary}` : "";
21428
23054
  return `${time} [${event.category}]${summaryStr} data=${JSON.stringify(event.data)}`;
21429
23055
  }, []);
21430
- const handleCopyAll = (0, react.useCallback)(() => {
23056
+ const handleCopyAll = (0, react$1.useCallback)(() => {
21431
23057
  const lines = allEvents.map(formatEventForCopy);
21432
23058
  navigator.clipboard.writeText(lines.join("\n")).then(() => {
21433
23059
  setCopiedAll(true);
21434
23060
  setTimeout(() => setCopiedAll(false), 1500);
21435
23061
  });
21436
23062
  }, [allEvents, formatEventForCopy]);
21437
- const copyOne = (0, react.useCallback)((event) => {
23063
+ const copyOne = (0, react$1.useCallback)((event) => {
21438
23064
  navigator.clipboard.writeText(formatEventForCopy(event)).then(() => {
21439
23065
  setCopiedRowId(event.id);
21440
23066
  setTimeout(() => setCopiedRowId((prev) => prev === event.id ? null : prev), 1200);
21441
23067
  });
21442
23068
  }, [formatEventForCopy]);
21443
- const handleSelectAll = (0, react.useCallback)(() => {
23069
+ const handleSelectAll = (0, react$1.useCallback)(() => {
21444
23070
  setActiveCategories(new Set(ALL_EVENT_CATEGORIES));
21445
23071
  }, []);
21446
- const handleSelectNone = (0, react.useCallback)(() => {
23072
+ const handleSelectNone = (0, react$1.useCallback)(() => {
21447
23073
  setActiveCategories(/* @__PURE__ */ new Set());
21448
23074
  }, []);
21449
- const filteredPopoverCategories = (0, react.useMemo)(() => {
23075
+ const filteredPopoverCategories = (0, react$1.useMemo)(() => {
21450
23076
  const needle = categorySearch.trim().toLowerCase();
21451
23077
  if (!needle) return ALL_EVENT_CATEGORIES;
21452
23078
  return ALL_EVENT_CATEGORIES.filter((c) => c.toLowerCase().includes(needle));
@@ -21824,8 +23450,8 @@ function DiscoveryPanel({ deviceId, className = "", onOpenChild }) {
21824
23450
  const releaseMutation = trpc.deviceDiscovery.releaseDevice.useMutation({ onSuccess: () => {
21825
23451
  utils.deviceDiscovery.listDiscovered.invalidate({ deviceId });
21826
23452
  } });
21827
- const [busyChildId, setBusyChildId] = (0, react.useState)(null);
21828
- const { available, adopted } = (0, react.useMemo)(() => {
23453
+ const [busyChildId, setBusyChildId] = (0, react$1.useState)(null);
23454
+ const { available, adopted } = (0, react$1.useMemo)(() => {
21829
23455
  const list = listQuery.data ?? [];
21830
23456
  const sortKey = (c) => typeof c.metadata.rtspChannel === "number" ? c.metadata.rtspChannel : Number.POSITIVE_INFINITY;
21831
23457
  const byChannel = (a, b) => {
@@ -22104,20 +23730,20 @@ var MAX_LIVE_ENTRIES = 300;
22104
23730
  */
22105
23731
  var ALL_DEVICE_CAP_NAMES = Object.freeze([...new Set(_camstack_types.ALL_CAPABILITY_DEFINITIONS.filter((c) => c.scope === "device").map((c) => c.name))].sort());
22106
23732
  function StateValuesStream({ deviceId, defaultCaps, maxHeight = "max-h-96", limit = 50, liveBuffer: externalBuffer, onClose, className }) {
22107
- const [activeCaps, setActiveCaps] = (0, react.useState)((0, react.useMemo)(() => new Set(defaultCaps ?? []), [defaultCaps]));
22108
- const [searchText, setSearchText] = (0, react.useState)("");
22109
- const [autoScroll, setAutoScroll] = (0, react.useState)(true);
22110
- const [expandedRows, setExpandedRows] = (0, react.useState)(/* @__PURE__ */ new Set());
22111
- const [clearedAt, setClearedAt] = (0, react.useState)(0);
22112
- const [filterOpen, setFilterOpen] = (0, react.useState)(false);
22113
- const [filterSearch, setFilterSearch] = (0, react.useState)("");
22114
- const filterRootRef = (0, react.useRef)(null);
23733
+ const [activeCaps, setActiveCaps] = (0, react$1.useState)((0, react$1.useMemo)(() => new Set(defaultCaps ?? []), [defaultCaps]));
23734
+ const [searchText, setSearchText] = (0, react$1.useState)("");
23735
+ const [autoScroll, setAutoScroll] = (0, react$1.useState)(true);
23736
+ const [expandedRows, setExpandedRows] = (0, react$1.useState)(/* @__PURE__ */ new Set());
23737
+ const [clearedAt, setClearedAt] = (0, react$1.useState)(0);
23738
+ const [filterOpen, setFilterOpen] = (0, react$1.useState)(false);
23739
+ const [filterSearch, setFilterSearch] = (0, react$1.useState)("");
23740
+ const filterRootRef = (0, react$1.useRef)(null);
22115
23741
  const fallbackBuffer = useLiveBuffer(MAX_LIVE_ENTRIES);
22116
23742
  const buffer = externalBuffer ?? fallbackBuffer;
22117
23743
  const liveEvents = buffer.entries;
22118
- const scrollRef = (0, react.useRef)(null);
22119
- const prevDeviceRef = (0, react.useRef)(deviceId);
22120
- (0, react.useEffect)(() => {
23744
+ const scrollRef = (0, react$1.useRef)(null);
23745
+ const prevDeviceRef = (0, react$1.useRef)(deviceId);
23746
+ (0, react$1.useEffect)(() => {
22121
23747
  if (prevDeviceRef.current !== deviceId) {
22122
23748
  prevDeviceRef.current = deviceId;
22123
23749
  buffer.reset();
@@ -22125,14 +23751,14 @@ function StateValuesStream({ deviceId, defaultCaps, maxHeight = "max-h-96", limi
22125
23751
  setClearedAt(0);
22126
23752
  }
22127
23753
  }, [deviceId, buffer]);
22128
- const recentInput = (0, react.useMemo)(() => ({
23754
+ const recentInput = (0, react$1.useMemo)(() => ({
22129
23755
  deviceId,
22130
23756
  category: _camstack_types.EventCategory.DeviceStateChanged,
22131
23757
  limit
22132
23758
  }), [deviceId, limit]);
22133
23759
  const { data: initialEvents, isLoading } = trpc.systemEvents.getRecent.useQuery(recentInput, { staleTime: 3e4 });
22134
- const activeCapsRef = (0, react.useRef)(activeCaps);
22135
- (0, react.useEffect)(() => {
23760
+ const activeCapsRef = (0, react$1.useRef)(activeCaps);
23761
+ (0, react$1.useEffect)(() => {
22136
23762
  activeCapsRef.current = activeCaps;
22137
23763
  }, [activeCaps]);
22138
23764
  trpc.systemEvents.subscribe.useSubscription({
@@ -22146,8 +23772,8 @@ function StateValuesStream({ deviceId, defaultCaps, maxHeight = "max-h-96", limi
22146
23772
  if (active.size > 0 && !active.has(entry.capName)) return;
22147
23773
  buffer.append(entry);
22148
23774
  } });
22149
- const prevLiveCountRef = (0, react.useRef)(liveEvents.length);
22150
- (0, react.useEffect)(() => {
23775
+ const prevLiveCountRef = (0, react$1.useRef)(liveEvents.length);
23776
+ (0, react$1.useEffect)(() => {
22151
23777
  const el = scrollRef.current;
22152
23778
  if (!el) {
22153
23779
  prevLiveCountRef.current = liveEvents.length;
@@ -22164,7 +23790,7 @@ function StateValuesStream({ deviceId, defaultCaps, maxHeight = "max-h-96", limi
22164
23790
  el.scrollTop += rowHeight * newCount;
22165
23791
  }
22166
23792
  }, [liveEvents.length, autoScroll]);
22167
- const allEntries = (0, react.useMemo)(() => {
23793
+ const allEntries = (0, react$1.useMemo)(() => {
22168
23794
  const byId = /* @__PURE__ */ new Map();
22169
23795
  for (const e of initialEvents ?? []) {
22170
23796
  const entry = toEntry(e);
@@ -22196,7 +23822,7 @@ function StateValuesStream({ deviceId, defaultCaps, maxHeight = "max-h-96", limi
22196
23822
  searchText,
22197
23823
  clearedAt
22198
23824
  ]);
22199
- const visibleCaps = (0, react.useMemo)(() => {
23825
+ const visibleCaps = (0, react$1.useMemo)(() => {
22200
23826
  const caps = new Set(ALL_DEVICE_CAP_NAMES);
22201
23827
  for (const e of initialEvents ?? []) {
22202
23828
  const entry = toEntry(e);
@@ -22205,7 +23831,7 @@ function StateValuesStream({ deviceId, defaultCaps, maxHeight = "max-h-96", limi
22205
23831
  for (const e of liveEvents) caps.add(e.capName);
22206
23832
  return [...caps].sort();
22207
23833
  }, [initialEvents, liveEvents]);
22208
- const toggleRow = (0, react.useCallback)((id) => {
23834
+ const toggleRow = (0, react$1.useCallback)((id) => {
22209
23835
  setExpandedRows((prev) => {
22210
23836
  const next = new Set(prev);
22211
23837
  if (next.has(id)) next.delete(id);
@@ -22213,7 +23839,7 @@ function StateValuesStream({ deviceId, defaultCaps, maxHeight = "max-h-96", limi
22213
23839
  return next;
22214
23840
  });
22215
23841
  }, []);
22216
- const toggleCap = (0, react.useCallback)((cap) => {
23842
+ const toggleCap = (0, react$1.useCallback)((cap) => {
22217
23843
  setActiveCaps((prev) => {
22218
23844
  const next = new Set(prev);
22219
23845
  if (next.has(cap)) next.delete(cap);
@@ -22221,39 +23847,39 @@ function StateValuesStream({ deviceId, defaultCaps, maxHeight = "max-h-96", limi
22221
23847
  return next;
22222
23848
  });
22223
23849
  }, []);
22224
- const handleReset = (0, react.useCallback)(() => {
23850
+ const handleReset = (0, react$1.useCallback)(() => {
22225
23851
  setActiveCaps(new Set(defaultCaps ?? []));
22226
23852
  setSearchText("");
22227
23853
  }, [defaultCaps]);
22228
- const handleClear = (0, react.useCallback)(() => {
23854
+ const handleClear = (0, react$1.useCallback)(() => {
22229
23855
  setClearedAt(Date.now());
22230
23856
  buffer.reset();
22231
23857
  }, [buffer]);
22232
- const [copiedAll, setCopiedAll] = (0, react.useState)(false);
22233
- const [copiedRowId, setCopiedRowId] = (0, react.useState)(null);
22234
- const formatEntryForCopy = (0, react.useCallback)((entry) => {
23858
+ const [copiedAll, setCopiedAll] = (0, react$1.useState)(false);
23859
+ const [copiedRowId, setCopiedRowId] = (0, react$1.useState)(null);
23860
+ const formatEntryForCopy = (0, react$1.useCallback)((entry) => {
22235
23861
  return `${new Date(entry.timestamp).toISOString()} [${entry.capName}] slice=${JSON.stringify(entry.slice)}`;
22236
23862
  }, []);
22237
- const handleCopyAll = (0, react.useCallback)(() => {
23863
+ const handleCopyAll = (0, react$1.useCallback)(() => {
22238
23864
  const lines = allEntries.map(formatEntryForCopy);
22239
23865
  navigator.clipboard.writeText(lines.join("\n")).then(() => {
22240
23866
  setCopiedAll(true);
22241
23867
  setTimeout(() => setCopiedAll(false), 1500);
22242
23868
  });
22243
23869
  }, [allEntries, formatEntryForCopy]);
22244
- const copyOne = (0, react.useCallback)((entry) => {
23870
+ const copyOne = (0, react$1.useCallback)((entry) => {
22245
23871
  navigator.clipboard.writeText(formatEntryForCopy(entry)).then(() => {
22246
23872
  setCopiedRowId(entry.id);
22247
23873
  setTimeout(() => setCopiedRowId((prev) => prev === entry.id ? null : prev), 1200);
22248
23874
  });
22249
23875
  }, [formatEntryForCopy]);
22250
- const handleSelectAllCaps = (0, react.useCallback)(() => {
23876
+ const handleSelectAllCaps = (0, react$1.useCallback)(() => {
22251
23877
  setActiveCaps(new Set(visibleCaps));
22252
23878
  }, [visibleCaps]);
22253
- const handleSelectNoCaps = (0, react.useCallback)(() => {
23879
+ const handleSelectNoCaps = (0, react$1.useCallback)(() => {
22254
23880
  setActiveCaps(/* @__PURE__ */ new Set());
22255
23881
  }, []);
22256
- const filteredPopoverCaps = (0, react.useMemo)(() => {
23882
+ const filteredPopoverCaps = (0, react$1.useMemo)(() => {
22257
23883
  const needle = filterSearch.trim().toLowerCase();
22258
23884
  if (!needle) return visibleCaps;
22259
23885
  return visibleCaps.filter((c) => c.toLowerCase().includes(needle));
@@ -22262,7 +23888,7 @@ function StateValuesStream({ deviceId, defaultCaps, maxHeight = "max-h-96", limi
22262
23888
  const totalActive = activeCaps.size;
22263
23889
  const allSelected = totalActive === 0 || totalActive === totalAvailable;
22264
23890
  const filterLabel = allSelected ? "All" : `${totalActive}/${totalAvailable}`;
22265
- (0, react.useEffect)(() => {
23891
+ (0, react$1.useEffect)(() => {
22266
23892
  if (!filterOpen) return;
22267
23893
  const onDocClick = (e) => {
22268
23894
  const root = filterRootRef.current;
@@ -22622,14 +24248,14 @@ var TABS = [
22622
24248
  }
22623
24249
  ];
22624
24250
  function DeviceActivityPanel({ deviceId, defaultEventCategories, defaultStateCaps, initialTab = "events", className, maxHeight = "max-h-96" }) {
22625
- const [tab, setTab] = (0, react.useState)(initialTab);
24251
+ const [tab, setTab] = (0, react$1.useState)(initialTab);
22626
24252
  const logsBuffer = useLiveBuffer(PANEL_BUFFER_SIZE);
22627
24253
  const eventsBuffer = useLiveBuffer(PANEL_BUFFER_SIZE);
22628
24254
  const stateBuffer = useLiveBuffer(PANEL_BUFFER_SIZE);
22629
24255
  const logsReset = logsBuffer.reset;
22630
24256
  const eventsReset = eventsBuffer.reset;
22631
24257
  const stateReset = stateBuffer.reset;
22632
- (0, react.useEffect)(() => {
24258
+ (0, react$1.useEffect)(() => {
22633
24259
  logsReset();
22634
24260
  eventsReset();
22635
24261
  stateReset();
@@ -22693,9 +24319,9 @@ function DeviceActivityPanel({ deviceId, defaultEventCategories, defaultStateCap
22693
24319
  * for reboot, RefreshCw for restart).
22694
24320
  */
22695
24321
  function ConfirmActionButton({ label, icon: Icon, title = "Confirm action", description, confirmLabel, triggerVariant = "outline", confirmVariant = "danger", size = "sm", disabled, className, action, onSuccess }) {
22696
- const [open, setOpen] = (0, react.useState)(false);
22697
- const [running, setRunning] = (0, react.useState)(false);
22698
- const [error, setError] = (0, react.useState)(null);
24322
+ const [open, setOpen] = (0, react$1.useState)(false);
24323
+ const [running, setRunning] = (0, react$1.useState)(false);
24324
+ const [error, setError] = (0, react$1.useState)(null);
22699
24325
  const handleConfirm = async () => {
22700
24326
  setError(null);
22701
24327
  setRunning(true);
@@ -22774,9 +24400,9 @@ function ConfirmActionButton({ label, icon: Icon, title = "Confirm action", desc
22774
24400
  * release (`startContinuous` + `stopContinuous` on pointer up).
22775
24401
  */
22776
24402
  function DPadButton({ direction, icon: Icon, disabled, className, variant, onMove, onStart, onStop }) {
22777
- const [pressedAt, setPressedAt] = (0, react.useState)(null);
22778
- const [continuous, setContinuous] = (0, react.useState)(false);
22779
- const handlePointerDown = (0, react.useCallback)((e) => {
24403
+ const [pressedAt, setPressedAt] = (0, react$1.useState)(null);
24404
+ const [continuous, setContinuous] = (0, react$1.useState)(false);
24405
+ const handlePointerDown = (0, react$1.useCallback)((e) => {
22780
24406
  if (disabled) return;
22781
24407
  e.currentTarget.setPointerCapture(e.pointerId);
22782
24408
  setPressedAt(Date.now());
@@ -22791,7 +24417,7 @@ function DPadButton({ direction, icon: Icon, disabled, className, variant, onMov
22791
24417
  disabled,
22792
24418
  onStart
22793
24419
  ]);
22794
- const handlePointerUp = (0, react.useCallback)((e) => {
24420
+ const handlePointerUp = (0, react$1.useCallback)((e) => {
22795
24421
  const timerId = Number(e.currentTarget.dataset.timer);
22796
24422
  if (timerId) clearTimeout(timerId);
22797
24423
  e.currentTarget.dataset.timer = "";
@@ -22806,7 +24432,7 @@ function DPadButton({ direction, icon: Icon, disabled, className, variant, onMov
22806
24432
  onStop,
22807
24433
  pressedAt
22808
24434
  ]);
22809
- const handlePointerCancel = (0, react.useCallback)((e) => {
24435
+ const handlePointerCancel = (0, react$1.useCallback)((e) => {
22810
24436
  const timerId = Number(e.currentTarget.dataset.timer);
22811
24437
  if (timerId) clearTimeout(timerId);
22812
24438
  e.currentTarget.dataset.timer = "";
@@ -22829,7 +24455,7 @@ function DPadButton({ direction, icon: Icon, disabled, className, variant, onMov
22829
24455
  }
22830
24456
  function PTZOverlay({ controls, mode = "overlay", showPresets, showZoom = true, showHome = true, className }) {
22831
24457
  const { move, startContinuous, stopContinuous, zoom, goHome, goToPreset, presets, busy, error } = controls;
22832
- const [presetsOpen, setPresetsOpen] = (0, react.useState)(false);
24458
+ const [presetsOpen, setPresetsOpen] = (0, react$1.useState)(false);
22833
24459
  const presetsVisible = (showPresets ?? presets.length > 0) && presets.length > 0;
22834
24460
  const isPanel = mode === "panel";
22835
24461
  const containerClass = isPanel ? "flex flex-col items-stretch gap-2 w-full h-full p-3" : "pointer-events-auto absolute top-3 right-3 z-10 flex flex-col items-end gap-2";
@@ -22982,11 +24608,11 @@ function downloadDataUrl(filename, dataUrl) {
22982
24608
  document.body.removeChild(link);
22983
24609
  }
22984
24610
  function SnapshotButton({ trpc, deviceId, deviceName, size = "sm", className }) {
22985
- const [busy, setBusy] = (0, react.useState)(false);
22986
- const [done, setDone] = (0, react.useState)(false);
22987
- const [error, setError] = (0, react.useState)(null);
24611
+ const [busy, setBusy] = (0, react$1.useState)(false);
24612
+ const [done, setDone] = (0, react$1.useState)(false);
24613
+ const [error, setError] = (0, react$1.useState)(null);
22988
24614
  const safeName = deviceName.replace(/[^a-zA-Z0-9_.-]+/g, "_");
22989
- const fetchSnapshot = (0, react.useCallback)(async (action) => {
24615
+ const fetchSnapshot = (0, react$1.useCallback)(async (action) => {
22990
24616
  setBusy(true);
22991
24617
  setError(null);
22992
24618
  setDone(false);
@@ -23019,8 +24645,8 @@ function SnapshotButton({ trpc, deviceId, deviceName, size = "sm", className })
23019
24645
  safeName
23020
24646
  ]);
23021
24647
  const sizeClasses = size === "md" ? "h-9 px-3 text-sm gap-2" : "h-7 px-2.5 text-[11px] gap-1.5";
23022
- const [pressTimer, setPressTimer] = (0, react.useState)(null);
23023
- const [longPressed, setLongPressed] = (0, react.useState)(false);
24648
+ const [pressTimer, setPressTimer] = (0, react$1.useState)(null);
24649
+ const [longPressed, setLongPressed] = (0, react$1.useState)(false);
23024
24650
  const handlePointerDown = () => {
23025
24651
  setLongPressed(false);
23026
24652
  setPressTimer(setTimeout(() => {
@@ -23127,7 +24753,7 @@ function DoorbellRecentPanel({ history, limit = 5, latestIsFresh, className }) {
23127
24753
  * touch devices, no extra wiring needed.
23128
24754
  */
23129
24755
  function KebabMenu({ items, header, triggerClassName, title = "More actions" }) {
23130
- const [open, setOpen] = (0, react.useState)(false);
24756
+ const [open, setOpen] = (0, react$1.useState)(false);
23131
24757
  const visible = items.filter((i) => !i.hidden);
23132
24758
  if (visible.length === 0) return null;
23133
24759
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Popover, {
@@ -23269,19 +24895,19 @@ function clampedAccessForRow(row, parent) {
23269
24895
  function ScopePicker({ value, onChange, clampToParent, emptyHint }) {
23270
24896
  const { data: addons } = useAddonsList();
23271
24897
  const { data: devices } = useDeviceManagerListAll({});
23272
- const addonChoices = (0, react.useMemo)(() => (addons ?? []).map((a) => ({
24898
+ const addonChoices = (0, react$1.useMemo)(() => (addons ?? []).map((a) => ({
23273
24899
  value: a.manifest.id,
23274
24900
  label: a.manifest.id
23275
24901
  })).sort((a, b) => a.label.localeCompare(b.label)), [addons]);
23276
- const capChoices = (0, react.useMemo)(() => [..._camstack_types.KNOWN_CAP_NAMES].sort().map((c) => ({
24902
+ const capChoices = (0, react$1.useMemo)(() => [..._camstack_types.KNOWN_CAP_NAMES].sort().map((c) => ({
23277
24903
  value: c,
23278
24904
  label: c
23279
24905
  })), []);
23280
- const deviceChoices = (0, react.useMemo)(() => (devices ?? []).map((d) => ({
24906
+ const deviceChoices = (0, react$1.useMemo)(() => (devices ?? []).map((d) => ({
23281
24907
  value: String(d.id),
23282
24908
  label: `${d.name} (#${d.id} · ${d.addonId})`
23283
24909
  })).sort((a, b) => a.label.localeCompare(b.label)), [devices]);
23284
- const parentDeviceClamp = (0, react.useMemo)(() => clampToParent == null ? null : parentDeviceTargets(clampToParent), [clampToParent]);
24910
+ const parentDeviceClamp = (0, react$1.useMemo)(() => clampToParent == null ? null : parentDeviceTargets(clampToParent), [clampToParent]);
23285
24911
  /**
23286
24912
  * Build a fresh scope row when `type` changes. The discriminated union
23287
24913
  * forces us to re-construct the object per variant so the resulting
@@ -23448,8 +25074,8 @@ function ScopePicker({ value, onChange, clampToParent, emptyHint }) {
23448
25074
  });
23449
25075
  }
23450
25076
  function DeviceTargetPicker({ value, choices, clampToParent, onChange }) {
23451
- const [pendingAdd, setPendingAdd] = (0, react.useState)("");
23452
- const visibleChoices = (0, react.useMemo)(() => {
25077
+ const [pendingAdd, setPendingAdd] = (0, react$1.useState)("");
25078
+ const visibleChoices = (0, react$1.useMemo)(() => {
23453
25079
  const filtered = clampToParent == null ? choices : choices.filter((c) => clampToParent.includes(c.value));
23454
25080
  const taken = new Set(value);
23455
25081
  return filtered.filter((c) => !taken.has(c.value));
@@ -23545,11 +25171,11 @@ function validateScopes(scopes) {
23545
25171
  */
23546
25172
  var ZoneEditingContext = createSharedContext("camstack:zone-editing", null);
23547
25173
  function ZoneEditingProvider({ children }) {
23548
- const [editing, setEditingRaw] = (0, react.useState)(false);
23549
- const [drawingKind, setDrawingKindRaw] = (0, react.useState)(null);
23550
- const [selectedZoneId, setSelectedZoneIdRaw] = (0, react.useState)(null);
23551
- const [editingDraft, setEditingDraftRaw] = (0, react.useState)(null);
23552
- const setEditing = (0, react.useCallback)((next) => {
25174
+ const [editing, setEditingRaw] = (0, react$1.useState)(false);
25175
+ const [drawingKind, setDrawingKindRaw] = (0, react$1.useState)(null);
25176
+ const [selectedZoneId, setSelectedZoneIdRaw] = (0, react$1.useState)(null);
25177
+ const [editingDraft, setEditingDraftRaw] = (0, react$1.useState)(null);
25178
+ const setEditing = (0, react$1.useCallback)((next) => {
23553
25179
  setEditingRaw(next);
23554
25180
  if (!next) {
23555
25181
  setDrawingKindRaw(null);
@@ -23557,38 +25183,38 @@ function ZoneEditingProvider({ children }) {
23557
25183
  setEditingDraftRaw(null);
23558
25184
  }
23559
25185
  }, []);
23560
- const setDrawingKind = (0, react.useCallback)((kind) => {
25186
+ const setDrawingKind = (0, react$1.useCallback)((kind) => {
23561
25187
  setDrawingKindRaw(kind);
23562
25188
  }, []);
23563
- const setSelectedZoneId = (0, react.useCallback)((id) => {
25189
+ const setSelectedZoneId = (0, react$1.useCallback)((id) => {
23564
25190
  setSelectedZoneIdRaw(id);
23565
25191
  }, []);
23566
- const startDrawing = (0, react.useCallback)((kind) => {
25192
+ const startDrawing = (0, react$1.useCallback)((kind) => {
23567
25193
  setEditingRaw(true);
23568
25194
  setSelectedZoneIdRaw(null);
23569
25195
  setDrawingKindRaw(kind);
23570
25196
  setEditingDraftRaw(null);
23571
25197
  }, []);
23572
- const exitEditing = (0, react.useCallback)(() => {
25198
+ const exitEditing = (0, react$1.useCallback)(() => {
23573
25199
  setEditingRaw(false);
23574
25200
  setDrawingKindRaw(null);
23575
25201
  setSelectedZoneIdRaw(null);
23576
25202
  setEditingDraftRaw(null);
23577
25203
  }, []);
23578
- const enterDraft = (0, react.useCallback)((draft) => {
25204
+ const enterDraft = (0, react$1.useCallback)((draft) => {
23579
25205
  setSelectedZoneIdRaw(draft.id);
23580
25206
  setEditingDraftRaw(draft);
23581
25207
  }, []);
23582
- const updateDraft = (0, react.useCallback)((patch) => {
25208
+ const updateDraft = (0, react$1.useCallback)((patch) => {
23583
25209
  setEditingDraftRaw((prev) => prev === null ? prev : {
23584
25210
  ...prev,
23585
25211
  ...patch
23586
25212
  });
23587
25213
  }, []);
23588
- const discardDraft = (0, react.useCallback)(() => {
25214
+ const discardDraft = (0, react$1.useCallback)(() => {
23589
25215
  setEditingDraftRaw(null);
23590
25216
  }, []);
23591
- const value = (0, react.useMemo)(() => ({
25217
+ const value = (0, react$1.useMemo)(() => ({
23592
25218
  editing,
23593
25219
  drawingKind,
23594
25220
  selectedZoneId,
@@ -23624,7 +25250,7 @@ function ZoneEditingProvider({ children }) {
23624
25250
  * provider so callers that mount in pages without zones (e.g. a
23625
25251
  * shared hero on a non-camera device) can no-op gracefully. */
23626
25252
  function useZoneEditing() {
23627
- return (0, react.useContext)(ZoneEditingContext);
25253
+ return (0, react$1.useContext)(ZoneEditingContext);
23628
25254
  }
23629
25255
  //#endregion
23630
25256
  //#region src/hooks/use-device-detections.ts
@@ -23652,14 +25278,14 @@ function matchesDevice(source, deviceId) {
23652
25278
  return source?.id === deviceId;
23653
25279
  }
23654
25280
  function useDeviceDetections(trpc, deviceId) {
23655
- const [motion, setMotion] = (0, react.useState)(null);
23656
- const [motionRaw, setMotionRaw] = (0, react.useState)(null);
23657
- const [detection, setDetection] = (0, react.useState)(null);
23658
- const [phase, setPhase] = (0, react.useState)("watching");
23659
- const motionTimer = (0, react.useRef)(void 0);
23660
- const motionRawTimer = (0, react.useRef)(void 0);
23661
- const detectionTimer = (0, react.useRef)(void 0);
23662
- (0, react.useEffect)(() => {
25281
+ const [motion, setMotion] = (0, react$1.useState)(null);
25282
+ const [motionRaw, setMotionRaw] = (0, react$1.useState)(null);
25283
+ const [detection, setDetection] = (0, react$1.useState)(null);
25284
+ const [phase, setPhase] = (0, react$1.useState)("watching");
25285
+ const motionTimer = (0, react$1.useRef)(void 0);
25286
+ const motionRawTimer = (0, react$1.useRef)(void 0);
25287
+ const detectionTimer = (0, react$1.useRef)(void 0);
25288
+ (0, react$1.useEffect)(() => {
23663
25289
  if (deviceId === null) return;
23664
25290
  const sub = safeSubscribe(trpc, "detection.motion-analysis", (event) => {
23665
25291
  const e = event;
@@ -23682,7 +25308,7 @@ function useDeviceDetections(trpc, deviceId) {
23682
25308
  if (motionTimer.current) clearTimeout(motionTimer.current);
23683
25309
  };
23684
25310
  }, [trpc, deviceId]);
23685
- (0, react.useEffect)(() => {
25311
+ (0, react$1.useEffect)(() => {
23686
25312
  if (deviceId === null) return;
23687
25313
  const sub = safeSubscribe(trpc, "detection.motion-zones-raw", (event) => {
23688
25314
  const e = event;
@@ -23706,7 +25332,7 @@ function useDeviceDetections(trpc, deviceId) {
23706
25332
  if (motionRawTimer.current) clearTimeout(motionRawTimer.current);
23707
25333
  };
23708
25334
  }, [trpc, deviceId]);
23709
- (0, react.useEffect)(() => {
25335
+ (0, react$1.useEffect)(() => {
23710
25336
  if (deviceId === null) return;
23711
25337
  const sub = safeSubscribe(trpc, "detection.result", (event) => {
23712
25338
  const e = event;
@@ -23726,7 +25352,7 @@ function useDeviceDetections(trpc, deviceId) {
23726
25352
  if (detectionTimer.current) clearTimeout(detectionTimer.current);
23727
25353
  };
23728
25354
  }, [trpc, deviceId]);
23729
- (0, react.useEffect)(() => {
25355
+ (0, react$1.useEffect)(() => {
23730
25356
  if (deviceId === null) return;
23731
25357
  const sub = safeSubscribe(trpc, "detection.phase-transition", (event) => {
23732
25358
  const e = event;
@@ -23763,8 +25389,8 @@ function useDeviceDetections(trpc, deviceId) {
23763
25389
  * @param pollIntervalMs - how often to refresh profile slots (default: 5000)
23764
25390
  */
23765
25391
  function useDeviceWebrtc(trpc, deviceId, pollIntervalMs = 5e3) {
23766
- const [remoteStreams, setRemoteStreams] = (0, react.useState)([]);
23767
- (0, react.useEffect)(() => {
25392
+ const [remoteStreams, setRemoteStreams] = (0, react$1.useState)([]);
25393
+ (0, react$1.useEffect)(() => {
23768
25394
  if (deviceId === null) return;
23769
25395
  let cancelled = false;
23770
25396
  const fetch = () => {
@@ -23783,8 +25409,8 @@ function useDeviceWebrtc(trpc, deviceId, pollIntervalMs = 5e3) {
23783
25409
  deviceId,
23784
25410
  pollIntervalMs
23785
25411
  ]);
23786
- const [pipelineMetrics, setPipelineMetrics] = (0, react.useState)(null);
23787
- (0, react.useEffect)(() => {
25412
+ const [pipelineMetrics, setPipelineMetrics] = (0, react$1.useState)(null);
25413
+ (0, react$1.useEffect)(() => {
23788
25414
  if (deviceId === null) return;
23789
25415
  let cancelled = false;
23790
25416
  if (trpc.pipelineOrchestrator) trpc.pipelineOrchestrator.getCameraMetrics.query({ deviceId }).then((m) => {
@@ -23811,7 +25437,7 @@ function useDeviceWebrtc(trpc, deviceId, pollIntervalMs = 5e3) {
23811
25437
  droppedFrames: payload.metrics.droppedFrames
23812
25438
  });
23813
25439
  });
23814
- const { streams, hasWebrtc } = (0, react.useMemo)(() => {
25440
+ const { streams, hasWebrtc } = (0, react$1.useMemo)(() => {
23815
25441
  if (deviceId === null || remoteStreams.length === 0) return {
23816
25442
  streams: [],
23817
25443
  hasWebrtc: false
@@ -23833,7 +25459,7 @@ function useDeviceWebrtc(trpc, deviceId, pollIntervalMs = 5e3) {
23833
25459
  streams,
23834
25460
  hasWebrtc,
23835
25461
  pipelineMetrics,
23836
- createSession: (0, react.useCallback)(async (target, hints) => {
25462
+ createSession: (0, react$1.useCallback)(async (target, hints) => {
23837
25463
  if (deviceId === null) throw new Error("No device selected");
23838
25464
  const res = await trpc.webrtcSession.createSession.mutate({
23839
25465
  deviceId,
@@ -23845,7 +25471,7 @@ function useDeviceWebrtc(trpc, deviceId, pollIntervalMs = 5e3) {
23845
25471
  sdpOffer: res.sdpOffer
23846
25472
  };
23847
25473
  }, [trpc, deviceId]),
23848
- sendAnswer: (0, react.useCallback)(async (sessionId, sdpAnswer) => {
25474
+ sendAnswer: (0, react$1.useCallback)(async (sessionId, sdpAnswer) => {
23849
25475
  if (deviceId === null) throw new Error("No device selected");
23850
25476
  await trpc.webrtcSession.handleAnswer.mutate({
23851
25477
  deviceId,
@@ -23853,7 +25479,7 @@ function useDeviceWebrtc(trpc, deviceId, pollIntervalMs = 5e3) {
23853
25479
  sdpAnswer
23854
25480
  });
23855
25481
  }, [trpc, deviceId]),
23856
- closeSession: (0, react.useCallback)(async (sessionId) => {
25482
+ closeSession: (0, react$1.useCallback)(async (sessionId) => {
23857
25483
  if (deviceId === null) return;
23858
25484
  await trpc.webrtcSession.closeSession.mutate({
23859
25485
  deviceId,
@@ -23926,10 +25552,10 @@ function usePTZ(trpc, deviceId, options) {
23926
25552
  const pulseMs = options?.pulseMs ?? 250;
23927
25553
  const enabled = options?.enabled ?? true;
23928
25554
  const ptz = useDeviceProxy(trpc, enabled ? deviceId : null)?.ptz;
23929
- const [presets, setPresets] = (0, react.useState)([]);
23930
- const [busy, setBusy] = (0, react.useState)(false);
23931
- const [error, setError] = (0, react.useState)(null);
23932
- const refreshPresets = (0, react.useCallback)(async () => {
25555
+ const [presets, setPresets] = (0, react$1.useState)([]);
25556
+ const [busy, setBusy] = (0, react$1.useState)(false);
25557
+ const [error, setError] = (0, react$1.useState)(null);
25558
+ const refreshPresets = (0, react$1.useCallback)(async () => {
23933
25559
  if (!enabled || !ptz) return;
23934
25560
  try {
23935
25561
  setPresets(await ptz.getPresets({}));
@@ -23939,10 +25565,10 @@ function usePTZ(trpc, deviceId, options) {
23939
25565
  setError(msg);
23940
25566
  }
23941
25567
  }, [ptz, enabled]);
23942
- (0, react.useEffect)(() => {
25568
+ (0, react$1.useEffect)(() => {
23943
25569
  refreshPresets();
23944
25570
  }, [refreshPresets]);
23945
- const wrap = (0, react.useCallback)(async (fn) => {
25571
+ const wrap = (0, react$1.useCallback)(async (fn) => {
23946
25572
  if (!enabled || !ptz) return void 0;
23947
25573
  setError(null);
23948
25574
  setBusy(true);
@@ -23956,7 +25582,7 @@ function usePTZ(trpc, deviceId, options) {
23956
25582
  }
23957
25583
  }, [enabled, ptz]);
23958
25584
  return {
23959
- move: (0, react.useCallback)(async (direction, speed) => {
25585
+ move: (0, react$1.useCallback)(async (direction, speed) => {
23960
25586
  if (!ptz) return;
23961
25587
  const v = DIRECTION_VECTORS[direction];
23962
25588
  const s = speed ?? defaultSpeed;
@@ -23975,7 +25601,7 @@ function usePTZ(trpc, deviceId, options) {
23975
25601
  pulseMs,
23976
25602
  wrap
23977
25603
  ]),
23978
- startContinuous: (0, react.useCallback)(async (direction, speed) => {
25604
+ startContinuous: (0, react$1.useCallback)(async (direction, speed) => {
23979
25605
  if (!ptz) return;
23980
25606
  const v = DIRECTION_VECTORS[direction];
23981
25607
  const s = speed ?? defaultSpeed;
@@ -23989,11 +25615,11 @@ function usePTZ(trpc, deviceId, options) {
23989
25615
  defaultSpeed,
23990
25616
  wrap
23991
25617
  ]),
23992
- stopContinuous: (0, react.useCallback)(async () => {
25618
+ stopContinuous: (0, react$1.useCallback)(async () => {
23993
25619
  if (!ptz) return;
23994
25620
  await wrap(() => ptz.stop({}));
23995
25621
  }, [ptz, wrap]),
23996
- zoom: (0, react.useCallback)(async (direction, speed) => {
25622
+ zoom: (0, react$1.useCallback)(async (direction, speed) => {
23997
25623
  if (!ptz) return;
23998
25624
  const z = direction === "in" ? 1 : -1;
23999
25625
  const s = speed ?? defaultSpeed;
@@ -24011,11 +25637,11 @@ function usePTZ(trpc, deviceId, options) {
24011
25637
  pulseMs,
24012
25638
  wrap
24013
25639
  ]),
24014
- goHome: (0, react.useCallback)(async () => {
25640
+ goHome: (0, react$1.useCallback)(async () => {
24015
25641
  if (!ptz) return;
24016
25642
  await wrap(() => ptz.goHome({}));
24017
25643
  }, [ptz, wrap]),
24018
- goToPreset: (0, react.useCallback)(async (presetId) => {
25644
+ goToPreset: (0, react$1.useCallback)(async (presetId) => {
24019
25645
  if (!ptz) return;
24020
25646
  await wrap(() => ptz.goToPreset({ presetId }));
24021
25647
  }, [ptz, wrap]),
@@ -24042,8 +25668,8 @@ function useDoorbellEvents(options) {
24042
25668
  const deviceId = options?.deviceId ?? null;
24043
25669
  const historyLimit = options?.historyLimit ?? 20;
24044
25670
  const event = useEventStreamLatest("doorbell.onPressed", deviceId !== null ? (data) => data.deviceId === deviceId : void 0);
24045
- const [history, setHistory] = (0, react.useState)([]);
24046
- (0, react.useEffect)(() => {
25671
+ const [history, setHistory] = (0, react$1.useState)([]);
25672
+ (0, react$1.useEffect)(() => {
24047
25673
  if (!event) return;
24048
25674
  setHistory((prev) => {
24049
25675
  if (prev.length > 0 && prev[0].deviceId === event.deviceId && prev[0].timestamp === event.timestamp) return prev;
@@ -24079,9 +25705,9 @@ function useDoorbellEvents(options) {
24079
25705
  */
24080
25706
  function useDevices(filters) {
24081
25707
  const system = useSystem();
24082
- const filtersKey = (0, react.useMemo)(() => filters ? JSON.stringify(filters) : "", [filters]);
24083
- const [devices, setDevices] = (0, react.useState)(() => system.listDevices(filters));
24084
- (0, react.useEffect)(() => {
25708
+ const filtersKey = (0, react$1.useMemo)(() => filters ? JSON.stringify(filters) : "", [filters]);
25709
+ const [devices, setDevices] = (0, react$1.useState)(() => system.listDevices(filters));
25710
+ (0, react$1.useEffect)(() => {
24085
25711
  const refresh = () => {
24086
25712
  setDevices(system.listDevices(filters));
24087
25713
  };
@@ -24114,8 +25740,8 @@ function useDevices(filters) {
24114
25740
  */
24115
25741
  function useDevice(deviceId) {
24116
25742
  const system = useSystem();
24117
- const [device, setDevice] = (0, react.useState)(() => deviceId === null ? null : system.getDevice(deviceId));
24118
- (0, react.useEffect)(() => {
25743
+ const [device, setDevice] = (0, react$1.useState)(() => deviceId === null ? null : system.getDevice(deviceId));
25744
+ (0, react$1.useEffect)(() => {
24119
25745
  if (deviceId === null) {
24120
25746
  setDevice(null);
24121
25747
  return;
@@ -24213,15 +25839,15 @@ function useSystemMutation(select, opts) {
24213
25839
  function useEventInvalidation(queryKey, categories) {
24214
25840
  const system = useSystem();
24215
25841
  const queryClient = (0, _tanstack_react_query.useQueryClient)();
24216
- const [tick, setTick] = (0, react.useState)(system.connectionVersion);
24217
- (0, react.useEffect)(() => {
25842
+ const [tick, setTick] = (0, react$1.useState)(system.connectionVersion);
25843
+ (0, react$1.useEffect)(() => {
24218
25844
  return system.subscribeConnectionEvents((state, version) => {
24219
25845
  if (state === "connected") setTick(version);
24220
25846
  });
24221
25847
  }, [system]);
24222
25848
  const key = categories.join("|");
24223
25849
  const keyJson = JSON.stringify(queryKey);
24224
- (0, react.useEffect)(() => {
25850
+ (0, react$1.useEffect)(() => {
24225
25851
  const subs = [];
24226
25852
  const refresh = () => {
24227
25853
  const raw = JSON.parse(keyJson);
@@ -24276,6 +25902,7 @@ exports.ConfigFormField = FormField;
24276
25902
  exports.ConfigSchemaField = ConfigSchemaField;
24277
25903
  exports.ConfirmActionButton = ConfirmActionButton;
24278
25904
  exports.ConfirmDialogProvider = ConfirmDialogProvider;
25905
+ exports.CopyButton = CopyButton;
24279
25906
  exports.CustomFieldRenderersProvider = CustomFieldRenderersProvider;
24280
25907
  exports.DEFAULT_COLOR = DEFAULT_COLOR;
24281
25908
  exports.DataTable = DataTable;
@@ -24286,6 +25913,7 @@ exports.DevShell = DevShell;
24286
25913
  exports.DeviceActivityPanel = DeviceActivityPanel;
24287
25914
  exports.DeviceCard = DeviceCard;
24288
25915
  exports.DeviceContextProvider = DeviceContextProvider;
25916
+ exports.DeviceExportPanel = DeviceExportPanel;
24289
25917
  exports.DeviceGrid = DeviceGrid;
24290
25918
  exports.DeviceItem = DeviceItem;
24291
25919
  exports.DeviceList = DeviceList;
@@ -24303,6 +25931,7 @@ exports.DropdownContent = DropdownContent;
24303
25931
  exports.DropdownItem = DropdownItem;
24304
25932
  exports.DropdownTrigger = DropdownTrigger;
24305
25933
  exports.EmptyState = EmptyState;
25934
+ exports.ErrorBox = ErrorBox;
24306
25935
  exports.EventStream = EventStream;
24307
25936
  exports.FilterBar = FilterBar;
24308
25937
  exports.FloatingEventStream = FloatingEventStream;
@@ -24340,6 +25969,7 @@ exports.Popover = Popover;
24340
25969
  exports.PopoverContent = PopoverContent;
24341
25970
  exports.PopoverTrigger = PopoverTrigger;
24342
25971
  exports.ProviderBadge = ProviderBadge;
25972
+ exports.QrCode = QrCode;
24343
25973
  exports.ResponseLog = ResponseLog;
24344
25974
  exports.SECTION_BODY = SECTION_BODY;
24345
25975
  exports.SECTION_CARD = SECTION_CARD;
@@ -24414,12 +26044,15 @@ exports.useAddonsCustom = useAddonsCustom;
24414
26044
  exports.useAddonsForceRefresh = useAddonsForceRefresh;
24415
26045
  exports.useAddonsGetAddonAutoUpdate = useAddonsGetAddonAutoUpdate;
24416
26046
  exports.useAddonsGetAutoUpdateSettings = useAddonsGetAutoUpdateSettings;
26047
+ exports.useAddonsGetLastRestart = useAddonsGetLastRestart;
24417
26048
  exports.useAddonsGetLogs = useAddonsGetLogs;
24418
26049
  exports.useAddonsGetVersions = useAddonsGetVersions;
24419
26050
  exports.useAddonsInstallFromWorkspace = useAddonsInstallFromWorkspace;
24420
26051
  exports.useAddonsInstallPackage = useAddonsInstallPackage;
24421
26052
  exports.useAddonsIsWorkspaceAvailable = useAddonsIsWorkspaceAvailable;
24422
26053
  exports.useAddonsList = useAddonsList;
26054
+ exports.useAddonsListCapabilityProviders = useAddonsListCapabilityProviders;
26055
+ exports.useAddonsListFrameworkPackages = useAddonsListFrameworkPackages;
24423
26056
  exports.useAddonsListPackages = useAddonsListPackages;
24424
26057
  exports.useAddonsListUpdates = useAddonsListUpdates;
24425
26058
  exports.useAddonsListWorkspacePackages = useAddonsListWorkspacePackages;
@@ -24432,7 +26065,9 @@ exports.useAddonsRollbackPackage = useAddonsRollbackPackage;
24432
26065
  exports.useAddonsSearchAvailable = useAddonsSearchAvailable;
24433
26066
  exports.useAddonsSetAddonAutoUpdate = useAddonsSetAddonAutoUpdate;
24434
26067
  exports.useAddonsSetAutoUpdateSettings = useAddonsSetAutoUpdateSettings;
26068
+ exports.useAddonsSetCapabilityProviderEnabled = useAddonsSetCapabilityProviderEnabled;
24435
26069
  exports.useAddonsUninstallPackage = useAddonsUninstallPackage;
26070
+ exports.useAddonsUpdateFrameworkPackage = useAddonsUpdateFrameworkPackage;
24436
26071
  exports.useAddonsUpdatePackage = useAddonsUpdatePackage;
24437
26072
  exports.useAlertsDismiss = useAlertsDismiss;
24438
26073
  exports.useAlertsEmit = useAlertsEmit;
@@ -24464,8 +26099,6 @@ exports.useAudioCodecPushEncodedFrame = useAudioCodecPushEncodedFrame;
24464
26099
  exports.useAudioCodecPushPcm = useAudioCodecPushPcm;
24465
26100
  exports.useAudioMetricsGetCurrentSnapshot = useAudioMetricsGetCurrentSnapshot;
24466
26101
  exports.useAudioMetricsGetHistory = useAudioMetricsGetHistory;
24467
- exports.useAuthenticationListProviders = useAuthenticationListProviders;
24468
- exports.useAuthenticationSetProviderEnabled = useAuthenticationSetProviderEnabled;
24469
26102
  exports.useBackupDelete = useBackupDelete;
24470
26103
  exports.useBackupGetEntries = useBackupGetEntries;
24471
26104
  exports.useBackupList = useBackupList;
@@ -24637,12 +26270,6 @@ exports.useMeshNetworkListPeers = useMeshNetworkListPeers;
24637
26270
  exports.useMeshNetworkLogout = useMeshNetworkLogout;
24638
26271
  exports.useMeshNetworkStartLogin = useMeshNetworkStartLogin;
24639
26272
  exports.useMeshNetworkTestConnection = useMeshNetworkTestConnection;
24640
- exports.useMeshOrchestratorJoinProvider = useMeshOrchestratorJoinProvider;
24641
- exports.useMeshOrchestratorLeaveProvider = useMeshOrchestratorLeaveProvider;
24642
- exports.useMeshOrchestratorListProviderPeers = useMeshOrchestratorListProviderPeers;
24643
- exports.useMeshOrchestratorListProviders = useMeshOrchestratorListProviders;
24644
- exports.useMeshOrchestratorLogoutProvider = useMeshOrchestratorLogoutProvider;
24645
- exports.useMeshOrchestratorStartLoginProvider = useMeshOrchestratorStartLoginProvider;
24646
26273
  exports.useMetricsProviderCollectSnapshot = useMetricsProviderCollectSnapshot;
24647
26274
  exports.useMetricsProviderGetAddonStats = useMetricsProviderGetAddonStats;
24648
26275
  exports.useMetricsProviderGetCached = useMetricsProviderGetCached;
@@ -24673,6 +26300,11 @@ exports.useMqttBrokerStartEmbeddedBroker = useMqttBrokerStartEmbeddedBroker;
24673
26300
  exports.useMqttBrokerStopEmbeddedBroker = useMqttBrokerStopEmbeddedBroker;
24674
26301
  exports.useMqttBrokerTestConnection = useMqttBrokerTestConnection;
24675
26302
  exports.useNativeObjectDetectionGetStatus = useNativeObjectDetectionGetStatus;
26303
+ exports.useNetworkAccessGetEndpoint = useNetworkAccessGetEndpoint;
26304
+ exports.useNetworkAccessGetStatus = useNetworkAccessGetStatus;
26305
+ exports.useNetworkAccessListEndpoints = useNetworkAccessListEndpoints;
26306
+ exports.useNetworkAccessStart = useNetworkAccessStart;
26307
+ exports.useNetworkAccessStop = useNetworkAccessStop;
24676
26308
  exports.useNetworkQualityGetAllStats = useNetworkQualityGetAllStats;
24677
26309
  exports.useNetworkQualityGetDeviceStats = useNetworkQualityGetDeviceStats;
24678
26310
  exports.useNetworkQualityReportClientStats = useNetworkQualityReportClientStats;
@@ -24830,9 +26462,6 @@ exports.useRecordingEngineUpdateRetentionConfig = useRecordingEngineUpdateRetent
24830
26462
  exports.useRecordingGetPlaybackUrl = useRecordingGetPlaybackUrl;
24831
26463
  exports.useRecordingGetSegments = useRecordingGetSegments;
24832
26464
  exports.useRecordingGetThumbnailAt = useRecordingGetThumbnailAt;
24833
- exports.useRemoteAccessListProviders = useRemoteAccessListProviders;
24834
- exports.useRemoteAccessStartProvider = useRemoteAccessStartProvider;
24835
- exports.useRemoteAccessStopProvider = useRemoteAccessStopProvider;
24836
26465
  exports.useSettingsStoreCount = useSettingsStoreCount;
24837
26466
  exports.useSettingsStoreDeclareCollection = useSettingsStoreDeclareCollection;
24838
26467
  exports.useSettingsStoreDelete = useSettingsStoreDelete;
@@ -24910,9 +26539,6 @@ exports.useSystemQuery = useSystemQuery;
24910
26539
  exports.useSystemSetRetentionConfig = useSystemSetRetentionConfig;
24911
26540
  exports.useThemeMode = require_theme_index.useThemeMode$1;
24912
26541
  exports.useToastOnToast = useToastOnToast;
24913
- exports.useTurnOrchestratorGetAllServers = useTurnOrchestratorGetAllServers;
24914
- exports.useTurnOrchestratorListProviders = useTurnOrchestratorListProviders;
24915
- exports.useTurnOrchestratorSetProviderEnabled = useTurnOrchestratorSetProviderEnabled;
24916
26542
  exports.useTurnProviderGetTurnServers = useTurnProviderGetTurnServers;
24917
26543
  exports.useUserManagementConfirmTotp = useUserManagementConfirmTotp;
24918
26544
  exports.useUserManagementCreateApiKey = useUserManagementCreateApiKey;