@camstack/ui-library 1.2.290 → 1.2.292

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.
Files changed (89) hide show
  1. package/dist/{MaskShapeCanvas-DI4BY7W2.js → MaskShapeCanvas-C9cJlxvG.js} +3 -1
  2. package/dist/{MaskShapeCanvas-BByN3jvt.cjs → MaskShapeCanvas-NCNwu9_5.cjs} +3 -1
  3. package/dist/{MotionZonesSettings-CiYjd-yl.js → MotionZonesSettings-Bv8XzCa3.js} +45 -48
  4. package/dist/{MotionZonesSettings-BK9R9NIr.cjs → MotionZonesSettings-CPRH536-.cjs} +44 -47
  5. package/dist/{PrivacyMaskSettings-DuXUCUev.cjs → PrivacyMaskSettings-BUWvVF_n.cjs} +33 -42
  6. package/dist/{PrivacyMaskSettings-BmRdUrPp.js → PrivacyMaskSettings-BlkbESYj.js} +34 -43
  7. package/dist/{SceneMonitorEditor-COgAjtq5.cjs → SceneMonitorEditor-D_jkzQ2o.cjs} +189 -86
  8. package/dist/{SceneMonitorEditor-J4Ix_0tu.js → SceneMonitorEditor-i3-nXAEU.js} +190 -87
  9. package/dist/composites/addon-global-settings-form.d.ts +0 -12
  10. package/dist/composites/cap-settings/AutotrackSection.d.ts +0 -16
  11. package/dist/composites/cap-settings/CameraGridLayoutEditor.d.ts +0 -21
  12. package/dist/composites/cap-settings/ConsumablesPanel.d.ts +0 -18
  13. package/dist/composites/cap-settings/MaskShapeCanvas.d.ts +0 -102
  14. package/dist/composites/cap-settings/MotionZonesSettings.d.ts +0 -38
  15. package/dist/composites/cap-settings/SceneReferenceGallery.d.ts +0 -38
  16. package/dist/composites/cap-settings/scene-monitor-copy.d.ts +12 -6
  17. package/dist/composites/clips/clip-source-state.d.ts +3 -2
  18. package/dist/composites/clips/clip-thumbnail-fetch.d.ts +2 -1
  19. package/dist/composites/clips/clip-tile-media.d.ts +3 -2
  20. package/dist/composites/clips/clip-view-state.d.ts +2 -1
  21. package/dist/composites/confirm-dialog.d.ts +0 -62
  22. package/dist/composites/data-table.d.ts +2 -11
  23. package/dist/composites/detection-canvas.d.ts +0 -9
  24. package/dist/composites/detection-result-tree.d.ts +0 -12
  25. package/dist/composites/device-controls/container-primary-hero.d.ts +0 -17
  26. package/dist/composites/device-controls/humidifier-control.d.ts +0 -17
  27. package/dist/composites/device-controls/lawn-mower-control.d.ts +2 -1
  28. package/dist/composites/device-controls/pet-feeder-panel.d.ts +0 -18
  29. package/dist/composites/device-controls/script-automation-controls.d.ts +2 -1
  30. package/dist/composites/device-controls/sensor-hero-card.d.ts +0 -18
  31. package/dist/composites/device-controls/update-control.d.ts +0 -13
  32. package/dist/composites/device-controls/vacuum-control.d.ts +2 -1
  33. package/dist/composites/device-controls/valve-control.d.ts +2 -1
  34. package/dist/composites/device-controls/weather-control.d.ts +2 -1
  35. package/dist/composites/device-item/actions.d.ts +0 -22
  36. package/dist/composites/device-item/helpers.d.ts +2 -1
  37. package/dist/composites/device-item/index.d.ts +0 -9
  38. package/dist/composites/device-list/batch-actions-bar.d.ts +0 -11
  39. package/dist/composites/device-list/filter-chips.d.ts +0 -13
  40. package/dist/composites/device-list/page-size-select.d.ts +2 -1
  41. package/dist/composites/device-list/url-state.d.ts +2 -3
  42. package/dist/composites/device-meta.d.ts +14 -7
  43. package/dist/composites/device-picker/DevicePicker.d.ts +9 -1
  44. package/dist/composites/device-picker/device-filter-bar.d.ts +2 -1
  45. package/dist/composites/device-picker/device-parent.d.ts +2 -1
  46. package/dist/composites/device-picker/device-selection-rows.d.ts +6 -1
  47. package/dist/composites/device-selector-picker.d.ts +25 -1
  48. package/dist/composites/device-step-matrix.d.ts +0 -26
  49. package/dist/composites/error-box.d.ts +0 -15
  50. package/dist/composites/event-stream.d.ts +2 -1
  51. package/dist/composites/extensions/extensions-view-state.d.ts +2 -1
  52. package/dist/composites/hls-quality.d.ts +3 -2
  53. package/dist/composites/index.d.ts +0 -2
  54. package/dist/composites/notification-targets-field.d.ts +2 -2
  55. package/dist/composites/option-select/OptionSelect.d.ts +6 -0
  56. package/dist/composites/pipeline-matrix-shared.d.ts +2 -1
  57. package/dist/composites/provider-entries/AddProviderEntryDialog.d.ts +1 -1
  58. package/dist/composites/provider-entries/ProviderEntryPills.d.ts +1 -1
  59. package/dist/composites/ptz-overlay.d.ts +0 -19
  60. package/dist/composites/qr-code.d.ts +0 -14
  61. package/dist/composites/scope-picker.d.ts +2 -1
  62. package/dist/composites/step-inspector/layered-settings-form.d.ts +0 -11
  63. package/dist/composites/step-inspector/step-inspector-panel.d.ts +0 -6
  64. package/dist/composites/stream-broker-selector.d.ts +0 -21
  65. package/dist/composites/training/TrainingBaseModelPicker.d.ts +0 -10
  66. package/dist/composites/training/retrain-review-badge.d.ts +2 -1
  67. package/dist/composites/webrtc-diagnostics/endpoint-test.d.ts +2 -1
  68. package/dist/composites/webrtc-diagnostics/nat-mapping.d.ts +2 -1
  69. package/dist/composites/webrtc-diagnostics/session-run.d.ts +2 -1
  70. package/dist/composites/webrtc-diagnostics/session-verdict.d.ts +2 -1
  71. package/dist/contexts/ui-text.d.ts +49 -0
  72. package/dist/generated/system-hooks.d.ts +4 -0
  73. package/dist/i18n/addon-i18n.d.ts +46 -0
  74. package/dist/i18n/index.d.ts +2 -0
  75. package/dist/i18n/use-addon-t.d.ts +57 -0
  76. package/dist/index.cjs +3309 -2368
  77. package/dist/index.d.ts +2 -0
  78. package/dist/index.js +3297 -2368
  79. package/dist/lib/format-last-seen.d.ts +15 -1
  80. package/dist/lib/phase-config.d.ts +9 -3
  81. package/dist/lib/pipeline-mirror.d.ts +2 -1
  82. package/package.json +1 -1
  83. package/dist/composites/data-table/data-table-header.d.ts +0 -11
  84. package/dist/composites/data-table/data-table-pagination.d.ts +0 -10
  85. package/dist/composites/data-table/data-table-row.d.ts +0 -11
  86. package/dist/composites/data-table/data-table.d.ts +0 -3
  87. package/dist/composites/data-table/index.d.ts +0 -2
  88. package/dist/composites/data-table/types.d.ts +0 -34
  89. package/dist/composites/data-table-layout.d.ts +0 -31
@@ -1,21 +1,3 @@
1
- /**
2
- * SensorHeroCard — large-format sensor value display for the device-detail
3
- * hero area.
4
- *
5
- * Renders:
6
- * - Typed numeric sensors: value in `text-3xl font-semibold tabular-nums` +
7
- * canonical unit from ROLE_DESCRIPTOR (e.g. temperature-sensor → '°C').
8
- * - Generic numeric-sensor: value + unit read live from the slice
9
- * (`slice.unit`, populated by the HA provider from state attributes).
10
- * - Binary sensors: coloured state badge ("Detected"/"Clear" etc.) — same
11
- * labels and colours as SensorValueAtom's binary branch.
12
- * - Presence: Home/Away/zone-name badge — same labels as SensorValueAtom.
13
- * - All: sensor name label below the value.
14
- *
15
- * Unit resolution uses the same logic as SensorValueAtom (live slice.unit
16
- * wins, ROLE_DESCRIPTOR canonicalUnit as fallback) — the two surfaces stay
17
- * in sync.
18
- */
19
1
  import type { ReactNode } from "react";
20
2
  import type { DeviceControlProps } from "./control-registry";
21
3
  /**
@@ -1,16 +1,3 @@
1
- /**
2
- * Firmware/software Update controls for a `DeviceType.Update` device.
3
- *
4
- * Reads the `update` cap status slice (currentVersion / availableVersion /
5
- * updatable / state / inProgress) and renders:
6
- * - InlineControl (device-list row): a compact state badge — "Update
7
- * available" (actionable) / "Installing…" / current version (up to date).
8
- * - HeroCard (device-detail hero): the version transition + an Install button
9
- * that calls `update.installUpdate()` when an update is available.
10
- *
11
- * Mirrors the cover/sensor controls' `useDeviceCapability` pattern so the row
12
- * and the hero never diverge.
13
- */
14
1
  import type { ReactNode } from "react";
15
2
  import type { DeviceControlProps } from "./control-registry";
16
3
  /**
@@ -14,6 +14,7 @@
14
14
  * Mirrors the cover/update controls' `useDeviceCapability` pattern so the
15
15
  * row and hero never diverge. Buttons are gated on `available`.
16
16
  */
17
+ import { type UiTextFn } from "../../contexts/ui-text";
17
18
  import type { ReactNode } from "react";
18
19
  import type { VacuumState, TankStatus } from "@camstack/types";
19
20
  import type { DeviceControlProps } from "./control-registry";
@@ -27,7 +28,7 @@ export interface VacuumStateMeta {
27
28
  * human label + colour tone. Exhaustive switch: a new enum member fails
28
29
  * the build.
29
30
  */
30
- export declare function vacuumStateMeta(state: VacuumState | undefined): VacuumStateMeta;
31
+ export declare function vacuumStateMeta(state: VacuumState | undefined, t?: UiTextFn): VacuumStateMeta;
31
32
  /** The four intrinsic tanks a vacuum cap can expose. */
32
33
  export type TankKind = "cleanWater" | "dirtyWater" | "detergent" | "dustBin";
33
34
  export type TankAlert = "ok" | "warning";
@@ -14,6 +14,7 @@
14
14
  * `coverHighlight` — the valve state enum is identical to the cover one.
15
15
  * Buttons are gated on `available`.
16
16
  */
17
+ import { type UiTextFn } from "../../contexts/ui-text";
17
18
  import { type ReactNode } from "react";
18
19
  import { type ValveState } from "@camstack/types";
19
20
  import type { DeviceControlProps } from "./control-registry";
@@ -27,7 +28,7 @@ export interface ValveStateMeta {
27
28
  * human label + colour tone. Exhaustive switch: a new enum member fails
28
29
  * the build.
29
30
  */
30
- export declare function valveStateMeta(state: ValveState | undefined): ValveStateMeta;
31
+ export declare function valveStateMeta(state: ValveState | undefined, t?: UiTextFn): ValveStateMeta;
31
32
  /**
32
33
  * ValveInlineControl — compact, state-aware valve controls for a
33
34
  * device-list row. Open ▲ Stop ■ Close ▼ + optional position % badge.
@@ -17,6 +17,7 @@
17
17
  * default.
18
18
  */
19
19
  import { type ReactNode } from "react";
20
+ import { type UiTextFn } from "../../contexts/ui-text";
20
21
  import type { DeviceControlProps } from "./control-registry";
21
22
  /** Which sky glyph a condition maps to. Drives both the inline icon and
22
23
  * the hero scene's graphic branch. */
@@ -38,7 +39,7 @@ export interface WeatherTint {
38
39
  * Covers the known HA `weather.*` condition set; an unknown / null
39
40
  * condition falls back to a neutral cloud.
40
41
  */
41
- export declare function weatherConditionMeta(condition: string | null): WeatherConditionMeta;
42
+ export declare function weatherConditionMeta(condition: string | null, t?: UiTextFn): WeatherConditionMeta;
42
43
  /**
43
44
  * Pure helper — maps a verbatim HA condition string to a tint. Exhaustive
44
45
  * over the known condition set with a neutral default.
@@ -1,25 +1,3 @@
1
- /**
2
- * <DeviceItemActions> — type-aware dispatcher for inline quick actions.
3
- *
4
- * Two layers compose the row's trailing affordances:
5
- * 1. Type-specific InlineControl: rendered directly from the
6
- * `DEVICE_TYPE_CONTROL` registry (cover → ↑■↓ + %; all other
7
- * non-sensor types → DummyInline which renders nothing visible).
8
- * Sensor / Presence device rows display their live value via
9
- * `SensorValueAtom` instead (needs device.role + sourceInfo which
10
- * DeviceControlProps does not carry).
11
- * 2. Cross-cutting feature-gated extras (motion-trigger, PTZ, reboot)
12
- * stay here — they gate on `device.features`, are device-type
13
- * agnostic, and so are NOT in the per-type registry.
14
- *
15
- * High-frequency toggles stay inline. Reboot is a dedicated row-level
16
- * action button (`RebootQuickAction`) — destructive, so clicking it opens
17
- * a confirm modal rather than rebooting on the first click.
18
- *
19
- * Each atom self-gates via `useDeviceCapability` / the panel's own cap
20
- * lookup — the dispatcher is a coarse pre-flight only. An atom that
21
- * finds its cap unbound returns `null` so the row stays compact.
22
- */
23
1
  import { type ReactNode } from "react";
24
2
  import type { UseDeviceProxyTrpc } from "../../hooks/use-device-proxy";
25
3
  import { type ControlPlacement } from "../device-controls/control-registry";
@@ -19,6 +19,7 @@ import { type ChildLayout, type DeviceDisplayOverride, type RoleDisplayDefault,
19
19
  import type { LucideIcon } from "lucide-react";
20
20
  import type { ReactNode } from "react";
21
21
  import type { UseDeviceProxyTrpc } from "../../hooks/use-device-proxy";
22
+ import { type UiTextFn } from "../../contexts/ui-text";
22
23
  /**
23
24
  * Mirror of the canonical `DeviceInfo` wire shape (see
24
25
  * `packages/types/src/capabilities/device-manager.cap.ts`). Every
@@ -243,7 +244,7 @@ export declare function deviceLeadIcon(device: DeviceItemDevice, roleDefaults?:
243
244
  * override (falls back to the `DEVICE_ROLE_META` label). NOT the device name —
244
245
  * this is the small secondary role caption on accessory/sensor rows.
245
246
  */
246
- export declare function displayRoleLabel(device: DeviceItemDevice): string;
247
+ export declare function displayRoleLabel(device: DeviceItemDevice, t?: UiTextFn): string;
247
248
  export declare function stripParentNamePrefix(name: string, parentName: string): string;
248
249
  /**
249
250
  * Display name for a child device rendered UNDER its container/parent row.
@@ -1,12 +1,3 @@
1
- /**
2
- * <DeviceItem> — orchestrator that composes Header / Preview /
3
- * Features / Actions / StatusDot in a flex row (`view='card'`) or a
4
- * `<tr>` with one `<td>` per logical column (`view='table'`).
5
- *
6
- * Public API contract: identical to the predecessor `device-item.tsx`
7
- * file so the 5 existing call sites compile unchanged. The new
8
- * `view` prop defaults to `'card'`.
9
- */
10
1
  import { type ReactNode } from "react";
11
2
  import { type DeviceItemProps } from "./helpers";
12
3
  export type { ChildLayoutSection, GroupedChildren } from "./child-layout";
@@ -1,14 +1,3 @@
1
- /**
2
- * <DeviceBatchActionsBar> — responsive wrapper around <DeviceBatchToolbar>.
3
- *
4
- * Surfaces the available bulk actions once devices are selected:
5
- * - L2+ (`sm` and up): the toolbar renders inline as a row of buttons.
6
- * - L1 (`< sm`): a compact "Actions · N" trigger opens a popover that
7
- * hosts the SAME <DeviceBatchToolbar>, so the action logic (inline
8
- * delete-confirm, clear) is reused verbatim — never forked.
9
- *
10
- * Renders nothing while the selection is empty (delegated to the toolbar).
11
- */
12
1
  import { type ReactNode } from "react";
13
2
  export interface DeviceBatchActionsBarProps {
14
3
  readonly selectedIds: ReadonlySet<number>;
@@ -1,16 +1,3 @@
1
- /**
2
- * <FilterChips> — top-row filter UI for DeviceList.
3
- *
4
- * Layout: [Type chips] [Integration multi-select] [Clear filters]
5
- * (search input lives separately; this component only handles the
6
- * chip-style selectors + the integration dropdown).
7
- *
8
- * Type is radio-like (clicking the active chip clears it). Integration
9
- * is a compact MULTI-select dropdown — previously every integration
10
- * spilled into the row as inline chips and only one could be active;
11
- * now a single "Integration" button opens a checkbox menu so several
12
- * integrations can be filtered at once without flooding the toolbar.
13
- */
14
1
  import { type ReactNode } from "react";
15
2
  import type { MultiSelectOption } from "./multi-select";
16
3
  export interface FilterChipsAddonOption {
@@ -5,6 +5,7 @@
5
5
  * so the two never drift in look or wording. `PAGE_SIZE_ALL` renders as "All".
6
6
  */
7
7
  import { type ReactNode } from "react";
8
+ import { type UiTextFn } from "../../contexts/ui-text";
8
9
  export interface PageSizeSelectProps {
9
10
  readonly value: number;
10
11
  readonly options: readonly number[];
@@ -12,5 +13,5 @@ export interface PageSizeSelectProps {
12
13
  /** Accessible name — names what is being paged ("Devices per page"). */
13
14
  readonly ariaLabel: string;
14
15
  }
15
- export declare function pageSizeLabel(size: number): string;
16
+ export declare function pageSizeLabel(size: number, t?: UiTextFn): string;
16
17
  export declare function PageSizeSelect({ value, options, onChange, ariaLabel }: PageSizeSelectProps): ReactNode;
@@ -7,9 +7,8 @@
7
7
  * `?view=cards` link still opens: the parameter is simply not read, and the
8
8
  * next write drops it from the URL.
9
9
  *
10
- * The DataTable's own phone rendering is a different thing entirely and is
11
- * untouched (`data-table-layout.ts`): that is how ONE table degrades on a
12
- * narrow screen, not a view the operator picks.
10
+ * The DataTable never swaps to cards on a phone either: it scrolls sideways
11
+ * inside its own container.
13
12
  */
14
13
  export interface DeviceListUrlState {
15
14
  readonly page: number;
@@ -1,6 +1,7 @@
1
1
  import type { LucideIcon } from "lucide-react";
2
2
  import { DeviceType, DeviceRole, type IconKey } from "@camstack/types";
3
3
  import type { MultiSelectOption } from "./device-list/multi-select";
4
+ import { type UiTextFn } from "../contexts/ui-text";
4
5
  /**
5
6
  * Single source of truth for rendering a device TYPE or ROLE: its icon + label.
6
7
  *
@@ -21,12 +22,18 @@ export interface DeviceRoleMeta {
21
22
  readonly icon: LucideIcon;
22
23
  readonly label: string;
23
24
  }
24
- export declare const DEVICE_TYPE_META: Record<DeviceType, DeviceTypeMeta>;
25
- export declare const DEVICE_ROLE_META: Record<DeviceRole, DeviceRoleMeta>;
25
+ /** A table row: the label is a catalogue key + English fallback, resolved by the consumer. */
26
+ export interface DeviceMetaEntry {
27
+ readonly icon: LucideIcon;
28
+ readonly labelKey: string;
29
+ readonly labelFallback: string;
30
+ }
31
+ export declare const DEVICE_TYPE_META: Record<DeviceType, DeviceMetaEntry>;
32
+ export declare const DEVICE_ROLE_META: Record<DeviceRole, DeviceMetaEntry>;
26
33
  /** Meta for a known `DeviceType`. */
27
- export declare function deviceTypeMeta(type: DeviceType): DeviceTypeMeta;
34
+ export declare function deviceTypeMeta(type: DeviceType, t?: UiTextFn): DeviceTypeMeta;
28
35
  /** Meta for a known `DeviceRole`. */
29
- export declare function deviceRoleMeta(role: DeviceRole): DeviceRoleMeta;
36
+ export declare function deviceRoleMeta(role: DeviceRole, t?: UiTextFn): DeviceRoleMeta;
30
37
  /**
31
38
  * Runtime-string-safe lookup: device data crosses process / network boundaries
32
39
  * as plain strings, so an unrecognised value falls back to the `Generic` meta
@@ -36,9 +43,9 @@ export declare function deviceRoleMeta(role: DeviceRole): DeviceRoleMeta;
36
43
  * `@camstack/types` enum has a new member before the loaded ui-library bundle
37
44
  * has the matching `DEVICE_TYPE_META` entry.
38
45
  */
39
- export declare function deviceTypeMetaOf(type: string): DeviceTypeMeta;
46
+ export declare function deviceTypeMetaOf(type: string, t?: UiTextFn): DeviceTypeMeta;
40
47
  /** Runtime-string-safe role lookup; unknown roles fall back to `GenericSensor`. */
41
- export declare function deviceRoleMetaOf(role: string): DeviceRoleMeta;
48
+ export declare function deviceRoleMetaOf(role: string, t?: UiTextFn): DeviceRoleMeta;
42
49
  /**
43
50
  * The glyphs the admin draws on FIRST PAINT, synchronously — the ones the
44
51
  * device-type and role meta tables above already import. Everything else in
@@ -51,4 +58,4 @@ export declare function deviceRoleMetaOf(role: string): DeviceRoleMeta;
51
58
  * cache of glyphs, not a list of choices.
52
59
  */
53
60
  export declare const FAST_ICON_GLYPHS: Readonly<Partial<Record<IconKey, LucideIcon>>>;
54
- export declare function allDeviceTypeFilterOptions(): readonly MultiSelectOption[];
61
+ export declare function allDeviceTypeFilterOptions(t?: UiTextFn): readonly MultiSelectOption[];
@@ -70,5 +70,13 @@ export interface DevicePickerProps<Id extends PickerId = number> {
70
70
  * surface whose whole job is the list — the rule's Devices tab (R15).
71
71
  */
72
72
  readonly showAll?: boolean;
73
+ /**
74
+ * Devices that are ALREADY part of the thing being edited (linked to the
75
+ * camera, assigned to the room): drawn checked and disabled with
76
+ * `lockedNote`, never part of `value`, never emitted by `onChange`.
77
+ */
78
+ readonly lockedIds?: readonly Id[];
79
+ /** The line under a locked device. Default "Already added". */
80
+ readonly lockedNote?: string;
73
81
  }
74
- export declare function DevicePicker<Id extends PickerId = number>({ devices: devicesIn, listState, fleet, value, onChange, emptyMeansAll, savedHadDevices, noun, groupTitle, emptyLabel, annotate, disabled, testId, showAll }: DevicePickerProps<Id>): JSX.Element;
82
+ export declare function DevicePicker<Id extends PickerId = number>({ devices: devicesIn, listState, fleet, value, onChange, emptyMeansAll, savedHadDevices, noun, groupTitle: groupTitleProp, emptyLabel, annotate, disabled, testId, showAll, lockedIds, lockedNote: lockedNoteProp }: DevicePickerProps<Id>): JSX.Element;
@@ -1,4 +1,5 @@
1
1
  import { type JSX } from "react";
2
+ import { type UiTextFn } from "../../contexts/ui-text";
2
3
  import { type PickerFacetOption, type PickerFilters, type PickerGroupBy, type PickerZonesFallback, type PickerZonesRead } from "./device-picker-model";
3
4
  /** The Group-by control's inputs, as `DevicePicker.tsx` passes them. */
4
5
  export interface DeviceFilterBarGrouping {
@@ -22,5 +23,5 @@ export interface DeviceFilterBarProps {
22
23
  readonly disabled?: boolean;
23
24
  }
24
25
  /** "media-player" → "Media player"; null → "No type". */
25
- export declare function typeLabel(type: string | null): string;
26
+ export declare function typeLabel(type: string | null, t?: UiTextFn): string;
26
27
  export declare function DeviceFilterBar({ filters, onFiltersChange, typeOptions, zoneOptions, locationOptions, zones, grouping, searchPlaceholder, searchLabel, disabled }: DeviceFilterBarProps): JSX.Element;
@@ -9,6 +9,7 @@
9
9
  * ONE level, deliberately: the operator's question is "which thing is this
10
10
  * attached to", not "what is the full ancestry".
11
11
  */
12
+ import { type UiTextFn } from "../../contexts/ui-text";
12
13
  /** The fields this needs. Any listing row satisfies it. */
13
14
  export interface ParentResolvable {
14
15
  readonly id: number;
@@ -24,7 +25,7 @@ export interface ParentResolvable {
24
25
  */
25
26
  export declare function resolveParentNames(devices: readonly ParentResolvable[]): ReadonlyMap<number, string>;
26
27
  /** Second-line hint: `in <parent>` when the device lives under a hub/container. */
27
- export declare function parentDetailOf(parentName: string | undefined): string | undefined;
28
+ export declare function parentDetailOf(parentName: string | undefined, t?: UiTextFn): string | undefined;
28
29
  /**
29
30
  * Fill unset `detail` with `in <parent>` from {@link parentDeviceId} on the
30
31
  * same list. Callers that already set `detail` keep it. String-id pickers
@@ -15,6 +15,7 @@
15
15
  */
16
16
  import type { SelectedDeviceRow, SelectionId } from "./device-selection";
17
17
  import { type JSX } from "react";
18
+ import { type UiTextFn } from "../../contexts/ui-text";
18
19
  /**
19
20
  * What a picker lists, for its sentences. `class` is a detection class (D641);
20
21
  * `zone` and `face` are a rule's zone and known-face scopes (D690).
@@ -24,8 +25,12 @@ export type PickerNoun = "camera" | "device" | "node" | "package" | "class" | "z
24
25
  export declare const PICKER_NOUN_PLURAL: Readonly<Record<PickerNoun, string>>;
25
26
  /** What a picker lists, plural — the only words the loading / failed lines say. */
26
27
  export type PickerNounPlural = (typeof PICKER_NOUN_PLURAL)[PickerNoun];
28
+ /** The translated singular of a picker noun. */
29
+ export declare function pickerNounLabel(noun: PickerNoun, t: UiTextFn): string;
30
+ /** The translated plural of a picker noun. */
31
+ export declare function pickerNounPluralLabel(noun: PickerNoun, t: UiTextFn): string;
27
32
  /** The label a picker gives a selected id its drawn list does not contain. */
28
- export declare function orphanDeviceLabel<Id extends SelectionId>(row: SelectedDeviceRow<Id>, noun?: PickerNoun): string;
33
+ export declare function orphanDeviceLabel<Id extends SelectionId>(row: SelectedDeviceRow<Id>, noun?: PickerNoun, t?: UiTextFn): string;
29
34
  interface DevicesWidenWarningProps {
30
35
  /** What the picker lists: the rule's Devices tab lists every device. */
31
36
  readonly noun?: PickerNoun;
@@ -1,3 +1,27 @@
1
+ /**
2
+ * <DeviceSelectorPicker> — the operator-facing editor for a v3
3
+ * {@link DeviceSelector}: the "on WHICH devices" half of a scope grant.
4
+ *
5
+ * Four tabs, one per selector kind, because the kinds are not interchangeable
6
+ * and the operator has to choose between them deliberately:
7
+ *
8
+ * All → every device, now and forever. DYNAMIC.
9
+ * By type → every device of a `DeviceType`. DYNAMIC — a camera added
10
+ * tomorrow is covered with no re-grant.
11
+ * By room → every device carrying an operator-assigned `location` label.
12
+ * DYNAMIC. Rendered ONLY when the fleet actually has labels;
13
+ * an empty tab reads as a broken feature, not as "unused".
14
+ * Chosen → an explicit id list. STATIC — this is the one that does NOT
15
+ * cover a new device, and the tab says so.
16
+ *
17
+ * Counts are LIVE (computed off `deviceManager.listAll`) so "Camera · 12"
18
+ * answers "how much am I granting" without leaving the panel.
19
+ *
20
+ * Shared, not forked: the raw `<ScopePicker>` device row and the simple
21
+ * Access panel both render this. Two editors for one wire shape is how a
22
+ * selector ends up meaning different things in two places.
23
+ */
24
+ import { type UiTextFn } from "../contexts/ui-text";
1
25
  import { DeviceType, type DeviceSelector } from "@camstack/types";
2
26
  /** The device fields this picker reads. */
3
27
  export interface SelectorDevice {
@@ -33,5 +57,5 @@ export declare function deviceTypeLabel(type: string): string;
33
57
  export declare function tabForSelector(selector: DeviceSelector): DeviceSelectorTab;
34
58
  export declare function DeviceSelectorPicker({ value, onChange, includeLinked, onIncludeLinkedChange, clampToDeviceIds, dense }: DeviceSelectorPickerProps): React.ReactElement;
35
59
  /** Summary line for a selector — used by the raw picker's collapsed row. */
36
- export declare function describeDeviceSelector(selector: DeviceSelector): string;
60
+ export declare function describeDeviceSelector(selector: DeviceSelector, t?: UiTextFn): string;
37
61
  export {};
@@ -1,29 +1,3 @@
1
- /**
2
- * DeviceStepMatrix — the step × accelerator TABLE of a detection pipeline
3
- * (D757): the node's Pipeline tab and the camera's Detection pipeline → Steps
4
- * are this matrix, and a click on a cell (or a step's header) opens that step's
5
- * settings in a docked panel (`StepDetailDock`) that overlays the page instead
6
- * of reflowing the matrix.
7
- *
8
- * Column 1 (STICKY): the indented step tree — slot, name, class-flow chips,
9
- * and an optional badge (the camera's gate). The header is a button: it
10
- * opens the step on the selected accelerator.
11
- * Columns 2..N: one per accelerator, grouped under their node; the header
12
- * names the accelerator, its format, the model it elects, and "off" for a
13
- * switched-off one. A cell shows the model that runs there, or "⚠ skip",
14
- * "→ iGPU", "root", "cluster", "ovr", "—".
15
- *
16
- * Keyboard: ONE Tab stop (a roving tabindex over the step headers and cells);
17
- * arrows move, Home / End go to the row's ends, Enter or Space opens.
18
- *
19
- * `reserveRightPx`: the width a docked panel covers at the right of the
20
- * viewport. The matrix adds a trailing spacer that wide (so any column can
21
- * scroll clear of it) and scrolls the selected cell into the uncovered part —
22
- * it never shrinks, so nothing reflows when the panel opens.
23
- *
24
- * Responsive, container-measured: narrower than the step column plus two
25
- * columns, the matrix shows ONE node at a time with a node selector.
26
- */
27
1
  import { type ReactNode, type ForwardRefExoticComponent, type RefAttributes } from "react";
28
2
  import type { StepTreeNode } from "./step-tree";
29
3
  import { type AgentColumn, type CellState, type MatrixSelectedCell } from "./pipeline-matrix-shared";
@@ -1,18 +1,3 @@
1
- /**
2
- * `<ErrorBox>` — the shared, presentational error/alert box for the
3
- * admin UI.
4
- *
5
- * One consistent way to surface connection / status / operation
6
- * failures across every addon surface (Remote Access, Mesh Networks,
7
- * TURN Servers, Authentication, device-export, …). It always renders
8
- * as a bordered box INSIDE a form/body — never as a tiny inline header
9
- * span. Light-theme readable by design.
10
- *
11
- * Purely presentational: no data fetching, no business logic. Pass a
12
- * message string (or richer `ReactNode`), an optional `title`, an
13
- * optional retry handler / action slot, and an optional `warning`
14
- * variant for non-fatal advisories.
15
- */
16
1
  import { type ReactNode, type JSX } from "react";
17
2
  export type ErrorBoxVariant = "danger" | "warning";
18
3
  export interface ErrorBoxProps {
@@ -15,6 +15,7 @@
15
15
  * input refreshes when the active category set changes.
16
16
  */
17
17
  import { type JSX } from "react";
18
+ import { type UiTextFn } from "../contexts/ui-text";
18
19
  import { type LiveBuffer } from "../hooks/use-live-buffer";
19
20
  interface EventEntry {
20
21
  readonly id: string;
@@ -60,7 +61,7 @@ export interface EventStreamProps {
60
61
  /** Categories visible in the events tab by default. The "All" badge
61
62
  * reflects this set, not the raw enum. */
62
63
  export declare const DEFAULT_EVENT_CATEGORIES: readonly string[];
63
- export declare function summarizeEvent(category: string, data: Record<string, unknown>): string | null;
64
+ export declare function summarizeEvent(category: string, data: Record<string, unknown>, t?: UiTextFn): string | null;
64
65
  export declare function EventStream({ agentId, addonId, deviceId, defaultCategories, categories: legacyCategories, category: propsCategory, maxHeight, limit, showCategoryFilter, showFilters: _showFilters, liveBuffer: externalBuffer, onClose, className }: EventStreamProps): JSX.Element | null;
65
66
  export interface FloatingEventStreamProps extends EventStreamProps {
66
67
  readonly position?: "bottom" | "overlay";
@@ -17,6 +17,7 @@
17
17
  * a spec cannot reach.
18
18
  */
19
19
  import { type ExtensionCandidate, type ExtensionSlotCardinality, type ExtensionSlotRow, type ExtensionSlotState, type ExtensionSlotUnreachable, type ExtensionSlotValue } from "@camstack/types";
20
+ import { type UiTextFn } from "../../contexts/ui-text.js";
20
21
  /** The one field of a query error this module reads. */
21
22
  export interface ExtensionsQueryError {
22
23
  readonly message: string;
@@ -64,7 +65,7 @@ export type ExtensionSlotTableOrder = readonly string[];
64
65
  * `order` is the generated table (`EXTENSION_SLOT_IDS`); a parameter only so a
65
66
  * spec can pin the comparator while the table holds a single slot.
66
67
  */
67
- export declare function resolveExtensionsView(query: ExtensionsQueryView, order?: ExtensionSlotTableOrder): ExtensionsView;
68
+ export declare function resolveExtensionsView(query: ExtensionsQueryView, order?: ExtensionSlotTableOrder, t?: UiTextFn): ExtensionsView;
68
69
  /** Add or remove one pick. `one` replaces; `many` toggles. */
69
70
  export declare function togglePick(draft: readonly number[], deviceId: number, cardinality: ExtensionSlotCardinality): readonly number[];
70
71
  /** Suggested candidates the operator has NOT picked — shown to confirm, never saved on their own (D356). */
@@ -4,6 +4,7 @@
4
4
  * Intentionally decoupled from hls.js types so this module can be
5
5
  * imported and tested without a DOM or MSE environment.
6
6
  */
7
+ import { type UiTextFn } from "../contexts/ui-text";
7
8
  export interface QualityOption {
8
9
  readonly value: number;
9
10
  readonly label: string;
@@ -25,11 +26,11 @@ export interface HlsLevelInfo {
25
26
  * 3. `bitrate` (> 0) → e.g. "2500 kbps"
26
27
  * 4. Fallback → "Level N" (1-based)
27
28
  */
28
- export declare function levelLabel(level: HlsLevelInfo, index: number): string;
29
+ export declare function levelLabel(level: HlsLevelInfo, index: number, t?: UiTextFn): string;
29
30
  /**
30
31
  * Build the full list of quality options for the selector overlay.
31
32
  *
32
33
  * Always starts with the Auto entry (`value: -1`), followed by one
33
34
  * entry per available HLS level in manifest order.
34
35
  */
35
- export declare function qualityOptions(levels: readonly HlsLevelInfo[]): QualityOption[];
36
+ export declare function qualityOptions(levels: readonly HlsLevelInfo[], t?: UiTextFn): QualityOption[];
@@ -85,8 +85,6 @@ export type { DataTableFilterBarGroup, DataTableFilterBarLabels, DataTableFilter
85
85
  export { DataTableFilterBar } from "./data-table-filter-bar";
86
86
  export type { DataTableFilter, DataTableFilterGroupView } from "./use-data-table-filter";
87
87
  export { useDataTableFilter } from "./use-data-table-filter";
88
- export type { TableLayoutKind, TableMobileMode } from "./data-table-layout";
89
- export { CARD_MODE_MIN_COLUMNS, resolveTableLayout } from "./data-table-layout";
90
88
  export type { SortHeaderButtonProps } from "./sort-header-button";
91
89
  export { SortHeaderButton } from "./sort-header-button";
92
90
  export type { AriaSortValue, TableSortDirection, TableSortState, TableSortValue } from "./table-sort";
@@ -55,11 +55,11 @@ export interface NotificationTargetSelectFieldProps {
55
55
  /**
56
56
  * Multi-select of delivery targets (NC Summaries / Timelapses / Rules shape).
57
57
  */
58
- export declare function NotificationTargetsField({ targets, value, onChange, disabled, maxItems, testIdPrefix, emptyMessage, noteIds, noteLabel, label, description, kindIconUrls: kindIconUrlsProp }: NotificationTargetsFieldProps): JSX.Element;
58
+ export declare function NotificationTargetsField({ targets, value, onChange, disabled, maxItems, testIdPrefix, emptyMessage: emptyMessageProp, noteIds, noteLabel: noteLabelProp, label, description, kindIconUrls: kindIconUrlsProp }: NotificationTargetsFieldProps): JSX.Element;
59
59
  /**
60
60
  * Single-select of one delivery target (Calendar events / script settings).
61
61
  */
62
- export declare function NotificationTargetSelectField({ targets, value, onChange, disabled, emptyMessage, placeholder, testId, label, description, kindIconUrls: kindIconUrlsProp }: NotificationTargetSelectFieldProps): JSX.Element;
62
+ export declare function NotificationTargetSelectField({ targets, value, onChange, disabled, emptyMessage: emptyMessageProp, placeholder: placeholderProp, testId, label, description, kindIconUrls: kindIconUrlsProp }: NotificationTargetSelectFieldProps): JSX.Element;
63
63
  /**
64
64
  * ConfigUISchema `notification-target-multiselect` — fetches listTargets and
65
65
  * stores a `string[]` of target ids.
@@ -17,6 +17,12 @@ type OptionSelectSharedProps = {
17
17
  };
18
18
  export type OptionSelectSingleProps = OptionSelectSharedProps & {
19
19
  readonly mode: "single";
20
+ /**
21
+ * `chip` (default): the choice is a removable chip above the field.
22
+ * `field`: the field itself shows the current choice (placeholder-style, so
23
+ * typing searches), no chip and no clear — for a choice that always exists.
24
+ */
25
+ readonly singleDisplay?: "chip" | "field";
20
26
  readonly value: string;
21
27
  readonly onChange: (next: string) => void;
22
28
  };
@@ -7,6 +7,7 @@
7
7
  * Nothing here holds state or talks to a store — pure display + one pure
8
8
  * layout-decision helper (`shouldUseSingleNode`).
9
9
  */
10
+ import { type UiTextFn } from "../contexts/ui-text";
10
11
  import { type ReactNode, type JSX } from "react";
11
12
  import type { PipelineSlot } from "@camstack/types";
12
13
  import type { StepTreeNode } from "./step-tree";
@@ -195,5 +196,5 @@ export declare function StepLabel({ node }: {
195
196
  * the model id truncates inside a `min-w-0` flex row, so a longer model id never
196
197
  * widens the cell — it ellipsises instead.
197
198
  */
198
- export declare function renderCellContent(state: CellState): ReactNode;
199
+ export declare function renderCellContent(t: UiTextFn, state: CellState): ReactNode;
199
200
  export declare function cellButtonClass(state: CellState, isSelected: boolean, extra?: string): string;
@@ -25,4 +25,4 @@ export interface AddProviderEntryDialogProps {
25
25
  readonly title?: string;
26
26
  readonly description?: string;
27
27
  }
28
- export declare function AddProviderEntryDialog({ open, onOpenChange, types, onCreate, submitting, title, description }: AddProviderEntryDialogProps): JSX.Element;
28
+ export declare function AddProviderEntryDialog({ open, onOpenChange, types, onCreate, submitting, title: titleProp, description: descriptionProp }: AddProviderEntryDialogProps): JSX.Element;
@@ -16,4 +16,4 @@ export interface ProviderEntryPillsProps {
16
16
  readonly onAdd?: () => void;
17
17
  readonly addLabel?: string;
18
18
  }
19
- export declare function ProviderEntryPills({ label, entries, selectedEntryId, onSelect, onAdd, addLabel }: ProviderEntryPillsProps): JSX.Element;
19
+ export declare function ProviderEntryPills({ label, entries, selectedEntryId, onSelect, onAdd, addLabel: addLabelProp }: ProviderEntryPillsProps): JSX.Element;
@@ -1,22 +1,3 @@
1
- /**
2
- * PTZOverlay — pan / tilt / zoom controls.
3
- *
4
- * Two visual variants driven by `mode`:
5
- * - `'overlay'` (default): translucent dark pill positioned bottom-
6
- * right of the camera viewport. Used as `extraOverlay` on the
7
- * `CameraStreamPlayer` so operators can drive PTZ without leaving
8
- * the live view. Opaque background + subtle ring keeps the d-pad
9
- * legible against any frame.
10
- * - `'panel'`: full-bleed inside a host container (e.g. the floating
11
- * PTZ panel in DeviceDetail). No absolute positioning, no inner
12
- * wrapper card — the host's chrome is the only frame. Inherits the
13
- * surrounding `bg-surface` so the dark theme reads consistently
14
- * instead of the previous always-dark-bubble look.
15
- *
16
- * Interaction model is identical across modes: short tap fires a
17
- * discrete pulse (`move`); long press starts continuous motion until
18
- * release (`startContinuous` + `stopContinuous` on pointer up).
19
- */
20
1
  import { type JSX } from "react";
21
2
  import type { UsePTZResult } from "../hooks/use-ptz";
22
3
  export interface PTZOverlayProps {
@@ -1,17 +1,3 @@
1
- /**
2
- * `QrCode` — renders a scannable QR code from an arbitrary string.
3
- *
4
- * Browser-pure: wraps `qrcode.react`'s synchronous SVG renderer.
5
- * The `qrcode` npm package is intentionally NOT used — it is a
6
- * CommonJS, Node-targeted library, and bundling it into ui-library
7
- * dragged `node:module` / `createRequire` into the browser output,
8
- * breaking every downstream browser build that consumes ui-library.
9
- *
10
- * Addon-agnostic — used by the generic device-export panel to render a
11
- * HAP `X-HM://…` setup URI, a pairing URL, or any other scannable
12
- * string an export addon surfaces via the `device-export` cap's
13
- * `setup.qr` field.
14
- */
15
1
  import { type ReactElement } from "react";
16
2
  export interface QrCodeProps {
17
3
  /** The string encoded into the QR. Empty/whitespace renders nothing. */
@@ -24,6 +24,7 @@
24
24
  */
25
25
  import { type ReactNode } from "react";
26
26
  import { type TokenScope } from "@camstack/types";
27
+ import { type UiTextFn } from "../contexts/ui-text";
27
28
  export type ScopeAccess = "view" | "create" | "delete";
28
29
  interface ScopePickerProps {
29
30
  readonly value: readonly TokenScope[];
@@ -50,5 +51,5 @@ export declare function ScopePicker({ value, onChange, clampToParent, emptyHint
50
51
  * the schema's `.min(1)` would reject it server-side anyway, and the failure
51
52
  * mode of guessing wrong here is granting the whole fleet.
52
53
  */
53
- export declare function validateScopes(scopes: readonly TokenScope[]): string | null;
54
+ export declare function validateScopes(scopes: readonly TokenScope[], t?: UiTextFn): string | null;
54
55
  export {};
@@ -1,14 +1,3 @@
1
- /**
2
- * LayeredSettingsForm — a detection step's settings, edited on ONE layer
3
- * (D754): the node base, the camera (every accelerator) or one accelerator.
4
- *
5
- * Every field shows the value that runs on the viewed accelerator, which layer
6
- * supplies it, the values of the other levels (so "node vs camera" is read, not
7
- * clicked for), and a reset that removes the field from the edited layer only.
8
- * A change writes the touched field alone — a model-bound field (D738) as its
9
- * value + binding pair — so the edited layer stays field-level and never
10
- * freezes the levels below it.
11
- */
12
1
  import { type ReactNode, type JSX } from "react";
13
2
  import { type ConfigField, type PipelineAddonSchema, type StepSettingSource, type StepSettingsLayers } from "@camstack/types";
14
3
  import { type RootModelInfo } from "../root-model-source";