@camstack/ui-library 1.2.305 → 1.2.307

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 (37) hide show
  1. package/dist/{MotionZonesSettings-C3Tj12yc.js → MotionZonesSettings-DR1g9ja3.js} +1 -1
  2. package/dist/{PrivacyMaskSettings-C9wfHkiB.js → PrivacyMaskSettings-CtetT6Jl.js} +1 -1
  3. package/dist/{SceneMonitorEditor-30H29vN4.js → SceneMonitorEditor-BQhVO2F2.js} +1 -1
  4. package/dist/composites/cap-settings/EventHeatmap.d.ts +8 -2
  5. package/dist/composites/charts/BarSeries.d.ts +49 -0
  6. package/dist/composites/charts/Sparkline.d.ts +26 -0
  7. package/dist/composites/charts/StateTimeline.d.ts +47 -0
  8. package/dist/composites/charts/TimeSeriesChart.d.ts +48 -0
  9. package/dist/composites/charts/bar-series-model.d.ts +25 -0
  10. package/dist/composites/charts/chart-data.d.ts +87 -0
  11. package/dist/composites/charts/chart-frame.d.ts +53 -0
  12. package/dist/composites/charts/chart-palette.d.ts +46 -0
  13. package/dist/composites/charts/chart-scale.d.ts +29 -0
  14. package/dist/composites/charts/chart-uplot.d.ts +44 -0
  15. package/dist/composites/charts/chart-window.d.ts +19 -0
  16. package/dist/composites/charts/index.d.ts +16 -0
  17. package/dist/composites/charts/time-series-model.d.ts +47 -0
  18. package/dist/composites/charts/uplot-host.d.ts +34 -0
  19. package/dist/composites/device-history/DeviceHistoryView.d.ts +26 -0
  20. package/dist/composites/device-history/HistoryChart.d.ts +31 -0
  21. package/dist/composites/device-history/HistoryWindowBar.d.ts +16 -0
  22. package/dist/composites/device-history/history-model.d.ts +121 -0
  23. package/dist/composites/device-history/history-reads.d.ts +43 -0
  24. package/dist/composites/device-history/history-selection.d.ts +55 -0
  25. package/dist/composites/device-history/history-window.d.ts +31 -0
  26. package/dist/composites/device-history/index.d.ts +14 -0
  27. package/dist/composites/device-history/use-device-history.d.ts +37 -0
  28. package/dist/composites/device-history/use-history-panels.d.ts +10 -0
  29. package/dist/composites/index.d.ts +2 -0
  30. package/dist/{icons-B1AFXUaZ.cjs → icons-BTux33dH.cjs} +2 -35
  31. package/dist/{icons-BT8c2hxp.js → icons-D178phML.js} +1 -34
  32. package/dist/index.cjs +3172 -45
  33. package/dist/index.js +3094 -52
  34. package/dist/uPlot.esm-BbxBUnav.cjs +3767 -0
  35. package/dist/uPlot.esm-C_8LiAPm.js +3767 -0
  36. package/package.json +2 -1
  37. package/src/tailwind/camstack-theme.css +104 -2
@@ -0,0 +1,26 @@
1
+ /**
2
+ * DeviceHistoryView — a device's recorded history (device-history, D850):
3
+ * the device page's History tab, and — with `fixedWindow="24h"` — the last
4
+ * day on a camera's Live Stats tab. One code path for both.
5
+ *
6
+ * Grouping mirrors the State panel: one collapsible section per capability
7
+ * (catalog order), then per producer addon; inside, one chart per unit and
8
+ * one timeline per state. Every chart shares one cursor. A chart's ⋯ menu
9
+ * opens its series on the History page or hides it (remembered in the
10
+ * user's account preferences).
11
+ *
12
+ * Absent and pending are different screens (D315): device-history not
13
+ * installed, the list not answered yet, and "nothing recorded" each say so.
14
+ */
15
+ import { type JSX } from "react";
16
+ import { type HistoryWindowId } from "./history-window";
17
+ export interface DeviceHistoryViewProps {
18
+ readonly deviceId: number;
19
+ /** A fixed window with no window controls (the Live Stats tab's last day). */
20
+ readonly fixedWindow?: Exclude<HistoryWindowId, "custom">;
21
+ /** In-app navigation (react-router); default a page load under the mount. */
22
+ readonly onNavigate?: (path: string) => void;
23
+ }
24
+ /** `climate-control` → `Climate control`. */
25
+ export declare function humanizeName(name: string): string;
26
+ export declare function DeviceHistoryView({ deviceId, fixedWindow, onNavigate }: DeviceHistoryViewProps): JSX.Element;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * One chart of a device's History view, from its spec and the reads.
3
+ * Lines → `TimeSeriesChart`, states → `StateTimeline`, energy → `BarSeries`
4
+ * with the window total, occupancy → one `TimeSeriesChart` of every
5
+ * (zone × class) scope with zone and class filters.
6
+ *
7
+ * A read that failed says so in place of the chart; a read that answered no
8
+ * point is the empty state — never a flat zero.
9
+ */
10
+ import { type JSX, type ReactNode } from "react";
11
+ import type { DeviceHistoryQueryManyEntry } from "@camstack/types";
12
+ import { type UiTextFn } from "../../contexts/ui-text";
13
+ import { type HistoryChartSpec } from "./history-model";
14
+ import type { HistoryReads } from "./use-device-history";
15
+ import type { HistoryWindow } from "./history-window";
16
+ export interface HistoryChartProps {
17
+ readonly spec: HistoryChartSpec;
18
+ /** Entry for a series key (all scopes), current and previous period. */
19
+ readonly entryFor: (key: string, previous: boolean) => DeviceHistoryQueryManyEntry | undefined;
20
+ readonly reads: HistoryReads | null;
21
+ readonly window: HistoryWindow;
22
+ readonly compare: boolean;
23
+ readonly syncKey: string;
24
+ readonly actions?: ReactNode;
25
+ }
26
+ /** Operator words for a boolean field's two states. */
27
+ export declare function booleanLabels(key: string, t: UiTextFn): {
28
+ readonly on: string;
29
+ readonly off: string;
30
+ };
31
+ export declare function HistoryChart({ spec, entryFor, reads, window, compare, syncKey, actions }: HistoryChartProps): JSX.Element;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The window controls on top of a History view: 24h | 7d | 30d | 1y | custom,
3
+ * a custom from/to when picked, and "compare with previous period".
4
+ */
5
+ import { type JSX } from "react";
6
+ import type { CustomWindow, HistoryWindowId } from "./history-window";
7
+ export interface HistoryWindowBarProps {
8
+ readonly value: HistoryWindowId;
9
+ readonly onChange: (id: HistoryWindowId) => void;
10
+ readonly custom: CustomWindow | null;
11
+ readonly onCustomChange: (w: CustomWindow) => void;
12
+ /** Omit to hide the compare control. */
13
+ readonly compare?: boolean;
14
+ readonly onCompareChange?: (on: boolean) => void;
15
+ }
16
+ export declare function HistoryWindowBar({ value, onChange, custom, onCustomChange, compare, onCompareChange }: HistoryWindowBarProps): JSX.Element;
@@ -0,0 +1,121 @@
1
+ /**
2
+ * The pure half of a device's History view: which charts a device's series
3
+ * make, in which sections, and how a `query` answer becomes chart data.
4
+ *
5
+ * Grouping mirrors the State panel: one section per capability in
6
+ * `HISTORY_CATALOG` order (its fields in catalog order), then one section per
7
+ * producer addon, sorted. Inside a section: one line chart per UNIT (never
8
+ * two units on one axis), one state timeline per boolean or enum, the
9
+ * derived energy as bars. A camera's occupancy is ONE chart of every
10
+ * (zone × class) scope.
11
+ */
12
+ import { type DeviceHistoryQueryResult, type DeviceHistorySeriesInfo } from "@camstack/types";
13
+ import type { BarBucket } from "../charts/bar-series-model";
14
+ import type { StateSegment, TimePoint } from "../charts/chart-data";
15
+ /** The producer series a camera's occupancy chart reads. */
16
+ export declare const OCCUPANCY_KEY = "addon:pipeline-analytics/occupancy";
17
+ export type HistoryChartSpec = {
18
+ readonly type: "lines";
19
+ readonly id: string;
20
+ readonly title: string;
21
+ readonly unit: string | null;
22
+ readonly series: readonly DeviceHistorySeriesInfo[];
23
+ } | {
24
+ readonly type: "states";
25
+ readonly id: string;
26
+ readonly title: string;
27
+ readonly series: DeviceHistorySeriesInfo;
28
+ } | {
29
+ readonly type: "energy";
30
+ readonly id: string;
31
+ readonly title: string;
32
+ readonly series: DeviceHistorySeriesInfo;
33
+ } | {
34
+ readonly type: "occupancy";
35
+ readonly id: string;
36
+ readonly title: string;
37
+ readonly series: readonly DeviceHistorySeriesInfo[];
38
+ };
39
+ export interface HistorySection {
40
+ readonly id: string;
41
+ /** `cap` — a capability's fields; `producer` — an addon's declared series. */
42
+ readonly kind: "cap" | "producer";
43
+ /** Capability name or producer addon id. */
44
+ readonly name: string;
45
+ readonly charts: readonly HistoryChartSpec[];
46
+ }
47
+ /** `cap:<capName>.<fieldPath>` → its parts; `null` for any other key. */
48
+ export declare function parseCapKey(key: string): {
49
+ readonly cap: string;
50
+ readonly field: string;
51
+ } | null;
52
+ /** `addon:<addonId>/<name>` → its parts; `null` for any other key. */
53
+ export declare function parseProducerKey(key: string): {
54
+ readonly addonId: string;
55
+ readonly name: string;
56
+ } | null;
57
+ /**
58
+ * Group a device's series into sections. Energy (a derived key) joins the
59
+ * `power-meter` section when the device has one, else gets its own.
60
+ */
61
+ export declare function groupDeviceSeries(series: readonly DeviceHistorySeriesInfo[], capTitle: (cap: string) => string): readonly HistorySection[];
62
+ /** The unique keys a set of charts reads (one `queryMany` item each: every scope comes back). */
63
+ export declare function chartKeys(charts: readonly HistoryChartSpec[]): readonly string[];
64
+ /** One series of a `query` answer, found by scope. */
65
+ export declare function seriesOf(result: DeviceHistoryQueryResult | undefined, scope: string): DeviceHistoryQueryResult["series"][number] | undefined;
66
+ /**
67
+ * Line points for a gauge or counter. A rolled-up answer carries its
68
+ * min/max (a band). A CAP series is change-only and held, so the window
69
+ * opens on the value in force (`before`); a producer's buckets are not held
70
+ * and an absent bucket is a hole.
71
+ */
72
+ export declare function linePoints(info: DeviceHistorySeriesInfo, result: DeviceHistoryQueryResult | undefined, from: number): {
73
+ readonly points: readonly TimePoint[];
74
+ readonly gapMs: number | undefined;
75
+ readonly held: boolean;
76
+ };
77
+ /** Shift every point by `shiftMs` (a previous period laid over the current one). */
78
+ export declare function shiftPoints(points: readonly TimePoint[], shiftMs: number): readonly TimePoint[];
79
+ /** The state names a boolean series takes, `false` first. */
80
+ export declare const BOOLEAN_STATES: readonly ["false", "true"];
81
+ /**
82
+ * A state series as segments plus the exact time spent in each state.
83
+ *
84
+ * Raw points are changes. A rollup bucket is drawn in its DOMINANT state
85
+ * (the one held longest in it), while the totals add the bucket's real
86
+ * per-state milliseconds — so "open 2h 14m" stays exact at any zoom.
87
+ */
88
+ export declare function stateRow(info: DeviceHistorySeriesInfo, result: DeviceHistoryQueryResult | undefined, from: number, to: number): {
89
+ readonly segments: readonly StateSegment[];
90
+ readonly totals: ReadonlyMap<string, number>;
91
+ readonly states: readonly string[];
92
+ };
93
+ /** Energy bars: one bucket per point, the kWh used in it (`delta`). */
94
+ export declare function energyBuckets(result: DeviceHistoryQueryResult | undefined): {
95
+ readonly buckets: readonly BarBucket[];
96
+ readonly bucketMs: number;
97
+ };
98
+ export interface OccupancyScopeLine {
99
+ readonly scope: string;
100
+ /** `''` = the whole frame. */
101
+ readonly zoneId: string;
102
+ /** `undefined` = every class. */
103
+ readonly className: string | undefined;
104
+ }
105
+ export declare function occupancyLines(series: readonly DeviceHistorySeriesInfo[]): readonly OccupancyScopeLine[];
106
+ /** The filter values an occupancy chart offers: zones and classes that exist. */
107
+ export declare function occupancyFacets(lines: readonly OccupancyScopeLine[]): {
108
+ readonly zones: readonly string[];
109
+ readonly classes: readonly string[];
110
+ };
111
+ /** `null` = all. */
112
+ export interface OccupancyFilter {
113
+ readonly zone: string | null;
114
+ readonly className: string | null;
115
+ }
116
+ /**
117
+ * The lines a filter keeps. With no class picked the per-zone AGGREGATE lines
118
+ * show (summing classes again would double count); a class shows that class
119
+ * in every (or the picked) zone.
120
+ */
121
+ export declare function filterOccupancyLines(lines: readonly OccupancyScopeLine[], filter: OccupancyFilter): readonly OccupancyScopeLine[];
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Batched history reads. `queryMany` answers up to 24 reads over one window
3
+ * in one call — but it is admin-only (its subjects are nested where the
4
+ * device scope gate cannot see them). A principal it refuses reads each
5
+ * DEVICE series through `query` instead; a node series has no other door and
6
+ * is reported as refused.
7
+ *
8
+ * Every item gets an entry, in order: an answer, or the error that item met.
9
+ * A failed item never hides the others, and is never an empty series.
10
+ */
11
+ import { type DeviceHistoryQueryManyEntry, type DeviceHistoryQueryManyItem, type DeviceHistoryQueryResult } from "@camstack/types";
12
+ export interface HistoryReadWindow {
13
+ readonly from: number;
14
+ readonly to: number;
15
+ readonly maxPoints?: number;
16
+ }
17
+ /** The two doors `readHistory` uses — the tRPC client in the app, a fake in a spec. */
18
+ export interface HistoryReader {
19
+ queryMany(input: {
20
+ readonly items: DeviceHistoryQueryManyItem[];
21
+ readonly from: number;
22
+ readonly to: number;
23
+ readonly resolution: "auto";
24
+ readonly maxPoints: number;
25
+ }): Promise<{
26
+ readonly results: readonly DeviceHistoryQueryManyEntry[];
27
+ }>;
28
+ query(input: {
29
+ readonly deviceId: number;
30
+ readonly key: string;
31
+ readonly scope?: string;
32
+ readonly from: number;
33
+ readonly to: number;
34
+ readonly resolution: "auto";
35
+ readonly maxPoints: number;
36
+ }): Promise<DeviceHistoryQueryResult>;
37
+ }
38
+ /** Split into batches of at most `size`. */
39
+ export declare function chunk<T>(items: readonly T[], size: number): readonly (readonly T[])[];
40
+ /** Did the hub refuse this principal (rather than fail)? */
41
+ export declare function isRefusal(err: unknown): boolean;
42
+ /** Read every item over one window; one entry per item, in order. */
43
+ export declare function readHistory(reader: HistoryReader, items: readonly DeviceHistoryQueryManyItem[], window: HistoryReadWindow): Promise<readonly DeviceHistoryQueryManyEntry[]>;
@@ -0,0 +1,55 @@
1
+ import { type HistoryWindowId } from "./history-window";
2
+ export type HistorySubject = {
3
+ readonly kind: "device";
4
+ readonly deviceId: number;
5
+ } | {
6
+ readonly kind: "node";
7
+ readonly nodeId: string;
8
+ };
9
+ export interface HistorySeriesRef {
10
+ readonly subject: HistorySubject;
11
+ readonly key: string;
12
+ readonly scope: string;
13
+ }
14
+ /** The most series one overlay may carry — one `queryMany` batch. */
15
+ export declare const HISTORY_SELECTION_MAX = 24;
16
+ /** Stable identity of a series ref (React key, dedup, colour slot). */
17
+ export declare function seriesRefId(ref: HistorySeriesRef): string;
18
+ /** One `?s=` value: `d,<deviceId>,<key>,<scope>` or `n,<nodeId>,<key>,<scope>`, each part URI-encoded. */
19
+ export declare function encodeSeriesRef(ref: HistorySeriesRef): string;
20
+ export declare function decodeSeriesRef(raw: string): HistorySeriesRef | null;
21
+ /** Unique refs, in order, capped at {@link HISTORY_SELECTION_MAX}. */
22
+ export declare function normalizeSelection(refs: readonly HistorySeriesRef[]): readonly HistorySeriesRef[];
23
+ /** The History page path showing `refs` over `window`. */
24
+ export declare function historyPageHref(refs: readonly HistorySeriesRef[], window?: HistoryWindowId): string;
25
+ /** The cross-device History page's route. */
26
+ export declare const HISTORY_PAGE_PATH = "/system/history";
27
+ /** The account preference namespace that holds saved panels and hidden charts. */
28
+ export declare const HISTORY_PANELS_NAMESPACE = "admin.history-panels";
29
+ export interface HistoryPanel {
30
+ readonly id: string;
31
+ readonly name: string;
32
+ readonly window: HistoryWindowId;
33
+ readonly selection: readonly HistorySeriesRef[];
34
+ }
35
+ export interface HistoryPanelsValue {
36
+ readonly version: 1;
37
+ readonly panels: readonly HistoryPanel[];
38
+ /** Chart ids an operator hid on a device's History tab, per device id. */
39
+ readonly hidden: Readonly<Record<string, readonly string[]>>;
40
+ }
41
+ export declare const EMPTY_HISTORY_PANELS: HistoryPanelsValue;
42
+ /**
43
+ * Read a stored row's value. A row this client cannot read (another
44
+ * version, a hand edit) is answered as empty rather than throwing — and the
45
+ * caller must not write over it blindly: `parsed: false` says so.
46
+ */
47
+ export declare function readHistoryPanels(value: unknown): {
48
+ readonly value: HistoryPanelsValue;
49
+ readonly parsed: boolean;
50
+ };
51
+ /** A copy of `value` with chart `chartId` hidden (or shown again) on device `deviceId`. */
52
+ export declare function withHiddenChart(value: HistoryPanelsValue, deviceId: number, chartId: string, hidden: boolean): HistoryPanelsValue;
53
+ /** A copy of `value` with `panel` saved (replacing one with the same id). */
54
+ export declare function withPanel(value: HistoryPanelsValue, panel: HistoryPanel): HistoryPanelsValue;
55
+ export declare function withoutPanel(value: HistoryPanelsValue, panelId: string): HistoryPanelsValue;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * The time windows a history view offers, and the "previous period" a
3
+ * comparison reads. Pure: the caller supplies `now`.
4
+ */
5
+ export type HistoryWindowId = "24h" | "7d" | "30d" | "1y" | "custom";
6
+ export declare const HISTORY_WINDOW_IDS: readonly ["24h", "7d", "30d", "1y", "custom"];
7
+ export declare const HISTORY_WINDOW_MS: Readonly<Record<Exclude<HistoryWindowId, "custom">, number>>;
8
+ export interface HistoryWindow {
9
+ readonly from: number;
10
+ readonly to: number;
11
+ }
12
+ export interface CustomWindow {
13
+ readonly from: number;
14
+ readonly to: number;
15
+ }
16
+ export declare function isHistoryWindowId(v: string | null | undefined): v is HistoryWindowId;
17
+ /**
18
+ * The window a preset means at `now`. `custom` without a valid range (from
19
+ * before to) falls back to the last 24 hours rather than an empty window.
20
+ */
21
+ export declare function resolveHistoryWindow(id: HistoryWindowId, now: number, custom?: CustomWindow | null): HistoryWindow;
22
+ /** The period of the same length just before `w`, and the shift that lays it over `w`. */
23
+ export declare function previousWindow(w: HistoryWindow): {
24
+ readonly window: HistoryWindow;
25
+ readonly shiftMs: number;
26
+ };
27
+ /** Encode a custom range for the URL: `<fromMs>-<toMs>`. */
28
+ export declare function encodeCustomWindow(w: CustomWindow): string;
29
+ export declare function decodeCustomWindow(raw: string | null | undefined): CustomWindow | null;
30
+ /** Milliseconds a rollup bucket of a resolution covers (`1d` is nominal across DST). */
31
+ export declare const RESOLUTION_BUCKET_MS: Readonly<Record<"5m" | "1h" | "1d", number>>;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Device history views (D850, D896): the device History tab / Live Stats
3
+ * last day (`DeviceHistoryView`) and the building blocks the cross-device
4
+ * History page composes.
5
+ */
6
+ export { DeviceHistoryView, humanizeName, type DeviceHistoryViewProps } from "./DeviceHistoryView";
7
+ export { HistoryChart, booleanLabels, type HistoryChartProps } from "./HistoryChart";
8
+ export { HistoryWindowBar, type HistoryWindowBarProps } from "./HistoryWindowBar";
9
+ export { BOOLEAN_STATES, OCCUPANCY_KEY, chartKeys, energyBuckets, filterOccupancyLines, groupDeviceSeries, linePoints, occupancyFacets, occupancyLines, parseCapKey, parseProducerKey, shiftPoints, stateRow, type HistoryChartSpec, type HistorySection, type OccupancyFilter, type OccupancyScopeLine } from "./history-model";
10
+ export { chunk, isRefusal, readHistory, type HistoryReader, type HistoryReadWindow } from "./history-reads";
11
+ export { EMPTY_HISTORY_PANELS, HISTORY_PAGE_PATH, HISTORY_PANELS_NAMESPACE, HISTORY_SELECTION_MAX, decodeSeriesRef, encodeSeriesRef, historyPageHref, normalizeSelection, readHistoryPanels, seriesRefId, withHiddenChart, withPanel, withoutPanel, type HistoryPanel, type HistoryPanelsValue, type HistorySeriesRef, type HistorySubject } from "./history-selection";
12
+ export { HISTORY_WINDOW_IDS, HISTORY_WINDOW_MS, RESOLUTION_BUCKET_MS, decodeCustomWindow, encodeCustomWindow, isHistoryWindowId, previousWindow, resolveHistoryWindow, type CustomWindow, type HistoryWindow, type HistoryWindowId } from "./history-window";
13
+ export { anchorNow, readItemId, useDeviceSeriesList, useHistoryReader, useHistoryReads, type HistoryReads, type HistoryStage } from "./use-device-history";
14
+ export { useHistoryPanels, type HistoryPanelsState } from "./use-history-panels";
@@ -0,0 +1,37 @@
1
+ import type { DeviceHistoryQueryManyEntry, DeviceHistoryQueryManyItem, DeviceHistorySeriesInfo } from "@camstack/types";
2
+ import { type CapabilityPresence } from "../../hooks/use-capability-presence";
3
+ import { type HistoryReader } from "./history-reads";
4
+ import { type HistoryWindow } from "./history-window";
5
+ /** How a stage of the view stands. */
6
+ export type HistoryStage<T> = {
7
+ readonly status: "pending";
8
+ } | {
9
+ readonly status: "error";
10
+ readonly error: string;
11
+ } | {
12
+ readonly status: "ok";
13
+ readonly data: T;
14
+ };
15
+ /**
16
+ * The instant a window ends at, rounded so the query key is stable between
17
+ * renders and the view refreshes at a pace its width justifies.
18
+ */
19
+ export declare function anchorNow(now: number, spanMs: number): number;
20
+ /** The tRPC client as the two doors `readHistory` needs. */
21
+ export declare function useHistoryReader(): HistoryReader;
22
+ /** A device's series list, gated on device-history being present. */
23
+ export declare function useDeviceSeriesList(deviceId: number): {
24
+ readonly presence: CapabilityPresence;
25
+ readonly list: HistoryStage<readonly DeviceHistorySeriesInfo[]>;
26
+ };
27
+ export interface HistoryReads {
28
+ /** Entry per item id (see {@link readItemId}). */
29
+ readonly current: ReadonlyMap<string, DeviceHistoryQueryManyEntry>;
30
+ /** The previous period, when comparing; shifted by `shiftMs` to overlay. */
31
+ readonly previous: ReadonlyMap<string, DeviceHistoryQueryManyEntry> | null;
32
+ readonly shiftMs: number;
33
+ }
34
+ /** Identity of a read item: subject + key (+ scope when narrowed). */
35
+ export declare function readItemId(item: DeviceHistoryQueryManyItem): string;
36
+ /** Read `items` over `window` (and the previous period when `compare`). */
37
+ export declare function useHistoryReads(items: readonly DeviceHistoryQueryManyItem[], window: HistoryWindow, compare: boolean, enabled?: boolean): HistoryStage<HistoryReads>;
@@ -0,0 +1,10 @@
1
+ import { type HistoryPanelsValue } from "./history-selection";
2
+ export interface HistoryPanelsState {
3
+ /** `pending` until the row answered; `error` when the read failed (never "no panels"). */
4
+ readonly status: "pending" | "error" | "ok";
5
+ readonly value: HistoryPanelsValue;
6
+ /** False when the stored row could not be read: writing would destroy it. */
7
+ readonly writable: boolean;
8
+ readonly update: (change: (current: HistoryPanelsValue) => HistoryPanelsValue) => Promise<void>;
9
+ }
10
+ export declare function useHistoryPanels(): HistoryPanelsState;
@@ -223,3 +223,5 @@ export * from "./device-picker/index.js";
223
223
  export * from "./unit-picker/index.js";
224
224
  export * from "./placeholder-field/index.js";
225
225
  export { type RetrainReviewBadgeKind, type RetrainReviewBadgeLook, type RetrainReviewBadgeProps, RetrainReviewBadge, retrainReviewBadgeLook } from "./training/retrain-review-badge";
226
+ export * from "./charts/index.js";
227
+ export * from "./device-history/index.js";
@@ -7414,19 +7414,6 @@ var ChartGantt = require_createLucideIcon.createLucideIcon("chart-gantt", [
7414
7414
  * This source code is licensed under the ISC license.
7415
7415
  * See the LICENSE file in the root directory of this source tree.
7416
7416
  */
7417
- var ChartLine = require_createLucideIcon.createLucideIcon("chart-line", [["path", {
7418
- d: "M3 3v16a2 2 0 0 0 2 2h16",
7419
- key: "c24i48"
7420
- }], ["path", {
7421
- d: "m19 9-5 5-4-4-3 3",
7422
- key: "2osh9i"
7423
- }]]);
7424
- /**
7425
- * @license lucide-react v0.576.0 - ISC
7426
- *
7427
- * This source code is licensed under the ISC license.
7428
- * See the LICENSE file in the root directory of this source tree.
7429
- */
7430
7417
  var ChartNetwork = require_createLucideIcon.createLucideIcon("chart-network", [
7431
7418
  ["path", {
7432
7419
  d: "m13.11 7.664 1.78 2.672",
@@ -18204,26 +18191,6 @@ var Highlighter = require_createLucideIcon.createLucideIcon("highlighter", [["pa
18204
18191
  * This source code is licensed under the ISC license.
18205
18192
  * See the LICENSE file in the root directory of this source tree.
18206
18193
  */
18207
- var History = require_createLucideIcon.createLucideIcon("history", [
18208
- ["path", {
18209
- d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",
18210
- key: "1357e3"
18211
- }],
18212
- ["path", {
18213
- d: "M3 3v5h5",
18214
- key: "1xhq8a"
18215
- }],
18216
- ["path", {
18217
- d: "M12 7v5l4 2",
18218
- key: "1fdv2h"
18219
- }]
18220
- ]);
18221
- /**
18222
- * @license lucide-react v0.576.0 - ISC
18223
- *
18224
- * This source code is licensed under the ISC license.
18225
- * See the LICENSE file in the root directory of this source tree.
18226
- */
18227
18194
  var HopOff = require_createLucideIcon.createLucideIcon("hop-off", [
18228
18195
  ["path", {
18229
18196
  d: "M10.82 16.12c1.69.6 3.91.79 5.18.85.28.01.53-.09.7-.27",
@@ -38164,7 +38131,7 @@ exports.ChartColumnDecreasing = ChartColumnDecreasing;
38164
38131
  exports.ChartColumnIncreasing = ChartColumnIncreasing;
38165
38132
  exports.ChartColumnStacked = ChartColumnStacked;
38166
38133
  exports.ChartGantt = ChartGantt;
38167
- exports.ChartLine = ChartLine;
38134
+ exports.ChartLine = require_index.ChartLine;
38168
38135
  exports.ChartNetwork = ChartNetwork;
38169
38136
  exports.ChartNoAxesColumn = ChartNoAxesColumn;
38170
38137
  exports.ChartNoAxesColumnDecreasing = ChartNoAxesColumnDecreasing;
@@ -38662,7 +38629,7 @@ exports.Heater = require_index.Heater;
38662
38629
  exports.Helicopter = Helicopter;
38663
38630
  exports.Hexagon = require_mic_off.Hexagon;
38664
38631
  exports.Highlighter = Highlighter;
38665
- exports.History = History;
38632
+ exports.History = require_index.History;
38666
38633
  exports.Hop = Hop;
38667
38634
  exports.HopOff = HopOff;
38668
38635
  exports.Hospital = Hospital;
@@ -1,7 +1,7 @@
1
1
  import { t as createLucideIcon } from "./createLucideIcon-kNomBP27.js";
2
2
  import { n as Hexagon, t as MicOff } from "./mic-off-C2VTYr91.js";
3
3
  import { t as Settings2 } from "./settings-2-jT1iBqHD.js";
4
- import { $ as ShieldOff, $n as Clock, $t as LoaderCircle, A as TrainFront, An as Feather, Ar as Bell, At as Pause, B as SunMedium, Bn as DoorClosed, Br as ArrowUp, Bt as MonitorPlay, C as Undo2, Cn as Funnel, Cr as Bug, Ct as Play, D as TrendingDown, Dn as FlashlightOff, Dr as Blinds, Dt as Phone, E as TriangleAlert, En as Flashlight, Er as Bone, Et as Pin, F as Thermometer, Fn as EllipsisVertical, Fr as BatteryLow, Ft as Move, G as Snowflake, Gn as Copy, Gr as ArrowDownToLine, Gt as Menu, H as Square, Hn as Database, Hr as ArrowRight, Ht as Minimize2, I as Target, In as Droplets, Ir as BatteryFull, It as MoveVertical, J as SkipForward, Jn as CloudSun, Jr as Activity, Jt as MapPin, K as Smartphone, Kn as Cog, Kr as AlarmSmoke, Kt as Megaphone, L as Tag, Ln as Droplet, Lr as Bath, Lt as MoveHorizontal, M as ToggleRight, Mn as Eye, Mr as Battery, Mt as Network, N as ToggleLeft, Nn as EyeOff, Nr as BatteryWarning, Nt as Navigation, O as TrendingUp, On as Flame, Or as Bird, Ot as Pencil, P as Timer, Pn as ExternalLink, Pr as BatteryMedium, Pt as Music, Q as Shield, Qn as CloudFog, Qt as LocateFixed, R as Sunrise, Rn as Download, Rr as Ban, Rt as MousePointerClick, S as Unlink2, Sn as Gamepad2, Sr as Bus, St as Plus, T as Truck, Tn as FlaskConical, Tr as Bot, Tt as Pipette, U as Sprout, Un as Crosshair, Ur as ArrowLeft, Ut as Mic, V as Star, Vn as Dog, Vr as ArrowUpToLine, Vt as Minus, W as Sparkles, Wn as Cpu, Wr as ArrowDown, Wt as MessageSquare, X as Siren, Xn as CloudRain, Xt as Lock, Y as SkipBack, Yn as CloudSnow, Yt as Mail, Z as Ship, Zn as CloudLightning, Zt as LockOpen, _ as UtensilsCrossed, _n as Hammer, _r as Cat, _t as QrCode, a as Wrench, an as LayoutGrid, ar as CirclePause, at as Search, b as UserCheck, bn as GraduationCap, br as Camera, bt as PowerOff, c as Wifi, cr as CircleCheckBig, ct as Save, d as WifiLow, dn as ImageOff, dr as ChevronsDownUp, dt as RotateCw, en as List, er as Clapperboard, et as ShieldCheck, f as WifiHigh, fn as House, fr as ChevronUp, ft as RotateCcw, g as Vibrate, gn as Hand, gr as Check, gt as Radar, h as Volume2, hn as HardDrive, hr as ChevronDown, ht as RadioTower, i as X, in as Leaf, ir as CirclePlus, it as Server, j as Tractor, jn as Fan, jr as BellRing, jt as Package, k as Trash2, kn as Film, kr as Bike, kt as PawPrint, l as WifiZero, ln as Inbox, lr as CircleAlert, lt as Sailboat, m as VolumeX, mn as Hash, mr as ChevronLeft, mt as Radio, n as ZoomIn, nn as Link2, nr as CircleStop, nt as Share2, o as Workflow, on as Laugh, or as CircleDot, ot as ScrollText, p as Waves, pn as Heater, pr as ChevronRight, pt as RefreshCw, q as SlidersHorizontal, qn as Cloud, qr as AirVent, qt as Maximize2, r as Zap, rn as Lightbulb, rr as CircleQuestionMark, rt as Settings, s as Wind, sn as Info, sr as CircleCheck, st as Scan, t as ZoomOut, tn as ListChecks, tr as CircleX, tt as ShieldAlert, u as WifiOff, un as Image, ur as ChevronsUpDown, ut as Route, v as Users, vn as GripHorizontal, vr as Cast, vt as Puzzle, w as Type, wn as Footprints, wr as Box, wt as Plane, x as Upload, xn as Gauge, xr as Cable, xt as Plug, y as User, yn as Grid2x2, yr as Car, yt as Power, z as Sun, zn as DoorOpen, zr as Baby, zt as Moon } from "./index.js";
4
+ import { $ as ShieldOff, $n as CloudFog, $t as LoaderCircle, A as TrainFront, An as Film, Ar as Bird, At as Pause, B as SunMedium, Bn as DoorOpen, Br as Ban, Bt as MonitorPlay, C as Undo2, Cn as Gamepad2, Cr as Cable, Ct as Play, D as TrendingDown, Dn as Flashlight, Dr as Bot, Dt as Phone, E as TriangleAlert, En as FlaskConical, Er as Box, Et as Pin, F as Thermometer, Fn as ExternalLink, Fr as BatteryWarning, Ft as Move, G as Snowflake, Gn as Cpu, Gr as ArrowLeft, Gt as Menu, H as Square, Hn as Dog, Hr as ArrowUp, Ht as Minimize2, I as Target, In as EllipsisVertical, Ir as BatteryMedium, It as MoveVertical, J as SkipForward, Jn as Cloud, Jr as AlarmSmoke, Jt as MapPin, K as Smartphone, Kn as Copy, Kr as ArrowDown, Kt as Megaphone, L as Tag, Ln as Droplets, Lr as BatteryLow, Lt as MoveHorizontal, M as ToggleRight, Mn as Fan, Mr as Bell, Mt as Network, N as ToggleLeft, Nn as Eye, Nr as BellRing, Nt as Navigation, O as TrendingUp, On as FlashlightOff, Or as Bone, Ot as Pencil, P as Timer, Pn as EyeOff, Pr as Battery, Pt as Music, Q as Shield, Qn as CloudLightning, Qt as LocateFixed, R as Sunrise, Rn as Droplet, Rr as BatteryFull, Rt as MousePointerClick, S as Unlink2, Sn as Gauge, Sr as Camera, St as Plus, T as Truck, Tn as Footprints, Tr as Bug, Tt as Pipette, U as Sprout, Un as Database, Ur as ArrowUpToLine, Ut as Mic, V as Star, Vn as DoorClosed, Vr as Baby, Vt as Minus, W as Sparkles, Wn as Crosshair, Wr as ArrowRight, Wt as MessageSquare, X as Siren, Xn as CloudSnow, Xr as Activity, Xt as Lock, Y as SkipBack, Yn as CloudSun, Yr as AirVent, Yt as Mail, Z as Ship, Zn as CloudRain, Zt as LockOpen, _ as UtensilsCrossed, _n as Hand, _r as Check, _t as QrCode, a as Wrench, an as LayoutGrid, ar as CirclePlus, at as Search, b as UserCheck, bn as Grid2x2, br as Cast, bt as PowerOff, c as Wifi, cr as CircleCheck, ct as Save, d as WifiLow, dn as ImageOff, dr as ChevronsUpDown, dt as RotateCw, en as List, er as Clock, et as ShieldCheck, f as WifiHigh, fn as House, fr as ChevronsDownUp, ft as RotateCcw, g as Vibrate, gn as HardDrive, gr as ChevronDown, gt as Radar, h as Volume2, hn as Hash, hr as ChevronLeft, ht as RadioTower, i as X, in as Leaf, ir as CircleQuestionMark, it as Server, j as Tractor, jn as Feather, jr as Bike, jt as Package, k as Trash2, kn as Flame, kr as Blinds, kt as PawPrint, l as WifiZero, ln as Inbox, lr as CircleCheckBig, lt as Sailboat, m as VolumeX, mn as Heater, mr as ChevronRight, mt as Radio, n as ZoomIn, nn as Link2, nr as CircleX, nt as Share2, o as Workflow, on as Laugh, or as CirclePause, ot as ScrollText, p as Waves, pn as History, pr as ChevronUp, pt as RefreshCw, q as SlidersHorizontal, qn as Cog, qr as ArrowDownToLine, qt as Maximize2, r as Zap, rn as Lightbulb, rr as CircleStop, rt as Settings, s as Wind, sn as Info, sr as CircleDot, st as Scan, t as ZoomOut, tn as ListChecks, tr as Clapperboard, tt as ShieldAlert, u as WifiOff, un as Image, ur as CircleAlert, ut as Route, v as Users, vn as Hammer, vr as ChartLine, vt as Puzzle, w as Type, wn as Funnel, wr as Bus, wt as Plane, x as Upload, xn as GraduationCap, xr as Car, xt as Plug, y as User, yn as GripHorizontal, yr as Cat, yt as Power, z as Sun, zn as Download, zr as Bath, zt as Moon } from "./index.js";
5
5
  /**
6
6
  * @license lucide-react v0.576.0 - ISC
7
7
  *
@@ -7414,19 +7414,6 @@ var ChartGantt = createLucideIcon("chart-gantt", [
7414
7414
  * This source code is licensed under the ISC license.
7415
7415
  * See the LICENSE file in the root directory of this source tree.
7416
7416
  */
7417
- var ChartLine = createLucideIcon("chart-line", [["path", {
7418
- d: "M3 3v16a2 2 0 0 0 2 2h16",
7419
- key: "c24i48"
7420
- }], ["path", {
7421
- d: "m19 9-5 5-4-4-3 3",
7422
- key: "2osh9i"
7423
- }]]);
7424
- /**
7425
- * @license lucide-react v0.576.0 - ISC
7426
- *
7427
- * This source code is licensed under the ISC license.
7428
- * See the LICENSE file in the root directory of this source tree.
7429
- */
7430
7417
  var ChartNetwork = createLucideIcon("chart-network", [
7431
7418
  ["path", {
7432
7419
  d: "m13.11 7.664 1.78 2.672",
@@ -18204,26 +18191,6 @@ var Highlighter = createLucideIcon("highlighter", [["path", {
18204
18191
  * This source code is licensed under the ISC license.
18205
18192
  * See the LICENSE file in the root directory of this source tree.
18206
18193
  */
18207
- var History = createLucideIcon("history", [
18208
- ["path", {
18209
- d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",
18210
- key: "1357e3"
18211
- }],
18212
- ["path", {
18213
- d: "M3 3v5h5",
18214
- key: "1xhq8a"
18215
- }],
18216
- ["path", {
18217
- d: "M12 7v5l4 2",
18218
- key: "1fdv2h"
18219
- }]
18220
- ]);
18221
- /**
18222
- * @license lucide-react v0.576.0 - ISC
18223
- *
18224
- * This source code is licensed under the ISC license.
18225
- * See the LICENSE file in the root directory of this source tree.
18226
- */
18227
18194
  var HopOff = createLucideIcon("hop-off", [
18228
18195
  ["path", {
18229
18196
  d: "M10.82 16.12c1.69.6 3.91.79 5.18.85.28.01.53-.09.7-.27",