@camstack/ui-library 1.2.322 → 1.2.324

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.
@@ -31,8 +31,8 @@
31
31
  * - **Four states are tellable apart**: loading, empty-with-a-cause,
32
32
  * degraded-per-source, and each silent source in its own words. Every one
33
33
  * of them used to render as "no clips", which is the defect this whole line
34
- * of work is about — a camera with no SD card (640) is not quiet, and a
35
- * camera whose own index disagrees with its own calendar (618, 6–20
34
+ * of work is about — a camera with no SD card (106) is not quiet, and a
35
+ * camera whose own index disagrees with its own calendar (108, 6–20
36
36
  * September) is not quiet either.
37
37
  *
38
38
  * ## The period comes from the recording section's timebar, not a day picker
@@ -85,7 +85,7 @@
85
85
  * There is no "default" option and no empty value. This section used to send
86
86
  * no `provider` at all until the operator chose, because the cap documented
87
87
  * absence as "the device's bound provider, which is CamStack on every camera".
88
- * No code implemented that: measured on device 592 (2026-09-20, bound to
88
+ * No code implemented that: measured on device 107 (2026-09-20, bound to
89
89
  * `recorder` AND `provider-reolink`) a bare `listClips` with `limit: 3`
90
90
  * answered SIX rows — three per source, merged — while the default option read
91
91
  * "CamStack recordings". The label named one thing and the query asked two.
@@ -1,14 +1,24 @@
1
1
  /**
2
- * Fixed colors for known detection classes — derived from the taxonomy
3
- * (every detection/motion kind) plus the UI-only face/plate classes. Kept as
4
- * a named export for back-compat with existing consumers.
2
+ * Detection class colours — the bundled display palette (D939).
3
+ *
4
+ * A mounted {@link DisplayPaletteProvider} paints the cluster's effective
5
+ * palette instead. There is no second hex table here.
6
+ */
7
+ import { type PaletteReady } from "@camstack/types";
8
+ /**
9
+ * Fixed colours for known classes, from the bundled CamStack preset.
10
+ * Kept for callers that read the map directly.
5
11
  */
6
12
  export declare const CLASS_COLORS: Readonly<Record<string, string>>;
7
- /** Primary/default color when nothing else matches */
13
+ /** Primary colour when nothing else matches — the first bundled fallback. */
8
14
  export declare const DEFAULT_COLOR: string;
15
+ export interface PalettePaintSource {
16
+ readonly swatches: PaletteReady["swatches"];
17
+ readonly fallbacks: PaletteReady["fallbacks"];
18
+ }
9
19
  /**
10
- * Get the color for a detection class name.
11
- * Resolves: custom override → taxonomy/UI-only fixed color → deterministic
12
- * hash-based color for unknown classes.
20
+ * Colour for a detection class. Custom overrides win, then the palette
21
+ * (the bundled preset when none is passed). Unknown classes hash into
22
+ * the palette's fallbacks.
13
23
  */
14
- export declare function getClassColor(className: string, customColors?: Readonly<Record<string, string>>): string;
24
+ export declare function getClassColor(className: string, customColors?: Readonly<Record<string, string>>, palette?: PalettePaintSource): string;
@@ -9,7 +9,7 @@
9
9
  * narrow. Used by table view + minimal in-panel lists.
10
10
  * - `stacked=true`: name is the visual anchor of a vertical card. No
11
11
  * truncation, two-line clamp so longer names wrap instead of
12
- * collapsing into "Videocamera vera…". Typography is larger /
12
+ * collapsing into "Camera vera…". Typography is larger /
13
13
  * heavier so the name dominates the secondary metadata that sits
14
14
  * below it.
15
15
  *
@@ -89,7 +89,7 @@ export declare const NAME_COLUMN_PIN_CLASS: "md:sticky md:left-0 md:z-[1]";
89
89
  * ── The NAME never truncates below the pin breakpoint ─────────────────────
90
90
  *
91
91
  * Fitting NAME + Preview inside a phone viewport was the wrong trade: every
92
- * camera collapsed to "Videocamera ve…" / "Videocamera co…", which is not a
92
+ * camera collapsed to "Camera ve…" / "Camera co…", which is not a
93
93
  * shortened name, it is NO name — the rows became indistinguishable and the
94
94
  * one thing the operator opened the page to read was the part that got cut.
95
95
  *
@@ -2,17 +2,17 @@
2
2
  * fuzzy-match — case and separator-insensitive text search helper.
3
3
  *
4
4
  * Normalization rule: lowercase + strip all runs of hyphens, underscores and
5
- * whitespace entirely. This makes `Tapparella cucina` and `tapparella-cucina`
6
- * both normalize to `tapparellacucina`, so a substring match succeeds in
5
+ * whitespace entirely. This makes `Tapparella kitchen` and `tapparella-kitchen`
6
+ * both normalize to `tapparellakitchen`, so a substring match succeeds in
7
7
  * either direction.
8
8
  */
9
9
  /**
10
10
  * Strips hyphens, underscores and whitespace runs from `s` and lowercases it.
11
11
  *
12
12
  * @example
13
- * normalizeForSearch('Tapparella cucina') // 'tapparellacucina'
14
- * normalizeForSearch('tapparella-cucina') // 'tapparellacucina'
15
- * normalizeForSearch('tapparella_cucina') // 'tapparellacucina'
13
+ * normalizeForSearch('Tapparella kitchen') // 'tapparellakitchen'
14
+ * normalizeForSearch('tapparella-kitchen') // 'tapparellakitchen'
15
+ * normalizeForSearch('tapparella_kitchen') // 'tapparellakitchen'
16
16
  */
17
17
  export declare function normalizeForSearch(s: string): string;
18
18
  /**
@@ -20,8 +20,8 @@ export declare function normalizeForSearch(s: string): string;
20
20
  * form of `query`. An empty query always matches.
21
21
  *
22
22
  * @example
23
- * fuzzyMatch('Tapparella cucina', 'tapparella-cucina') // true
24
- * fuzzyMatch('tapparella cucina', 'Tapparella-Cucina') // true
25
- * fuzzyMatch('xyz', 'tapparella-cucina') // false
23
+ * fuzzyMatch('Tapparella kitchen', 'tapparella-kitchen') // true
24
+ * fuzzyMatch('tapparella kitchen', 'Tapparella-Kitchen') // true
25
+ * fuzzyMatch('xyz', 'tapparella-kitchen') // false
26
26
  */
27
27
  export declare function fuzzyMatch(query: string, target: string): boolean;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The cluster palette, when a host has read `display-palette` (D939).
3
+ * No provider, a pending read, or an unknown store all paint the bundled
4
+ * CamStack preset. Only `ready` replaces it. Callers that must say the
5
+ * store was unreadable read {@link useDisplayPaletteView}.
6
+ */
7
+ import { type ReactNode } from "react";
8
+ import { type PaletteReady } from "@camstack/types";
9
+ export type DisplayPaletteView = {
10
+ readonly status: "absent";
11
+ } | {
12
+ readonly status: "pending";
13
+ } | {
14
+ readonly status: "unknown";
15
+ readonly reason: string;
16
+ } | {
17
+ readonly status: "ready";
18
+ readonly palette: PaletteReady;
19
+ };
20
+ export interface DisplayPaletteProviderProps {
21
+ readonly value: DisplayPaletteView;
22
+ readonly children: ReactNode;
23
+ }
24
+ export declare function DisplayPaletteProvider({ value, children }: DisplayPaletteProviderProps): ReactNode;
25
+ export declare function useDisplayPaletteView(): DisplayPaletteView;
26
+ export declare function useClassPainter(): (className: string, customColors?: Readonly<Record<string, string>>) => string;
@@ -98,6 +98,7 @@ export { ariaSortForColumn, nextSortDirection, nextTableSort, sortRowsByColumn }
98
98
  export type { Detection, DetectionCanvasProps } from "./detection-canvas";
99
99
  export { DetectionCanvas } from "./detection-canvas";
100
100
  export { CLASS_COLORS, DEFAULT_COLOR, getClassColor } from "./detection-colors";
101
+ export { DisplayPaletteProvider, useClassPainter, useDisplayPaletteView, type DisplayPaletteProviderProps, type DisplayPaletteView } from "./display-palette-context";
101
102
  export type { DetectionOverlayProps } from "./detection-overlay";
102
103
  export { DetectionOverlay } from "./detection-overlay";
103
104
  export type { DetectionResultTreeProps } from "./detection-result-tree";
@@ -4,7 +4,7 @@ export type ModelOption = PipelineAddonSchema["models"][number];
4
4
  /**
5
5
  * Shared model picker — the ONE model-selection control across the app.
6
6
  *
7
- * Provider first (CamStack / Frigate / Scrypted / Custom), then inside that
7
+ * Provider first (CamStack / plus catalog / plugin catalog / Custom), then inside that
8
8
  * catalog the grouped Family→Tier→Variant selector when entries declare
9
9
  * `group`, else a flat `<select>`. The persisted value stays the flat model
10
10
  * id. `value === ''` renders nothing selected (callers that support an
@@ -781,6 +781,12 @@ export declare const useDishwasherSetOption: typeof trpc.dishwasher.setOption.us
781
781
  export declare const useDishwasherGetOptions: typeof trpc.dishwasher.getOptions.useQuery;
782
782
  /** Generated alias around `trpc.dishwasher.getStatus.useQuery`. */
783
783
  export declare const useDishwasherGetStatus: typeof trpc.dishwasher.getStatus.useQuery;
784
+ /** Generated alias around `trpc.displayPalette.getPalette.useQuery`. */
785
+ export declare const useDisplayPaletteGetPalette: typeof trpc.displayPalette.getPalette.useQuery;
786
+ /** Generated alias around `trpc.displayPalette.listPresets.useQuery`. */
787
+ export declare const useDisplayPaletteListPresets: typeof trpc.displayPalette.listPresets.useQuery;
788
+ /** Generated alias around `trpc.displayPalette.setPalette.useMutation`. */
789
+ export declare const useDisplayPaletteSetPalette: typeof trpc.displayPalette.setPalette.useMutation;
784
790
  /** Generated alias around `trpc.doorbell.getStatus.useQuery`. */
785
791
  export declare const useDoorbellGetStatus: typeof trpc.doorbell.getStatus.useQuery;
786
792
  /** Generated alias around `trpc.enumSensor.getStatus.useQuery`. */
@@ -3,7 +3,7 @@ import type { StationaryOverlayBox } from "@camstack/types";
3
3
  * The ONE route this hook needs.
4
4
  *
5
5
  * Deliberately NOT the device proxy. The proxy exposes only the caps BOUND to
6
- * a device, and `zone-analytics` is not one of them — on device 617 the
6
+ * a device, and `zone-analytics` is not one of them — on device 102 the
7
7
  * bindings are `pipeline-analytics` and `motion-zones`. Reading the census
8
8
  * through `dev?.zoneAnalytics?.…` therefore resolved to `undefined`, the hook
9
9
  * returned an empty census, and the overlay drew nothing while reporting