@camstack/ui-library 1.2.217 → 1.2.219
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.
|
@@ -40,6 +40,10 @@ export interface EventStreamProps {
|
|
|
40
40
|
readonly onClose?: () => void;
|
|
41
41
|
readonly className?: string;
|
|
42
42
|
}
|
|
43
|
+
/** Categories visible in the events tab by default. The "All" badge
|
|
44
|
+
* reflects this set, not the raw enum. */
|
|
45
|
+
export declare const DEFAULT_EVENT_CATEGORIES: readonly string[];
|
|
46
|
+
export declare function summarizeEvent(category: string, data: Record<string, unknown>): string | null;
|
|
43
47
|
export declare function EventStream({ agentId, addonId, deviceId, defaultCategories, categories: legacyCategories, category: propsCategory, maxHeight, limit, showCategoryFilter, showFilters: _showFilters, liveBuffer: externalBuffer, onClose, className, }: EventStreamProps): import("react").JSX.Element;
|
|
44
48
|
export interface FloatingEventStreamProps extends EventStreamProps {
|
|
45
49
|
readonly position?: 'bottom' | 'overlay';
|
|
@@ -22,14 +22,31 @@ export interface ExtensionsUnknownView {
|
|
|
22
22
|
export interface ExtensionsNoneView {
|
|
23
23
|
readonly kind: 'none';
|
|
24
24
|
}
|
|
25
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* A row of a slot this build does NOT declare — an older or newer server than
|
|
27
|
+
* this admin UI (a rollback after slice 6 still answers `doorbell-source`).
|
|
28
|
+
* It cannot be a card (no descriptor), so it is said by name instead: never
|
|
29
|
+
* dropped, never crashing the panel (D315, task 17 re-review R1).
|
|
30
|
+
*/
|
|
31
|
+
export interface ExtensionsUnknownSlotRow {
|
|
32
|
+
readonly slot: string;
|
|
33
|
+
readonly slotRef: string;
|
|
34
|
+
}
|
|
35
|
+
/** Cards in table order, every slot this build does not know, and every owner that could not answer. */
|
|
26
36
|
export interface ExtensionsRowsView {
|
|
27
37
|
readonly kind: 'rows';
|
|
28
38
|
readonly slots: readonly ExtensionSlotState[];
|
|
39
|
+
readonly unknownSlots: readonly ExtensionsUnknownSlotRow[];
|
|
29
40
|
readonly unreachable: readonly ExtensionSlotUnreachable[];
|
|
30
41
|
}
|
|
31
42
|
export type ExtensionsView = ExtensionsPendingView | ExtensionsUnknownView | ExtensionsNoneView | ExtensionsRowsView;
|
|
32
|
-
|
|
43
|
+
/** The order cards are shown in: the generated slot table's. */
|
|
44
|
+
export type ExtensionSlotTableOrder = readonly string[];
|
|
45
|
+
/**
|
|
46
|
+
* `order` is the generated table (`EXTENSION_SLOT_IDS`); a parameter only so a
|
|
47
|
+
* spec can pin the comparator while the table holds a single slot.
|
|
48
|
+
*/
|
|
49
|
+
export declare function resolveExtensionsView(query: ExtensionsQueryView, order?: ExtensionSlotTableOrder): ExtensionsView;
|
|
33
50
|
/** Add or remove one pick. `one` replaces; `many` toggles. */
|
|
34
51
|
export declare function togglePick(draft: readonly number[], deviceId: number, cardinality: ExtensionSlotCardinality): readonly number[];
|
|
35
52
|
/** Suggested candidates the operator has NOT picked — shown to confirm, never saved on their own (D356). */
|
package/dist/index.cjs
CHANGED
|
@@ -20975,10 +20975,21 @@ function ClipsSection({ deviceId }) {
|
|
|
20975
20975
|
* Also here, pure: the editor's draft rules, so the component holds no logic
|
|
20976
20976
|
* a spec cannot reach.
|
|
20977
20977
|
*/
|
|
20978
|
-
|
|
20979
|
-
|
|
20978
|
+
/**
|
|
20979
|
+
* Whether the WIRE row's slot is one this build declares. The tRPC client does
|
|
20980
|
+
* not validate output, so a row's `slot` can be any string at runtime even
|
|
20981
|
+
* though its type says otherwise; the comparison runs on the string.
|
|
20982
|
+
*/
|
|
20983
|
+
function isDeclaredSlotRow(row, order) {
|
|
20984
|
+
const slot = row.slot;
|
|
20985
|
+
return order.some((id) => id === slot);
|
|
20980
20986
|
}
|
|
20981
|
-
|
|
20987
|
+
/**
|
|
20988
|
+
* `order` is the generated table (`EXTENSION_SLOT_IDS`); a parameter only so a
|
|
20989
|
+
* spec can pin the comparator while the table holds a single slot.
|
|
20990
|
+
*/
|
|
20991
|
+
function resolveExtensionsView(query, order = _camstack_types.EXTENSION_SLOT_IDS) {
|
|
20992
|
+
const tableOrder = (slot) => order.indexOf(slot);
|
|
20982
20993
|
if (query.status === "pending") return { kind: "pending" };
|
|
20983
20994
|
if (query.status === "error") return {
|
|
20984
20995
|
kind: "unknown",
|
|
@@ -20987,12 +20998,18 @@ function resolveExtensionsView(query) {
|
|
|
20987
20998
|
const rows = query.data ?? [];
|
|
20988
20999
|
if (rows.length === 0) return { kind: "none" };
|
|
20989
21000
|
const slots = [];
|
|
21001
|
+
const unknownSlots = [];
|
|
20990
21002
|
const unreachable = [];
|
|
20991
|
-
for (const row of rows) if (row.state
|
|
20992
|
-
else
|
|
21003
|
+
for (const row of rows) if (row.state !== "ok") unreachable.push(row);
|
|
21004
|
+
else if (isDeclaredSlotRow(row, order)) slots.push(row);
|
|
21005
|
+
else unknownSlots.push({
|
|
21006
|
+
slot: row.slot,
|
|
21007
|
+
slotRef: row.slotRef
|
|
21008
|
+
});
|
|
20993
21009
|
return {
|
|
20994
21010
|
kind: "rows",
|
|
20995
21011
|
slots: slots.toSorted((a, b) => tableOrder(a.slot) - tableOrder(b.slot)),
|
|
21012
|
+
unknownSlots,
|
|
20996
21013
|
unreachable
|
|
20997
21014
|
};
|
|
20998
21015
|
}
|
|
@@ -21098,8 +21115,8 @@ function slotWriteValue(saved, deviceIds, tracked) {
|
|
|
21098
21115
|
* (D356).
|
|
21099
21116
|
* - Every saved source shows its health; a missing or unavailable one is
|
|
21100
21117
|
* shown with its reason and never silently dropped from the draft.
|
|
21101
|
-
* - A gate owned by ANOTHER authority (
|
|
21102
|
-
* shown read-only, naming that authority (D62).
|
|
21118
|
+
* - A gate owned by ANOTHER authority (e.g. a wrapper's binding; no slot
|
|
21119
|
+
* reports one today) is shown read-only, naming that authority (D62).
|
|
21103
21120
|
* - A slot whose value carries a tracked-event opt-in (`linked-devices`,
|
|
21104
21121
|
* D655) gets one toggle per LINKED device — the picks, what the owner links
|
|
21105
21122
|
* by structure (`impliedSources`: tree children, never a container, D356)
|
|
@@ -21428,9 +21445,11 @@ function ExtensionsPanel({ deviceId, slots, title, readOnly = false }) {
|
|
|
21428
21445
|
data: query.data,
|
|
21429
21446
|
error: query.error
|
|
21430
21447
|
});
|
|
21431
|
-
const
|
|
21448
|
+
const named = (slot) => slots === void 0 || slots.some((id) => id === slot);
|
|
21449
|
+
const shown = view.kind !== "rows" ? [] : view.slots.filter((row) => named(row.slot));
|
|
21450
|
+
const unknownShown = view.kind !== "rows" ? [] : view.unknownSlots.filter((row) => named(row.slot));
|
|
21432
21451
|
const panelTitle = title ?? "Extensions";
|
|
21433
|
-
const filteredToNothing = view.kind === "rows" && slots !== void 0 && shown.length === 0 && view.unreachable.length === 0;
|
|
21452
|
+
const filteredToNothing = view.kind === "rows" && slots !== void 0 && shown.length === 0 && unknownShown.length === 0 && view.unreachable.length === 0;
|
|
21434
21453
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WidgetPanel, {
|
|
21435
21454
|
title: panelTitle,
|
|
21436
21455
|
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Puzzle, { className: "h-3.5 w-3.5 text-foreground-subtle" }),
|
|
@@ -21466,6 +21485,30 @@ function ExtensionsPanel({ deviceId, slots, title, readOnly = false }) {
|
|
|
21466
21485
|
onSaved: () => void query.refetch(),
|
|
21467
21486
|
readOnly
|
|
21468
21487
|
}, row.slotRef)),
|
|
21488
|
+
unknownShown.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
21489
|
+
role: "alert",
|
|
21490
|
+
className: "flex flex-col gap-1 rounded-md border border-warning/40 bg-warning/5 p-3",
|
|
21491
|
+
children: [
|
|
21492
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
21493
|
+
className: "flex items-center gap-2",
|
|
21494
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Badge, {
|
|
21495
|
+
variant: "warning",
|
|
21496
|
+
children: "Unknown slot"
|
|
21497
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
21498
|
+
className: "text-xs font-semibold text-foreground",
|
|
21499
|
+
children: row.slot
|
|
21500
|
+
})]
|
|
21501
|
+
}),
|
|
21502
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
21503
|
+
className: "text-[11px] text-foreground-muted break-words",
|
|
21504
|
+
children: row.slotRef
|
|
21505
|
+
}),
|
|
21506
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
21507
|
+
className: "text-[10px] text-foreground-subtle",
|
|
21508
|
+
children: "The admin UI and the server disagree: the server offers a slot this admin UI does not know. Update the admin UI, or the server."
|
|
21509
|
+
})
|
|
21510
|
+
]
|
|
21511
|
+
}, `unknown:${row.slotRef}`)),
|
|
21469
21512
|
view.unreachable.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
21470
21513
|
role: "alert",
|
|
21471
21514
|
className: "flex flex-col gap-1 rounded-md border border-warning/40 bg-warning/5 p-3",
|
|
@@ -36026,7 +36069,8 @@ var LIVE_NOISE_CATEGORIES = Object.freeze([
|
|
|
36026
36069
|
_camstack_types.EventCategory.PipelineAudioInferenceResult,
|
|
36027
36070
|
_camstack_types.EventCategory.PlatformProbePhase,
|
|
36028
36071
|
_camstack_types.EventCategory.BenchmarkProgress,
|
|
36029
|
-
_camstack_types.EventCategory.ModelDownloadProgress
|
|
36072
|
+
_camstack_types.EventCategory.ModelDownloadProgress,
|
|
36073
|
+
_camstack_types.EventCategory.ProviderMotion
|
|
36030
36074
|
]);
|
|
36031
36075
|
var LIVE_NOISE_SET = new Set(LIVE_NOISE_CATEGORIES);
|
|
36032
36076
|
/** Categories visible in the events tab by default. The "All" badge
|
|
@@ -36074,7 +36118,7 @@ function summarizeEvent(category, data) {
|
|
|
36074
36118
|
if (typeof score === "number") parts.push(`${Math.round(score * 100)}%`);
|
|
36075
36119
|
return parts.length > 0 ? parts.join(" — ") : null;
|
|
36076
36120
|
}
|
|
36077
|
-
if (category === _camstack_types.EventCategory.ProviderMotion) return data["
|
|
36121
|
+
if (category === _camstack_types.EventCategory.ProviderMotion) return data["detected"] === true ? "motion start" : "motion stop";
|
|
36078
36122
|
if (category === _camstack_types.EventCategory.DeviceStateChanged) {
|
|
36079
36123
|
const slice = data["slice"];
|
|
36080
36124
|
if (slice && typeof slice === "object") {
|
|
@@ -36879,7 +36923,7 @@ function runtimeStateKeys(capName) {
|
|
|
36879
36923
|
}
|
|
36880
36924
|
/**
|
|
36881
36925
|
* Cold placeholder slice for a bound cap that declares `runtimeState` but
|
|
36882
|
-
* has never written it (e.g. a
|
|
36926
|
+
* has never written it (e.g. a doorbell that has never rung).
|
|
36883
36927
|
* Every declared field is seeded `null` so the tree surfaces the cap's
|
|
36884
36928
|
* presence and reads as "never" instead of the cap being OMITTED entirely.
|
|
36885
36929
|
* Returns `null` when the cap has no runtime-state schema (nothing to seed).
|
package/dist/index.js
CHANGED
|
@@ -20951,10 +20951,21 @@ function ClipsSection({ deviceId }) {
|
|
|
20951
20951
|
* Also here, pure: the editor's draft rules, so the component holds no logic
|
|
20952
20952
|
* a spec cannot reach.
|
|
20953
20953
|
*/
|
|
20954
|
-
|
|
20955
|
-
|
|
20954
|
+
/**
|
|
20955
|
+
* Whether the WIRE row's slot is one this build declares. The tRPC client does
|
|
20956
|
+
* not validate output, so a row's `slot` can be any string at runtime even
|
|
20957
|
+
* though its type says otherwise; the comparison runs on the string.
|
|
20958
|
+
*/
|
|
20959
|
+
function isDeclaredSlotRow(row, order) {
|
|
20960
|
+
const slot = row.slot;
|
|
20961
|
+
return order.some((id) => id === slot);
|
|
20956
20962
|
}
|
|
20957
|
-
|
|
20963
|
+
/**
|
|
20964
|
+
* `order` is the generated table (`EXTENSION_SLOT_IDS`); a parameter only so a
|
|
20965
|
+
* spec can pin the comparator while the table holds a single slot.
|
|
20966
|
+
*/
|
|
20967
|
+
function resolveExtensionsView(query, order = EXTENSION_SLOT_IDS) {
|
|
20968
|
+
const tableOrder = (slot) => order.indexOf(slot);
|
|
20958
20969
|
if (query.status === "pending") return { kind: "pending" };
|
|
20959
20970
|
if (query.status === "error") return {
|
|
20960
20971
|
kind: "unknown",
|
|
@@ -20963,12 +20974,18 @@ function resolveExtensionsView(query) {
|
|
|
20963
20974
|
const rows = query.data ?? [];
|
|
20964
20975
|
if (rows.length === 0) return { kind: "none" };
|
|
20965
20976
|
const slots = [];
|
|
20977
|
+
const unknownSlots = [];
|
|
20966
20978
|
const unreachable = [];
|
|
20967
|
-
for (const row of rows) if (row.state
|
|
20968
|
-
else
|
|
20979
|
+
for (const row of rows) if (row.state !== "ok") unreachable.push(row);
|
|
20980
|
+
else if (isDeclaredSlotRow(row, order)) slots.push(row);
|
|
20981
|
+
else unknownSlots.push({
|
|
20982
|
+
slot: row.slot,
|
|
20983
|
+
slotRef: row.slotRef
|
|
20984
|
+
});
|
|
20969
20985
|
return {
|
|
20970
20986
|
kind: "rows",
|
|
20971
20987
|
slots: slots.toSorted((a, b) => tableOrder(a.slot) - tableOrder(b.slot)),
|
|
20988
|
+
unknownSlots,
|
|
20972
20989
|
unreachable
|
|
20973
20990
|
};
|
|
20974
20991
|
}
|
|
@@ -21074,8 +21091,8 @@ function slotWriteValue(saved, deviceIds, tracked) {
|
|
|
21074
21091
|
* (D356).
|
|
21075
21092
|
* - Every saved source shows its health; a missing or unavailable one is
|
|
21076
21093
|
* shown with its reason and never silently dropped from the draft.
|
|
21077
|
-
* - A gate owned by ANOTHER authority (
|
|
21078
|
-
* shown read-only, naming that authority (D62).
|
|
21094
|
+
* - A gate owned by ANOTHER authority (e.g. a wrapper's binding; no slot
|
|
21095
|
+
* reports one today) is shown read-only, naming that authority (D62).
|
|
21079
21096
|
* - A slot whose value carries a tracked-event opt-in (`linked-devices`,
|
|
21080
21097
|
* D655) gets one toggle per LINKED device — the picks, what the owner links
|
|
21081
21098
|
* by structure (`impliedSources`: tree children, never a container, D356)
|
|
@@ -21404,9 +21421,11 @@ function ExtensionsPanel({ deviceId, slots, title, readOnly = false }) {
|
|
|
21404
21421
|
data: query.data,
|
|
21405
21422
|
error: query.error
|
|
21406
21423
|
});
|
|
21407
|
-
const
|
|
21424
|
+
const named = (slot) => slots === void 0 || slots.some((id) => id === slot);
|
|
21425
|
+
const shown = view.kind !== "rows" ? [] : view.slots.filter((row) => named(row.slot));
|
|
21426
|
+
const unknownShown = view.kind !== "rows" ? [] : view.unknownSlots.filter((row) => named(row.slot));
|
|
21408
21427
|
const panelTitle = title ?? "Extensions";
|
|
21409
|
-
const filteredToNothing = view.kind === "rows" && slots !== void 0 && shown.length === 0 && view.unreachable.length === 0;
|
|
21428
|
+
const filteredToNothing = view.kind === "rows" && slots !== void 0 && shown.length === 0 && unknownShown.length === 0 && view.unreachable.length === 0;
|
|
21410
21429
|
return /* @__PURE__ */ jsx(WidgetPanel, {
|
|
21411
21430
|
title: panelTitle,
|
|
21412
21431
|
icon: /* @__PURE__ */ jsx(Puzzle, { className: "h-3.5 w-3.5 text-foreground-subtle" }),
|
|
@@ -21442,6 +21461,30 @@ function ExtensionsPanel({ deviceId, slots, title, readOnly = false }) {
|
|
|
21442
21461
|
onSaved: () => void query.refetch(),
|
|
21443
21462
|
readOnly
|
|
21444
21463
|
}, row.slotRef)),
|
|
21464
|
+
unknownShown.map((row) => /* @__PURE__ */ jsxs("div", {
|
|
21465
|
+
role: "alert",
|
|
21466
|
+
className: "flex flex-col gap-1 rounded-md border border-warning/40 bg-warning/5 p-3",
|
|
21467
|
+
children: [
|
|
21468
|
+
/* @__PURE__ */ jsxs("div", {
|
|
21469
|
+
className: "flex items-center gap-2",
|
|
21470
|
+
children: [/* @__PURE__ */ jsx(Badge, {
|
|
21471
|
+
variant: "warning",
|
|
21472
|
+
children: "Unknown slot"
|
|
21473
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
21474
|
+
className: "text-xs font-semibold text-foreground",
|
|
21475
|
+
children: row.slot
|
|
21476
|
+
})]
|
|
21477
|
+
}),
|
|
21478
|
+
/* @__PURE__ */ jsx("p", {
|
|
21479
|
+
className: "text-[11px] text-foreground-muted break-words",
|
|
21480
|
+
children: row.slotRef
|
|
21481
|
+
}),
|
|
21482
|
+
/* @__PURE__ */ jsx("p", {
|
|
21483
|
+
className: "text-[10px] text-foreground-subtle",
|
|
21484
|
+
children: "The admin UI and the server disagree: the server offers a slot this admin UI does not know. Update the admin UI, or the server."
|
|
21485
|
+
})
|
|
21486
|
+
]
|
|
21487
|
+
}, `unknown:${row.slotRef}`)),
|
|
21445
21488
|
view.unreachable.map((row) => /* @__PURE__ */ jsxs("div", {
|
|
21446
21489
|
role: "alert",
|
|
21447
21490
|
className: "flex flex-col gap-1 rounded-md border border-warning/40 bg-warning/5 p-3",
|
|
@@ -36002,7 +36045,8 @@ var LIVE_NOISE_CATEGORIES = Object.freeze([
|
|
|
36002
36045
|
EventCategory.PipelineAudioInferenceResult,
|
|
36003
36046
|
EventCategory.PlatformProbePhase,
|
|
36004
36047
|
EventCategory.BenchmarkProgress,
|
|
36005
|
-
EventCategory.ModelDownloadProgress
|
|
36048
|
+
EventCategory.ModelDownloadProgress,
|
|
36049
|
+
EventCategory.ProviderMotion
|
|
36006
36050
|
]);
|
|
36007
36051
|
var LIVE_NOISE_SET = new Set(LIVE_NOISE_CATEGORIES);
|
|
36008
36052
|
/** Categories visible in the events tab by default. The "All" badge
|
|
@@ -36050,7 +36094,7 @@ function summarizeEvent(category, data) {
|
|
|
36050
36094
|
if (typeof score === "number") parts.push(`${Math.round(score * 100)}%`);
|
|
36051
36095
|
return parts.length > 0 ? parts.join(" — ") : null;
|
|
36052
36096
|
}
|
|
36053
|
-
if (category === EventCategory.ProviderMotion) return data["
|
|
36097
|
+
if (category === EventCategory.ProviderMotion) return data["detected"] === true ? "motion start" : "motion stop";
|
|
36054
36098
|
if (category === EventCategory.DeviceStateChanged) {
|
|
36055
36099
|
const slice = data["slice"];
|
|
36056
36100
|
if (slice && typeof slice === "object") {
|
|
@@ -36855,7 +36899,7 @@ function runtimeStateKeys(capName) {
|
|
|
36855
36899
|
}
|
|
36856
36900
|
/**
|
|
36857
36901
|
* Cold placeholder slice for a bound cap that declares `runtimeState` but
|
|
36858
|
-
* has never written it (e.g. a
|
|
36902
|
+
* has never written it (e.g. a doorbell that has never rung).
|
|
36859
36903
|
* Every declared field is seeded `null` so the tree surfaces the cap's
|
|
36860
36904
|
* presence and reads as "never" instead of the cap being OMITTED entirely.
|
|
36861
36905
|
* Returns `null` when the cap has no runtime-state schema (nothing to seed).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/ui-library",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.219",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
],
|
|
31
31
|
"scripts": {
|
|
32
32
|
"build": "vite build",
|
|
33
|
-
"typecheck": "tsc --noEmit",
|
|
33
|
+
"typecheck": "tsc --noEmit -p tsconfig.spec.json",
|
|
34
34
|
"test": "vitest run",
|
|
35
35
|
"publish:npm": "npm publish --access public"
|
|
36
36
|
},
|