@devicechain/widgets 0.22.0 → 0.23.0

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 (54) hide show
  1. package/README.md +15 -0
  2. package/dist/access-strings.d.ts +6 -0
  3. package/dist/chunks/{aggregate-feed-6ZYKOQOB.js → aggregate-feed-BD3CHNFU.js} +5 -4
  4. package/dist/chunks/aggregate-feed-BD3CHNFU.js.map +7 -0
  5. package/dist/chunks/{aggregate-widgets-WVXAW3UL.js → aggregate-widgets-HZQI5HTX.js} +3 -2
  6. package/dist/chunks/{aggregate-widgets-WVXAW3UL.js.map → aggregate-widgets-HZQI5HTX.js.map} +1 -1
  7. package/dist/chunks/alarm-widgets-7UY6MIYZ.js +9 -0
  8. package/dist/chunks/alarm-widgets-7UY6MIYZ.js.map +7 -0
  9. package/dist/chunks/chunk-6OGI4UFJ.js +367 -0
  10. package/dist/chunks/chunk-6OGI4UFJ.js.map +7 -0
  11. package/dist/chunks/chunk-BRH66T5F.js +15 -0
  12. package/dist/chunks/chunk-BRH66T5F.js.map +7 -0
  13. package/dist/chunks/chunk-FM7OI5TQ.js +87 -0
  14. package/dist/chunks/chunk-FM7OI5TQ.js.map +7 -0
  15. package/dist/chunks/chunk-USRYKW2J.js +55 -0
  16. package/dist/chunks/chunk-USRYKW2J.js.map +7 -0
  17. package/dist/chunks/{chunk-S2OMBJLI.js → chunk-WBKHYZU2.js} +7 -3
  18. package/dist/chunks/{chunk-S2OMBJLI.js.map → chunk-WBKHYZU2.js.map} +2 -2
  19. package/dist/chunks/chunk-XSLFHCNI.js +419 -0
  20. package/dist/chunks/chunk-XSLFHCNI.js.map +7 -0
  21. package/dist/chunks/{control-widgets-UDS4ET3T.js → control-widgets-3V2LSSRF.js} +4 -2
  22. package/dist/chunks/{control-widgets-UDS4ET3T.js.map → control-widgets-3V2LSSRF.js.map} +1 -1
  23. package/dist/chunks/entity-selector-3JJFI4DT.js +7 -0
  24. package/dist/chunks/entity-selector-3JJFI4DT.js.map +7 -0
  25. package/dist/chunks/{fleet-feed-FK4ZMKIK.js → fleet-feed-5QGDLOV5.js} +27 -7
  26. package/dist/chunks/fleet-feed-5QGDLOV5.js.map +7 -0
  27. package/dist/chunks/table-6EVV7QZH.js +7 -0
  28. package/dist/chunks/table-6EVV7QZH.js.map +7 -0
  29. package/dist/connected-widget.d.ts +2 -0
  30. package/dist/dashboard-renderer.d.ts +1 -0
  31. package/dist/fleet-feed.d.ts +1 -0
  32. package/dist/index.d.ts +1 -0
  33. package/dist/index.js +478 -1142
  34. package/dist/index.js.map +4 -4
  35. package/dist/preload.d.ts +2 -0
  36. package/dist/widgets/alarm-count.d.ts +0 -46
  37. package/dist/widgets/alarm-lazy.d.ts +123 -0
  38. package/dist/widgets/alarm-table.d.ts +0 -76
  39. package/dist/widgets/alarm-widgets.d.ts +2 -0
  40. package/dist/widgets/command-button.d.ts +0 -38
  41. package/dist/widgets/control-lazy.d.ts +38 -0
  42. package/dist/widgets/control-widgets.d.ts +1 -0
  43. package/dist/widgets/entity-selector.d.ts +0 -15
  44. package/dist/widgets/gauge.d.ts +4 -0
  45. package/dist/widgets/lazy-chunk.d.ts +2 -1
  46. package/dist/widgets/selection-lazy.d.ts +16 -0
  47. package/dist/widgets/table-lazy.d.ts +39 -0
  48. package/dist/widgets/table.d.ts +0 -38
  49. package/dist/widgets/time-series-chart.d.ts +4 -0
  50. package/package.json +10 -7
  51. package/dist/chunks/aggregate-feed-6ZYKOQOB.js.map +0 -7
  52. package/dist/chunks/chunk-YPFB6DAL.js +0 -157
  53. package/dist/chunks/chunk-YPFB6DAL.js.map +0 -7
  54. package/dist/chunks/fleet-feed-FK4ZMKIK.js.map +0 -7
@@ -0,0 +1,2 @@
1
+ import type { WidgetRegistry } from '@devicechain/widget-sdk';
2
+ export declare function preloadWidgets(registry: WidgetRegistry, types: Iterable<string>): Promise<void>;
@@ -1,49 +1,3 @@
1
1
  import { type AlarmStreamState, type WidgetProps } from '@devicechain/widget-sdk';
2
2
  export declare const ALARM_COUNT_CAPTION_ROOM_PX = 20;
3
3
  export declare function AlarmCount({ widget, data }: WidgetProps<AlarmStreamState>): import("react").JSX.Element;
4
- export declare const alarmCountWidget: import("@devicechain/widget-sdk").WidgetDefinition<"alarm", {
5
- readonly title: {
6
- readonly kind: 'string';
7
- readonly labelId: 'widgetLabelTitle';
8
- readonly doc: 'Heading shown in the widget frame. Blank hides the frame heading.';
9
- };
10
- readonly state: {
11
- readonly kind: 'enum';
12
- readonly values: readonly ["ACTIVE", "CLEARED"];
13
- readonly labelId: 'widgetLabelState';
14
- readonly helpId: 'widgetStateHint';
15
- readonly valueLabelIds: {
16
- readonly ACTIVE: 'widgetAlarmStateActive';
17
- readonly CLEARED: 'widgetAlarmStateCleared';
18
- };
19
- readonly placeholderId: 'widgetPlaceholderAny';
20
- readonly doc: 'Show only alarms in this state. Unset shows every state.';
21
- };
22
- readonly severity: {
23
- readonly kind: 'enum';
24
- readonly values: readonly ["CRITICAL", "MAJOR", "MINOR", "WARNING", "INDETERMINATE"];
25
- readonly labelId: 'widgetLabelSeverity';
26
- readonly helpId: 'widgetSeverityHint';
27
- readonly valueLabelIds: {
28
- readonly CRITICAL: 'widgetAlarmSeverityCritical';
29
- readonly MAJOR: 'widgetAlarmSeverityMajor';
30
- readonly MINOR: 'widgetAlarmSeverityMinor';
31
- readonly WARNING: 'widgetAlarmSeverityWarning';
32
- readonly INDETERMINATE: 'widgetAlarmSeverityIndeterminate';
33
- };
34
- readonly placeholderId: 'widgetPlaceholderAny';
35
- readonly doc: 'Show only alarms at this severity. Unset shows every severity.';
36
- };
37
- readonly acknowledged: {
38
- readonly kind: 'enum';
39
- readonly values: readonly ["true", "false"];
40
- readonly labelId: 'widgetLabelAcknowledged';
41
- readonly helpId: 'widgetAcknowledgedHint';
42
- readonly valueLabelIds: {
43
- readonly true: 'widgetAlarmAckAcknowledged';
44
- readonly false: 'widgetAlarmAckUnacknowledged';
45
- };
46
- readonly placeholderId: 'widgetPlaceholderAny';
47
- readonly doc: "Show only acknowledged ('true') or unacknowledged ('false') alarms. Unset shows both.";
48
- };
49
- }>;
@@ -0,0 +1,123 @@
1
+ export declare const loadAlarmWidgets: () => Promise<typeof import("./alarm-widgets")>;
2
+ export declare const alarmTableWidget: import("@devicechain/widget-sdk").WidgetDefinition<"alarm", {
3
+ readonly title: {
4
+ readonly kind: 'string';
5
+ readonly labelId: 'widgetLabelTitle';
6
+ readonly doc: 'Heading shown in the widget frame. Blank hides the frame heading.';
7
+ };
8
+ readonly state: {
9
+ readonly kind: 'enum';
10
+ readonly values: readonly ["ACTIVE", "CLEARED"];
11
+ readonly labelId: 'widgetLabelState';
12
+ readonly helpId: 'widgetStateHint';
13
+ readonly valueLabelIds: {
14
+ readonly ACTIVE: 'widgetAlarmStateActive';
15
+ readonly CLEARED: 'widgetAlarmStateCleared';
16
+ };
17
+ readonly placeholderId: 'widgetPlaceholderAny';
18
+ readonly doc: 'Show only alarms in this state. Unset shows every state.';
19
+ };
20
+ readonly severity: {
21
+ readonly kind: 'enum';
22
+ readonly values: readonly ["CRITICAL", "MAJOR", "MINOR", "WARNING", "INDETERMINATE"];
23
+ readonly labelId: 'widgetLabelSeverity';
24
+ readonly helpId: 'widgetSeverityHint';
25
+ readonly valueLabelIds: {
26
+ readonly CRITICAL: 'widgetAlarmSeverityCritical';
27
+ readonly MAJOR: 'widgetAlarmSeverityMajor';
28
+ readonly MINOR: 'widgetAlarmSeverityMinor';
29
+ readonly WARNING: 'widgetAlarmSeverityWarning';
30
+ readonly INDETERMINATE: 'widgetAlarmSeverityIndeterminate';
31
+ };
32
+ readonly placeholderId: 'widgetPlaceholderAny';
33
+ readonly doc: 'Show only alarms at this severity. Unset shows every severity.';
34
+ };
35
+ readonly acknowledged: {
36
+ readonly kind: 'enum';
37
+ readonly values: readonly ["true", "false"];
38
+ readonly labelId: 'widgetLabelAcknowledged';
39
+ readonly helpId: 'widgetAcknowledgedHint';
40
+ readonly valueLabelIds: {
41
+ readonly true: 'widgetAlarmAckAcknowledged';
42
+ readonly false: 'widgetAlarmAckUnacknowledged';
43
+ };
44
+ readonly placeholderId: 'widgetPlaceholderAny';
45
+ readonly doc: "Show only acknowledged ('true') or unacknowledged ('false') alarms. Unset shows both.";
46
+ };
47
+ readonly maxRows: {
48
+ readonly kind: "number";
49
+ readonly integer: true;
50
+ readonly min: 1;
51
+ readonly labelId: "widgetLabelMaxRows";
52
+ readonly helpId: "widgetMaxRowsAlarmHint";
53
+ readonly doc: "Alarms loaded into the table. Default 50.";
54
+ };
55
+ readonly precision: {
56
+ readonly kind: 'number';
57
+ readonly integer: true;
58
+ readonly min: 0;
59
+ readonly max: 100;
60
+ readonly labelId: 'widgetLabelPrecision';
61
+ readonly helpId: 'widgetHintPrecision';
62
+ readonly doc: 'Decimal places to round displayed values to. Unset rounds to at most 3 decimals (4 significant digits under 1).';
63
+ };
64
+ readonly flashOnChange: {
65
+ readonly kind: 'boolean';
66
+ readonly labelId: 'widgetFlashOnChange';
67
+ readonly helpId: 'widgetFlashOnChangeHint';
68
+ readonly doc: 'Briefly tint a value green on a rise and red on a fall when it changes.';
69
+ };
70
+ readonly selectionTarget: {
71
+ readonly kind: 'string';
72
+ readonly labelId: 'widgetLabelTargetSlot';
73
+ readonly helpId: 'widgetTargetSlotHint';
74
+ readonly control: 'slot-target';
75
+ readonly doc: 'Name of the slot this widget re-points when the viewer picks an entity.';
76
+ };
77
+ }>;
78
+ export declare const alarmCountWidget: import("@devicechain/widget-sdk").WidgetDefinition<"alarm", {
79
+ readonly title: {
80
+ readonly kind: 'string';
81
+ readonly labelId: 'widgetLabelTitle';
82
+ readonly doc: 'Heading shown in the widget frame. Blank hides the frame heading.';
83
+ };
84
+ readonly state: {
85
+ readonly kind: 'enum';
86
+ readonly values: readonly ["ACTIVE", "CLEARED"];
87
+ readonly labelId: 'widgetLabelState';
88
+ readonly helpId: 'widgetStateHint';
89
+ readonly valueLabelIds: {
90
+ readonly ACTIVE: 'widgetAlarmStateActive';
91
+ readonly CLEARED: 'widgetAlarmStateCleared';
92
+ };
93
+ readonly placeholderId: 'widgetPlaceholderAny';
94
+ readonly doc: 'Show only alarms in this state. Unset shows every state.';
95
+ };
96
+ readonly severity: {
97
+ readonly kind: 'enum';
98
+ readonly values: readonly ["CRITICAL", "MAJOR", "MINOR", "WARNING", "INDETERMINATE"];
99
+ readonly labelId: 'widgetLabelSeverity';
100
+ readonly helpId: 'widgetSeverityHint';
101
+ readonly valueLabelIds: {
102
+ readonly CRITICAL: 'widgetAlarmSeverityCritical';
103
+ readonly MAJOR: 'widgetAlarmSeverityMajor';
104
+ readonly MINOR: 'widgetAlarmSeverityMinor';
105
+ readonly WARNING: 'widgetAlarmSeverityWarning';
106
+ readonly INDETERMINATE: 'widgetAlarmSeverityIndeterminate';
107
+ };
108
+ readonly placeholderId: 'widgetPlaceholderAny';
109
+ readonly doc: 'Show only alarms at this severity. Unset shows every severity.';
110
+ };
111
+ readonly acknowledged: {
112
+ readonly kind: 'enum';
113
+ readonly values: readonly ["true", "false"];
114
+ readonly labelId: 'widgetLabelAcknowledged';
115
+ readonly helpId: 'widgetAcknowledgedHint';
116
+ readonly valueLabelIds: {
117
+ readonly true: 'widgetAlarmAckAcknowledged';
118
+ readonly false: 'widgetAlarmAckUnacknowledged';
119
+ };
120
+ readonly placeholderId: 'widgetPlaceholderAny';
121
+ readonly doc: "Show only acknowledged ('true') or unacknowledged ('false') alarms. Unset shows both.";
122
+ };
123
+ }>;
@@ -3,79 +3,3 @@ import { type AlarmStreamState, type WidgetProps } from '@devicechain/widget-sdk
3
3
  export declare const ALARM_TABLE_NARROW_PX = 480;
4
4
  export declare function hyphenBreaks(text: string): ReactNode;
5
5
  export declare function AlarmTable({ widget, data, actions }: WidgetProps<AlarmStreamState>): import("react").JSX.Element;
6
- export declare const alarmTableWidget: import("@devicechain/widget-sdk").WidgetDefinition<"alarm", {
7
- readonly title: {
8
- readonly kind: 'string';
9
- readonly labelId: 'widgetLabelTitle';
10
- readonly doc: 'Heading shown in the widget frame. Blank hides the frame heading.';
11
- };
12
- readonly state: {
13
- readonly kind: 'enum';
14
- readonly values: readonly ["ACTIVE", "CLEARED"];
15
- readonly labelId: 'widgetLabelState';
16
- readonly helpId: 'widgetStateHint';
17
- readonly valueLabelIds: {
18
- readonly ACTIVE: 'widgetAlarmStateActive';
19
- readonly CLEARED: 'widgetAlarmStateCleared';
20
- };
21
- readonly placeholderId: 'widgetPlaceholderAny';
22
- readonly doc: 'Show only alarms in this state. Unset shows every state.';
23
- };
24
- readonly severity: {
25
- readonly kind: 'enum';
26
- readonly values: readonly ["CRITICAL", "MAJOR", "MINOR", "WARNING", "INDETERMINATE"];
27
- readonly labelId: 'widgetLabelSeverity';
28
- readonly helpId: 'widgetSeverityHint';
29
- readonly valueLabelIds: {
30
- readonly CRITICAL: 'widgetAlarmSeverityCritical';
31
- readonly MAJOR: 'widgetAlarmSeverityMajor';
32
- readonly MINOR: 'widgetAlarmSeverityMinor';
33
- readonly WARNING: 'widgetAlarmSeverityWarning';
34
- readonly INDETERMINATE: 'widgetAlarmSeverityIndeterminate';
35
- };
36
- readonly placeholderId: 'widgetPlaceholderAny';
37
- readonly doc: 'Show only alarms at this severity. Unset shows every severity.';
38
- };
39
- readonly acknowledged: {
40
- readonly kind: 'enum';
41
- readonly values: readonly ["true", "false"];
42
- readonly labelId: 'widgetLabelAcknowledged';
43
- readonly helpId: 'widgetAcknowledgedHint';
44
- readonly valueLabelIds: {
45
- readonly true: 'widgetAlarmAckAcknowledged';
46
- readonly false: 'widgetAlarmAckUnacknowledged';
47
- };
48
- readonly placeholderId: 'widgetPlaceholderAny';
49
- readonly doc: "Show only acknowledged ('true') or unacknowledged ('false') alarms. Unset shows both.";
50
- };
51
- readonly maxRows: {
52
- readonly kind: "number";
53
- readonly integer: true;
54
- readonly min: 1;
55
- readonly labelId: "widgetLabelMaxRows";
56
- readonly helpId: "widgetMaxRowsAlarmHint";
57
- readonly doc: "Alarms loaded into the table. Default 50.";
58
- };
59
- readonly precision: {
60
- readonly kind: 'number';
61
- readonly integer: true;
62
- readonly min: 0;
63
- readonly max: 100;
64
- readonly labelId: 'widgetLabelPrecision';
65
- readonly helpId: 'widgetHintPrecision';
66
- readonly doc: 'Decimal places to round displayed values to. Unset rounds to at most 3 decimals (4 significant digits under 1).';
67
- };
68
- readonly flashOnChange: {
69
- readonly kind: 'boolean';
70
- readonly labelId: 'widgetFlashOnChange';
71
- readonly helpId: 'widgetFlashOnChangeHint';
72
- readonly doc: 'Briefly tint a value green on a rise and red on a fall when it changes.';
73
- };
74
- readonly selectionTarget: {
75
- readonly kind: 'string';
76
- readonly labelId: 'widgetLabelTargetSlot';
77
- readonly helpId: 'widgetTargetSlotHint';
78
- readonly control: 'slot-target';
79
- readonly doc: 'Name of the slot this widget re-points when the viewer picks an entity.';
80
- };
81
- }>;
@@ -0,0 +1,2 @@
1
+ export { AlarmTable } from './alarm-table';
2
+ export { AlarmCount } from './alarm-count';
@@ -1,40 +1,2 @@
1
1
  import { type CommandStreamState, type WidgetProps } from '@devicechain/widget-sdk';
2
2
  export declare function CommandButton({ widget, data, actions }: WidgetProps<CommandStreamState>): import("react").JSX.Element;
3
- export declare const commandButtonWidget: import("@devicechain/widget-sdk").WidgetDefinition<"control", {
4
- readonly title: {
5
- readonly kind: 'string';
6
- readonly labelId: 'widgetLabelTitle';
7
- readonly doc: 'Heading shown in the widget frame. Blank hides the frame heading.';
8
- };
9
- readonly commandName: {
10
- readonly kind: "string";
11
- readonly required: true;
12
- readonly labelId: "widgetCommandHeading";
13
- readonly helpId: "widgetCommandFieldHint";
14
- readonly control: "command-vocabulary";
15
- readonly doc: "Command key issued to the target device. Without it the widget cannot send.";
16
- };
17
- readonly commandLabel: {
18
- readonly kind: "string";
19
- readonly labelId: "widgetCommandHeading";
20
- readonly helpId: "widgetCommandFieldHint";
21
- readonly control: "command-vocabulary";
22
- readonly doc: "Text on the send button. Defaults to the command key.";
23
- };
24
- readonly parameterSchema: {
25
- readonly kind: "string";
26
- readonly format: "json";
27
- readonly labelId: "widgetCommandHeading";
28
- readonly helpId: "widgetCommandFieldHint";
29
- readonly control: "command-vocabulary";
30
- readonly doc: "The command's parameter descriptors, baked in as JSON at author time. Drives the typed form.";
31
- };
32
- readonly maxRows: {
33
- readonly kind: "number";
34
- readonly integer: true;
35
- readonly min: 1;
36
- readonly labelId: "widgetLabelMaxRows";
37
- readonly helpId: "widgetMaxRowsCommandHint";
38
- readonly doc: "Recent commands shown in the history. Default 20.";
39
- };
40
- }>;
@@ -90,3 +90,41 @@ export declare const commandToggleWidget: import("@devicechain/widget-sdk").Widg
90
90
  readonly doc: 'Which parameter of the command this control sets. May be left blank when the command has exactly one parameter of the right type.';
91
91
  };
92
92
  }>;
93
+ export declare const commandButtonWidget: import("@devicechain/widget-sdk").WidgetDefinition<"control", {
94
+ readonly title: {
95
+ readonly kind: 'string';
96
+ readonly labelId: 'widgetLabelTitle';
97
+ readonly doc: 'Heading shown in the widget frame. Blank hides the frame heading.';
98
+ };
99
+ readonly commandName: {
100
+ readonly kind: "string";
101
+ readonly required: true;
102
+ readonly labelId: "widgetCommandHeading";
103
+ readonly helpId: "widgetCommandFieldHint";
104
+ readonly control: "command-vocabulary";
105
+ readonly doc: "Command key issued to the target device. Without it the widget cannot send.";
106
+ };
107
+ readonly commandLabel: {
108
+ readonly kind: "string";
109
+ readonly labelId: "widgetCommandHeading";
110
+ readonly helpId: "widgetCommandFieldHint";
111
+ readonly control: "command-vocabulary";
112
+ readonly doc: "Text on the send button. Defaults to the command key.";
113
+ };
114
+ readonly parameterSchema: {
115
+ readonly kind: "string";
116
+ readonly format: "json";
117
+ readonly labelId: "widgetCommandHeading";
118
+ readonly helpId: "widgetCommandFieldHint";
119
+ readonly control: "command-vocabulary";
120
+ readonly doc: "The command's parameter descriptors, baked in as JSON at author time. Drives the typed form.";
121
+ };
122
+ readonly maxRows: {
123
+ readonly kind: "number";
124
+ readonly integer: true;
125
+ readonly min: 1;
126
+ readonly labelId: "widgetLabelMaxRows";
127
+ readonly helpId: "widgetMaxRowsCommandHint";
128
+ readonly doc: "Recent commands shown in the history. Default 20.";
129
+ };
130
+ }>;
@@ -1,2 +1,3 @@
1
+ export { CommandButton } from './command-button';
1
2
  export { CommandSlider } from './command-slider';
2
3
  export { CommandToggle } from './command-toggle';
@@ -1,17 +1,2 @@
1
1
  import { type WidgetProps } from '@devicechain/widget-sdk';
2
2
  export declare function EntitySelector({ widget }: WidgetProps<null>): import("react").JSX.Element;
3
- export declare const entitySelectorWidget: import("@devicechain/widget-sdk").WidgetDefinition<"selection", {
4
- readonly title: {
5
- readonly kind: 'string';
6
- readonly labelId: 'widgetLabelTitle';
7
- readonly doc: 'Heading shown in the widget frame. Blank hides the frame heading.';
8
- };
9
- readonly selectionTarget: {
10
- readonly kind: 'string';
11
- readonly labelId: 'widgetLabelTargetSlot';
12
- readonly helpId: 'widgetTargetSlotHint';
13
- readonly control: 'slot-target';
14
- readonly doc: 'Name of the slot this widget re-points when the viewer picks an entity.';
15
- readonly required: true;
16
- };
17
- }>;
@@ -1,5 +1,9 @@
1
1
  import { type WidgetProps } from '@devicechain/widget-sdk';
2
+ import { loadChartEngine } from '@devicechain/widget-sdk/echarts';
2
3
  export declare function Gauge({ widget, data }: WidgetProps): import("react").JSX.Element;
4
+ export declare namespace Gauge {
5
+ export { loadChartEngine as preload };
6
+ }
3
7
  export declare const gaugeWidget: import("@devicechain/widget-sdk").WidgetDefinition<"measurement", {
4
8
  readonly title: {
5
9
  readonly kind: 'string';
@@ -1,8 +1,9 @@
1
1
  import type { MeasurementStreamState, WidgetProps } from '@devicechain/widget-sdk';
2
2
  export declare function lazyChunk<M extends Record<string, unknown>, D = MeasurementStreamState>(importer: () => Promise<M>): {
3
3
  load: () => Promise<M>;
4
- component: <P = D, Props extends object = WidgetProps<P>>(name: keyof M & string) => {
4
+ component: <P = D, Props extends object = WidgetProps<P>>(name: keyof M & string, alsoPreload?: () => Promise<unknown>) => {
5
5
  (props: Props): import("react").JSX.Element | null;
6
6
  displayName: string;
7
+ preload: () => Promise<M>;
7
8
  };
8
9
  };
@@ -0,0 +1,16 @@
1
+ export declare const loadSelectionWidgets: () => Promise<typeof import("./entity-selector")>;
2
+ export declare const entitySelectorWidget: import("@devicechain/widget-sdk").WidgetDefinition<"selection", {
3
+ readonly title: {
4
+ readonly kind: 'string';
5
+ readonly labelId: 'widgetLabelTitle';
6
+ readonly doc: 'Heading shown in the widget frame. Blank hides the frame heading.';
7
+ };
8
+ readonly selectionTarget: {
9
+ readonly kind: 'string';
10
+ readonly labelId: 'widgetLabelTargetSlot';
11
+ readonly helpId: 'widgetTargetSlotHint';
12
+ readonly control: 'slot-target';
13
+ readonly doc: 'Name of the slot this widget re-points when the viewer picks an entity.';
14
+ readonly required: true;
15
+ };
16
+ }>;
@@ -0,0 +1,39 @@
1
+ export declare const loadTableWidget: () => Promise<typeof import("./table")>;
2
+ export declare const tableWidget: import("@devicechain/widget-sdk").WidgetDefinition<"measurement", {
3
+ readonly title: {
4
+ readonly kind: 'string';
5
+ readonly labelId: 'widgetLabelTitle';
6
+ readonly doc: 'Heading shown in the widget frame. Blank hides the frame heading.';
7
+ };
8
+ readonly precision: {
9
+ readonly kind: 'number';
10
+ readonly integer: true;
11
+ readonly min: 0;
12
+ readonly max: 100;
13
+ readonly labelId: 'widgetLabelPrecision';
14
+ readonly helpId: 'widgetHintPrecision';
15
+ readonly doc: 'Decimal places to round displayed values to. Unset rounds to at most 3 decimals (4 significant digits under 1).';
16
+ };
17
+ readonly flashOnChange: {
18
+ readonly kind: 'boolean';
19
+ readonly labelId: 'widgetFlashOnChange';
20
+ readonly helpId: 'widgetFlashOnChangeHint';
21
+ readonly doc: 'Briefly tint a value green on a rise and red on a fall when it changes.';
22
+ };
23
+ readonly staleAfterSeconds: {
24
+ readonly kind: 'number';
25
+ readonly integer: true;
26
+ readonly min: 1;
27
+ readonly labelId: 'widgetLabelStaleAfter';
28
+ readonly helpId: 'widgetHintStaleAfter';
29
+ readonly doc: 'Seconds after which the newest sample is called stale: the value is greyed out and badged. Unset shows the sample age only and never marks the widget stale.';
30
+ };
31
+ readonly window: {
32
+ readonly kind: 'number';
33
+ readonly integer: true;
34
+ readonly min: 1;
35
+ readonly labelId: 'widgetLabelWindow';
36
+ readonly helpId: 'widgetHintWindow';
37
+ readonly doc: 'Samples retained across ALL of the widget\'s measurements before the oldest are dropped. Bounds memory; only the chart draws them. Default 300.';
38
+ };
39
+ }>;
@@ -1,40 +1,2 @@
1
1
  import { type WidgetProps } from '@devicechain/widget-sdk';
2
2
  export declare function Table({ widget, data }: WidgetProps): import("react").JSX.Element;
3
- export declare const tableWidget: import("@devicechain/widget-sdk").WidgetDefinition<"measurement", {
4
- readonly title: {
5
- readonly kind: 'string';
6
- readonly labelId: 'widgetLabelTitle';
7
- readonly doc: 'Heading shown in the widget frame. Blank hides the frame heading.';
8
- };
9
- readonly precision: {
10
- readonly kind: 'number';
11
- readonly integer: true;
12
- readonly min: 0;
13
- readonly max: 100;
14
- readonly labelId: 'widgetLabelPrecision';
15
- readonly helpId: 'widgetHintPrecision';
16
- readonly doc: 'Decimal places to round displayed values to. Unset rounds to at most 3 decimals (4 significant digits under 1).';
17
- };
18
- readonly flashOnChange: {
19
- readonly kind: 'boolean';
20
- readonly labelId: 'widgetFlashOnChange';
21
- readonly helpId: 'widgetFlashOnChangeHint';
22
- readonly doc: 'Briefly tint a value green on a rise and red on a fall when it changes.';
23
- };
24
- readonly staleAfterSeconds: {
25
- readonly kind: 'number';
26
- readonly integer: true;
27
- readonly min: 1;
28
- readonly labelId: 'widgetLabelStaleAfter';
29
- readonly helpId: 'widgetHintStaleAfter';
30
- readonly doc: 'Seconds after which the newest sample is called stale: the value is greyed out and badged. Unset shows the sample age only and never marks the widget stale.';
31
- };
32
- readonly window: {
33
- readonly kind: 'number';
34
- readonly integer: true;
35
- readonly min: 1;
36
- readonly labelId: 'widgetLabelWindow';
37
- readonly helpId: 'widgetHintWindow';
38
- readonly doc: 'Samples retained across ALL of the widget\'s measurements before the oldest are dropped. Bounds memory; only the chart draws them. Default 300.';
39
- };
40
- }>;
@@ -1,5 +1,9 @@
1
1
  import { type WidgetProps } from '@devicechain/widget-sdk';
2
+ import { loadChartEngine } from '@devicechain/widget-sdk/echarts';
2
3
  export declare function TimeSeriesChart({ widget, data }: WidgetProps): import("react").JSX.Element;
4
+ export declare namespace TimeSeriesChart {
5
+ export { loadChartEngine as preload };
6
+ }
3
7
  export declare const timeSeriesChartWidget: import("@devicechain/widget-sdk").WidgetDefinition<"measurement", {
4
8
  readonly title: {
5
9
  readonly kind: 'string';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devicechain/widgets",
3
- "version": "0.22.0",
3
+ "version": "0.23.0",
4
4
  "description": "DeviceChain's built-in dashboard widgets across six channels — telemetry (time-series chart + gauge over Apache ECharts, latest card, table, and lazily loaded level, indicator and radial widgets: linear and level gauges, battery, status light, signal bars, compass, progress ring), static (label, image; no data), alarm (table, count), control (command button), selection (entity selector), and location (map over MapLibre GL, lazily loaded, tile source supplied by the host app) — plus the renderer that lays them out. Each is a registration built on @devicechain/widget-sdk. Themed via CSS custom properties, no Tailwind leakage.",
5
5
  "keywords": [
6
6
  "devicechain",
@@ -35,6 +35,9 @@
35
35
  },
36
36
  "./package.json": "./package.json"
37
37
  },
38
+ "sideEffects": [
39
+ "./dist/vite.js"
40
+ ],
38
41
  "files": [
39
42
  "dist",
40
43
  "README.md",
@@ -50,18 +53,18 @@
50
53
  "test": "vitest run"
51
54
  },
52
55
  "peerDependencies": {
53
- "@devicechain/client": "0.22.0",
54
- "@devicechain/dashboards": "0.22.0",
55
- "@devicechain/widget-sdk": "0.22.0",
56
+ "@devicechain/client": "0.23.0",
57
+ "@devicechain/dashboards": "0.23.0",
58
+ "@devicechain/widget-sdk": "0.23.0",
56
59
  "echarts": "^6.0.0",
57
60
  "maplibre-gl": "^6.13.0",
58
61
  "react": "^19.3.0",
59
62
  "react-dom": "^19.3.0"
60
63
  },
61
64
  "devDependencies": {
62
- "@devicechain/client": "0.22.0",
63
- "@devicechain/dashboards": "0.22.0",
64
- "@devicechain/widget-sdk": "0.22.0",
65
+ "@devicechain/client": "0.23.0",
66
+ "@devicechain/dashboards": "0.23.0",
67
+ "@devicechain/widget-sdk": "0.23.0",
65
68
  "@testing-library/react": "^16.3.3",
66
69
  "@types/node": "^26.6.5",
67
70
  "@types/react": "^19.3.0",
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/aggregate-feed.tsx", "../../src/aggregate-fold.ts"],
4
- "sourcesContent": ["// Copyright The DeviceChain Authors\n// SPDX-License-Identifier: Apache-2.0\n\n// The data feed of an aggregate widget: the exact aggregates of its measurements over its span,\n// plus the newest live reading of each. Loaded on first use (connected-widget.tsx imports it\n// dynamically), so a board with no aggregate widget never downloads it.\n//\n// The aggregates are folded from the source's own buckets (WidgetDataSource.bucketMeasurements: each\n// carries the exact count, min, max and sum), never from the chart seed: a seed is a series of bucket\n// AVERAGES, and a minimum or maximum cannot be recovered from those. A source that produces no\n// buckets is an explained state, not a guess.\n//\n// - the span is the widget's pinned one, else the board's (DEFAULT_TIME_RANGE_SECONDS off a board);\n// - the window is whole minutes (aggregateWindow), so it holds no reading from before the span;\n// - live, the read ends at the last minute and repeats on the boundaries of aggregateRefreshMs\n// (one chart bucket of the span: a minute for an hour, 42 minutes for a week), so every card on\n// the board reads at the same moment and the hub serves identical reads once; paused, it ends\n// at the freeze instant and is read once, so the number on screen does not move;\n// - a hidden tab does not read; it reads once when it is shown again;\n// - a read for a different selector, span or freeze instant is not shown under the new one: a\n// result is tagged with the key it was read for, and a mismatch reads as loading.\n\nimport {\n DEFAULT_TIME_RANGE_SECONDS,\n type AggregateResult,\n type AggregateStreamState,\n type WidgetActions,\n type WidgetDataSource,\n type WidgetDescriptor,\n type WidgetInstance,\n} from '@devicechain/dashboards';\nimport { useMeasurementStream, useWidgetTimeRange } from '@devicechain/widget-sdk';\nimport { useEffect, useMemo, useState, type ComponentType } from 'react';\n\nimport { aggregateBuckets, aggregateRefreshMs, aggregateWindow } from './aggregate-fold';\nimport { measurementSpan } from './binding-policy';\n\nconst LOADING: AggregateResult = { status: 'loading' };\n\nexport interface AggregateFeedProps {\n hub: WidgetDataSource;\n widget: WidgetInstance;\n descriptor: WidgetDescriptor;\n // The widget's component, and the host's pane for a stream that failed (before any figure).\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Component: ComponentType<any>;\n actions: WidgetActions | undefined;\n ErrorFrame: ComponentType<{ widget: WidgetInstance; error: unknown }>;\n}\n\nexport default function AggregateFeed({ hub, widget, descriptor, Component, actions, ErrorFrame }: AggregateFeedProps) {\n const range = useWidgetTimeRange();\n const now = useMemo(() => (hub.now ? () => hub.now!() : Date.now), [hub]);\n const spanSeconds = measurementSpan(descriptor, widget, range?.spanSeconds) ?? DEFAULT_TIME_RANGE_SECONDS;\n const pausedAt = range?.paused ? range.pausedAt : undefined;\n const ds = widget.datasource;\n\n // The newest live reading per measurement. It holds one sample: only `latest` is read, and the\n // pause keeps it from moving.\n const stream = useMeasurementStream(hub, ds, { window: 1, pausedAt, now });\n\n const key = JSON.stringify([ds ?? null, spanSeconds, pausedAt ?? null]);\n const supported = hub.bucketMeasurements !== undefined;\n const [tagged, setTagged] = useState<{ key: string; result: AggregateResult }>({ key, result: LOADING });\n\n useEffect(() => {\n if (!supported || !ds) return;\n let current = true;\n const run = (): void => {\n const { window, spanSeconds: covered } = aggregateWindow(spanSeconds, pausedAt ?? now());\n // Folded inside the chain, so a bucket that cannot be trusted fails the read like a network error.\n hub.bucketMeasurements!(ds, window).then(aggregateBuckets).then(\n (byName) => {\n if (!current) return;\n const { startTime, endTime } = window;\n setTagged({ key, result: { status: 'ready', byName, startTime, endTime, spanSeconds: covered } });\n },\n (err: unknown) => {\n if (!current) return;\n const message = err instanceof Error ? err.message : String(err);\n setTagged({ key, result: { status: 'unavailable', reason: 'failed', message } });\n },\n );\n };\n run();\n // Paused, the window is fixed at the freeze instant: nothing new can land in it.\n if (pausedAt !== undefined) return () => void (current = false);\n const hidden = () => document.hidden;\n const every = aggregateRefreshMs(spanSeconds);\n let timer: ReturnType<typeof setTimeout>;\n const schedule = (): void => {\n timer = setTimeout(\n () => {\n if (!hidden()) run();\n schedule();\n },\n every - (now() % every),\n );\n };\n schedule();\n const shown = (): void => {\n if (!hidden()) run();\n };\n document.addEventListener('visibilitychange', shown);\n return () => {\n current = false;\n clearTimeout(timer);\n document.removeEventListener('visibilitychange', shown);\n };\n // `ds` is read through `key` (value identity), not by reference.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [hub, supported, key]);\n\n let aggregates: AggregateResult;\n if (!supported) aggregates = { status: 'unavailable', reason: 'unsupported' };\n else if (!ds) aggregates = { status: 'ready', byName: {}, startTime: '', endTime: '', spanSeconds };\n else aggregates = tagged.key === key ? tagged.result : LOADING;\n\n const data: AggregateStreamState = { aggregates, latest: stream.latest, error: stream.error };\n return data.error ? <ErrorFrame widget={widget} error={data.error} /> : <Component widget={widget} data={data} actions={actions} />;\n}\n", "// Copyright The DeviceChain Authors\n// SPDX-License-Identifier: Apache-2.0\n\n// Aggregates over a span, folded from the backend's time buckets. Each bucket carries the exact\n// count, minimum, maximum and sum of the readings in it, so the span's aggregates are exact too:\n// the min of the mins, the max of the maxes, the sum of the sums, the count of the counts, and a\n// mean that is the total sum over the total count (which is the count-weighted mean of the\n// buckets' averages, without ever reading an average).\n//\n// \uD83D\uDD34 A MINIMUM OR MAXIMUM IS NEVER DERIVED FROM AVERAGES. A bucket's average hides its extremes, so\n// the \"max of the avgs\" is a plausible number that is not the maximum. A bucket that holds\n// readings but lacks a field the aggregate needs is therefore a loud failure here, never a\n// quiet substitution.\n\nimport { bucketSecondsFor, type HistoryWindow, type MeasurementAggregate, type MeasurementBucket } from '@devicechain/dashboards';\n\nexport class AggregateFieldsError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'AggregateFieldsError';\n }\n}\n\n// aggregateBuckets folds the buckets (any number of devices) into one aggregate per measurement\n// name. A name with no readings in any bucket is absent from the result, not zero.\nexport function aggregateBuckets(buckets: readonly MeasurementBucket[]): Record<string, MeasurementAggregate> {\n const out: Record<string, MeasurementAggregate> = {};\n for (const b of buckets) {\n if (typeof b.count !== 'number') {\n throw new AggregateFieldsError(`the bucket at ${b.bucketStart} for \"${b.name}\" carries no reading count`);\n }\n if (b.count === 0) continue;\n const { min, max, sum } = b;\n if (min == null || max == null || sum == null) {\n const missing = [min == null && 'min', max == null && 'max', sum == null && 'sum'].filter(Boolean);\n throw new AggregateFieldsError(\n `the bucket at ${b.bucketStart} for \"${b.name}\" holds ${b.count} readings but no ${missing.join(', ')}`,\n );\n }\n const a = out[b.name];\n if (!a) out[b.name] = { count: b.count, min, max, sum, avg: sum / b.count };\n else {\n a.count += b.count;\n a.sum += sum;\n a.min = Math.min(a.min, min);\n a.max = Math.max(a.max, max);\n a.avg = a.sum / a.count;\n }\n }\n return out;\n}\n\n// ---- The window a stat reads ------------------------------------------------------------------\n\nconst MINUTE_MS = 60_000;\n\n// aggregateRefreshMs is how often a live stat reads again: one bucket of the span's chart\n// (bucketSecondsFor), so never more often than once a minute. Finer is wasted -- the window it\n// reads moves in whole minutes (aggregateWindow) -- and a 7-day figure re-read every few seconds\n// costs the event store a scan of a week of summaries to move by a few seconds' readings.\nexport function aggregateRefreshMs(spanSeconds: number): number {\n return bucketSecondsFor(spanSeconds) * 1000;\n}\n\nexport interface AggregateWindow {\n window: HistoryWindow;\n // The length the window actually covers, in seconds: the span, or less when the span is not a\n // whole number of minutes. This, not the span asked for, is what the card says it covers.\n spanSeconds: number;\n}\n\n// aggregateWindow is the window a stat over `spanSeconds` reads at `at` (epoch ms): whole minutes,\n// ending at the last minute boundary at or before `at`.\n//\n// \uD83D\uDD34 Whole minutes because the event store answers from one-minute summaries, and a summary is\n// read whole: a window starting mid-minute would also count the readings from that minute's\n// start, BEFORE the span, so \"Maximum \u00B7 1h\" could be the maximum of an hour and a minute. Both\n// edges fall on minute boundaries instead, and the end is asked for as the instant just before\n// its boundary (the store's end is inclusive), so the summaries read are exactly the window's.\n// The start rounds UP, so a span that is not a whole number of minutes covers less, never more,\n// and says so (`spanSeconds`).\n//\n// Live cards read again on the boundaries of aggregateRefreshMs (a whole number of minutes), so\n// every card of one span ends its window on the same boundary: cards that read the same\n// measurement ask the same question at the same moment, and the hub answers them with one read.\n// One bucket wide: the card needs only the totals, so the store returns one or two rows per\n// measurement rather than a chart's worth.\nexport function aggregateWindow(spanSeconds: number, at: number): AggregateWindow {\n const end = Math.floor(at / MINUTE_MS) * MINUTE_MS;\n const start = Math.ceil((end - spanSeconds * 1000) / MINUTE_MS) * MINUTE_MS;\n const covered = (end - start) / 1000;\n return {\n window: {\n startTime: new Date(start).toISOString(),\n endTime: new Date(end - 1).toISOString(),\n intervalSeconds: Math.max(60, covered),\n },\n spanSeconds: covered,\n };\n}\n"],
5
- "mappings": "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",
6
- "names": []
7
- }