@adcops/autocore-react 3.0.40 → 3.1.5

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 (277) hide show
  1. package/.claude/settings.local.json +7 -0
  2. package/additional-docs/AutoCoreTagContext.md +441 -0
  3. package/dist/assets/BlocklyLogo.d.ts +1 -0
  4. package/dist/assets/BlocklyLogo.d.ts.map +1 -0
  5. package/dist/assets/Distance.d.ts +1 -0
  6. package/dist/assets/Distance.d.ts.map +1 -0
  7. package/dist/assets/JogLong.d.ts +1 -0
  8. package/dist/assets/JogLong.d.ts.map +1 -0
  9. package/dist/assets/JogMedium.d.ts +1 -0
  10. package/dist/assets/JogMedium.d.ts.map +1 -0
  11. package/dist/assets/JogShort.d.ts +1 -0
  12. package/dist/assets/JogShort.d.ts.map +1 -0
  13. package/dist/assets/PythonLogo.d.ts +1 -0
  14. package/dist/assets/PythonLogo.d.ts.map +1 -0
  15. package/dist/assets/Rotation3D.d.ts +1 -0
  16. package/dist/assets/Rotation3D.d.ts.map +1 -0
  17. package/dist/assets/RotationCcw.d.ts +1 -0
  18. package/dist/assets/RotationCcw.d.ts.map +1 -0
  19. package/dist/assets/RotationCcwA.d.ts +1 -0
  20. package/dist/assets/RotationCcwA.d.ts.map +1 -0
  21. package/dist/assets/RotationCcwB.d.ts +1 -0
  22. package/dist/assets/RotationCcwB.d.ts.map +1 -0
  23. package/dist/assets/RotationCcwC.d.ts +1 -0
  24. package/dist/assets/RotationCcwC.d.ts.map +1 -0
  25. package/dist/assets/RotationCw.d.ts +1 -0
  26. package/dist/assets/RotationCw.d.ts.map +1 -0
  27. package/dist/assets/RotationCwA.d.ts +1 -0
  28. package/dist/assets/RotationCwA.d.ts.map +1 -0
  29. package/dist/assets/RotationCwB.d.ts +1 -0
  30. package/dist/assets/RotationCwB.d.ts.map +1 -0
  31. package/dist/assets/RotationCwC.d.ts +1 -0
  32. package/dist/assets/RotationCwC.d.ts.map +1 -0
  33. package/dist/assets/Run.d.ts +1 -0
  34. package/dist/assets/Run.d.ts.map +1 -0
  35. package/dist/assets/Speed.d.ts +1 -0
  36. package/dist/assets/Speed.d.ts.map +1 -0
  37. package/dist/assets/SpeedFast.d.ts +1 -0
  38. package/dist/assets/SpeedFast.d.ts.map +1 -0
  39. package/dist/assets/SpeedMedium.d.ts +1 -0
  40. package/dist/assets/SpeedMedium.d.ts.map +1 -0
  41. package/dist/assets/SpeedNone.d.ts +1 -0
  42. package/dist/assets/SpeedNone.d.ts.map +1 -0
  43. package/dist/assets/SpeedSlow.d.ts +1 -0
  44. package/dist/assets/SpeedSlow.d.ts.map +1 -0
  45. package/dist/assets/Walk.d.ts +1 -0
  46. package/dist/assets/Walk.d.ts.map +1 -0
  47. package/dist/assets/index.d.ts +1 -0
  48. package/dist/assets/index.d.ts.map +1 -0
  49. package/dist/components/AutoCoreDevPanel.d.ts +144 -0
  50. package/dist/components/AutoCoreDevPanel.d.ts.map +1 -0
  51. package/dist/components/AutoCoreDevPanel.js +1 -0
  52. package/dist/components/BlocklyEditor.d.ts +1 -0
  53. package/dist/components/BlocklyEditor.d.ts.map +1 -0
  54. package/dist/components/BlocklyEditor.js +1 -1
  55. package/dist/components/CodeEditor.d.ts +2 -1
  56. package/dist/components/CodeEditor.d.ts.map +1 -0
  57. package/dist/components/CodeEditor.js +1 -1
  58. package/dist/components/FileList.d.ts +1 -0
  59. package/dist/components/FileList.d.ts.map +1 -0
  60. package/dist/components/FileList.js +1 -1
  61. package/dist/components/FileSelect.d.ts +1 -0
  62. package/dist/components/FileSelect.d.ts.map +1 -0
  63. package/dist/components/FileSelect.js +1 -1
  64. package/dist/components/FitText.d.ts +1 -0
  65. package/dist/components/FitText.d.ts.map +1 -0
  66. package/dist/components/FitText.js +1 -1
  67. package/dist/components/Indicator.d.ts +2 -1
  68. package/dist/components/Indicator.d.ts.map +1 -0
  69. package/dist/components/Indicator.js +1 -1
  70. package/dist/components/IndicatorButton.d.ts +2 -1
  71. package/dist/components/IndicatorButton.d.ts.map +1 -0
  72. package/dist/components/IndicatorButton.js +1 -1
  73. package/dist/components/IndicatorRect.d.ts +2 -1
  74. package/dist/components/IndicatorRect.d.ts.map +1 -0
  75. package/dist/components/JogPanel.d.ts +1 -0
  76. package/dist/components/JogPanel.d.ts.map +1 -0
  77. package/dist/components/Lamp.d.ts +2 -1
  78. package/dist/components/Lamp.d.ts.map +1 -0
  79. package/dist/components/Lamp.js +1 -1
  80. package/dist/components/Osk.d.ts +1 -0
  81. package/dist/components/Osk.d.ts.map +1 -0
  82. package/dist/components/Osk.js +1 -1
  83. package/dist/components/OskDialog.d.ts +1 -0
  84. package/dist/components/OskDialog.d.ts.map +1 -0
  85. package/dist/components/ProgressBarWithValue.d.ts +1 -0
  86. package/dist/components/ProgressBarWithValue.d.ts.map +1 -0
  87. package/dist/components/ProgressBarWithValue.js +1 -1
  88. package/dist/components/TextInput.d.ts +62 -103
  89. package/dist/components/TextInput.d.ts.map +1 -0
  90. package/dist/components/TextInput.js +1 -1
  91. package/dist/components/ToggleGroup.d.ts +2 -1
  92. package/dist/components/ToggleGroup.d.ts.map +1 -0
  93. package/dist/components/ToggleGroup.js +1 -1
  94. package/dist/components/ValueDisplay.d.ts +3 -2
  95. package/dist/components/ValueDisplay.d.ts.map +1 -0
  96. package/dist/components/ValueDisplay.js +1 -1
  97. package/dist/components/ValueIndicator.d.ts +2 -1
  98. package/dist/components/ValueIndicator.d.ts.map +1 -0
  99. package/dist/components/ValueIndicator.js +1 -1
  100. package/dist/components/ValueInput.d.ts +2 -1
  101. package/dist/components/ValueInput.d.ts.map +1 -0
  102. package/dist/components/ValueInput.js +1 -1
  103. package/dist/core/ActionMode.d.ts +1 -0
  104. package/dist/core/ActionMode.d.ts.map +1 -0
  105. package/dist/core/AutoCoreTagContext.d.ts +243 -0
  106. package/dist/core/AutoCoreTagContext.d.ts.map +1 -0
  107. package/dist/core/AutoCoreTagContext.js +1 -0
  108. package/dist/core/AutoCoreTagTypes.d.ts +162 -0
  109. package/dist/core/AutoCoreTagTypes.d.ts.map +1 -0
  110. package/dist/core/AutoCoreTagTypes.js +1 -0
  111. package/dist/core/EventEmitterContext.d.ts +295 -2
  112. package/dist/core/EventEmitterContext.d.ts.map +1 -0
  113. package/dist/core/EventEmitterContext.js +1 -1
  114. package/dist/core/IndicatorButtonState.d.ts +1 -0
  115. package/dist/core/IndicatorButtonState.d.ts.map +1 -0
  116. package/dist/core/IndicatorColor.d.ts +1 -0
  117. package/dist/core/IndicatorColor.d.ts.map +1 -0
  118. package/dist/core/MaskPatterns.d.ts +1 -0
  119. package/dist/core/MaskPatterns.d.ts.map +1 -0
  120. package/dist/core/NumerableTypes.d.ts +1 -0
  121. package/dist/core/NumerableTypes.d.ts.map +1 -0
  122. package/dist/core/NumerableTypes.js +1 -1
  123. package/dist/core/PositionContext.d.ts +1 -1
  124. package/dist/core/PositionContext.d.ts.map +1 -0
  125. package/dist/core/UniqueId.d.ts +1 -0
  126. package/dist/core/UniqueId.d.ts.map +1 -0
  127. package/dist/core/ValueSimulator.d.ts +2 -1
  128. package/dist/core/ValueSimulator.d.ts.map +1 -0
  129. package/dist/core/ValueSimulator.js +1 -1
  130. package/dist/core/hoc.d.ts +1 -0
  131. package/dist/core/hoc.d.ts.map +1 -0
  132. package/dist/core/hoc.js +1 -1
  133. package/dist/hooks/adsHooks.d.ts +1 -0
  134. package/dist/hooks/adsHooks.d.ts.map +1 -0
  135. package/dist/hooks/adsHooks.js +1 -1
  136. package/dist/hooks/commandHooks.d.ts +1 -0
  137. package/dist/hooks/commandHooks.d.ts.map +1 -0
  138. package/dist/hooks/commandHooks.js +1 -1
  139. package/dist/hooks/index.d.ts +1 -0
  140. package/dist/hooks/index.d.ts.map +1 -0
  141. package/dist/hooks/useAutoCoreTag.d.ts +26 -0
  142. package/dist/hooks/useAutoCoreTag.d.ts.map +1 -0
  143. package/dist/hooks/useAutoCoreTag.js +1 -0
  144. package/dist/hooks/useScaledValue.d.ts +1 -0
  145. package/dist/hooks/useScaledValue.d.ts.map +1 -0
  146. package/dist/hooks/useScaledValue.js +1 -1
  147. package/dist/hub/CommandMessage.d.ts +1 -0
  148. package/dist/hub/CommandMessage.d.ts.map +1 -0
  149. package/dist/hub/HubBase.d.ts +3 -2
  150. package/dist/hub/HubBase.d.ts.map +1 -0
  151. package/dist/hub/HubSimulate.d.ts +2 -1
  152. package/dist/hub/HubSimulate.d.ts.map +1 -0
  153. package/dist/hub/HubSimulate.js +1 -1
  154. package/dist/hub/HubTauri.d.ts +2 -1
  155. package/dist/hub/HubTauri.d.ts.map +1 -0
  156. package/dist/hub/HubTauri.js +1 -1
  157. package/dist/hub/HubWebSocket.d.ts +2 -1
  158. package/dist/hub/HubWebSocket.d.ts.map +1 -0
  159. package/dist/hub/HubWebSocket.js +1 -1
  160. package/dist/hub/index.d.ts +2 -1
  161. package/dist/hub/index.d.ts.map +1 -0
  162. package/dist/hub/index.js +1 -1
  163. package/dist/themes/adc-dark/blue/theme.css +305 -0
  164. package/dist/themes/adc-dark/blue/theme.css.map +1 -1
  165. package/package.json +33 -28
  166. package/readme.md +193 -22
  167. package/src/components/AutoCoreDevPanel.tsx +411 -0
  168. package/src/components/CodeEditor.tsx +2 -2
  169. package/src/components/FileList.tsx +2 -2
  170. package/src/components/FileSelect.tsx +31 -11
  171. package/src/components/Indicator.tsx +2 -2
  172. package/src/components/IndicatorButton.tsx +2 -2
  173. package/src/components/IndicatorRect.tsx +2 -2
  174. package/src/components/Lamp.tsx +3 -3
  175. package/src/components/TextInput.tsx +159 -240
  176. package/src/components/ToggleGroup.tsx +3 -3
  177. package/src/components/ValueDisplay.tsx +4 -4
  178. package/src/components/ValueIndicator.tsx +2 -2
  179. package/src/components/ValueInput.tsx +2 -2
  180. package/src/core/AutoCoreTagContext.tsx +1137 -0
  181. package/src/core/AutoCoreTagTypes.ts +202 -0
  182. package/src/core/EventEmitterContext.tsx +357 -43
  183. package/src/core/ValueSimulator.ts +2 -2
  184. package/src/hooks/useAutoCoreTag.ts +103 -0
  185. package/src/hub/HubBase.ts +3 -3
  186. package/src/hub/HubSimulate.ts +2 -2
  187. package/src/hub/HubTauri.ts +3 -3
  188. package/src/hub/HubWebSocket.ts +29 -32
  189. package/src/hub/index.ts +2 -2
  190. package/src/themes/adc-dark/_extensions.scss +327 -0
  191. package/tsconfig.json +43 -28
  192. package/docs/classes/components_BlocklyEditor.BlocklyEditor.html +0 -124
  193. package/docs/classes/components_CodeEditor.CodeEditor.html +0 -128
  194. package/docs/classes/components_JogPanel.JogPanel.html +0 -138
  195. package/docs/classes/components_Lamp.Lamp.html +0 -105
  196. package/docs/classes/components_TextInput.TextInput.html +0 -115
  197. package/docs/classes/components_ValueIndicator.ValueIndicator.html +0 -119
  198. package/docs/classes/components_ValueInput.ValueInput.html +0 -113
  199. package/docs/classes/hub_HubWebSocket.HubWebSocket.html +0 -106
  200. package/docs/enums/components_JogPanel.JogDistanceAction.html +0 -5
  201. package/docs/enums/components_JogPanel.JogPanelAction.html +0 -18
  202. package/docs/enums/components_JogPanel.JogSpeedAction.html +0 -5
  203. package/docs/enums/core_ActionMode.ActionMode.html +0 -6
  204. package/docs/enums/core_IndicatorColor.IndicatorColor.html +0 -23
  205. package/docs/functions/assets_BlocklyLogo.default.html +0 -1
  206. package/docs/functions/assets_Distance.default.html +0 -1
  207. package/docs/functions/assets_JogLong.default.html +0 -1
  208. package/docs/functions/assets_JogMedium.default.html +0 -1
  209. package/docs/functions/assets_JogShort.default.html +0 -1
  210. package/docs/functions/assets_PythonLogo.default.html +0 -1
  211. package/docs/functions/assets_Rotation3D.default.html +0 -1
  212. package/docs/functions/assets_RotationCcw.default.html +0 -1
  213. package/docs/functions/assets_RotationCcwA.default.html +0 -1
  214. package/docs/functions/assets_RotationCcwB.default.html +0 -1
  215. package/docs/functions/assets_RotationCcwC.default.html +0 -1
  216. package/docs/functions/assets_RotationCw.default.html +0 -1
  217. package/docs/functions/assets_RotationCwA.default.html +0 -1
  218. package/docs/functions/assets_RotationCwB.default.html +0 -1
  219. package/docs/functions/assets_RotationCwC.default.html +0 -1
  220. package/docs/functions/assets_Run.default.html +0 -1
  221. package/docs/functions/assets_Speed.default.html +0 -1
  222. package/docs/functions/assets_SpeedFast.default.html +0 -1
  223. package/docs/functions/assets_SpeedMedium.default.html +0 -1
  224. package/docs/functions/assets_SpeedNone.default.html +0 -1
  225. package/docs/functions/assets_SpeedSlow.default.html +0 -1
  226. package/docs/functions/assets_Walk.default.html +0 -1
  227. package/docs/functions/components_BlocklyEditor.createCustomToolbox.html +0 -6
  228. package/docs/functions/components_FileList.FileList.html +0 -21
  229. package/docs/functions/components_FitText.FitText.html +0 -8
  230. package/docs/functions/components_ToggleGroup.ToggleGroup.html +0 -5
  231. package/docs/interfaces/components_JogPanel.JogPanelButtonDefinition.html +0 -5
  232. package/docs/interfaces/components_ToggleGroup.ToggleGroupProps.html +0 -618
  233. package/docs/interfaces/core_IndicatorButtonState.IndicatorButtonState.html +0 -10
  234. package/docs/interfaces/hub_CommandMessage.CommandMessage.html +0 -6
  235. package/docs/interfaces/hub_CommandMessage.CommandMessageResult.html +0 -4
  236. package/docs/modules/assets.html +0 -23
  237. package/docs/modules/assets_BlocklyLogo.html +0 -2
  238. package/docs/modules/assets_Distance.html +0 -2
  239. package/docs/modules/assets_JogLong.html +0 -2
  240. package/docs/modules/assets_JogMedium.html +0 -2
  241. package/docs/modules/assets_JogShort.html +0 -2
  242. package/docs/modules/assets_PythonLogo.html +0 -2
  243. package/docs/modules/assets_Rotation3D.html +0 -2
  244. package/docs/modules/assets_RotationCcw.html +0 -2
  245. package/docs/modules/assets_RotationCcwA.html +0 -2
  246. package/docs/modules/assets_RotationCcwB.html +0 -2
  247. package/docs/modules/assets_RotationCcwC.html +0 -2
  248. package/docs/modules/assets_RotationCw.html +0 -2
  249. package/docs/modules/assets_RotationCwA.html +0 -2
  250. package/docs/modules/assets_RotationCwB.html +0 -2
  251. package/docs/modules/assets_RotationCwC.html +0 -2
  252. package/docs/modules/assets_Run.html +0 -2
  253. package/docs/modules/assets_Speed.html +0 -2
  254. package/docs/modules/assets_SpeedFast.html +0 -2
  255. package/docs/modules/assets_SpeedMedium.html +0 -2
  256. package/docs/modules/assets_SpeedNone.html +0 -2
  257. package/docs/modules/assets_SpeedSlow.html +0 -2
  258. package/docs/modules/assets_Walk.html +0 -2
  259. package/docs/modules/components_BlocklyEditor.html +0 -5
  260. package/docs/modules/components_CodeEditor.html +0 -3
  261. package/docs/modules/components_FileList.html +0 -3
  262. package/docs/modules/components_FitText.html +0 -3
  263. package/docs/modules/components_JogPanel.html +0 -9
  264. package/docs/modules/components_Lamp.html +0 -4
  265. package/docs/modules/components_TextInput.html +0 -2
  266. package/docs/modules/components_ToggleGroup.html +0 -6
  267. package/docs/modules/components_ValueIndicator.html +0 -4
  268. package/docs/modules/components_ValueInput.html +0 -2
  269. package/docs/modules/core_ActionMode.html +0 -2
  270. package/docs/modules/core_IndicatorButtonState.html +0 -2
  271. package/docs/modules/core_IndicatorColor.html +0 -2
  272. package/docs/modules/hub_CommandMessage.html +0 -3
  273. package/docs/modules/hub_HubWebSocket.html +0 -2
  274. package/docs/types/components_IndicatorButton.IndicatorButtonOptionsType.html +0 -1
  275. package/docs/variables/components_BlocklyEditor.StandardToolbox.html +0 -1
  276. package/docs/variables/components_JogPanel.DefaultLinearJogButtons.html +0 -2
  277. package/docs/variables/components_JogPanel.DefaultRotationJogButtons.html +0 -2
@@ -0,0 +1,103 @@
1
+ /*
2
+ * Copyright (C) 2025 Automated Design Corp.. All Rights Reserved.
3
+ * Created Date: 2025-09-05 08:03:32
4
+ * -----
5
+ * Last Modified: 2025-09-10 10:22:31
6
+ * -----
7
+ *
8
+ */
9
+
10
+ /**
11
+ * @module hooks/useAutoCoreTag.ts
12
+ *
13
+ * Factory for generating strongly-typed React hooks to consume AutoCoreTagContext.
14
+ */
15
+
16
+ import { useCallback, useContext, useMemo } from "react";
17
+ import type { BaseContextValue, TagConfig, TagValueMap } from "../core/AutoCoreTagTypes";
18
+
19
+ export function makeAutoCoreTagHooks<Spec extends readonly TagConfig[]>(
20
+ Context: React.Context<BaseContextValue<TagValueMap<Spec>>>,
21
+ tags: Spec
22
+ ) {
23
+ type VMap = TagValueMap<Spec>;
24
+ type TagNames = keyof VMap & string;
25
+
26
+ const findCfg = (tagName: string) =>
27
+ tags.find(t => t.tagName === tagName) as (Spec[number] | undefined);
28
+
29
+ /**
30
+ * Access a single tag by name.
31
+ * Returns current value, raw value, direct server writer, and tap helper.
32
+ */
33
+ const useAutoCoreTag = <K extends TagNames>(tagName: K) => {
34
+ const { values, rawValues, isLoading, write: ctxWrite, tap: ctxTap } = useContext(Context);
35
+
36
+ const cfg = findCfg(tagName as string);
37
+ if (!cfg) throw new Error(`useAutoCoreTag: unknown tagName '${String(tagName)}'`);
38
+
39
+ const write = useCallback(
40
+ (displayValue: VMap[K]) => ctxWrite(tagName, displayValue),
41
+ [ctxWrite, tagName]
42
+ );
43
+
44
+ const tap = useCallback(() => ctxTap?.(tagName), [ctxTap, tagName]);
45
+
46
+ return {
47
+ value: values[tagName] as VMap[K],
48
+ rawValue: rawValues[tagName as string],
49
+ write,
50
+ tap,
51
+ isLoading,
52
+ } as const;
53
+ };
54
+
55
+ /**
56
+ * Access multiple tags at once with a bulk writer.
57
+ */
58
+ const useAutoCoreTags = <K extends TagNames>(tagNames: readonly K[]) => {
59
+ const { values, rawValues, isLoading, write: ctxWrite } = useContext(Context);
60
+
61
+ const subset = useMemo(
62
+ () =>
63
+ Object.fromEntries(
64
+ tagNames.map(k => [k, values[k] as VMap[K]])
65
+ ) as { [P in K]: VMap[P] },
66
+ [values, tagNames]
67
+ );
68
+
69
+ const rawSubset = useMemo(
70
+ () =>
71
+ Object.fromEntries(
72
+ tagNames.map(k => [k, rawValues[k as string]])
73
+ ) as { [P in K]: unknown },
74
+ [rawValues, tagNames]
75
+ );
76
+
77
+ const write = useCallback(async (tagName: K, value: VMap[K]) => {
78
+ await ctxWrite(tagName, value);
79
+ }, [ctxWrite]);
80
+
81
+ return { values: subset, rawValues: rawSubset, write, isLoading } as const;
82
+ };
83
+
84
+ /**
85
+ * Compute a derived value from the full tag state.
86
+ */
87
+ const useAutoCoreSelect = <R>(selector: (all: Readonly<Partial<VMap>>) => R, deps: any[] = []) => {
88
+ const { values, isLoading } = useContext(Context);
89
+ const selected = useMemo(() => selector(values), [values, ...deps]);
90
+ return { selected, isLoading } as const;
91
+ };
92
+
93
+ /**
94
+ * Access scale configurations and update functions.
95
+ */
96
+ const useScales = () => {
97
+ const { scales, updateScale } = useContext(Context);
98
+ const getScale = useCallback((scaleName: string) => scales[scaleName], [scales]);
99
+ return { scales, updateScale, getScale } as const;
100
+ };
101
+
102
+ return { useAutoCoreTag, useAutoCoreTags, useAutoCoreSelect, useScales } as const;
103
+ }
@@ -3,14 +3,14 @@
3
3
  * Created Date: 2023-12-15 14:21:33
4
4
  * Author: Thomas C. Bitsky Jr.
5
5
  * -----
6
- * Last Modified: 2025-03-31 08:35:09
6
+ * Last Modified: 2025-09-05 14:50:03
7
7
  * Modified By: ADC
8
8
  * -----
9
9
  *
10
10
  */
11
11
 
12
- import { EventEmitterContextType} from '../core/EventEmitterContext';
13
- import {CommandMessageResult} from "./CommandMessage";
12
+ import type { EventEmitterContextType} from '../core/EventEmitterContext';
13
+ import type {CommandMessageResult} from "./CommandMessage";
14
14
 
15
15
 
16
16
  /**
@@ -2,7 +2,7 @@
2
2
  * Copyright (C) 2023 Automated Design Corp. All Rights Reserved.
3
3
  * Created Date: 2023-12-17 10:38:21
4
4
  * -----
5
- * Last Modified: 2024-04-24 11:56:26
5
+ * Last Modified: 2025-09-05 14:49:57
6
6
  * Modified By: ADC
7
7
  * -----
8
8
  *
@@ -10,7 +10,7 @@
10
10
 
11
11
 
12
12
  import { HubBase } from './HubBase';
13
- import { CommandMessageResult } from "./CommandMessage";
13
+ import type { CommandMessageResult } from "./CommandMessage";
14
14
  /**
15
15
  * Hub for simulating functionality when no backend is present.
16
16
  */
@@ -3,16 +3,16 @@
3
3
  * Created Date: 2023-12-17 09:50:23
4
4
  * Author: Thomas C. Bitsky Jr.
5
5
  * -----
6
- * Last Modified: 2024-04-24 11:56:32
6
+ * Last Modified: 2025-09-05 14:53:18
7
7
  * Modified By: ADC
8
8
  * -----
9
9
  *
10
10
  */
11
11
 
12
- import { InvokeArgs } from '@tauri-apps/api/tauri';
12
+ import type { InvokeArgs } from '@tauri-apps/api/tauri';
13
13
  import { HubBase } from './HubBase';
14
14
  import {event, invoke} from '@tauri-apps/api';
15
- import {CommandMessageResult} from "./CommandMessage";
15
+ import type {CommandMessageResult} from "./CommandMessage";
16
16
 
17
17
  /**
18
18
  * Hub for integrating with the Tauri backend.
@@ -2,7 +2,7 @@
2
2
  * Copyright (C) 2024 Automated Design Corp.. All Rights Reserved.
3
3
  * Created Date: 2024-04-17 09:13:07
4
4
  * -----
5
- * Last Modified: 2025-03-31 08:35:12
5
+ * Last Modified: 2025-09-05 15:18:44
6
6
  * -----
7
7
  *
8
8
  */
@@ -22,7 +22,7 @@
22
22
  */
23
23
 
24
24
  import { HubBase } from './HubBase';
25
- import {CommandMessage, CommandMessageResult} from "./CommandMessage";
25
+ import type { CommandMessage, CommandMessageResult } from "./CommandMessage";
26
26
 
27
27
  // Function to parse the JSON string received from the server into a CommandMessage object
28
28
  // function parseCommandMessage(jsonString: string): CommandMessage {
@@ -57,31 +57,28 @@ interface RequestRecord {
57
57
  * @returns {Blob} A Blob object representing the decoded binary data.
58
58
  */
59
59
  function b64toBlob(
60
- b64Data: string,
61
- contentType: string = 'application/octet-stream',
60
+ b64Data: string,
61
+ contentType: string = "application/octet-stream",
62
62
  sliceSize: number = 512
63
63
  ): Blob {
64
-
65
64
  const byteCharacters = atob(b64Data);
66
- const byteArrays: Uint8Array[] = [];
65
+ const buffers: ArrayBuffer[] = [];
67
66
 
68
67
  for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
69
68
  const slice = byteCharacters.slice(offset, offset + sliceSize);
70
69
 
71
- const byteNumbers: number[] = new Array(slice.length);
72
- for (let i = 0; i < slice.length; i++) {
73
- byteNumbers[i] = slice.charCodeAt(i);
74
- }
70
+ const byteNumbers = new Array<number>(slice.length);
71
+ for (let i = 0; i < slice.length; i++) byteNumbers[i] = slice.charCodeAt(i);
75
72
 
76
- const byteArray = new Uint8Array(byteNumbers);
77
- byteArrays.push(byteArray);
73
+ const uint8 = new Uint8Array(byteNumbers);
74
+ buffers.push(uint8.buffer as ArrayBuffer); // <-- pass ArrayBuffer to Blob
78
75
  }
79
76
 
80
- const blob = new Blob(byteArrays, { type: contentType });
81
- return blob;
77
+ return new Blob(buffers, { type: contentType });
82
78
  }
83
79
 
84
80
 
81
+
85
82
  /**
86
83
  * Creates a temporary hyperlink in the document and programmatically triggers a download of the Blob provided.
87
84
  *
@@ -129,9 +126,9 @@ export class HubWebSocket extends HubBase {
129
126
  */
130
127
  constructor() {
131
128
  super();
132
-
129
+
133
130
  const host = window.location.hostname; // Get the hostname from the address bar
134
-
131
+
135
132
  // Default to using autocore-server.
136
133
  let port = undefined; // window.location.port; // Get the port from the address bar, if any
137
134
 
@@ -146,13 +143,13 @@ export class HubWebSocket extends HubBase {
146
143
  //
147
144
  // Websocket connection established.
148
145
  //
149
- this.socket.onopen = function() {
146
+ this.socket.onopen = function () {
150
147
  console.log("WebSocket connection established.");
151
148
  self.publish("HUB/connected", true);
152
149
  self.setIsConnected(true);
153
150
  };
154
-
155
-
151
+
152
+
156
153
  // Message recevied via the websocket connection.
157
154
  //
158
155
  this.socket.onmessage = (event) => {
@@ -164,22 +161,22 @@ export class HubWebSocket extends HubBase {
164
161
 
165
162
  const { resolve, reject } = this.pendingRequests.get(data.request_id)!;
166
163
 
167
- if (data.fname === "FILE_DOWNLOAD"
164
+ if (data.fname === "FILE_DOWNLOAD"
168
165
  && data.args["file_name"] !== undefined && data.args["file_name"] !== null
169
166
  && data.args["file_name"].length > 0
170
167
  ) {
171
168
 
172
169
  // The file name was supplied in the original request
173
170
  let tokens = data.args["file_name"].split("/");
174
-
175
- const filename = tokens[tokens.length - 1];
171
+
172
+ const filename = tokens[tokens.length - 1];
176
173
  if (data.result && data.result.success) {
177
174
  const blob = b64toBlob(data.result.data);
178
175
  downloadBlob(blob, filename);
179
-
176
+
180
177
  // Don't send the whole file through; that's crazy.
181
178
  data.result.data = filename;
182
-
179
+
183
180
  // Signal the function that initiated the download that all is well.
184
181
  resolve(data.result);
185
182
 
@@ -190,14 +187,14 @@ export class HubWebSocket extends HubBase {
190
187
 
191
188
  }
192
189
  else {
193
-
190
+
194
191
  if (!data.result?.success) {
195
192
  // Return the result to the function that initiated the request.
196
193
  reject(new Error(data.result?.error_message));
197
194
  } else {
198
195
  // Send the error to the function that intiated the request.
199
196
  resolve(data.result);
200
- }
197
+ }
201
198
  }
202
199
  this.pendingRequests.delete(data.request_id);
203
200
  } else {
@@ -217,7 +214,7 @@ export class HubWebSocket extends HubBase {
217
214
  //
218
215
  this.socket.onclose = () => {
219
216
  self.setIsConnected(false);
220
- console.log('WebSocket connection closed.');
217
+ console.log('WebSocket connection closed.');
221
218
  };
222
219
  }
223
220
 
@@ -229,13 +226,13 @@ export class HubWebSocket extends HubBase {
229
226
  * @param payload The arguments of the command.
230
227
  * @returns Promise<CommandMessageResult>
231
228
  */
232
- invoke = (domain : string, fname: string, payload?: object): Promise<CommandMessageResult> => {
229
+ invoke = (domain: string, fname: string, payload?: object): Promise<CommandMessageResult> => {
233
230
 
234
231
  return new Promise((resolve, reject) => {
235
232
  const id = ++this.requestId; // Increment and use the request ID
236
233
  this.pendingRequests.set(id, { resolve, reject });
237
234
 
238
- let cm : CommandMessage = {
235
+ let cm: CommandMessage = {
239
236
  request_id: id,
240
237
  domain: domain,
241
238
  fname: fname,
@@ -250,10 +247,10 @@ export class HubWebSocket extends HubBase {
250
247
  handleUnsolicitedMessage = (msg: CommandMessage) => {
251
248
  // Handle messages that do not correspond to a pending request
252
249
 
253
- if (msg.fname === "BROADCAST"
250
+ if (msg.fname === "BROADCAST"
254
251
  && msg.domain.length >= 1
255
252
  && msg.result !== undefined && msg.result !== null
256
- && msg.result.data !== undefined && msg.result.data !== null
253
+ && msg.result.data !== undefined && msg.result.data !== null
257
254
  ) {
258
255
 
259
256
  let topic = `${msg.domain}/${msg.result.data["topic"]}`;
@@ -266,7 +263,7 @@ export class HubWebSocket extends HubBase {
266
263
  // }
267
264
  }
268
265
 
269
- disconnect= (): void => {
266
+ disconnect = (): void => {
270
267
  this.socket.close();
271
268
  }
272
269
 
package/src/hub/index.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * Copyright (C) 2024 Automated Design Corp. All Rights Reserved.
3
3
  * Created Date: 2024-01-16 21:07:29
4
4
  * -----
5
- * Last Modified: 2024-05-31 07:51:19
5
+ * Last Modified: 2025-09-05 14:53:01
6
6
  * Modified By: ADC
7
7
  * -----
8
8
  *
@@ -12,7 +12,7 @@ import { HubBase as Hub } from './HubBase';
12
12
  import { HubTauri } from './HubTauri';
13
13
  import { HubWebSocket } from "./HubWebSocket";
14
14
  import {HubSimulate} from "./HubSimulate"
15
- import { CommandMessage, CommandMessageResult } from './CommandMessage';
15
+ import type { CommandMessage, CommandMessageResult } from './CommandMessage';
16
16
 
17
17
 
18
18
  let hubInstance: Hub | null = null;
@@ -128,6 +128,163 @@
128
128
  font-weight: 500;
129
129
  }
130
130
 
131
+ /* ---- ac-toolbar: consistent square icon-button sizing ----
132
+ *
133
+ * SVG icons (Lucide, custom <SvgAxis/> ) and PrimeIcon font glyphs
134
+ * (`<i class="pi pi-...">`) are normalized to render at a consistent
135
+ * weight inside toolbar buttons. The two need different treatment:
136
+ *
137
+ * - Size — both: width/height for SVG, font-size for icon font.
138
+ * - Weight — SVG only: Lucide ships `stroke-width="2"` on a 24×24
139
+ * viewBox; when scaled to 18px the strokes drop to
140
+ * effective 1.5px and look thinner than PrimeIcons.
141
+ * Setting `stroke-width: 2.25` via CSS (which overrides
142
+ * the SVG presentation attribute) restores parity. The
143
+ * fill: none / stroke: currentColor lines defend against
144
+ * custom SVGs that didn't inherit those by attribute.
145
+ * - Align — `vertical-align: middle` matches PrimeIcon's default
146
+ * and prevents baseline drift in non-flex parents.
147
+ */
148
+
149
+ @mixin ac-toolbar-svg-normalize {
150
+ vertical-align: middle;
151
+ stroke: currentColor;
152
+ fill: none;
153
+ stroke-width: 2.25;
154
+ stroke-linecap: round;
155
+ stroke-linejoin: round;
156
+ }
157
+
158
+ .ac-toolbar-icon-btn {
159
+ width: 19mm;
160
+ height: 12.7mm;
161
+ padding: 0;
162
+ display: inline-flex;
163
+ align-items: center;
164
+ justify-content: center;
165
+ flex-shrink: 0;
166
+
167
+ svg, i { font-size: 11mm; width: 11mm; height: 11mm; }
168
+ svg { @include ac-toolbar-svg-normalize; }
169
+ .p-button-icon { margin: 0; }
170
+ }
171
+
172
+ .ac-toolbar-icon-lg {
173
+ width: 25.4mm;
174
+ height: 19mm;
175
+ padding: 0;
176
+ display: inline-flex;
177
+ align-items: center;
178
+ justify-content: center;
179
+ flex-shrink: 0;
180
+
181
+ svg, i { font-size: 16mm; width: 16mm; height: 16mm; }
182
+ svg { @include ac-toolbar-svg-normalize; }
183
+ .p-button-icon { margin: 0; }
184
+ }
185
+
186
+ .ac-toolbar-icon-panic {
187
+ width: 25.4mm;
188
+ height: 25.4mm;
189
+ padding: 0;
190
+ display: inline-flex;
191
+ align-items: center;
192
+ justify-content: center;
193
+ flex-shrink: 0;
194
+
195
+ svg { width: 20mm; height: 20mm; @include ac-toolbar-svg-normalize; }
196
+ .p-button-icon { margin: 0; }
197
+ }
198
+
199
+ /* ---- OverlayPanel + Dialog: comfortable interior padding ----
200
+ */
201
+ body .p-component.p-dialog .p-dialog-content {
202
+ padding: 4mm;
203
+ }
204
+
205
+ body .p-component.p-overlaypanel .p-overlaypanel-content {
206
+ padding: 4mm;
207
+ }
208
+
209
+
210
+ :root {
211
+ --p-dialog-content-padding: 4mm;
212
+ --p-overlaypanel-content-padding: 4mm;
213
+ }
214
+
215
+ .ac-toolbar-group {
216
+ display: flex;
217
+ flex-direction: row;
218
+ align-items: center;
219
+ gap: 2px;
220
+ }
221
+
222
+ /* ---- ac-toolbar-tool-list: stacked text buttons in an OverlayPanel ---- */
223
+ /*
224
+ * Spacing between buttons uses `gap` on the flex parent rather than
225
+ * `margin` on the buttons. PrimeReact's `.p-button` rules carry their
226
+ * own margin reset and tie our `.ac-toolbar-tool-item` on specificity;
227
+ * because PrimeReact's CSS loads later, its margin wins. Flex `gap`
228
+ * has no PrimeReact equivalent to fight.
229
+ */
230
+ .ac-toolbar-tool-list {
231
+ display: flex;
232
+ flex-direction: column;
233
+ min-width: 16rem;
234
+ padding: 2mm;
235
+ gap: 2mm;
236
+ }
237
+
238
+ /* `gap: 0.75rem` here is the *intra-button* spacing — between the
239
+ * leading icon and the text label — not between buttons. */
240
+ .ac-toolbar-tool-item {
241
+ justify-content: flex-start;
242
+ gap: 0.75rem;
243
+ }
244
+
245
+ /* ---- ac-form: content page form layout ---- */
246
+
247
+ .ac-form {
248
+ display: flex;
249
+ flex-direction: column;
250
+ gap: 10px;
251
+ }
252
+
253
+ .ac-form-row {
254
+ display: flex;
255
+ flex-direction: row;
256
+ align-items: center;
257
+ gap: 8px;
258
+
259
+ > * {
260
+ min-width: 0;
261
+ }
262
+ }
263
+
264
+ .ac-form-field {
265
+ flex: 1;
266
+ min-width: 0;
267
+ }
268
+
269
+ .ac-form-section {
270
+ font-size: 11px;
271
+ font-weight: 700;
272
+ text-transform: uppercase;
273
+ letter-spacing: 0.06em;
274
+ color: $primaryColor;
275
+ border-bottom: 1px solid $shade600;
276
+ padding-bottom: 4px;
277
+ margin-top: 6px;
278
+ }
279
+
280
+ .ac-form-label {
281
+ font-size: 13px;
282
+ font-weight: 600;
283
+ color: $textSecondaryColor;
284
+ white-space: nowrap;
285
+ flex-shrink: 0;
286
+ }
287
+
131
288
  .p-picklist-buttons .p-button,
132
289
  .p-orderlist-controls .p-button {
133
290
  transition: opacity $transitionDuration, background-color $transitionDuration, color $transitionDuration, border-color $transitionDuration, box-shadow $transitionDuration;
@@ -164,3 +321,173 @@
164
321
  }
165
322
  }
166
323
  }
324
+
325
+ /* Padding for OverlayPanels and Dialogs */
326
+ .p-overlaypanel .p-overlaypanel-content {
327
+ padding: 4mm !important;
328
+ }
329
+
330
+ .p-dialog .p-dialog-content {
331
+ padding: 4mm !important;
332
+ }
333
+
334
+
335
+ /* Padding for fieldset */
336
+
337
+ .p-fieldset {
338
+ .p-fieldset-legend {
339
+ padding: 0.5mm;
340
+ border-width: 0.5mm;
341
+ margin-left: 1.5mm;
342
+ }
343
+
344
+ .p-fieldset-content {
345
+ padding: 1mm;
346
+ }
347
+
348
+ border-width: 0.5mm;
349
+ }
350
+
351
+ /*
352
+ * Padding for dropdown items.
353
+ * Makes them work better on touchscreens.
354
+ */
355
+ .p-autocomplete-item {
356
+ padding-top: 2mm;
357
+ padding-bottom: 2mm;
358
+ }
359
+
360
+ .p-dropdown-item-label {
361
+ padding-top: 2mm;
362
+ padding-bottom: 2mm;
363
+ }
364
+
365
+ /*
366
+ * Clearable dropdowns (showClear): by default PrimeReact floats the clear
367
+ * "×" over the selected value, where it obscures the text and is hard to
368
+ * tap. Reserve space at the far right, move the clear icon to the RIGHT of
369
+ * the chevron, vertically centre it, and give it a button-like bordered
370
+ * tap target separated from the chevron so the two are easy to target.
371
+ */
372
+ .ac-dropdown-clearable.p-dropdown {
373
+ // Push the chevron left to open a gap at the far right for the clear
374
+ // button, and draw a full-height divider after the chevron.
375
+ .p-dropdown-trigger {
376
+ margin-right: 2.75rem;
377
+ border-right: 1px solid $shade600;
378
+ }
379
+
380
+ .p-dropdown-clear-icon {
381
+ // Centre on the input's mid-line with a transform so it doesn't
382
+ // depend on the glyph's exact height (the old margin-top hack left
383
+ // it sitting low). right places it inside the reserved gap.
384
+ top: 50%;
385
+ right: 0.4rem;
386
+ margin-top: 0;
387
+ transform: translateY(-50%);
388
+
389
+ // Button-like target: padding enlarges the box around the 1rem
390
+ // glyph without scaling it (content-box), bordered + subtle fill so
391
+ // it reads as a tappable control distinct from the chevron.
392
+ box-sizing: content-box;
393
+ width: 1rem;
394
+ height: 1rem;
395
+ padding: 0.4rem;
396
+ border: 1px solid $shade600;
397
+ border-radius: $borderRadius;
398
+ color: $textSecondaryColor;
399
+ background: rgba(255, 255, 255, 0.04);
400
+ transition: background-color $transitionDuration,
401
+ border-color $transitionDuration,
402
+ color $transitionDuration;
403
+
404
+ &:hover {
405
+ background: rgba(255, 255, 255, 0.10);
406
+ border-color: $primaryColor;
407
+ color: $primaryColor;
408
+ }
409
+
410
+ // PrimeReact decides "clear vs. open" from event.target's
411
+ // data-pc-section attribute, which lives on the <svg> clear icon
412
+ // but NOT on its child <path>s. A click landing on the glyph
413
+ // therefore targets a <path>, fails that test, and just toggles
414
+ // the list open. Make the inner paths transparent to pointer
415
+ // events so every click resolves to the <svg> and fires clear.
416
+ * {
417
+ pointer-events: none;
418
+ }
419
+ }
420
+ }
421
+
422
+ /*
423
+ * TestSetupView / TestSetupForm scroll containment.
424
+ *
425
+ * The whole view fills its parent and confines overflow to the inner
426
+ * field/history regions, so the tab strip and the section headers stay
427
+ * visible instead of the entire page scrolling. All the height plumbing
428
+ * hangs on `min-height: 0` — without it a flex child refuses to shrink
429
+ * below its content and the overflow leaks back out to the page.
430
+ */
431
+ .ac-test-setup-view {
432
+ display: flex;
433
+ flex-direction: column;
434
+ height: 100%;
435
+ min-height: 0;
436
+
437
+ > .p-tabview {
438
+ display: flex;
439
+ flex-direction: column;
440
+ flex: 1 1 auto;
441
+ min-height: 0;
442
+ }
443
+
444
+ .p-tabview-panels {
445
+ display: flex;
446
+ flex-direction: column;
447
+ flex: 1 1 auto;
448
+ min-height: 0;
449
+ overflow: hidden;
450
+ }
451
+
452
+ .p-tabview-panel {
453
+ flex: 1 1 auto;
454
+ min-height: 0;
455
+ height: 100%;
456
+ }
457
+ }
458
+
459
+ /* Project tab: fixed ProjectSelector + scrolling Test History. */
460
+ .ac-test-setup-view__tab {
461
+ display: flex;
462
+ flex-direction: column;
463
+ height: 100%;
464
+ min-height: 0;
465
+ }
466
+
467
+ .ac-test-setup-view__fixed {
468
+ flex: 0 0 auto;
469
+ }
470
+
471
+ .ac-test-setup-view__scroll {
472
+ flex: 1 1 auto;
473
+ min-height: 0;
474
+ overflow-y: auto;
475
+ }
476
+
477
+ /* Test tab: fixed Test-Setup header + scrolling Test-Configuration list. */
478
+ .ac-test-setup-form {
479
+ display: flex;
480
+ flex-direction: column;
481
+ height: 100%;
482
+ min-height: 0;
483
+ }
484
+
485
+ .ac-test-setup-form__head {
486
+ flex: 0 0 auto;
487
+ }
488
+
489
+ .ac-test-setup-form__body {
490
+ flex: 1 1 auto;
491
+ min-height: 0;
492
+ overflow-y: auto;
493
+ }