@adcops/autocore-react 3.0.33 → 3.0.34
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.
- package/dist/assets/BlocklyLogo.js +9 -1
- package/dist/assets/Distance.js +5 -1
- package/dist/assets/JogLong.js +3 -1
- package/dist/assets/JogMedium.js +3 -1
- package/dist/assets/JogShort.js +3 -1
- package/dist/assets/PythonLogo.js +21 -1
- package/dist/assets/Rotation3D.js +3 -1
- package/dist/assets/RotationCcw.js +10 -1
- package/dist/assets/RotationCcwA.js +16 -1
- package/dist/assets/RotationCcwB.js +16 -1
- package/dist/assets/RotationCcwC.js +16 -1
- package/dist/assets/RotationCw.js +10 -1
- package/dist/assets/RotationCwA.js +16 -1
- package/dist/assets/RotationCwB.js +16 -1
- package/dist/assets/RotationCwC.js +16 -1
- package/dist/assets/Run.js +3 -1
- package/dist/assets/Speed.js +5 -1
- package/dist/assets/SpeedFast.js +3 -1
- package/dist/assets/SpeedMedium.js +3 -1
- package/dist/assets/SpeedNone.js +3 -1
- package/dist/assets/SpeedSlow.js +3 -1
- package/dist/assets/Walk.js +3 -1
- package/dist/assets/index.js +22 -1
- package/dist/components/BlocklyEditor.js +508 -1
- package/dist/components/CodeEditor.js +108 -1
- package/dist/components/FileList.js +218 -1
- package/dist/components/FileSelect.js +63 -1
- package/dist/components/FitText.js +13 -1
- package/dist/components/Indicator.js +113 -1
- package/dist/components/IndicatorButton.js +187 -1
- package/dist/components/IndicatorRect.js +93 -1
- package/dist/components/JogPanel.js +295 -1
- package/dist/components/Lamp.js +161 -1
- package/dist/components/Osk.js +125 -1
- package/dist/components/OskDialog.js +128 -1
- package/dist/components/ProgressBarWithValue.js +18 -1
- package/dist/components/TextInput.js +139 -1
- package/dist/components/ToggleGroup.js +204 -1
- package/dist/components/ValueDisplay.js +160 -1
- package/dist/components/ValueIndicator.js +38 -1
- package/dist/components/ValueInput.js +158 -1
- package/dist/core/ActionMode.js +18 -1
- package/dist/core/EventEmitterContext.js +252 -1
- package/dist/core/IndicatorButtonState.js +9 -1
- package/dist/core/IndicatorColor.js +36 -1
- package/dist/core/MaskPatterns.js +80 -1
- package/dist/core/NumerableTypes.js +10 -1
- package/dist/core/PositionContext.js +24 -1
- package/dist/core/UniqueId.js +32 -1
- package/dist/core/ValueSimulator.js +233 -1
- package/dist/core/hoc.js +44 -1
- package/dist/hooks/adsHooks.js +253 -1
- package/dist/hooks/commandHooks.js +252 -1
- package/dist/hooks/index.js +10 -1
- package/dist/hooks/useScaledValue.js +86 -1
- package/dist/hub/CommandMessage.js +9 -1
- package/dist/hub/HubBase.js +310 -1
- package/dist/hub/HubSimulate.js +46 -1
- package/dist/hub/HubTauri.js +130 -1
- package/dist/hub/HubWebSocket.js +240 -1
- package/dist/hub/index.js +57 -1
- package/package.json +3 -3
|
@@ -1 +1,160 @@
|
|
|
1
|
-
import{jsx as _jsx}from"react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (C) 2024 Automated Design Corp. All Rights Reserved.
|
|
4
|
+
* Created Date: 2024-01-16 14:17:02
|
|
5
|
+
* -----
|
|
6
|
+
* Last Modified: 2024-05-01 12:14:27
|
|
7
|
+
* Modified By: ADC
|
|
8
|
+
* -----
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
import { Component } from 'react';
|
|
12
|
+
//import useFitText from 'use-fit-text';
|
|
13
|
+
import { format as numerableFormat } from 'numerable';
|
|
14
|
+
import clsx from 'clsx';
|
|
15
|
+
import { EventEmitterContext } from '../core/EventEmitterContext';
|
|
16
|
+
/**
|
|
17
|
+
* `ValueDisplay` is a React component designed to display a value which can be a string, number, or null.
|
|
18
|
+
* It supports formatting numeric values using the `numerableFormat` function, and is capable of dynamic positioning
|
|
19
|
+
* and sizing within its parent container. The component integrates with an `EventEmitterContext` to listen for
|
|
20
|
+
* updates to its value based on a specified topic, making it ideal for real-time data display scenarios.
|
|
21
|
+
*
|
|
22
|
+
* The component can be absolutely positioned based on `x` and `y` props, and its size can be adjusted using
|
|
23
|
+
* `width` and `height` props. If `useAbsolutePositioning` is true, it will position itself based on the provided
|
|
24
|
+
* coordinates; otherwise, it will position relatively.
|
|
25
|
+
*
|
|
26
|
+
* ### Props:
|
|
27
|
+
* - `value`: The initial value to display, which can be updated via props or context events.
|
|
28
|
+
* - `x`, `y`: Coordinates for absolute positioning within the parent container.
|
|
29
|
+
* - `width`, `height`: Dimensions of the component. If height is not provided, it defaults to the width.
|
|
30
|
+
* - `format`: A string specifying the format for numeric values (see numerable.js documentation for format strings).
|
|
31
|
+
* - `formatOptions`: Additional formatting options as per numerable.js.
|
|
32
|
+
* - `className`: Custom class for CSS styling.
|
|
33
|
+
* - `useAbsolutePositioning`: Boolean to toggle absolute positioning.
|
|
34
|
+
* - `topic`: Optional string to subscribe to context updates for dynamic value changes.
|
|
35
|
+
*
|
|
36
|
+
* ### Usage Example:
|
|
37
|
+
* ```tsx
|
|
38
|
+
* import React from 'react';
|
|
39
|
+
* import ReactDOM from 'react-dom';
|
|
40
|
+
* import { ValueDisplay } from './components/ValueDisplay';
|
|
41
|
+
*
|
|
42
|
+
* const App = () => {
|
|
43
|
+
* return (
|
|
44
|
+
* <div>
|
|
45
|
+
* <ValueDisplay
|
|
46
|
+
* value={1234.56}
|
|
47
|
+
* x={100}
|
|
48
|
+
* y={200}
|
|
49
|
+
* width={150}
|
|
50
|
+
* height={50}
|
|
51
|
+
* format="0,0.00"
|
|
52
|
+
* className="numeric-display"
|
|
53
|
+
* useAbsolutePositioning={true}
|
|
54
|
+
* topic="priceUpdate"
|
|
55
|
+
* />
|
|
56
|
+
* </div>
|
|
57
|
+
* );
|
|
58
|
+
* };
|
|
59
|
+
*
|
|
60
|
+
* ReactDOM.render(<App />, document.getElementById('root'));
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* In this example, `ValueDisplay` is used to show a numeric value formatted as a string with two decimal places.
|
|
64
|
+
* It is positioned absolutely at coordinates (100, 200) with a specified width and height. The component listens
|
|
65
|
+
* for updates on the "priceUpdate" topic to dynamically update its displayed value.
|
|
66
|
+
*/
|
|
67
|
+
class ValueDisplay extends Component {
|
|
68
|
+
/**
|
|
69
|
+
* The constructor initializes the component state and binds the initial value.
|
|
70
|
+
* @param props The properties passed to the component, including initial value and other display options.
|
|
71
|
+
*/
|
|
72
|
+
constructor(props) {
|
|
73
|
+
super(props);
|
|
74
|
+
/** ID for the subscription to the topic, used to unsubscribe on component unmount. */
|
|
75
|
+
Object.defineProperty(this, "unsubscribeTopicId", {
|
|
76
|
+
enumerable: true,
|
|
77
|
+
configurable: true,
|
|
78
|
+
writable: true,
|
|
79
|
+
value: null
|
|
80
|
+
});
|
|
81
|
+
this.state = {
|
|
82
|
+
subscribedValue: props.value,
|
|
83
|
+
fontSize: '100%' // Initial font size, adjust as needed
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Upon mounting, the component subscribes to updates on the specified topic if it exists,
|
|
88
|
+
* updating its state with the new value when the topic publishes updates.
|
|
89
|
+
*/
|
|
90
|
+
componentDidMount() {
|
|
91
|
+
const { topic } = this.props;
|
|
92
|
+
if (topic) {
|
|
93
|
+
const { subscribe } = this.context;
|
|
94
|
+
this.unsubscribeTopicId = subscribe(topic, (value) => {
|
|
95
|
+
this.setState({ subscribedValue: value });
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* If the value prop changes, the component updates its state with the new value.
|
|
101
|
+
* This ensures that the component remains in sync with its props.
|
|
102
|
+
* @param prevProps The previous properties for comparison to detect changes.
|
|
103
|
+
*/
|
|
104
|
+
componentDidUpdate(prevProps) {
|
|
105
|
+
// Check if the value prop has changed
|
|
106
|
+
if (this.props.value !== prevProps.value) {
|
|
107
|
+
// Update the state with the new value
|
|
108
|
+
this.setState({ subscribedValue: this.props.value });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Before the component is unmounted, it unsubscribes from the topic to prevent memory leaks
|
|
113
|
+
* and unnecessary updates from occurring.
|
|
114
|
+
*/
|
|
115
|
+
componentWillUnmount() {
|
|
116
|
+
if (this.unsubscribeTopicId) {
|
|
117
|
+
const { unsubscribe } = this.context;
|
|
118
|
+
unsubscribe(this.unsubscribeTopicId);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Renders the component with styling and formatting based on the provided properties and state.
|
|
123
|
+
* Supports absolute or relative positioning and scales the display based on the context's dimensions.
|
|
124
|
+
* @returns A styled `div` element displaying the formatted value.
|
|
125
|
+
*/
|
|
126
|
+
render() {
|
|
127
|
+
const { x, y, width, height, format, formatOptions, className, useAbsolutePositioning } = this.props;
|
|
128
|
+
const { subscribedValue, fontSize } = this.state;
|
|
129
|
+
const { scale, xOffset, yOffset } = this.context;
|
|
130
|
+
const style = {
|
|
131
|
+
position: useAbsolutePositioning ? 'absolute' : 'relative',
|
|
132
|
+
display: useAbsolutePositioning ? "" : "inline-block",
|
|
133
|
+
verticalAlign: 'middle',
|
|
134
|
+
fontSize: fontSize && scale > 1 ? `${scale * 100}%` : fontSize,
|
|
135
|
+
top: useAbsolutePositioning && y ? `${yOffset + scale * y}px` : undefined,
|
|
136
|
+
left: useAbsolutePositioning && x ? `${xOffset + scale * x}px` : undefined,
|
|
137
|
+
width: width ? `${width * scale}px` : undefined,
|
|
138
|
+
height: height ? `${height * scale}px` : undefined,
|
|
139
|
+
lineHeight: height ? `${height * scale}px` : undefined,
|
|
140
|
+
whiteSpace: 'nowrap',
|
|
141
|
+
};
|
|
142
|
+
// Determine how to display the value
|
|
143
|
+
let displayValue;
|
|
144
|
+
if (typeof subscribedValue === 'number' || (typeof subscribedValue === 'string' && !isNaN(Number(subscribedValue)))) {
|
|
145
|
+
displayValue = numerableFormat(subscribedValue, format, formatOptions);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
displayValue = subscribedValue; // Directly use the string if it's not numeric
|
|
149
|
+
}
|
|
150
|
+
return (_jsx("div", { className: clsx(className), style: style, children: displayValue }));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/** Defines the context type to subscribe to changes using EventEmitter. */
|
|
154
|
+
Object.defineProperty(ValueDisplay, "contextType", {
|
|
155
|
+
enumerable: true,
|
|
156
|
+
configurable: true,
|
|
157
|
+
writable: true,
|
|
158
|
+
value: EventEmitterContext
|
|
159
|
+
});
|
|
160
|
+
export { ValueDisplay };
|
|
@@ -1 +1,38 @@
|
|
|
1
|
-
import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (C) 2024 Automated Design Corp. All Rights Reserved.
|
|
4
|
+
* Created Date: 2024-01-16 14:17:02
|
|
5
|
+
* -----
|
|
6
|
+
* Last Modified: 2024-03-22 06:42:57
|
|
7
|
+
* Modified By: ADC
|
|
8
|
+
* -----
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
import { Component } from 'react';
|
|
12
|
+
import { Tooltip } from "primereact/tooltip";
|
|
13
|
+
import { ValueDisplay } from './ValueDisplay';
|
|
14
|
+
import "./ValueIndicator.css";
|
|
15
|
+
/**
|
|
16
|
+
* `ValueIndicator` wraps `ValueDisplay` in a frame and label, giving it a widget appearance.
|
|
17
|
+
* Care is taken to adapt to the selected theme of the application.
|
|
18
|
+
*
|
|
19
|
+
*/
|
|
20
|
+
export class ValueIndicator extends Component {
|
|
21
|
+
/**
|
|
22
|
+
* The constructor initializes the component state and binds the initial value.
|
|
23
|
+
* @param {ValueIndicatorProps} props The properties passed to the component, including initial value and other display options.
|
|
24
|
+
*/
|
|
25
|
+
constructor(props) {
|
|
26
|
+
super(props);
|
|
27
|
+
this.state = {};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Renders the component into the DOM.
|
|
31
|
+
* @returns A styled `div` element displaying the indicator.
|
|
32
|
+
*/
|
|
33
|
+
render() {
|
|
34
|
+
return (_jsxs("div", { className: 'value-indicator-container', style: this.props.style, children: [_jsx(Tooltip, { target: ".value-indicator-container" }), this.props.label !== undefined &&
|
|
35
|
+
_jsx("div", { className: "value-indicator-label", children: this.props.label }), _jsx(ValueDisplay, { className: this.props.className, value: this.props.value, format: this.props.format, formatOptions: this.props.formatOptions, topic: this.props.topic, "data-pr-tooltip": this.props.tooltip, "data-pr-position": "down", "data-pr-mousetrack": true, "data-pr-showDelay": 2000 })] }));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export default ValueIndicator;
|
|
@@ -1 +1,158 @@
|
|
|
1
|
-
import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (C) 2024 Automated Design Corp.. All Rights Reserved.
|
|
4
|
+
* Created Date: 2024-03-20 13:05:42
|
|
5
|
+
* -----
|
|
6
|
+
* Last Modified: 2024-05-17 10:01:45
|
|
7
|
+
* -----
|
|
8
|
+
*
|
|
9
|
+
*/
|
|
10
|
+
/** @file
|
|
11
|
+
* `ValueInput` is a React component for number input that encapsulates various features
|
|
12
|
+
* such as custom numeric formatting, optional currency formatting, increment and decrement
|
|
13
|
+
* buttons, and validation. This component uses the PrimeReact `InputNumber` control
|
|
14
|
+
* to provide a rich input experience, including handling both decimal and currency modes,
|
|
15
|
+
* with configurable precision and optional prefix/suffix text.
|
|
16
|
+
*
|
|
17
|
+
* Properties:
|
|
18
|
+
* - `label`: Label text displayed on the input field.
|
|
19
|
+
* - `value`: Current numeric value of the input field.
|
|
20
|
+
* - `min`: Minimum allowable value.
|
|
21
|
+
* - `max`: Maximum allowable value.
|
|
22
|
+
* - `minPrecision`: Minimum number of decimal places to display.
|
|
23
|
+
* - `maxPrecision`: Maximum number of decimal places allowed.
|
|
24
|
+
* - `mode`: Determines whether the input is treated as a plain decimal or currency. Defaults to "decimal".
|
|
25
|
+
* - `currency`: ISO 4217 currency code for formatting the value as currency.
|
|
26
|
+
* - `prefix`: String to display before the value.
|
|
27
|
+
* - `suffix`: String to display after the value.
|
|
28
|
+
* - `showButtons`: Whether to display increment and decrement buttons.
|
|
29
|
+
* - `step`: The amount by which the value should be incremented or decremented.
|
|
30
|
+
* - `locale`: Locale code for formatting the value.
|
|
31
|
+
* - `description`: Additional descriptive text to display below the input.
|
|
32
|
+
* - `disabled`: Whether the input is disabled.
|
|
33
|
+
* - `dispatchTopic`: Event topic to dispatch on value change.
|
|
34
|
+
* - `placeholder`: Placeholder text when the input is empty.
|
|
35
|
+
* - `onValueChanged`: Callback function that is called when the user accepts a new value.
|
|
36
|
+
*
|
|
37
|
+
* Example Usage:
|
|
38
|
+
* ```tsx
|
|
39
|
+
* <ValueInput
|
|
40
|
+
* label="Quantity"
|
|
41
|
+
* value={10}
|
|
42
|
+
* min={1}
|
|
43
|
+
* max={100}
|
|
44
|
+
* minPrecision={0}
|
|
45
|
+
* maxPrecision={2}
|
|
46
|
+
* mode="decimal"
|
|
47
|
+
* showButtons={true}
|
|
48
|
+
* step={1}
|
|
49
|
+
* locale="en-US"
|
|
50
|
+
* onValueChanged={(newValue) => console.log("New Value:", newValue)}
|
|
51
|
+
* />
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* This example creates a `ValueInput` component for entering quantities, with values ranging from 1 to 100,
|
|
55
|
+
* allowing up to 2 decimal places. Increment and decrement buttons are visible, and the new value is logged
|
|
56
|
+
* to the console when accepted.
|
|
57
|
+
*/
|
|
58
|
+
import { useState, useRef, useEffect, useContext } from 'react';
|
|
59
|
+
import { InputNumber } from 'primereact/inputnumber';
|
|
60
|
+
import { EventEmitterContext } from "../core/EventEmitterContext";
|
|
61
|
+
import { Button } from 'primereact/button';
|
|
62
|
+
/**
|
|
63
|
+
* A convenient field with all the usual features of inputing numbers.
|
|
64
|
+
* Wraps the common features of use of a InputNumber, p-inputgroup, some icon buttons,
|
|
65
|
+
* accepting and rejecting values and keyboard management.
|
|
66
|
+
*/
|
|
67
|
+
export const ValueInput = ({ label = '', value = null, min = undefined, max = undefined, minPrecision = 0, maxPrecision = 3, mode = "decimal", currency = "USD", prefix = undefined, suffix = undefined, showButtons = false, step = 1, locale = "en-US", description = undefined, disabled = false, dispatchTopic = undefined, placeholder = undefined, onValueChanged = undefined, ...restProps }) => {
|
|
68
|
+
const [entryValue, setEntryValue] = useState(value);
|
|
69
|
+
const [currentValue, setCurrentValue] = useState(value);
|
|
70
|
+
const [bufferedValue, setBufferedValue] = useState(value);
|
|
71
|
+
const [editing, setEditing] = useState(false);
|
|
72
|
+
const [invalidValue, setInvalidValue] = useState(false);
|
|
73
|
+
const inputRef = useRef(null);
|
|
74
|
+
const eventEmitter = useContext(EventEmitterContext);
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
if (bufferedValue !== null) {
|
|
77
|
+
setCurrentValue(bufferedValue);
|
|
78
|
+
setBufferedValue(null);
|
|
79
|
+
setInvalidValue(false);
|
|
80
|
+
}
|
|
81
|
+
else if (value !== currentValue) {
|
|
82
|
+
setCurrentValue(value);
|
|
83
|
+
setEntryValue(value);
|
|
84
|
+
setEditing(false);
|
|
85
|
+
setInvalidValue(false);
|
|
86
|
+
}
|
|
87
|
+
}, [value, currentValue]);
|
|
88
|
+
/**
|
|
89
|
+
* Buffers the original value, if editing just starting,
|
|
90
|
+
* and updates the entry value.
|
|
91
|
+
*
|
|
92
|
+
* @param val New value being entered.
|
|
93
|
+
*/
|
|
94
|
+
const handleBufferValue = (val) => {
|
|
95
|
+
if (!editing) {
|
|
96
|
+
setBufferedValue(currentValue);
|
|
97
|
+
setEditing(true);
|
|
98
|
+
}
|
|
99
|
+
setEntryValue(val);
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* Returns true if the new value falls within specified parameters.
|
|
103
|
+
* @param val The new value.
|
|
104
|
+
* @returns
|
|
105
|
+
*/
|
|
106
|
+
const validateValue = (val) => {
|
|
107
|
+
if (max !== undefined) {
|
|
108
|
+
if (val > max) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (min !== undefined) {
|
|
113
|
+
if (val < min) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return true;
|
|
118
|
+
};
|
|
119
|
+
/**
|
|
120
|
+
* The user has elected to accept the input value. Validate and store, if valid.
|
|
121
|
+
*/
|
|
122
|
+
const handleAcceptValue = () => {
|
|
123
|
+
if (editing && entryValue !== null) {
|
|
124
|
+
if (validateValue(entryValue)) {
|
|
125
|
+
setCurrentValue(entryValue);
|
|
126
|
+
setEditing(false);
|
|
127
|
+
onValueChanged?.(entryValue);
|
|
128
|
+
setInvalidValue(false);
|
|
129
|
+
if (dispatchTopic) {
|
|
130
|
+
eventEmitter.dispatch({ topic: dispatchTopic, payload: entryValue });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
setInvalidValue(true);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
/**
|
|
139
|
+
* The user wishes to cancel/reset to the previous value.
|
|
140
|
+
*/
|
|
141
|
+
const handleResetValue = () => {
|
|
142
|
+
if (editing) {
|
|
143
|
+
setEntryValue(null);
|
|
144
|
+
setCurrentValue(null);
|
|
145
|
+
setEditing(false);
|
|
146
|
+
setInvalidValue(false);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
return (_jsxs("div", { children: [_jsxs("div", { className: "p-inputgroup flex-1", children: [_jsx("span", { className: "p-inputgroup-addon", children: label }), _jsx(InputNumber, { ...restProps, ref: inputRef, invalid: invalidValue, min: min, max: max, minFractionDigits: minPrecision, maxFractionDigits: maxPrecision, mode: mode, prefix: prefix, suffix: suffix, showButtons: showButtons, step: step, placeholder: placeholder, value: currentValue, onChange: (e) => handleBufferValue(e.value), locale: locale, currency: currency, onKeyDown: (e) => {
|
|
150
|
+
if (e.key === 'Enter') {
|
|
151
|
+
handleAcceptValue();
|
|
152
|
+
}
|
|
153
|
+
else if (e.key === 'Escape') {
|
|
154
|
+
handleResetValue();
|
|
155
|
+
}
|
|
156
|
+
}, disabled: disabled }), _jsx(Button, { icon: "pi pi-check", disabled: disabled || !editing, className: "p-button-success", onClick: () => handleAcceptValue(), visible: editing, size: "small", autoFocus: false }), _jsx(Button, { icon: "pi pi-times", disabled: disabled || !editing, className: "p-button-danger", onClickCapture: () => handleResetValue(), visible: editing, size: "small", autoFocus: false })] }), description && _jsx("small", { children: description })] }));
|
|
157
|
+
};
|
|
158
|
+
export default ValueInput;
|
package/dist/core/ActionMode.js
CHANGED
|
@@ -1 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2024 Automated Design Corp.. All Rights Reserved.
|
|
3
|
+
* Created Date: 2024-03-12 10:28:38
|
|
4
|
+
* -----
|
|
5
|
+
* Last Modified: 2024-03-12 10:28:47
|
|
6
|
+
* -----
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Enum for different input modes of the IndicatorButton.
|
|
11
|
+
*/
|
|
12
|
+
export var ActionMode;
|
|
13
|
+
(function (ActionMode) {
|
|
14
|
+
ActionMode["Tap"] = "Tap";
|
|
15
|
+
ActionMode["Toggle"] = "Toggle";
|
|
16
|
+
ActionMode["Pressed"] = "Pressed";
|
|
17
|
+
ActionMode["Released"] = "Released";
|
|
18
|
+
})(ActionMode || (ActionMode = {}));
|
|
@@ -1 +1,252 @@
|
|
|
1
|
-
import{jsx as _jsx}from"react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (C) 2024 Automated Design Corp. All Rights Reserved.
|
|
4
|
+
* Created Date: 2024-01-17 11:45:10
|
|
5
|
+
* -----
|
|
6
|
+
* Last Modified: 2024-04-25 15:24:53
|
|
7
|
+
* Modified By: ADC
|
|
8
|
+
* -----
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
import { createContext, useState, useMemo, useCallback } from 'react';
|
|
12
|
+
import { createHub, Hub } from "../hub";
|
|
13
|
+
export { Hub };
|
|
14
|
+
let globalSubscriptionId = 1;
|
|
15
|
+
/**
|
|
16
|
+
* A global context for managing event emission and subscription.
|
|
17
|
+
*
|
|
18
|
+
* Creates a React context for the EventEmitter system, providing a structured way to manage events and data flow
|
|
19
|
+
* in a React application. It serves as a global event bus that components can subscribe to or emit events, allowing for
|
|
20
|
+
* a loosely coupled architecture. Additionally, it provides a mechanism for invoking backend functions and managing
|
|
21
|
+
* subscriptions, making it easier to integrate React components with backend services.
|
|
22
|
+
*
|
|
23
|
+
* The context includes several key functionalities:
|
|
24
|
+
* - `state`: Maintains the current state of subscriptions and their identifiers.
|
|
25
|
+
* - `dispatch`: Allows components to emit events with specific topics and payloads, which can be listened to by other components.
|
|
26
|
+
* - `subscribe`: Enables components to listen to specific topics and react to those events by providing a callback function.
|
|
27
|
+
* - `unsubscribe`: Provides a way for components to stop listening to events, helping prevent memory leaks and unnecessary updates.
|
|
28
|
+
* - `invoke`: Facilitates calling backend functions with specific arguments and handling their responses asynchronously.
|
|
29
|
+
* - `getSubscriptions`: Offers insight into current active subscriptions, useful for debugging purposes.
|
|
30
|
+
*
|
|
31
|
+
* This context is essential for applications that require a high degree of inter-component communication or need to
|
|
32
|
+
* interact with a backend efficiently.
|
|
33
|
+
*
|
|
34
|
+
* For more information, see [Additional Documentation](../additional-docs/GlobalEventEmitter.md).
|
|
35
|
+
*
|
|
36
|
+
* ## Usage
|
|
37
|
+
*
|
|
38
|
+
* The entire application should be wrapped in the EventEmitterProvider.
|
|
39
|
+
*
|
|
40
|
+
* App.tsx
|
|
41
|
+
* ```
|
|
42
|
+
* import { EventEmitterProvider } from "@adcops/autocore-react/core/EventEmitterContext.js";
|
|
43
|
+
* function App() {
|
|
44
|
+
*
|
|
45
|
+
* return(
|
|
46
|
+
* <EventEmitterProvider>
|
|
47
|
+
* <PrimeReactProvider>
|
|
48
|
+
* <main>
|
|
49
|
+
* <section>
|
|
50
|
+
* <ContentView />
|
|
51
|
+
* </section>
|
|
52
|
+
* </main>
|
|
53
|
+
* </PrimeReactProvider>
|
|
54
|
+
* </EventEmitterProvider>
|
|
55
|
+
* );
|
|
56
|
+
*
|
|
57
|
+
* }
|
|
58
|
+
*
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* ### Catching and receiving events
|
|
62
|
+
* The EventEmitterContext creates an appropriate instance of the hub, which is derived from HubBase.
|
|
63
|
+
* That hub can be used to publish and subscribe to
|
|
64
|
+
* topics globally in the front-end, regardless of being connected to any backend.
|
|
65
|
+
* Usage within a component is simple.
|
|
66
|
+
*
|
|
67
|
+
* ```
|
|
68
|
+
* const {dispatch, subscribe, unsubscribe} = useContext(EventEmitterContext);
|
|
69
|
+
* const [controlPower, setControlPower] = useState(false);
|
|
70
|
+
* useEffect(() => {
|
|
71
|
+
* const unsubscribeControlPower = subscribe('value-simulator-bBit1', (value) => {
|
|
72
|
+
* setControlPower(value);
|
|
73
|
+
* });
|
|
74
|
+
*
|
|
75
|
+
*
|
|
76
|
+
* return () => {
|
|
77
|
+
* unsubscribe(unsubscribeControlPower);
|
|
78
|
+
* }
|
|
79
|
+
* }, [] );
|
|
80
|
+
*
|
|
81
|
+
* const onPbPressed = () => {
|
|
82
|
+
* let count = 1;
|
|
83
|
+
* dispatch({
|
|
84
|
+
* topic: "my-awesome-topic",
|
|
85
|
+
* payload: count
|
|
86
|
+
* });
|
|
87
|
+
* }
|
|
88
|
+
*
|
|
89
|
+
* ```
|
|
90
|
+
* The hub should also be used for invoking events in the backend.
|
|
91
|
+
* This example will call the function "update_count" in the backend, passing
|
|
92
|
+
* the expected argument "count". Details of the interaction between the Hub and
|
|
93
|
+
* the backend will be handled by the appropriate HubBase sub-class, and should
|
|
94
|
+
* be transparent to the front end.
|
|
95
|
+
*
|
|
96
|
+
* ```
|
|
97
|
+
* const {invoke} = useContext(EventEmitterContext);
|
|
98
|
+
* const incrementCount = () => {
|
|
99
|
+
* count += 1;
|
|
100
|
+
* invoke('update_count', {"count": count});
|
|
101
|
+
* };
|
|
102
|
+
*
|
|
103
|
+
* Subscribing to a topic is simple. The type of value received is specific
|
|
104
|
+
* to the topic.
|
|
105
|
+
*
|
|
106
|
+
* Example: Listen to an event 'xarm-position':
|
|
107
|
+
* ```
|
|
108
|
+
* const {subscribe, unsubscribe} = useContext(EventEmitterContext);
|
|
109
|
+
* useEffect(() => {
|
|
110
|
+
* const unsubscripeMp = subscribe('xarm-position', (value) => {
|
|
111
|
+
* // The publisher sent a JSON object of 3D position values.
|
|
112
|
+
* setX(value.x);
|
|
113
|
+
* setY(value.y);
|
|
114
|
+
* setZ(value.z);
|
|
115
|
+
* setA(value.roll);
|
|
116
|
+
* setB(value.yaw);
|
|
117
|
+
* setC(value.pitch);
|
|
118
|
+
* });
|
|
119
|
+
*
|
|
120
|
+
* return () => {
|
|
121
|
+
* unsubscribe(unsubscripeMp);
|
|
122
|
+
* }
|
|
123
|
+
*
|
|
124
|
+
* }, [] );
|
|
125
|
+
*
|
|
126
|
+
* ```
|
|
127
|
+
*
|
|
128
|
+
* For applications that need to access the instance of the hub, get the current instance
|
|
129
|
+
* from the EventEmitterContext:
|
|
130
|
+
*
|
|
131
|
+
* ```
|
|
132
|
+
* const {hub} = useContext(EventEmitterContext);
|
|
133
|
+
* * ```
|
|
134
|
+
*
|
|
135
|
+
*
|
|
136
|
+
*/
|
|
137
|
+
export const EventEmitterContext = createContext({
|
|
138
|
+
state: { subscriptions: {}, nextSubscriptionId: 1 },
|
|
139
|
+
dispatch: () => { },
|
|
140
|
+
subscribe: () => { return 0; }, // Placeholder for subscription logic
|
|
141
|
+
invoke: async (domain, fname, payload) => {
|
|
142
|
+
domain;
|
|
143
|
+
fname;
|
|
144
|
+
payload;
|
|
145
|
+
let ret = {
|
|
146
|
+
data: {},
|
|
147
|
+
success: false,
|
|
148
|
+
error_message: ""
|
|
149
|
+
};
|
|
150
|
+
// Placeholder for invoke logic
|
|
151
|
+
// Implement the logic to send a message to the backend and return a promise
|
|
152
|
+
return Promise.resolve(ret); // Example placeholder, replace with actual implementation
|
|
153
|
+
},
|
|
154
|
+
unsubscribe: (subscriptionId) => { subscriptionId; }, // Placeholder for unsubscription logic
|
|
155
|
+
hub: null,
|
|
156
|
+
getSubscriptions: () => { return []; },
|
|
157
|
+
isConnected: () => { return false; }
|
|
158
|
+
});
|
|
159
|
+
/**
|
|
160
|
+
* A React component that provides the EventEmitterContext to its children.
|
|
161
|
+
*
|
|
162
|
+
* Wraps child components with the context, enabling them to access and interact
|
|
163
|
+
* with the event emitter.
|
|
164
|
+
*
|
|
165
|
+
* @param children The child components to be wrapped in the context.
|
|
166
|
+
*
|
|
167
|
+
* ## Usage
|
|
168
|
+
*
|
|
169
|
+
* The entire application should be wrapped in the EventEmitterProvider.
|
|
170
|
+
*
|
|
171
|
+
* App.tsx
|
|
172
|
+
* ```
|
|
173
|
+
* import { EventEmitterProvider } from "@adcops/autocore-react/core/EventEmitterContext.js";
|
|
174
|
+
* function App() {
|
|
175
|
+
*
|
|
176
|
+
* return(
|
|
177
|
+
* <EventEmitterProvider>
|
|
178
|
+
* <PrimeReactProvider>
|
|
179
|
+
* <main>
|
|
180
|
+
* <section>
|
|
181
|
+
* <ContentView />
|
|
182
|
+
* </section>
|
|
183
|
+
* </main>
|
|
184
|
+
* </PrimeReactProvider>
|
|
185
|
+
* </EventEmitterProvider>
|
|
186
|
+
* );
|
|
187
|
+
*
|
|
188
|
+
* }
|
|
189
|
+
*
|
|
190
|
+
* ```
|
|
191
|
+
*/
|
|
192
|
+
export const EventEmitterProvider = ({ children }) => {
|
|
193
|
+
const [state, setState] = useState({ subscriptions: {}, nextSubscriptionId: 1 });
|
|
194
|
+
// Memoize the hub instance so it's only created once
|
|
195
|
+
const hub = useMemo(() => createHub(), []);
|
|
196
|
+
const dispatch = useCallback((action) => {
|
|
197
|
+
const { topic, payload } = action;
|
|
198
|
+
setState(prevState => {
|
|
199
|
+
const callbacks = prevState.subscriptions[topic] || [];
|
|
200
|
+
callbacks.forEach(sub => sub.callback(payload));
|
|
201
|
+
return { ...prevState, eventData: payload };
|
|
202
|
+
});
|
|
203
|
+
}, []);
|
|
204
|
+
const subscribe = useCallback((topic, callback) => {
|
|
205
|
+
globalSubscriptionId += 1;
|
|
206
|
+
const subscriptionId = globalSubscriptionId; // state.nextSubscriptionId;
|
|
207
|
+
setState(prevState => ({
|
|
208
|
+
...prevState,
|
|
209
|
+
subscriptions: {
|
|
210
|
+
...prevState.subscriptions,
|
|
211
|
+
[topic]: [...(prevState.subscriptions[topic] || []), { id: subscriptionId, callback }]
|
|
212
|
+
},
|
|
213
|
+
nextSubscriptionId: globalSubscriptionId + 1 // prevState.nextSubscriptionId + 1
|
|
214
|
+
}));
|
|
215
|
+
return subscriptionId;
|
|
216
|
+
}, []);
|
|
217
|
+
const unsubscribe = useCallback((subscriptionId) => {
|
|
218
|
+
setState(prevState => {
|
|
219
|
+
const newSubscriptions = { ...prevState.subscriptions };
|
|
220
|
+
Object.keys(newSubscriptions).forEach(topic => {
|
|
221
|
+
newSubscriptions[topic] = newSubscriptions[topic].filter(sub => sub.id !== subscriptionId);
|
|
222
|
+
if (newSubscriptions[topic].length === 0) {
|
|
223
|
+
delete newSubscriptions[topic];
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
return { ...prevState, subscriptions: newSubscriptions };
|
|
227
|
+
});
|
|
228
|
+
}, []);
|
|
229
|
+
const getSubscriptions = useCallback((topic) => {
|
|
230
|
+
if (topic) {
|
|
231
|
+
// Return subscriptions for the provided topic, or an empty array if the topic doesn't exist
|
|
232
|
+
return state.subscriptions[topic] || [];
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
// Return all subscriptions
|
|
236
|
+
return state.subscriptions;
|
|
237
|
+
}
|
|
238
|
+
}, []);
|
|
239
|
+
// Provide the memoized hub instance in the context value
|
|
240
|
+
const contextValue = useMemo(() => ({
|
|
241
|
+
state,
|
|
242
|
+
dispatch,
|
|
243
|
+
subscribe,
|
|
244
|
+
unsubscribe,
|
|
245
|
+
invoke: hub.invoke,
|
|
246
|
+
hub,
|
|
247
|
+
getSubscriptions,
|
|
248
|
+
isConnected: hub.isConnected
|
|
249
|
+
}), [state, hub]);
|
|
250
|
+
hub.setContext(contextValue);
|
|
251
|
+
return (_jsx(EventEmitterContext.Provider, { value: contextValue, children: children }));
|
|
252
|
+
};
|