@camstack/types 1.2.446 → 1.2.448

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 (35) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/addon.js +3 -2
  3. package/dist/addon.mjs +3 -2
  4. package/dist/automation/action.d.ts +2 -0
  5. package/dist/automation/index.d.ts +3 -1
  6. package/dist/automation/normalize-units.d.ts +59 -0
  7. package/dist/automation/recipe.d.ts +15 -1
  8. package/dist/capabilities/action-source.cap.d.ts +1 -0
  9. package/dist/capabilities/actions.cap.d.ts +32 -1
  10. package/dist/capabilities/core-blocks.cap.d.ts +17 -0
  11. package/dist/capabilities/index.d.ts +3 -1
  12. package/dist/capabilities/remote-layout-components.cap.d.ts +81 -0
  13. package/dist/capabilities/remote.cap.d.ts +2 -0
  14. package/dist/client.js +1 -2
  15. package/dist/client.mjs +1 -2
  16. package/dist/device/cap-vocabulary/types.d.ts +9 -1
  17. package/dist/generated/addon-api.d.ts +15 -0
  18. package/dist/generated/capability-router-map.d.ts +5 -2
  19. package/dist/generated/collection-array-methods.d.ts +1 -1
  20. package/dist/generated/method-access-map.d.ts +1 -1
  21. package/dist/generated/system-proxy.d.ts +2 -0
  22. package/dist/index.d.ts +6 -1
  23. package/dist/index.js +1786 -733
  24. package/dist/index.mjs +1750 -734
  25. package/dist/interfaces/event-bus.d.ts +9 -0
  26. package/dist/remote/remote-builtin-components.d.ts +15 -0
  27. package/dist/remote/remote-components.d.ts +109 -0
  28. package/dist/remote/remote-config.d.ts +121 -0
  29. package/dist/remote/remote-layout-ops.d.ts +68 -0
  30. package/dist/{sleep-6eG9C8Xl.mjs → sleep-63gM_1JR.mjs} +1 -0
  31. package/dist/{sleep-UXDHn-oJ.js → sleep-BSPhInRm.js} +1 -0
  32. package/dist/units/index.d.ts +3 -0
  33. package/dist/units/quantity-input.d.ts +58 -0
  34. package/dist/units/quantity-units.d.ts +8 -0
  35. package/package.json +1 -1
@@ -641,6 +641,8 @@ export interface SystemReadyStatePayload {
641
641
  readonly ts: number;
642
642
  readonly [key: string]: unknown;
643
643
  }
644
+ /** What a node update replaces — see {@link PendingRestartMarkerPayload.what}. */
645
+ export type NodeUpdateTarget = 'server' | 'desktop-shell' | 'container-image';
644
646
  /**
645
647
  * Payload carried on `system.restarting` (when the restart is being
646
648
  * scheduled) and `system.restart-completed` (after the new process
@@ -659,6 +661,13 @@ export interface SystemReadyStatePayload {
659
661
  */
660
662
  export interface PendingRestartMarkerPayload {
661
663
  readonly kind: 'framework-update' | 'manual' | 'system' | 'framework-bulk-update';
664
+ /**
665
+ * WHAT is being replaced when the restart is an update. Absent means the
666
+ * `@camstack/server` closure (every announcement predating the field):
667
+ * `desktop-shell` is the Electron app's own self-update, `container-image` a
668
+ * container that booted on a different image than its previous boot.
669
+ */
670
+ readonly what?: NodeUpdateTarget;
662
671
  readonly packageName?: string;
663
672
  readonly fromVersion?: string;
664
673
  readonly toVersion?: string;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * The built-in palette of remote layout components (D973): what the template
3
+ * editor's "Add component" offers before any addon contributes more. The
4
+ * core-blocks builtin serves this list through the `remote-layout-components`
5
+ * cap; the built-in layout presets are composed from the same entries with
6
+ * `insertComponent`, so a preset and a hand-built layout use one vocabulary.
7
+ *
8
+ * Roles are the existing remote roles; where the vocabulary has no word
9
+ * (a generic minus / plus, a colour key, an app slot) the key is `custom:<key>`.
10
+ * Printed legends are data, not interface strings, so they are not translated.
11
+ */
12
+ import type { RemoteLayoutComponent } from './remote-components.js';
13
+ export declare const BUILTIN_REMOTE_COMPONENTS: readonly RemoteLayoutComponent[];
14
+ /** A built-in component by id (the presets compose from these). */
15
+ export declare function builtinRemoteComponent(id: string): RemoteLayoutComponent;
@@ -0,0 +1,109 @@
1
+ /**
2
+ * A remote layout COMPONENT (D973): a reusable, named chunk of a remote — a
3
+ * D-pad, a keypad, a section divider — offered in the template editor's
4
+ * "Add component" palette. Pure data: the buttons are placed RELATIVE to the
5
+ * component, and the frame, shape and tone are names from the closed
6
+ * vocabularies the UI draws. An addon contributes components through the
7
+ * `remote-layout-components` cap and ships no UI code.
8
+ */
9
+ import { z } from 'zod';
10
+ export declare const REMOTE_COMPONENT_CATEGORIES: readonly ['power', 'navigation', 'volume', 'numbers', 'media', 'colour', 'apps', 'layout'];
11
+ export declare const RemoteComponentCategorySchema: z.ZodEnum<{
12
+ apps: "apps";
13
+ colour: "colour";
14
+ layout: "layout";
15
+ media: "media";
16
+ navigation: "navigation";
17
+ numbers: "numbers";
18
+ power: "power";
19
+ volume: "volume";
20
+ }>;
21
+ export type RemoteComponentCategory = z.infer<typeof RemoteComponentCategorySchema>;
22
+ export declare const MAX_COMPONENT_BUTTONS = 40;
23
+ export declare const RemoteComponentButtonSchema: z.ZodObject<{
24
+ idSuffix: z.ZodString;
25
+ row: z.ZodNumber;
26
+ col: z.ZodNumber;
27
+ rowSpan: z.ZodNumber;
28
+ colSpan: z.ZodNumber;
29
+ role: z.ZodString;
30
+ icon: z.ZodOptional<z.ZodString>;
31
+ label: z.ZodOptional<z.ZodString>;
32
+ shape: z.ZodOptional<z.ZodEnum<{
33
+ pill: "pill";
34
+ rect: "rect";
35
+ round: "round";
36
+ rounded: "rounded";
37
+ }>>;
38
+ tone: z.ZodOptional<z.ZodEnum<{
39
+ accent: "accent";
40
+ blue: "blue";
41
+ danger: "danger";
42
+ green: "green";
43
+ neutral: "neutral";
44
+ red: "red";
45
+ yellow: "yellow";
46
+ }>>;
47
+ }, z.core.$strip>;
48
+ export type RemoteComponentButton = z.infer<typeof RemoteComponentButtonSchema>;
49
+ export declare const RemoteLayoutComponentSchema: z.ZodObject<{
50
+ id: z.ZodString;
51
+ name: z.ZodString;
52
+ nameI18n: z.ZodOptional<z.ZodObject<{
53
+ en: z.ZodString;
54
+ it: z.ZodString;
55
+ }, z.core.$strip>>;
56
+ icon: z.ZodString;
57
+ category: z.ZodEnum<{
58
+ apps: "apps";
59
+ colour: "colour";
60
+ layout: "layout";
61
+ media: "media";
62
+ navigation: "navigation";
63
+ numbers: "numbers";
64
+ power: "power";
65
+ volume: "volume";
66
+ }>;
67
+ size: z.ZodObject<{
68
+ rows: z.ZodNumber;
69
+ cols: z.ZodNumber;
70
+ }, z.core.$strip>;
71
+ group: z.ZodNullable<z.ZodObject<{
72
+ frame: z.ZodEnum<{
73
+ divider: "divider";
74
+ dpad: "dpad";
75
+ keypad: "keypad";
76
+ none: "none";
77
+ panel: "panel";
78
+ "rocker-h": "rocker-h";
79
+ "rocker-v": "rocker-v";
80
+ }>;
81
+ title: z.ZodOptional<z.ZodString>;
82
+ }, z.core.$strip>>;
83
+ buttons: z.ZodArray<z.ZodObject<{
84
+ idSuffix: z.ZodString;
85
+ row: z.ZodNumber;
86
+ col: z.ZodNumber;
87
+ rowSpan: z.ZodNumber;
88
+ colSpan: z.ZodNumber;
89
+ role: z.ZodString;
90
+ icon: z.ZodOptional<z.ZodString>;
91
+ label: z.ZodOptional<z.ZodString>;
92
+ shape: z.ZodOptional<z.ZodEnum<{
93
+ pill: "pill";
94
+ rect: "rect";
95
+ round: "round";
96
+ rounded: "rounded";
97
+ }>>;
98
+ tone: z.ZodOptional<z.ZodEnum<{
99
+ accent: "accent";
100
+ blue: "blue";
101
+ danger: "danger";
102
+ green: "green";
103
+ neutral: "neutral";
104
+ red: "red";
105
+ yellow: "yellow";
106
+ }>>;
107
+ }, z.core.$strip>>;
108
+ }, z.core.$strip>;
109
+ export type RemoteLayoutComponent = z.infer<typeof RemoteLayoutComponentSchema>;
@@ -15,6 +15,7 @@ export declare const RemoteBindingActionSchema: z.ZodObject<{
15
15
  cap: z.ZodString;
16
16
  method: z.ZodString;
17
17
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
18
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
18
19
  deviceId: z.ZodNumber;
19
20
  }, z.core.$strip>;
20
21
  export type RemoteBindingAction = z.infer<typeof RemoteBindingActionSchema>;
@@ -24,6 +25,7 @@ export declare const RemoteBindingSchema: z.ZodObject<{
24
25
  cap: z.ZodString;
25
26
  method: z.ZodString;
26
27
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
28
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
27
29
  deviceId: z.ZodNumber;
28
30
  }, z.core.$strip>;
29
31
  }, z.core.$strip>;
@@ -50,6 +52,7 @@ export declare const RemoteConfigSchema: z.ZodObject<{
50
52
  cap: z.ZodString;
51
53
  method: z.ZodString;
52
54
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
55
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
53
56
  deviceId: z.ZodNumber;
54
57
  }, z.core.$strip>;
55
58
  }, z.core.$strip>>;
@@ -88,6 +91,42 @@ export declare const RemoteAssumedStateSchema: z.ZodObject<{
88
91
  export type RemoteAssumedState = z.infer<typeof RemoteAssumedStateSchema>;
89
92
  export declare const EMPTY_REMOTE_ASSUMED_STATE: RemoteAssumedState;
90
93
  export declare const MAX_LAYOUT_SPAN = 24;
94
+ export declare const MAX_LAYOUT_GROUPS = 50;
95
+ /**
96
+ * Closed vocabularies the UI knows how to DRAW (D973). A layout names a shape,
97
+ * a tone or a frame; it never carries a style. An addon that contributes a
98
+ * component picks from these lists — it ships no UI code.
99
+ */
100
+ export declare const REMOTE_BUTTON_SHAPES: readonly ['rect', 'rounded', 'round', 'pill'];
101
+ export declare const RemoteButtonShapeSchema: z.ZodEnum<{
102
+ pill: "pill";
103
+ rect: "rect";
104
+ round: "round";
105
+ rounded: "rounded";
106
+ }>;
107
+ export type RemoteButtonShape = z.infer<typeof RemoteButtonShapeSchema>;
108
+ export declare const REMOTE_BUTTON_TONES: readonly ['neutral', 'accent', 'danger', 'red', 'green', 'yellow', 'blue'];
109
+ export declare const RemoteButtonToneSchema: z.ZodEnum<{
110
+ accent: "accent";
111
+ blue: "blue";
112
+ danger: "danger";
113
+ green: "green";
114
+ neutral: "neutral";
115
+ red: "red";
116
+ yellow: "yellow";
117
+ }>;
118
+ export type RemoteButtonTone = z.infer<typeof RemoteButtonToneSchema>;
119
+ export declare const REMOTE_GROUP_FRAMES: readonly ['none', 'panel', 'divider', 'dpad', 'rocker-v', 'rocker-h', 'keypad'];
120
+ export declare const RemoteGroupFrameSchema: z.ZodEnum<{
121
+ divider: "divider";
122
+ dpad: "dpad";
123
+ keypad: "keypad";
124
+ none: "none";
125
+ panel: "panel";
126
+ "rocker-h": "rocker-h";
127
+ "rocker-v": "rocker-v";
128
+ }>;
129
+ export type RemoteGroupFrame = z.infer<typeof RemoteGroupFrameSchema>;
91
130
  export declare const RemoteLayoutButtonSchema: z.ZodObject<{
92
131
  id: z.ZodString;
93
132
  row: z.ZodNumber;
@@ -97,8 +136,56 @@ export declare const RemoteLayoutButtonSchema: z.ZodObject<{
97
136
  icon: z.ZodOptional<z.ZodString>;
98
137
  label: z.ZodOptional<z.ZodString>;
99
138
  role: z.ZodString;
139
+ shape: z.ZodOptional<z.ZodEnum<{
140
+ pill: "pill";
141
+ rect: "rect";
142
+ round: "round";
143
+ rounded: "rounded";
144
+ }>>;
145
+ tone: z.ZodOptional<z.ZodEnum<{
146
+ accent: "accent";
147
+ blue: "blue";
148
+ danger: "danger";
149
+ green: "green";
150
+ neutral: "neutral";
151
+ red: "red";
152
+ yellow: "yellow";
153
+ }>>;
154
+ groupId: z.ZodOptional<z.ZodString>;
100
155
  }, z.core.$strip>;
101
156
  export type RemoteLayoutButton = z.infer<typeof RemoteLayoutButtonSchema>;
157
+ /**
158
+ * A rectangle of the grid that moves as ONE thing and is drawn with a frame: a
159
+ * titled panel, a section divider, a D-pad ring. `componentId` names the palette
160
+ * entry it came from (informational: the layout is self-contained).
161
+ */
162
+ export declare const RemoteLayoutGroupSchema: z.ZodObject<{
163
+ id: z.ZodString;
164
+ componentId: z.ZodString;
165
+ frame: z.ZodEnum<{
166
+ divider: "divider";
167
+ dpad: "dpad";
168
+ keypad: "keypad";
169
+ none: "none";
170
+ panel: "panel";
171
+ "rocker-h": "rocker-h";
172
+ "rocker-v": "rocker-v";
173
+ }>;
174
+ row: z.ZodNumber;
175
+ col: z.ZodNumber;
176
+ rowSpan: z.ZodNumber;
177
+ colSpan: z.ZodNumber;
178
+ title: z.ZodOptional<z.ZodString>;
179
+ }, z.core.$strip>;
180
+ export type RemoteLayoutGroup = z.infer<typeof RemoteLayoutGroupSchema>;
181
+ export interface LayoutRect {
182
+ readonly row: number;
183
+ readonly col: number;
184
+ readonly rowSpan: number;
185
+ readonly colSpan: number;
186
+ }
187
+ export declare function rectsOverlap(a: LayoutRect, b: LayoutRect): boolean;
188
+ export declare function rectContains(outer: LayoutRect, inner: LayoutRect): boolean;
102
189
  export declare const RemoteLayoutPayloadSchema: z.ZodObject<{
103
190
  columns: z.ZodNumber;
104
191
  rows: z.ZodNumber;
@@ -111,6 +198,40 @@ export declare const RemoteLayoutPayloadSchema: z.ZodObject<{
111
198
  icon: z.ZodOptional<z.ZodString>;
112
199
  label: z.ZodOptional<z.ZodString>;
113
200
  role: z.ZodString;
201
+ shape: z.ZodOptional<z.ZodEnum<{
202
+ pill: "pill";
203
+ rect: "rect";
204
+ round: "round";
205
+ rounded: "rounded";
206
+ }>>;
207
+ tone: z.ZodOptional<z.ZodEnum<{
208
+ accent: "accent";
209
+ blue: "blue";
210
+ danger: "danger";
211
+ green: "green";
212
+ neutral: "neutral";
213
+ red: "red";
214
+ yellow: "yellow";
215
+ }>>;
216
+ groupId: z.ZodOptional<z.ZodString>;
114
217
  }, z.core.$strip>>;
218
+ groups: z.ZodOptional<z.ZodArray<z.ZodObject<{
219
+ id: z.ZodString;
220
+ componentId: z.ZodString;
221
+ frame: z.ZodEnum<{
222
+ divider: "divider";
223
+ dpad: "dpad";
224
+ keypad: "keypad";
225
+ none: "none";
226
+ panel: "panel";
227
+ "rocker-h": "rocker-h";
228
+ "rocker-v": "rocker-v";
229
+ }>;
230
+ row: z.ZodNumber;
231
+ col: z.ZodNumber;
232
+ rowSpan: z.ZodNumber;
233
+ colSpan: z.ZodNumber;
234
+ title: z.ZodOptional<z.ZodString>;
235
+ }, z.core.$strip>>>;
115
236
  }, z.core.$strip>;
116
237
  export type RemoteLayoutPayload = z.infer<typeof RemoteLayoutPayloadSchema>;
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Pure edits of a remote layout that involve groups and components (D973).
3
+ * Shared by the template editor, the built-in presets and the server so an
4
+ * accepted edit is always a payload `RemoteLayoutPayloadSchema` accepts.
5
+ * Every function returns a NEW layout or a typed refusal; none mutates.
6
+ */
7
+ import type { RemoteLayoutComponent } from './remote-components.js';
8
+ import { type RemoteLayoutPayload } from './remote-config.js';
9
+ export declare const LAYOUT_EDIT_REFUSALS: readonly ['outside', 'overlap', 'unknown-group', 'too-many'];
10
+ export type LayoutEditRefusal = (typeof LAYOUT_EDIT_REFUSALS)[number];
11
+ export type LayoutEditResult = {
12
+ readonly ok: true;
13
+ readonly layout: RemoteLayoutPayload;
14
+ } | {
15
+ readonly ok: false;
16
+ readonly reason: LayoutEditRefusal;
17
+ };
18
+ export interface InsertedComponent {
19
+ readonly ok: true;
20
+ readonly layout: RemoteLayoutPayload;
21
+ /** The group created for the component, or null for a component of loose buttons. */
22
+ readonly groupId: string | null;
23
+ readonly buttonIds: readonly string[];
24
+ }
25
+ export type InsertComponentResult = InsertedComponent | {
26
+ readonly ok: false;
27
+ readonly reason: LayoutEditRefusal;
28
+ };
29
+ /** A button of a component, positioned relative to it. */
30
+ export type ComponentButtonSpec = RemoteLayoutComponent['buttons'][number];
31
+ export interface InsertOptions {
32
+ /** Multiply the component's rows / columns (and every button's span), e.g. a D-pad on a 12-column grid. */
33
+ readonly scale?: {
34
+ readonly rows?: number;
35
+ readonly cols?: number;
36
+ };
37
+ /** Extra relative buttons joined to this instance (the keypad's bottom-corner keys). */
38
+ readonly extras?: readonly ComponentButtonSpec[];
39
+ /** Replaces the component's own frame title ("Section" -> "Volume"). */
40
+ readonly title?: string;
41
+ }
42
+ /** The columns a component must be scaled by to span the whole grid width, or null when it does not divide. */
43
+ export declare function fillWidthScale(layout: RemoteLayoutPayload, component: RemoteLayoutComponent): number | null;
44
+ /**
45
+ * Put `component` on the layout with its top-left cell at `at`. A component
46
+ * with a group becomes one group whose rectangle is the whole component and
47
+ * whose members are its buttons; one without is a set of loose buttons. The
48
+ * grid does not grow: a component that does not fit is refused `outside`, one
49
+ * that would sit on an existing key or group `overlap`.
50
+ */
51
+ export declare function insertComponent(layout: RemoteLayoutPayload, component: RemoteLayoutComponent, at: {
52
+ readonly row: number;
53
+ readonly col: number;
54
+ }, options?: InsertOptions): InsertComponentResult;
55
+ /** Move a group and every member by the same offset, atomically. */
56
+ export declare function moveGroup(layout: RemoteLayoutPayload, groupId: string, to: {
57
+ readonly row: number;
58
+ readonly col: number;
59
+ }): LayoutEditResult;
60
+ /**
61
+ * Delete a group. With `keepButtons` its members stay where they are as loose
62
+ * keys; without, they go with it.
63
+ */
64
+ export declare function removeGroup(layout: RemoteLayoutPayload, groupId: string, options: {
65
+ readonly keepButtons: boolean;
66
+ }): LayoutEditResult;
67
+ /** Dissolve a group, keeping its buttons in place. */
68
+ export declare function ungroup(layout: RemoteLayoutPayload, groupId: string): LayoutEditResult;
@@ -6877,6 +6877,7 @@ var CAP_NAMES = Object.freeze([
6877
6877
  "recording-signal",
6878
6878
  "records",
6879
6879
  "remote",
6880
+ "remote-layout-components",
6880
6881
  "running-state",
6881
6882
  "scene-monitor",
6882
6883
  "script-runner",
@@ -6877,6 +6877,7 @@ var CAP_NAMES = Object.freeze([
6877
6877
  "recording-signal",
6878
6878
  "records",
6879
6879
  "remote",
6880
+ "remote-layout-components",
6880
6881
  "running-state",
6881
6882
  "scene-monitor",
6882
6883
  "script-runner",
@@ -8,6 +8,9 @@ export { UnitConversionError, unitDimension, convertUnit, tryConvertUnit, tryCon
8
8
  export type { UnitConversionReason } from './convert.js';
9
9
  export { DEFAULT_DISPLAY_PREFERENCE, DISPLAY_PREFERENCES, QUANTITY_BASE, ReadingQuantitySchema, baseUnitOf, displayUnitFor, historyUnitFor, isReadingQuantity, readingMeta, } from './quantity.js';
10
10
  export type { DisplayPreference, ReadingMeta, ReadingQuantity } from './quantity.js';
11
+ export { baseUnitForQuantity, unitsForQuantity } from './quantity-units.js';
12
+ export { QuantityUnitError, QuantityValueSchema, convertQuantityInput, isQuantityValue, paramMeta, paramMetaOf, } from './quantity-input.js';
13
+ export type { ConvertQuantityInput, ParamMeta, QuantityUnitErrorCode, QuantityValue, } from './quantity-input.js';
11
14
  export { thresholdToBase, thresholdToDisplay } from './threshold.js';
12
15
  export { formatReading } from './format-reading.js';
13
16
  export type { FormatReadingInput, FormattedReading } from './format-reading.js';
@@ -0,0 +1,58 @@
1
+ /**
2
+ * A number a person types for a physical quantity — the input side of the
3
+ * value + unit contract (D972).
4
+ *
5
+ * Readings are stored in the base unit of their quantity (D944); a cap method
6
+ * param is stored in the unit its input schema DECLARES (`paramMeta`). The
7
+ * wire pair {@link QuantityValue} says "this number is expressed in this
8
+ * unit"; {@link convertQuantityInput} brings it to the stored unit and refuses,
9
+ * with a typed {@link QuantityUnitError}, a unit that cannot be that quantity.
10
+ */
11
+ import { z } from 'zod';
12
+ import { type ReadingQuantity } from './quantity.js';
13
+ export type QuantityUnitErrorCode = 'non-finite' | 'unknown-unit' | 'cross-dimension'
14
+ /** A unit was given for a field or param that is not a quantity. */
15
+ | 'no-quantity';
16
+ /** A unit that cannot be applied to the number it was given with. */
17
+ export declare class QuantityUnitError extends Error {
18
+ readonly code: QuantityUnitErrorCode;
19
+ constructor(code: QuantityUnitErrorCode, message: string);
20
+ }
21
+ /** The wire pair: `value` is expressed in `unit`. */
22
+ export declare const QuantityValueSchema: z.ZodObject<{
23
+ value: z.ZodNumber;
24
+ unit: z.ZodString;
25
+ }, z.core.$strip>;
26
+ export type QuantityValue = z.infer<typeof QuantityValueSchema>;
27
+ export declare function isQuantityValue(candidate: unknown): candidate is QuantityValue;
28
+ export interface ConvertQuantityInput {
29
+ readonly value: number;
30
+ /** The unit `value` is expressed in, as the person picked it. */
31
+ readonly unit: string;
32
+ /** The unit to store: the quantity base, or a param's declared unit. */
33
+ readonly target: string;
34
+ }
35
+ /**
36
+ * `value` expressed in `unit`, brought to `target`. Throws
37
+ * {@link QuantityUnitError} for a non-finite value, an unknown unit or a unit
38
+ * of another dimension — never guesses.
39
+ */
40
+ export declare function convertQuantityInput(input: ConvertQuantityInput): number;
41
+ /** What a method input field declares: the quantity and the unit its value is in. */
42
+ export interface ParamMeta {
43
+ readonly [key: string]: unknown;
44
+ readonly quantity: ReadingQuantity;
45
+ readonly unit: string;
46
+ }
47
+ /**
48
+ * Zod `.meta()` bag for a cap METHOD param that is a physical quantity — the
49
+ * input-side twin of `readingMeta`. The value is carried in `unit` (a gram
50
+ * portion stays in grams); the unit must belong to the quantity, checked once
51
+ * when the cap is declared.
52
+ */
53
+ export declare function paramMeta(declared: {
54
+ readonly quantity: ReadingQuantity;
55
+ readonly unit: string;
56
+ }): ParamMeta;
57
+ /** The `paramMeta` on a method input field (or its unwrapped leaf), if any. */
58
+ export declare function paramMetaOf(field: z.ZodType): ParamMeta | undefined;
@@ -0,0 +1,8 @@
1
+ import { type ReadingQuantity } from './quantity.js';
2
+ /** The unit a reading of `quantity` is stored in, or `undefined` when it has none. */
3
+ export declare function baseUnitForQuantity(quantity: ReadingQuantity): string | undefined;
4
+ /**
5
+ * The units a person can enter a number of `quantity` in — base unit first.
6
+ * Empty when the quantity carries no unit.
7
+ */
8
+ export declare function unitsForQuantity(quantity: ReadingQuantity): readonly string[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/types",
3
- "version": "1.2.446",
3
+ "version": "1.2.448",
4
4
  "description": "Shared types, interfaces, and model catalogs for the CamStack detection ecosystem",
5
5
  "keywords": [
6
6
  "camstack",