@camstack/ui-library 1.2.46 → 1.2.48

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.
@@ -41,5 +41,21 @@ export interface DataTableProps<T> {
41
41
  * card list at any column count.
42
42
  */
43
43
  readonly mobileMode?: TableMobileMode;
44
+ /**
45
+ * Tailwind `max-h-*` class capping the table. The rows then scroll INSIDE
46
+ * this container and the column header is pinned to its top; the page around
47
+ * it does not move. Absent (default) = the table is as tall as its rows and
48
+ * the page scrolls. Use {@link TABLE_SCROLL_MAX_H} unless a surface has a
49
+ * reason of its own.
50
+ */
51
+ readonly maxBodyHeight?: string;
44
52
  }
45
- export declare function DataTable<T>({ columns, rows, rowKey, onRowClick, minWidthPx, emptyMessage, className, bordered, rowClassName, mobileMode, }: DataTableProps<T>): import("react").JSX.Element | null;
53
+ /**
54
+ * The default cap for an internally-scrolling table.
55
+ *
56
+ * `60vh` leaves the page header, its filters and its actions on screen at
57
+ * every viewport while still showing ~10 rows — and it is a fraction, so it
58
+ * does not need a breakpoint of its own.
59
+ */
60
+ export declare const TABLE_SCROLL_MAX_H: "max-h-[60vh]";
61
+ export declare function DataTable<T>({ columns, rows, rowKey, onRowClick, minWidthPx, emptyMessage, className, bordered, rowClassName, mobileMode, maxBodyHeight, }: DataTableProps<T>): import("react").JSX.Element | null;
@@ -0,0 +1,37 @@
1
+ import { DeviceType, DeviceSelector } from '@camstack/types';
2
+ /** The device fields this picker reads. */
3
+ export interface SelectorDevice {
4
+ readonly id: number;
5
+ readonly name: string;
6
+ readonly type: DeviceType;
7
+ readonly location: string | null;
8
+ readonly parentDeviceId: number | null;
9
+ }
10
+ export type DeviceSelectorTab = 'all' | 'types' | 'locations' | 'ids';
11
+ interface DeviceSelectorPickerProps {
12
+ readonly value: DeviceSelector;
13
+ readonly onChange: (next: DeviceSelector) => void;
14
+ /**
15
+ * `includeLinked` lives next to the selector because it changes what the
16
+ * selector REACHES, not what it selects. Omit both to hide the toggle
17
+ * (the raw picker renders it per row instead).
18
+ */
19
+ readonly includeLinked?: boolean;
20
+ readonly onIncludeLinkedChange?: (next: boolean) => void;
21
+ /**
22
+ * Ids the CALLER may delegate. `null` = unclamped (admin). A clamped
23
+ * picker hides devices outside the set from the Chosen tab and reports the
24
+ * counts it can actually see.
25
+ */
26
+ readonly clampToDeviceIds?: readonly number[] | null;
27
+ /** Compact spacing for the raw picker's inline row. */
28
+ readonly dense?: boolean;
29
+ }
30
+ /** Human label for a `DeviceType` — 'lawn-mower' → 'Lawn mower'. */
31
+ export declare function deviceTypeLabel(type: string): string;
32
+ /** Which tab a selector belongs to. */
33
+ export declare function tabForSelector(selector: DeviceSelector): DeviceSelectorTab;
34
+ export declare function DeviceSelectorPicker({ value, onChange, includeLinked, onIncludeLinkedChange, clampToDeviceIds, dense, }: DeviceSelectorPickerProps): React.ReactElement;
35
+ /** Summary line for a selector — used by the raw picker's collapsed row. */
36
+ export declare function describeDeviceSelector(selector: DeviceSelector): string;
37
+ export {};
@@ -135,6 +135,8 @@ export { WidgetSlot } from './widget-slot';
135
135
  export type { WidgetSlotProps } from './widget-slot';
136
136
  export { ScopePicker, validateScopes } from './scope-picker';
137
137
  export type { ScopeAccess } from './scope-picker';
138
+ export { DeviceSelectorPicker, describeDeviceSelector, deviceTypeLabel, tabForSelector, } from './device-selector-picker';
139
+ export type { DeviceSelectorTab, SelectorDevice } from './device-selector-picker';
138
140
  export { PtzPanel } from './cap-settings/PtzPanel';
139
141
  export { ConsumablesPanel } from './cap-settings/ConsumablesPanel';
140
142
  export { AutotrackSection } from './cap-settings/AutotrackSection';
@@ -17,9 +17,14 @@ interface ScopePickerProps {
17
17
  export declare function ScopePicker({ value, onChange, clampToParent, emptyHint, }: ScopePickerProps): React.ReactElement;
18
18
  /**
19
19
  * Validation helper. The wire schema (`TokenScopeSchema`) requires every
20
- * scope to carry a non-empty target/targets and `access.length >= 1`.
21
- * Use this before passing the picker output to a mutate call so the
20
+ * scope to carry a usable target and `access.length >= 1`; a v3 device
21
+ * selector additionally requires a non-empty list for every kind except
22
+ * `all`. Use this before passing the picker output to a mutate call so the
22
23
  * user sees a clean inline error instead of a tRPC ZodError.
24
+ *
25
+ * An EMPTY selector list is rejected rather than silently treated as "all":
26
+ * the schema's `.min(1)` would reject it server-side anyway, and the failure
27
+ * mode of guessing wrong here is granting the whole fleet.
23
28
  */
24
29
  export declare function validateScopes(scopes: readonly TokenScope[]): string | null;
25
30
  export {};