@adcops/autocore-react 3.0.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 (136) hide show
  1. package/LICENSE +59 -0
  2. package/additional-docs/ButtonApiSpecs.md +48 -0
  3. package/additional-docs/GlobalEventEmitter.md +244 -0
  4. package/additional-docs/general_recommendations.md +22 -0
  5. package/dist/components/DPad.css +522 -0
  6. package/dist/components/DPad.d.ts +34 -0
  7. package/dist/components/DPad.js +1 -0
  8. package/dist/components/Indicator.d.ts +81 -0
  9. package/dist/components/Indicator.js +1 -0
  10. package/dist/components/IndicatorButton.d.ts +137 -0
  11. package/dist/components/IndicatorButton.js +1 -0
  12. package/dist/components/IndicatorColor.d.ts +26 -0
  13. package/dist/components/IndicatorColor.js +1 -0
  14. package/dist/components/Osk.d.ts +14 -0
  15. package/dist/components/Osk.js +1 -0
  16. package/dist/components/OskDialog.d.ts +33 -0
  17. package/dist/components/OskDialog.js +1 -0
  18. package/dist/components/ValueDisplay.d.ts +99 -0
  19. package/dist/components/ValueDisplay.js +1 -0
  20. package/dist/components/osk.css +123 -0
  21. package/dist/core/EventEmitterContext.d.ts +223 -0
  22. package/dist/core/EventEmitterContext.js +1 -0
  23. package/dist/core/MaskPatterns.d.ts +71 -0
  24. package/dist/core/MaskPatterns.js +1 -0
  25. package/dist/core/NumerableTypes.d.ts +58 -0
  26. package/dist/core/NumerableTypes.js +1 -0
  27. package/dist/core/PositionContext.d.ts +38 -0
  28. package/dist/core/PositionContext.js +1 -0
  29. package/dist/core/UniqueId.d.ts +16 -0
  30. package/dist/core/UniqueId.js +1 -0
  31. package/dist/core/ValueSimulator.d.ts +71 -0
  32. package/dist/core/ValueSimulator.js +1 -0
  33. package/dist/core/hoc.d.ts +31 -0
  34. package/dist/core/hoc.js +1 -0
  35. package/dist/hub/HubBase.d.ts +169 -0
  36. package/dist/hub/HubBase.js +1 -0
  37. package/dist/hub/HubSimulate.d.ts +20 -0
  38. package/dist/hub/HubSimulate.js +1 -0
  39. package/dist/hub/HubSocketIo.d.ts +101 -0
  40. package/dist/hub/HubSocketIo.js +1 -0
  41. package/dist/hub/HubTauri.d.ts +86 -0
  42. package/dist/hub/HubTauri.js +1 -0
  43. package/dist/hub/index.d.ts +13 -0
  44. package/dist/hub/index.js +1 -0
  45. package/docs/.nojekyll +1 -0
  46. package/docs/assets/highlight.css +106 -0
  47. package/docs/assets/icons.js +15 -0
  48. package/docs/assets/icons.svg +1 -0
  49. package/docs/assets/main.js +59 -0
  50. package/docs/assets/navigation.js +1 -0
  51. package/docs/assets/search.js +1 -0
  52. package/docs/assets/style.css +1414 -0
  53. package/docs/classes/components_Indicator.Indicator.html +105 -0
  54. package/docs/classes/components_IndicatorButton.IndicatorButton.html +119 -0
  55. package/docs/classes/components_OskDialog.OskDialog.html +117 -0
  56. package/docs/classes/components_ValueDisplay.ValueDisplay.html +104 -0
  57. package/docs/classes/core_ValueSimulator.ValueSimulator.html +41 -0
  58. package/docs/classes/hub_HubBase.HubBase.html +67 -0
  59. package/docs/classes/hub_HubSimulate.HubSimulate.html +72 -0
  60. package/docs/classes/hub_HubSocketIo.HubSocketIo.html +80 -0
  61. package/docs/classes/hub_HubTauri.HubTauri.html +80 -0
  62. package/docs/enums/components_DPad.VcJoyPadAction.html +10 -0
  63. package/docs/enums/components_DPad.VcJoyPadButtonId.html +7 -0
  64. package/docs/enums/components_IndicatorButton.ActionMode.html +6 -0
  65. package/docs/enums/components_IndicatorColor.IndicatorColor.html +13 -0
  66. package/docs/functions/components_DPad.VcDPad.html +5 -0
  67. package/docs/functions/components_Osk.Osk.html +5 -0
  68. package/docs/functions/core_EventEmitterContext.EventEmitterProvider.html +8 -0
  69. package/docs/functions/core_UniqueId.UniqueId.html +4 -0
  70. package/docs/functions/core_hoc.hocAddSubscription.html +6 -0
  71. package/docs/functions/hub.createHub.html +3 -0
  72. package/docs/hierarchy.html +1 -0
  73. package/docs/index.html +69 -0
  74. package/docs/interfaces/components_IndicatorButton.IndicatorButtonProps.html +635 -0
  75. package/docs/interfaces/components_IndicatorButton.IndicatorButtonState.html +10 -0
  76. package/docs/interfaces/core_DimensionsContext.IDimensionsContext.html +4 -0
  77. package/docs/interfaces/core_EventEmitterContext.Action.html +5 -0
  78. package/docs/interfaces/core_EventEmitterContext.EventEmitterContextType.html +18 -0
  79. package/docs/interfaces/core_EventEmitterContext.State.html +8 -0
  80. package/docs/interfaces/core_EventEmitterContext.Subscription.html +6 -0
  81. package/docs/modules/components_DPad.html +5 -0
  82. package/docs/modules/components_Indicator.html +4 -0
  83. package/docs/modules/components_IndicatorButton.html +7 -0
  84. package/docs/modules/components_IndicatorColor.html +2 -0
  85. package/docs/modules/components_Osk.html +3 -0
  86. package/docs/modules/components_OskDialog.html +3 -0
  87. package/docs/modules/components_ValueDisplay.html +3 -0
  88. package/docs/modules/core_DimensionsContext.html +4 -0
  89. package/docs/modules/core_EventEmitterContext.html +11 -0
  90. package/docs/modules/core_InputPatterns.html +2 -0
  91. package/docs/modules/core_NumerableTypes.html +2 -0
  92. package/docs/modules/core_UniqueId.html +2 -0
  93. package/docs/modules/core_ValueSimulator.html +3 -0
  94. package/docs/modules/core_hoc.html +3 -0
  95. package/docs/modules/hub.html +6 -0
  96. package/docs/modules/hub_HubBase.html +3 -0
  97. package/docs/modules/hub_HubSimulate.html +3 -0
  98. package/docs/modules/hub_HubSocketIo.html +3 -0
  99. package/docs/modules/hub_HubTauri.html +2 -0
  100. package/docs/types/core_EventEmitterContext.EmitterDispatchFunction.html +1 -0
  101. package/docs/types/core_EventEmitterContext.EmitterSubscribeFunction.html +1 -0
  102. package/docs/types/core_EventEmitterContext.EmitterUnsubscribeFunction.html +1 -0
  103. package/docs/types/core_NumerableTypes.NumerableFormatOptions.html +1 -0
  104. package/docs/types/core_hoc.HocAddSubscriptionProps.html +4 -0
  105. package/docs/variables/core_DimensionsContext.DimensionsContext.html +1 -0
  106. package/docs/variables/core_EventEmitterContext.EventEmitterContext.html +5 -0
  107. package/docs/variables/core_InputPatterns.InputPatterns.html +2 -0
  108. package/package.json +79 -0
  109. package/readme.md +140 -0
  110. package/src/components/DPad.css +522 -0
  111. package/src/components/DPad.tsx +94 -0
  112. package/src/components/Indicator.tsx +243 -0
  113. package/src/components/IndicatorButton.tsx +306 -0
  114. package/src/components/IndicatorColor.ts +36 -0
  115. package/src/components/Osk.tsx +193 -0
  116. package/src/components/OskDialog.tsx +165 -0
  117. package/src/components/ValueDisplay.tsx +181 -0
  118. package/src/components/osk.css +123 -0
  119. package/src/core/EventEmitterContext.tsx +394 -0
  120. package/src/core/MaskPatterns.ts +82 -0
  121. package/src/core/NumerableTypes.ts +81 -0
  122. package/src/core/PositionContext.ts +60 -0
  123. package/src/core/UniqueId.ts +41 -0
  124. package/src/core/ValueSimulator.ts +167 -0
  125. package/src/core/hoc.tsx +65 -0
  126. package/src/hub/HubBase.ts +293 -0
  127. package/src/hub/HubSimulate.ts +47 -0
  128. package/src/hub/HubSocketIo.ts +166 -0
  129. package/src/hub/HubTauri.ts +145 -0
  130. package/src/hub/index.ts +41 -0
  131. package/terser.config.cjs +25 -0
  132. package/todo.md +18 -0
  133. package/tools/copy-distribution-files.cjs +73 -0
  134. package/tools/minify.cjs +56 -0
  135. package/tsconfig.json +34 -0
  136. package/typedoc.json +13 -0
@@ -0,0 +1,193 @@
1
+ import React, { useState, useEffect, useRef } from 'react';
2
+ import { InputText } from 'primereact/inputtext';
3
+ import Keyboard from "react-simple-keyboard";
4
+ import "./osk.css";
5
+ import { RegExMaskPatterns } from "../core/MaskPatterns";
6
+
7
+
8
+ const numpadLayout = {
9
+ numbers: ["1 2 3", "4 5 6", "7 8 9", "- 0 .", "{symbols} {backspace}"],
10
+ default: ["! / #", "$ % ^", "& * (", "= ) +", "{numbers} {backspace}"]
11
+ };
12
+
13
+
14
+ const englishLayout = {
15
+ default: [
16
+ "q w e r t y u i o p",
17
+ "a s d f g h j k l",
18
+ "{shift} z x c v b n m {backspace}",
19
+ "{numbers} {space} {ent}"
20
+ ],
21
+ shift: [
22
+ "Q W E R T Y U I O P",
23
+ "A S D F G H J K L",
24
+ "{shift} Z X C V B N M {backspace}",
25
+ "{numbers} {space} {ent}"
26
+ ],
27
+ numbers: ["1 2 3", "4 5 6", "7 8 9", "{abc} 0 {backspace}"]
28
+ };
29
+
30
+ const keyboardDisplay = {
31
+ "{numbers}": "123",
32
+ "{ent}": "return",
33
+ "{escape}": "esc ⎋",
34
+ "{tab}": "tab ⇥",
35
+ "{backspace}": "⌫",
36
+ "{capslock}": "caps lock ⇪",
37
+ "{shift}": "⇧",
38
+ "{controlleft}": "ctrl ⌃",
39
+ "{controlright}": "ctrl ⌃",
40
+ "{altleft}": "alt ⌥",
41
+ "{altright}": "alt ⌥",
42
+ "{metaleft}": "cmd ⌘",
43
+ "{metaright}": "cmd ⌘",
44
+ "{abc}": "ABC",
45
+ "{space}": "space",
46
+ "{symbols}": "#+="
47
+ };
48
+
49
+
50
+
51
+ interface OskProps {
52
+ onAccept?: () => void;
53
+ onChange?: (value: string) => void;
54
+ isNumPad?: boolean;
55
+ input?: string;
56
+ label?: string;
57
+ inputPattern?: RegExp;
58
+ checkValue?: (value: string) => string;
59
+ description?: string;
60
+ }
61
+
62
+ export const Osk: React.FC<OskProps> = ({
63
+ onAccept,
64
+ onChange,
65
+ isNumPad = false,
66
+ input = "",
67
+ label = "",
68
+ inputPattern,
69
+ checkValue,
70
+ description,
71
+ }) => {
72
+ const [state, setState] = useState({
73
+ isVisible: false,
74
+ layoutName: isNumPad ? "numbers" : "default",
75
+ minWidth: 500,
76
+ maxWidth: 800,
77
+ input,
78
+ label,
79
+ isNumPad,
80
+ inputPattern: inputPattern || RegExMaskPatterns.IntegerPositive,
81
+ checkValue,
82
+ description,
83
+ firstKeyPressed: false,
84
+ onAccept: onAccept || undefined,
85
+ onChange: onChange || undefined
86
+ });
87
+ const keyboardRef = useRef<any>(null);
88
+
89
+ useEffect(() => {
90
+ return () => {
91
+ if (keyboardRef.current) {
92
+ keyboardRef.current.destroy();
93
+ }
94
+ };
95
+ }, []);
96
+
97
+ // const setProperty = (key: keyof typeof state, val: any) => {
98
+ // setState((prev) => ({ ...prev, [key]: val }));
99
+ // };
100
+
101
+ const onChanged = (val: string) => {
102
+ let newInput = val;
103
+ if (!state.firstKeyPressed) {
104
+ newInput = state.input + val;
105
+ keyboardRef.current.setInput(newInput);
106
+ }
107
+
108
+ if (state.onChange) {
109
+ state.onChange(newInput);
110
+ }
111
+
112
+ setState(prevState => ({ ...prevState, input: newInput, firstKeyPressed: true }));
113
+ };
114
+
115
+
116
+ const getLayout = () => {
117
+ if (state.isNumPad) {
118
+ if (state.isNumPad) {
119
+
120
+ if ( state.inputPattern === undefined || state.inputPattern === null) {
121
+ setState(prevState=> ({...prevState, inputPattern:RegExMaskPatterns.IntegerPositive}));
122
+ }
123
+
124
+ return numpadLayout;
125
+ }
126
+ else {
127
+ return englishLayout;
128
+ }
129
+ }
130
+ }
131
+
132
+
133
+ const onKeyPress = (button: string) => {
134
+ if (button === "{shift}" || button === "{lock}" || button == "{symbols}")
135
+ handleShift();
136
+
137
+ if (button === "{numbers}" || button === "{abc}")
138
+ handleNumbers();
139
+
140
+ if (button === "{backspace}" ) {
141
+ // Backspace was pressed
142
+
143
+ if ( !state.firstKeyPressed )
144
+ {
145
+ setState(prevState => ({...prevState, input:"",firstKeyPressed:true}));
146
+ }
147
+ }
148
+ };
149
+
150
+
151
+
152
+ /**
153
+ * Toggle between the shifted and default display when the shift key is pressed.
154
+ */
155
+ const handleShift = () => {
156
+ let currentLayout = state.layoutName;
157
+ let shiftToggle = currentLayout === "default" ? "shift" : "default";
158
+ setState(prevState => ({...prevState, layoutName: shiftToggle }));
159
+ }
160
+
161
+ /**
162
+ * Toggle between the number and alpha-numeric display when the numbers key is pressed.
163
+ */
164
+ const handleNumbers = () => {
165
+ let currentLayout = state.layoutName;
166
+ let numbersToggle = currentLayout !== "numbers" ? "numbers" : "default";
167
+ setState(prevState => ({...prevState, layoutName: numbersToggle }));
168
+ }
169
+
170
+ return (
171
+ <div>
172
+ <InputText
173
+ value={state.input}
174
+ readOnly={true}
175
+ tooltip={state.description}
176
+ />
177
+ <br />
178
+ <Keyboard
179
+ keyboardRef={(r) => (keyboardRef.current = r)}
180
+ name='keyboard'
181
+ layoutName={state.layoutName}
182
+ layout={getLayout()}
183
+ display={keyboardDisplay}
184
+ physicalKeyboardHighlight={true}
185
+ physicalKeyboardHighlightPress={true}
186
+ onChange={(val) => onChanged(val)}
187
+ onKeyPress={(button) => onKeyPress(button)}
188
+ />
189
+ </div>
190
+ );
191
+ };
192
+
193
+ export default Osk;
@@ -0,0 +1,165 @@
1
+ import React from 'react';
2
+ import ReactDOM from 'react-dom';
3
+ import { Dialog } from 'primereact/dialog';
4
+ import {Button} from "primereact/button";
5
+ import { Osk } from './Osk';
6
+
7
+ interface OskDialogProps {
8
+ isVisible: boolean;
9
+ onAccept?: (value: string) => void;
10
+ onReject?: () => void;
11
+ onChange?: (value: string) => void;
12
+ isNumPad?: boolean;
13
+ maxWidth?: number;
14
+ input?: string;
15
+ label?: string;
16
+ description?: string;
17
+ inputPattern?: RegExp;
18
+ textMode?: boolean;
19
+ minValue?: number;
20
+ maxValue?: number;
21
+ minLength?: number;
22
+ }
23
+
24
+ interface OskDialogState {
25
+ input: string;
26
+ errorMessage: string;
27
+ }
28
+
29
+ export class OskDialog extends React.Component<OskDialogProps, OskDialogState> {
30
+ private container: HTMLDivElement | null = null;
31
+
32
+ constructor(props: OskDialogProps) {
33
+ super(props);
34
+ this.state = {
35
+ input: props.input || "",
36
+ errorMessage: ""
37
+ };
38
+ }
39
+
40
+ componentWillUnmount() {
41
+ if (this.container) {
42
+ document.body.removeChild(this.container);
43
+ }
44
+ }
45
+
46
+ checkValue = (value: string): string => {
47
+ // Checks the value against settings and returns an error message
48
+ // if invalid. If the value is valid and should be accepted,
49
+ // a blank error message is returned.
50
+
51
+ var ok = true;
52
+
53
+ if (value !== undefined && value !== null && value.length > 0) {
54
+
55
+ if (this.props.inputPattern !== undefined) {
56
+ ok = this.props.inputPattern.test(value);
57
+ }
58
+ else if (!this.props.textMode) {
59
+
60
+ if (value.length < 0)
61
+ ok = false;
62
+
63
+ if (isNaN(parseFloat(value)))
64
+ ok = false;
65
+
66
+
67
+ var checkValue = parseFloat(value);
68
+
69
+ if (this.props.minValue !== undefined && this.props.minValue !== null) {
70
+ if (checkValue < this.props.minValue)
71
+ ok = false;
72
+
73
+ }
74
+
75
+ if (this.props.maxValue !== undefined && this.props.maxValue !== null) {
76
+ if (checkValue > this.props.maxValue)
77
+ ok = false;
78
+ }
79
+ }
80
+ else {
81
+ if (this.props.minLength !== undefined
82
+ && value.length < this.props.minLength
83
+ ) {
84
+ ok = false;
85
+ }
86
+ }
87
+ }
88
+ else {
89
+ ok = false;
90
+ }
91
+
92
+ if (ok) {
93
+ return "";
94
+ }
95
+ else {
96
+ return "Invalid value.";
97
+ }
98
+ }
99
+
100
+ onAccepted = () => {
101
+ const error = this.checkValue(this.state.input);
102
+ if (!error) {
103
+ this.props.onAccept?.(this.state.input);
104
+ this.closeDialog();
105
+ } else {
106
+ this.setState({ errorMessage: error });
107
+ }
108
+ }
109
+
110
+ onChanged = (val: string) => {
111
+ this.setState({ input: val, errorMessage: "" });
112
+ if (this.props.onChange) {
113
+ this.props.onChange(val);
114
+ }
115
+ }
116
+
117
+ closeDialog = () => {
118
+ if (this.container) {
119
+ ReactDOM.unmountComponentAtNode(this.container);
120
+ this.container = null;
121
+ }
122
+ this.props.onReject?.();
123
+ }
124
+
125
+ show = () => {
126
+ if (!this.container) {
127
+ this.container = document.createElement('div');
128
+ document.body.appendChild(this.container);
129
+ }
130
+
131
+ const footerContent = (
132
+ <div>
133
+ <Button label="Cancel" icon="pi pi-times" onClick={() => this.closeDialog()} className="p-button-text" />
134
+ <Button label="Accept" icon="pi pi-check" onClick={() => this.onAccepted()} autoFocus />
135
+ </div>
136
+ );
137
+
138
+
139
+ ReactDOM.render(
140
+ <Dialog
141
+ visible={this.props.isVisible}
142
+ onHide={this.closeDialog}
143
+ header={this.props.label}
144
+ style={{ width: this.props.maxWidth || '50vw' }}
145
+ footer={footerContent}
146
+ >
147
+ <Osk
148
+ onChange={this.onChanged}
149
+ isNumPad={this.props.isNumPad}
150
+ inputPattern={this.props.inputPattern}
151
+ input={this.state.input}
152
+ />
153
+ {this.state.errorMessage && <div className="error-message">{this.state.errorMessage}</div>}
154
+ </Dialog>,
155
+ this.container
156
+ );
157
+ }
158
+
159
+ render() {
160
+ // The actual rendering is handled by the show method.
161
+ return null;
162
+ }
163
+ }
164
+
165
+ export default OskDialog;
@@ -0,0 +1,181 @@
1
+ /*
2
+ * Copyright (C) 2024 Automated Design Corp. All Rights Reserved.
3
+ * Created Date: 2024-01-16 14:17:02
4
+ * -----
5
+ * Last Modified: 2024-03-08 07:48:42
6
+ * Modified By: ADC
7
+ * -----
8
+ *
9
+ */
10
+
11
+
12
+
13
+ import {Component} from 'react';
14
+ //import useFitText from 'use-fit-text';
15
+ import { format as numerableFormat } from 'numerable';
16
+ import clsx from 'clsx';
17
+ import { EventEmitterContext, EventEmitterContextType} from '../core/EventEmitterContext';
18
+
19
+ import {IPositionContext} from '../core/PositionContext';
20
+ import type { NumerableFormatOptions } from '../core/NumerableTypes';
21
+
22
+ /**
23
+ * Properties of the ValueDisplay component.
24
+ */
25
+ interface Props {
26
+ /**
27
+ * Value to be displayed
28
+ */
29
+ value?: string | number | null | undefined;
30
+ /**
31
+ * X position (in pixels)
32
+ */
33
+ x?: number;
34
+ /**
35
+ * Y position (in pixels)
36
+ */
37
+ y?: number;
38
+ /**
39
+ * Width (in pixels)
40
+ */
41
+ width?: number;
42
+ /**
43
+ * Height (in pixels)<br/>
44
+ * @default width
45
+ */
46
+ height?: number;
47
+ /**
48
+ * Format for `value`<br/>
49
+ * See [numerable formats](https://github.com/gastonmesseri/numerable#1234-formatting-numbers)
50
+ */
51
+ format?: string | null | undefined;
52
+ /**
53
+ * Format options for `value`<br/>
54
+ * See [numerable format options](https://github.com/gastonmesseri/numerable#format)
55
+ */
56
+ formatOptions?: NumerableFormatOptions;
57
+ /**
58
+ * Custom class name to be attached
59
+ */
60
+ className?: string;
61
+
62
+ /**
63
+ * Enable absolute positioning for the component, allowing it to be
64
+ * placed on a specific position of its parent. This is useful when
65
+ * laying components over an image or wireframe.
66
+ */
67
+ useAbsolutePositioning?: boolean;
68
+
69
+
70
+ /**
71
+ * The topic to monitor to display. Optional.
72
+ */
73
+ topic?: string;
74
+ }
75
+
76
+ /**
77
+ * State of the ValueDisplay component.
78
+ */
79
+ interface State {
80
+ subscribedValue?: string | number | null;
81
+ fontSize?: string;
82
+ }
83
+
84
+
85
+
86
+ /**
87
+ * `ValueDisplay` is a React component that subscribes to a value from an `EventEmitterContext` and renders it.
88
+ * This component adjusts its display based on the provided properties, including positioning and styling adjustments
89
+ * based on its context. It is designed to work within a system that provides dynamic updates to values via an event emitter.
90
+ */
91
+ class ValueDisplay extends Component<Props, State> {
92
+
93
+ /** Defines the context type to subscribe to changes using EventEmitter. */
94
+ static contextType = EventEmitterContext;
95
+
96
+
97
+ /** ID for the subscription to the topic, used to unsubscribe on component unmount. */
98
+ protected unsubscribeTopicId: number | null = null;
99
+
100
+ /**
101
+ * The constructor initializes the component state and binds the initial value.
102
+ * @param props The properties passed to the component, including initial value and other display options.
103
+ */
104
+ constructor(props: Props) {
105
+ super(props);
106
+ this.state = {
107
+ subscribedValue: props.value,
108
+ fontSize: '100%' // Initial font size, adjust as needed
109
+ };
110
+ }
111
+
112
+ /**
113
+ * Upon mounting, the component subscribes to updates on the specified topic if it exists,
114
+ * updating its state with the new value when the topic publishes updates.
115
+ */
116
+ componentDidMount() {
117
+ const { topic } = this.props;
118
+ if (topic) {
119
+ const { subscribe } = this.context as EventEmitterContextType;
120
+ this.unsubscribeTopicId = subscribe(topic, (value: any) => {
121
+ this.setState({ subscribedValue: value });
122
+ });
123
+ }
124
+ }
125
+
126
+ /**
127
+ * If the value prop changes, the component updates its state with the new value.
128
+ * This ensures that the component remains in sync with its props.
129
+ * @param prevProps The previous properties for comparison to detect changes.
130
+ */
131
+ componentDidUpdate(prevProps: Props) {
132
+ // Check if the value prop has changed
133
+ if (this.props.value !== prevProps.value) {
134
+ // Update the state with the new value
135
+ this.setState({ subscribedValue: this.props.value });
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Before the component is unmounted, it unsubscribes from the topic to prevent memory leaks
141
+ * and unnecessary updates from occurring.
142
+ */
143
+ componentWillUnmount() {
144
+ if (this.unsubscribeTopicId) {
145
+ const { unsubscribe } = this.context as EventEmitterContextType;
146
+ unsubscribe(this.unsubscribeTopicId);
147
+ }
148
+ }
149
+
150
+ /**
151
+ * Renders the component with styling and formatting based on the provided properties and state.
152
+ * Supports absolute or relative positioning and scales the display based on the context's dimensions.
153
+ * @returns A styled `div` element displaying the formatted value.
154
+ */
155
+ render() {
156
+ const { x, y, width, height, format, formatOptions, className, useAbsolutePositioning } = this.props;
157
+ const { subscribedValue, fontSize } = this.state;
158
+ const { scale, xOffset, yOffset } = this.context as IPositionContext;
159
+
160
+ const style : React.CSSProperties = {
161
+ position: useAbsolutePositioning ? 'absolute' : 'relative',
162
+ display: useAbsolutePositioning ? "" : "inline-block",
163
+ verticalAlign: 'middle',
164
+ fontSize: fontSize && scale > 1 ? `${scale * 100}%` : fontSize,
165
+ top: useAbsolutePositioning && y ? `${yOffset + scale * y}px` : undefined,
166
+ left: useAbsolutePositioning && x ? `${xOffset + scale * x}px` : undefined,
167
+ width: width ? `${width * scale}px` : undefined,
168
+ height: height ? `${height * scale}px` : undefined,
169
+ lineHeight: height ? `${height * scale}px` : undefined,
170
+ whiteSpace: 'nowrap',
171
+ };
172
+
173
+ return (
174
+ <div className={clsx(className)} style={style}>
175
+ {numerableFormat(subscribedValue, format, formatOptions)}
176
+ </div>
177
+ );
178
+ }
179
+ }
180
+
181
+ export { ValueDisplay, NumerableFormatOptions };
@@ -0,0 +1,123 @@
1
+ /*
2
+ * Customized by Thomas C. Bitsky Jr. Automated Design Corporation.
3
+ *
4
+ * Original file:
5
+ *
6
+ * simple-keyboard v2.32.100
7
+ * https://github.com/hodgef/simple-keyboard
8
+ *
9
+ * Copyright (c) Francisco Hodge (https://github.com/hodgef)
10
+ */
11
+
12
+ .hg-theme-default {
13
+ width: 100%;
14
+ -webkit-user-select: none;
15
+ -moz-user-select: none;
16
+ -ms-user-select: none;
17
+ user-select: none;
18
+ box-sizing: border-box;
19
+ overflow: hidden;
20
+ touch-action: manipulation
21
+ }
22
+
23
+ .hg-theme-default .hg-button span {
24
+ pointer-events: none
25
+ }
26
+
27
+ .hg-theme-default button.hg-button {
28
+ border-width: 0;
29
+ outline: 0;
30
+ font-size: inherit
31
+ }
32
+
33
+ .hg-theme-default {
34
+ background-color: #ececec;
35
+ padding: 5px;
36
+ border-radius: 5px
37
+ }
38
+
39
+ .hg-theme-default .hg-button {
40
+ display: inline-block;
41
+ flex-grow: 1
42
+ }
43
+
44
+ .hg-theme-default .hg-row {
45
+ display: flex
46
+ }
47
+
48
+ .hg-theme-default .hg-row:not(:last-child) {
49
+ margin-bottom: 5px
50
+ }
51
+
52
+ .hg-theme-default .hg-row .hg-button-container,
53
+ .hg-theme-default .hg-row .hg-button:not(:last-child) {
54
+ margin-right: 5px
55
+ }
56
+
57
+ .hg-theme-default .hg-row>div:last-child {
58
+ margin-right: 0
59
+ }
60
+
61
+ .hg-theme-default .hg-row .hg-button-container {
62
+ display: flex
63
+ }
64
+
65
+ .hg-theme-default .hg-button {
66
+ /* box-shadow: 0 0 3px -1px rgba(0, 0, 0, .3); */ /* use the shadow for an ios look */
67
+ font-weight: 600;
68
+ font-size: large;
69
+ height: 40px;
70
+ border-radius: 3px; /* set to 5 for ios look, 3 for microsoft look */
71
+ box-sizing: border-box;
72
+ padding: 5px;
73
+ color: white; /* color of the button text */
74
+ background: #444444; /* background of the button text */
75
+ border: 1px solid black;
76
+ cursor:pointer;
77
+ display: flex;
78
+ align-items: center;
79
+ justify-content: center;
80
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0)
81
+ }
82
+
83
+ .hg-theme-default .hg-button.hg-activeButton {
84
+ background: #efefef
85
+ }
86
+
87
+ .hg-theme-default.hg-layout-numeric .hg-button {
88
+ width: 33.3%;
89
+ height: 60px;
90
+ align-items: center;
91
+ display: flex;
92
+ justify-content: center
93
+ }
94
+
95
+ .hg-theme-default .hg-button.hg-button-numpadadd,
96
+ .hg-theme-default .hg-button.hg-button-numpadenter {
97
+ height: 85px
98
+ }
99
+
100
+ .hg-theme-default .hg-button.hg-button-numpad0 {
101
+ width: 105px
102
+ }
103
+
104
+ .hg-theme-default .hg-button.hg-button-com {
105
+ max-width: 85px
106
+ }
107
+
108
+ .hg-theme-default .hg-button.hg-standardBtn.hg-button-at {
109
+ max-width: 45px
110
+ }
111
+
112
+ .hg-theme-default .hg-button.hg-selectedButton {
113
+ background: rgba(5, 25, 70, .53);
114
+ color: #fff
115
+ }
116
+
117
+ .hg-theme-default .hg-button.hg-standardBtn[data-skbtn=".com"] {
118
+ max-width: 82px
119
+ }
120
+
121
+ .hg-theme-default .hg-button.hg-standardBtn[data-skbtn="@"] {
122
+ max-width: 60px
123
+ }