@dvrd/dvr-controls 1.0.88 → 1.1.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dvrd/dvr-controls",
3
- "version": "1.0.88",
3
+ "version": "1.1.0",
4
4
  "description": "Custom web controls",
5
5
  "main": "index.ts",
6
6
  "files": [
@@ -21,6 +21,7 @@ import {ElementPosition, ErrorType, OrnamentShape} from '../util/interfaces';
21
21
  import AwesomeIcon from '../icon/awesomeIcon';
22
22
  import {directTimeout} from '../util/componentUtil';
23
23
  import {stopPropagation} from "../util/controlUtil";
24
+ import NumberString from "../util/numberString";
24
25
 
25
26
  interface Props {
26
27
  onChange: ChangeEventHandler;
@@ -29,7 +30,7 @@ interface Props {
29
30
  onKeyDown: KeyboardEventHandler;
30
31
  onKeyUp?: KeyboardEventHandler;
31
32
  onClearInput?: MouseEventHandler;
32
- value: string | number;
33
+ value: string | number | NumberString;
33
34
  disabled?: boolean;
34
35
  autoFocus?: boolean;
35
36
  autoSelect?: boolean;
@@ -127,8 +128,8 @@ export default function DvrdInput(props: Props) {
127
128
 
128
129
  function renderInput() {
129
130
  const elementProps = {
130
- ...inputProps, value, onChange, onFocus: onFocusInput, onBlur: onBlurInput, onKeyDown, disabled,
131
- className: classNames('dvrd-input', inputClassName, noResize && 'no-resize'), id: `${id}-input`,
131
+ ...inputProps, value: value.toString(), onChange, onFocus: onFocusInput, onBlur: onBlurInput, onKeyDown,
132
+ disabled, className: classNames('dvrd-input', inputClassName, noResize && 'no-resize'), id: `${id}-input`,
132
133
  ref: inputRef, onKeyUp,
133
134
  };
134
135
  if (area) return <textarea {...elementProps}/>;
@@ -16,6 +16,7 @@ import {generateComponentId} from '../util/componentUtil';
16
16
  import {enterPressed} from '../util/controlUtil';
17
17
  import {ErrorType, OrnamentShape} from '../util/interfaces';
18
18
  import DvrdInput from "./dvrdInput";
19
+ import NumberString from "../util/numberString";
19
20
 
20
21
  export interface InputControllerProps {
21
22
  onChange: (value: string, evt: React.ChangeEvent) => void;
@@ -25,7 +26,7 @@ export interface InputControllerProps {
25
26
  onKeyUp?: KeyboardEventHandler;
26
27
  onEnter?: KeyboardEventHandler;
27
28
  onClearInput?: MouseEventHandler;
28
- value: string | number;
29
+ value: string | number | NumberString;
29
30
  label?: string;
30
31
  ornaments?: OrnamentShape | OrnamentShape[];
31
32
  inputProps?: InputHTMLAttributes<any> & TextareaHTMLAttributes<any>;
@@ -8,15 +8,16 @@ import {ChangeFunction, ErrorType, OrnamentShape} from '../util/interfaces';
8
8
  import {roundTo} from '../util/miscUtil';
9
9
  import DvrdInputController from "./dvrdInputController";
10
10
  import {isPasting, positionIsAfterComma, textIsSelected} from "../util/inputUtil";
11
+ import NumberString from "../util/numberString";
11
12
 
12
13
  interface Props {
13
- onChange: ChangeFunction<string | number>;
14
+ onChange: ChangeFunction<NumberString>;
14
15
  onFocus?: FocusEventHandler;
15
16
  onBlur?: FocusEventHandler;
16
17
  onKeyDown?: KeyboardEventHandler;
17
18
  onKeyUp?: KeyboardEventHandler;
18
19
  onEnter?: KeyboardEventHandler;
19
- value: string | number;
20
+ value: string | number | NumberString;
20
21
  label?: string;
21
22
  ornaments?: OrnamentShape | OrnamentShape[];
22
23
  inputProps?: InputHTMLAttributes<any>;
@@ -32,7 +33,6 @@ interface Props {
32
33
  placeholder?: string;
33
34
  multipleSeparators?: boolean;
34
35
  wholeNumbers?: boolean;
35
- asNumber?: boolean;
36
36
  asCurrency?: boolean;
37
37
  autoSelect?: boolean;
38
38
  unControlled?: boolean;
@@ -41,9 +41,9 @@ interface Props {
41
41
 
42
42
  export default function DVRDNumberInput(props: Props) {
43
43
  const {
44
- onKeyDown, inputProps, asCurrency, asNumber, wholeNumbers, disableSymbols, onChange, value, unControlled
44
+ onKeyDown, inputProps, asCurrency, wholeNumbers, disableSymbols, onChange, value, unControlled
45
45
  } = props;
46
- const [innerValue, setInnerValue] = useState(value);
46
+ const [innerValue, setInnerValue] = useState<NumberString>(new NumberString(value));
47
47
  const id = useRef(generateComponentId(props.id));
48
48
 
49
49
  function _onKeyDown(evt: React.KeyboardEvent<HTMLInputElement>) {
@@ -77,8 +77,7 @@ export default function DVRDNumberInput(props: Props) {
77
77
  numValue -= step;
78
78
  let stringValue = numValue.toString();
79
79
  if (asCurrency) stringValue = roundTo(numValue, 2);
80
- if (asNumber) change(Number(stringValue));
81
- else change(stringValue);
80
+ change(new NumberString(stringValue));
82
81
  }
83
82
 
84
83
  function onKeyDownSelected(evt: React.KeyboardEvent<HTMLInputElement>) {
@@ -111,15 +110,13 @@ export default function DVRDNumberInput(props: Props) {
111
110
  value = value.replace(/[^0-9-]/g, '').trim();
112
111
  if (disableSymbols)
113
112
  value = value.replace(/[\-+]/g, '').trim();
114
- if (asNumber) {
115
- const numValue = Number(value.replace(',', '.'));
116
- change(numValue, evt);
117
- } else change(value, evt);
113
+ const numValue = new NumberString(value);
114
+ change(numValue, evt);
118
115
  }
119
116
  return value;
120
117
  }
121
118
 
122
- function change(value: number | string, evt?: React.ChangeEvent<HTMLInputElement>) {
119
+ function change(value: NumberString, evt?: React.ChangeEvent<HTMLInputElement>) {
123
120
  setInnerValue(value);
124
121
  onChange(value, evt);
125
122
  }
@@ -129,7 +126,7 @@ export default function DVRDNumberInput(props: Props) {
129
126
  }
130
127
 
131
128
  useEffect(() => {
132
- if (!unControlled) setInnerValue(value);
129
+ if (!unControlled) setInnerValue(new NumberString(value));
133
130
  }, [value]);
134
131
 
135
132
  useEffect(() => {
@@ -138,6 +135,7 @@ export default function DVRDNumberInput(props: Props) {
138
135
  }, [props.disabled, props.autoFocus]);
139
136
 
140
137
  return (
141
- <DvrdInputController {...props} id={id.current} onChange={_onChange} onKeyDown={_onKeyDown} value={innerValue}/>
138
+ <DvrdInputController {...props} id={id.current} onChange={_onChange} onKeyDown={_onKeyDown}
139
+ value={innerValue}/>
142
140
  );
143
141
  }
@@ -0,0 +1,41 @@
1
+ import { nullify } from "./miscUtil";
2
+
3
+ export default class NumberString {
4
+ private value: string;
5
+ private readonly zeroAsNull: boolean;
6
+
7
+ constructor(value?: string | number | NumberString, zeroAsNull: boolean = false) {
8
+ this.value = value?.toString() ?? '';
9
+ this.zeroAsNull = zeroAsNull;
10
+ }
11
+
12
+ get stringValue(): string {
13
+ return this.value;
14
+ }
15
+
16
+ get numberValue(): number {
17
+ const numValue = Number(this.value.replace(',', '.'));
18
+ return Number.isNaN(numValue) ? 0 : numValue;
19
+ }
20
+
21
+ get nullStringValue(): string | null {
22
+ return nullify(this.value);
23
+ }
24
+
25
+ get nullNumberValue(): number | null {
26
+ const nullString = this.nullStringValue;
27
+ if (!nullString) return null;
28
+ const numValue = Number(nullString.replace(',', '.'));
29
+ if (Number.isNaN(numValue)) return null;
30
+ return (this.zeroAsNull && !numValue) ? null : 0;
31
+ }
32
+
33
+ setValue = (value: string | number): NumberString => {
34
+ this.value = value.toString();
35
+ return this;
36
+ }
37
+
38
+ toString = () => {
39
+ return this.stringValue;
40
+ }
41
+ }