numora-react 1.0.6 → 1.0.7

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/index.cjs ADDED
@@ -0,0 +1,171 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var react = require('react');
5
+ var numora = require('numora');
6
+
7
+ function handleNumoraOnChange(e, options) {
8
+ numora.handleOnChangeNumoraInput(e.nativeEvent, options.decimalMaxLength, options.caretPositionBeforeChange, options.formattingOptions);
9
+ const target = e.target;
10
+ const rawValue = target.getAttribute('data-raw-value') ?? undefined;
11
+ if (rawValue) {
12
+ target.removeAttribute('data-raw-value');
13
+ }
14
+ return {
15
+ value: target.value,
16
+ rawValue,
17
+ };
18
+ }
19
+ function handleNumoraOnPaste(e, options) {
20
+ const value = numora.handleOnPasteNumoraInput(e.nativeEvent, options.decimalMaxLength, options.formattingOptions);
21
+ const target = e.target;
22
+ const rawValue = target.getAttribute('data-raw-value') ?? undefined;
23
+ if (rawValue) {
24
+ target.removeAttribute('data-raw-value');
25
+ }
26
+ return {
27
+ value,
28
+ rawValue,
29
+ };
30
+ }
31
+ function handleNumoraOnKeyDown(e, formattingOptions) {
32
+ return numora.handleOnKeyDownNumoraInput(e.nativeEvent, formattingOptions);
33
+ }
34
+ function handleNumoraOnBlur(e, options) {
35
+ // If formatOn is blur, force formatting on blur by invoking change handler logic
36
+ if (options.formattingOptions.formatOn === numora.FormatOn.Blur) {
37
+ numora.handleOnChangeNumoraInput(e.nativeEvent, options.decimalMaxLength, undefined, { ...options.formattingOptions, formatOn: numora.FormatOn.Change });
38
+ }
39
+ const target = e.target;
40
+ const rawValue = target.getAttribute('data-raw-value') ?? undefined;
41
+ if (rawValue) {
42
+ target.removeAttribute('data-raw-value');
43
+ }
44
+ return {
45
+ value: target.value,
46
+ rawValue,
47
+ };
48
+ }
49
+
50
+ const NumoraInput = react.forwardRef((props, ref) => {
51
+ const { maxDecimals = 2, onChange, onPaste, onBlur, onKeyDown, formatOn = numora.FormatOn.Blur, thousandSeparator = ',', thousandStyle = numora.ThousandStyle.Thousand, decimalSeparator = '.', decimalMinLength, enableCompactNotation = false, enableNegative = false, enableLeadingZeros = false, rawValueMode = false, value: controlledValue, defaultValue, ...rest } = props;
52
+ const inputRef = react.useRef(null);
53
+ const caretInfoRef = react.useRef(undefined);
54
+ const [internalValue, setInternalValue] = react.useState(controlledValue !== undefined
55
+ ? String(controlledValue)
56
+ : defaultValue !== undefined
57
+ ? String(defaultValue)
58
+ : '');
59
+ // Keep internal state in sync when controlled
60
+ react.useEffect(() => {
61
+ if (controlledValue !== undefined) {
62
+ setInternalValue(String(controlledValue));
63
+ }
64
+ }, [controlledValue]);
65
+ react.useImperativeHandle(ref, () => inputRef.current, []);
66
+ const formattingOptions = {
67
+ formatOn,
68
+ thousandSeparator,
69
+ ThousandStyle: thousandStyle,
70
+ decimalSeparator,
71
+ decimalMinLength,
72
+ enableCompactNotation,
73
+ enableNegative,
74
+ enableLeadingZeros,
75
+ rawValueMode,
76
+ };
77
+ const formatValueWithCore = (value) => {
78
+ const el = inputRef.current ?? document.createElement('input');
79
+ el.value = value;
80
+ const fakeEvent = { target: el };
81
+ numora.handleOnChangeNumoraInput(fakeEvent, maxDecimals, undefined, formattingOptions);
82
+ return el.value;
83
+ };
84
+ // When controlled value changes, normalize/format it for display
85
+ react.useEffect(() => {
86
+ if (controlledValue !== undefined) {
87
+ const formatted = formatValueWithCore(String(controlledValue));
88
+ setInternalValue(formatted);
89
+ }
90
+ }, [controlledValue, formatOn, thousandSeparator, thousandStyle, decimalSeparator, decimalMinLength, enableCompactNotation, enableNegative, enableLeadingZeros, rawValueMode, maxDecimals]);
91
+ const handleChange = (e) => {
92
+ const { value, rawValue } = handleNumoraOnChange(e, {
93
+ decimalMaxLength: maxDecimals,
94
+ caretPositionBeforeChange: caretInfoRef.current,
95
+ formattingOptions,
96
+ });
97
+ caretInfoRef.current = undefined;
98
+ if (controlledValue === undefined) {
99
+ setInternalValue(value);
100
+ }
101
+ else {
102
+ setInternalValue(value);
103
+ }
104
+ if (onChange) {
105
+ onChange(e);
106
+ }
107
+ // Optionally expose rawValue via a custom event attribute if needed later
108
+ if (rawValue && e.target && rawValueMode) {
109
+ // Keep the raw value on the input for consumers that read it directly
110
+ e.target.setAttribute('data-raw-value', rawValue);
111
+ }
112
+ };
113
+ const handlePaste = (e) => {
114
+ const { value, rawValue } = handleNumoraOnPaste(e, {
115
+ decimalMaxLength: maxDecimals,
116
+ formattingOptions,
117
+ });
118
+ if (controlledValue === undefined) {
119
+ setInternalValue(value);
120
+ }
121
+ else {
122
+ setInternalValue(value);
123
+ }
124
+ if (onPaste) {
125
+ onPaste(e);
126
+ }
127
+ if (onChange) {
128
+ onChange(e);
129
+ }
130
+ if (rawValue && e.target && rawValueMode) {
131
+ e.target.setAttribute('data-raw-value', rawValue);
132
+ }
133
+ };
134
+ const handleKeyDown = (e) => {
135
+ caretInfoRef.current = handleNumoraOnKeyDown(e, formattingOptions);
136
+ if (onKeyDown) {
137
+ onKeyDown(e);
138
+ }
139
+ };
140
+ const handleBlur = (e) => {
141
+ const { value, rawValue } = handleNumoraOnBlur(e, {
142
+ decimalMaxLength: maxDecimals,
143
+ formattingOptions,
144
+ });
145
+ if (controlledValue === undefined) {
146
+ setInternalValue(value);
147
+ }
148
+ else {
149
+ setInternalValue(value);
150
+ }
151
+ if (onBlur) {
152
+ onBlur(e);
153
+ }
154
+ if (rawValue && e.target && rawValueMode) {
155
+ e.target.setAttribute('data-raw-value', rawValue);
156
+ }
157
+ };
158
+ return (jsxRuntime.jsx("input", { ...rest, ref: inputRef, value: internalValue, onChange: handleChange, onPaste: handlePaste, onKeyDown: handleKeyDown, onBlur: handleBlur, type: "text", inputMode: "decimal" }));
159
+ });
160
+ NumoraInput.displayName = 'NumoraInput';
161
+
162
+ Object.defineProperty(exports, "FormatOn", {
163
+ enumerable: true,
164
+ get: function () { return numora.FormatOn; }
165
+ });
166
+ Object.defineProperty(exports, "ThousandStyle", {
167
+ enumerable: true,
168
+ get: function () { return numora.ThousandStyle; }
169
+ });
170
+ exports.NumoraInput = NumoraInput;
171
+ //# sourceMappingURL=index.cjs.map
package/dist/index.cjs.js CHANGED
@@ -5,192 +5,157 @@ var react = require('react');
5
5
  var numora = require('numora');
6
6
 
7
7
  function handleNumoraOnChange(e, options) {
8
- numora.handleOnChangeNumoraInput(e.nativeEvent, options.decimalMaxLength, options.caretPositionBeforeChange, options.formattingOptions);
9
- const target = e.target;
10
- const rawValue = target.getAttribute('data-raw-value') ?? undefined;
11
- if (rawValue) {
12
- target.removeAttribute('data-raw-value');
13
- }
14
- return {
15
- value: target.value,
16
- rawValue
17
- };
8
+ numora.handleOnChangeNumoraInput(e.nativeEvent, options.decimalMaxLength, options.caretPositionBeforeChange, options.formattingOptions);
9
+ const target = e.target;
10
+ const rawValue = target.getAttribute('data-raw-value') ?? undefined;
11
+ if (rawValue) {
12
+ target.removeAttribute('data-raw-value');
13
+ }
14
+ return {
15
+ value: target.value,
16
+ rawValue,
17
+ };
18
18
  }
19
19
  function handleNumoraOnPaste(e, options) {
20
- const value = numora.handleOnPasteNumoraInput(e.nativeEvent, options.decimalMaxLength, options.formattingOptions);
21
- const target = e.target;
22
- const rawValue = target.getAttribute('data-raw-value') ?? undefined;
23
- if (rawValue) {
24
- target.removeAttribute('data-raw-value');
25
- }
26
- return {
27
- value,
28
- rawValue
29
- };
20
+ const value = numora.handleOnPasteNumoraInput(e.nativeEvent, options.decimalMaxLength, options.formattingOptions);
21
+ const target = e.target;
22
+ const rawValue = target.getAttribute('data-raw-value') ?? undefined;
23
+ if (rawValue) {
24
+ target.removeAttribute('data-raw-value');
25
+ }
26
+ return {
27
+ value,
28
+ rawValue,
29
+ };
30
30
  }
31
31
  function handleNumoraOnKeyDown(e, formattingOptions) {
32
- return numora.handleOnKeyDownNumoraInput(e.nativeEvent, formattingOptions);
32
+ return numora.handleOnKeyDownNumoraInput(e.nativeEvent, formattingOptions);
33
33
  }
34
34
  function handleNumoraOnBlur(e, options) {
35
- // If formatOn is blur, force formatting on blur by invoking change handler logic
36
- if (options.formattingOptions.formatOn === numora.FormatOn.Blur) {
37
- numora.handleOnChangeNumoraInput(e.nativeEvent, options.decimalMaxLength, undefined, {
38
- ...options.formattingOptions,
39
- formatOn: numora.FormatOn.Change
40
- });
41
- }
42
- const target = e.target;
43
- const rawValue = target.getAttribute('data-raw-value') ?? undefined;
44
- if (rawValue) {
45
- target.removeAttribute('data-raw-value');
46
- }
47
- return {
48
- value: target.value,
49
- rawValue
50
- };
35
+ // If formatOn is blur, force formatting on blur by invoking change handler logic
36
+ if (options.formattingOptions.formatOn === numora.FormatOn.Blur) {
37
+ numora.handleOnChangeNumoraInput(e.nativeEvent, options.decimalMaxLength, undefined, { ...options.formattingOptions, formatOn: numora.FormatOn.Change });
38
+ }
39
+ const target = e.target;
40
+ const rawValue = target.getAttribute('data-raw-value') ?? undefined;
41
+ if (rawValue) {
42
+ target.removeAttribute('data-raw-value');
43
+ }
44
+ return {
45
+ value: target.value,
46
+ rawValue,
47
+ };
51
48
  }
52
49
 
53
- const NumoraInput = /*#__PURE__*/react.forwardRef((props, ref) => {
54
- const {
55
- maxDecimals = 2,
56
- onChange,
57
- onPaste,
58
- onBlur,
59
- onKeyDown,
60
- formatOn = numora.FormatOn.Blur,
61
- thousandSeparator = ',',
62
- thousandStyle = numora.ThousandStyle.Thousand,
63
- decimalSeparator = '.',
64
- decimalMinLength,
65
- enableCompactNotation = false,
66
- enableNegative = false,
67
- enableLeadingZeros = false,
68
- rawValueMode = false,
69
- value: controlledValue,
70
- defaultValue,
71
- ...rest
72
- } = props;
73
- const inputRef = react.useRef(null);
74
- const caretInfoRef = react.useRef(undefined);
75
- const [internalValue, setInternalValue] = react.useState(controlledValue !== undefined ? String(controlledValue) : defaultValue !== undefined ? String(defaultValue) : '');
76
- // Keep internal state in sync when controlled
77
- react.useEffect(() => {
78
- if (controlledValue !== undefined) {
79
- setInternalValue(String(controlledValue));
80
- }
81
- }, [controlledValue]);
82
- react.useImperativeHandle(ref, () => inputRef.current, []);
83
- const formattingOptions = {
84
- formatOn,
85
- thousandSeparator,
86
- ThousandStyle: thousandStyle,
87
- decimalSeparator,
88
- decimalMinLength,
89
- enableCompactNotation,
90
- enableNegative,
91
- enableLeadingZeros,
92
- rawValueMode
93
- };
94
- const formatValueWithCore = value => {
95
- const el = inputRef.current ?? document.createElement('input');
96
- el.value = value;
97
- const fakeEvent = {
98
- target: el
50
+ const NumoraInput = react.forwardRef((props, ref) => {
51
+ const { maxDecimals = 2, onChange, onPaste, onBlur, onKeyDown, formatOn = numora.FormatOn.Blur, thousandSeparator = ',', thousandStyle = numora.ThousandStyle.Thousand, decimalSeparator = '.', decimalMinLength, enableCompactNotation = false, enableNegative = false, enableLeadingZeros = false, rawValueMode = false, value: controlledValue, defaultValue, ...rest } = props;
52
+ const inputRef = react.useRef(null);
53
+ const caretInfoRef = react.useRef(undefined);
54
+ const [internalValue, setInternalValue] = react.useState(controlledValue !== undefined
55
+ ? String(controlledValue)
56
+ : defaultValue !== undefined
57
+ ? String(defaultValue)
58
+ : '');
59
+ // Keep internal state in sync when controlled
60
+ react.useEffect(() => {
61
+ if (controlledValue !== undefined) {
62
+ setInternalValue(String(controlledValue));
63
+ }
64
+ }, [controlledValue]);
65
+ react.useImperativeHandle(ref, () => inputRef.current, []);
66
+ const formattingOptions = {
67
+ formatOn,
68
+ thousandSeparator,
69
+ ThousandStyle: thousandStyle,
70
+ decimalSeparator,
71
+ decimalMinLength,
72
+ enableCompactNotation,
73
+ enableNegative,
74
+ enableLeadingZeros,
75
+ rawValueMode,
99
76
  };
100
- numora.handleOnChangeNumoraInput(fakeEvent, maxDecimals, undefined, formattingOptions);
101
- return el.value;
102
- };
103
- // When controlled value changes, normalize/format it for display
104
- react.useEffect(() => {
105
- if (controlledValue !== undefined) {
106
- const formatted = formatValueWithCore(String(controlledValue));
107
- setInternalValue(formatted);
108
- }
109
- }, [controlledValue, formatOn, thousandSeparator, thousandStyle, decimalSeparator, decimalMinLength, enableCompactNotation, enableNegative, enableLeadingZeros, rawValueMode, maxDecimals]);
110
- const handleChange = e => {
111
- const {
112
- value,
113
- rawValue
114
- } = handleNumoraOnChange(e, {
115
- decimalMaxLength: maxDecimals,
116
- caretPositionBeforeChange: caretInfoRef.current,
117
- formattingOptions
118
- });
119
- caretInfoRef.current = undefined;
120
- if (controlledValue === undefined) {
121
- setInternalValue(value);
122
- } else {
123
- setInternalValue(value);
124
- }
125
- if (onChange) {
126
- onChange(e);
127
- }
128
- // Optionally expose rawValue via a custom event attribute if needed later
129
- if (rawValue && e.target && rawValueMode) {
130
- // Keep the raw value on the input for consumers that read it directly
131
- e.target.setAttribute('data-raw-value', rawValue);
132
- }
133
- };
134
- const handlePaste = e => {
135
- const {
136
- value,
137
- rawValue
138
- } = handleNumoraOnPaste(e, {
139
- decimalMaxLength: maxDecimals,
140
- formattingOptions
141
- });
142
- if (controlledValue === undefined) {
143
- setInternalValue(value);
144
- } else {
145
- setInternalValue(value);
146
- }
147
- if (onPaste) {
148
- onPaste(e);
149
- }
150
- if (onChange) {
151
- onChange(e);
152
- }
153
- if (rawValue && e.target && rawValueMode) {
154
- e.target.setAttribute('data-raw-value', rawValue);
155
- }
156
- };
157
- const handleKeyDown = e => {
158
- caretInfoRef.current = handleNumoraOnKeyDown(e, formattingOptions);
159
- if (onKeyDown) {
160
- onKeyDown(e);
161
- }
162
- };
163
- const handleBlur = e => {
164
- const {
165
- value,
166
- rawValue
167
- } = handleNumoraOnBlur(e, {
168
- decimalMaxLength: maxDecimals,
169
- formattingOptions
170
- });
171
- if (controlledValue === undefined) {
172
- setInternalValue(value);
173
- } else {
174
- setInternalValue(value);
175
- }
176
- if (onBlur) {
177
- onBlur(e);
178
- }
179
- if (rawValue && e.target && rawValueMode) {
180
- e.target.setAttribute('data-raw-value', rawValue);
181
- }
182
- };
183
- return jsxRuntime.jsx("input", {
184
- ...rest,
185
- ref: inputRef,
186
- value: internalValue,
187
- onChange: handleChange,
188
- onPaste: handlePaste,
189
- onKeyDown: handleKeyDown,
190
- onBlur: handleBlur,
191
- type: "text",
192
- inputMode: "decimal"
193
- });
77
+ const formatValueWithCore = (value) => {
78
+ const el = inputRef.current ?? document.createElement('input');
79
+ el.value = value;
80
+ const fakeEvent = { target: el };
81
+ numora.handleOnChangeNumoraInput(fakeEvent, maxDecimals, undefined, formattingOptions);
82
+ return el.value;
83
+ };
84
+ // When controlled value changes, normalize/format it for display
85
+ react.useEffect(() => {
86
+ if (controlledValue !== undefined) {
87
+ const formatted = formatValueWithCore(String(controlledValue));
88
+ setInternalValue(formatted);
89
+ }
90
+ }, [controlledValue, formatOn, thousandSeparator, thousandStyle, decimalSeparator, decimalMinLength, enableCompactNotation, enableNegative, enableLeadingZeros, rawValueMode, maxDecimals]);
91
+ const handleChange = (e) => {
92
+ const { value, rawValue } = handleNumoraOnChange(e, {
93
+ decimalMaxLength: maxDecimals,
94
+ caretPositionBeforeChange: caretInfoRef.current,
95
+ formattingOptions,
96
+ });
97
+ caretInfoRef.current = undefined;
98
+ if (controlledValue === undefined) {
99
+ setInternalValue(value);
100
+ }
101
+ else {
102
+ setInternalValue(value);
103
+ }
104
+ if (onChange) {
105
+ onChange(e);
106
+ }
107
+ // Optionally expose rawValue via a custom event attribute if needed later
108
+ if (rawValue && e.target && rawValueMode) {
109
+ // Keep the raw value on the input for consumers that read it directly
110
+ e.target.setAttribute('data-raw-value', rawValue);
111
+ }
112
+ };
113
+ const handlePaste = (e) => {
114
+ const { value, rawValue } = handleNumoraOnPaste(e, {
115
+ decimalMaxLength: maxDecimals,
116
+ formattingOptions,
117
+ });
118
+ if (controlledValue === undefined) {
119
+ setInternalValue(value);
120
+ }
121
+ else {
122
+ setInternalValue(value);
123
+ }
124
+ if (onPaste) {
125
+ onPaste(e);
126
+ }
127
+ if (onChange) {
128
+ onChange(e);
129
+ }
130
+ if (rawValue && e.target && rawValueMode) {
131
+ e.target.setAttribute('data-raw-value', rawValue);
132
+ }
133
+ };
134
+ const handleKeyDown = (e) => {
135
+ caretInfoRef.current = handleNumoraOnKeyDown(e, formattingOptions);
136
+ if (onKeyDown) {
137
+ onKeyDown(e);
138
+ }
139
+ };
140
+ const handleBlur = (e) => {
141
+ const { value, rawValue } = handleNumoraOnBlur(e, {
142
+ decimalMaxLength: maxDecimals,
143
+ formattingOptions,
144
+ });
145
+ if (controlledValue === undefined) {
146
+ setInternalValue(value);
147
+ }
148
+ else {
149
+ setInternalValue(value);
150
+ }
151
+ if (onBlur) {
152
+ onBlur(e);
153
+ }
154
+ if (rawValue && e.target && rawValueMode) {
155
+ e.target.setAttribute('data-raw-value', rawValue);
156
+ }
157
+ };
158
+ return (jsxRuntime.jsx("input", { ...rest, ref: inputRef, value: internalValue, onChange: handleChange, onPaste: handlePaste, onKeyDown: handleKeyDown, onBlur: handleBlur, type: "text", inputMode: "decimal" }));
194
159
  });
195
160
  NumoraInput.displayName = 'NumoraInput';
196
161
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../src/handlers.ts","../src/index.tsx"],"sourcesContent":["import type React from 'react';\nimport {\n handleOnChangeNumoraInput,\n handleOnKeyDownNumoraInput,\n handleOnPasteNumoraInput,\n type CaretPositionInfo,\n type FormattingOptions,\n FormatOn,\n} from 'numora';\n\ntype ChangeResult = {\n value: string;\n rawValue?: string;\n};\n\ntype PasteResult = ChangeResult;\ntype BlurResult = ChangeResult;\n\ntype BaseOptions = {\n decimalMaxLength: number;\n caretPositionBeforeChange?: CaretPositionInfo;\n formattingOptions: FormattingOptions & { rawValueMode?: boolean };\n};\n\nexport function handleNumoraOnChange(\n e: React.ChangeEvent<HTMLInputElement>,\n options: BaseOptions\n): ChangeResult {\n handleOnChangeNumoraInput(\n e.nativeEvent as unknown as Event,\n options.decimalMaxLength,\n options.caretPositionBeforeChange,\n options.formattingOptions\n );\n\n const target = e.target;\n const rawValue = target.getAttribute('data-raw-value') ?? undefined;\n if (rawValue) {\n target.removeAttribute('data-raw-value');\n }\n\n return {\n value: target.value,\n rawValue,\n };\n}\n\nexport function handleNumoraOnPaste(\n e: React.ClipboardEvent<HTMLInputElement>,\n options: Omit<BaseOptions, 'caretPositionBeforeChange'>\n): PasteResult {\n const value = handleOnPasteNumoraInput(\n e.nativeEvent as ClipboardEvent,\n options.decimalMaxLength,\n options.formattingOptions\n );\n\n const target = e.target as HTMLInputElement;\n const rawValue = target.getAttribute('data-raw-value') ?? undefined;\n if (rawValue) {\n target.removeAttribute('data-raw-value');\n }\n\n return {\n value,\n rawValue,\n };\n}\n\nexport function handleNumoraOnKeyDown(\n e: React.KeyboardEvent<HTMLInputElement>,\n formattingOptions: FormattingOptions\n): CaretPositionInfo | undefined {\n return handleOnKeyDownNumoraInput(\n e.nativeEvent as unknown as KeyboardEvent,\n formattingOptions\n );\n}\n\nexport function handleNumoraOnBlur(\n e: React.FocusEvent<HTMLInputElement>,\n options: {\n decimalMaxLength: number;\n formattingOptions: FormattingOptions & { rawValueMode?: boolean };\n }\n): BlurResult {\n // If formatOn is blur, force formatting on blur by invoking change handler logic\n if (options.formattingOptions.formatOn === FormatOn.Blur) {\n handleOnChangeNumoraInput(\n e.nativeEvent as unknown as Event,\n options.decimalMaxLength,\n undefined,\n { ...options.formattingOptions, formatOn: FormatOn.Change }\n );\n }\n\n const target = e.target;\n const rawValue = target.getAttribute('data-raw-value') ?? undefined;\n if (rawValue) {\n target.removeAttribute('data-raw-value');\n }\n\n return {\n value: target.value,\n rawValue,\n };\n}\n","import React, {\n useRef,\n useState,\n useEffect,\n forwardRef,\n useImperativeHandle,\n} from 'react';\nimport {\n FormatOn,\n ThousandStyle,\n type CaretPositionInfo,\n type FormattingOptions,\n handleOnChangeNumoraInput,\n} from 'numora';\nimport {\n handleNumoraOnBlur,\n handleNumoraOnChange,\n handleNumoraOnKeyDown,\n handleNumoraOnPaste,\n} from './handlers';\n\ninterface NumoraInputProps\n extends Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n 'onChange' | 'type' | 'inputMode'\n > {\n maxDecimals?: number;\n onChange?: (e: React.ChangeEvent<HTMLInputElement> | React.ClipboardEvent<HTMLInputElement>) => void;\n\n formatOn?: FormatOn;\n thousandSeparator?: string;\n thousandStyle?: ThousandStyle;\n decimalSeparator?: string;\n decimalMinLength?: number;\n\n enableCompactNotation?: boolean;\n enableNegative?: boolean;\n enableLeadingZeros?: boolean;\n rawValueMode?: boolean;\n}\n\nconst NumoraInput = forwardRef<HTMLInputElement, NumoraInputProps>((props, ref) => {\n const {\n maxDecimals = 2,\n onChange,\n onPaste,\n onBlur,\n onKeyDown,\n formatOn = FormatOn.Blur,\n thousandSeparator = ',',\n thousandStyle = ThousandStyle.Thousand,\n decimalSeparator = '.',\n decimalMinLength,\n enableCompactNotation = false,\n enableNegative = false,\n enableLeadingZeros = false,\n rawValueMode = false,\n value: controlledValue,\n defaultValue,\n ...rest\n } = props;\n\n const inputRef = useRef<HTMLInputElement>(null);\n const caretInfoRef = useRef<CaretPositionInfo | undefined>(undefined);\n\n const [internalValue, setInternalValue] = useState<string>(\n controlledValue !== undefined\n ? String(controlledValue)\n : defaultValue !== undefined\n ? String(defaultValue)\n : ''\n );\n\n // Keep internal state in sync when controlled\n useEffect(() => {\n if (controlledValue !== undefined) {\n setInternalValue(String(controlledValue));\n }\n }, [controlledValue]);\n\n useImperativeHandle(ref, () => inputRef.current as HTMLInputElement, []);\n\n const formattingOptions: FormattingOptions & { rawValueMode?: boolean } = {\n formatOn,\n thousandSeparator,\n ThousandStyle: thousandStyle,\n decimalSeparator,\n decimalMinLength,\n enableCompactNotation,\n enableNegative,\n enableLeadingZeros,\n rawValueMode,\n };\n\n const formatValueWithCore = (value: string): string => {\n const el = inputRef.current ?? document.createElement('input');\n el.value = value;\n const fakeEvent = { target: el } as unknown as Event;\n handleOnChangeNumoraInput(fakeEvent, maxDecimals, undefined, formattingOptions);\n return el.value;\n };\n\n // When controlled value changes, normalize/format it for display\n useEffect(() => {\n if (controlledValue !== undefined) {\n const formatted = formatValueWithCore(String(controlledValue));\n setInternalValue(formatted);\n }\n }, [controlledValue, formatOn, thousandSeparator, thousandStyle, decimalSeparator, decimalMinLength, enableCompactNotation, enableNegative, enableLeadingZeros, rawValueMode, maxDecimals]);\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const { value, rawValue } = handleNumoraOnChange(e, {\n decimalMaxLength: maxDecimals,\n caretPositionBeforeChange: caretInfoRef.current,\n formattingOptions,\n });\n caretInfoRef.current = undefined;\n\n if (controlledValue === undefined) {\n setInternalValue(value);\n } else {\n setInternalValue(value);\n }\n\n if (onChange) {\n onChange(e);\n }\n\n // Optionally expose rawValue via a custom event attribute if needed later\n if (rawValue && e.target && rawValueMode) {\n // Keep the raw value on the input for consumers that read it directly\n e.target.setAttribute('data-raw-value', rawValue);\n }\n };\n\n const handlePaste = (e: React.ClipboardEvent<HTMLInputElement>) => {\n const { value, rawValue } = handleNumoraOnPaste(e, {\n decimalMaxLength: maxDecimals,\n formattingOptions,\n });\n\n if (controlledValue === undefined) {\n setInternalValue(value);\n } else {\n setInternalValue(value);\n }\n\n if (onPaste) {\n onPaste(e);\n }\n if (onChange) {\n onChange(e);\n }\n\n if (rawValue && e.target && rawValueMode) {\n (e.target as HTMLInputElement).setAttribute('data-raw-value', rawValue);\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n caretInfoRef.current = handleNumoraOnKeyDown(e, formattingOptions);\n if (onKeyDown) {\n onKeyDown(e);\n }\n };\n\n const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {\n const { value, rawValue } = handleNumoraOnBlur(e, {\n decimalMaxLength: maxDecimals,\n formattingOptions,\n });\n\n if (controlledValue === undefined) {\n setInternalValue(value);\n } else {\n setInternalValue(value);\n }\n\n if (onBlur) {\n onBlur(e);\n }\n\n if (rawValue && e.target && rawValueMode) {\n (e.target as HTMLInputElement).setAttribute('data-raw-value', rawValue);\n }\n };\n\n return (\n <input\n {...rest}\n ref={inputRef}\n value={internalValue}\n onChange={handleChange}\n onPaste={handlePaste}\n onKeyDown={handleKeyDown}\n onBlur={handleBlur}\n type=\"text\"\n inputMode=\"decimal\"\n />\n );\n});\n\nNumoraInput.displayName = 'NumoraInput';\n\nexport { NumoraInput };\nexport { FormatOn, ThousandStyle } from 'numora';\nexport type { FormattingOptions, CaretPositionInfo } from 'numora';\n"],"names":["handleNumoraOnChange","e","options","handleOnChangeNumoraInput","nativeEvent","decimalMaxLength","caretPositionBeforeChange","formattingOptions","target","rawValue","getAttribute","undefined","removeAttribute","value","handleNumoraOnPaste","handleOnPasteNumoraInput","handleNumoraOnKeyDown","handleOnKeyDownNumoraInput","handleNumoraOnBlur","formatOn","FormatOn","Blur","Change","NumoraInput","forwardRef","props","ref","maxDecimals","onChange","onPaste","onBlur","onKeyDown","thousandSeparator","thousandStyle","ThousandStyle","Thousand","decimalSeparator","decimalMinLength","enableCompactNotation","enableNegative","enableLeadingZeros","rawValueMode","controlledValue","defaultValue","rest","inputRef","useRef","caretInfoRef","internalValue","setInternalValue","useState","String","useEffect","useImperativeHandle","current","formatValueWithCore","el","document","createElement","fakeEvent","formatted","handleChange","setAttribute","handlePaste","handleKeyDown","handleBlur","_jsx","type","inputMode","displayName"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/handlers.ts","../src/index.tsx"],"sourcesContent":["import type React from 'react';\nimport {\n handleOnChangeNumoraInput,\n handleOnKeyDownNumoraInput,\n handleOnPasteNumoraInput,\n type CaretPositionInfo,\n type FormattingOptions,\n FormatOn,\n} from 'numora';\n\ntype ChangeResult = {\n value: string;\n rawValue?: string;\n};\n\ntype PasteResult = ChangeResult;\ntype BlurResult = ChangeResult;\n\ntype BaseOptions = {\n decimalMaxLength: number;\n caretPositionBeforeChange?: CaretPositionInfo;\n formattingOptions: FormattingOptions & { rawValueMode?: boolean };\n};\n\nexport function handleNumoraOnChange(\n e: React.ChangeEvent<HTMLInputElement>,\n options: BaseOptions\n): ChangeResult {\n handleOnChangeNumoraInput(\n e.nativeEvent as unknown as Event,\n options.decimalMaxLength,\n options.caretPositionBeforeChange,\n options.formattingOptions\n );\n\n const target = e.target;\n const rawValue = target.getAttribute('data-raw-value') ?? undefined;\n if (rawValue) {\n target.removeAttribute('data-raw-value');\n }\n\n return {\n value: target.value,\n rawValue,\n };\n}\n\nexport function handleNumoraOnPaste(\n e: React.ClipboardEvent<HTMLInputElement>,\n options: Omit<BaseOptions, 'caretPositionBeforeChange'>\n): PasteResult {\n const value = handleOnPasteNumoraInput(\n e.nativeEvent as ClipboardEvent,\n options.decimalMaxLength,\n options.formattingOptions\n );\n\n const target = e.target as HTMLInputElement;\n const rawValue = target.getAttribute('data-raw-value') ?? undefined;\n if (rawValue) {\n target.removeAttribute('data-raw-value');\n }\n\n return {\n value,\n rawValue,\n };\n}\n\nexport function handleNumoraOnKeyDown(\n e: React.KeyboardEvent<HTMLInputElement>,\n formattingOptions: FormattingOptions\n): CaretPositionInfo | undefined {\n return handleOnKeyDownNumoraInput(\n e.nativeEvent as unknown as KeyboardEvent,\n formattingOptions\n );\n}\n\nexport function handleNumoraOnBlur(\n e: React.FocusEvent<HTMLInputElement>,\n options: {\n decimalMaxLength: number;\n formattingOptions: FormattingOptions & { rawValueMode?: boolean };\n }\n): BlurResult {\n // If formatOn is blur, force formatting on blur by invoking change handler logic\n if (options.formattingOptions.formatOn === FormatOn.Blur) {\n handleOnChangeNumoraInput(\n e.nativeEvent as unknown as Event,\n options.decimalMaxLength,\n undefined,\n { ...options.formattingOptions, formatOn: FormatOn.Change }\n );\n }\n\n const target = e.target;\n const rawValue = target.getAttribute('data-raw-value') ?? undefined;\n if (rawValue) {\n target.removeAttribute('data-raw-value');\n }\n\n return {\n value: target.value,\n rawValue,\n };\n}\n","import React, {\n useRef,\n useState,\n useEffect,\n forwardRef,\n useImperativeHandle,\n} from 'react';\nimport {\n FormatOn,\n ThousandStyle,\n type CaretPositionInfo,\n type FormattingOptions,\n handleOnChangeNumoraInput,\n} from 'numora';\nimport {\n handleNumoraOnBlur,\n handleNumoraOnChange,\n handleNumoraOnKeyDown,\n handleNumoraOnPaste,\n} from './handlers';\n\ninterface NumoraInputProps\n extends Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n 'onChange' | 'type' | 'inputMode'\n > {\n maxDecimals?: number;\n onChange?: (e: React.ChangeEvent<HTMLInputElement> | React.ClipboardEvent<HTMLInputElement>) => void;\n\n formatOn?: FormatOn;\n thousandSeparator?: string;\n thousandStyle?: ThousandStyle;\n decimalSeparator?: string;\n decimalMinLength?: number;\n\n enableCompactNotation?: boolean;\n enableNegative?: boolean;\n enableLeadingZeros?: boolean;\n rawValueMode?: boolean;\n}\n\nconst NumoraInput = forwardRef<HTMLInputElement, NumoraInputProps>((props, ref) => {\n const {\n maxDecimals = 2,\n onChange,\n onPaste,\n onBlur,\n onKeyDown,\n formatOn = FormatOn.Blur,\n thousandSeparator = ',',\n thousandStyle = ThousandStyle.Thousand,\n decimalSeparator = '.',\n decimalMinLength,\n enableCompactNotation = false,\n enableNegative = false,\n enableLeadingZeros = false,\n rawValueMode = false,\n value: controlledValue,\n defaultValue,\n ...rest\n } = props;\n\n const inputRef = useRef<HTMLInputElement>(null);\n const caretInfoRef = useRef<CaretPositionInfo | undefined>(undefined);\n\n const [internalValue, setInternalValue] = useState<string>(\n controlledValue !== undefined\n ? String(controlledValue)\n : defaultValue !== undefined\n ? String(defaultValue)\n : ''\n );\n\n // Keep internal state in sync when controlled\n useEffect(() => {\n if (controlledValue !== undefined) {\n setInternalValue(String(controlledValue));\n }\n }, [controlledValue]);\n\n useImperativeHandle(ref, () => inputRef.current as HTMLInputElement, []);\n\n const formattingOptions: FormattingOptions & { rawValueMode?: boolean } = {\n formatOn,\n thousandSeparator,\n ThousandStyle: thousandStyle,\n decimalSeparator,\n decimalMinLength,\n enableCompactNotation,\n enableNegative,\n enableLeadingZeros,\n rawValueMode,\n };\n\n const formatValueWithCore = (value: string): string => {\n const el = inputRef.current ?? document.createElement('input');\n el.value = value;\n const fakeEvent = { target: el } as unknown as Event;\n handleOnChangeNumoraInput(fakeEvent, maxDecimals, undefined, formattingOptions);\n return el.value;\n };\n\n // When controlled value changes, normalize/format it for display\n useEffect(() => {\n if (controlledValue !== undefined) {\n const formatted = formatValueWithCore(String(controlledValue));\n setInternalValue(formatted);\n }\n }, [controlledValue, formatOn, thousandSeparator, thousandStyle, decimalSeparator, decimalMinLength, enableCompactNotation, enableNegative, enableLeadingZeros, rawValueMode, maxDecimals]);\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const { value, rawValue } = handleNumoraOnChange(e, {\n decimalMaxLength: maxDecimals,\n caretPositionBeforeChange: caretInfoRef.current,\n formattingOptions,\n });\n caretInfoRef.current = undefined;\n\n if (controlledValue === undefined) {\n setInternalValue(value);\n } else {\n setInternalValue(value);\n }\n\n if (onChange) {\n onChange(e);\n }\n\n // Optionally expose rawValue via a custom event attribute if needed later\n if (rawValue && e.target && rawValueMode) {\n // Keep the raw value on the input for consumers that read it directly\n e.target.setAttribute('data-raw-value', rawValue);\n }\n };\n\n const handlePaste = (e: React.ClipboardEvent<HTMLInputElement>) => {\n const { value, rawValue } = handleNumoraOnPaste(e, {\n decimalMaxLength: maxDecimals,\n formattingOptions,\n });\n\n if (controlledValue === undefined) {\n setInternalValue(value);\n } else {\n setInternalValue(value);\n }\n\n if (onPaste) {\n onPaste(e);\n }\n if (onChange) {\n onChange(e);\n }\n\n if (rawValue && e.target && rawValueMode) {\n (e.target as HTMLInputElement).setAttribute('data-raw-value', rawValue);\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n caretInfoRef.current = handleNumoraOnKeyDown(e, formattingOptions);\n if (onKeyDown) {\n onKeyDown(e);\n }\n };\n\n const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {\n const { value, rawValue } = handleNumoraOnBlur(e, {\n decimalMaxLength: maxDecimals,\n formattingOptions,\n });\n\n if (controlledValue === undefined) {\n setInternalValue(value);\n } else {\n setInternalValue(value);\n }\n\n if (onBlur) {\n onBlur(e);\n }\n\n if (rawValue && e.target && rawValueMode) {\n (e.target as HTMLInputElement).setAttribute('data-raw-value', rawValue);\n }\n };\n\n return (\n <input\n {...rest}\n ref={inputRef}\n value={internalValue}\n onChange={handleChange}\n onPaste={handlePaste}\n onKeyDown={handleKeyDown}\n onBlur={handleBlur}\n type=\"text\"\n inputMode=\"decimal\"\n />\n );\n});\n\nNumoraInput.displayName = 'NumoraInput';\n\nexport { NumoraInput };\nexport { FormatOn, ThousandStyle } from 'numora';\nexport type { FormattingOptions, CaretPositionInfo } from 'numora';\n"],"names":["handleOnChangeNumoraInput","handleOnPasteNumoraInput","handleOnKeyDownNumoraInput","FormatOn","forwardRef","ThousandStyle","useRef","useState","useEffect","useImperativeHandle","_jsx"],"mappings":";;;;;;AAwBM,SAAU,oBAAoB,CAClC,CAAsC,EACtC,OAAoB,EAAA;AAEpB,IAAAA,gCAAyB,CACvB,CAAC,CAAC,WAA+B,EACjC,OAAO,CAAC,gBAAgB,EACxB,OAAO,CAAC,yBAAyB,EACjC,OAAO,CAAC,iBAAiB,CAC1B;AAED,IAAA,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM;IACvB,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,gBAAgB,CAAC,IAAI,SAAS;IACnE,IAAI,QAAQ,EAAE;AACZ,QAAA,MAAM,CAAC,eAAe,CAAC,gBAAgB,CAAC;IAC1C;IAEA,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,QAAQ;KACT;AACH;AAEM,SAAU,mBAAmB,CACjC,CAAyC,EACzC,OAAuD,EAAA;AAEvD,IAAA,MAAM,KAAK,GAAGC,+BAAwB,CACpC,CAAC,CAAC,WAA6B,EAC/B,OAAO,CAAC,gBAAgB,EACxB,OAAO,CAAC,iBAAiB,CAC1B;AAED,IAAA,MAAM,MAAM,GAAG,CAAC,CAAC,MAA0B;IAC3C,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,gBAAgB,CAAC,IAAI,SAAS;IACnE,IAAI,QAAQ,EAAE;AACZ,QAAA,MAAM,CAAC,eAAe,CAAC,gBAAgB,CAAC;IAC1C;IAEA,OAAO;QACL,KAAK;QACL,QAAQ;KACT;AACH;AAEM,SAAU,qBAAqB,CACnC,CAAwC,EACxC,iBAAoC,EAAA;IAEpC,OAAOC,iCAA0B,CAC/B,CAAC,CAAC,WAAuC,EACzC,iBAAiB,CAClB;AACH;AAEM,SAAU,kBAAkB,CAChC,CAAqC,EACrC,OAGC,EAAA;;IAGD,IAAI,OAAO,CAAC,iBAAiB,CAAC,QAAQ,KAAKC,eAAQ,CAAC,IAAI,EAAE;QACxDH,gCAAyB,CACvB,CAAC,CAAC,WAA+B,EACjC,OAAO,CAAC,gBAAgB,EACxB,SAAS,EACT,EAAE,GAAG,OAAO,CAAC,iBAAiB,EAAE,QAAQ,EAAEG,eAAQ,CAAC,MAAM,EAAE,CAC5D;IACH;AAEA,IAAA,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM;IACvB,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,gBAAgB,CAAC,IAAI,SAAS;IACnE,IAAI,QAAQ,EAAE;AACZ,QAAA,MAAM,CAAC,eAAe,CAAC,gBAAgB,CAAC;IAC1C;IAEA,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,QAAQ;KACT;AACH;;ACjEA,MAAM,WAAW,GAAGC,gBAAU,CAAqC,CAAC,KAAK,EAAE,GAAG,KAAI;AAChF,IAAA,MAAM,EACJ,WAAW,GAAG,CAAC,EACf,QAAQ,EACR,OAAO,EACP,MAAM,EACN,SAAS,EACT,QAAQ,GAAGD,eAAQ,CAAC,IAAI,EACxB,iBAAiB,GAAG,GAAG,EACvB,aAAa,GAAGE,oBAAa,CAAC,QAAQ,EACtC,gBAAgB,GAAG,GAAG,EACtB,gBAAgB,EAChB,qBAAqB,GAAG,KAAK,EAC7B,cAAc,GAAG,KAAK,EACtB,kBAAkB,GAAG,KAAK,EAC1B,YAAY,GAAG,KAAK,EACpB,KAAK,EAAE,eAAe,EACtB,YAAY,EACZ,GAAG,IAAI,EACR,GAAG,KAAK;AAET,IAAA,MAAM,QAAQ,GAAGC,YAAM,CAAmB,IAAI,CAAC;AAC/C,IAAA,MAAM,YAAY,GAAGA,YAAM,CAAgC,SAAS,CAAC;IAErE,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAGC,cAAQ,CAChD,eAAe,KAAK;AAClB,UAAE,MAAM,CAAC,eAAe;UACtB,YAAY,KAAK;AACjB,cAAE,MAAM,CAAC,YAAY;cACnB,EAAE,CACT;;IAGDC,eAAS,CAAC,MAAK;AACb,QAAA,IAAI,eAAe,KAAK,SAAS,EAAE;AACjC,YAAA,gBAAgB,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QAC3C;AACF,IAAA,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC;AAErB,IAAAC,yBAAmB,CAAC,GAAG,EAAE,MAAM,QAAQ,CAAC,OAA2B,EAAE,EAAE,CAAC;AAExE,IAAA,MAAM,iBAAiB,GAAmD;QACxE,QAAQ;QACR,iBAAiB;AACjB,QAAA,aAAa,EAAE,aAAa;QAC5B,gBAAgB;QAChB,gBAAgB;QAChB,qBAAqB;QACrB,cAAc;QACd,kBAAkB;QAClB,YAAY;KACb;AAED,IAAA,MAAM,mBAAmB,GAAG,CAAC,KAAa,KAAY;AACpD,QAAA,MAAM,EAAE,GAAG,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC;AAC9D,QAAA,EAAE,CAAC,KAAK,GAAG,KAAK;AAChB,QAAA,MAAM,SAAS,GAAG,EAAE,MAAM,EAAE,EAAE,EAAsB;QACpDT,gCAAyB,CAAC,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,iBAAiB,CAAC;QAC/E,OAAO,EAAE,CAAC,KAAK;AACjB,IAAA,CAAC;;IAGDQ,eAAS,CAAC,MAAK;AACb,QAAA,IAAI,eAAe,KAAK,SAAS,EAAE;YACjC,MAAM,SAAS,GAAG,mBAAmB,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;YAC9D,gBAAgB,CAAC,SAAS,CAAC;QAC7B;IACF,CAAC,EAAE,CAAC,eAAe,EAAE,QAAQ,EAAE,iBAAiB,EAAE,aAAa,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,cAAc,EAAE,kBAAkB,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;AAE3L,IAAA,MAAM,YAAY,GAAG,CAAC,CAAsC,KAAI;QAC9D,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,oBAAoB,CAAC,CAAC,EAAE;AAClD,YAAA,gBAAgB,EAAE,WAAW;YAC7B,yBAAyB,EAAE,YAAY,CAAC,OAAO;YAC/C,iBAAiB;AAClB,SAAA,CAAC;AACF,QAAA,YAAY,CAAC,OAAO,GAAG,SAAS;AAEhC,QAAA,IAAI,eAAe,KAAK,SAAS,EAAE;YACjC,gBAAgB,CAAC,KAAK,CAAC;QACzB;aAAO;YACL,gBAAgB,CAAC,KAAK,CAAC;QACzB;QAEA,IAAI,QAAQ,EAAE;YACZ,QAAQ,CAAC,CAAC,CAAC;QACb;;QAGA,IAAI,QAAQ,IAAI,CAAC,CAAC,MAAM,IAAI,YAAY,EAAE;;YAExC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,gBAAgB,EAAE,QAAQ,CAAC;QACnD;AACF,IAAA,CAAC;AAED,IAAA,MAAM,WAAW,GAAG,CAAC,CAAyC,KAAI;QAChE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,mBAAmB,CAAC,CAAC,EAAE;AACjD,YAAA,gBAAgB,EAAE,WAAW;YAC7B,iBAAiB;AAClB,SAAA,CAAC;AAEF,QAAA,IAAI,eAAe,KAAK,SAAS,EAAE;YACjC,gBAAgB,CAAC,KAAK,CAAC;QACzB;aAAO;YACL,gBAAgB,CAAC,KAAK,CAAC;QACzB;QAEA,IAAI,OAAO,EAAE;YACX,OAAO,CAAC,CAAC,CAAC;QACZ;QACA,IAAI,QAAQ,EAAE;YACZ,QAAQ,CAAC,CAAC,CAAC;QACb;QAEA,IAAI,QAAQ,IAAI,CAAC,CAAC,MAAM,IAAI,YAAY,EAAE;YACvC,CAAC,CAAC,MAA2B,CAAC,YAAY,CAAC,gBAAgB,EAAE,QAAQ,CAAC;QACzE;AACF,IAAA,CAAC;AAED,IAAA,MAAM,aAAa,GAAG,CAAC,CAAwC,KAAI;QACjE,YAAY,CAAC,OAAO,GAAG,qBAAqB,CAAC,CAAC,EAAE,iBAAiB,CAAC;QAClE,IAAI,SAAS,EAAE;YACb,SAAS,CAAC,CAAC,CAAC;QACd;AACF,IAAA,CAAC;AAED,IAAA,MAAM,UAAU,GAAG,CAAC,CAAqC,KAAI;QAC3D,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,kBAAkB,CAAC,CAAC,EAAE;AAChD,YAAA,gBAAgB,EAAE,WAAW;YAC7B,iBAAiB;AAClB,SAAA,CAAC;AAEF,QAAA,IAAI,eAAe,KAAK,SAAS,EAAE;YACjC,gBAAgB,CAAC,KAAK,CAAC;QACzB;aAAO;YACL,gBAAgB,CAAC,KAAK,CAAC;QACzB;QAEA,IAAI,MAAM,EAAE;YACV,MAAM,CAAC,CAAC,CAAC;QACX;QAEA,IAAI,QAAQ,IAAI,CAAC,CAAC,MAAM,IAAI,YAAY,EAAE;YACvC,CAAC,CAAC,MAA2B,CAAC,YAAY,CAAC,gBAAgB,EAAE,QAAQ,CAAC;QACzE;AACF,IAAA,CAAC;AAED,IAAA,QACEE,cAAA,CAAA,OAAA,EAAA,EAAA,GACM,IAAI,EACR,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,aAAa,EACpB,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,aAAa,EACxB,MAAM,EAAE,UAAU,EAClB,IAAI,EAAC,MAAM,EACX,SAAS,EAAC,SAAS,EAAA,CACnB;AAEN,CAAC;AAED,WAAW,CAAC,WAAW,GAAG,aAAa;;;;;;;;;;;;"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/handlers.ts","../src/index.tsx"],"sourcesContent":["import type React from 'react';\nimport {\n handleOnChangeNumoraInput,\n handleOnKeyDownNumoraInput,\n handleOnPasteNumoraInput,\n type CaretPositionInfo,\n type FormattingOptions,\n FormatOn,\n} from 'numora';\n\ntype ChangeResult = {\n value: string;\n rawValue?: string;\n};\n\ntype PasteResult = ChangeResult;\ntype BlurResult = ChangeResult;\n\ntype BaseOptions = {\n decimalMaxLength: number;\n caretPositionBeforeChange?: CaretPositionInfo;\n formattingOptions: FormattingOptions & { rawValueMode?: boolean };\n};\n\nexport function handleNumoraOnChange(\n e: React.ChangeEvent<HTMLInputElement>,\n options: BaseOptions\n): ChangeResult {\n handleOnChangeNumoraInput(\n e.nativeEvent as unknown as Event,\n options.decimalMaxLength,\n options.caretPositionBeforeChange,\n options.formattingOptions\n );\n\n const target = e.target;\n const rawValue = target.getAttribute('data-raw-value') ?? undefined;\n if (rawValue) {\n target.removeAttribute('data-raw-value');\n }\n\n return {\n value: target.value,\n rawValue,\n };\n}\n\nexport function handleNumoraOnPaste(\n e: React.ClipboardEvent<HTMLInputElement>,\n options: Omit<BaseOptions, 'caretPositionBeforeChange'>\n): PasteResult {\n const value = handleOnPasteNumoraInput(\n e.nativeEvent as ClipboardEvent,\n options.decimalMaxLength,\n options.formattingOptions\n );\n\n const target = e.target as HTMLInputElement;\n const rawValue = target.getAttribute('data-raw-value') ?? undefined;\n if (rawValue) {\n target.removeAttribute('data-raw-value');\n }\n\n return {\n value,\n rawValue,\n };\n}\n\nexport function handleNumoraOnKeyDown(\n e: React.KeyboardEvent<HTMLInputElement>,\n formattingOptions: FormattingOptions\n): CaretPositionInfo | undefined {\n return handleOnKeyDownNumoraInput(\n e.nativeEvent as unknown as KeyboardEvent,\n formattingOptions\n );\n}\n\nexport function handleNumoraOnBlur(\n e: React.FocusEvent<HTMLInputElement>,\n options: {\n decimalMaxLength: number;\n formattingOptions: FormattingOptions & { rawValueMode?: boolean };\n }\n): BlurResult {\n // If formatOn is blur, force formatting on blur by invoking change handler logic\n if (options.formattingOptions.formatOn === FormatOn.Blur) {\n handleOnChangeNumoraInput(\n e.nativeEvent as unknown as Event,\n options.decimalMaxLength,\n undefined,\n { ...options.formattingOptions, formatOn: FormatOn.Change }\n );\n }\n\n const target = e.target;\n const rawValue = target.getAttribute('data-raw-value') ?? undefined;\n if (rawValue) {\n target.removeAttribute('data-raw-value');\n }\n\n return {\n value: target.value,\n rawValue,\n };\n}\n","import React, {\n useRef,\n useState,\n useEffect,\n forwardRef,\n useImperativeHandle,\n} from 'react';\nimport {\n FormatOn,\n ThousandStyle,\n type CaretPositionInfo,\n type FormattingOptions,\n handleOnChangeNumoraInput,\n} from 'numora';\nimport {\n handleNumoraOnBlur,\n handleNumoraOnChange,\n handleNumoraOnKeyDown,\n handleNumoraOnPaste,\n} from './handlers';\n\ninterface NumoraInputProps\n extends Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n 'onChange' | 'type' | 'inputMode'\n > {\n maxDecimals?: number;\n onChange?: (e: React.ChangeEvent<HTMLInputElement> | React.ClipboardEvent<HTMLInputElement>) => void;\n\n formatOn?: FormatOn;\n thousandSeparator?: string;\n thousandStyle?: ThousandStyle;\n decimalSeparator?: string;\n decimalMinLength?: number;\n\n enableCompactNotation?: boolean;\n enableNegative?: boolean;\n enableLeadingZeros?: boolean;\n rawValueMode?: boolean;\n}\n\nconst NumoraInput = forwardRef<HTMLInputElement, NumoraInputProps>((props, ref) => {\n const {\n maxDecimals = 2,\n onChange,\n onPaste,\n onBlur,\n onKeyDown,\n formatOn = FormatOn.Blur,\n thousandSeparator = ',',\n thousandStyle = ThousandStyle.Thousand,\n decimalSeparator = '.',\n decimalMinLength,\n enableCompactNotation = false,\n enableNegative = false,\n enableLeadingZeros = false,\n rawValueMode = false,\n value: controlledValue,\n defaultValue,\n ...rest\n } = props;\n\n const inputRef = useRef<HTMLInputElement>(null);\n const caretInfoRef = useRef<CaretPositionInfo | undefined>(undefined);\n\n const [internalValue, setInternalValue] = useState<string>(\n controlledValue !== undefined\n ? String(controlledValue)\n : defaultValue !== undefined\n ? String(defaultValue)\n : ''\n );\n\n // Keep internal state in sync when controlled\n useEffect(() => {\n if (controlledValue !== undefined) {\n setInternalValue(String(controlledValue));\n }\n }, [controlledValue]);\n\n useImperativeHandle(ref, () => inputRef.current as HTMLInputElement, []);\n\n const formattingOptions: FormattingOptions & { rawValueMode?: boolean } = {\n formatOn,\n thousandSeparator,\n ThousandStyle: thousandStyle,\n decimalSeparator,\n decimalMinLength,\n enableCompactNotation,\n enableNegative,\n enableLeadingZeros,\n rawValueMode,\n };\n\n const formatValueWithCore = (value: string): string => {\n const el = inputRef.current ?? document.createElement('input');\n el.value = value;\n const fakeEvent = { target: el } as unknown as Event;\n handleOnChangeNumoraInput(fakeEvent, maxDecimals, undefined, formattingOptions);\n return el.value;\n };\n\n // When controlled value changes, normalize/format it for display\n useEffect(() => {\n if (controlledValue !== undefined) {\n const formatted = formatValueWithCore(String(controlledValue));\n setInternalValue(formatted);\n }\n }, [controlledValue, formatOn, thousandSeparator, thousandStyle, decimalSeparator, decimalMinLength, enableCompactNotation, enableNegative, enableLeadingZeros, rawValueMode, maxDecimals]);\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const { value, rawValue } = handleNumoraOnChange(e, {\n decimalMaxLength: maxDecimals,\n caretPositionBeforeChange: caretInfoRef.current,\n formattingOptions,\n });\n caretInfoRef.current = undefined;\n\n if (controlledValue === undefined) {\n setInternalValue(value);\n } else {\n setInternalValue(value);\n }\n\n if (onChange) {\n onChange(e);\n }\n\n // Optionally expose rawValue via a custom event attribute if needed later\n if (rawValue && e.target && rawValueMode) {\n // Keep the raw value on the input for consumers that read it directly\n e.target.setAttribute('data-raw-value', rawValue);\n }\n };\n\n const handlePaste = (e: React.ClipboardEvent<HTMLInputElement>) => {\n const { value, rawValue } = handleNumoraOnPaste(e, {\n decimalMaxLength: maxDecimals,\n formattingOptions,\n });\n\n if (controlledValue === undefined) {\n setInternalValue(value);\n } else {\n setInternalValue(value);\n }\n\n if (onPaste) {\n onPaste(e);\n }\n if (onChange) {\n onChange(e);\n }\n\n if (rawValue && e.target && rawValueMode) {\n (e.target as HTMLInputElement).setAttribute('data-raw-value', rawValue);\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n caretInfoRef.current = handleNumoraOnKeyDown(e, formattingOptions);\n if (onKeyDown) {\n onKeyDown(e);\n }\n };\n\n const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {\n const { value, rawValue } = handleNumoraOnBlur(e, {\n decimalMaxLength: maxDecimals,\n formattingOptions,\n });\n\n if (controlledValue === undefined) {\n setInternalValue(value);\n } else {\n setInternalValue(value);\n }\n\n if (onBlur) {\n onBlur(e);\n }\n\n if (rawValue && e.target && rawValueMode) {\n (e.target as HTMLInputElement).setAttribute('data-raw-value', rawValue);\n }\n };\n\n return (\n <input\n {...rest}\n ref={inputRef}\n value={internalValue}\n onChange={handleChange}\n onPaste={handlePaste}\n onKeyDown={handleKeyDown}\n onBlur={handleBlur}\n type=\"text\"\n inputMode=\"decimal\"\n />\n );\n});\n\nNumoraInput.displayName = 'NumoraInput';\n\nexport { NumoraInput };\nexport { FormatOn, ThousandStyle } from 'numora';\nexport type { FormattingOptions, CaretPositionInfo } from 'numora';\n"],"names":["handleOnChangeNumoraInput","handleOnPasteNumoraInput","handleOnKeyDownNumoraInput","FormatOn","forwardRef","ThousandStyle","useRef","useState","useEffect","useImperativeHandle","_jsx"],"mappings":";;;;;;AAwBM,SAAU,oBAAoB,CAClC,CAAsC,EACtC,OAAoB,EAAA;AAEpB,IAAAA,gCAAyB,CACvB,CAAC,CAAC,WAA+B,EACjC,OAAO,CAAC,gBAAgB,EACxB,OAAO,CAAC,yBAAyB,EACjC,OAAO,CAAC,iBAAiB,CAC1B;AAED,IAAA,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM;IACvB,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,gBAAgB,CAAC,IAAI,SAAS;IACnE,IAAI,QAAQ,EAAE;AACZ,QAAA,MAAM,CAAC,eAAe,CAAC,gBAAgB,CAAC;IAC1C;IAEA,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,QAAQ;KACT;AACH;AAEM,SAAU,mBAAmB,CACjC,CAAyC,EACzC,OAAuD,EAAA;AAEvD,IAAA,MAAM,KAAK,GAAGC,+BAAwB,CACpC,CAAC,CAAC,WAA6B,EAC/B,OAAO,CAAC,gBAAgB,EACxB,OAAO,CAAC,iBAAiB,CAC1B;AAED,IAAA,MAAM,MAAM,GAAG,CAAC,CAAC,MAA0B;IAC3C,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,gBAAgB,CAAC,IAAI,SAAS;IACnE,IAAI,QAAQ,EAAE;AACZ,QAAA,MAAM,CAAC,eAAe,CAAC,gBAAgB,CAAC;IAC1C;IAEA,OAAO;QACL,KAAK;QACL,QAAQ;KACT;AACH;AAEM,SAAU,qBAAqB,CACnC,CAAwC,EACxC,iBAAoC,EAAA;IAEpC,OAAOC,iCAA0B,CAC/B,CAAC,CAAC,WAAuC,EACzC,iBAAiB,CAClB;AACH;AAEM,SAAU,kBAAkB,CAChC,CAAqC,EACrC,OAGC,EAAA;;IAGD,IAAI,OAAO,CAAC,iBAAiB,CAAC,QAAQ,KAAKC,eAAQ,CAAC,IAAI,EAAE;QACxDH,gCAAyB,CACvB,CAAC,CAAC,WAA+B,EACjC,OAAO,CAAC,gBAAgB,EACxB,SAAS,EACT,EAAE,GAAG,OAAO,CAAC,iBAAiB,EAAE,QAAQ,EAAEG,eAAQ,CAAC,MAAM,EAAE,CAC5D;IACH;AAEA,IAAA,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM;IACvB,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,gBAAgB,CAAC,IAAI,SAAS;IACnE,IAAI,QAAQ,EAAE;AACZ,QAAA,MAAM,CAAC,eAAe,CAAC,gBAAgB,CAAC;IAC1C;IAEA,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,QAAQ;KACT;AACH;;ACjEA,MAAM,WAAW,GAAGC,gBAAU,CAAqC,CAAC,KAAK,EAAE,GAAG,KAAI;AAChF,IAAA,MAAM,EACJ,WAAW,GAAG,CAAC,EACf,QAAQ,EACR,OAAO,EACP,MAAM,EACN,SAAS,EACT,QAAQ,GAAGD,eAAQ,CAAC,IAAI,EACxB,iBAAiB,GAAG,GAAG,EACvB,aAAa,GAAGE,oBAAa,CAAC,QAAQ,EACtC,gBAAgB,GAAG,GAAG,EACtB,gBAAgB,EAChB,qBAAqB,GAAG,KAAK,EAC7B,cAAc,GAAG,KAAK,EACtB,kBAAkB,GAAG,KAAK,EAC1B,YAAY,GAAG,KAAK,EACpB,KAAK,EAAE,eAAe,EACtB,YAAY,EACZ,GAAG,IAAI,EACR,GAAG,KAAK;AAET,IAAA,MAAM,QAAQ,GAAGC,YAAM,CAAmB,IAAI,CAAC;AAC/C,IAAA,MAAM,YAAY,GAAGA,YAAM,CAAgC,SAAS,CAAC;IAErE,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAGC,cAAQ,CAChD,eAAe,KAAK;AAClB,UAAE,MAAM,CAAC,eAAe;UACtB,YAAY,KAAK;AACjB,cAAE,MAAM,CAAC,YAAY;cACnB,EAAE,CACT;;IAGDC,eAAS,CAAC,MAAK;AACb,QAAA,IAAI,eAAe,KAAK,SAAS,EAAE;AACjC,YAAA,gBAAgB,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QAC3C;AACF,IAAA,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC;AAErB,IAAAC,yBAAmB,CAAC,GAAG,EAAE,MAAM,QAAQ,CAAC,OAA2B,EAAE,EAAE,CAAC;AAExE,IAAA,MAAM,iBAAiB,GAAmD;QACxE,QAAQ;QACR,iBAAiB;AACjB,QAAA,aAAa,EAAE,aAAa;QAC5B,gBAAgB;QAChB,gBAAgB;QAChB,qBAAqB;QACrB,cAAc;QACd,kBAAkB;QAClB,YAAY;KACb;AAED,IAAA,MAAM,mBAAmB,GAAG,CAAC,KAAa,KAAY;AACpD,QAAA,MAAM,EAAE,GAAG,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC;AAC9D,QAAA,EAAE,CAAC,KAAK,GAAG,KAAK;AAChB,QAAA,MAAM,SAAS,GAAG,EAAE,MAAM,EAAE,EAAE,EAAsB;QACpDT,gCAAyB,CAAC,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,iBAAiB,CAAC;QAC/E,OAAO,EAAE,CAAC,KAAK;AACjB,IAAA,CAAC;;IAGDQ,eAAS,CAAC,MAAK;AACb,QAAA,IAAI,eAAe,KAAK,SAAS,EAAE;YACjC,MAAM,SAAS,GAAG,mBAAmB,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;YAC9D,gBAAgB,CAAC,SAAS,CAAC;QAC7B;IACF,CAAC,EAAE,CAAC,eAAe,EAAE,QAAQ,EAAE,iBAAiB,EAAE,aAAa,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,cAAc,EAAE,kBAAkB,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;AAE3L,IAAA,MAAM,YAAY,GAAG,CAAC,CAAsC,KAAI;QAC9D,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,oBAAoB,CAAC,CAAC,EAAE;AAClD,YAAA,gBAAgB,EAAE,WAAW;YAC7B,yBAAyB,EAAE,YAAY,CAAC,OAAO;YAC/C,iBAAiB;AAClB,SAAA,CAAC;AACF,QAAA,YAAY,CAAC,OAAO,GAAG,SAAS;AAEhC,QAAA,IAAI,eAAe,KAAK,SAAS,EAAE;YACjC,gBAAgB,CAAC,KAAK,CAAC;QACzB;aAAO;YACL,gBAAgB,CAAC,KAAK,CAAC;QACzB;QAEA,IAAI,QAAQ,EAAE;YACZ,QAAQ,CAAC,CAAC,CAAC;QACb;;QAGA,IAAI,QAAQ,IAAI,CAAC,CAAC,MAAM,IAAI,YAAY,EAAE;;YAExC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,gBAAgB,EAAE,QAAQ,CAAC;QACnD;AACF,IAAA,CAAC;AAED,IAAA,MAAM,WAAW,GAAG,CAAC,CAAyC,KAAI;QAChE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,mBAAmB,CAAC,CAAC,EAAE;AACjD,YAAA,gBAAgB,EAAE,WAAW;YAC7B,iBAAiB;AAClB,SAAA,CAAC;AAEF,QAAA,IAAI,eAAe,KAAK,SAAS,EAAE;YACjC,gBAAgB,CAAC,KAAK,CAAC;QACzB;aAAO;YACL,gBAAgB,CAAC,KAAK,CAAC;QACzB;QAEA,IAAI,OAAO,EAAE;YACX,OAAO,CAAC,CAAC,CAAC;QACZ;QACA,IAAI,QAAQ,EAAE;YACZ,QAAQ,CAAC,CAAC,CAAC;QACb;QAEA,IAAI,QAAQ,IAAI,CAAC,CAAC,MAAM,IAAI,YAAY,EAAE;YACvC,CAAC,CAAC,MAA2B,CAAC,YAAY,CAAC,gBAAgB,EAAE,QAAQ,CAAC;QACzE;AACF,IAAA,CAAC;AAED,IAAA,MAAM,aAAa,GAAG,CAAC,CAAwC,KAAI;QACjE,YAAY,CAAC,OAAO,GAAG,qBAAqB,CAAC,CAAC,EAAE,iBAAiB,CAAC;QAClE,IAAI,SAAS,EAAE;YACb,SAAS,CAAC,CAAC,CAAC;QACd;AACF,IAAA,CAAC;AAED,IAAA,MAAM,UAAU,GAAG,CAAC,CAAqC,KAAI;QAC3D,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,kBAAkB,CAAC,CAAC,EAAE;AAChD,YAAA,gBAAgB,EAAE,WAAW;YAC7B,iBAAiB;AAClB,SAAA,CAAC;AAEF,QAAA,IAAI,eAAe,KAAK,SAAS,EAAE;YACjC,gBAAgB,CAAC,KAAK,CAAC;QACzB;aAAO;YACL,gBAAgB,CAAC,KAAK,CAAC;QACzB;QAEA,IAAI,MAAM,EAAE;YACV,MAAM,CAAC,CAAC,CAAC;QACX;QAEA,IAAI,QAAQ,IAAI,CAAC,CAAC,MAAM,IAAI,YAAY,EAAE;YACvC,CAAC,CAAC,MAA2B,CAAC,YAAY,CAAC,gBAAgB,EAAE,QAAQ,CAAC;QACzE;AACF,IAAA,CAAC;AAED,IAAA,QACEE,cAAA,CAAA,OAAA,EAAA,EAAA,GACM,IAAI,EACR,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,aAAa,EACpB,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,aAAa,EACxB,MAAM,EAAE,UAAU,EAClB,IAAI,EAAC,MAAM,EACX,SAAS,EAAC,SAAS,EAAA,CACnB;AAEN,CAAC;AAED,WAAW,CAAC,WAAW,GAAG,aAAa;;;;;;;;;;;;"}
package/dist/index.esm.js CHANGED
@@ -4,192 +4,157 @@ import { FormatOn, handleOnChangeNumoraInput, handleOnKeyDownNumoraInput, handle
4
4
  export { FormatOn, ThousandStyle } from 'numora';
5
5
 
6
6
  function handleNumoraOnChange(e, options) {
7
- handleOnChangeNumoraInput(e.nativeEvent, options.decimalMaxLength, options.caretPositionBeforeChange, options.formattingOptions);
8
- const target = e.target;
9
- const rawValue = target.getAttribute('data-raw-value') ?? undefined;
10
- if (rawValue) {
11
- target.removeAttribute('data-raw-value');
12
- }
13
- return {
14
- value: target.value,
15
- rawValue
16
- };
7
+ handleOnChangeNumoraInput(e.nativeEvent, options.decimalMaxLength, options.caretPositionBeforeChange, options.formattingOptions);
8
+ const target = e.target;
9
+ const rawValue = target.getAttribute('data-raw-value') ?? undefined;
10
+ if (rawValue) {
11
+ target.removeAttribute('data-raw-value');
12
+ }
13
+ return {
14
+ value: target.value,
15
+ rawValue,
16
+ };
17
17
  }
18
18
  function handleNumoraOnPaste(e, options) {
19
- const value = handleOnPasteNumoraInput(e.nativeEvent, options.decimalMaxLength, options.formattingOptions);
20
- const target = e.target;
21
- const rawValue = target.getAttribute('data-raw-value') ?? undefined;
22
- if (rawValue) {
23
- target.removeAttribute('data-raw-value');
24
- }
25
- return {
26
- value,
27
- rawValue
28
- };
19
+ const value = handleOnPasteNumoraInput(e.nativeEvent, options.decimalMaxLength, options.formattingOptions);
20
+ const target = e.target;
21
+ const rawValue = target.getAttribute('data-raw-value') ?? undefined;
22
+ if (rawValue) {
23
+ target.removeAttribute('data-raw-value');
24
+ }
25
+ return {
26
+ value,
27
+ rawValue,
28
+ };
29
29
  }
30
30
  function handleNumoraOnKeyDown(e, formattingOptions) {
31
- return handleOnKeyDownNumoraInput(e.nativeEvent, formattingOptions);
31
+ return handleOnKeyDownNumoraInput(e.nativeEvent, formattingOptions);
32
32
  }
33
33
  function handleNumoraOnBlur(e, options) {
34
- // If formatOn is blur, force formatting on blur by invoking change handler logic
35
- if (options.formattingOptions.formatOn === FormatOn.Blur) {
36
- handleOnChangeNumoraInput(e.nativeEvent, options.decimalMaxLength, undefined, {
37
- ...options.formattingOptions,
38
- formatOn: FormatOn.Change
39
- });
40
- }
41
- const target = e.target;
42
- const rawValue = target.getAttribute('data-raw-value') ?? undefined;
43
- if (rawValue) {
44
- target.removeAttribute('data-raw-value');
45
- }
46
- return {
47
- value: target.value,
48
- rawValue
49
- };
34
+ // If formatOn is blur, force formatting on blur by invoking change handler logic
35
+ if (options.formattingOptions.formatOn === FormatOn.Blur) {
36
+ handleOnChangeNumoraInput(e.nativeEvent, options.decimalMaxLength, undefined, { ...options.formattingOptions, formatOn: FormatOn.Change });
37
+ }
38
+ const target = e.target;
39
+ const rawValue = target.getAttribute('data-raw-value') ?? undefined;
40
+ if (rawValue) {
41
+ target.removeAttribute('data-raw-value');
42
+ }
43
+ return {
44
+ value: target.value,
45
+ rawValue,
46
+ };
50
47
  }
51
48
 
52
- const NumoraInput = /*#__PURE__*/forwardRef((props, ref) => {
53
- const {
54
- maxDecimals = 2,
55
- onChange,
56
- onPaste,
57
- onBlur,
58
- onKeyDown,
59
- formatOn = FormatOn.Blur,
60
- thousandSeparator = ',',
61
- thousandStyle = ThousandStyle.Thousand,
62
- decimalSeparator = '.',
63
- decimalMinLength,
64
- enableCompactNotation = false,
65
- enableNegative = false,
66
- enableLeadingZeros = false,
67
- rawValueMode = false,
68
- value: controlledValue,
69
- defaultValue,
70
- ...rest
71
- } = props;
72
- const inputRef = useRef(null);
73
- const caretInfoRef = useRef(undefined);
74
- const [internalValue, setInternalValue] = useState(controlledValue !== undefined ? String(controlledValue) : defaultValue !== undefined ? String(defaultValue) : '');
75
- // Keep internal state in sync when controlled
76
- useEffect(() => {
77
- if (controlledValue !== undefined) {
78
- setInternalValue(String(controlledValue));
79
- }
80
- }, [controlledValue]);
81
- useImperativeHandle(ref, () => inputRef.current, []);
82
- const formattingOptions = {
83
- formatOn,
84
- thousandSeparator,
85
- ThousandStyle: thousandStyle,
86
- decimalSeparator,
87
- decimalMinLength,
88
- enableCompactNotation,
89
- enableNegative,
90
- enableLeadingZeros,
91
- rawValueMode
92
- };
93
- const formatValueWithCore = value => {
94
- const el = inputRef.current ?? document.createElement('input');
95
- el.value = value;
96
- const fakeEvent = {
97
- target: el
49
+ const NumoraInput = forwardRef((props, ref) => {
50
+ const { maxDecimals = 2, onChange, onPaste, onBlur, onKeyDown, formatOn = FormatOn.Blur, thousandSeparator = ',', thousandStyle = ThousandStyle.Thousand, decimalSeparator = '.', decimalMinLength, enableCompactNotation = false, enableNegative = false, enableLeadingZeros = false, rawValueMode = false, value: controlledValue, defaultValue, ...rest } = props;
51
+ const inputRef = useRef(null);
52
+ const caretInfoRef = useRef(undefined);
53
+ const [internalValue, setInternalValue] = useState(controlledValue !== undefined
54
+ ? String(controlledValue)
55
+ : defaultValue !== undefined
56
+ ? String(defaultValue)
57
+ : '');
58
+ // Keep internal state in sync when controlled
59
+ useEffect(() => {
60
+ if (controlledValue !== undefined) {
61
+ setInternalValue(String(controlledValue));
62
+ }
63
+ }, [controlledValue]);
64
+ useImperativeHandle(ref, () => inputRef.current, []);
65
+ const formattingOptions = {
66
+ formatOn,
67
+ thousandSeparator,
68
+ ThousandStyle: thousandStyle,
69
+ decimalSeparator,
70
+ decimalMinLength,
71
+ enableCompactNotation,
72
+ enableNegative,
73
+ enableLeadingZeros,
74
+ rawValueMode,
98
75
  };
99
- handleOnChangeNumoraInput(fakeEvent, maxDecimals, undefined, formattingOptions);
100
- return el.value;
101
- };
102
- // When controlled value changes, normalize/format it for display
103
- useEffect(() => {
104
- if (controlledValue !== undefined) {
105
- const formatted = formatValueWithCore(String(controlledValue));
106
- setInternalValue(formatted);
107
- }
108
- }, [controlledValue, formatOn, thousandSeparator, thousandStyle, decimalSeparator, decimalMinLength, enableCompactNotation, enableNegative, enableLeadingZeros, rawValueMode, maxDecimals]);
109
- const handleChange = e => {
110
- const {
111
- value,
112
- rawValue
113
- } = handleNumoraOnChange(e, {
114
- decimalMaxLength: maxDecimals,
115
- caretPositionBeforeChange: caretInfoRef.current,
116
- formattingOptions
117
- });
118
- caretInfoRef.current = undefined;
119
- if (controlledValue === undefined) {
120
- setInternalValue(value);
121
- } else {
122
- setInternalValue(value);
123
- }
124
- if (onChange) {
125
- onChange(e);
126
- }
127
- // Optionally expose rawValue via a custom event attribute if needed later
128
- if (rawValue && e.target && rawValueMode) {
129
- // Keep the raw value on the input for consumers that read it directly
130
- e.target.setAttribute('data-raw-value', rawValue);
131
- }
132
- };
133
- const handlePaste = e => {
134
- const {
135
- value,
136
- rawValue
137
- } = handleNumoraOnPaste(e, {
138
- decimalMaxLength: maxDecimals,
139
- formattingOptions
140
- });
141
- if (controlledValue === undefined) {
142
- setInternalValue(value);
143
- } else {
144
- setInternalValue(value);
145
- }
146
- if (onPaste) {
147
- onPaste(e);
148
- }
149
- if (onChange) {
150
- onChange(e);
151
- }
152
- if (rawValue && e.target && rawValueMode) {
153
- e.target.setAttribute('data-raw-value', rawValue);
154
- }
155
- };
156
- const handleKeyDown = e => {
157
- caretInfoRef.current = handleNumoraOnKeyDown(e, formattingOptions);
158
- if (onKeyDown) {
159
- onKeyDown(e);
160
- }
161
- };
162
- const handleBlur = e => {
163
- const {
164
- value,
165
- rawValue
166
- } = handleNumoraOnBlur(e, {
167
- decimalMaxLength: maxDecimals,
168
- formattingOptions
169
- });
170
- if (controlledValue === undefined) {
171
- setInternalValue(value);
172
- } else {
173
- setInternalValue(value);
174
- }
175
- if (onBlur) {
176
- onBlur(e);
177
- }
178
- if (rawValue && e.target && rawValueMode) {
179
- e.target.setAttribute('data-raw-value', rawValue);
180
- }
181
- };
182
- return jsx("input", {
183
- ...rest,
184
- ref: inputRef,
185
- value: internalValue,
186
- onChange: handleChange,
187
- onPaste: handlePaste,
188
- onKeyDown: handleKeyDown,
189
- onBlur: handleBlur,
190
- type: "text",
191
- inputMode: "decimal"
192
- });
76
+ const formatValueWithCore = (value) => {
77
+ const el = inputRef.current ?? document.createElement('input');
78
+ el.value = value;
79
+ const fakeEvent = { target: el };
80
+ handleOnChangeNumoraInput(fakeEvent, maxDecimals, undefined, formattingOptions);
81
+ return el.value;
82
+ };
83
+ // When controlled value changes, normalize/format it for display
84
+ useEffect(() => {
85
+ if (controlledValue !== undefined) {
86
+ const formatted = formatValueWithCore(String(controlledValue));
87
+ setInternalValue(formatted);
88
+ }
89
+ }, [controlledValue, formatOn, thousandSeparator, thousandStyle, decimalSeparator, decimalMinLength, enableCompactNotation, enableNegative, enableLeadingZeros, rawValueMode, maxDecimals]);
90
+ const handleChange = (e) => {
91
+ const { value, rawValue } = handleNumoraOnChange(e, {
92
+ decimalMaxLength: maxDecimals,
93
+ caretPositionBeforeChange: caretInfoRef.current,
94
+ formattingOptions,
95
+ });
96
+ caretInfoRef.current = undefined;
97
+ if (controlledValue === undefined) {
98
+ setInternalValue(value);
99
+ }
100
+ else {
101
+ setInternalValue(value);
102
+ }
103
+ if (onChange) {
104
+ onChange(e);
105
+ }
106
+ // Optionally expose rawValue via a custom event attribute if needed later
107
+ if (rawValue && e.target && rawValueMode) {
108
+ // Keep the raw value on the input for consumers that read it directly
109
+ e.target.setAttribute('data-raw-value', rawValue);
110
+ }
111
+ };
112
+ const handlePaste = (e) => {
113
+ const { value, rawValue } = handleNumoraOnPaste(e, {
114
+ decimalMaxLength: maxDecimals,
115
+ formattingOptions,
116
+ });
117
+ if (controlledValue === undefined) {
118
+ setInternalValue(value);
119
+ }
120
+ else {
121
+ setInternalValue(value);
122
+ }
123
+ if (onPaste) {
124
+ onPaste(e);
125
+ }
126
+ if (onChange) {
127
+ onChange(e);
128
+ }
129
+ if (rawValue && e.target && rawValueMode) {
130
+ e.target.setAttribute('data-raw-value', rawValue);
131
+ }
132
+ };
133
+ const handleKeyDown = (e) => {
134
+ caretInfoRef.current = handleNumoraOnKeyDown(e, formattingOptions);
135
+ if (onKeyDown) {
136
+ onKeyDown(e);
137
+ }
138
+ };
139
+ const handleBlur = (e) => {
140
+ const { value, rawValue } = handleNumoraOnBlur(e, {
141
+ decimalMaxLength: maxDecimals,
142
+ formattingOptions,
143
+ });
144
+ if (controlledValue === undefined) {
145
+ setInternalValue(value);
146
+ }
147
+ else {
148
+ setInternalValue(value);
149
+ }
150
+ if (onBlur) {
151
+ onBlur(e);
152
+ }
153
+ if (rawValue && e.target && rawValueMode) {
154
+ e.target.setAttribute('data-raw-value', rawValue);
155
+ }
156
+ };
157
+ return (jsx("input", { ...rest, ref: inputRef, value: internalValue, onChange: handleChange, onPaste: handlePaste, onKeyDown: handleKeyDown, onBlur: handleBlur, type: "text", inputMode: "decimal" }));
193
158
  });
194
159
  NumoraInput.displayName = 'NumoraInput';
195
160
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../src/handlers.ts","../src/index.tsx"],"sourcesContent":["import type React from 'react';\nimport {\n handleOnChangeNumoraInput,\n handleOnKeyDownNumoraInput,\n handleOnPasteNumoraInput,\n type CaretPositionInfo,\n type FormattingOptions,\n FormatOn,\n} from 'numora';\n\ntype ChangeResult = {\n value: string;\n rawValue?: string;\n};\n\ntype PasteResult = ChangeResult;\ntype BlurResult = ChangeResult;\n\ntype BaseOptions = {\n decimalMaxLength: number;\n caretPositionBeforeChange?: CaretPositionInfo;\n formattingOptions: FormattingOptions & { rawValueMode?: boolean };\n};\n\nexport function handleNumoraOnChange(\n e: React.ChangeEvent<HTMLInputElement>,\n options: BaseOptions\n): ChangeResult {\n handleOnChangeNumoraInput(\n e.nativeEvent as unknown as Event,\n options.decimalMaxLength,\n options.caretPositionBeforeChange,\n options.formattingOptions\n );\n\n const target = e.target;\n const rawValue = target.getAttribute('data-raw-value') ?? undefined;\n if (rawValue) {\n target.removeAttribute('data-raw-value');\n }\n\n return {\n value: target.value,\n rawValue,\n };\n}\n\nexport function handleNumoraOnPaste(\n e: React.ClipboardEvent<HTMLInputElement>,\n options: Omit<BaseOptions, 'caretPositionBeforeChange'>\n): PasteResult {\n const value = handleOnPasteNumoraInput(\n e.nativeEvent as ClipboardEvent,\n options.decimalMaxLength,\n options.formattingOptions\n );\n\n const target = e.target as HTMLInputElement;\n const rawValue = target.getAttribute('data-raw-value') ?? undefined;\n if (rawValue) {\n target.removeAttribute('data-raw-value');\n }\n\n return {\n value,\n rawValue,\n };\n}\n\nexport function handleNumoraOnKeyDown(\n e: React.KeyboardEvent<HTMLInputElement>,\n formattingOptions: FormattingOptions\n): CaretPositionInfo | undefined {\n return handleOnKeyDownNumoraInput(\n e.nativeEvent as unknown as KeyboardEvent,\n formattingOptions\n );\n}\n\nexport function handleNumoraOnBlur(\n e: React.FocusEvent<HTMLInputElement>,\n options: {\n decimalMaxLength: number;\n formattingOptions: FormattingOptions & { rawValueMode?: boolean };\n }\n): BlurResult {\n // If formatOn is blur, force formatting on blur by invoking change handler logic\n if (options.formattingOptions.formatOn === FormatOn.Blur) {\n handleOnChangeNumoraInput(\n e.nativeEvent as unknown as Event,\n options.decimalMaxLength,\n undefined,\n { ...options.formattingOptions, formatOn: FormatOn.Change }\n );\n }\n\n const target = e.target;\n const rawValue = target.getAttribute('data-raw-value') ?? undefined;\n if (rawValue) {\n target.removeAttribute('data-raw-value');\n }\n\n return {\n value: target.value,\n rawValue,\n };\n}\n","import React, {\n useRef,\n useState,\n useEffect,\n forwardRef,\n useImperativeHandle,\n} from 'react';\nimport {\n FormatOn,\n ThousandStyle,\n type CaretPositionInfo,\n type FormattingOptions,\n handleOnChangeNumoraInput,\n} from 'numora';\nimport {\n handleNumoraOnBlur,\n handleNumoraOnChange,\n handleNumoraOnKeyDown,\n handleNumoraOnPaste,\n} from './handlers';\n\ninterface NumoraInputProps\n extends Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n 'onChange' | 'type' | 'inputMode'\n > {\n maxDecimals?: number;\n onChange?: (e: React.ChangeEvent<HTMLInputElement> | React.ClipboardEvent<HTMLInputElement>) => void;\n\n formatOn?: FormatOn;\n thousandSeparator?: string;\n thousandStyle?: ThousandStyle;\n decimalSeparator?: string;\n decimalMinLength?: number;\n\n enableCompactNotation?: boolean;\n enableNegative?: boolean;\n enableLeadingZeros?: boolean;\n rawValueMode?: boolean;\n}\n\nconst NumoraInput = forwardRef<HTMLInputElement, NumoraInputProps>((props, ref) => {\n const {\n maxDecimals = 2,\n onChange,\n onPaste,\n onBlur,\n onKeyDown,\n formatOn = FormatOn.Blur,\n thousandSeparator = ',',\n thousandStyle = ThousandStyle.Thousand,\n decimalSeparator = '.',\n decimalMinLength,\n enableCompactNotation = false,\n enableNegative = false,\n enableLeadingZeros = false,\n rawValueMode = false,\n value: controlledValue,\n defaultValue,\n ...rest\n } = props;\n\n const inputRef = useRef<HTMLInputElement>(null);\n const caretInfoRef = useRef<CaretPositionInfo | undefined>(undefined);\n\n const [internalValue, setInternalValue] = useState<string>(\n controlledValue !== undefined\n ? String(controlledValue)\n : defaultValue !== undefined\n ? String(defaultValue)\n : ''\n );\n\n // Keep internal state in sync when controlled\n useEffect(() => {\n if (controlledValue !== undefined) {\n setInternalValue(String(controlledValue));\n }\n }, [controlledValue]);\n\n useImperativeHandle(ref, () => inputRef.current as HTMLInputElement, []);\n\n const formattingOptions: FormattingOptions & { rawValueMode?: boolean } = {\n formatOn,\n thousandSeparator,\n ThousandStyle: thousandStyle,\n decimalSeparator,\n decimalMinLength,\n enableCompactNotation,\n enableNegative,\n enableLeadingZeros,\n rawValueMode,\n };\n\n const formatValueWithCore = (value: string): string => {\n const el = inputRef.current ?? document.createElement('input');\n el.value = value;\n const fakeEvent = { target: el } as unknown as Event;\n handleOnChangeNumoraInput(fakeEvent, maxDecimals, undefined, formattingOptions);\n return el.value;\n };\n\n // When controlled value changes, normalize/format it for display\n useEffect(() => {\n if (controlledValue !== undefined) {\n const formatted = formatValueWithCore(String(controlledValue));\n setInternalValue(formatted);\n }\n }, [controlledValue, formatOn, thousandSeparator, thousandStyle, decimalSeparator, decimalMinLength, enableCompactNotation, enableNegative, enableLeadingZeros, rawValueMode, maxDecimals]);\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const { value, rawValue } = handleNumoraOnChange(e, {\n decimalMaxLength: maxDecimals,\n caretPositionBeforeChange: caretInfoRef.current,\n formattingOptions,\n });\n caretInfoRef.current = undefined;\n\n if (controlledValue === undefined) {\n setInternalValue(value);\n } else {\n setInternalValue(value);\n }\n\n if (onChange) {\n onChange(e);\n }\n\n // Optionally expose rawValue via a custom event attribute if needed later\n if (rawValue && e.target && rawValueMode) {\n // Keep the raw value on the input for consumers that read it directly\n e.target.setAttribute('data-raw-value', rawValue);\n }\n };\n\n const handlePaste = (e: React.ClipboardEvent<HTMLInputElement>) => {\n const { value, rawValue } = handleNumoraOnPaste(e, {\n decimalMaxLength: maxDecimals,\n formattingOptions,\n });\n\n if (controlledValue === undefined) {\n setInternalValue(value);\n } else {\n setInternalValue(value);\n }\n\n if (onPaste) {\n onPaste(e);\n }\n if (onChange) {\n onChange(e);\n }\n\n if (rawValue && e.target && rawValueMode) {\n (e.target as HTMLInputElement).setAttribute('data-raw-value', rawValue);\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n caretInfoRef.current = handleNumoraOnKeyDown(e, formattingOptions);\n if (onKeyDown) {\n onKeyDown(e);\n }\n };\n\n const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {\n const { value, rawValue } = handleNumoraOnBlur(e, {\n decimalMaxLength: maxDecimals,\n formattingOptions,\n });\n\n if (controlledValue === undefined) {\n setInternalValue(value);\n } else {\n setInternalValue(value);\n }\n\n if (onBlur) {\n onBlur(e);\n }\n\n if (rawValue && e.target && rawValueMode) {\n (e.target as HTMLInputElement).setAttribute('data-raw-value', rawValue);\n }\n };\n\n return (\n <input\n {...rest}\n ref={inputRef}\n value={internalValue}\n onChange={handleChange}\n onPaste={handlePaste}\n onKeyDown={handleKeyDown}\n onBlur={handleBlur}\n type=\"text\"\n inputMode=\"decimal\"\n />\n );\n});\n\nNumoraInput.displayName = 'NumoraInput';\n\nexport { NumoraInput };\nexport { FormatOn, ThousandStyle } from 'numora';\nexport type { FormattingOptions, CaretPositionInfo } from 'numora';\n"],"names":["handleNumoraOnChange","e","options","handleOnChangeNumoraInput","nativeEvent","decimalMaxLength","caretPositionBeforeChange","formattingOptions","target","rawValue","getAttribute","undefined","removeAttribute","value","handleNumoraOnPaste","handleOnPasteNumoraInput","handleNumoraOnKeyDown","handleOnKeyDownNumoraInput","handleNumoraOnBlur","formatOn","FormatOn","Blur","Change","NumoraInput","forwardRef","props","ref","maxDecimals","onChange","onPaste","onBlur","onKeyDown","thousandSeparator","thousandStyle","ThousandStyle","Thousand","decimalSeparator","decimalMinLength","enableCompactNotation","enableNegative","enableLeadingZeros","rawValueMode","controlledValue","defaultValue","rest","inputRef","useRef","caretInfoRef","internalValue","setInternalValue","useState","String","useEffect","useImperativeHandle","current","formatValueWithCore","el","document","createElement","fakeEvent","formatted","handleChange","setAttribute","handlePaste","handleKeyDown","handleBlur","_jsx","type","inputMode","displayName"],"mappings":"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"}
1
+ {"version":3,"file":"index.esm.js","sources":["../src/handlers.ts","../src/index.tsx"],"sourcesContent":["import type React from 'react';\nimport {\n handleOnChangeNumoraInput,\n handleOnKeyDownNumoraInput,\n handleOnPasteNumoraInput,\n type CaretPositionInfo,\n type FormattingOptions,\n FormatOn,\n} from 'numora';\n\ntype ChangeResult = {\n value: string;\n rawValue?: string;\n};\n\ntype PasteResult = ChangeResult;\ntype BlurResult = ChangeResult;\n\ntype BaseOptions = {\n decimalMaxLength: number;\n caretPositionBeforeChange?: CaretPositionInfo;\n formattingOptions: FormattingOptions & { rawValueMode?: boolean };\n};\n\nexport function handleNumoraOnChange(\n e: React.ChangeEvent<HTMLInputElement>,\n options: BaseOptions\n): ChangeResult {\n handleOnChangeNumoraInput(\n e.nativeEvent as unknown as Event,\n options.decimalMaxLength,\n options.caretPositionBeforeChange,\n options.formattingOptions\n );\n\n const target = e.target;\n const rawValue = target.getAttribute('data-raw-value') ?? undefined;\n if (rawValue) {\n target.removeAttribute('data-raw-value');\n }\n\n return {\n value: target.value,\n rawValue,\n };\n}\n\nexport function handleNumoraOnPaste(\n e: React.ClipboardEvent<HTMLInputElement>,\n options: Omit<BaseOptions, 'caretPositionBeforeChange'>\n): PasteResult {\n const value = handleOnPasteNumoraInput(\n e.nativeEvent as ClipboardEvent,\n options.decimalMaxLength,\n options.formattingOptions\n );\n\n const target = e.target as HTMLInputElement;\n const rawValue = target.getAttribute('data-raw-value') ?? undefined;\n if (rawValue) {\n target.removeAttribute('data-raw-value');\n }\n\n return {\n value,\n rawValue,\n };\n}\n\nexport function handleNumoraOnKeyDown(\n e: React.KeyboardEvent<HTMLInputElement>,\n formattingOptions: FormattingOptions\n): CaretPositionInfo | undefined {\n return handleOnKeyDownNumoraInput(\n e.nativeEvent as unknown as KeyboardEvent,\n formattingOptions\n );\n}\n\nexport function handleNumoraOnBlur(\n e: React.FocusEvent<HTMLInputElement>,\n options: {\n decimalMaxLength: number;\n formattingOptions: FormattingOptions & { rawValueMode?: boolean };\n }\n): BlurResult {\n // If formatOn is blur, force formatting on blur by invoking change handler logic\n if (options.formattingOptions.formatOn === FormatOn.Blur) {\n handleOnChangeNumoraInput(\n e.nativeEvent as unknown as Event,\n options.decimalMaxLength,\n undefined,\n { ...options.formattingOptions, formatOn: FormatOn.Change }\n );\n }\n\n const target = e.target;\n const rawValue = target.getAttribute('data-raw-value') ?? undefined;\n if (rawValue) {\n target.removeAttribute('data-raw-value');\n }\n\n return {\n value: target.value,\n rawValue,\n };\n}\n","import React, {\n useRef,\n useState,\n useEffect,\n forwardRef,\n useImperativeHandle,\n} from 'react';\nimport {\n FormatOn,\n ThousandStyle,\n type CaretPositionInfo,\n type FormattingOptions,\n handleOnChangeNumoraInput,\n} from 'numora';\nimport {\n handleNumoraOnBlur,\n handleNumoraOnChange,\n handleNumoraOnKeyDown,\n handleNumoraOnPaste,\n} from './handlers';\n\ninterface NumoraInputProps\n extends Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n 'onChange' | 'type' | 'inputMode'\n > {\n maxDecimals?: number;\n onChange?: (e: React.ChangeEvent<HTMLInputElement> | React.ClipboardEvent<HTMLInputElement>) => void;\n\n formatOn?: FormatOn;\n thousandSeparator?: string;\n thousandStyle?: ThousandStyle;\n decimalSeparator?: string;\n decimalMinLength?: number;\n\n enableCompactNotation?: boolean;\n enableNegative?: boolean;\n enableLeadingZeros?: boolean;\n rawValueMode?: boolean;\n}\n\nconst NumoraInput = forwardRef<HTMLInputElement, NumoraInputProps>((props, ref) => {\n const {\n maxDecimals = 2,\n onChange,\n onPaste,\n onBlur,\n onKeyDown,\n formatOn = FormatOn.Blur,\n thousandSeparator = ',',\n thousandStyle = ThousandStyle.Thousand,\n decimalSeparator = '.',\n decimalMinLength,\n enableCompactNotation = false,\n enableNegative = false,\n enableLeadingZeros = false,\n rawValueMode = false,\n value: controlledValue,\n defaultValue,\n ...rest\n } = props;\n\n const inputRef = useRef<HTMLInputElement>(null);\n const caretInfoRef = useRef<CaretPositionInfo | undefined>(undefined);\n\n const [internalValue, setInternalValue] = useState<string>(\n controlledValue !== undefined\n ? String(controlledValue)\n : defaultValue !== undefined\n ? String(defaultValue)\n : ''\n );\n\n // Keep internal state in sync when controlled\n useEffect(() => {\n if (controlledValue !== undefined) {\n setInternalValue(String(controlledValue));\n }\n }, [controlledValue]);\n\n useImperativeHandle(ref, () => inputRef.current as HTMLInputElement, []);\n\n const formattingOptions: FormattingOptions & { rawValueMode?: boolean } = {\n formatOn,\n thousandSeparator,\n ThousandStyle: thousandStyle,\n decimalSeparator,\n decimalMinLength,\n enableCompactNotation,\n enableNegative,\n enableLeadingZeros,\n rawValueMode,\n };\n\n const formatValueWithCore = (value: string): string => {\n const el = inputRef.current ?? document.createElement('input');\n el.value = value;\n const fakeEvent = { target: el } as unknown as Event;\n handleOnChangeNumoraInput(fakeEvent, maxDecimals, undefined, formattingOptions);\n return el.value;\n };\n\n // When controlled value changes, normalize/format it for display\n useEffect(() => {\n if (controlledValue !== undefined) {\n const formatted = formatValueWithCore(String(controlledValue));\n setInternalValue(formatted);\n }\n }, [controlledValue, formatOn, thousandSeparator, thousandStyle, decimalSeparator, decimalMinLength, enableCompactNotation, enableNegative, enableLeadingZeros, rawValueMode, maxDecimals]);\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const { value, rawValue } = handleNumoraOnChange(e, {\n decimalMaxLength: maxDecimals,\n caretPositionBeforeChange: caretInfoRef.current,\n formattingOptions,\n });\n caretInfoRef.current = undefined;\n\n if (controlledValue === undefined) {\n setInternalValue(value);\n } else {\n setInternalValue(value);\n }\n\n if (onChange) {\n onChange(e);\n }\n\n // Optionally expose rawValue via a custom event attribute if needed later\n if (rawValue && e.target && rawValueMode) {\n // Keep the raw value on the input for consumers that read it directly\n e.target.setAttribute('data-raw-value', rawValue);\n }\n };\n\n const handlePaste = (e: React.ClipboardEvent<HTMLInputElement>) => {\n const { value, rawValue } = handleNumoraOnPaste(e, {\n decimalMaxLength: maxDecimals,\n formattingOptions,\n });\n\n if (controlledValue === undefined) {\n setInternalValue(value);\n } else {\n setInternalValue(value);\n }\n\n if (onPaste) {\n onPaste(e);\n }\n if (onChange) {\n onChange(e);\n }\n\n if (rawValue && e.target && rawValueMode) {\n (e.target as HTMLInputElement).setAttribute('data-raw-value', rawValue);\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n caretInfoRef.current = handleNumoraOnKeyDown(e, formattingOptions);\n if (onKeyDown) {\n onKeyDown(e);\n }\n };\n\n const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {\n const { value, rawValue } = handleNumoraOnBlur(e, {\n decimalMaxLength: maxDecimals,\n formattingOptions,\n });\n\n if (controlledValue === undefined) {\n setInternalValue(value);\n } else {\n setInternalValue(value);\n }\n\n if (onBlur) {\n onBlur(e);\n }\n\n if (rawValue && e.target && rawValueMode) {\n (e.target as HTMLInputElement).setAttribute('data-raw-value', rawValue);\n }\n };\n\n return (\n <input\n {...rest}\n ref={inputRef}\n value={internalValue}\n onChange={handleChange}\n onPaste={handlePaste}\n onKeyDown={handleKeyDown}\n onBlur={handleBlur}\n type=\"text\"\n inputMode=\"decimal\"\n />\n );\n});\n\nNumoraInput.displayName = 'NumoraInput';\n\nexport { NumoraInput };\nexport { FormatOn, ThousandStyle } from 'numora';\nexport type { FormattingOptions, CaretPositionInfo } from 'numora';\n"],"names":["_jsx"],"mappings":"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"}
package/package.json CHANGED
@@ -1,12 +1,19 @@
1
1
  {
2
2
  "name": "numora-react",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "Numora for React - Headless finance input library",
5
5
  "homepage": "https://numora.xyz/",
6
6
  "type": "module",
7
- "main": "dist/index.cjs.js",
7
+ "main": "dist/index.cjs",
8
8
  "module": "dist/index.esm.js",
9
9
  "types": "dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.esm.js",
14
+ "require": "./dist/index.cjs"
15
+ }
16
+ },
10
17
  "sideEffects": false,
11
18
  "repository": {
12
19
  "type": "git",
@@ -48,10 +55,6 @@
48
55
  "react-dom": "^18.0.0 || ^19.0.0"
49
56
  },
50
57
  "devDependencies": {
51
- "@babel/core": "^7.26.10",
52
- "@babel/preset-env": "^7.26.9",
53
- "@babel/preset-react": "^7.26.3",
54
- "@rollup/plugin-babel": "^6.0.4",
55
58
  "@rollup/plugin-commonjs": "^28.0.3",
56
59
  "@rollup/plugin-node-resolve": "^16.0.1",
57
60
  "@rollup/plugin-typescript": "^12.1.2",
package/rollup.config.mjs CHANGED
@@ -1,6 +1,5 @@
1
1
  import resolve from '@rollup/plugin-node-resolve';
2
2
  import commonjs from '@rollup/plugin-commonjs';
3
- import babel from '@rollup/plugin-babel';
4
3
  import typescript from '@rollup/plugin-typescript';
5
4
  import peerDepsExternal from 'rollup-plugin-peer-deps-external';
6
5
  import packageJson from './package.json' assert { type: 'json' };
@@ -24,15 +23,6 @@ export default {
24
23
  resolve(),
25
24
  commonjs(),
26
25
  typescript({ tsconfig: './tsconfig.json' }),
27
- babel({
28
- exclude: 'node_modules/**',
29
- extensions: ['.js', '.jsx', '.ts', '.tsx'],
30
- babelHelpers: 'bundled',
31
- presets: [
32
- ['@babel/preset-env', { targets: 'defaults' }],
33
- ['@babel/preset-react', { runtime: 'automatic' }],
34
- ],
35
- }),
36
26
  ],
37
27
  external: ['react', 'react-dom', 'numora'],
38
28
  };