@camstack/ui-library 1.2.206 → 1.2.208
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/composites/extensions/AssociationSlotCard.d.ts +28 -0
- package/dist/composites/extensions/ExtensionsPanel.d.ts +4 -0
- package/dist/composites/extensions/extensions-view-state.d.ts +89 -0
- package/dist/generated/system-hooks.d.ts +10 -12
- package/dist/index.cjs +596 -21
- package/dist/index.js +593 -17
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -4100,6 +4100,16 @@ var Projector = createLucideIcon("projector", [
|
|
|
4100
4100
|
* This source code is licensed under the ISC license.
|
|
4101
4101
|
* See the LICENSE file in the root directory of this source tree.
|
|
4102
4102
|
*/
|
|
4103
|
+
var Puzzle = createLucideIcon("puzzle", [["path", {
|
|
4104
|
+
d: "M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z",
|
|
4105
|
+
key: "w46dr5"
|
|
4106
|
+
}]]);
|
|
4107
|
+
/**
|
|
4108
|
+
* @license lucide-react v0.576.0 - ISC
|
|
4109
|
+
*
|
|
4110
|
+
* This source code is licensed under the ISC license.
|
|
4111
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
4112
|
+
*/
|
|
4103
4113
|
var QrCode$1 = createLucideIcon("qr-code", [
|
|
4104
4114
|
["rect", {
|
|
4105
4115
|
width: "5",
|
|
@@ -6932,6 +6942,14 @@ var useDeviceExportGetDeviceSettingsContribution = trpc.deviceExport.getDeviceSe
|
|
|
6932
6942
|
var useDeviceExportGetDeviceLiveContribution = trpc.deviceExport.getDeviceLiveContribution.useQuery;
|
|
6933
6943
|
/** Generated alias around `trpc.deviceExport.applyDeviceSettingsPatch.useMutation`. */
|
|
6934
6944
|
var useDeviceExportApplyDeviceSettingsPatch = trpc.deviceExport.applyDeviceSettingsPatch.useMutation;
|
|
6945
|
+
/** Generated alias around `trpc.deviceExtension.listSources.useQuery`. */
|
|
6946
|
+
var useDeviceExtensionListSources = trpc.deviceExtension.listSources.useQuery;
|
|
6947
|
+
/** Generated alias around `trpc.deviceExtension.listSlots.useQuery`. */
|
|
6948
|
+
var useDeviceExtensionListSlots = trpc.deviceExtension.listSlots.useQuery;
|
|
6949
|
+
/** Generated alias around `trpc.deviceExtension.listCandidates.useQuery`. */
|
|
6950
|
+
var useDeviceExtensionListCandidates = trpc.deviceExtension.listCandidates.useQuery;
|
|
6951
|
+
/** Generated alias around `trpc.deviceExtension.setSlot.useMutation`. */
|
|
6952
|
+
var useDeviceExtensionSetSlot = trpc.deviceExtension.setSlot.useMutation;
|
|
6935
6953
|
/** Generated alias around `trpc.deviceManager.allocateDeviceId.useMutation`. */
|
|
6936
6954
|
var useDeviceManagerAllocateDeviceId = trpc.deviceManager.allocateDeviceId.useMutation;
|
|
6937
6955
|
/** Generated alias around `trpc.deviceManager.migrateDevice.useMutation`. */
|
|
@@ -7110,12 +7128,6 @@ var useDeviceManagerTestField = trpc.deviceManager.testField.useMutation;
|
|
|
7110
7128
|
var useDeviceManagerGetDeviceStatusAggregate = trpc.deviceManager.getDeviceStatusAggregate.useQuery;
|
|
7111
7129
|
/** Generated alias around `trpc.deviceManager.getDeviceStatusAggregateBatch.useQuery`. */
|
|
7112
7130
|
var useDeviceManagerGetDeviceStatusAggregateBatch = trpc.deviceManager.getDeviceStatusAggregateBatch.useQuery;
|
|
7113
|
-
/** Generated alias around `trpc.deviceManager.getDeviceSettingsContribution.useQuery`. */
|
|
7114
|
-
var useDeviceManagerGetDeviceSettingsContribution = trpc.deviceManager.getDeviceSettingsContribution.useQuery;
|
|
7115
|
-
/** Generated alias around `trpc.deviceManager.getDeviceLiveContribution.useQuery`. */
|
|
7116
|
-
var useDeviceManagerGetDeviceLiveContribution = trpc.deviceManager.getDeviceLiveContribution.useQuery;
|
|
7117
|
-
/** Generated alias around `trpc.deviceManager.applyDeviceSettingsPatch.useMutation`. */
|
|
7118
|
-
var useDeviceManagerApplyDeviceSettingsPatch = trpc.deviceManager.applyDeviceSettingsPatch.useMutation;
|
|
7119
7131
|
/** Generated alias around `trpc.deviceOps.getStreamSources.useQuery`. */
|
|
7120
7132
|
var useDeviceOpsGetStreamSources = trpc.deviceOps.getStreamSources.useQuery;
|
|
7121
7133
|
/** Generated alias around `trpc.deviceOps.getConfigEntries.useQuery`. */
|
|
@@ -7170,12 +7182,6 @@ var useDeviceStateSetCapSlice = trpc.deviceState.setCapSlice.useMutation;
|
|
|
7170
7182
|
var useDeviceStatusGetStatus = trpc.deviceStatus.getStatus.useQuery;
|
|
7171
7183
|
/** Generated alias around `trpc.doorbell.getStatus.useQuery`. */
|
|
7172
7184
|
var useDoorbellGetStatus = trpc.doorbell.getStatus.useQuery;
|
|
7173
|
-
/** Generated alias around `trpc.doorbell.getDeviceSettingsContribution.useQuery`. */
|
|
7174
|
-
var useDoorbellGetDeviceSettingsContribution = trpc.doorbell.getDeviceSettingsContribution.useQuery;
|
|
7175
|
-
/** Generated alias around `trpc.doorbell.getDeviceLiveContribution.useQuery`. */
|
|
7176
|
-
var useDoorbellGetDeviceLiveContribution = trpc.doorbell.getDeviceLiveContribution.useQuery;
|
|
7177
|
-
/** Generated alias around `trpc.doorbell.applyDeviceSettingsPatch.useMutation`. */
|
|
7178
|
-
var useDoorbellApplyDeviceSettingsPatch = trpc.doorbell.applyDeviceSettingsPatch.useMutation;
|
|
7179
7185
|
/** Generated alias around `trpc.enumSensor.getStatus.useQuery`. */
|
|
7180
7186
|
var useEnumSensorGetStatus = trpc.enumSensor.getStatus.useQuery;
|
|
7181
7187
|
/** Generated alias around `trpc.eventEmitter.getStatus.useQuery`. */
|
|
@@ -7894,6 +7900,8 @@ var usePipelineOrchestratorGetPipelineAssignments = trpc.pipelineOrchestrator.ge
|
|
|
7894
7900
|
var usePipelineOrchestratorGetPipelineAssignment = trpc.pipelineOrchestrator.getPipelineAssignment.useQuery;
|
|
7895
7901
|
/** Generated alias around `trpc.pipelineOrchestrator.getAgentLoad.useQuery`. */
|
|
7896
7902
|
var usePipelineOrchestratorGetAgentLoad = trpc.pipelineOrchestrator.getAgentLoad.useQuery;
|
|
7903
|
+
/** Generated alias around `trpc.pipelineOrchestrator.getClusterModelChoice.useQuery`. */
|
|
7904
|
+
var usePipelineOrchestratorGetClusterModelChoice = trpc.pipelineOrchestrator.getClusterModelChoice.useQuery;
|
|
7897
7905
|
/** Generated alias around `trpc.pipelineOrchestrator.getGlobalMetrics.useQuery`. */
|
|
7898
7906
|
var usePipelineOrchestratorGetGlobalMetrics = trpc.pipelineOrchestrator.getGlobalMetrics.useQuery;
|
|
7899
7907
|
/** Generated alias around `trpc.pipelineOrchestrator.getCameraMetrics.useQuery`. */
|
|
@@ -12307,8 +12315,8 @@ function selectedDeviceOptions(options, selected) {
|
|
|
12307
12315
|
* `device-select-filter.ts`). No server-computed option list is involved —
|
|
12308
12316
|
* the form field carries only the filter. Value(s) are device ids as strings.
|
|
12309
12317
|
*
|
|
12310
|
-
* The multi variant
|
|
12311
|
-
*
|
|
12318
|
+
* The multi variant is a searchable combobox (removable chips + typeahead
|
|
12319
|
+
* dropdown); the single variant is a native
|
|
12312
12320
|
* select. Both are inline in ui-library (like `node-select`) so any host that
|
|
12313
12321
|
* renders the shared form field gets them without extra registration.
|
|
12314
12322
|
*/
|
|
@@ -20896,6 +20904,573 @@ function ClipsSection({ deviceId }) {
|
|
|
20896
20904
|
});
|
|
20897
20905
|
}
|
|
20898
20906
|
//#endregion
|
|
20907
|
+
//#region src/composites/extensions/extensions-view-state.ts
|
|
20908
|
+
/**
|
|
20909
|
+
* What the Extensions section may CLAIM, from what `listSlots` answered
|
|
20910
|
+
* (D648, D315).
|
|
20911
|
+
*
|
|
20912
|
+
* Four states, and the two a boolean would collapse are kept apart on purpose:
|
|
20913
|
+
*
|
|
20914
|
+
* - `pending` — nobody has answered yet. Never "no extensions".
|
|
20915
|
+
* - `unknown` — the query FAILED. It is not an answer, so it is not absence
|
|
20916
|
+
* either; the reason is shown verbatim.
|
|
20917
|
+
* - `none` — the query answered with nothing. The only state that may say
|
|
20918
|
+
* "no extensions".
|
|
20919
|
+
* - `rows` — cards, in the generated table's order, and every owner that
|
|
20920
|
+
* could not answer as its own row with its reason (D554.4). A device whose
|
|
20921
|
+
* ONLY owner failed is `rows` with no slots, not `none`.
|
|
20922
|
+
*
|
|
20923
|
+
* Also here, pure: the editor's draft rules, so the component holds no logic
|
|
20924
|
+
* a spec cannot reach.
|
|
20925
|
+
*/
|
|
20926
|
+
function tableOrder(slot) {
|
|
20927
|
+
return _camstack_types.EXTENSION_SLOT_IDS.indexOf(slot);
|
|
20928
|
+
}
|
|
20929
|
+
function resolveExtensionsView(query) {
|
|
20930
|
+
if (query.status === "pending") return { kind: "pending" };
|
|
20931
|
+
if (query.status === "error") return {
|
|
20932
|
+
kind: "unknown",
|
|
20933
|
+
reason: query.error?.message ?? "the request failed"
|
|
20934
|
+
};
|
|
20935
|
+
const rows = query.data ?? [];
|
|
20936
|
+
if (rows.length === 0) return { kind: "none" };
|
|
20937
|
+
const slots = [];
|
|
20938
|
+
const unreachable = [];
|
|
20939
|
+
for (const row of rows) if (row.state === "ok") slots.push(row);
|
|
20940
|
+
else unreachable.push(row);
|
|
20941
|
+
return {
|
|
20942
|
+
kind: "rows",
|
|
20943
|
+
slots: slots.toSorted((a, b) => tableOrder(a.slot) - tableOrder(b.slot)),
|
|
20944
|
+
unreachable
|
|
20945
|
+
};
|
|
20946
|
+
}
|
|
20947
|
+
/** Add or remove one pick. `one` replaces; `many` toggles. */
|
|
20948
|
+
function togglePick(draft, deviceId, cardinality) {
|
|
20949
|
+
if (draft.includes(deviceId)) return draft.filter((id) => id !== deviceId);
|
|
20950
|
+
return cardinality === "one" ? [deviceId] : [...draft, deviceId];
|
|
20951
|
+
}
|
|
20952
|
+
/** Suggested candidates the operator has NOT picked — shown to confirm, never saved on their own (D356). */
|
|
20953
|
+
function pendingSuggestions(candidates, draft) {
|
|
20954
|
+
return candidates.filter((c) => c.suggested && !draft.includes(c.deviceId));
|
|
20955
|
+
}
|
|
20956
|
+
/** Candidates matching a free-text search, not already picked. */
|
|
20957
|
+
function searchCandidates(candidates, draft, query) {
|
|
20958
|
+
const needle = query.trim().toLowerCase();
|
|
20959
|
+
if (needle.length === 0) return [];
|
|
20960
|
+
return candidates.filter((c) => !draft.includes(c.deviceId) && [
|
|
20961
|
+
c.name,
|
|
20962
|
+
c.location ?? "",
|
|
20963
|
+
c.parentName ?? "",
|
|
20964
|
+
c.type
|
|
20965
|
+
].some((v) => v.toLowerCase().includes(needle)));
|
|
20966
|
+
}
|
|
20967
|
+
/** Whether the draft differs from what the owner's store holds. */
|
|
20968
|
+
function isDirty(saved, draft) {
|
|
20969
|
+
return saved.length !== draft.length || saved.some((id, i) => draft[i] !== id);
|
|
20970
|
+
}
|
|
20971
|
+
/**
|
|
20972
|
+
* The tracked-event opt-in a slot's value carries, or `undefined` when it
|
|
20973
|
+
* carries none — every slot but `linked-devices`, and a `linked-devices` row
|
|
20974
|
+
* from a server older than D655. `undefined` is "this owner offers no
|
|
20975
|
+
* opt-in", never "nothing is opted in": the card then shows no toggle rather
|
|
20976
|
+
* than a row of unticked ones it could not save.
|
|
20977
|
+
*/
|
|
20978
|
+
function trackedOptInOf(value) {
|
|
20979
|
+
return value.slot === "linked-devices" ? value.trackedDeviceIds : void 0;
|
|
20980
|
+
}
|
|
20981
|
+
/** Flip one device's tracked-event opt-in. */
|
|
20982
|
+
function toggleTracked(tracked, deviceId) {
|
|
20983
|
+
return tracked.includes(deviceId) ? tracked.filter((id) => id !== deviceId) : [...tracked, deviceId];
|
|
20984
|
+
}
|
|
20985
|
+
/** Whether two opt-ins differ as SETS — the order carries no meaning. */
|
|
20986
|
+
function isTrackedDirty(saved, draft) {
|
|
20987
|
+
return saved.length !== draft.length || saved.some((id) => !draft.includes(id));
|
|
20988
|
+
}
|
|
20989
|
+
/**
|
|
20990
|
+
* One toggle per device the camera links — the old section's set (D655):
|
|
20991
|
+
* the valid picks, then what the owner links by structure (tree children, a
|
|
20992
|
+
* picked container's child — never the container itself, D356), then every
|
|
20993
|
+
* opted-in device that is linked no more, so a stored opt-in is always
|
|
20994
|
+
* visible and can always be removed.
|
|
20995
|
+
*/
|
|
20996
|
+
function trackedOptions(input) {
|
|
20997
|
+
const out = [];
|
|
20998
|
+
const seen = /* @__PURE__ */ new Set();
|
|
20999
|
+
const add = (deviceId, origin) => {
|
|
21000
|
+
if (seen.has(deviceId)) return;
|
|
21001
|
+
seen.add(deviceId);
|
|
21002
|
+
out.push({
|
|
21003
|
+
deviceId,
|
|
21004
|
+
origin
|
|
21005
|
+
});
|
|
21006
|
+
};
|
|
21007
|
+
for (const id of input.picks) if (!input.invalidPicks.includes(id)) add(id, "pick");
|
|
21008
|
+
for (const id of input.implied) add(id, "implied");
|
|
21009
|
+
for (const id of input.tracked) add(id, "not-linked");
|
|
21010
|
+
return out;
|
|
21011
|
+
}
|
|
21012
|
+
/**
|
|
21013
|
+
* The opt-in after one device is removed from the draft picks: its toggle
|
|
21014
|
+
* goes with it, unless the camera still links it by structure.
|
|
21015
|
+
*/
|
|
21016
|
+
function untrackUnpicked(tracked, deviceId, implied) {
|
|
21017
|
+
return implied.includes(deviceId) ? tracked : tracked.filter((id) => id !== deviceId);
|
|
21018
|
+
}
|
|
21019
|
+
/**
|
|
21020
|
+
* The value a Save sends. The opt-in travels only when the owner offered one,
|
|
21021
|
+
* and then WHOLE: it replaces the stored one, and the owner accepts any id it
|
|
21022
|
+
* already stored, so what was read can be sent back unchanged (D655).
|
|
21023
|
+
*/
|
|
21024
|
+
function slotWriteValue(saved, deviceIds, tracked) {
|
|
21025
|
+
if (saved.slot === "linked-devices" && tracked !== void 0) return {
|
|
21026
|
+
slot: "linked-devices",
|
|
21027
|
+
deviceIds: [...deviceIds],
|
|
21028
|
+
trackedDeviceIds: [...tracked]
|
|
21029
|
+
};
|
|
21030
|
+
return {
|
|
21031
|
+
slot: saved.slot,
|
|
21032
|
+
deviceIds: [...deviceIds]
|
|
21033
|
+
};
|
|
21034
|
+
}
|
|
21035
|
+
//#endregion
|
|
21036
|
+
//#region src/composites/extensions/AssociationSlotCard.tsx
|
|
21037
|
+
/**
|
|
21038
|
+
* One ASSOCIATION slot (D648): the devices a host lists, edited as a device
|
|
21039
|
+
* multiselect.
|
|
21040
|
+
*
|
|
21041
|
+
* - The saved value is the owner's store, read by `listSlots`. The draft is
|
|
21042
|
+
* local until Save, and Save is `setSlot` — the owner validates and writes
|
|
21043
|
+
* through its existing path, so a refusal comes back BY NAME and is shown.
|
|
21044
|
+
* - Candidates (`listCandidates`) are fetched only while editing. Suggestions
|
|
21045
|
+
* are chips the operator must click to add; nothing is picked on its own
|
|
21046
|
+
* (D356).
|
|
21047
|
+
* - Every saved source shows its health; a missing or unavailable one is
|
|
21048
|
+
* shown with its reason and never silently dropped from the draft.
|
|
21049
|
+
* - A gate owned by ANOTHER authority (the doorbell wrapper's binding) is
|
|
21050
|
+
* shown read-only, naming that authority (D62).
|
|
21051
|
+
* - A slot whose value carries a tracked-event opt-in (`linked-devices`,
|
|
21052
|
+
* D655) gets one toggle per LINKED device — the picks, what the owner links
|
|
21053
|
+
* by structure (`impliedSources`: tree children, never a container, D356)
|
|
21054
|
+
* and any stored opt-in no longer linked, so each can be removed — saved
|
|
21055
|
+
* with the picks, whole.
|
|
21056
|
+
*/
|
|
21057
|
+
var HEALTH_LABEL = {
|
|
21058
|
+
ok: "OK",
|
|
21059
|
+
missing: "Missing",
|
|
21060
|
+
foreign: "Other owner",
|
|
21061
|
+
unavailable: "Not a valid source"
|
|
21062
|
+
};
|
|
21063
|
+
var HEALTH_VARIANT = {
|
|
21064
|
+
ok: "success",
|
|
21065
|
+
missing: "danger",
|
|
21066
|
+
foreign: "warning",
|
|
21067
|
+
unavailable: "warning"
|
|
21068
|
+
};
|
|
21069
|
+
/** The saved sources, each with its health — a bad one is shown, never hidden. */
|
|
21070
|
+
function SlotSourceList({ sources, tracked }) {
|
|
21071
|
+
if (sources.length === 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
21072
|
+
className: "text-[11px] text-foreground-subtle italic",
|
|
21073
|
+
children: "No devices picked."
|
|
21074
|
+
});
|
|
21075
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
21076
|
+
className: "flex flex-col gap-1",
|
|
21077
|
+
children: sources.map((s) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
21078
|
+
className: "flex flex-wrap items-center gap-2 text-[11px]",
|
|
21079
|
+
children: [
|
|
21080
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
21081
|
+
className: "text-foreground",
|
|
21082
|
+
children: s.name ?? `Device ${s.deviceId}`
|
|
21083
|
+
}),
|
|
21084
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Badge, {
|
|
21085
|
+
variant: HEALTH_VARIANT[s.health],
|
|
21086
|
+
children: HEALTH_LABEL[s.health]
|
|
21087
|
+
}),
|
|
21088
|
+
tracked?.includes(s.deviceId) === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Badge, {
|
|
21089
|
+
variant: "info",
|
|
21090
|
+
children: "Tracked events"
|
|
21091
|
+
}),
|
|
21092
|
+
s.detail !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
21093
|
+
className: "text-[10px] text-foreground-subtle",
|
|
21094
|
+
children: s.detail
|
|
21095
|
+
})
|
|
21096
|
+
]
|
|
21097
|
+
}, s.deviceId))
|
|
21098
|
+
});
|
|
21099
|
+
}
|
|
21100
|
+
function ActivationLine({ row }) {
|
|
21101
|
+
const activation = row.activation;
|
|
21102
|
+
if (activation === null) return null;
|
|
21103
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
21104
|
+
className: "flex flex-wrap items-center gap-2 text-[10px] text-foreground-subtle",
|
|
21105
|
+
children: [
|
|
21106
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Badge, {
|
|
21107
|
+
variant: activation.state === "active" ? "success" : activation.state === "inactive" ? "warning" : "default",
|
|
21108
|
+
children: activation.state === "active" ? "Active" : activation.state === "inactive" ? "Inactive" : "Unknown"
|
|
21109
|
+
}),
|
|
21110
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: ["set by ", activation.authority] }),
|
|
21111
|
+
activation.detail !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: activation.detail })
|
|
21112
|
+
]
|
|
21113
|
+
});
|
|
21114
|
+
}
|
|
21115
|
+
/**
|
|
21116
|
+
* What the owner links by structure — tree children, a picked container's
|
|
21117
|
+
* child (D356). Shown, never editable as a pick: removing one is not the
|
|
21118
|
+
* editor's to do.
|
|
21119
|
+
*/
|
|
21120
|
+
function ImpliedSourceList({ sources, tracked }) {
|
|
21121
|
+
if (sources.length === 0) return null;
|
|
21122
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
21123
|
+
className: "flex flex-col gap-1",
|
|
21124
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
21125
|
+
className: "text-[10px] text-foreground-subtle",
|
|
21126
|
+
children: "Always linked (device tree):"
|
|
21127
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
21128
|
+
"aria-label": "Always linked",
|
|
21129
|
+
className: "flex flex-col gap-1",
|
|
21130
|
+
children: sources.map((s) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
21131
|
+
className: "flex flex-wrap items-center gap-2 text-[11px]",
|
|
21132
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
21133
|
+
className: "text-foreground",
|
|
21134
|
+
children: s.name ?? `Device ${s.deviceId}`
|
|
21135
|
+
}), tracked?.includes(s.deviceId) === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Badge, {
|
|
21136
|
+
variant: "info",
|
|
21137
|
+
children: "Tracked events"
|
|
21138
|
+
})]
|
|
21139
|
+
}, s.deviceId))
|
|
21140
|
+
})]
|
|
21141
|
+
});
|
|
21142
|
+
}
|
|
21143
|
+
var ORIGIN_NOTE = {
|
|
21144
|
+
pick: null,
|
|
21145
|
+
implied: "always linked",
|
|
21146
|
+
"not-linked": "not linked any more — untick to remove"
|
|
21147
|
+
};
|
|
21148
|
+
/** One opt-in toggle per linked device: does it produce tracked events here? */
|
|
21149
|
+
function TrackedToggles({ options, tracked, nameOf, onToggle }) {
|
|
21150
|
+
if (options.length === 0) return null;
|
|
21151
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("fieldset", {
|
|
21152
|
+
className: "flex flex-col gap-1",
|
|
21153
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("legend", {
|
|
21154
|
+
className: "text-[10px] text-foreground-subtle",
|
|
21155
|
+
children: "Produce tracked events on this camera (opt-in):"
|
|
21156
|
+
}), options.map(({ deviceId: id, origin }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
21157
|
+
className: "flex items-center gap-2 text-[11px] text-foreground",
|
|
21158
|
+
children: [
|
|
21159
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
21160
|
+
type: "checkbox",
|
|
21161
|
+
"aria-label": `Tracked events from ${nameOf(id)}`,
|
|
21162
|
+
checked: tracked.includes(id),
|
|
21163
|
+
onChange: () => onToggle(id)
|
|
21164
|
+
}),
|
|
21165
|
+
nameOf(id),
|
|
21166
|
+
ORIGIN_NOTE[origin] !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
21167
|
+
className: "text-[10px] text-foreground-subtle",
|
|
21168
|
+
children: ["· ", ORIGIN_NOTE[origin]]
|
|
21169
|
+
})
|
|
21170
|
+
]
|
|
21171
|
+
}, id))]
|
|
21172
|
+
});
|
|
21173
|
+
}
|
|
21174
|
+
function AssociationSlotCard({ deviceId, row, onSaved }) {
|
|
21175
|
+
const descriptor = _camstack_types.EXTENSION_SLOTS[row.slot].descriptor;
|
|
21176
|
+
const saved = row.value.deviceIds;
|
|
21177
|
+
const savedTracked = trackedOptInOf(row.value);
|
|
21178
|
+
const implied = row.impliedSources ?? [];
|
|
21179
|
+
const impliedIds = implied.map((s) => s.deviceId);
|
|
21180
|
+
const invalidPicks = row.sources.filter((s) => s.health === "unavailable").map((s) => s.deviceId);
|
|
21181
|
+
const [editing, setEditing] = (0, react$1.useState)(false);
|
|
21182
|
+
const [draft, setDraft] = (0, react$1.useState)(saved);
|
|
21183
|
+
const [draftTracked, setDraftTracked] = (0, react$1.useState)(savedTracked ?? []);
|
|
21184
|
+
const [search, setSearch] = (0, react$1.useState)("");
|
|
21185
|
+
const [refusal, setRefusal] = (0, react$1.useState)(null);
|
|
21186
|
+
const candidatesQuery = useDeviceExtensionListCandidates({
|
|
21187
|
+
deviceId,
|
|
21188
|
+
slotRef: row.slotRef
|
|
21189
|
+
}, { enabled: editing });
|
|
21190
|
+
const setSlot = useDeviceExtensionSetSlot();
|
|
21191
|
+
const candidates = candidatesQuery.data?.candidates ?? [];
|
|
21192
|
+
const nameOf = (id) => candidates.find((c) => c.deviceId === id)?.name ?? row.sources.find((s) => s.deviceId === id)?.name ?? implied.find((s) => s.deviceId === id)?.name ?? `Device ${id}`;
|
|
21193
|
+
const removePick = (id) => {
|
|
21194
|
+
setDraft(togglePick(draft, id, descriptor.cardinality));
|
|
21195
|
+
setDraftTracked(untrackUnpicked(draftTracked, id, impliedIds));
|
|
21196
|
+
};
|
|
21197
|
+
const startEditing = () => {
|
|
21198
|
+
setDraft(saved);
|
|
21199
|
+
setDraftTracked(savedTracked ?? []);
|
|
21200
|
+
setRefusal(null);
|
|
21201
|
+
setEditing(true);
|
|
21202
|
+
};
|
|
21203
|
+
const save = async () => {
|
|
21204
|
+
setRefusal(null);
|
|
21205
|
+
try {
|
|
21206
|
+
await setSlot.mutateAsync({
|
|
21207
|
+
deviceId,
|
|
21208
|
+
slotRef: row.slotRef,
|
|
21209
|
+
value: slotWriteValue(row.value, draft, savedTracked === void 0 ? void 0 : draftTracked)
|
|
21210
|
+
});
|
|
21211
|
+
setEditing(false);
|
|
21212
|
+
onSaved();
|
|
21213
|
+
} catch (err) {
|
|
21214
|
+
setRefusal(err instanceof Error ? err.message : String(err));
|
|
21215
|
+
}
|
|
21216
|
+
};
|
|
21217
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
21218
|
+
role: "group",
|
|
21219
|
+
"aria-label": descriptor.label,
|
|
21220
|
+
className: "flex flex-col gap-2 rounded-md border border-border/40 bg-surface-elevated/30 p-3",
|
|
21221
|
+
children: [
|
|
21222
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
21223
|
+
className: "flex items-start justify-between gap-2",
|
|
21224
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
21225
|
+
className: "flex flex-col gap-0.5",
|
|
21226
|
+
children: [
|
|
21227
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
21228
|
+
className: "text-xs font-semibold text-foreground",
|
|
21229
|
+
children: descriptor.label
|
|
21230
|
+
}),
|
|
21231
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
21232
|
+
className: "text-[10px] text-foreground-subtle",
|
|
21233
|
+
children: descriptor.description
|
|
21234
|
+
}),
|
|
21235
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
21236
|
+
className: "text-[10px] text-foreground-subtle",
|
|
21237
|
+
children: ["Stored in ", row.authority]
|
|
21238
|
+
})
|
|
21239
|
+
]
|
|
21240
|
+
}), !editing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
|
|
21241
|
+
variant: "outline",
|
|
21242
|
+
size: "sm",
|
|
21243
|
+
onClick: startEditing,
|
|
21244
|
+
children: "Edit"
|
|
21245
|
+
})]
|
|
21246
|
+
}),
|
|
21247
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ActivationLine, { row }),
|
|
21248
|
+
!editing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SlotSourceList, {
|
|
21249
|
+
sources: row.sources,
|
|
21250
|
+
tracked: savedTracked
|
|
21251
|
+
}),
|
|
21252
|
+
!editing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ImpliedSourceList, {
|
|
21253
|
+
sources: implied,
|
|
21254
|
+
tracked: savedTracked
|
|
21255
|
+
}),
|
|
21256
|
+
editing && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
21257
|
+
className: "flex flex-col gap-2",
|
|
21258
|
+
children: [
|
|
21259
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
21260
|
+
"aria-label": "Picked devices",
|
|
21261
|
+
className: "flex flex-wrap gap-1.5",
|
|
21262
|
+
children: draft.map((id) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
21263
|
+
type: "button",
|
|
21264
|
+
"aria-label": `Remove ${nameOf(id)}`,
|
|
21265
|
+
onClick: () => removePick(id),
|
|
21266
|
+
className: "inline-flex items-center gap-1 rounded-full bg-primary/15 px-2 py-0.5 text-[11px] text-foreground",
|
|
21267
|
+
children: [nameOf(id), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(X, { className: "h-3 w-3" })]
|
|
21268
|
+
}) }, id))
|
|
21269
|
+
}),
|
|
21270
|
+
candidatesQuery.status === "pending" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
21271
|
+
role: "status",
|
|
21272
|
+
className: "text-[10px] text-foreground-subtle",
|
|
21273
|
+
children: "Loading candidates…"
|
|
21274
|
+
}),
|
|
21275
|
+
candidatesQuery.status === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
21276
|
+
role: "alert",
|
|
21277
|
+
className: "text-[10px] text-danger",
|
|
21278
|
+
children: ["Candidates could not be read: ", candidatesQuery.error.message]
|
|
21279
|
+
}),
|
|
21280
|
+
pendingSuggestions(candidates, draft).length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
21281
|
+
className: "flex flex-col gap-1",
|
|
21282
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
21283
|
+
className: "text-[10px] text-foreground-subtle",
|
|
21284
|
+
children: "Suggested — added only if you click them:"
|
|
21285
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
21286
|
+
"aria-label": "Suggestions",
|
|
21287
|
+
className: "flex flex-wrap gap-1.5",
|
|
21288
|
+
children: pendingSuggestions(candidates, draft).map((c) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
21289
|
+
type: "button",
|
|
21290
|
+
"aria-label": `Add ${c.name}`,
|
|
21291
|
+
onClick: () => setDraft(togglePick(draft, c.deviceId, descriptor.cardinality)),
|
|
21292
|
+
className: "inline-flex items-center gap-1 rounded-full border border-dashed border-border px-2 py-0.5 text-[11px] text-foreground-muted",
|
|
21293
|
+
children: [
|
|
21294
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Plus, { className: "h-3 w-3" }),
|
|
21295
|
+
c.name,
|
|
21296
|
+
c.reason !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
21297
|
+
className: "text-foreground-subtle",
|
|
21298
|
+
children: ["· ", c.reason]
|
|
21299
|
+
})
|
|
21300
|
+
]
|
|
21301
|
+
}) }, c.deviceId))
|
|
21302
|
+
})]
|
|
21303
|
+
}),
|
|
21304
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
21305
|
+
type: "search",
|
|
21306
|
+
"aria-label": "Search devices",
|
|
21307
|
+
value: search,
|
|
21308
|
+
onChange: (e) => setSearch(e.target.value),
|
|
21309
|
+
placeholder: "Search devices by name, location or type",
|
|
21310
|
+
className: "w-full rounded-md border border-border bg-background px-2.5 py-1.5 text-xs text-foreground outline-none focus:border-primary"
|
|
21311
|
+
}),
|
|
21312
|
+
searchCandidates(candidates, draft, search).length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
21313
|
+
"aria-label": "Search results",
|
|
21314
|
+
className: "flex max-h-40 flex-col gap-0.5 overflow-y-auto",
|
|
21315
|
+
children: searchCandidates(candidates, draft, search).map((c) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
21316
|
+
type: "button",
|
|
21317
|
+
onClick: () => {
|
|
21318
|
+
setDraft(togglePick(draft, c.deviceId, descriptor.cardinality));
|
|
21319
|
+
setSearch("");
|
|
21320
|
+
},
|
|
21321
|
+
className: "w-full rounded px-2 py-1 text-left text-[11px] text-foreground hover:bg-surface-hover",
|
|
21322
|
+
children: [
|
|
21323
|
+
c.name,
|
|
21324
|
+
c.parentName !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
21325
|
+
className: "text-foreground-subtle",
|
|
21326
|
+
children: [" in ", c.parentName]
|
|
21327
|
+
}),
|
|
21328
|
+
c.location !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
21329
|
+
className: "text-foreground-subtle",
|
|
21330
|
+
children: [" · ", c.location]
|
|
21331
|
+
})
|
|
21332
|
+
]
|
|
21333
|
+
}) }, c.deviceId))
|
|
21334
|
+
}),
|
|
21335
|
+
savedTracked !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TrackedToggles, {
|
|
21336
|
+
options: trackedOptions({
|
|
21337
|
+
picks: draft,
|
|
21338
|
+
invalidPicks,
|
|
21339
|
+
implied: impliedIds,
|
|
21340
|
+
tracked: draftTracked
|
|
21341
|
+
}),
|
|
21342
|
+
tracked: draftTracked,
|
|
21343
|
+
nameOf,
|
|
21344
|
+
onToggle: (id) => setDraftTracked(toggleTracked(draftTracked, id))
|
|
21345
|
+
}),
|
|
21346
|
+
refusal !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
21347
|
+
role: "alert",
|
|
21348
|
+
className: "text-[11px] text-danger break-words",
|
|
21349
|
+
children: ["Not saved: ", refusal]
|
|
21350
|
+
}),
|
|
21351
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
21352
|
+
className: "flex justify-end gap-2",
|
|
21353
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
|
|
21354
|
+
variant: "ghost",
|
|
21355
|
+
size: "sm",
|
|
21356
|
+
onClick: () => setEditing(false),
|
|
21357
|
+
children: "Cancel"
|
|
21358
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
|
|
21359
|
+
size: "sm",
|
|
21360
|
+
disabled: !(isDirty(saved, draft) || savedTracked !== void 0 && isTrackedDirty(savedTracked, draftTracked)) || setSlot.isPending,
|
|
21361
|
+
onClick: () => void save(),
|
|
21362
|
+
children: "Save"
|
|
21363
|
+
})]
|
|
21364
|
+
})
|
|
21365
|
+
]
|
|
21366
|
+
})
|
|
21367
|
+
]
|
|
21368
|
+
});
|
|
21369
|
+
}
|
|
21370
|
+
//#endregion
|
|
21371
|
+
//#region src/composites/extensions/ExtensionsPanel.tsx
|
|
21372
|
+
/**
|
|
21373
|
+
* `host/extensions-panel` — what a device is extended with by OTHER devices,
|
|
21374
|
+
* in one place (D648).
|
|
21375
|
+
*
|
|
21376
|
+
* Mounted by the framework: `device-extension.cap.ts` declares
|
|
21377
|
+
* `deviceConfig.ui = { kind:'widget', widgetId:'host/extensions-panel',
|
|
21378
|
+
* tab:'general', order:72 }` and `deriveDeviceConfigContribution` emits the
|
|
21379
|
+
* section (D14). The panel STORES NOTHING: every card is one row of
|
|
21380
|
+
* `device-extension.listSlots`, read by the slot's owner from the store it
|
|
21381
|
+
* already has, and every save is `setSlot`, written by that owner through its
|
|
21382
|
+
* existing path. It is the only editor of what it shows: the hand-written
|
|
21383
|
+
* "Linked devices" and "Virtual doorbell" sections it replaced were retired
|
|
21384
|
+
* once the live read matched them on every measured camera (D655).
|
|
21385
|
+
*
|
|
21386
|
+
* It renders ASSOCIATION cards only (a device multiselect). A `graft`
|
|
21387
|
+
* slot (slice 2) gets a read-only card here until its editor exists.
|
|
21388
|
+
*
|
|
21389
|
+
* Absence is claimed only from an answer (D315): pending, failed and empty
|
|
21390
|
+
* are three different sentences, and an owner that could not answer is shown
|
|
21391
|
+
* with its reason, verbatim — never dropped.
|
|
21392
|
+
*/
|
|
21393
|
+
function ExtensionsPanel({ deviceId }) {
|
|
21394
|
+
const query = useDeviceExtensionListSlots({ deviceId });
|
|
21395
|
+
const view = resolveExtensionsView({
|
|
21396
|
+
status: query.status,
|
|
21397
|
+
data: query.data,
|
|
21398
|
+
error: query.error
|
|
21399
|
+
});
|
|
21400
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WidgetPanel, {
|
|
21401
|
+
title: "Extensions",
|
|
21402
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Puzzle, { className: "h-3.5 w-3.5 text-foreground-subtle" }),
|
|
21403
|
+
bodyClassName: "p-3",
|
|
21404
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
21405
|
+
"aria-label": "Extensions",
|
|
21406
|
+
className: "flex flex-col gap-3",
|
|
21407
|
+
children: [
|
|
21408
|
+
view.kind === "pending" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
21409
|
+
role: "status",
|
|
21410
|
+
className: "text-[11px] text-foreground-subtle",
|
|
21411
|
+
children: "Loading this device’s extensions…"
|
|
21412
|
+
}),
|
|
21413
|
+
view.kind === "unknown" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorBox, {
|
|
21414
|
+
title: "Extensions could not be read",
|
|
21415
|
+
message: `Nothing is known about this device’s extensions yet: ${view.reason}`,
|
|
21416
|
+
onRetry: () => void query.refetch()
|
|
21417
|
+
}),
|
|
21418
|
+
view.kind === "none" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
21419
|
+
role: "status",
|
|
21420
|
+
className: "text-[11px] text-foreground-subtle italic",
|
|
21421
|
+
children: "No extensions are offered on this device."
|
|
21422
|
+
}),
|
|
21423
|
+
view.kind === "rows" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [view.slots.map((row) => _camstack_types.EXTENSION_SLOTS[row.slot].descriptor.shape === "association" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AssociationSlotCard, {
|
|
21424
|
+
deviceId,
|
|
21425
|
+
row,
|
|
21426
|
+
onSaved: () => void query.refetch()
|
|
21427
|
+
}, row.slotRef) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
21428
|
+
className: "rounded-md border border-border/40 p-3",
|
|
21429
|
+
children: [
|
|
21430
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
21431
|
+
className: "text-xs font-semibold text-foreground",
|
|
21432
|
+
children: _camstack_types.EXTENSION_SLOTS[row.slot].descriptor.label
|
|
21433
|
+
}),
|
|
21434
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
21435
|
+
className: "text-[10px] text-foreground-subtle",
|
|
21436
|
+
children: [
|
|
21437
|
+
row.enabled === false ? "Off" : "On",
|
|
21438
|
+
" — ",
|
|
21439
|
+
row.authority,
|
|
21440
|
+
". Editing it needs a newer admin."
|
|
21441
|
+
]
|
|
21442
|
+
}),
|
|
21443
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SlotSourceList, { sources: row.sources })
|
|
21444
|
+
]
|
|
21445
|
+
}, row.slotRef)), view.unreachable.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
21446
|
+
role: "alert",
|
|
21447
|
+
className: "flex flex-col gap-1 rounded-md border border-warning/40 bg-warning/5 p-3",
|
|
21448
|
+
children: [
|
|
21449
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
21450
|
+
className: "flex items-center gap-2",
|
|
21451
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Badge, {
|
|
21452
|
+
variant: "warning",
|
|
21453
|
+
children: "Unreachable"
|
|
21454
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
21455
|
+
className: "text-xs font-semibold text-foreground",
|
|
21456
|
+
children: row.addonId
|
|
21457
|
+
})]
|
|
21458
|
+
}),
|
|
21459
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
21460
|
+
className: "text-[11px] text-foreground-muted break-words",
|
|
21461
|
+
children: row.reason
|
|
21462
|
+
}),
|
|
21463
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
21464
|
+
className: "text-[10px] text-foreground-subtle",
|
|
21465
|
+
children: "The extensions this component owns are unknown until it answers."
|
|
21466
|
+
})
|
|
21467
|
+
]
|
|
21468
|
+
}, `unreachable:${row.addonId}`))] })
|
|
21469
|
+
]
|
|
21470
|
+
})
|
|
21471
|
+
});
|
|
21472
|
+
}
|
|
21473
|
+
//#endregion
|
|
20899
21474
|
//#region src/hooks/use-navigation.ts
|
|
20900
21475
|
/**
|
|
20901
21476
|
* useNavigation — drive a `navigation` robot camera from the UI.
|
|
@@ -23831,7 +24406,8 @@ var HOST_WIDGETS = {
|
|
|
23831
24406
|
"host/ptz-autotrack": AutotrackSection,
|
|
23832
24407
|
"host/recording-panel": RecordingPanel,
|
|
23833
24408
|
"host/camera-grid-layout": CameraGridLayoutEditor,
|
|
23834
|
-
"host/clips-browser": ClipsSection
|
|
24409
|
+
"host/clips-browser": ClipsSection,
|
|
24410
|
+
"host/extensions-panel": ExtensionsPanel
|
|
23835
24411
|
};
|
|
23836
24412
|
//#endregion
|
|
23837
24413
|
//#region src/composites/widget-slot.tsx
|
|
@@ -56622,6 +57198,10 @@ exports.useDeviceExportGetStatus = useDeviceExportGetStatus;
|
|
|
56622
57198
|
exports.useDeviceExportListExposedDevices = useDeviceExportListExposedDevices;
|
|
56623
57199
|
exports.useDeviceExportListSupportedDeviceKinds = useDeviceExportListSupportedDeviceKinds;
|
|
56624
57200
|
exports.useDeviceExportUnexposeDevice = useDeviceExportUnexposeDevice;
|
|
57201
|
+
exports.useDeviceExtensionListCandidates = useDeviceExtensionListCandidates;
|
|
57202
|
+
exports.useDeviceExtensionListSlots = useDeviceExtensionListSlots;
|
|
57203
|
+
exports.useDeviceExtensionListSources = useDeviceExtensionListSources;
|
|
57204
|
+
exports.useDeviceExtensionSetSlot = useDeviceExtensionSetSlot;
|
|
56625
57205
|
exports.useDeviceId = useDeviceId;
|
|
56626
57206
|
exports.useDeviceListPageSize = useDeviceListPageSize;
|
|
56627
57207
|
exports.useDeviceManagerAddLocation = useDeviceManagerAddLocation;
|
|
@@ -56636,7 +57216,6 @@ exports.useDeviceManagerAdoptionRelease = useDeviceManagerAdoptionRelease;
|
|
|
56636
57216
|
exports.useDeviceManagerAdoptionResync = useDeviceManagerAdoptionResync;
|
|
56637
57217
|
exports.useDeviceManagerAdoptionStartJob = useDeviceManagerAdoptionStartJob;
|
|
56638
57218
|
exports.useDeviceManagerAllocateDeviceId = useDeviceManagerAllocateDeviceId;
|
|
56639
|
-
exports.useDeviceManagerApplyDeviceSettingsPatch = useDeviceManagerApplyDeviceSettingsPatch;
|
|
56640
57219
|
exports.useDeviceManagerApplyInitialMeta = useDeviceManagerApplyInitialMeta;
|
|
56641
57220
|
exports.useDeviceManagerCreateDevice = useDeviceManagerCreateDevice;
|
|
56642
57221
|
exports.useDeviceManagerDisable = useDeviceManagerDisable;
|
|
@@ -56654,10 +57233,8 @@ exports.useDeviceManagerGetConfigSchema = useDeviceManagerGetConfigSchema;
|
|
|
56654
57233
|
exports.useDeviceManagerGetCreationSchema = useDeviceManagerGetCreationSchema;
|
|
56655
57234
|
exports.useDeviceManagerGetDevice = useDeviceManagerGetDevice;
|
|
56656
57235
|
exports.useDeviceManagerGetDeviceAggregate = useDeviceManagerGetDeviceAggregate;
|
|
56657
|
-
exports.useDeviceManagerGetDeviceLiveContribution = useDeviceManagerGetDeviceLiveContribution;
|
|
56658
57236
|
exports.useDeviceManagerGetDeviceLiveInfoAggregate = useDeviceManagerGetDeviceLiveInfoAggregate;
|
|
56659
57237
|
exports.useDeviceManagerGetDeviceSettingsAggregate = useDeviceManagerGetDeviceSettingsAggregate;
|
|
56660
|
-
exports.useDeviceManagerGetDeviceSettingsContribution = useDeviceManagerGetDeviceSettingsContribution;
|
|
56661
57238
|
exports.useDeviceManagerGetDeviceStatusAggregate = useDeviceManagerGetDeviceStatusAggregate;
|
|
56662
57239
|
exports.useDeviceManagerGetDeviceStatusAggregateBatch = useDeviceManagerGetDeviceStatusAggregateBatch;
|
|
56663
57240
|
exports.useDeviceManagerGetLinkedDevices = useDeviceManagerGetLinkedDevices;
|
|
@@ -56753,10 +57330,7 @@ exports.useDeviceStateSlice$1 = useDeviceStateSlice;
|
|
|
56753
57330
|
exports.useDeviceStatusGetStatus = useDeviceStatusGetStatus;
|
|
56754
57331
|
exports.useDeviceWebrtc = useDeviceWebrtc;
|
|
56755
57332
|
exports.useDevices = useDevices;
|
|
56756
|
-
exports.useDoorbellApplyDeviceSettingsPatch = useDoorbellApplyDeviceSettingsPatch;
|
|
56757
57333
|
exports.useDoorbellEvents = useDoorbellEvents;
|
|
56758
|
-
exports.useDoorbellGetDeviceLiveContribution = useDoorbellGetDeviceLiveContribution;
|
|
56759
|
-
exports.useDoorbellGetDeviceSettingsContribution = useDoorbellGetDeviceSettingsContribution;
|
|
56760
57334
|
exports.useDoorbellGetStatus = useDoorbellGetStatus;
|
|
56761
57335
|
exports.useEnumSensorGetStatus = useEnumSensorGetStatus;
|
|
56762
57336
|
exports.useEventEmitterGetStatus = useEventEmitterGetStatus;
|
|
@@ -57135,6 +57709,7 @@ exports.usePipelineOrchestratorGetCameraStatuses = usePipelineOrchestratorGetCam
|
|
|
57135
57709
|
exports.usePipelineOrchestratorGetCameraStepOverrides = usePipelineOrchestratorGetCameraStepOverrides;
|
|
57136
57710
|
exports.usePipelineOrchestratorGetCameraSwitches = usePipelineOrchestratorGetCameraSwitches;
|
|
57137
57711
|
exports.usePipelineOrchestratorGetCapabilityBindings = usePipelineOrchestratorGetCapabilityBindings;
|
|
57712
|
+
exports.usePipelineOrchestratorGetClusterModelChoice = usePipelineOrchestratorGetClusterModelChoice;
|
|
57138
57713
|
exports.usePipelineOrchestratorGetDeviceLiveContribution = usePipelineOrchestratorGetDeviceLiveContribution;
|
|
57139
57714
|
exports.usePipelineOrchestratorGetDeviceSettingsContribution = usePipelineOrchestratorGetDeviceSettingsContribution;
|
|
57140
57715
|
exports.usePipelineOrchestratorGetGlobalMetrics = usePipelineOrchestratorGetGlobalMetrics;
|