@opalkelly/frontpanel-react-components 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. package/dist/cjs/index.js +1 -1
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/cjs/types/components/FrontPanel/FrontPanel.props.d.ts +0 -1
  4. package/dist/cjs/types/components/FrontPanelSelectEntry/FrontPanelSelectEntry.d.ts +0 -1
  5. package/dist/cjs/types/contexts/FrontPanelContext.d.ts +2 -2
  6. package/dist/cjs/types/primitives/Application/Application.props.d.ts +0 -1
  7. package/dist/cjs/types/primitives/Label/Label.props.d.ts +0 -1
  8. package/dist/cjs/types/primitives/SelectEntry/SelectEntry.d.ts +0 -1
  9. package/dist/cjs/types/primitives/Toggle/Toggle.props.d.ts +0 -1
  10. package/dist/esm/index.js +1 -1
  11. package/dist/esm/index.js.map +1 -1
  12. package/dist/esm/types/components/FrontPanel/FrontPanel.props.d.ts +0 -1
  13. package/dist/esm/types/components/FrontPanelSelectEntry/FrontPanelSelectEntry.d.ts +0 -1
  14. package/dist/esm/types/contexts/FrontPanelContext.d.ts +2 -2
  15. package/dist/esm/types/primitives/Application/Application.props.d.ts +0 -1
  16. package/dist/esm/types/primitives/Label/Label.props.d.ts +0 -1
  17. package/dist/esm/types/primitives/SelectEntry/SelectEntry.d.ts +0 -1
  18. package/dist/esm/types/primitives/Toggle/Toggle.props.d.ts +0 -1
  19. package/dist/index.d.ts +2 -3
  20. package/package.json +5 -3
  21. package/src/components/FrontPanel/FrontPanel.tsx +1 -7
  22. package/src/components/FrontPanelIndicator/FrontPanelIndicator.tsx +8 -7
  23. package/src/components/FrontPanelNumberDisplay/FrontPanelNumberDisplay.tsx +9 -8
  24. package/src/components/FrontPanelNumberEntry/FrontPanelNumberEntry.tsx +53 -48
  25. package/src/components/FrontPanelPushButton/FrontPanelPushButton.tsx +16 -11
  26. package/src/components/FrontPanelRangeSlider/FrontPanelRangeSlider.tsx +20 -15
  27. package/src/components/FrontPanelSelectEntry/FrontPanelSelectEntryRoot.tsx +57 -51
  28. package/src/components/FrontPanelToggleSwitch/FrontPanelToggleSwitch.tsx +20 -18
  29. package/src/components/FrontPanelTriggerButton/FrontPanelTriggerButton.tsx +15 -6
  30. package/src/contexts/FrontPanelContext.ts +3 -6
@@ -56,7 +56,7 @@ const FrontPanelNumberEntry = React.forwardRef<
56
56
 
57
57
  const { device, workQueue } = React.useContext(FrontPanelContext);
58
58
 
59
- const { maximumValue, minimumValue, fpEndpoint, ...rootProps } = props;
59
+ const { maximumValue, minimumValue, fpEndpoint, disabled, ...rootProps } = props;
60
60
 
61
61
  const clampedMinimumValue = React.useMemo(() => {
62
62
  return typeof minimumValue !== "undefined"
@@ -72,10 +72,10 @@ const FrontPanelNumberEntry = React.forwardRef<
72
72
  ((1n << BigInt(targetBitLength)) - 1n) << BigInt(fpEndpoint.bitOffset);
73
73
 
74
74
  const onUpdateWireValue = React.useCallback(
75
- async (sender: IFrontPanel): Promise<void> => {
76
- await workQueue.Post(async () => {
75
+ (sender?: IFrontPanel): void => {
76
+ if (sender != null && workQueue != null) {
77
77
  // Get the wire value for the endpoint
78
- let sourceWireValue = await sender.getWireInValue(fpEndpoint.epAddress);
78
+ let sourceWireValue = sender.getWireInValue(fpEndpoint.epAddress);
79
79
  let targetWireBitMask = targetWireSpanBitMask & 0xffffffffn;
80
80
  let sourceSpanValue =
81
81
  (BigInt(sourceWireValue) & targetWireBitMask) >> BigInt(fpEndpoint.bitOffset);
@@ -92,7 +92,7 @@ const FrontPanelNumberEntry = React.forwardRef<
92
92
  sourceWireAddress++
93
93
  ) {
94
94
  // Get the wire value for the next endpoint
95
- sourceWireValue = await sender.getWireInValue(sourceWireAddress);
95
+ sourceWireValue = sender.getWireInValue(sourceWireAddress);
96
96
  targetWireBitMask = currentWireSpanBitMask & 0xffffffffn;
97
97
  sourceSpanValue |=
98
98
  (BigInt(sourceWireValue) & targetWireBitMask) <<
@@ -104,9 +104,11 @@ const FrontPanelNumberEntry = React.forwardRef<
104
104
  }
105
105
 
106
106
  setValue(sourceSpanValue);
107
- });
107
+ } else {
108
+ setValue(0n);
109
+ }
108
110
  },
109
- [fpEndpoint, targetWireSpanBitMask]
111
+ [workQueue, fpEndpoint, targetWireSpanBitMask]
110
112
  );
111
113
 
112
114
  React.useEffect(() => {
@@ -115,49 +117,51 @@ const FrontPanelNumberEntry = React.forwardRef<
115
117
 
116
118
  const onNumberEntryValueChange = React.useCallback(
117
119
  async (value: bigint): Promise<void> => {
118
- await workQueue.Post(async () => {
119
- let targetWireBitMask = targetWireSpanBitMask & 0xffffffffn;
120
- let targetWireValue = Number(
121
- (value << BigInt(fpEndpoint.bitOffset)) & targetWireBitMask
122
- );
123
-
124
- // Set the wire value for the endpoint
125
- await device.setWireInValue(
126
- fpEndpoint.epAddress,
127
- targetWireValue,
128
- Number(targetWireBitMask)
129
- );
130
-
131
- if (targetWireSpanBitMask > 0xffffffffn) {
132
- // The operations spans multiple endpoints
133
- let currentWireSpanBitOffset = 32n - BigInt(fpEndpoint.bitOffset);
134
- let currentWireSpanBitMask = targetWireSpanBitMask >> 32n;
135
-
136
- for (
137
- let targetWireAddress = fpEndpoint.epAddress + 1;
138
- targetWireAddress <= WIREIN_ADDRESS_RANGE.Maximum &&
139
- currentWireSpanBitMask > 0n;
140
- targetWireAddress++
141
- ) {
142
- targetWireBitMask = currentWireSpanBitMask & 0xffffffffn;
143
- targetWireValue = Number(
144
- (value >> currentWireSpanBitOffset) & targetWireBitMask
145
- );
146
-
147
- // Set the wire value for the next endpoint
148
- await device.setWireInValue(
149
- targetWireAddress,
150
- targetWireValue,
151
- Number(targetWireBitMask)
152
- );
153
-
154
- currentWireSpanBitOffset += 32n;
155
- currentWireSpanBitMask >>= 32n;
120
+ if (device != null && workQueue != null) {
121
+ await workQueue.Post(async () => {
122
+ let targetWireBitMask = targetWireSpanBitMask & 0xffffffffn;
123
+ let targetWireValue = Number(
124
+ (value << BigInt(fpEndpoint.bitOffset)) & targetWireBitMask
125
+ );
126
+
127
+ // Set the wire value for the endpoint
128
+ device.setWireInValue(
129
+ fpEndpoint.epAddress,
130
+ targetWireValue,
131
+ Number(targetWireBitMask)
132
+ );
133
+
134
+ if (targetWireSpanBitMask > 0xffffffffn) {
135
+ // The operations spans multiple endpoints
136
+ let currentWireSpanBitOffset = 32n - BigInt(fpEndpoint.bitOffset);
137
+ let currentWireSpanBitMask = targetWireSpanBitMask >> 32n;
138
+
139
+ for (
140
+ let targetWireAddress = fpEndpoint.epAddress + 1;
141
+ targetWireAddress <= WIREIN_ADDRESS_RANGE.Maximum &&
142
+ currentWireSpanBitMask > 0n;
143
+ targetWireAddress++
144
+ ) {
145
+ targetWireBitMask = currentWireSpanBitMask & 0xffffffffn;
146
+ targetWireValue = Number(
147
+ (value >> currentWireSpanBitOffset) & targetWireBitMask
148
+ );
149
+
150
+ // Set the wire value for the next endpoint
151
+ device.setWireInValue(
152
+ targetWireAddress,
153
+ targetWireValue,
154
+ Number(targetWireBitMask)
155
+ );
156
+
157
+ currentWireSpanBitOffset += 32n;
158
+ currentWireSpanBitMask >>= 32n;
159
+ }
156
160
  }
157
- }
158
161
 
159
- await device.updateWireIns();
160
- });
162
+ await device.updateWireIns();
163
+ });
164
+ }
161
165
 
162
166
  onUpdateWireValue(device);
163
167
  },
@@ -168,6 +172,7 @@ const FrontPanelNumberEntry = React.forwardRef<
168
172
  <NumberEntry
169
173
  {...rootProps}
170
174
  ref={forwardedRef}
175
+ disabled={disabled || device === null}
171
176
  maximumValue={maximumValue}
172
177
  minimumValue={clampedMinimumValue}
173
178
  value={value}
@@ -47,28 +47,33 @@ const FrontPanelPushButton = React.forwardRef<
47
47
  >((props, forwardedRef) => {
48
48
  const { device, workQueue } = React.useContext(FrontPanelContext);
49
49
 
50
- const { fpEndpoint, ...buttonProps } = props;
50
+ const { fpEndpoint, disabled, ...buttonProps } = props;
51
51
 
52
52
  const targetWireBitMask = 1 << fpEndpoint.bitOffset;
53
53
 
54
54
  const onButtonUp = React.useCallback(async (): Promise<void> => {
55
- await workQueue.Post(async () => {
56
- await device.setWireInValue(fpEndpoint.epAddress, 0, targetWireBitMask);
57
- await device.updateWireIns();
58
- });
59
- }, [device, fpEndpoint, targetWireBitMask, workQueue]);
55
+ if (device != null && workQueue != null) {
56
+ await workQueue.Post(async () => {
57
+ device.setWireInValue(fpEndpoint.epAddress, 0, targetWireBitMask);
58
+ await device.updateWireIns();
59
+ });
60
+ }
61
+ }, [device, workQueue, fpEndpoint, targetWireBitMask, workQueue]);
60
62
 
61
63
  const onButtonDown = React.useCallback(async (): Promise<void> => {
62
- await workQueue.Post(async () => {
63
- await device.setWireInValue(fpEndpoint.epAddress, 0xffffffff, targetWireBitMask);
64
- await device.updateWireIns();
65
- });
66
- }, [device, fpEndpoint, targetWireBitMask, workQueue]);
64
+ if (device != null && workQueue != null) {
65
+ await workQueue.Post(async () => {
66
+ device.setWireInValue(fpEndpoint.epAddress, 0xffffffff, targetWireBitMask);
67
+ await device.updateWireIns();
68
+ });
69
+ }
70
+ }, [device, workQueue, fpEndpoint, targetWireBitMask, workQueue]);
67
71
 
68
72
  return (
69
73
  <Button
70
74
  {...buttonProps}
71
75
  ref={forwardedRef}
76
+ disabled={disabled || device == null}
72
77
  onButtonUp={onButtonUp}
73
78
  onButtonDown={onButtonDown}
74
79
  />
@@ -53,7 +53,7 @@ const FrontPanelRangeSlider = React.forwardRef<
53
53
 
54
54
  const { device, workQueue } = React.useContext(FrontPanelContext);
55
55
 
56
- const { fpEndpoint, maximumValue, ...rootProps } = props;
56
+ const { fpEndpoint, maximumValue, disabled, ...rootProps } = props;
57
57
 
58
58
  const targetBitLength: number = React.useMemo(() => {
59
59
  return CalculateBitLength(BigInt(maximumValue));
@@ -63,29 +63,33 @@ const FrontPanelRangeSlider = React.forwardRef<
63
63
  ((1n << BigInt(targetBitLength)) - 1n) << BigInt(fpEndpoint.bitOffset);
64
64
 
65
65
  const onUpdateWireValue = React.useCallback(
66
- async (sender: IFrontPanel): Promise<void> => {
67
- await workQueue.Post(async () => {
68
- const sourceWireValue = await sender.getWireInValue(fpEndpoint.epAddress);
66
+ (sender?: IFrontPanel): void => {
67
+ if (sender != null && workQueue != null) {
68
+ const sourceWireValue = sender.getWireInValue(fpEndpoint.epAddress);
69
69
  const sourceValue =
70
70
  (BigInt(sourceWireValue) & targetWireBitMask) >> BigInt(fpEndpoint.bitOffset);
71
71
  setValue(sourceValue);
72
- });
72
+ } else {
73
+ setValue(0n);
74
+ }
73
75
  },
74
- [fpEndpoint, targetWireBitMask]
76
+ [workQueue, fpEndpoint, targetWireBitMask]
75
77
  );
76
78
 
77
79
  const onSelectedValueChangeHandler = React.useCallback(
78
80
  (value: number) => {
79
- workQueue.Post(async () => {
80
- await device.setWireInValue(
81
- fpEndpoint.epAddress,
82
- value << fpEndpoint.bitOffset,
83
- Number(targetWireBitMask)
84
- );
85
- await device.updateWireIns();
86
- });
81
+ if (device != null && workQueue != null) {
82
+ workQueue.Post(async () => {
83
+ device.setWireInValue(
84
+ fpEndpoint.epAddress,
85
+ value << fpEndpoint.bitOffset,
86
+ Number(targetWireBitMask)
87
+ );
88
+ await device.updateWireIns();
89
+ });
90
+ }
87
91
  },
88
- [device, fpEndpoint, workQueue, targetWireBitMask]
92
+ [device, workQueue, fpEndpoint, workQueue, targetWireBitMask]
89
93
  );
90
94
 
91
95
  React.useEffect(() => {
@@ -96,6 +100,7 @@ const FrontPanelRangeSlider = React.forwardRef<
96
100
  <RangeSlider
97
101
  {...rootProps}
98
102
  ref={forwardedRef}
103
+ disabled={disabled || device == null}
99
104
  defaultValue={Number(value)}
100
105
  maximumValue={maximumValue}
101
106
  onValueChange={onSelectedValueChangeHandler}
@@ -57,7 +57,7 @@ const FrontPanelSelectEntryRoot: React.FC<FrontPanelSelectEntryRootCombinedProps
57
57
 
58
58
  const { device, workQueue } = React.useContext(FrontPanelContext);
59
59
 
60
- const { fpEndpoint, maximumValue, ...rootProps } = props;
60
+ const { fpEndpoint, maximumValue, disabled, ...rootProps } = props;
61
61
 
62
62
  const targetBitLength: number = React.useMemo(() => {
63
63
  return CalculateBitLength(maximumValue);
@@ -67,10 +67,10 @@ const FrontPanelSelectEntryRoot: React.FC<FrontPanelSelectEntryRootCombinedProps
67
67
  ((1n << BigInt(targetBitLength)) - 1n) << BigInt(fpEndpoint.bitOffset);
68
68
 
69
69
  const onUpdateWireValue = React.useCallback(
70
- async (sender: IFrontPanel): Promise<void> => {
71
- await workQueue.Post(async () => {
70
+ (sender?: IFrontPanel): void => {
71
+ if (sender != null && workQueue != null) {
72
72
  // Get the wire value for the endpoint
73
- let sourceWireValue = await sender.getWireInValue(fpEndpoint.epAddress);
73
+ let sourceWireValue = sender.getWireInValue(fpEndpoint.epAddress);
74
74
  let targetWireBitMask = targetWireSpanBitMask & 0xffffffffn;
75
75
  let sourceSpanValue =
76
76
  (BigInt(sourceWireValue) & targetWireBitMask) >> BigInt(fpEndpoint.bitOffset);
@@ -87,7 +87,7 @@ const FrontPanelSelectEntryRoot: React.FC<FrontPanelSelectEntryRootCombinedProps
87
87
  sourceWireAddress++
88
88
  ) {
89
89
  // Get the wire value for the next endpoint
90
- sourceWireValue = await sender.getWireInValue(sourceWireAddress);
90
+ sourceWireValue = sender.getWireInValue(sourceWireAddress);
91
91
  targetWireBitMask = currentWireSpanBitMask & 0xffffffffn;
92
92
  sourceSpanValue |=
93
93
  (BigInt(sourceWireValue) & targetWireBitMask) <<
@@ -99,62 +99,67 @@ const FrontPanelSelectEntryRoot: React.FC<FrontPanelSelectEntryRootCombinedProps
99
99
  }
100
100
 
101
101
  setValue(sourceSpanValue);
102
- });
102
+ } else {
103
+ setValue(0n);
104
+ }
103
105
  },
104
- [fpEndpoint, targetWireSpanBitMask]
106
+ [workQueue, fpEndpoint, targetWireSpanBitMask]
105
107
  );
106
108
 
107
109
  const onSelectedValueChangeHandler = React.useCallback(
108
110
  (value: string) => {
109
- const targetWireSpanValue = BigInt(value);
110
- workQueue.Post(async () => {
111
- let targetWireBitMask = targetWireSpanBitMask & 0xffffffffn;
112
- let targetWireValue = Number(
113
- (targetWireSpanValue << BigInt(fpEndpoint.bitOffset)) & targetWireBitMask
114
- );
115
-
116
- // Set the wire value for the endpoint
117
- await device.setWireInValue(
118
- fpEndpoint.epAddress,
119
- targetWireValue,
120
- Number(targetWireBitMask)
121
- );
122
-
123
- if (targetWireSpanBitMask > 0xffffffffn) {
124
- // The operations spans multiple endpoints
125
- let currentWireSpanBitOffset = 32n - BigInt(fpEndpoint.bitOffset);
126
- let currentWireSpanBitMask = targetWireSpanBitMask >> 32n;
127
-
128
- const maxWireCount = 0x20 - fpEndpoint.epAddress;
129
-
130
- for (
131
- let wireIndex = 1;
132
- wireIndex < maxWireCount && currentWireSpanBitMask > 0n;
133
- wireIndex++
134
- ) {
135
- targetWireBitMask = currentWireSpanBitMask & 0xffffffffn;
136
- targetWireValue = Number(
137
- (targetWireSpanValue >> currentWireSpanBitOffset) & targetWireBitMask
138
- );
139
-
140
- // Set the wire value for the next endpoint
141
- await device.setWireInValue(
142
- fpEndpoint.epAddress + wireIndex,
143
- targetWireValue,
144
- Number(targetWireBitMask)
145
- );
146
-
147
- currentWireSpanBitOffset += 32n;
148
- currentWireSpanBitMask >>= 32n;
111
+ if (device != null && workQueue != null) {
112
+ const targetWireSpanValue = BigInt(value);
113
+ workQueue.Post(async () => {
114
+ let targetWireBitMask = targetWireSpanBitMask & 0xffffffffn;
115
+ let targetWireValue = Number(
116
+ (targetWireSpanValue << BigInt(fpEndpoint.bitOffset)) & targetWireBitMask
117
+ );
118
+
119
+ // Set the wire value for the endpoint
120
+ device.setWireInValue(
121
+ fpEndpoint.epAddress,
122
+ targetWireValue,
123
+ Number(targetWireBitMask)
124
+ );
125
+
126
+ if (targetWireSpanBitMask > 0xffffffffn) {
127
+ // The operations spans multiple endpoints
128
+ let currentWireSpanBitOffset = 32n - BigInt(fpEndpoint.bitOffset);
129
+ let currentWireSpanBitMask = targetWireSpanBitMask >> 32n;
130
+
131
+ const maxWireCount = 0x20 - fpEndpoint.epAddress;
132
+
133
+ for (
134
+ let wireIndex = 1;
135
+ wireIndex < maxWireCount && currentWireSpanBitMask > 0n;
136
+ wireIndex++
137
+ ) {
138
+ targetWireBitMask = currentWireSpanBitMask & 0xffffffffn;
139
+ targetWireValue = Number(
140
+ (targetWireSpanValue >> currentWireSpanBitOffset) &
141
+ targetWireBitMask
142
+ );
143
+
144
+ // Set the wire value for the next endpoint
145
+ device.setWireInValue(
146
+ fpEndpoint.epAddress + wireIndex,
147
+ targetWireValue,
148
+ Number(targetWireBitMask)
149
+ );
150
+
151
+ currentWireSpanBitOffset += 32n;
152
+ currentWireSpanBitMask >>= 32n;
153
+ }
149
154
  }
150
- }
151
155
 
152
- await device.updateWireIns();
153
- });
156
+ await device.updateWireIns();
157
+ });
158
+ }
154
159
 
155
160
  onUpdateWireValue(device);
156
161
  },
157
- [device, fpEndpoint, workQueue, onUpdateWireValue]
162
+ [device, workQueue, fpEndpoint, onUpdateWireValue]
158
163
  );
159
164
 
160
165
  React.useEffect(() => {
@@ -164,6 +169,7 @@ const FrontPanelSelectEntryRoot: React.FC<FrontPanelSelectEntryRootCombinedProps
164
169
  return (
165
170
  <SelectEntry.Root
166
171
  {...rootProps}
172
+ disabled={disabled || device == null}
167
173
  value={value.toString()}
168
174
  onValueChange={onSelectedValueChangeHandler}
169
175
  />
@@ -53,40 +53,41 @@ const FrontPanelToggleSwitch = React.forwardRef<
53
53
 
54
54
  const { device, workQueue } = React.useContext(FrontPanelContext);
55
55
 
56
- const { fpEndpoint, ...buttonProps } = props;
56
+ const { fpEndpoint, disabled, ...buttonProps } = props;
57
57
 
58
58
  const targetWireBitMask = 1 << fpEndpoint.bitOffset;
59
59
 
60
60
  const onUpdateWireValue = React.useCallback(
61
- async (sender: IFrontPanel): Promise<void> => {
62
- await workQueue.Post(async () => {
61
+ (sender?: IFrontPanel): void => {
62
+ if (sender != null && workQueue != null) {
63
63
  // Set the toggle state based on the value of the target bit of the Wire endpoint
64
- const sourceWireValue = await sender.getWireInValue(fpEndpoint.epAddress);
64
+ const sourceWireValue = sender.getWireInValue(fpEndpoint.epAddress);
65
65
  const sourceBitValue = (sourceWireValue & targetWireBitMask) === targetWireBitMask;
66
66
  const newToggleState = sourceBitValue ? ToggleState.On : ToggleState.Off;
67
67
  setState(newToggleState);
68
- });
68
+ } else {
69
+ setState(ToggleState.Off);
70
+ }
69
71
  },
70
- [fpEndpoint, targetWireBitMask]
72
+ [workQueue, fpEndpoint, targetWireBitMask]
71
73
  );
72
74
 
73
75
  const onToggleStateChanged = React.useCallback(
74
76
  async (state: ToggleState): Promise<void> => {
75
- await workQueue.Post(async () => {
76
- // Set the value of the target bit of the Wire endpoint based on the toggle state
77
- const targetWireValue: WireValue = state === ToggleState.On ? 0xffffffff : 0;
78
-
79
- await device.setWireInValue(
80
- fpEndpoint.epAddress,
81
- targetWireValue,
82
- targetWireBitMask
83
- );
84
- await device.updateWireIns();
85
- });
77
+ if (device != null && workQueue != null) {
78
+ await workQueue.Post(async () => {
79
+ // Set the value of the target bit of the Wire endpoint based on the toggle state
80
+ const targetWireValue: WireValue = state === ToggleState.On ? 0xffffffff : 0;
81
+
82
+ device.setWireInValue(fpEndpoint.epAddress, targetWireValue, targetWireBitMask);
83
+
84
+ await device.updateWireIns();
85
+ });
86
+ }
86
87
 
87
88
  onUpdateWireValue(device);
88
89
  },
89
- [device, fpEndpoint, targetWireBitMask, workQueue]
90
+ [device, workQueue, fpEndpoint, targetWireBitMask]
90
91
  );
91
92
 
92
93
  React.useEffect(() => {
@@ -97,6 +98,7 @@ const FrontPanelToggleSwitch = React.forwardRef<
97
98
  <ToggleSwitch
98
99
  ref={forwardedRef}
99
100
  {...buttonProps}
101
+ disabled={disabled || device == null}
100
102
  state={state}
101
103
  onToggleStateChanged={onToggleStateChanged}
102
104
  />
@@ -49,15 +49,24 @@ const FrontPanelTriggerButton = React.forwardRef<
49
49
  >((props, forwardedRef) => {
50
50
  const { device, workQueue } = React.useContext(FrontPanelContext);
51
51
 
52
- const { fpEndpoint, ...buttonProps } = props;
52
+ const { fpEndpoint, disabled, ...buttonProps } = props;
53
53
 
54
54
  const onButtonDown = React.useCallback(async (): Promise<void> => {
55
- await workQueue.Post(async () => {
56
- await device.activateTriggerIn(fpEndpoint.epAddress, fpEndpoint.bitOffset);
57
- });
58
- }, [device, fpEndpoint]);
55
+ if (device != null && workQueue != null) {
56
+ await workQueue.Post(async () => {
57
+ await device.activateTriggerIn(fpEndpoint.epAddress, fpEndpoint.bitOffset);
58
+ });
59
+ }
60
+ }, [device, workQueue, fpEndpoint]);
59
61
 
60
- return <Button {...buttonProps} ref={forwardedRef} onButtonDown={onButtonDown} />;
62
+ return (
63
+ <Button
64
+ {...buttonProps}
65
+ ref={forwardedRef}
66
+ disabled={disabled || device == null}
67
+ onButtonDown={onButtonDown}
68
+ />
69
+ );
61
70
  });
62
71
 
63
72
  FrontPanelTriggerButton.displayName = "FrontPanelTriggerButton";
@@ -10,14 +10,11 @@ import React from "react";
10
10
  import { IFrontPanel, IFrontPanelEventSource, WorkQueue } from "@opalkelly/frontpanel-alloy-core";
11
11
 
12
12
  export type FrontPanelContextValue = {
13
- device: IFrontPanel;
14
- workQueue: WorkQueue;
13
+ device?: IFrontPanel;
14
+ workQueue?: WorkQueue;
15
15
  eventSource?: IFrontPanelEventSource;
16
16
  };
17
17
 
18
- const FrontPanelContext = React.createContext<FrontPanelContextValue>({
19
- device: window.FrontPanel,
20
- workQueue: new WorkQueue()
21
- });
18
+ const FrontPanelContext = React.createContext<FrontPanelContextValue>({});
22
19
 
23
20
  export default FrontPanelContext;